From 1ec5bc8ffdacfa50e4743b5329fab052d6bf15e7 Mon Sep 17 00:00:00 2001 From: a1012112796 <1012112796@qq.com> Date: Tue, 3 Jan 2023 13:16:29 +0800 Subject: [PATCH] =?UTF-8?q?iap=20=E5=AE=8C=E5=96=84=20&=20=E6=B5=AE?= =?UTF-8?q?=E7=82=B9=E6=95=B0printf=20=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: a1012112796 <1012112796@qq.com> --- .config | 303 ++++- .gitignore | 2 +- iap/iap.c | 89 +- packages/SConscript | 12 + packages/pkgs.json | 7 + packages/pkgs_error.json | 1 + packages/rt_vsnprintf_full-latest/README.md | 59 + packages/rt_vsnprintf_full-latest/SConscript | 14 + .../rt_vsnprintf_full-latest/figures/1.png | Bin 0 -> 44224 bytes .../rt_vsnprintf_full-latest/figures/2.png | Bin 0 -> 37729 bytes .../rt_vsnprintf_full-latest/figures/3.png | Bin 0 -> 36800 bytes .../rt_vsnprintf_full-latest/rt_vsnprintf.c | 1101 +++++++++++++++++ project.uvoptx | 84 +- project.uvprojx | 48 +- rt-thread/src/kservice.c | 495 -------- rtconfig.h | 32 +- 16 files changed, 1668 insertions(+), 579 deletions(-) create mode 100644 packages/SConscript create mode 100644 packages/pkgs.json create mode 100644 packages/pkgs_error.json create mode 100644 packages/rt_vsnprintf_full-latest/README.md create mode 100644 packages/rt_vsnprintf_full-latest/SConscript create mode 100644 packages/rt_vsnprintf_full-latest/figures/1.png create mode 100644 packages/rt_vsnprintf_full-latest/figures/2.png create mode 100644 packages/rt_vsnprintf_full-latest/figures/3.png create mode 100644 packages/rt_vsnprintf_full-latest/rt_vsnprintf.c diff --git a/.config b/.config index 73aec0c..94bc8d5 100644 --- a/.config +++ b/.config @@ -220,7 +220,7 @@ CONFIG_ULOG_ASYNC_OUTPUT_THREAD_PRIORITY=30 # # log format # -# CONFIG_ULOG_OUTPUT_FLOAT is not set +CONFIG_ULOG_OUTPUT_FLOAT=y CONFIG_ULOG_USING_COLOR=y CONFIG_ULOG_OUTPUT_TIME=y # CONFIG_ULOG_TIME_USING_TIMESTAMP is not set @@ -322,6 +322,8 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # CONFIG_PKG_USING_AGILE_FTP is not set # CONFIG_PKG_USING_EMBEDDEDPROTO is not set # CONFIG_PKG_USING_RT_LINK_HW is not set +# CONFIG_PKG_USING_RYANMQTT is not set +# CONFIG_PKG_USING_RYANW5500 is not set # CONFIG_PKG_USING_LORA_PKT_FWD is not set # CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set # CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set @@ -329,6 +331,7 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # CONFIG_PKG_USING_SMALL_MODBUS is not set # CONFIG_PKG_USING_NET_SERVER is not set # CONFIG_PKG_USING_ZFTP is not set +# CONFIG_PKG_USING_WOL is not set # # security packages @@ -420,7 +423,6 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # CONFIG_PKG_USING_SEGGER_RTT is not set # CONFIG_PKG_USING_RDB is not set # CONFIG_PKG_USING_ULOG_EASYFLASH is not set -# CONFIG_PKG_USING_ULOG_FILE is not set # CONFIG_PKG_USING_LOGMGR is not set # CONFIG_PKG_USING_ADBD is not set # CONFIG_PKG_USING_COREMARK is not set @@ -454,7 +456,6 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # CONFIG_PKG_USING_CBOX is not set # CONFIG_PKG_USING_SNOWFLAKE is not set # CONFIG_PKG_USING_HASH_MATCH is not set -# CONFIG_PKG_USING_FIRE_PID_CURVE is not set # CONFIG_PKG_USING_ARMV7M_DWT_TOOL is not set # CONFIG_PKG_USING_VOFA_PLUS is not set @@ -467,7 +468,15 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # # CONFIG_PKG_USING_RT_MEMCPY_CM is not set # CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set -# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set +CONFIG_PKG_USING_RT_VSNPRINTF_FULL=y +CONFIG_PKG_RT_VSNPRINTF_FULL_PATH="/packages/system/enhanced-kservice/rt_vsnprintf_full" +# CONFIG_RT_VSNPRINTF_FULL_REPLACING_SPRINTF is not set +# CONFIG_RT_VSNPRINTF_FULL_REPLACING_SNPRINTF is not set +# CONFIG_RT_VSNPRINTF_FULL_REPLACING_PRINTF is not set +# CONFIG_RT_VSNPRINTF_FULL_REPLACING_VSPRINTF is not set +# CONFIG_RT_VSNPRINTF_FULL_REPLACING_VSNPRINTF is not set +CONFIG_PKG_USING_RT_VSNPRINTF_FULL_LATEST_VERSION=y +CONFIG_PKG_RT_VSNPRINTF_FULL_VER="latest" # # acceleration: Assembly language or algorithmic acceleration packages @@ -531,15 +540,88 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # # peripheral libraries and drivers # -# CONFIG_PKG_USING_SENSORS_DRIVERS is not set -# CONFIG_PKG_USING_REALTEK_AMEBA is not set + +# +# sensors drivers +# +# CONFIG_PKG_USING_LSM6DSM is not set +# CONFIG_PKG_USING_LSM6DSL is not set +# CONFIG_PKG_USING_LPS22HB is not set +# CONFIG_PKG_USING_HTS221 is not set +# CONFIG_PKG_USING_LSM303AGR is not set +# CONFIG_PKG_USING_BME280 is not set +# CONFIG_PKG_USING_BME680 is not set +# CONFIG_PKG_USING_BMA400 is not set +# CONFIG_PKG_USING_BMI160_BMX160 is not set +# CONFIG_PKG_USING_SPL0601 is not set +# CONFIG_PKG_USING_MS5805 is not set +# CONFIG_PKG_USING_DA270 is not set +# CONFIG_PKG_USING_DF220 is not set +# CONFIG_PKG_USING_HSHCAL001 is not set +# CONFIG_PKG_USING_BH1750 is not set +# CONFIG_PKG_USING_MPU6XXX is not set +# CONFIG_PKG_USING_AHT10 is not set +# CONFIG_PKG_USING_AP3216C is not set +# CONFIG_PKG_USING_TSL4531 is not set +# CONFIG_PKG_USING_DS18B20 is not set +# CONFIG_PKG_USING_DHT11 is not set +# CONFIG_PKG_USING_DHTXX is not set +# CONFIG_PKG_USING_GY271 is not set +# CONFIG_PKG_USING_GP2Y10 is not set +# CONFIG_PKG_USING_SGP30 is not set +# CONFIG_PKG_USING_HDC1000 is not set +# CONFIG_PKG_USING_BMP180 is not set +# CONFIG_PKG_USING_BMP280 is not set +# CONFIG_PKG_USING_SHTC1 is not set +# CONFIG_PKG_USING_BMI088 is not set +# CONFIG_PKG_USING_HMC5883 is not set +# CONFIG_PKG_USING_MAX6675 is not set +# CONFIG_PKG_USING_TMP1075 is not set +# CONFIG_PKG_USING_SR04 is not set +# CONFIG_PKG_USING_CCS811 is not set +# CONFIG_PKG_USING_PMSXX is not set +# CONFIG_PKG_USING_RT3020 is not set +# CONFIG_PKG_USING_MLX90632 is not set +# CONFIG_PKG_USING_MLX90393 is not set +# CONFIG_PKG_USING_MLX90392 is not set +# CONFIG_PKG_USING_MLX90397 is not set +# CONFIG_PKG_USING_MS5611 is not set +# CONFIG_PKG_USING_MAX31865 is not set +# CONFIG_PKG_USING_VL53L0X is not set +# CONFIG_PKG_USING_INA260 is not set +# CONFIG_PKG_USING_MAX30102 is not set +# CONFIG_PKG_USING_INA226 is not set +# CONFIG_PKG_USING_LIS2DH12 is not set +# CONFIG_PKG_USING_HS300X is not set +# CONFIG_PKG_USING_ZMOD4410 is not set +# CONFIG_PKG_USING_ISL29035 is not set +# CONFIG_PKG_USING_MMC3680KJ is not set +# CONFIG_PKG_USING_QMP6989 is not set +# CONFIG_PKG_USING_BALANCE is not set # CONFIG_PKG_USING_SHT2X is not set # CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_AD7746 is not set # CONFIG_PKG_USING_ADT74XX is not set +# CONFIG_PKG_USING_MAX17048 is not set # CONFIG_PKG_USING_AS7341 is not set +# CONFIG_PKG_USING_CW2015 is not set +# CONFIG_PKG_USING_ICM20608 is not set +# CONFIG_PKG_USING_PAJ7620 is not set + +# +# touch drivers +# +# CONFIG_PKG_USING_GT9147 is not set +# CONFIG_PKG_USING_GT1151 is not set +# CONFIG_PKG_USING_GT917S is not set +# CONFIG_PKG_USING_GT911 is not set +# CONFIG_PKG_USING_FT6206 is not set +# CONFIG_PKG_USING_FT5426 is not set +# CONFIG_PKG_USING_FT6236 is not set +# CONFIG_PKG_USING_XPT2046_TOUCH is not set +# CONFIG_PKG_USING_REALTEK_AMEBA is not set # CONFIG_PKG_USING_STM32_SDIO is not set # CONFIG_PKG_USING_ESP_IDF is not set -# CONFIG_PKG_USING_ICM20608 is not set # CONFIG_PKG_USING_BUTTON is not set # CONFIG_PKG_USING_PCF8574 is not set # CONFIG_PKG_USING_SX12XX is not set @@ -562,12 +644,9 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # CONFIG_PKG_USING_AGILE_LED is not set # CONFIG_PKG_USING_AT24CXX is not set # CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set -# CONFIG_PKG_USING_AD7746 is not set # CONFIG_PKG_USING_PCA9685 is not set # CONFIG_PKG_USING_I2C_TOOLS is not set # CONFIG_PKG_USING_NRF24L01 is not set -# CONFIG_PKG_USING_TOUCH_DRIVERS is not set -# CONFIG_PKG_USING_MAX17048 is not set # CONFIG_PKG_USING_RPLIDAR is not set # CONFIG_PKG_USING_AS608 is not set # CONFIG_PKG_USING_RC522 is not set @@ -582,7 +661,6 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # CONFIG_PKG_USING_CAN_YMODEM is not set # CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set # CONFIG_PKG_USING_QLED is not set -# CONFIG_PKG_USING_PAJ7620 is not set # CONFIG_PKG_USING_AGILE_CONSOLE is not set # CONFIG_PKG_USING_LD3320 is not set # CONFIG_PKG_USING_WK2124 is not set @@ -613,10 +691,11 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # CONFIG_PKG_USING_BL_MCU_SDK is not set # CONFIG_PKG_USING_SOFT_SERIAL is not set # CONFIG_PKG_USING_MB85RS16 is not set -# CONFIG_PKG_USING_CW2015 is not set # CONFIG_PKG_USING_RFM300 is not set # CONFIG_PKG_USING_IO_INPUT_FILTER is not set # CONFIG_PKG_USING_RASPBERRYPI_PICO_SDK is not set +# CONFIG_PKG_USING_LRF_NV7LIDAR is not set +# CONFIG_PKG_USING_FINGERPRINT is not set # # AI packages @@ -631,6 +710,12 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # CONFIG_PKG_USING_QUEST is not set # CONFIG_PKG_USING_NAXOS is not set +# +# Signal Processing and Control Algorithm Packages +# +# CONFIG_PKG_USING_FIRE_PID_CURVE is not set +# CONFIG_PKG_USING_UKAL is not set + # # miscellaneous packages # @@ -682,7 +767,6 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # CONFIG_PKG_USING_VI is not set # CONFIG_PKG_USING_KI is not set # CONFIG_PKG_USING_ARMv7M_DWT is not set -# CONFIG_PKG_USING_UKAL is not set # CONFIG_PKG_USING_CRCLIB is not set # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set @@ -693,27 +777,165 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # CONFIG_PKG_USING_SLCAN2RTT is not set # CONFIG_PKG_USING_SOEM is not set # CONFIG_PKG_USING_QPARAM is not set +# CONFIG_PKG_USING_CorevMCU_CLI is not set +# CONFIG_PKG_USING_GET_IRQ_PRIORITY is not set # # Arduino libraries # # CONFIG_PKG_USING_RTDUINO is not set +# +# Projects +# +# CONFIG_PKG_USING_ARDUINO_ULTRASOUND_RADAR is not set +# CONFIG_PKG_USING_ARDUINO_SENSOR_KIT is not set +# CONFIG_PKG_USING_ARDUINO_MATLAB_SUPPORT is not set + # # Sensors # -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSOR is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BUSIO is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AHTX0 is not set -# CONFIG_PKG_USING_ARDUINO_DHT_SENSOR is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_BMP280 is not set -# CONFIG_PKG_USING_ARDUINO_SEEED_LIS3DHTR is not set +# CONFIG_PKG_USING_ARDUINO_SENSOR_DEVICE_DRIVERS is not set # CONFIG_PKG_USING_ARDUINO_CAPACITIVESENSOR is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL375 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L0X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L1X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSOR is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL6180X is not set +# CONFIG_PKG_USING_ADAFRUIT_MAX31855 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31865 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31856 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX6675 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90614 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS1 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AHTX0 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS0 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP280 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADT7410 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME680 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9808 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4728 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA219 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR390 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL345 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DHT is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9600 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM6DS is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO055 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX1704X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMC56X3 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90393 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90395 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ICM20X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DPS310 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTS221 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT4X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT31 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL343 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME280 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS726X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AMG88XX is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2320 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2315 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR329_LTR303 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP3XX is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MS8607 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3MDL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90640 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMA8451 is not set +# CONFIG_PKG_USING_ADAFRUIT_MSA301 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL115A2 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X_RVC is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS2MDL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303DLH_MAG is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LC709203F is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CAP1188 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CCS811 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_NAU7802 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS331 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS2X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS35HW is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303_ACCEL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3DH is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8591 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL3115A2 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPR121 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPRLS is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPU6050 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCT2075 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PM25AQI is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_EMC2101 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXAS21002C is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SCD30 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXOS8700 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HMC5883_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP30 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP006 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TLA202X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCS34725 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI7021 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI1145 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP40 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHTC3 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HDC1000 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU21DF is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS7341 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU31D is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSORLAB is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA260 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP007_LIBRARY is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_L3GD20 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP117 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSC2007 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2561 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2591_LIBRARY is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VCNL4040 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6070 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6075 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML7700 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LIS3DHTR is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_DHT is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_ADXL335 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_ADXL345 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BME280 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BMP280 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_H3LIS331DL is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_MMA7660 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_TSL2561 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_PAJ7620 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_VL53L0X is not set +# CONFIG_PKG_USING_SEEED_ITG3200 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_SHT31 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HP20X is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_DRV2605L is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BBM150 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HMC5883L is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LSM303DLH is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_TCS3414CS is not set +# CONFIG_PKG_USING_SEEED_MP503 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_BMP085 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HIGHTEMP is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_VEML6070 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_SI1145 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_SHT35 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_AT42QT1070 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LSM6DS3 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HDC1000 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_HM3301 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_MCP9600 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LTC2941 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LDC1612 is not set # # Display # # CONFIG_PKG_USING_ARDUINO_U8G2 is not set +# CONFIG_PKG_USING_SEEED_TM1637 is not set # # Timing @@ -721,10 +943,47 @@ CONFIG_ULOG_BACKEND_USING_CONSOLE=y # CONFIG_PKG_USING_ARDUINO_MSTIMER2 is not set # -# Projects +# Data Processing +# +# CONFIG_PKG_USING_ARDUINO_KALMANFILTER is not set +# CONFIG_PKG_USING_ARDUINO_ARDUINOJSON is not set + +# +# Data Storage +# + +# +# Communication +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PN532 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI4713 is not set + +# +# Device Control +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8574 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCA9685 is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_PCF85063TP is not set + +# +# Other +# + +# +# Signal IO +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BUSIO is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCA8418 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP23017 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADS1X15 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AW9523 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP3008 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4725 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BD3491FS is not set + +# +# Uncategorized # -# CONFIG_PKG_USING_ARDUINO_ULTRASOUND_RADAR is not set -# CONFIG_PKG_USING_ARDUINO_SENSOR_KIT is not set CONFIG_SOC_FAMILY_STM32=y CONFIG_SOC_SERIES_STM32F4=y diff --git a/.gitignore b/.gitignore index 7221bde..3d051c6 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,6 @@ build Debug documentation/html -packages/ *~ *.o *.obj @@ -40,3 +39,4 @@ RTE/ settings/ *.uvguix* cconfig.h +packages/packages.dbsqlite diff --git a/iap/iap.c b/iap/iap.c index 645db2a..2dea004 100644 --- a/iap/iap.c +++ b/iap/iap.c @@ -116,10 +116,60 @@ rt_err_t port_rx_ind(rt_device_t dev, rt_size_t size) #define RT_BUF_SIZE (1024) +/* + * 固件格式: + * + * 作用 & 说明 + * - 记录固件对应硬件 & 版本信息 + * - 简便起见,不包含校验信息 + * + * index len desc + * 0 4 'XYFC' + * 4 4 固件信息长度 + * 8 N 固件信息 ('类型'-'版本') + * 8+N M 固件数据 + */ +static const char FIXED_HEAD[] = {'X', 'Y', 'F', 'C'}; +extern const char IAP_BIN_PREFIX[]; + +static int _check_head(const rt_uint8_t *buf, rt_size_t len) +{ + if (len < 8) + { + return -1; + } + + for (int i = 0; i < sizeof(FIXED_HEAD); i++) + { + if (FIXED_HEAD[i] != buf[i]) + { + return -2; + } + } + + rt_uint32_t real = *((const rt_uint32_t *)&buf[4]); + rt_uint32_t want = rt_strlen(IAP_BIN_PREFIX); + if (real <= want || len - 8 < real) + { + return -3; + } + + for(int i = 0; i < want; i++) + { + if (IAP_BIN_PREFIX[i] != buf[8 + i]) + { + return -4; + } + } + + return real + 8; +} + struct custom_ctx { struct rym_ctx parent; int32_t file_size; int32_t w_index; + int32_t recevied_head; const struct fal_partition *flash; rt_uint8_t ck_buffer[RT_BUF_SIZE]; }; @@ -167,11 +217,8 @@ static enum rym_code _rym_recv_begin( return RYM_CODE_CAN; } - if (fal_partition_erase(cctx->flash, 0, cctx->file_size) < 0) - { - return RYM_CODE_CAN; - } cctx->w_index = 0; + cctx->recevied_head = 0; return RYM_CODE_ACK; } @@ -185,6 +232,23 @@ static enum rym_code _rym_recv_data( RT_ASSERT(cctx); RT_ASSERT(len <= RT_BUF_SIZE); + int offset = 0; + if (cctx->recevied_head == 0) + { + offset = _check_head(buf, len); + if (offset < 0) + { + return RYM_ERR_FILE; + } + + if (fal_partition_erase(cctx->flash, 0, cctx->file_size) < 0) + { + return RYM_CODE_CAN; + } + + cctx->recevied_head = 1; + } + if (cctx->w_index >= cctx->file_size) { return RYM_CODE_ACK; @@ -195,22 +259,22 @@ static enum rym_code _rym_recv_data( len = cctx->file_size - cctx->w_index; } - if (fal_partition_write(cctx->flash, cctx->w_index, buf, len) <= 0) + if (fal_partition_write(cctx->flash, cctx->w_index, &buf[offset], len - offset) <= 0) { return RYM_CODE_CAN; } - if (fal_partition_read(cctx->flash, cctx->w_index, cctx->ck_buffer, len) <= 0) + if (fal_partition_read(cctx->flash, cctx->w_index, cctx->ck_buffer, len - offset) <= 0) { return RYM_CODE_CAN; } - for (int i = 0; i < len; i++) + for (int i = 0; i < len - offset; i++) { - if (cctx->ck_buffer[i] != buf[i]) + if (cctx->ck_buffer[i] != buf[i + offset]) return RYM_CODE_CAN; } - cctx->w_index += len; + cctx->w_index += len - offset; return RYM_CODE_ACK; } @@ -309,6 +373,8 @@ int iap_main_entry(void) return _iap_entry(RT_TRUE); } +#include "shell.h" + static int _iap_entry(rt_bool_t is_boot) { if (IapAppAddr && is_boot) @@ -316,6 +382,11 @@ static int _iap_entry(rt_bool_t is_boot) return 0; } + if ((!IapAppAddr) && is_boot) + { + finsh_set_prompt("msh (IAP)"); + } + rt_err_t err = RT_EOK; struct custom_ctx *ctx = RT_NULL; rt_device_t console = rt_console_get_device(); diff --git a/packages/SConscript b/packages/SConscript new file mode 100644 index 0000000..ca95be1 --- /dev/null +++ b/packages/SConscript @@ -0,0 +1,12 @@ +import os +from building import * + +objs = [] +cwd = GetCurrentDir() +list = os.listdir(cwd) + +for item in list: + if os.path.isfile(os.path.join(cwd, item, 'SConscript')): + objs = objs + SConscript(os.path.join(item, 'SConscript')) + +Return('objs') diff --git a/packages/pkgs.json b/packages/pkgs.json new file mode 100644 index 0000000..b1e6172 --- /dev/null +++ b/packages/pkgs.json @@ -0,0 +1,7 @@ +[ + { + "path": "/packages/system/enhanced-kservice/rt_vsnprintf_full", + "ver": "latest", + "name": "RT_VSNPRINTF_FULL" + } +] \ No newline at end of file diff --git a/packages/pkgs_error.json b/packages/pkgs_error.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/packages/pkgs_error.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/packages/rt_vsnprintf_full-latest/README.md b/packages/rt_vsnprintf_full-latest/README.md new file mode 100644 index 0000000..907c598 --- /dev/null +++ b/packages/rt_vsnprintf_full-latest/README.md @@ -0,0 +1,59 @@ +# rt_vsnprintf 完整功能版本 + +在RT-Thread的kservice.c源码中的这些函数的实现是为了满足RT-Thread内核的自持能力,即在不依赖标准C库的情况下,RT-Thread核心代码也可以正常运行,因此rt_kprintf、rt_sprintf、rt_snprintf、rt_vsnprintf这类打印函数(或者称之为rt_kprintf家族函数)仅仅满足内核的使用需求,不会实现完整的、和标准C库一致的功能,以减少ROM占用。但是,很多社区小伙伴希望rt_kprintf家族函数可以支持上更多的功能(例如打印浮点数据等等)。因此,本软件包实现了该功能。 + +本软件包实现了rt_kprintf家族函数的全功能版本,因为rt_kprintf家族函数的核心功能都是调用rt_vsnprintf函数,因此只需要重新实现rt_vsnprintf函数即可。本软件包基于开源项目[printf](https://github.com/eyalroz/printf)重新实现了rt_vsnprintf,在4.1.0以及以上的RT-Thread版本中,只需要安装本软件包即可。若RT-Thread低于4.1.0版本,需要手动将kservice.c内的rt_vsnprintf函数注释掉,再安装本软件包。 + +## 接管标准C库的printf家族函数(仅支持4.1.0及以上版本) +本软件包有三个功能宏开关,是否允许本软件包接管printf、sprintf以及snprintf函数,默认为yes,即接管。 +也就是说,安装本软件包后,即便没有使能libc(RT_USING_LIBC),你可以正常的使用printf、sprintf以及snprintf函数,当你调用这三个函数时,会自动被rt_kprintf、rt_sprintf、rt_snprintf函数接管。你可以正常使用printf家族函数的所有功能。 + +```c +#include + +printf("hello world\n"); +``` + +## ROM占用 +GCC下占用8.6KB, Keil下占用8KB。远小于开启标准C库的ROM占用。 + +## 如何添加该软件包 + +``` +RT-Thread online packages + system packages ---> + enhanced kernel services ---> + [*] rt_vsnprintf_full: fully functional version of rt_vsnprintf ---> + Version (latest) ---> +``` + +- 使用 `RT-Thread Studio` 打开 `RT-Thread Settings`, 点击添加软件包,输入关键字 `printf`, 添加 `rt_vsnprintf_full` 软件包,保存 + + ![1](figures/1.png) + + +- 软件包目录下多出了一个 `rt_vsnprintf_full-latest` 包 + + ![2](figures/2.png) + + +- 打开 rt_vsnprintf.c,发现其中也实现了 rt_vsnprintf + + ```c + rt_int32_t rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list args) + { + return __vsnprintf(out_buffer, buf, size, fmt, args); + } + ``` + +- 注释掉 kservice.c 中的 rt_vsnprintf **(只针对4.1.0版本以下)** + +- 重新编译并运行 `rt_kprintf ` 和 `LOG_I`, 浮点数打印正常 + ![3](figures/3.png) + + + +## 维护 + +[Meco Man](https://github.com/mysterywolf) + diff --git a/packages/rt_vsnprintf_full-latest/SConscript b/packages/rt_vsnprintf_full-latest/SConscript new file mode 100644 index 0000000..6dea429 --- /dev/null +++ b/packages/rt_vsnprintf_full-latest/SConscript @@ -0,0 +1,14 @@ +from building import * + +src = ['rt_vsnprintf.c'] +CPPDEFINES = [] + +if GetDepend('RT_VSNPRINTF_FULL_REPLACING_SPRINTF'): + CPPDEFINES += ['sprintf=rt_sprintf'] +if GetDepend('RT_VSNPRINTF_FULL_REPLACING_SNPRINTF'): + CPPDEFINES += ['snprintf=rt_snprintf'] +if GetDepend('RT_VSNPRINTF_FULL_REPLACING_PRINTF'): + CPPDEFINES += ['printf=rt_kprintf'] + +group = DefineGroup('rt_kprintf', src, depend = ['PKG_USING_RT_VSNPRINTF_FULL'], CPPDEFINES = CPPDEFINES) +Return('group') diff --git a/packages/rt_vsnprintf_full-latest/figures/1.png b/packages/rt_vsnprintf_full-latest/figures/1.png new file mode 100644 index 0000000000000000000000000000000000000000..127f1bad6601339a11df8fadc408560c940ade81 GIT binary patch literal 44224 zcma&NV~}Q1(=AxGZQJa!ZQHhO+qP|Y*>+c#ZQHJA`n`AVcQG>&bAIiJlbJgeCv&Zc zqbwyZ-cbt#q#-7(sIJIKRQvCo*aVUXOw$OK55muk6)j3aT!d^{`$Pl^)?D`3Gac)- ziO)#Sf_%wsINty4$7<}n&$rYD^xT)FM*(FK;{W-z>->#*#@G+={x1I6{iJ_{pZ~%3 zmKY%HG`Qlw3uswi)$?NWnm_Nq=pPQq0WAI?0sw0YuL5^~rJpn3h@a=5kROf?#B+^j zz_q}Mz%0NJ@cL@-!*~VRZE#oc1i1KF_67No`eyukeIwjX*adv|$L^j3o&pMAiN6!R z=C2Yy5fc%w3l0TtKa~JQfXy4s@5OJ-p9V+5lif{$8-K?yi-3E8)6Xzqb-~~z;5FbA zunA}f0G{x_Nk99)7&ipI1^NL10Fb}~0Pq3?82opZ=z#oY1pIvcnEk+htR4$I7o_nc z_|<$NUNgS*%LHJ&8(ao#2}}UuepUfB-xfO#`|mB6gdYLI0&#vGpA|2F$AatrF8|H% z@gLgnf`5KD+!G}K=zI#i1>6>N2^{zf1z`UOe0P6RUN^itY$r4s^Z{J9AFBhZ0a_QZ z7aBADV*pP8Hh}hX_txQ$Km#BVfc!)H-T!6)0KEDqe60QuKEi(P0s!BHg#uIk1p#S4 zub)BR^MKdy{-ORgPq81+Z-H;br+y%T8G*)t_8-8H1Ay?o;hzEkqdyl=_ha%se$Daw zb`CHKm;=!M%mWfW8~}iKfDj-JpbXIZ27JB#INTQi0H1!BfX7#p&nCd;cFaowfT@4P zy?#B5w_n@b$GQ)0?vZG2l&wyIgA-hLFLSD|PD5Fy0=%RQCz(#o)*-y`>R|;(Qr8UI zFK0E;srnXlUc~iJ{}-XOwF5;0G$$IyJ*&TC^;PPG zteS;<`}lEx=qu-w$;8Nf*E%w!IsnxL4Dvrx;BMyEJ8IIH5QT7=i^P8vqaHGW-Jp{92YHMmMwx((FkOqiJb!mLi z$o=hKP`3YfU5abNlWI;`KyhGLe`|IFFAjo^@D&9XAOUycBD{-v0xsjAVX zlX0+yh^)L2+A4@h+|3s8E!fLD3&PTWluQ4otN-f_N)1@|2<<4atkz>Cf8Akil#UKl zBQsy{V@$l&B(_Ol`5e(NtUv6g=~kEn)`q}f=-5omYxVvguKf?|izr#2f^7CyBNDmA z+Z=EnJZ0f@Z1ikPViG_(Rg233m?XB$BO6%^8B8X)RKs1I*>=F2vh2n;|7)24!`4|L zvBR~%A_uyBz@VKDzD$>`6C6Y*e);&h3_Ng-1htoZZW__JhkA2Q@ysOrFGl)||BF_hX)j`}g|sjAEjtR&5$dv(M^3IoV1i76f8AHDnwAIVmUy>a_pYCI3g# z|GTXt#}P^<3!{%w=^WmWMWTz zhURvxeN!7{9k8UJrm`K6{i`6{JaQv;u0gFm7%w&F`*5i$=%!(0o+jK$HxRDB5v|_{CQ15@4xTEn#iX* zxP;itUKC+7(1_cwl`f(Fr5wD15H!1II(gf$h~m#F4&;t_WFWSjLjH zZMhlJZH%Np0ZEUeIO2Z1(JFa(eCrK$lauwB;$7Kn2pQ;VC za8!#*kb5ckd%CC!uZyseFo>t_p1ZD zhrK@yvvW!HMZr`c-oWfp!{WQz=u|_BSVOr2OixZ9qRRV5s$gw7kly+VnVJye+~Hr~*}b>X?ke88qPiv0p(Y`{P<%TtN7aBT8(<+y#4=tpT_bhBVUI$fu} zw_Y3e(=@}0X2`>=K6~x0nNOC=L{=Z=LXJzc1MWQp~pt9SxwmDQ+x zJ#PVnIVX{c{4Txd*iC^gybK@*3-pZC$2Ur$$Ht3c;B?kDbGba!DEIM5h7Z2M=w~&j zpwY@dnTMaHlV%vfVcy z`uAk449rN#SDUsz;%FJ*9kXQ1p^~z;bElgJTLvLSw)>zgmR<4i(@Q0zR4K!wC&S$OWxc{on-%;)`OqT||UQ?JLXOX`tyXoGBQ#EYRm zkxozmtF<7sS3DVIHXf9RrAyf}!~eb}Y;8Gs|52F&#%tTqPMGHp@l`T^2rMhtY97t) zf9ZQ`Pn~)Hui@K>_K}_9+Q>ni*R2!sb?WQAg86u$0Bw@(6Cz~rU^f8!1!h_KIoS@x zcsi1gGS2o25!`>Y=~;uqfbUx`;_UcmuV&*_X`NX#N)?#o?6P(Nb@3*498NW1H)x;? z8KyfLV=K2ZjH0>kzpted{q!ViLcoH<>Wo`RXxi=nZ90F)068?)daE0xFs=NZ=ONm5 zaj2`-VGPL3NyG(haYQ6Sv|WaGhW=pG30r(;H^7@5s-mDUhJ1~YI*T>O-K0)o1=A5y zo8QS9D!2Rxu9~~jmT6ir@RSE9Vxv7oBmjyy0KeDwyNJO@A+R-)yjpeQ5|HI?1T4EcgSN^;D|RX?_1yqT|R_N$?G ziMvA2`hzgrgJ5}!vJPa!zah)UoK-iywgI8v8#0fsGT;JimMG5%Uv?x87 z1#WF$JlM_{9I?%m3Fw%C5};V#V!`IFdI&Cz;LRIHQB9G?GBqS|Ys?!LX&uX9lD*E1 zPiEA-{vKxv)qPq^`8#s`zqeq}f)lI@dGvT*A69n(Ov^Ey!WU%zZo@zcue|P+c4dYE zM5&>BK-(u`{&xCi#r z1KKLRVDHuCL4|b;iBe@Ay+ybZ(ksH&55&bgFyT)Ta(dO|RQFG@bXB*wtH;4Mkj`4V zB6fsAr>SwvFgr9ePCiI5`ic9J^AmW94tt6nWH|o4()0*vCcsodn4Ib$jd>h zIEZGWe_(W9Zx|rPc%l|#iI5#94h%|rX?h*1GDfp7$4!0fI&u1t92FJrdKx(7HkI`9 z9d7gGT#0?S_*9+(hEc3Q?kAPA)4p6P>&iX?%}k%tuW7m<=Na2iNi|Tix-!Zy~+znngfFpbA{q+XwbDKn_!Vi zIo>EKmxCa-dbaf~0G}OpDDSzzAIfg1LQ#{MFCjSIrL zE}e|dyGiHEn!rqk!YT%FKecEfDFzHop-grQO_zrkT6b>oNQL_Yn4ISYPa=)gEPJVz zBV*fGP%yQAS;UWIJvG?$fg;qOQJV^Sc;Z`Oc^>COPu$i?rkh~W+Y@+-bYKNVP6Tdw zQ2lRd0Dl`Rt~|F@ae`0s!fIaG@zN-T_R8ws;au&msQ%d-EX@>n;)@{PR3bf2HP$Zn z;6x9&!67W}y8My7yw#;FyUFT$iq3xT6D8r+pU&XOfUhp;)lR*OeUH z3@WAHjnopr5{il*Ou1!b1+8_lU`wO5#qz^Mf)o$h@(zP6>-wdML%qTtq$SQ1+gz-u ztGU~G7NXf_RAqnugpu{mC@}(5BB|;1AJfV2lJ*AUqG|D6S!r9S;zl&Uow`OM?BZ#2 zCFuF2N`Fs>6}+CINvJ!IZY4i+XaOi;$AATOJPn_+*$T z8`}SY;p0+ldMsO})oF}rxwJ})?=Hhx$#q#X9tS4HL`^#Z&65i~mMfOns=csP9ryQ5 z!>L_gYnyH5^>%O#r!({!Vu&3HxL#&5N15q9WQ-WLA~qvk{ctpbS1?zh*i7$$fqne* zUzT?h4vN7%thbL=CRsGS##&ny1UfCo$U89_C#cyYx3-Av2m+hwoQSV6BA(_zZ?AZ* z!Y|Utty@~LRtM{zy&5A8gUlQlCOBRMj3R=IZXr-rR#}9v0R!~VW+P2C&aa9P?t$(r zSMVDmmL;9gUP;rm{=h~<|40Dx5ydpP>cZjF{~$(UO2+>k#*{*_tNaJTL{7=dE1?)W zhyMdRKVal0y;e?fWR=Lhj}K9+Rv6^L$OivKe-L~tlG`}Hl4JC%|BcwB7Vi8R%`PP{YRNi%e7 zbxE<*;ZZmx-Cqf$!WHlAOd|M|*vcV3q>cMMo)Zqw^f-SRF!6gUgx1;T%pbAY8`#+@ zc}pPGxr&{?%@f<>0tsf?K-jn5&oyuYPa{qzn^=S!59*(P#;*=j1uzN@5LK0QEJqa; z1SAnC#@Vq)+sH3hQ?mYQu|syp!2Ae;S8Y;q=>`ldy&o@+5QgW(VN^~hjZsd4YAC43 z>>|>V`(lhNUjv6GF!CAJB9#IS(6YKlczAA+KwE4r)7>cDKIkDuywQCX@mJmN1D*0? zN`l9?-6atIn*ILX&f?zer^uO8e~YPEk4DkBm8Xzs+{&T;BXBQcaPrF3$!Hn%21F}v%i+w(^k{#b50_(ny!Ub3)YWHUhDeb# z&#)z0j)@78oSqe4{62WnshjPp8z^UVGDv`HMr~>b4-veo9v@k9=c0q1HnucC%Q9qJ z5M-Rj&m}?rvuw$#RKW}cr_R#t0yTbU%Xt0~D|ppOTmy@~{@qH>s5GG4WIr$Px}B;B z6F}wn2YhIB(%LrbmXTABJf)iC773m~Gd*rds8>+pQi!g9jir*GfnSFE`38a$AnNr| ze2KjBT4#UlJ+?SC03f_Y3>p}VWJ6Pn_3b?r;^T9ID0|}={!VS>VV4ABAM#(ovdWyj z{_s|EZnP%oKI!rs(4OIJ1*_LoJ$O!o){$<EwR5(HL*fG_vK>5p82F;gH+UI2Dz; zTLj_N$;KE+Ci5L~RQ>blW^X@YMm7agj=e~aI8O>x{MWy{mJGuN>t#PlY5nMTwhcMk zZ$^rk`-gh6SQ>4Z6{)UByAljhPhAc;GKS|bi%upv^E?G=7I^&5EzvT$XNq6m+bgGg#r^r?hOW+L!CiL=*ab5Vrg~6+<)Dbw@8uV^{~_Ut$A8Warq2l ziR3kQDu@g{_%K!>M;BnwM?P|^<3U8tU?AN7rVfn;aN(xDunWZO?^H!2kt-6{tE~@- zZEtE*knJak5g*tIsK67WoZH$}Vu;;58jq<=u>1n!w~4Gc@u|Z#7T%3Q_<22q=IUbI1rS~E7du$EtSV@+zBtV*VeSU7M=Qp) zVz*aaNKF$vdgl=@OQbFi(feAZ3i{J3NspQTK7ry09-KJh|B8eC3*ejB3jhASBOu`5`%Z(y=PGdv($B{g)!<ySa z2bZ5mu)W*_jt7mv9zOB;w+VK^h_z4*Qrvu7UTf*@UiJzVlkA4oG!#=_lz>rV@mhG% zXvSIU_iF|F?o|ANsT&$-#WGZOG>BPOjzzWY=Nm5dB`we^&kmE$Z;G|w6%!X4Ib=(l zYO5|{=oN1^5O=-t7{B=UhQhQ#PKGmNltK2{areB!w9moBO#Fz7d9Ee4oe}7TTY@?D z*-btKG=kBOZKJr{qd4+h4*q`ZJXk?2_LB^K!Fyv`_@5f#I)0VaCU%R2;4Mg$4AH!L z>6;FD_W2b5T5tfP^}P5ZrX*)?ldWTIAHn8M>2^n6b6o2LH8}4z1TiHgn3yLjGfVw5$E<>(le1!cSo5w@(t{_S8!E2()}Cxem==*3J$p^2F0tW}&+}0FLDm zYX=L|q)Z0ws=W4&BF8G*s6b&@HL^r*8lW>m#A&D6%--!G@`RUm%br!V;**P`tBkL8 z=1q9obgkHu8biLJNpp8r*GUy&5S|I{gP};%!a|m4kWyiU(u3@$C~VX(8LLRSMXfi- zj!*O3j5TwOgU%4Tg|%hne-1dv#K|icGeYOV*s3M+lzcI63+mjJRgId;sQO6*2mVdQ z+5tp*T)YUqLHdeFZ;V3)B$Jt6x#5?wx_2N=mKKe)0EOFo9gA2My7L zbMa3miEjoHS&FO*Wb~&r&@fUt!Iar;p=>DH6%+zs%>netkceCniw3lY-NT2+w3gn6 zRfMp22uwrQ`~;a^OBW)o{h~CF`euGFPvZKuERizcL=)OTg3CX}l($mDXfMMCSG3Pq zgn|gbP^`CJ87N)q9vXmtReF(;WyK@N~2&BKl;t!%re*7Y5EhvAd+ z3=rl7>J(b`zC+7=CII{)I@GlBo`4{TEpzFMw z0vU8FQ=&wWBWdE>haV-yua{g&R`FuCYe(eWO(hl-d>ewqA`s^nh!eem0Ve;Iss6I8 zX+S4aYyTQfl1m`4KK$t9&%a~_N+Rl+?Ra3yOzsA?&_Dz{*vqqG9Iw95(b zwsSsT(37nzEwUn1HCvGmFH{)58@e~^aNyD{AE$h8FR{=Txm2Oo>uc~4$^PJzh|V4B`&hh zcSsKKK&r;yfQH-Y)Csw z09j`k5R9&U2NOw(il)CQmz1IKJPKg4AB#g)jNL*#eI9sH()IiTl#@s}48~Dg2^+_U zlKaF*rN_AOB`$&ct<*%0)$1eNTajuo2udPv;Esrp^X8QDED2dBAPA5oyf32sDhjDw zv+~orI2tXEltV_bfNOS-;~}!*3J`B7r1t|rn%p%%}f zhb;EQslqX1PjX}XAQrPa;InPBYG-4Ew94QnIC_WNE$25X%6@vD-pP;AHZ(H5!PCK_ zF&?xPNSEvIq$%v#R}bff&8V=*%0npTc0?2kEwN96fWr|c$VzT$TV_7;M2GBO+H-bV z37T}sWH*+^Hty>@nVw=FS`Sytb(|bkh=e26j8<^-V^i8Z*#DCPDx$a1+!pgHw zO$AHO7Y?p{NT8TbI22*l^HFj+;lw5c&p6xr8@#&~6(M9T_5~tYDPvDrgGq1P%y=PB z>uA@@I{X<~MLr=$Q}2fC{^&_6DV^XYg*@BIfmfx!U`hq}J)HrZ(-+pXm&y42W6*kI z-{u1hY9;EBorbY_8f&k?CdJJsNvMa@{4-~z6=$EEI;JKuY6OVOUa?b$LElo{d{h!v zP(H=q_Gy~2puK?}n7~e|Kg%KhU7)`j^bzg(!XRCnFq`JkFu9e_8Zap>TQ_Ca<}Y`Q z#^?5fPN?9`p79g{GnKIj_Z;6vlRK??PbTLeCi-6o+ryD3E9C8rea{N{npVGGXe!n>Jj6XrM$>?@-1Dp0g_!RyRtwqUab@V&qRp8*VVsT=e}>ep<8DD!-OAe6l=O3B z1C*{?ATCU4UT5K1__+cj0rXmeymXBfM7bU~D91|H=r^5(Cv!@76gEzanxQ>R931=Y zUBYq~-VPJ7fT|P?Dc^Nge2~J`=`3c2P}&|&(>;-yWzt~z6jY$~{f|gr2$2T(PGXZR zsW*iMc0$9;^Rph*QPe{h96ztUbB!=m3Rqs0g#$hI`EaPv?^R^-n)1W>;F|eWu0dQ~ zGakuAIWwA<6I5v4RwCTa%}_oO!Ysj{PMN~$BF0$s*R|*i_Ci5aeEtOJ+;Ho{2G z{(6%u{H=}%-bS*6oi`KVg1xfa+?Ee{&7vbXM)qWQ&>2b4)yZ(%%HMf}rWyd?Yockl zr%qAjWIbruc%*>+6*Bl&TPW>6os~*YkSJa!he`UD&Z!1tOK>h(9jOs%V<+# zKewC%(cwCXO_2Ii6YcxcS1U6BL-#@^OBx(eSL|J1ysynaMWH$Hy6b}xWD`DLF^niT z{AL5$501IukN9IDyT1L3874PM05|)i@!iPJqbqDZ;hU1<1AWMB9E3nPEFd6Ae^G4T z_dFpA36^V^3e|Ys6o*{x7sj@VtWFLPES@-=*4)m&^)M`KHV#2XNilv~Te;r>uD+w- zjas($eO)*vNNmaRZuVm}ZimFB)kE`$Wz&Sv(^uc^ErDk0v&;CH`$7Jl!V$iz8R$?& zkq|~Pt_s`T+SVoaey8QWc)$8G9P`sw?bf~pS~Bt_5?~HFiGn_^C8)zK-!_5g8O;8-* zdkVNWCXdV_CssGLuNFQ3(R=zhcS1y%p1V=+HPAWDSp&9_szEV)dmkWh#Set4_J61X z57X;v_BW3o@*ZVzPCjwy9Q8F51j}eWjAgYLh0Ci_;kU#qGAI<1K7*#@szM`yD88`% z10`pAyl>i#5MT?@Bdwzu($DW%DKAgi!To^2aodgSeYEnIc z2M1bB3chi&^69Z3`Q~QtGBF?shtEE6PCd#td+9B%ss5fH@YUJ{fO&z5aVk!7W4WXP z{A;kQBUEO*++I9M6sVL|@(x<5j)<=LWirmf#N!Us#Br4c^nriTK?&mN$)CryU4^qn zt-)>V;JCm5dztt(%>lN~FS}UcdiknHhdqI$aM^;(SJ0Ob+$4hpA%j_FCZt}7WbPI2 zPhQu~SklLUeo3c)|G0R_x|m;krb3GeKz_iL8>VN!{6&eaXHJv_VGE7X%x4;aLsdu4 zk;$r?qR4%Texus9oxWmi#LDt}y#;Twt(zU{u^sN>qPEx0M_h;_bF@H1DJ>8)7Fc~B&9Qz_iOm{>4iN`%eXQk?-)zqZpPS?BA6G_3dmwDUvlDoz2&#XQus$+>S8X(K4zNvT7e8UX+trc1kV}AM{Y+ zZLB({jTlt=6+$!SVOnsBP2pMR*dOtEspc``&&Y!3gP?V1KzmmdSjmAeSxe=cY|TV; z*t7|k!v4DR)qtO;IwbiBWFbMB^Q&OM0%f)GJvrIL0}^(t=q$!e!v=@yO`fmvz zHX7q`Iud;2cg`S+R>ZO9jRjaN>JkXh(k&*Y_$#ZXn^`kgADlnN!O7me{6S~2@;8FO zWw%e|;R>LFcGrIWtA0_1|GE*)TfTe?%+xpb0y)nUToB2|5#2hDD<;Qu%9INcyOuV%k)_Uw5gu%!vS5kPn)F78=I!qsN*V}f>Elyz?0c zWgWX8c$7SqjZbw;cif00XtSBbBZmZh9c;|(+mUxclq*!8IhY&4Ar8aGYE20!v}&kRve1a=rp8@AOB;8 zcAO3NGjmmv1+8NI!7$Ck>W(yOZNdSC3nO(;%D{^aQ~uV6o~%UZZ~5oMt&SgQqYQ@22om}ZUbqvh;ZO=ApSrvLi=sY=8@ka&fyx;(VRTxhfO|g zhTB3En!)eplUhho$I1XxFp`&)6BJW=V-tBEo0Y$B$QwsO{kbw4{|U|#cx6l?-W$0& z#pY1V&^)KXZWo1QvcmrKdo%jdFvd2do@Xv`Ch?-W&9iwm%v?nVD(>Y+-N8!i4s&>1&*F!VWbo60St9OVf~Hy+n`&AQJ*_!90!#3)VAG zTShCf2|TiNIwsrS-U40lD4P{MY~Os5fp9Dxxp#^3_Oni0k$>SmNKJB*Hg1Q`E7s2D=4KC{esrl3$Hd4pK)-Vh zE~cx#&=pBW%P0Rxds$UsCV+1lW?2b~d$@VV@^DwA(dDKmKDbH9md?Bsf~4h*cro_j z1SJV#quU;w*mW)KDL`u@*?zYmeTsDrWd5fjbOW}&P#E;)<}C+QjN$Y%d2Z6ujIpU# z?Krf8&yI28!|?IyK;J_cAY6;A7X#4lFeLI2AISckH*aYrl=ROaE!|DSs=)D!I;zCK z9iUpZnGkgdZ+|Q%0N(`MwvshV9DS}q$A)KSOMg9Jv`2g91I*YG;G1n3=tu%H{<8*~i!$he-keH2i0blVJ(v>T`P?ba z?A>DfYJurrF+f6NA7)8^3{b&MuR6jR?xdYwjEvBwtgqevWUnTNU7#JMvKy3c8v7Zi zH~5T7#iZ5TBSIJ1oN}M-@;ZRwtq&{KK*xGlVHWi7MNs8ugyH7$MC%W~gQ~TaAllP@ zc=XgGr$bRv-L@&X?IL@?w*yJ4`}fa5%HUNjmfKAF!xhG6HYo$ZL*iTdbM&xR7PpzM z8cE5ARym)Y=4KwqdbB+xGx&9K%duA<3g$I?8G$7Gd#FIqb1NPD`1i`2m{TY@wpeB?x;i6e9k0+FKk3A?a#$AHPYqIwHlo7gUHpLj3S!R&YQZD4+k+_-Zx#!UJ$K2lwECI`Pb4RtDUI9KCKQO3Mq zuo|jc9{5+CrGoDc(p#b`w(Bhz1)gfjaq@eVoxUt;YRKX4(!$Zkg&?o2*ATsh-1DbM zF9k-=;_`tP8aiJ$#YnKz9IBNt!i#jumGwnw%%DVJ-On%mqSLdzA-ZW+-vL-V?e>kH z@&wqy-!QPszzzh-V<1O=FXYxs{UJBlH7-P91uTGbJi0=jN8_S=nj(}!uZNZV|4Q7G z7NjX+2udnKy=NpG8L7nY1RUHK=lx~r3bcdz+SQzln9P=FZApnafB5TWtp?5|z-xoV zckAN5`t*{R8>{z*CEmhTd4TZSOJmEl)9ID@^0ZFnYIHsK;u=T~KDv-5ixl2e*!^^J zIYT1*Rv=wHpm!;3z?WiP>Y7FuRc7Kyuhq9)HCd=iTh;$P%%vSe@$OF0rzvqY9hsX4 zjU`1y)L1x=XVS?xhA9=A*f9Y>p^^0~C@d`psm2B|zhjY|zgzRz|71~S`ll@>>$Rpr zuCN@nJjsH<2w=mCQ7=?{|-;8=YC$CG=oQaD$|%YI-uUbS7NIO3S%ck z35zDBt-9d)R(>GR`DTr0zOOZN`}{aFMs589+Ic!M+Yw|}AZOIH{v_`w&)0*05U9Ie zgw25DpdYgH@_fb-r<>Xh>6Ewk?l+3}Z4@`eK=#95;qCJRsSRi&h4xe5JQX8{scK)<5Rif?@=tC8hC65BS z)S1U?ad^98cZQb7n=a7C4RWoxP5E5e1r$4^%37(?F#ZT9?^u+ZtYS)bzAch*aPA9S zohMI1>)f`xOqs2`l+WF14R7B~klswBng6v{(exR5UvrEUOV6y3B%4&pOpNlU`v^F~ z{?7Q{Ei3v78K|i1racw1wJ+t$W&~)Z{B9` z2^%ik*&cWWnfLP-vQ~3ZqlDq!saWo7Q<%Ayg-#=5R%nan9e`E(qS#MdamFre! zy!5q#d3XaYqRhbQpU1LR-lkV#etxG1&w*aP&4hGAS&`Li%n5o$9ircx(N!zRyz^SA zD#nY3!P?U1J46Wt^YA0`w!sk(^fwN1tcgBKzw&i?r6&rHl2Mv$L3MovsoX6rr~XjU z*hPlunP@^J-4tsju8=-%4J*)tvU@9&C=VAxdI_7I7fH}a!(csf2us)*+MZIwWM`(~ zu!Yq&FnafzhnR{iZf(a`!x}PgE@Fz{X%(I@yo85@>H8D%`Sh%KC0^MpmB4q_5g~@a zel^G+v9-kerNKbBf*#)(c|pwXBn<#F@rP2YQPOp5QaMVdHE_PLuY>ndbdpoBh?y!I zR5K=ABf8n3LE;Lg!lITq7hlOc{z1OVghLi58)n=SYnb#fiUBhc!_;SP6wPp}dJmE7 zVc|nNdE=l1H3`d0l^LA8LB+fR{I%Rmd_W^5+*|hmtyBg66(7qCZhK66or0V<(?x4OUZQ{F&laaiC zNJiN_h?hQcJDoexl_E^Y{sJv16Ver~BC`6R=`f>C?@W$c33|Suo=#^Fak#VQ^Fcez zlwRY@*yik%6E|H%F`$8@xF$f>Pex_hj`hV`a*v%(1-qDRi+}S7OSFf`^G#2g|D_H* zYJ#vW%G{%2tGOYR>CYktN<683Pq$DJwzhV@(VEiw-Ot%`W?!3fV3tyNPYs_M`ty%V z{ChXis7vTTM-D)6$l(%veCxA9(Pf9XOoyX72df}rF8JRJ=ZC`0QZR=cGPTi=2Q-X@# z-s}E_{%UOmzu_`9V~@ZG=B%#@DwvQvXiYf~Om1p<6e!P80_Mfn&&%Fk|H#vrUn zA5a@R3+zoUIT?;&fZ2o^|LaRN=kcaf3;TE4VFWf5LFyY#+RE8+>=mmOwZTsihC#K! z#uQq9QLm$J+Rl8xunn1CaetfpQk1sdp5X!t znpD{qHt>UHW<3lLIs)eSHi*r^e(^-)1Mig+(bBl3tY!E{=k>(ytEumLZ}|o)MW$U~ z^a&xV!>RkY>(bgiY*vtCmg*Bo*~vr)xi?SP!82nM+SKn9W2eD37~7S#z1RH!%{Jy^ z$k2P_$?FuoNl%XdseSI*71v6SnCp ztx^(gNZt^G=>fX;tTCl>1(6=CU(k*T>b(Qy2}};C{SEVNsEAs@YW$SMKr_hIp{*#6 z3brFVejTSYp-^dV-VK^r`oy@3>p42(g&`! zVIDTE7d0HCfAFe3=fpN1g_@G3Noev>EtXx)L1;=M5`FZW3OpvOS*{z1vtw+>ndz}3 zP%b@PR9`GpX)~eCL_rkWghDM{#NOf*cZB18t# zIuSi;uh-ekUxA|YUFsuLUUc4B3vUE$^@1T&RW|t>hVi1N|Bq|@Hd@u6Reh-?XzJeu zAv&#_oqv&5R&G_!4zx+kfwhHurW>r4aRnt9fYIY)7$qBQe}SY$OpuE*lJXCQ12FCZzNxg6W|3 zpl0L%-)Ci;`hA*!u){fiYTPQsKB-@mCjS=zJwU?0rMPAKw!|<1vp@NzY0J`FB@2kh zj5=1O&wsfu(Z}oLXPtjS-&AOXDPA#X$}z@?pREThULDMy5l~BG;}~>7XIV zR)o9%4G?a%pLM{%+S&hQ6u9FLKDGgl@PotGGY7>2bLQOcz2vdp%_r{1sBlQ`m%5D_ zZ-Y>;n>wJwmDj|nQu(B@wrV$>%HQf=+cf%O%3zxy*Fcd} z=Bmr75w6*XG>!DvQx_OB-+tflffn6q=OE&u#s@BXzI>t4ApHb_e>FFcGy8U^;%u?BftPBU(L`s$?@%LS^C}jae80=uZ66exT#Gw(7O59* zsM_!EU=4Ff;bpE3N4G&;M9HqlD-d2cqm&kP6`E#^4-ysPdtuqnXuI2KSt~ZoSPdxm z&uwNr$GR9WYn5S*^+v40iYd%e6$d#!9-+hp1OZlpEbYrzPuC_h%26}iUVq{rH!sgA zc_U=#kDilI;49{q^JD4GwB!9X*cbmhHD%ot6U^{yB zMo$bbB0P&nA&my9yJl9K|NaSlLn!zw^nS3_%zYgSvkj2j|4JbO`3n{E#7LKkIi*ToF^)254(8_ zku%gCbLOR?J_h(uvaQcRGMH7rOQhxMRwWR{qz43h)tu>9?+^jp+ z@I|DFD1^|ATsT%}BjXjpH+4UD^rn&csxG`l`CW~ILeVaGL<)i6JX(1BXc#62?urWk{CHV}SX% zV=f({%$P+*b>%eOHv?gOmv6r?*shI{RS#`8-!3~tag?XWY9H9003P}p*R%n5T?yK9 z8t2dkq2aW@qQju)C&Z@{kp7{^flbJHyZ5DX2QYn<27Rc2Hrm!JmKK$8(~=w>PrIs$ z6SzO9cVOn+QYYaOPr1C{%(GOcZ-GeTR|mM~2CuEKP80^mRUSpoXQrLTzddAwwe8r& zOo{Wva-r9R_V|Rtm};YB+Y{S z<1vX1+?5()G>Mvwz&r|#mAYcnV4UlHw25f6ynUcV+Ypl1QhS+r&!^t_13ATHH40$S z$N@IO$yP{GEao6bAU9$NJ#QWIyba%RHxzKOT0xpI!S3O~AE-HHZ7x+M3!C_JmHrHl zA~PwxV_im*^Y)2VzE_D9BBi}97Ze@8ICwHz&jq4lkpty{>?488;B!^doEXWAR%zvw zWD3TPYoqWWx^6*VVViuhM9gtwHt}gdVxJ}XPEA=TS1AxV@w3uE;FZD&X+JCj(mZr$lrZH-MeYqRkLuTHeOLN3d0S3 zl)gRo2iKoK2d@Qu9J5Yq!$=44&-EL`iN8LX!nN#UZwPZhvhEOTj85v-&|qQMYjEyN zip4<*0h!!Ycv>^$-)3j|Hl4;a;x|>EsD-5r6zco(_yV&s}B)y}Wn)=sZr{6G2j`XjOft$K@%*Mn8W(G#CY?&#F~! zg4Ye!I9-aSxahF zEv?Ojt(Ck?S}9-91%(6^3^BgwL&!ynh+b=mZ>h*L?FiYQbKkn)E!TSSm?WJkHdFt5 zk%;yMe%+H7EAcA5Hn6#JB9m{q?}upyDY2k|^*cfx;VIY6RcR0VGG zGG3Gqo%_JzSA>odXDO7+1P>UIAbA*F*2pxlR+Zflksl>|Gidd2hrAx2V=aOqh)apjX3Ah2^})q=QW z>}8k#IyYjvr9)N>G4U~FO%-;8J*p{v#h+VMK?cXf(*^tK*rZvju_bLMciD83Goon& z3t{+C@q~+#l6bAbeHR0*SNwBy3ZyH4*soD&X}2<3*vz5}ix8lR7givl156b21VhxgC_3S6?1@U}d5bspA}cM+FVicGB&Xt5IVi3#ZzbG9 zv9g=^!9{1B!YI7No`OZhHT6B4y*GzRA6-A*-7r#&k%cDyv12FL+M!BC9cS(mt3i3d zAA5OEI^D~+cc4MuRMn{LUh??5!vQrM0JC`O+u<8`qy{}f@xeL@!4h9~9X;(zBC{pv z>AW0Iv@iVSC7Nexb&9KI9=FzcuD?o$buZ==X+b2q?wfPb9eFpt`!-9{iWzg| zc%O`@w7BsNnF4kqW!w~~WG)4vI>_dRQ?r=GGmow-p7m7zZL@OCZ-X z0{6BeeajG0Wa6wae1ha{u!b!^_uP|5h#!*jw|TZX7`-FH_CSzI#vmP@Ht3&I>06 zcZHtHGuMiTP^tOMv*0F>#R?@$oxRPz%5J!9N-*W+#2XO3@NBnZ#1dy~Z#QN$duw!cxV)*K-&d;hElbq%{49*7?Mo zN1r^I*QSdX3SKs3J!QvL!u%UiAb9f5M}^CXWcdISw<;NDK{d4mG4mPi?fwYsaFpoQ zic0*N8#T1`7so=)$q8yd4(TcLrNx@rxMXXKQ<-xT;xjjb^90yyieq8TjqL1HNfzop zv0NF)Cg)z@s@L|C2wLfU#T10f<B9&(*Z||=#$=VdImK8mURBXfTZHlIq zsqvv*?~Axk8XSM+PSHUnl(eT}V?+R9g7r15v3O_)R;fsmQMcBr)74f^0?U7>kC_F2 z9F`w4Z+{CS;T&mbWdPLI5dFgY{3`#t@Tj!rmZFAKrJn$GzDo^czV9CmIu*BEkZ-CC z+`q(B#Mzf=`bz_0-J83`;Z0GQrpjFqBKjBt5Qubb% zoR-O&zG-hd5o5%M#|Uj>%rWx=#Sz+$>(a0+=|+x-`ySY*j~6_P8M`;*Y2(^`K#BWj z!9%&ubw;V7kXr<|zKW}7xcj9biJVWtp;|Yz+!3Wr5qlM1{Z)g#BoO(btf(Hdx#KxG zBN(DPL78ZH{yxv;(2U+*n;~K$9;{+#F+lBrqAWo${vucHm~Ar?&9e;CqDZ zTA!u!fec?Dgaut6{nRX-ua#w1h^6U(F24OJtkk@E%n8g^ZOze!Y!rM3V3lf=Bnb+Q3w?>7`XBw+isd3R7R zejqI8C`>qdhb9j43UUZxSJjsc`6PZI)GFwM@#{L1r!2q})Kxok=f@qFB*S-e>97Nn-NScqgH)-;anJo!oH5zne3D&2w4 zYTfo<7{HVCye5=0hlPPW-M4XElGc`7CN+4lC4CC{r5h}hy$UFeAV$?7q<+CC#UB3E z?*&?Id=Rj#`G42>b()TU8G^O*jM=MMfq3Vv5~F)eE|!r7Bp8V8sPBP{Xep$^2Y)zY z)drAYTZM26=U2Ny-TJt@%;&72DztCoTQ)(4?T~P^6Q^$pw+*=Rdg9`pN3CyPMb4VF z?ID_&H=)EY=X6o$bK&z$C(8;z8s;|LQYA2H1jVLs8yza)pftNgH7>T!1U5KOx|O

+aWtnWdBeQ>7hVm-^B<7hza52BT;+g>-3&`(!&bmA3i!QWBb3dE63Lv<}g*p?qV^H_Y|?&1Kk*O0zW;Q z75|(we)GE4~m_#-}XQU=VNUc$QU3?`XZ{#6C-- zk5^zKJX^(NLd^P!cd%K?bI&Iif%P75eS|mfP!^f1P49X>1YlJHH{(F-4on|DATjX5 zp+|Y3s7GkvBRG9Sh$H@C#Rz<=>-zE$ki`qN5HszrWT6Upma<*GL*Xw{jFSnj%Y6Hp zgfA?X0xh`FOvn*m#)R>cTv+_s22u zI|N)hd9KWy@a!Ko@0J+U~lD1Ji(pZ<8xt_ke=|CB1u z2mT}{mh4>dR^i3M_1&dhJt$AvT{>{^K|I9}fytS6$$c+p3%&Z?ElEgV0sh8^xb^)u zpjW(zwKlS-{hu&vP4UeO87J$?XbHvHzVWCxEU|$gx+owhl(5FC-pdev+ zcGMd6upX&wTQ}5U8~7h&7y3YY{(Gc$(JGE1^=P_+8~Ihb)NZr<@91x6is-n&Y)H~D zBwHY7G5^Bzo8F}~Eme1X4+mQ}*bEx$e~KTdV`u4Kgp+l^@ib_7H)!q)Gxfa=Olr)L-`ZO5w1Jz>W_z$7}h z4``QtaK1zC33STFRDEL}w}!$x(-4-$kp#`(cM+W2O@c6c&XMWV|K# zSXuWRP&hFN$G%d>Rt1ISBJgzWxX-G?#iJ3Nj%1;mvHB4ENg~iuLC(Ok{qZ;YZF4sU zJ(!;_Gzsu^=EYT9xTsboepdKP}f z!-MA?l8sQN#gr9|yeS~ZR|;)d@g27e$d{q{P~7lX;X6$Kex_9K2P{VwsE&I!^~I3u z>$&2#2RrSR|A0w4K1086UX&(khXMVxe9{J&3?1aH`X5g@alS*vU zfp5ut8+t%nK*6{Tazf8T!ld-Xi?zGC8!~LNa-?EiI2b4QG z+xPMgi>iPF0mC%S1IoYvIlKS?6ae6ODcj-2ytP67N^1ev^j`ueq;HB91pdaz31D=& z8vG?*LT?1vB?+s2BVG5XkBIng2+~yb02aKc@59l*K|1j3)Z+r_ zWRc3}>5k|e2;#R%Q*MtXp6oDA!OUkFNN!js%IiF#@hazjou1xKT}I3|GR zqQ3NfN@0Rg=6~g8{VnvY&iDD4==f><+~$49j|63rkZ<{7251`gE+n3oI+yVwjaLN_ z?s=Jl4^~%hziZlM)K_u_rfu0AhPQG}q6d;? z(nrNO|I(+t`<2SatXni5BJj1=fI-KN@|Y}xs`2>w;}XlZ`HyLhK;2@eN$}D%uRk*t zQlLaw;b59nbU1LtRPczS)o`X+b>J{fRXTQvPIe!xvZsWiV+bcu7wf6)2G9XPJrXVh zrW7j&FzVh8b9l9I&fBbibv>DJpyJZTp-RtIe5JJHqby@`lgzEh{JMD0b1P zkfR%e(1Zu#<@86nxkgD9E2uFAip{H>x+lw{3bQ4-(8?Tz`JS@rdj|#Hat%DeJV)67 z=^P)Xr`%5gkV|Wea;SiI18L^D*+>&mpk&$0Wi!W16Xldm5iLZuqje}>CdKgnsYcwN z()TaU9o#$oP$U~$w6!=)ksZE400jljnS36Gi$CGI+suUiwDV#Tc`dRB0!>tdx$0sF zAKRT;Vz0KO;35$Jb%r3+iStMdhNtc|pu{RXosE~l#c(WUKzS&*gZDmwaMmH znWQm;*vj~IOH|9`&tbVf*s#pcF-!<6f=n`(xYo?66N0yi+7Ikqyhc%q4OSTPI-$|U zdSc4nU*YCe{1`cY-W^HwqNTzTk9jn+V{4Xom9-rNjRZSheTgppd(f>{?sn_OBRQxa8*L30dsroH~+|iiF;dGaUAAad& zW^WUPZCdmw1mWBoro}sj%>g(XC8Q&KghHH09A6}&7%NM^A*4<@vdiN`??K1}Ml!hi z@7nrg6(Xd#{suDa3c&*rV5DI~tAy7WT?)tt@SKDU--bCSRU048-5Z_u)yv(=2x_za3nyi?R8O%}M*%5@VK;DMa`N3O1he3=p!8G|}B87HmrGY=;}mm=F4 zeg`9ETEJShcZwhhGWtK5EY9wiQ$J%!4%tr{NFsHKHm?wSBV-`ZD2t|q4D+W5+eVDm z60tP*)yPSzcqL}_d9lJ~<;X|d(k^Rk7$90^DY=kIx<21UyiO1Ht$8?G-(YtgYDbcb zt*usI_hm7h>ZhTK1{sU{$u1ogqOAB1j$f>#F}BDe5-w)UW>SpH=v^&ZZ~eDU?LuJY zTJ#;Ufn03%GUF<*xp08bUp>SQwAH&u4v~&tXMwXdJ@1ui%XvudKgDt-Fzj6D5(_+n zHw6U1)Usw{)<&U84i{Ov%<&Im*?zPZ@WZ~hDP{aFQr!K-dH?{igXb{!0s4rA%u+0a zn2;W6uMO(3iBl@>MZ^l#maJJ)X#32Ce#q)Td446Zlvsx3CH6#J8G^@E|NVf*LJCuI z&Ui88^)YV^xNlyLbBNPM&m$g6BftOv21*DhxT{l}i|;o)RZdFp`qc>hQ^3=Vn=LtH z!nC$N_SiNP#ShfpJTKCx5=I_xZ&&c36ef)5Bcv>(o36@;JpdY@kq7r=DL%cY4berp zc#9`_3YV#YOM^;|xgj)}%M68*Vdt2#8eV|kc%XfxBVF)xDQHYfF*_^EJu&Uq>2cUL zOGB#dbw33_qZ<*8Bj=7HnQ^vp0McUt^ra9|2OWT2n6b*MF`iLvLj$kgn< z8sGFn`I3`bkMpvL%eA6s6pT~uv+QsxX!0JoEwRW023cE)J4Bkm6f+ENa3UFoz8p~o zXb7z*_p`mhXe$VSy$7yGNvSi@U6xlbBz)4F=-U>VPzi}LzW7g}JZ3PT(D0zAX+FiK zS@k46NYBY*vG;vlWe)q0(U&b03TIiWzn=O>=jedV3~I5-34~tw;7fb3(Nb^9VB0^9 zkXe?tDSCZ$$G@2Mrami4sjZF^6zpOc-*!%BY3u%0$!#&*xwkI4Qpk~Rjpt8q|J=?} zl>ikdFtd2&fEWO2!UXI3=my{fG)pxw&Kq!(De(B0Af%Zug6(OfY<1NQz|7z75>p z$e}UXd8!vK@==IYIs!@gB(1)^Rb}pt08OiSVTj+xL`~1ZcsM#-Xco<#bOlzeBu1yV zXtYBfxvoCV)VHP!gjij%DL7YQqRH@&f(?`!!T`3>-kX$ck0&ulXj>$6VNf;smxY<~cIQf&Dzih6ZoP^Omy{LZBDsS56d$3-= zj#JZ8#YOxnIQ-eYW^3@_Eckk+c>w17Y2i~J4#0R_rjFWH(L*!Vn4o0mre`+)>{<$g zgVwaf7bxoDa|})bEv@qq3Puj7#%F_?Ny!kwxU<=hp;~S56OpvZzyV( zkJZywy>T^c3C+oC()RG&_~umS)rj)}m_0w@=1WyIW;V^6wkC>P{Xq1$+_bGjN#MTO=RvLV5qzGvv^4?E6Gkh&{eH`(-6qhH+C(M#PJK_;QxdYaJ&P*x2Pj&c%GF)<*P&*O14?E%f zHVYuIjE)>X?xy+zCygq*T(SWbpMezQYNdjzY=B`No5#gv;`Glx^pN7Mp=gQJpd`E* z#yTh=s7gIRt7<|AUmn9h#31g!Q2OHS!@4kY5our$et!@) zsW)dJV5vPo3K@U^AeRPjGYD+W0Q5HQEf|^8)TZV*W{*Bja#b?iOr!36JRz(@6C9wJvk(%=Vpd6X<%8%iJ$ixb zjy@*^=|oHh^=0cBW)gR!Y(st(GxrMm{1%`h5k3+6jq_Oso7U)9X4TrR(5(q@bBbL2 zy@gaORj&#iPaP}`X>Sp!5@Xn{3Tzj!A-}WzT1@HU_>1#BN4ymNS-Ka z{9FOd7%o|Z=X$0vn)G>I9gyc+?o;aEZ|f>$b-J#U=h^#L((ALX zE$Mp&KaKan%EWN?QX)95GN*0N2pfbqzWc5fTWY@dz9LTYRpl$-yGG@?f(za}&XlHf zj2w`8-^819cVHFees$_XZ=+?R`(ixRg3qeNhb)8sTgl;s#?>8|GpX;VIsC5)+QBW~ zRh)7-05yr8;DQ>v#`S=cXysDF&Xc+a^}9R!#O9*V(V?aa#ORxG13(nYSLNeG=y!9t zQ}jExaB#p@Y|{3X&=Et&{g@mho|&FX=#_dG89Sbn0aOqpHmJA~0eGIkbkC&SlFTx# z(RHxUGOqfYPsFap3$ZuZTIpb)o&_UXO!6sa(n$Ok9iP9(E8;GH$( z=W@@QX+>F>KLX`ERx*#Ikh73-JQ-3C0FNbr3mHh9osmDSwLznqNkb%m02L6ZC-|>e z6gt_&&hplQ>?+UCb>&6DB2j5)M0%u3zw`G2S7A6jMvU%fBFYupbO1;}38dIG2UI22 zoQK=gdMLS~EIKGOMyBWfXkg~|e(!(hyoKQA~`S)++D5mXJ)2biOQ!Bynv4)65>F!`b!< zq);7ToGasUpjwlWB_+F1lLo1~468=`!X*b2dM>_N3#68Rx{%E_-bI{9wSN#0sNYKN zj1RaVo(M8H8%SzMz}0xk9xF^aszWjUD>^E}D_w{kqMLJ&aTVux-lwqxml-iR8B`R{bidLQD|WA?-*yb0jWqu zV2{daTLLf!CY?E@-r(_H$#vmY(CNGIa%(dlg>h8=2rc8{$c8D#+9~O<`5CSTtW8p> zb2{^XU=8y0BHF;_=YlI7%=Thx zWU)f~bgZeQFPhro#31qAdSCGAIR0P39v~pP`;vt-l%4yhW zE~$%M#EBZfRRjplgy8w|(9sX!g4_1aa1r?G zeJ+R&n%Y@tSYmn_-XNllLuqI;TsChx;$FD|LX`=>ujgNf$E70mPFNeEBV-UyF@J8t z{u-t(SE3}r4H35#l}g<@tJ>%b8#PwSs2xZN%cnM_$? zp3$1GRCal7tssQp--m;r&m#KBY(Rkx(rb)jJWqx1p`o#vhaoKp*X^kRF|~XZ8w}{k zX8_MV3v}t3SLqqw?C#o#pcDKiff!gL(ynm!XC;T_ZMI*bu!uhGD}Cla$kEy?>|&(G zf4MxX933_+ar#}p$Ur(py%o9kSd*ZR)60uz9y8&5C$vsb?cRuJ%`rp7+gh#@Q>+{u1zS~@t~h<8qV6j}(__|tuE?1r`y;>fR<&1upusTTvgHuHz! zuqC8MGm;Y!)0|5i8_eCJgkc$J1@eP!t5tQF((!*ay5AE!OtzO)WA{{Ifz%a=gZaoT z3}B9C>p;#)tGU+QB7oit^hyKl$Xf{h1jA_C^QV0V;P?AaOpEiWX*;(ww$qA`4qTmr zklkrUTVDhT&z7^C`RIH@UF9>3o!g?f?Dfny|`qe#aop#Fh7es=M;v*h_VSz|n!<1@Z@(UPV$5ec5PRuOFvwWS9yenpGSE=#BPf zq**tQM?mxBFWclm5Rw~NiJFOy*LDsVywSci{g%95BBup9{W4)XOSZSkp43E9PI)1e z$@Gh&#Z>I*Y~ELxsYcXtzWy=m*sE445PSi#~tK-~7|E2Da{FaNOLv(Hq$ic#MnYuuL+*he* zZ?oa#S^}cG9ryqJfQm~0Pw#(j*c097CvPbURR^x`3N43}a}<^Z3qhiAGU*0d;~nO9 z^>G{9SgakozKSNrBs$!@Fs^bSj_r_$NjGbaH6{n$#+2GhL)~9$;@_18>oFW`jVF|> z*xp!izF4JarXkG9dNTK2XgD2hQmT4B#9IUFG`mQj|wUMf~;L=#!M7fkb+Plo3|rCt!gePV0}QemF@sU*heF$1emOohg6&W%oV#s zO$8to6saBMO@(Gv*PGqnLKkxGjoMnq)+8uUagMltRktj3`!#r~T^DWiHTFRB!*+oB z3Z*en`fb$hHYZ!F-Iv_|6fCOG3t(I@f}aIqAg~|#L5D!O3o*T27TBP4@h|)c&H$_U zI<8@aZxI)Zw+{HhA`U(4D@W3Av2T$G=72MCfmGsd?5x8FGxvjyagRzDi#>Qn1M&3O zWIwK(EuJ!j&qjl>9*?hU=wTW2B}I|5qpms^VlH;dfg9wD^=;}WrlH6+89By6deb|& zY_9Q>h`KGplC|)PtwJ3Y$tlE3#SiQhYhtOxX9C~yxcci0WcSTXm!oJvk&>jsS#~%* zzS{NM7C;}-rhi}K^0mQIZU5!|nonXj$SB9*xJ#29-r(2;!Z}k)SvXR{`j`hTSh49gkX$u{vT<%&!#?yK}|FZ5B~4 z%ILv|%uV0s5P~nP6ZCq9jS)D?D>a#^mW6oH!f5j70D;b%wK|Sd5PUU@oj{tfhiZ6f z9)?j_UsEg4pDIZW{ih^wNM1eW*tgkXh2^A4$>;?%Ue@=hF7-e`_%3<>$Uyd}l}(60 zfeD{K@a=7D*!XhW`({Qmh}>Os@hX2GJPiu5bN|5M&gsO5cHft27O0V;mKsQI(XAdj?FyvX{;M?9 zu*Y1iv=m#M2{V(>K3ndznLNyVQ7uWzOrSM_z9>UeB)D|`n4%Rt-EfIz7|bZRag{y@v_m+`DwP_7+})&9pC z(zNWk%WAIGKqJ>Dgpqx3rrW_`o}`;q2Vn`FXQO6VYudm@ANNX5j+*69daM4di^!^) zbhG!K_sy<>vw596YNQG=x&a9emp0venAXmPq8F7+ywXf!#H4dK-wpc6Z1~fxG>b6Y z11Mkwxh>S%v4!63f$!oe40lo_#&CSA8KXN6tfi-h16>_ynjv`bI+0vIicU;ezux=7#a>})A+#RfsQ*~jr`p-pDW4imMQyBE(IfR%1u zR{XhT@Bty#_ID6-(Yj7R0q=ML0=)G93k}dfgVQq%m$YqOELwcJzGEYcRf+tEs>P=iZ-6=Y``i)vN$w`Ct ztj5(vCPzy}kf~>1VMrA>&flZ?&n($czu4*SZ0n6kMdaeY8B{$f=N8d10S!q%pVakO zhAfuo+;fQd1v4%Qb1Wc@dN+GaQL5CUBnMQ0faZ=CZirW{#b)i?)JC6y^&dOi%kZ&} za;;`HYJgRrK^4=(; zxsXs@FuMm!o7|U zlhVntXx*Bm%mz%)tlVb5NhupnkFFLfa5z19U|hVJr*z)aXCQy<$G?2GvUI|}Xvb&F zyUj2Z*(qwJc(DxveM_bM8mv-zlP!&+P1XKJPhOP4_t{-!hDnDZ8~n~=gTKTkwy=aj#&KXc|3+r&{qJRMiSFr_qM{xUI)*5fdC0oFhqUX z)KxJjfJ*wEyZOYlcp(P<3Vpu!Jr$@{=B_dB!9#yrw1~bVOe7N%o^Kr_JC%yBz2<&Q z15V&OlO-sCl82>4P`p;J8b_9;b4M+kgv4BmycMT#9O^E~NrN@#P;#M#*L=An972lmf?-^e+X(fa3;f84g@AstHRB@v3b=hMv_>E@v(|IV#e1y zuBlp!g>%I(0a(S;2klL8L=+;SK2+QPd;!zaU3(fVO)2AUCA&HUUSy=A;1$-`t}Bs2 z(E@!xP63B+kR8B`XL0}$(0~=WgW=GS5NW+e90l9iIjJAegfvsFqfv#fw+yNwvm z6mIQ+WLd~u2L>7rFe7g|HC;57t?Rn}B;zazseT9y#l9DV^Uwjf;+;v*-W0o*fWTqC zJX5EbNJd37YM&WIQi>m;A2|`OW()FaHQW0?Q>H05f%gsHsn${Pra8ls% zqYfVltuXLGVSL{jN6NUm7+f?iBB$XMB5Y~hGrj}(aT{aJ^d0A-K-tid=6?>$`e`2f zh5~#%P;cm7Bs6uX80aZ1mpzf|{{g!_;@>ffUkd64UT9y}!J1DB_RrLQs}~l$xH1rv z-z3vC8(){1(*yg5X#@f9nawt>Ay#GP-G=Jw9bTuVshO<}lb0>>tsZ&KNKISe9kG+- z3&{4fkv?hp1X`BTryOVlQWd@gX?IJ^eB6pt4LS6E-y|~sHf#GabzzY*zD_LuE=i9> z?WWMC8pLD4%`K+Ok?q_w(`gQ0edOD|VZJ!aAEgQ`C)`1v+6vL7bs@5|WeHCHfI=)w ztYiQ{OITKgDLFu9bg4IYN)JUy_cMO`AH=tUo15y~Yr{Q1T&*=IMVK}pCiiFY<#!+h z5YKqH1bWehW_4wSB0%@opNQ zagxl9;Z8txCM|z3hisTf2gDg4Hyy0=C$4(0&6$+jc$CQ|RdX=rrUisWsj4T~AGf8w z(9hbZXkPY0h?#R~^Qo~i_;!ul0*8U7NZYj(t2FaXG8lji+M;>-0NQ66v~IKmE6%jExHs?X)7LX< zxSr>zjy``3hYlq}-@0J)4iBNg;-n~g5NIhZpoeJ2*JRAy1%;IGnrjqx7V4xcEOyFopeRL)`Pli0#FQPRZ#*z0lXasnwL^WJW! z3VldG3F5srj8H zuj%iwEC}^YJ^H&rR!eS!QSx*Co{L*)wR@iNIMuPZM03d`3>`K-bDW=tATAxC?{iam z4MkH;E0a(L{c&`iiQ%;gCWjVeteZlZ|F=aGb#nW++kF)-*IVPA3OU4k+}BzHvDtgn zq4rDK;8ROkRJ`daC=K48T!%GGLjzsH#v#FgWsqZ-386vJ)S+i58y3?!l6)rwC<#7l z3wCF%)uUz0Q_2jBIUGv<2BexW0)Ah?1oRbU8U$-_svxgs#_^A*ERPcAf$clPYF?Z_ zP_xAo!yw7d<#+uolU*;FJ@UR5tlZWh&igtCN_w|_SdAvvM8?wU?k=-L3%ynwIPb43 zGPK7CSI&mL=L8Y#pV+s3pHvh`(A!F3)0F%JRqJzaO(aZ{9sh1N)|nDSxt|?n1+QZwWa^SMES*zOavr{(|+d+ zGN%~kOy`=>>d2kdDR?jGI>=!r9lqV`%E|yNy(g5j!2>8u6j2QCN$rR%cE$pVd1rP3-2|8n<};fnH3vO#QcNskAy=x?+&KAkrC*eA-a zW_2uk5@{$TbG4!Wr|~4@e2Xzeq?C?wceh#N(SVZ{5OAb9&@I&Df=B1~UyY%0b_J3K zF50mS7}cH_WxeX5CCXOdnS!Ki4si%DI>a4dpcAkIw8MboHV!yEO4n$+m@XwOfr(x( zhWIKFR6$pX){nwWzSrh$=fwLe5YI98ilA%CH)~bt6v&>525BG(ahew>>A?q zTv}$20=0}&aCH&hifQ%bMY)%lbSS7V(*aXK{2{z`ETmcVKJ7>>Pc-)ry)2`wot@nT zh4LlN4DUQ-{{4^o&=cxjdj2l&Gvfx;HS7pOn0YoZF)2Ymh<4%z35tpbxL|=qB(^sq z=AC!u0b55-bxmJlU%bT{*2uuWVe9{z592{Gz5#TJ0{IeSdISGy=hge5)dA-!7}e7l zNTRu>?PDw^Wt0hH0MiF8`L<0g#ma!4erk(>~nc2)*X%u4L+irR8!A zqaC7ZL2GgGq*&EZ;>99P&f!WOZE^Ov`)oYlGrSW$i8n;B#e1YN>uVW&VcAykf0Nt@ z97wg_&21nF5wxLkUS&tTNC;%rO)6+oCqVDN6A8aELWxI?v@e_J^BMj}F_xYHdg_kZ ziDKy98T?@%r`Ba`vPxq@pWPutjU}$yfw$)r@*blVTlxxst2J2PjTYmr#}$jcY$`!I zP0F+XeiO(u=Vd_ohZ0{bBd||<)5bcWEoiX*s1|JG@&y$_pmhFj9j}9C-X`>VimMi> z8^~^QJM8Muf+f(NgxeKv?Q(gIa-&;I^rs2ZM_(6~Ig()kuHvW&u=Q_atD?U!OVf!H2Cx-mDo%WjDi2v-%@O%Y=bFTdYva z*c*;YMTTYam_Te-XkCtro&X*sS4R&Sng#3Ymnh?zUfrZA#NSL+s+zW>Woq&)11(g~w>yLwZ3dzC-JkqmelzEV94 zSdz``YzuPS@*IHpSPzXa7qoIcjinL(Qyg8Wl=mD?SWvAfO`Os=Ju7DLoAgJLSbw`< zH+ay|uqRT^D?_phjccGQt_$TQQ3|G(dH!4_n1waLg4fLZf<3`ar5cLCcJ0xtv*>H+ zhSJSndubsJ5WJsy84I<_oGE~x$_yzV6#~ zhjUvL*Gpw^IYfAV^$}XWIK;wMl?OHtFUg*iqyAQV9)=P4mU&6W##wobgEf)*jNelI zrXjpm+^zz2e;TjtAPvh6|x7?t=x^F-)5q7AX2$XW40GcJemULg~BOSN%le;E?5 zfwEo29$j}=bh)zMHKyUA?`z3X7;RLu`0HZC56C2-_`=kH>u7^yfb#VDVZV5@Mt*jF zV|k=g&q?l%5$%LiwQ>gUNJ`PYNttN4G)(V-FmvXfIb>EWvsPCaiS1;(VHlrf!_-2| z)AX#qvC;p*j9q?b^rS8V_dIf%p-y*;o`S8_#^j3_wus`QYj_S3rwaf%Z%s}Ho_Pvl zMGG!umHJVb3BfA_xI`LXWDDYiHR7o(E{cO5argRwX#7|s3aRjA7R4spCp*Bz89Qir zC?yB{y7&eEO3O*)6(pf{=nr!04@UISPUeI#_x`6(mt<^>02n)syUBEIS zwhsnn2%i+{~VSm1k|$%8xeHshoWx&A*# zz7^}8jkqfsVxTYSJNie>dzrJwCj{KiD1*IsiquhZqnXtRIu?0S!<~lTXDWGX28>jr zcv|qK%Kr+JKouVs4W$!*`@T33bBN+yW%o~ZN=$>O_xJa%i8b4pn2|IGXPd_E-muZu zXLyBIbkAxuZOWeW)!l_-G<=9IeWxsaokT^;<5j>Mg`owFEj8rz>QV~u?Qnzl0ZHMj zc9i89cd$s@RnzFsgX$SKv0fKW(Sa&mRF`FWVtk7CNb%g97Zgjj(mBr)3^c1ff&C_O zHuH=1mI|Q{LbQqzGpxImP1cMZO+wTU{|Y_A9qem`D<^mftv3ZYF?p4EeV-bd(;IQ< zjI82su8i{L)0BKxm4l&Da(u|)CeYQ@bXk-7ruO64Qz2&C7@u;PxZH)+HE0)Z%(!Ta z{MPv6nM#vRs*S5Rh~Y@@k$5iTSwJXrd~vE7u@KRF2xH>P11xg+Iv~M|`fA_iI(Y(V zzfkqoBq-$4i3Nv;4u?~oHkp!ccl$9%ZSL6yBdWM?nJ$&mU}VDS)5I8@sQjPgz{5)x zAOs@51?4QUiflKV8tn&`O^+M=+WG8K5k(uI-cS*kmM|?T1Q=!+GfGWDEx0;~&TjaF zay#dbj~tp?;m*y6c}G{bk*||(7B~G3M~$aUy4#=jDG?3CL=d6t@%gBe(HLZORE4B(^Yi{IKryEWXzQq-w|9i8}|w zWiqMNy?+ry92HLi9it)e-QUnrdsFV$4g!H}PN#azS|@)SsXwxE^PN(&sxqmyTN5mq z5hZKou@P`=K(kdhT7V@)%xjJEd<%LfVzTcvF`o~Im*wXv)%bFYCdq!yDq|dnX+^BG zFqB|R;d*&r+oi1run|S?D>mGFo5A>8ntmd66PK^-Gv8gx@Z&Nbr*Ney>vQ!O|F+=R z>0%yL1B$=LmII4|kbvOr8j%L%dxt^h;MNF6FYNjNOoOp5iJ-6JD%3a3xFe7%Ky=)d z#m<`SOd*@NM;lQ1W*8=gnl>R~u7+|7xID?&0bn!P--4|zT_ZGAqC0zNd+963d1W6k z-iyHbseWmsK5>xgB>2?y9$R-!E(20S_Vms?a9tB1cW8h=$FczjL9m9ldsn4GWF4V( z4^ol--A?6Z;{!at7c#N0lfgBW#(=&$as_N?U z1rLxAD7fn0ei)K%$S6BLwTs9(48Z4eq_RXt)lz8oOmKu)3k_X3JZ87FZBDC~ zrS^6gY2o^soMe@8QzV4*?c{R9I}OMT@(lp+k`O>bZGV5s9k0K#UAEJSFY#j$dT?g6 zAZGvdRDf}DnA5_lv)hWlGOtdjae)@YF6~2e)H=6@YzM*P;Zs6ZD2yzc0NaXFSLvn@ zu34_BECRsmV#Kob&V80g4>RkWl4a|dM0&*tk^9ZwAU~J~FhFubQ0D1A7u~XELjX*u zWfF%GEJe)p4Ji(@DBE}y#IrM;UA@H9QoUb5=e3~$8FYZdQ(F$fh+9^$@TTM3HRxa< zON>hJfM@NSRMyJ>yRyjGJC!byX@$~#G-nizQ!DhPnhfWv8j zTrikog#2N;-&ej4eJxge3ejQxG)dAkk7IFOjU7sUizF?8X_W{dDF3`2EL{p^e5AJ} zS?I9|)$(aLPJ+n@4zJTPe0MGlG7Yh)y_3#wE#snU8ghp4wiTY{1-teNu(hQiW_apD zzrn{h1Uj0Gv?c3m_COGmDZ1;rp@OD?s|VARfxy(qD-8Z6f*ucbLeoN?RR)z=a>C>q zIBpCbug}El`|Qt4Wv_InfER9L9T^UjIPP46)HZ%az3H0j89&atjD#epdD+CE0a!Mk^a5^!^}h{YrAA_RMeBZ9VAFFge^!Zv`)+V z@7V%;zDv+O*iifpg&2vgeJ2)mJPGSxN|6@{9sx81QUEImbYv%k_&f}C$=+MRpprf@ z2VjdM`guT7>ocN)mN>$Dyq`q6nLcaW3hBnZJJ4EYq>m&EFx6;Q1-k4igr1e7;DQjT zV7G@aJa(Jxe$&|E6cpFU3NSkAst=bBX~U;*wxowa^ykvem8}TS)G56NKw^o9EUP%t zeuBk_$hxT>YbSvFcaWP_2)l|}j@n5Zg_aotoz)YEB@JqLUy<^{UtSZ#PIuqV+%B@; z7vQ~a+|AaaK_8D$nqK1D^II+-MHL0>SJfhx!V^2qrsr>P_zH$%t*NnZJCy-3oBPyb{gm1plv zd4+_BcUJV)6=ZxN(oR5R{9#PbaWZ{4a4Cgx zWDMK}`bk@{3!yZY(!olVFKQC)a2U*FXvzQ5<8yzw1IXvJb{p8?Zjd}hRnv|bDpF39 zKtdH?cM8Gq9dF=9g(mL4z!B`9^B=jR_(wC12Or#V#kkHz}u2tX&X-qr2KfkMh6*Cs4B) zOKwUyrdj2ebXTMLI-0#}=}9N2!HM4|S&QAvs?Z$cN21$kJtM0Sh2=DC)OCUr+{h`h zPsRL?r9awVFN~ z*>7X$Jku95iIhQbMut^Y1^liglKj)yD-d!Cr@^nEy``}2Q9rrrdyA4XGk|G4XiVbn zFlB#dy5J5LRmM+d{BMqo^(`rAw|zi9O1h{(3kdN5KGgdHOzE+c6NmzyX3 z`D3;*8nkrI^_UEU6^y&XgI;1|JL}0ess}1mEM10c+YUF5Ho8J-mUO#k>Y>3XhNChg z3Ou0+=l6xxF(?|T87x;!BQ8%&&t0YI4)Lt@HQ^I%ewkaJQ35b+3!uwJ>4)9^;HsQu*?=sNN97%wcTVd4Bm<@E=But-vyYhGF+)ZjNEZr0M>hGI|3BQG;JSq!}o^xINB}$C#c@j?tdeOM@)?MLG zb1_elfUl9}rcUN{ID|c2E~%8REfN|E^)wwo0#)MM#z@T#q&L1EzpliTS$kDqQrJQj zEBud6h&$pyY+|LK;5GO2@W=(tBY>UfCv`DCZ>u^YsU$zp0m4D>g$^X}got&GhuQTM z=Hh;6e7FNQ*V8AFmq*amy?uZ_C|q`cwx`u}`f4)0kC zK%U6Q=#$5r261PrpKnM{1UVIRs0@y#p3T!ZtoNJ|$ztqLj<)|IfCoHN`1_iKmA-WhY_ADM zGF-Wmkr}gS+yq(d9{}H|lIzv%1A==yGkbd$@ONBDgp^}yAYy6Yn@xvmkJEHAn$C$r z)mcqe7X!+b8a;5}61Jj1D##myv;ZK0mw3A?4d7)hhT-Qx!=x@RM?~B-9E8Yl3$xGc zPC`pz%*;%$WH*x*1dL_n#_ax$v|%lI>4;v#?-qTGFMhAs48v3GMXg*nU)PW? zAT77Cxjwq9+r-|$9WAf+NZ+EmhbnsRy_50 z{xK);;1nao`W3;hrpG+UuY_wn0n*`a;~xWs(9{|rx#y2OqCGMFA`!j5ogd#54dUfg zpa(Wn3k|L2SI;OHc^K+twvgRQsOKzSs$_8E!^0yik~nuEb@8*CAhsJb(h{cfP6&7@ zZho#qNJ#I9R$XO0Vw9}{Oq6m0QQAanKZgcFOt_O~_^;M01>2ACMhaTnmNQu& zy+6b#P+~1p$K!1u?!zlhdYSb4{kSCx?bzOFDo2e|Oeat6k%dh@lrQL^(+x7siB&Xi%z~VWd^JwxHdqcUIQ!zz-vt!#pC4`G3KLk58>vh=q)P$} zIPd4MAw9i3aIGH=b(3UP_B7EUSu^O6qx9hOgtqByyo=4bOH06dF2QXKIfEe?25=UO z()86H-t6`U#65J|X#z!SXdm5i5aXaajJD8(ePH&@uus*enB0=adcQ%XUw~l{G_s!)wAGW_4ID;n! zN+=hekBGMihHomJ250!a7%son{O=a~9SIihRU9%CAa)XbEf(ob&K!O<=Z;U8!o@qk z`~ac}Ye)Pcgc{H!o71m}>j>>z+`4|zA!U9PJn)IVB2E*8EmiM6!Y7kvU-iTUFb*^1 zL9%9VY$$wyr@f(GiF~|#q8p@=L+^azZIe>K^cCu#mHCh!4^KJ0XwaJv=7}<*JM~%4p_HAz&w$IKm>$pA zq0?m-LhG^sCYS`8=$|qx*CSe5Q+wqLd$i^n!pJ3P4elh8Tn3s=K z_C1An2w7fuzGJ8HjHa* zK@EDvPJIHe;ZUbsED!F{`VF-RUpx%bTASD_^~$9sA#0*M$*b%9dEEYt2*fztK_%!Y z_`MHxo{*K{_B73q59&PY*1j@8t1Pz1!pG=8UwL~yV{ol8=`t-q7;1dm)r>}kV)?t( zRd8pE2wt%R4|d``?_{Ub{1p9BQz*gW2fq1^^jyf%Gjf0-rMB~s@aMIX;pLi>%FjrH zg=#VEY3f`7^K+WpJg=2JdInLMA85u7*+GhH(PlT{6MhNh#}OXDxCIZ`F=Z@xKmen- zsNZ+poQd5_c+cahI+>>(9FHIHaVo{_ZPPaDWJixJ+*Z1krS)hB-|JSoo8e^gkhxfS zr4EF35*NiKB5gtL)hd1y1<8gb$oQg{uxcE{d#=l7aC?2)5v1HczDZbZJ*It&VUJa;^b>{MZ6&)rw{^;meM^<@cbsB_|3-q~K3eDq%f+!c!$!o(Jf?sqW7uNpR z8^5`^#V}yX$gzY2(D&S!HUke`WHpBG{w$L>avFieGgPj|m6}3?K%>wa7>AXt zZsZCIYowF>>!ruu8KhDi9GX{GT}I+wAV9zpCR}6{&m~r7N%(5I`<-^cv65Ya0pSsj zE8(21NXM=FILmyZB$8f}W~7QN7bS1;;fhm$J8URiRDDbSk|88&USn>>BY!ccD{Yw{gA0<*qVm{aO7n%{$5U8A8|Hc;=@t$y*Mr>LNIBc$ngfiZJ za;9#rqNv=;AF35g-POh-iTFRfL<4oci-SS1U;RgU2|=dw4-M=0Qs>tw11;C_x<25< zh=jwofEF!spL#z$C&O7uE;T6$7yTG-{O~>%blphXvX{3er`aX-;q4%6E;us9kY90_ zbmh5wET7LlB@5=aMdBox;A1^(N%SB2A8d5wvzjO=l53{=(&7f3Ux`7fTBruh&Yh4F zv=omT>57xQthTBwyqbx^51T~5ihR|=?^I!Q^a8&3WdZuY!s)n$s zRgwM(i=(B(Folg|3-^atjTb93tEc9uk>Ml`A2R}O)lmbUHpa!-Wo#YpTVaj=te-)X zcB-{d@)q9_4U?mL#QUX?+m?w1?C=1_Cagfr>DhW^LT%Bw?xjCx8#9r_ zh!oUlikfQ>c)jf->Nff95j#MWBy16^lH)+G1HIF<2q69LjMn5{RoWNp#NkUiBpOKr zI1s=2)|%4NMxB4z4%DrcDGq5kgo+gPof9Jhr~LhxJlN!qYXcP|_IW^zzB-P3EEdfm zfNyHE#S5pe!gxj6vx)~~8{7^-lVT6Dn#VPIC*M7X9U}{lb(IvQCm0-M6e}v7eIu`H zeHKJqB@b5-8SDsMb}NtkW0)uKC`^rtO3w(mnwwe_GCh~PpYz}d=B}`lJG>Ty5kJg7 zB$Z#N8xP!Z{>R1eZ3f*I%PSMMV8~3t0B5$Eic-dsD8d`~p$l54R4+$AI)m0LaRo&& zkxlldJNO=!%E(vso3ZcxXhMh_dcV4xTX_&`Cg zIjBw+v%thoy@47|`D&Uk$GBL^@%Aj zO3=ysQipg1uEA-q^Mv0@+2cR?adIk!PU~Utc>=rgpFLz!jBxwThQp<^JvW=#Uop1ITy+_# zqt2yps~%J*S>;3kA%0{Ma?vG9q2ZUCAgrZroG^K5Hj8(3ZKk*QV*$pR*>@yyS2;Z? z0QeHoM0PrP*@Fx@LIP_K@Lm6*>0j1i_#WpMJz4@=X%N3#uFZibbH~uxCpCGo=m`5s zAqdAtw9(TlF;HHlJKwHijtW3fYGKnXw#Ez(AWv1&;ERV>!C+%2ddkXwFkok^aW3p( z3?9xLLZ?M;SuQGa(}k8mTU@%-j!i7i*G{&Mh3RL#9dQaU-1wbqo48WR_{1)-=lyN? zbp`nDogHnuzOkD0X+}D%Dp^4H^aqM#0aH#fsU>X3; zH|g4*5D%6;a-cA7%76~|K5Z!l%eaSXPr{mBbV%gf1gsLoE1yVir+AY)R=RJ%gN!^V z_%s#AKuJo{wS$W>sdx(6gCPMGu*aVzpOzO#RPM}#FpVBvozQw$`RAm1M*QH|4|sj8o=9 z7FeA%dlnEHU;_O+igC$iEF!x;_6bywY!bH*RgI|DkMKe$68HMH0E0QiIMIZrJ*KRS z|JR%SuonJWLcI+x<-iiJx-pKYoLu?LIT@C$nrfNjLYF7BRAgm|dQ*Y-g^(jR4##p{ ztRh1>2VK854@)K3eSH;?ZA#HN>s2zmZ_*5PWCw? z7j)HOq7BgaEi1-Qr#=z`s$@S!?v*UNm?@=XbIDk2v@fa<^S~`y2FPmU%o4jv0LytXlB4@-7C=yO`8;TqLRvR9?LxcuFJ zlIt(GkH^2UQJ=k9juSb10g4Z!;0y3!U%>K3!kAhTlg!Iq-|_;`5-%7u7 z+XwR{?pd^6IhKnEA7WL#>6Dd}nd@;v2bHyK&Z|eVOx*sHlYY%LrzBX5E`9Zj?Bc@? z%kG_FOZud|`po~e-qth5IYmx<2a$v82k+p*vIBbHpck~1-=r0NY^xP_{T3Y1;*yS6 zoPBZ~dF~7o)r=2qZIWoMD4l{*vV8gC zed?qBJ&k7Bd&+aAT`>Y{%`L=t+?bX|TXCfr&UIGdEPrVUuc8?FsCa=}So)VD;3E@5 zE8*Af6sgz`DnBsiaMPJEWq#X6$oU5~JDJlPDkZjMUQW3O_?(?gfA}5mkpxo?ueXVu zJ_eDKz~nI)bVu#YXKYt}94O>2IGQ}UUi`fP$Z=b7 zAB&z(@-!>&OKweV19)o5;*2A@NgZIK&xQ_KxZ0~h6WRUpH}fW6V`UKD%ZU_aLMLH> z8e=N4$6mapTIhHK(2aguS{9aTuWD4kUO=6e0ve5uiNYzHdR>|dDL@edE;fmV%ghHC zsHB${NfF>WWZLC)K&m|&p#ADgZ+TVfasaqOFjCVNe|?1u^6rb z1ZD7NLU3TRx?oJ?-KxBg6+kMLXkNz#Ya>@(WCZ7C^wo2eWMgU zvz$kG5|Y)4@DNU-)J_%*$8hrwQq=`?5m;2NZPIut934mdd_C6yLA5y}@kaotS$Jhi z3vAmX;LUT`q0ARbQ_UneRp9_bo7o5=+*;ue z;6IX2B==dXe%#i?=hQ^8Ei6<>vm!|Tr#c+EdO7Y-V8$Q@L(ICH@Ypi%_;VY9!^3}3UYNtUthnq`;nze%IC z{%C*fG|r}0Opa{59+eTc34j`zLTXV(S5Mizlk%iuZ+Fj`0YycxtE*`tPNVWH=F>_J z&XUh_)>;WLmZRyfJ9!cY1NE-hN-yfDx0|E%iCmCX-w3|Zh5 zI~b~2Pq!KSqE~ShhW3oNa8L~*eV7T-Q|scHC6wsMq{!;gICgO)4ca``pOq8a#CFt= zXU>`{_BbMS*mmMoHliM#@(L`Y51T1_c;;qeB3U<@6LO;iDYRmK(d=*RR5q-H4nJKk zveZ5iYUtj0z7nfe(ug|SQO=dNB}FB{itHRM>b+$k3k(6xz_7h+T#zKu#K%8c`(pdK zKBo<5wfTD+b=4SCULa;QA6}xlSauBmB$lWSp-6B`izv_Zt5>_H$wEr{u)n5M@00=} zcpk^itdcO%(re7L4(Wdq{%~P@_E`90jS%xsOD;1(QQ2bwH+B>@+mmLR%<8si04h^d z_RQWS{F#vB9l$+KCR+>qRsQs***4muln=2|Z1KFcL-7eTkqn-FL$n+7c^~;M+>8 z#J**gZn_houPN7-V+^zaPLe_in5TCf$umOV^xwKYo zWifun7LO4KFMiPKy8@vM8IcXCgBaQwzX=d16#8YRsZptzQnfIz(Iv>D`@k`h zY;f%f-LRzSkq z2F6bp@ie_-f||N~H(0NsQ_PF2j`^f7l>)<}9l+w+BAin)vSx_4hH6-R-&(}O3qj__ zaiCGMVu)hVb2`V?VV*8$VW?(iIM`URr;HrB)D@BDsTR4?jWS5d4Gjs2fZW|)gKB=# zugr}FCd5693<(L5xl2%RLFnN4lA#f?AW^JkNE}Zh`HUovED3lBv}gL9B#~WHlM8Ll z)mYR-_2vgVG^Xtlv4+J3g^Sf7E)5P#di4H&MvkW}6&TB$yejxM-PRD-N!AEOo`BT( z)uNpc>;`AlvpD+}>W9XeA4V_a=Twp*G<^RW+Wq5%2)>jLy*V7W(ETjhvy)C_F5sF$ zl`c3qxp2b*_TF>mZE+5m9C95K-DaMDBGT~1Ae+L4DyH-IcgvBg)upGV*4Bk<=+Zdq zpBf)i75^P_Ur!LQZhr?@SmX=UoU3+wxo;~`#wkP_XmQAPg zAhlsG1lH^saR7D$pEozF%-Wc9aty*pE9d-qViW~#ASa64BX3kQBeqjtgKCSG=~L?5aul<^T5(C}vRg|UUeI~uDjj{a9>{vPHg55-bGFU5STL_^iih9xU_wKIcRs)58cEdTTh`^6cZ9- z#BDW?tLgGad3kW`av5y4plXUKq*7s!FD>~mjwmsd#)HD!zQ8b6s_1f`@bN*@js$0= zL_rr(W;)9Ys67psF4=S~xKumB{iwMZsXkBL$4dWY;+HEIT9+0(nsONa72e)n8#M=b z{2mcL%ULmOl^JVwaR>NZKNzj~CP&Ym6^lVupPwv|_=MPe6U(xQ8MXAoJP49_X{`CS z$=Z(GBJ_P}48jZH31h0Gm=>g98o$RiFiZ$;!)Z*9J`G}O5~c-7lF?qsG%f#4a<1%@ zCxY2k$W{nP#BcTs5n5gJ{YZtupxj-RmUGNtPU!b*JKz!dAz59^q1RL}*xe&vn4A+9BszD zd!5b-D}p`6)Nq`eqsy6M7DY;+=Z8>ugFv(UyDLw2Z4CD~FK|s;eHrckUz^i>$_nE4 zYqH+E*&@SjzPU<$u-lFb)Aza`0wCtmh>$>kOkJ`siby+W^pQp^nEn%-C_14QKbQOi ztaPjCV(WW{C<20ti1bhe3q!E4zwJ&-MLNe5clVngNqND);=qU*BPI!#_1%P#a2_Ta zbEIYm$wr%FFN)MwGjEQy-AX|2s?5$44t)c~CTsnU^cN*; z=OU#p-@uoNC9DPc@Z7f10%us>4Gr4reFYgMGrbjWBw;sSfDUAsTMQ9)b9+V&&8|ldNRPrhSg)Cc9-az5x)7ZYEwMm_`ChuGoF8O0HNEc9 zrQV&x%`~vS`e}@#e#NcPA=&NF8G`LObM~bw?C31KSU=O}^VRP6^RzDFuw)Kh++s>kIZ)|7f@4Dmu8{ zQ1HG|n6Vfi+)r1C{rT-isEdRD{n_H5498Hjs zdkeK^#`S2xuPnKnZ`c&B+lGI7%2Wu zLxbsU8NIKpyz@aV?zhgLd>lhY3OU7JzwWH}bSRGeJ^{GHh;(&WNkZz(hrWR`86Io+oW`^{`sFo9+)z#SO75LeqAi$NE$kgi>YPKd+k9 z=`geDZ#>_G`a*~b8Q^=<=%;6IYtV99BY&@X9Yj8DzJpPMN zI&uht^~VcHtcHEGgRCxf1iRl|Zdh1bKVIA%%@V%9IUyJE;{Ukb+>mZ{Qyk6ab>S|) zq=ZGax4wHhWgN)-XK)T(Otr@4_4R@)XZ>s~3OYIzB~9m_wzW3`(Qod0MEcGqnHPtf zM4GGjz&&iB2zcqNx5SvzV;vW-m~r&oW|`^~8f^gX^QvC_>5j9DK${a3?y8)zoQ}^R z;IK?vRWr`+szd;G-!19MvkyX53mRZsuE36yK(WV^Q}{axR#f~9h5gx@==lcM zXv@_3*E&uYPWXFUnQK-41L+?J?{Bt)4CJH_r!g^%;%Qj6Dr##~T8z-!9^A_!M!=y4 z{#qKMIOVG#gT<$hkf)c?x`uOfxG;#??3*nAE@?Z*62zFBbS)=I*Ko2}M__WRcEo>Y zv>w3*7suIy6iu}wZo#Qim0)7JEi|?Nx9!+y__5-bzBig#>QfgJlHqPTI8g! z-DiXvH0+?(H-p$dkb94F3(EVe$<3(q5s&Khd1YbFA7z3!^y{C9&O44e$4F$fpAfsf z&v`^l`TYl4#dK%7FolzWXyX@CSBD6$5X)dZxj$=Ice84Zl<~VjT~$X%QC=RsCz@*b zQ|{J5^Uy@3Z=bdEeN4-3MT7fVP08WW{V7^=3xh<59`fPM8mx57_U?;1Rud>Gnc@z9 z`a2iJyq7oO_rY@`#oUR%=HE*|Z3|gNXKQ?8Y5A(Es)|{=mfaF`JqOeGai(+CZb@!A zyhqo&pQAdC9KNHx5U|av-F|tu<9lh;7Z%RMIi%g%*hFynVB)jt9>MVe0dGuX}OiY+ZKXlI&?oO&d(TxwUkDWQTuyN z&J9e~i28TD8_B&VQFT}c3g0%u>psvBSmw zyZ~J+0#)OYM~2%#$7$dDuxq26*%+famkypAXvJRQ+`HZkQBP-mlxpkPUhFXL(lpKH5RGB_(nn zDLMj)Y0N7fN~$TwzlfZK{vYvcgXw#TRfh`e+3LUOY&^#ZpfDuPd1pe=<;lYfE2e$4 zaR+nox`X4ZK0fkJA+>FQ+^7-?%EX?U^az zx$m5$9qcZ7sbgE}%rfOCKW=TO<2yMqYiT|3ISwt{L)Jk_{oKyokT3*LI6#XC25jMC zZ&sR{G^e=OW;X#-Lw^?ejjj4CIs!-cy)Ik!BF4Uqyo0XuR>%BI+vYXOl5c-k)%Y0z zyi!>zx*l6}nWK!Z^Ujk$*E)o#kdf*$o6-&<91agA$LyO^qtI1E&dk`}s|lpWW>O~3 zm3}3uGhe*ad{(vk-t0yuM|O~+{>6jD`mYClmIy2Z;(q;3aT1Vk-^^-5DBJFJVK0FD~zWfYT$rjDd9a~B|LjQ%kvIvEsLvrnKi?$`QZ>-umVLyn(!i$t2W+iZ0% zXBV4Xm|@{^n|z82VVk>Qx)R*HjbwQFDJGa_)ty^^hyiP&1{LMZyP!(uk+SL+CxQTn zu)3K=p!@`jJj&06q#tdOdl!Qeg8(1|Uf&*WGr^a3j#hrF9ytOg>9E$P#d+C|&NebL zBWG>Rf=F4FY)w^2j1nj?B;GHRY^u;ayIAJNz)FYM3}W0QFR-^S5}NkJ9NZYc{HgV z21m%3SH!T(S#}gE|0Hr``^Xs=?M}=7v4s(%DJ{TNCKt-V0@NMJ9K*f zt#3=HMZ3T6xwV>idk2HaJ@M@={VhjavyXpqhAzS{Q>BgS6f#E2k|tMjON%G&Q?XYa zl$}XDSwgK#om+ni1**0hChNh~Z#y_nbRs_`04f22aBk3`u^I=pW5r32n%an)KXiAn zoVAIMw>z7&Hjv_M_DJJ-hK8wZv6U{TS{Yxn-0l3)G_}~|q3qn7KoBo2o=M6Y29|L&S@PMoHWYVeYAPJ7ri{*yH^^)UHl^tfA+)@Yu<2-e5+QP z>*P-D)i9+zI-V*x>vV)XkIeVQHaQ9ik{#l_?$z!QNnsB@&+R(kv>SWV@vRnrk5@QF zCLVQH$CkqW!&to!8(?6nzXL=`vl|=Jg!XG`HZ~MoTrS3lke~qsHOyITDCp}Sp)Sp@ zKCT;4-RdB`G}9YQFK(fzQVfPE%no#afhi1+G1sQ1LUrpccu_?wI4h#M<`txHeWlEj zO|Q`G@{$H;?%t&N{|XCPomYkhY^@=cY$yhIReW!BTb#pmTujkCT0L?yyV17A&~?KX zanwqb@@FNTygI^fyC&ui++W9>{eim@a^r^TY3m*D#yTydZ|mn*CSuRy7n2Mx`)rv! zvdGLz zgj$`JM*UMXM1V0r!587I1CCi5zO3K=ezQTz8C~;>```G!y(Jm&x4+mvpHSf9lF0Tm z@!LJcSkC%Jl^h3>p-&*{iR&W>H9168YAXqv)?=9>mKm5Sb=VwTwfT*hMndDPghGgd zJRM6~6~5@b`}+&iPesg;k$6%940jntv#MfPY6^wnNmRL-elPcA?JA>LqqY3D_DiOS z#Gx6|gzm>)Hvc44*Y5tWMD^YoW zH|(1%2$=1Sv&4@}9r);uU8OhNL3(z@MEsz82cu^xTG?p6o+m9)7*lkRXW2VKos3lD zG0r82kPU@kpp)NYW%KVoZ&f*QE2H*uD~bavmm)Dfd0rw|QE?ACTN}-sRZ=+HG>vlh zNeO%80_3WK4!+3Xnc?odQ%~t+@sJTYHMM$u7RBMM|2r-!5eLiYr~R8n zalusmnVL)K3y!BGohIB4SzTXgjAKW&M*{aEG4n_JViK7&gkKDd8Uk6{@kdbj(Jhe$F017O{#_t78v3$E%1ebRJ z7dFU~W%H>{%#wcaTdodFZ=9+{Tr>vcoH$0S zj)Oql@Io_M)Tn22_1WCvL=n`>P2IF_aiXPvYIVM*?u$y?bk8R?-_C;~e=MzpJ0k!iDg&=G(0BCje zi*}YwU(xa{mQi|etK6wzX<}leCdrH>lwC%_#Hh>2LvDW;k-bN=hL045#*BU0D*IAt zhM`rogGPJhXn_hO&!9{UDEA-)OI*VE*K~`o=n3I(<20@ML%j0RM`M(MROA8bN^h8Z zT5u#$3N;YGKS`#tr2$9HYWuhbF&ePL;$IH%m01V*mkAO;^q^hGJ$M$2Y)=QqB|I|V z143F$n+dlX25L?zNcM4AblV>KN~qEM7+ledsh(w%c$tTH+_@hJQyMv{d<@Dcup_hT zBj8Vm93bg)fHiwdWT^lVarXz?;Tkp5#^#e(*WFx&M`jOfBioNJK;0_ApA4T&NZY{^ zh%pO(k?%J+muCU2cZ~SIQ&nox$cN-^?ZZZ0aN*o_)8WsJzrlvFg91DS0%Y!=EiEl9 zEDV5@HY*WU;ZA4C>l3&sE4pV3=bt`SjJmlou+jA9^W-fdcUYxe?#QUVy=mp$#r1MQ zQfCj@$t=d+rz!Kn3n|GX|7oPm>N7wp|EKOFXGLLqflHF}+NhUDNCa$Y?)#?Gj4C(d zPq^9J1?f+LtcDl^Azt^6RpzN!*HeU-gl{Bgs&+&?^rWU=D|?9qFVMiNTX~@oqQZik z?RNDVmRQ1zf{Rw!5bh(r)w3Ueqbvgj*DKYc;OH*fpnO^II_Xj5obE`VL9Mx57jC@G?OYozW4x(MedgWE8 zMn|{;)@v=h>-lfw>5eEt@#f}o@)#6khcl13Q5;)DBuZoa2K%ccBsgm{9Bgc5$R8pv zl}{7zY~@|*BG!=YKAUL(_yC}{wEOJfSs;<__o}J{Ad4qt)#kUVv+>)nj&KxeY2dM( z{>1 zZ*Jh5u=<~UG{!iNRoI`Y3QtTV1a?w-K7hf4H6=!2A49k+h0WWhQ_$Mln%mZw_qyv) zOq`c(N#gw3be%s=KUWwssXv_JNTn&nmLlUFl48_c3HFkPygw9@_+3cEB;mOTnBby( z)QBX%$+?+_J1@7+rtR(PrP0{-5Ny4v$XSE7d2$rM1P$K&L-1>VMFX$bdtU7Sac3Ef zM@Nu-H|ps_h?|4JK#T%yMUb^>Y!OF>F@4cd4<2_5{XsAHGsa*cK5N1$kXOKidGg8 z{XC6&Te9(j`k@D4v#r|m>cT>_qqqk@0=rY}QkTgH* z<~Uj4zIPJTV6)cI?Cid$N=ww#GA*~;bf|sa^Div`ku;0CLqY1YrP{+l>gJe0n%h=UoV05gY+MJXGSYC8?$VbiybR7 znZ58{x)|h5--A3k`n7V`)pVnqj{B>m#?vz)*E^wYpN+TfTLmN9h)``B_%2FNj8E+o zB^M0q!-Dk!%y zrt3R;2Rr9*Xh?7TneYBB7D9T@(6O#z!11K-SqB6|Hd`M=VGC_Ih>`!C1+N$VzPTM8 zp(;VWve7Hl$PX9AGRabJ(@a*ktf}uxy>}Lwx zBrlQfsu77nqmN~AWAe9Bb~YZ8c2#9PhBB_C>Ir_A^^biNmmqOQPD1G@@)aV_bH{xz zhMwpa(I4K5V3mAhhfJZL1qC#ukz-?HkJvwp*O{HjO<3JL9gXv;pRM28-_LC*iqukr z4Q33!3XX3%i3uk!t1SGnu>ON%vu6q6$uegeGG3DP0{fti{HMTyoqUx+fRj9XP8KJ- zwKz#~X64q@f3*Aa#oR7^lQUpq4P8{V9_4Rwn3%al-@w}M`G4rdli#DIc{++;tpnOSN6y+?D4x8m%aMvg(MZ1VSF%E-V=aFP#h0XR6wWYo402nOGY8H z;~g_jfxi$@oY*ql` zOl?@irWz0{%fx(8eSSQ?&%5xt;>kMO*Gu*dq`Juip%bi)yCU4HdIr|s{&x#5jyg>q zJkrsWIY45&)}K^ix75D-*wb$xU!dx8Xo)L{I3bes6^<3{nydeibj*v6aX)HDAn@tWv&vs9T_E`LXMtU~!#s$9kqdfX!q5^-706xtq{QyfvDj3*yXq?{#8mNc>yuUMkm=eY?Gmpk;^4-Ft9{UvI%{%eFLGg$OfW$> zC4c>P$B}K6g3^aX61JgMwu&@4cG0J@aIfciOik%>d~h=z;9~Y6 z4am@z{Lt5LQERUj(DsyR!Ezf~j45i8yW-cz!JKr&xdKB46{sXTj`ZNGf%hU+chKEA zO5;JKiwKSC$gng#$X7fk1FJEcVrtd-|D7`&OxW2A&KPpj;dDh&_dPeVJ5w0SuwL;p zV@Mz%_%N6PIo*O<+_uR(-R$a5R11pM#MU{kmzpmC1I?g?BFGRSCFJ3sv z`Z(UNp5M2b(bxFmE>_&1Ol6<9EYCcpEKKdF^-wt_me%C z!!8`{m#94|og*qQj_m!#sUyAFP{!l$+pd;Dl`QW|!|0E~3n9B&*?x@<*{OLxJ}%`Q zy$y}lt#Pl0v7?UScj)hqARE#w*Wd5Yge9Dqm}_f(>+@m6;u{Bxv;g6J_glyuiNf{b zd#on=WDVx-kHh5MbJwg0I?6YwN;TD-u0vM2u=;>=FqPpE_#V+Dd}GY<6yw1AL^>XY zrt|I)1z5tY&pCk;8+s|LLU<6BwW<*TS#apflJqnm$)_W)4z%5)34kIIUaoj7KMEn= zV6NvwkXpB!pu?54zi;E==?OAT9J#+jyDEZmco==COj~aco33TS**V~SX$R|sY81S}1TuTppt;F#UuRE*y`eoSD zq(+z|Y)o#zqO0?lT8`38O}Mdy%4Mg-8wgWX!U~I)|AWo%b!r-QL*+<13aQF4N)&x;}gJ2D1ti_zxMH14(|N%#A%; z-<;wwGaGevn^c{q#C^Z?ruzYgcfaX7r|P7sa+2h(qhpSWBv3kv*-*9p+0EsEh6Rbs zg?h|a4smgH6@nJRot?ZquD-3BD6ac%y8IofGO^2u0qm|E0+Te+-%_sEkHh4{nbK9F zNVp!xyt$d}B_;Xt#Yavi)vf`HwShF182jSFLSnz_C{_dykL%6deFG0klJIr)uHmy& z`}!iTET8g>KZ#$z#PDn$NYe!!LFeQZlYE1klQPTRNxw#=9UwoFe>j=RYm%pIjKk&~ zX=)0Z{Y*pC>!Z`tvLELM<>+$`BiVmDt=~-Ncb42XL7f1faFfq#IsnFeqoRWQF}#HI zeF+bq?|}Gk9(9#ZB=-lj6SLC3diQUr1>|7VfySRqn8G&(`#knKL5}eWi6hY2p8Sau z?G`tiUslp)@lfk@nu(TJi$Nfq(DDP_ zgtF_)U(8wU4mgtMDEYV+Y7t<@&7Kc$^j*pV8HC+h3FELYkWj1l@@M%^M@n^>CbPJuFM#u8V3JRT1 z_@Jy;j>epu?WNZt7_P6EJ8Y(oFtq@B^J%0&QSwB~g5=TY$($E7lKE4uAE?3%us!!V zyIW`Nk2;F87d}e1mFPwg@&!TfuW@+`3=XFhVT2zsD^;ypmD>@VDghUBKJy|giTd%{ z`w5nmk$ImNdm+B1tYCr2x=9^H;2ed8hi@GmY_w0GyQCGU0sw+}0+3o6Ifk-lKV zQeI9EjmZ3oXJ`b@P}lx6@NuF`vm`++k;@a(IKIPW3;teH5WHE39zUE$c%W(=R$K3Z zB2P2`;hzL(ZDm_3lN`D_T-D5MqU)YbZEGy{S)Fap9GEF2>ITrPiaxMwgL~g1X zA{|p&6Qu~a{><;ZN}Lm{w7Nqm!Kwsc_~liIqz7v!xZ@MA^{I2Tj@hv4dzF+jsq&w+ zcY*T0$1yZBUedX>szpc0<#{#HMtL(_#p%M{Q3WL_0we~CO#iRATM1wb*&U_Ons~T4 zhAs?FQ;#ePawL=2K(BQZr_2t!!PbS@_yck-v}6aPkt2txE0XD%DEt@l-9+_ z`92zjiIpYSaH3aL)u_qaDUBbAK3ISxB|8~Q4h5On! z8a_Z8^(96)?MtQQU+P1pd!GgmAbPZs@h5jJ!Wn2pJZC)m2V7A5Of0xG`93a4viEFC zN*M1BkkA3{hr=u$LzebMGw)cMN~}lss{So{-&U1U-bF4+XS|Hu4>Hquc8}ul{d4qF zCn=^>T_pggOhjgA!ZXM4Oj(lUElfyW6J_RKJ@||?QM2#OQuHQIg=R-3eVMxpx7P9{ z@V;kOCijKCAJPdKo1Ya8#Z|&|*W?0`$5>fdK-|(5<3)aIAin8(B;#AT=}gtcmbII~ zAOe1S0L%+NML|J&IikPS{dvWQ)@hkIi)GXhIG!0xEg$dVbY)z~Y-HdQA=d!&si}y- z=d4EfJO=pCM?jf5%n}p|i)m79FcVNT<%%NDBn0HUW=c^1e3LNZN?fHXlhL0ai;Fb{ zcdPmYxPGQ_87X*&Jd$Ool?xe7RU-2K-0m}PDoGArGt9AbOswbe^>6`h@V zfUucd)CVZUynb^Lnil1X1tw`)`Ip)?&B(grn<1v+-L7l~pc4H-u^WL9lfL_er*tC5 zJPC)=(jj{k(5IndNtf4HXm&e1;;)h~e5iBQKxB4-OkDfuxH@&`e-jJXO*zaX%v+Oe zxcInQPLzNA{ZaU0jUa#W!sj~S=!r89swG*P)eMONrci5x^>eXGcQn3+GK~B<7A>d0 z%uMMYW+uYZ+~gr=Dg#9@<)y5@bm;1r=d81wWCipaKZ}YeobfX@>&&G%>$nb|SvH^6 z;qFvcRgE^@PVW*?SX$T#PUAT-j4>{dM-KB65tki3%SiBpk*kXO(3weDX4-8a$3?z`$f}y2hUBy61V08P$#{ zxN+9~o0|zel667JFj4Ga2#)xWYq=A&zBe4j{&K4oHtx5?9b(&H)UjjjM`2Wp)=#>9 zw5YiduR#Se=iBYF;gPYK2Z{;6pH-NA{nf<8Lm!sLNtJMM>-d9xZh0No2T7Y2`2}5@ zQ&W#;vShGc(i_Cvab7(m>Gp3C3iiD+5wazZc3AiF;Tr-8WhIjlB|5^Se;v=*zF=2? zax;|smx-7i=MOWlsqTml4(*9e2-^*Zn9Tkpri*!o3nKmxCG0lh!lldN5!h}KGV1!2 zO1b9tlFDuc$;i{CTt@fC<(1Qops4p?Jw>q=7~Cw8t*_|DDWJBX%xt*jd;-uyy&W#r z18USv)Nueo3z&xX7Qp2ryY(f^B4+}mjD%1ddQoLx~^N;RH;NPDku;Q%S(0av%1uQ9^#NiAE zMn~(~nIV^z8x7H{8qOr$ICeco1joZqfbb5-0(iiu3NtX;L79Qi?Xi#^D&MrhR6e5= z({6Vt_jIE>SG4FIywn*Cupa4p(@FNi7vG#S#R+g@9^oE|v|eeYvMb`>&&Lr+0<`Vn z)S!XF3BaXG-{ar{0#FNT?G~g05qlXiVmOYlUG0-7HTttanVS~>Rrgzs{&CK+;dA0o zviGU0$=}}OHKNJW3keFk9YYx0S7W5#qvcqn2p{*-2w$$oIXO8Q7uEcm8<~L}+Ly1T zl3!kS%#~l+oLlJ%tP<-uc&|KZc?O7MI_}yB3e7G|E;$q?l+_06UIP>|ddI%}^%7-s zOUSTDI~6iO*RXk+vlZAVdAXY(;c&inW4_#eeYunsQ*YlKJ+SB$HQ?6_TsoU|Vc z*mBiB3U~s$NtR;F(dXs{C7UjrKQc?~WY1FQ^#?$$11U&T+$S9b|?8znW|rQg6BXnBl%ovfpy=L+JxwDm?q|EcS-m zqampj1$@yrBY{g!WfP|>&%fHDTX7A-u{FA@;A~K&1@>H_+a9((8gbwg!hU>KV^*Ph zWJRwZP&u=3{;6ABjoB_siQ=ImT=|OCZ`>W8c=L9-9b`I zlX_m!`l~2lkZjtJn4fGp)ad5I^ZA`Y*LIhwr~lpyY(nKHCpK)n9g7q6-l;5)JC}Me zU=f4c)aF;g_rkdD{_5)1CZ4~5qFgT+Oe|?E2P%z`?O>k*%;*B^KEfq0}Q3JiJP-{8n{_P4PdauCZA@LzUP#fEtvSZFa81D|&R3I)jXt z>z(l_pnSb`aIv-OZB%*^%_DGS4qO!hZZ_!u0c%X5X%uNddsFWwj_Nt7wUXtB%T_&Z zu5WmoHJOm|!$4kZfcR)82wZox@&|ml2yTm)byHL)t~k|8i$NRz#wL_@1ao9Q(cWgmwZ@c1>!VJWqn>Vz zhxb8^9*O6-|D^BP^L~9nLM=rMrdgDsk4qY%L;(1AQ`bZTH*_CpCpfvw6;{%)bzJbJxEu;s*U-reX2l5e{FGE7i@z%U#u2K#Gd6F|6={7|LU;Sy1Jl6a*96qsx2KZmZ0Bk%t zGVh4pIkD{uKfpP^P@ds)6!Ws^_=-uEYJoLbLF4Th#8E}`ptx9d=yiTlj|cMr6c@2H z`TqzmvKFd=bjO%LD^6AD&qmqLIMCGKwSt^Cej99K(9|{O<{NAZa5W~JZi8U&%!E#h zs-FG&n9YVHucuBZ=L20nG)kdgDk@nfH~65J{SBC9_2QA|^ULd565^`Jc-;F5?YiS* zbDR$L+S~J4X+>JZde6+x9)^Z#61OlOOz?mVD=O9B!imec3Ir%q_%0S@tRcb51$Y;` z{CVuH=iAn%-dBUf2$dP{41~xjxmkDzCO(#a-a+y9WC>&dD#+uGu2Ed6 z%c2{K+{kG&qaSmdJD*LWPGy|Qx5p?B!BWKeen7R^q#TSLHqM`0Qr4o@Hw3fHN=Yh( z(jr*iCf`|w_psEaD$Z@?jfHE@ai{JVI-~I8slLN6=^g`0WWl(_c^Auk994HZ611wF z;e5MoE2WEQfo-O1?}(+QtJw;^FsT5w@E7j9&F-HNzW=azS0Uze(`r-*Ye)+EN7mqf zRVpjfkCQ!utV2AcK23TaeFK*647cu&4B%|88X_Nj28wMDo@)5~YN_*y*J_W@RDV(3 zZ;GB4o}{?O2!$xg>$+wM>aFJj;-EcZRccLkz%On=GrrcQAzGbT7N3IO0<@ypk)6@Z zK;&7C?#)1?6;vCwIWo$&IS%rL;Tct3n}xnG!tBWvKYmQi<1teqlIVE_{v@z+c<>&d zXdf7fh7L)g1 z&U_zj%(ijAnZ*xLuts6G7W7)`KMXvJqfpe{g|&d)!#{HlvFK~?X_ql;xmCFEO z#cJ5Mdt*-T(AAAO_JWrOFG70xuY1!mZhBr{(fIv|JGT4pxhGEvQh=L2tTgN2?;i@D zG5wltuSp*s1MMmJKjW69g1^^nRznK}K6aZ$i^l&ZXpHAX0Fs07#c#gRYHEL9(!Aqa zjQL7*RMb(?h*sea&vV*%FZJgUt6tJx?`no^(Exw9y4MGrRopsRQ=n4KyHXvYX1CcC zfE`r&TSK}qK^_#!MR{=l41WJdXPNCsu-m)35-qAEEscsTdcz*XarhGv%6-|**W6a9 zSpi=rYDuozcf{7LyYO660jfg}t+$J5Dh3i2g_YrTEKBLWimSkN_wd$3*zpj4Y;A7# zezF~2Pbi#*6J#>nR<{>4OD)UjDVz6fIOY^%j#EAJ=Wr`pUL^LGpcdK9s;21V z+0^x7MKVJWr?mWJ1^VjWZ+t3g*tE`H=nbgdvFl(zIHccSm>atvlsCaT{*k%Yy#z)d zOy!g8xG{7zz%`6;cvj+@UgC3BAbc{wHRpSOD|~a~Jj>Z%| zak;0QfF|0(hryBH;pPp9K2hvKhi zW{3XC`rx0r0CV!XS)o#>Q*qg}Kvc#YfEEg%i zUL}_RQjHx1=6($&1ha{BHETCMT8}cIV#X_u5ryeyjY#U>p-pADT7AOiP0KOsY0$Rk z`qtsYC<*b8e5pr(l0R;*OPT_kJSyVYC;YFm0Lv{)EW`L^4o~(w+4lyPmARn}eRKGCZz(dFt{8#0bRUelB| zP6$c4Y+W8qR;Hw-MK(AKrbu#w3h=s3SK6R!`CVCu?$RxH5V@?lXxQ-ux7n=e6PFu{ zz5P?9kCNcpISe2*f0@jbg33>h82p%8$Q8%%GKYsqM5cG0F0J=U$_iSRh>{n_BIf$J z@AJsoqZXAtqbvjg%EC1H49T4-KO$^3 z8m&}+BbPr4MDi)WJbUZqCX(}8%HV540D^GqzLJ-w@kT*Cm=MRmLIC^tbll%w8W{Sd0%^Xpby zk2=Qbn}!(ZBUweB43HO6PgmB|oSZ_Hq4V>DK)tI`@KQqg{9By|aAh}Rh<_SCannOB{+@>)b%S-AUP zH%%9pK}Ej8G^u#A5;q+E>0Io7XJy0)xC3r{sGEhUnAE|zyyj&~&H1|tz8vo4>Uy&1 zkIm_OcVlmRf4J1~a5v}XG*8rIFokDjp&32%?8U#d0KGYa-j9^Pmn^6q_kzWH-G&@d z>HK~M&&tfjFoQUpI&*4jQjHk&kQSo|z>j=fwT*Dk4U4299+&cI07b!82UrKS^{v;o81aOHK-7TH&nSY0L;a0sB2PgIbhMk}?N=3E~J z4__a&h`!hhj|iUNvONj+zQ3=nBGS9zJ_M~4x%z-|6mC2m*upQ>=X)dh7(wyvc0Yu8 zSGAe3sj^_Ne-}Mm7&ZPCB9%o_VpK*9Tn*WHU;T(3!#@z6=>3OhRH004Y#Z~gu$;O& z(B;Vnm+zg|uV24dnQUUjdH7=ns*jcyCEgpqWMms1-jPswkX0oG;xj0XOi#N*_R<8M z!ycm(8mG-xm?>|=To>FKTpDg;uW^}Z9lvQ8v zF@FB?<;!FqOTvTZ>wSrUSF!4K5i;~8U=havb7h7#6KLJ%{i^Z%yPD}M*ZT}~9c%Z{ zkF@Hp^CICoE&Iv4?8U@#^uc9Nb-v{@p8a|EFaW|?)wHy3{P%%xc?gg5fBjmXu`F2w z%A-y$F6DMh;(dL6j7*olyYuc|slP#ox3InWsJ-16=(KNW88~FWlzuW~%o$O8`nU!o z_wevrHCIA1R#8GVXzRLhDShj$AT$a+CKoEXU74OuLFn4{LxMDs@M+m2G(_>S0Ewrx zFVLpbyF&S7H*QxFjUlmC0!J_PV8hZ>h1Vh%0vlMdMe>uHtHVEtwXV1-3G}5GAM1Lr zm>~d(2&O9i;L=R=JiaJ>r%YL+4GOr$0~eyqkSw0^$-NUM(?Wv$@~yw}?i) z+psKjoKKrYG#Lq;o|4h|4)S>0!q#oVyL{N65icIHR3f9sN!M1j+sHhJKAHa9g%ViFrEAE=*IFZmjA z&HZV8;c63Yr( zD7axac4wIc!eth1znJBk&pSsb3QjI++z$K13O0(ucH9GoQ=QKC9TC4rPuTc^CV*Je zK_uC0C6aG*b8~S$)sw1vMwKxw$=)BDX@6BSm89$QxW#i9f9`hhlw@GwbYT9RfQH}F z>}Q_l?+YE)!6xMDYmSd(s8ycgPezm8F?NRHGbD3c-~lQenZEZ=ITDdC8oNy@N>-Lh z)KyeQoAw3^Nz~tK7uuHJ-7R2_W^HlB60E7_GlHMCetA1PeY0=NKU$7z?5xhw$G;Ei zxS75p3J+FxIzH{EvNt+ICe+atGx*Z2)u428bsjf&9ZI6jogXrfI&1EBjO24Q_*r*; z?5o8R@>kTM(NTh>F!}yVd#FhDLEWKszEnXP_5(RJRclW}K|wL+bG@gjH%S1YnSXhb zf)XcsZg+Dzkq)K|v3dF;fLK3IDgDvnayZ*MFeTs`WHNv_*p4Lu#2&LQci1(s8%$H( z4~mkP+=7BbW7E!2n$Q9!)-ll!w%E<_+|uQFlM8T7FQ4r9a@ag{-=1ZSgB%S~bcF`= zV4Ug7I(&~i3ORu>BHG=4J$gp8rXo=6r(RQOcangAIX6huRWk2cn=U|O-7VcMEe%rA-QC}yzjMCx#`XRI7n{AGXV0@{X2rek zwdU%0wEl1<11X%J{iWtgt7jCnO%lsKFM*@95K{_+*{!=^grX2r(;K7u-u+!(6#Jw# zLqA%kV@-d2Z z2=g?j+GT*!q;{b0E=K)G5oSe6yH)5af zk?b5U^vcS#hKeJe;DHdTM~8AoHV?2=E;{7D4KM#}e2=Ihmc1-m`ilN@B_e{-u+$g% zQGYv^A81|3yHYLZ9aXsb{X#KxT{oyLGihkrDEKikQ^@=u0kJWN!)m65dktEE%b`H$Hs{bg#IN6&NZL+O!mmhHXBYtp7<0*df zAz-t_RmhXdtgeoU;Jp=RjM0;N<9>`yr8z@_XJ*FNYz;Ng4|-KGJ>GkHxf+e%m~Dj_U-{U%Unw7*O;{;08M~U^FFe!@e}Av- zMdv=p`Aypy0Zuw!tbidZ$^E1U<9T~3Yq=Ose>=7pISm%p*>kf(l6XTowbRvnx1{dA zs?JA->mz4y{P>n;FzweYzYx(RO^E0>0SsCKZ=c&u2$`6S1E2lfGvXXVzp`9*y}6MN zRD0cU!%s9dv-j_?R~L_0qB&v&g9Q)=`A5>Y5_-O2*d5f&yj-07NNB4%8el(ehyp8hD>2A6NKX9Xn<6iKsc zXyP+G8-$A~XqXUliC_KABp_bAvZ z^2WP{FVa;iNhVi1s;xzwHpk>-6&1{1;1GoeES1z@RF0u)U-xdS1hW~+tlj)P)q<$_ z^NxMaDD0vwgi@jqh7el794GSh)D{8;24*!|UQbn$&^8JxTJU@ssCp(lTLwE?$_+X< zHJ6Pv6jZeJld0cx`@FNgBObTDmMBy(^(OL2cM-MKSJpT&RImzx?cppOd_y($^@)4s zZI9fSNt40k#}9i6A>`My`)}RNYXi!cAq!@?KZeO=*pb3dvgOm(SQJ?09a-RBn7N@> z*P{(AR+qf0`v?aQ-ee=gD0IkPpuosG%Fawb6l$4SJkx@+oWjewTqtMUd!PzHT)iL8 z;NvsIiNvvLW_UbX?fItK?0h2UBpEC~;**2uVfRSt;Qz5PvuM)xH3s2&0)xlr?+@%TP7Se8CB75KPyQ|s@Jw;$Hn9$T&fzI z+K{YKKGv4W)i09Q8LDp+6np%L)dMiq@j^|&P_)bu`^Nq z1d$pxkuS?+p>~U~DHsZ6n2VBVcfzve@qm|cj|4ILaB}pzNK!DEfp`n!50c=Us1)E| zbpaUUXPIUbbnauRdY$d=Bt@v`+V@Gi?f^>4!zL;1+Sk(N2%?PggumNykXcBr>F2o)ccIh=gE!0bB^c*un7*^^*48y2RIdt`O+zYbLN}C;mys- zF=*dK)2r7sZ!RBY+}MD;>InsskobG~BqarfZhth%$(BrhjOj$4&C|mbf_}L_n7v8? zUkM<74*lOhOmTT!V=pf+1^UTr>*@xxxb;5on)o?{$vK@>l?=Gyti)sl=*>}xy%~dj zOUk6O)z~m|Cb_GPmzDm8(EsOj&5YI{(zg zD0m$$cDsZ|Y`K?Wef{3ulOi;O-Pr?0Fw_!R>T>n6yfyXG`Hxp?FXzlKvYghN3_J@% z7N1R5xUNMELgA5uqM}Z7)`^9MArx6|2677xw}YB0@(4^t{2RWAv(3CS^^5BZry}d8 z88+xzAwjsxB1z!*4`jD6F)nEKb0A9@A_iH%bbW%eOyr->33gTOd z>`y`z&gF=JFSpg-QSB3?8?cZdpNTMgAWii#+Ew_#M&LO7m24^Bd>2(PIBG91#Zqr9 zOJpCkZ~(IiuhK$7LNb)jqaIlQ^^=&d0O6nNJk$HlIH9h^uvDTB1L#a^{HRG4WOxzq z#Sj{O*^-0bD$g~W^VUQ zlH=tw`k})1d?&AhN&U*=oNu?w!Kz{fHMhoK7+s6-Uv3cUud zI|T}za$2 zKe{UVs)zyS;2OCq1a@zCcGIL?IU}_Od`c!CUQEBuN(js~ST>*5D1}}rV^Ib+;c$>x z)pOCyKl^v>7|LZU->7E(s5Yg$Ts<=FEqf3+O}NJMHU?JsmQ_rTCi~SZxzYpBg0`&; zX*V9TV)FNKi9OQ(9`dtA$4_>D+gG%!s(V&39%o%s{^GR*b>Z$Zo-kc+S(43-Mj{Km z^aS8&8H=(=ccspv^X`wWCFf;R}3Ec<}7H$iBFt=2gCYV+6Qct*78 ztWl@q$RA+hJyuvdbw!lfo4f=gSkT330;axh;&(|mjhdNU`jgY6A7epC(y)3F?cIiw zPE>=zabf>5oAFbd|9TGl$6#L;nJ+x9LX9GJCQp0f^EY`IG;6_T8V@Z}t=tR+nDT@B zLxI2IdBea6RFHtN3K8z7p%kXH2Qjr-w{58W(b^Nf@}~df0GbZG1kAujf}8 zzdCL6DViE0T1mNQkBj`NGf(xh``mx#nC+WPTP$LA#crBa-r%uwvnu5rqKr3vhpjg1 zom$qd9b;`msk%i}|My+p+azEMX|8a0B8jkP)t_w^-y8}#0XwhsxVY%Pn*8d-?qOK! zCFZX3TDK1aAx{#s7z1|2O)|Gm@j)e8aDW<)b26hwQ&qC}$GQxItBb+3Jmw2h$(f8Z z;|{zO1*{Y{HL@;^e+vk6m^t@z@*?W%vDA=7z9S2)@w_|zjk=?CAFKPkQQJ1pdweDL zqdCIuC`6(Kau+LvSU_K3axiijubgB07*xpicNGfBUM3BFr^=#hhy4DcsLw0p5qI}$ z`u*Sc1m7^+N`STTUv`oFRWdptYw*5~6?HNJs{ZeX^n<`MF1hbu>RNmSgaAnzJYita zNAxwc2`@L+3vv3|#vsw}u-c4yDsLLYKG`I3YqScF5ZVu+X(ykmaPi0Dbu;q6LMRGTqYQCeX=(HL#;v9d+E0Fdi09cJsz0sm z!PDu;CQa=yaic(cWs|($Vzois{br@wEHSlG+3lQXcIyrps}J91%mYgO=L-xU#b0x;9QsGtS6 zD!(kA{UUwUp&lHSlQ2^<8g68sLmPR__Fhgbn}I>+Tz97APgvaBia%p;+HceroGoyo zTdmNE-ANs1hy(y^Aa`1nAD{6-`>fvx7h^t$>&zpelk*|T#gF6$8+g( zQiOp*r^kv99!R6z*ZZfps12ht{$v#5QaXh_y-JSIFS@wVdwjb}x-UPm>5dcihuZDi zB|*hJtAlsikb?zl?;vjpZs5aGwHdp8xstK$+3yQ}=Nm(D(c2q&59L^)`-#TV%ZYW|OcL`;F6sc^WosciQIL%QJdPvOIaw=d?eye!xn}#! zdS>2Xc&m1X09l0Vmx3lCt$w}OpSLV#1_Hy-=XK)L?32HKP;WJf1vOdfpqcgR5r=@a z-m-e<*(-J?SgyHV zeVL@pimqqCzC2?N4;wm0Ky$e5ep{+itt!=L+}Ai27-q=LE=q(RG#{?)9}IOS4jVE$7UF9RgB}e{A9ScH9vM~CGJ|W^Y2rC z_#?>rmT(P#nRpX$_ExO@Y+jnX^_HdeEF0r``f3I_oL@^9Yomu=f@@@N&udvsx^NIq zxm*e}=%6~AByA>0CrM0@^Ou}#^_M)};x=Xh4I``(5`T8DR#Jr7FK#8Nz&b*wpM{gg z1f}MsJQc7lwO5Jo%pZom2=d~9t+mui8WZjcKif}76atF^&wSRK2BfVXag!h^dg1)K z2$o@pAD!MeDvG;{So!&}z~W2aatVy0>14Y*5)HD>9+OhPwzMwMMH{3KuSDodmj4KE z`pu5i@u|7aP(0-@B5(QOb;b|gN#h1SSFeu;iwMTFi1xZ#FvTf*6Yh62cqZYGG^W1w zL!!0iKLgy5whUvN>s}849#Rr#HRsOkK2~nmBu!Dtcl24kCo~TSYvlzhGR{c7Aruae9s>3-%KZb<^#+sGs-=4x!Q(EA z=kZy>&7rK;p9~GH*2Ri=abda{Dj_u3hj6&HA1TL)sXGajhqSTWP^_j76u_Mg9h_cdsuuR>aanrThYVPK!6 zJ6t5P_42|P(u~KhVHk_Qr#Jc8x8=#i=LJt^A6Kgcaa zd5`_*QX=gf*9nhkpL56b2BfdG}Q$E+XjbqJidgDNeZFdN1uabKxH!2L&r;66SMd%1a}o)K zp&5-C{p8p)#Dz~L8;46wUHzWiU3vI!r>M9e&oFM5WZm8SE~ul#(YrMKXoo0@IeUBs zUcr9Ym(t&DB`_Y@zL#f`w%6K7QTHt|)n>nBxY9qE<@x+*EBTxHRmWnjSuBDMbFOBk8+fVHfoHA9`o-kr zb|G>jnu9eN`H;lsU4ajY11YYOG=XS}DXE`x`*(YyJw6U|JcnY*PJu0snK%{F6{1l@wlD(j63w zIMqFWJSry8*bEUKbDhON`^1B9t)a8?Ls{d>i(W-3yakyz4AXEOZtCa5n~L=`V`RKs z$$2CMd;Ndf%W;LKc%JXO9=y^o)yr#sxXflE?N8*AXnCjfTg;_CKzg`sb3Nq2Z`$(+ z=oIYBu}IqExv?SI^D!&GDJz0Yl}qC7&XOdXe(R>O+-#wza;Rvch@LQ*61`$Y#@Oe_ z!c-Az8(rT}c#j*-65)P}`T^tInQo9bri=KWYspg`8PccE=hpG%ucL(R{HxwiY|_>- zIh1+&)iD>`ZJZ2BZ!hOd&)3lIvn*8UCZ#OJdK=@DJ5Jsc{x)-gCZ;%A8>9-hpPxmT zJ^Bm5uI1{5v!26w2*AeH1O2Z~FE&^9MBmMW+Rk1(KqWbF^1wGk(aN=kgi0IBhQ^JU zRk_@@gTi|U2jx;`16eC}KgNIh2^|V`0HP9NoVT3I`am_`bnZj*KnAP#{(T`Kw|C*P-Fd8t^^O7Ob6!jnia*&6Wnf>OC}OwF;!p%tcSR_>>OI zX?=_vhGWjH_rhJ;c@{!6%rK?Y5i{#s~JK5c*yA{}70s{5?_=i2Ui>ae~r8M&c`LHm)!|Xh7+hjS` za^<=60_7J2o6^*)pYx=)KA$>}8o$pR!Jp}SXP}uO!I8!q&|mnnr52-j8kO%IYusmx zz&#)T+q=iQp9`W^7p`$MO00iAlbR3ASG&v4onMi4%ekHnvrR4eZAIhzQDDLueWLuX zG|&Nq#{79&4x@j7ufFVqEUT|EG3Fq zdGd02S$BqS@5`W7(k@eZ+e}iJzGoUV=A&z^E}rxnhBaRHny9+pozG1+s%Fp^)8D2 z>iG*y>ubo8qPh0)c9-S9VV&srl{svKH~t@Pgg+d2+okO6!;H<1iHI2ohmX*5W0ZYZ*FPeDu7%I7p2B`pc|&kzQ%5*h=>@BIPDDfeze8*^sF(Vi|=qtVVa` zM{6w-y>nEyU+zM-gK=wQZ2D!tsFSbHo_90xRM`A}+N?TW#}FxP(9B2ZpZ@Ced8>Yo z7U@l--?|XiZht+2VKV27Z|a$hqA7p1$APVDq8V|P^Or@VY37y=FW#1Pf`?r+{HL35 z?nh+2t!u9F;yDCe8Yzvh?Oth0+FV;qs(H6N-jk9QXMa+))+DNQ{}8Wc?kUz;K~GTT z507d=m2CQMa?C_(wy9G4;+0LQ6y|2KEw3)7+OGgA&h?U34)2L|V>j=054^jgwsNm; zQWgfPRvE5MV7SklvO98MZpeT2fYPel4Qg)t~ zx>eO2eNTB6!0;LRf&zAC1f2LoGSiI|12iXoRjepJ6ps2&nELffZJ`8aV(k`wWLu}s zq|)g)sLAXJ`gu{(7V)2Nri7H-m0~YR=9Q{#;5~czkGTnq&5IrA_u$arb4woeDvLMP za!$Ftlo_dU8lRp9_U!c_K~?YI!($TZZkw$Y9m^}5q%d>sF*}rFq)uZobyc3*K+o`L zPgtZHmouZhkrEkBRyWa|?=^L9SC(@!f1x&_kME30&w|P8_b!VSMnpc_HjEJk4=(U4 z+I3PEDj|>>^S@;L|3#uxMU^@l)25mr(hsZQZ7hyepsg9EIuX2~Bt62v>qzuGna_&z zr>$dRF`^(G>9bLMMu9Dv!%k5D>s`UWpfj*%U7ZI6){{9XAOTG7=qEL4r} z%PkYm@;ukV;vX|U_vEWfJnTbDxWd#0>~%o55uuQyM1ClLiTZITf=Ddf7PNO{bl9C- zIV^f!G9csjI+bIlW5*5;;If2qF&#PbUjbnUIfT6Nis#dJ2U3Vsi?f+_c+jIu=_{?c-re*TMC~)Gm~3H5OZKjy*#gV*#yjc zatex-1E-~pR=P=e)r{xcr`CqcEd6ecIq2Z&`W^A5E0?+~9i$)+y-a|C1xfXvvR>ou z4cXW(B6Km@o)}RhLjI#B>k)SpE+o?aBe=p2_VV?&w4VzCekF0A!f5{*bi{qXQ1nUe z1agz^^h`E_TTn!#$9g#)5yHPq7a~u#MBG*D^JihukQQ{lFzgM*f?TpRHYNk5ZJ{`9 z;mys>&P~0l3TqF)m@V4p@j`4F6F+}M3OR=(V+nrbt5HdSr~sLT%!65zzmy9ECpv#b zU+@SEvgI4cC+M8N=Yd2PD$cV@N^d*V@dWf6O6K08N?5WbErNSSpq3j7CFqBqz_9Ha@;Xu>nLJ zia%^+@jST4ste6``0Vs09!VT#=+w8E&;PGYHVdqw(=-42a2{7<9~Mc~hi; z21JGEO(Xsj4Txg;e={NcAb#0C?)%bHykL;-nxuk}nEE1l55CZYnd2=pov!9Ur7IlI zuDB(WCXXv$(~$)iRn`X6RZAVK`)p0zXD*CYYiHMmAVfift%rx#93Hpl6|bWqUL)ZC ziRMT+eSGxuhKkYK#`BtkikcMR+f-ZObGsyTjo0ELx8TMOB{hp?U9ICFPhh0H@tptonE1 z0oL`iCAVOQ{AvW*?MvAVW9Xw&0qsgJ`Kw31Pq4YDApwF>s{!Bt73#n*&4iXBt^(;@ zq7LT1^G9<#Xt~Ni!^UD0`w{}?rz}_o`);fj*EZ(bKJteq-i@d;$f}bdHN_VYK(r-0 zE57>;)2(+{Tj0*qYT%@K{2gs_E}d`{TYXA&6=M-P^|tb2X};{4=X*r2GVl9=$x1g8 z4E4JiQ^LTXi)`A%G|Hm{zc?|5qVNdyY){Lz&EaQe5odfmpVPhrZv)g!t@wl``t3hF zU~YanBZUh8Z?B=!Puh_gp}!-pTw?UF2LZD{8~6u|mp{G+uvdJUx4x_qEGmDC;7R|5 z9r;~~bbfe_aPBp0&tED1H$H-6EvYl;(G9L`nV)0gWO34@X!hEfsrW-=!^B6oHvX=wC& zC;J~-5eT6L=L``(InD_c_8~l>UlU>sC%@u16d_p~=({LBwAomjt#)IJ5{H6-50mh^ zFegxc%V100V6);~UgQdhTqEf`T;CnSm4LqLm5)I~19;s2IOKp_L7cDe=^@+(#7NS) z`F!BpSu`lgX)IP)%Uo-eZo}zc_jyZx1L<8dYqa(%At7J%y~_K4UA?dXhHX4WrLcTK zSxxOD;1`3Za$YSCDj-*!_2Olrn7!+G=&R3d3?qBk;NCn)pSK`u6FO#ltx0i0?-5{+@5?s_?qftNBP_D8u718^=ylYgt4zqZ_mG zdqryPr4YoA8ob?4w0An=6YJleaP4V&R_Z>bM7CC!n&fc+ocdE2KGm1Po=vA;h;7Wl zW`TC$G*-fh2D! z;$KlyOhC4LU44U=dwX<_g%YiNm4Y>_a>f$>rskWr@VzcB zA)jB_C`=XpurQ6REsgQgO0I22?6R;pYr1znD8AqAVPp3wOXF*;iP3KR5!E!L%xE_N z)q4KGlFB>Nk(cI{#9_$2Vb~+lCzCO;MO5yx0`J*;srdZk=;`d7c=TocXaA6aUZjfR z1^vO;dq&hRxsA8;iyN+sVT?&(q|C$EUh$5ZxI#R`MKDcynIePrkTOG}G>udtZ}TUh z!xlG+v6&l-FGRPL^7MB;Dcd7`FFAUz7IdmN6KZl&S;g8+saac%fOW^~Z2=-6=v$B6eTz7NTKdSDXNp~&zjan# zBk<$htW8O%)79>Tk7W^OkAcadH$PKF@BnN&=e^qXdz0qmm2+7N zTM%$?^p;34P7dz)hTZPoowWFeu4`@n$Em6 zwyIQMPShEC$9=gkl&5ccJ2S%)VsZIX#^}(^%0k7OOk@aLq>zA#AsD?OYEN_)8Ctt7YfOCwvm2_TY~6 zMImfZEE+g3;~3`A;>kgO{z$S9b$# z4Kb<;q!7;nzhCpn*c^PSCDppbcskbMzDs03zc_Dj-1VAmiCff8DgRS6Xb_yWADWs~m(|gP zv-|mKcBf0~3^ix(wuVdcy;^B0w^I49WeSC6cr`9vTkZRbeiVb`z zk-eoVAP>o*uBblC{-8Cd^-;vsKaGHdZhGxTfuxSwM6yX`w7Wkh`u0P&HT&ak>94rP zII;P|^DYgxqx2y*FHgKPI*y)JqP1BkDebr_^9A;$C9b3lNGmAHiP~IKYg-Q*R5GvR z5xSH?;t3oKcRE41A6Cm(g*hBCl?{)HTb;VwOt3j zR-M0pSEt1j@$^uLvnpU{sA|)!0e%fIM1A~Ahsu_hsC<0gnpG8@Ef#1Dx$|{kAgA>W z1MXL2588thDRsZ|T=UfQF`cLeSc_n)odIcrdJ=M);p380pmwl&Ad?Oah!+5_q#fnqm zNS8gXG-F@pei(b&Rj|@m_XA}wv3q4r@r4Tc@0^qY7N+67qd> zd1bh9-besg=@U8l7`ZN{gT2=Kef~??#*CM4-u9Imy;yIHI3ve;8~G`X8(}RS>duKoW#5Z~vsf z!)51}ka%m=c1C;Uk!kt!mKad!bToDAV_);$Q6w)f4fubxl}R_ni*_XY9Lr?m{%W%r z!zN&5oX}JuSnBj6odj2e&2)1@L!=J!xwm}gwaykTM6YZjxgBXwu#!t&Od;7kdExZd zkFAZ33mcIq)8tkpv%YJ+ydOU*W6r;|hP?s~Gi7eDuxnt9nmeS{H^rw*^NBoZq4~-) z-RHW5zd^EIcVnk@A(Xvf&PhlL--yT6g3#KLml!)P$B}EE%uLV#K8JH8i`n$~C$->A zyP;%DtW^2>8F3J&M~VCU`uZR^eUy|0MdVE}1%O51EO;r}um7YRqNzl}xKA9|;pd&S_B}$JI)k-Das6me=Aad6FvELLISi z^u0SzBDeKEF+fB<$H#q-%_=Po>+BRHmBvoxI1mvLkxFHcnx0lVJv&=_u>l+!2H+u5 z4t|6tA>u^dSl1+l4)M`^641?T#j?`X<=}F3r?Y4ndQN#bW*|Jfd<2f#d8@QT$${u} zkVguvT^M7?WWy1}@Zby$4FTvA1}NQqcPn39X_g{<((^gwH%#c0?wfN| zMumYhC9A;61(FsuV^cbDGl6}{q{nA-W1(S_AX>E$Kv)IDlTzX)fO{`)_|e95qOXQc z6)&7O2FmuHx^m5@`dojl8GxP6@gD!n*Qb5v>l3H{gSPZ^KF6XdsIt~x;*AXJFgD)H zmX{2Y0-P}UWKP-%BetE_-b#H4F>(KHTXyU>9xvh+5 z(14pUF*KKyiW1HhVlKD*5Cf)0UQTW)Efcq$BPQKqp1v|n^I_mp)w+){UNXB&$E~Hc zZA1Dq&fNsTGbR?w5p|}WD)xqcFY04b zcHhHA^*h}^0@hudU*L7FfCg1eP(!0T1aLSZ*`+;eUk8uGNTHA$Q4&}fo36fUg~pw% z6u!)R7F+KRUmN8}K1NW`eF(?$5HQFqb-(=@oF_yU|xA3lWr&JW=DMEAmZQ&VI zCH4N%g#-lYBd~;`KT@@aYl?Pte`gCA0P#9p)HMxWG~yUC;z*k$vpf!^Sb75fw2@*i zoj(fA8o-WmYPQRWNmFHTm>m)RoBmb>kyI6yG@##6+C0lbl$_nvr==Lt9Sz3S zJ)4IXYJ5u8c$G3lmogeF`#|#8ym0Li9Bwc`)fg;MXAXvgSr;i$r!}h;Cm6htTZp?r zuof1E({Q`n;}NgE+?=j%)sPz@|4&GLBHeQlHEW4o(E8tVsGax#cgLg^$PWp0@mz>M-|}#TFV4T> z1bMDwE`w~+C_i5rspl+|=Q;_k|8_*`uvFmxnMLhd9PU7~*PR}!_w8Cl0yk6>$bTz6 zv5EkwX3iyQ;|wuOHwoFp#nD&9GVab6U3Nr*aEb3_6i(gR4{;88-!e?P&rY>E>Qr_C~i4^_Ri(PDwAVnB@^5fqi7ZuJ)qj*e$_O z9+naq;pNvpism)R*3d8fAlsr#a(+7S?kA(IdcnS=cAk{E%D;p=LKrJfg(npPNjjwC zdq7M~%fKIm_j0q!a%K zdxq~FSV%YV@^7NJkeQ-*m|}VjaRQs%1mWoZLuRvta@RuABZqRTsxd+vT${jyW52f? zAMuR55}USl95EnIl@+D{{lCm&!o_0s23D`~qsVE9@SlXy=8&cn2hZ!`nd^>G?ad}W7auQMmm9|} zwGT)w8s%_`)aP6#;t7>!EGrBgD6K2v`F)5gGz@8nU4S#(uzzwEf;IeoaAD9vEy7GM zsb`y``kT(L01i*hh%*TxM-Q-f-+7&`nY0BgVrr zxfn$&zR+HUS97xBN$n;Vco%~EoFNi(8)T-LK%e?VkXD z0RYP#j$Bmuwa43Rhs6IO!gy&pQ=Ai40ej#tg4>?_If9_?a+c1Vj6HrAcJp6l7mhZ> zhxkC*(rOM}+~WTfg}IKm+^=nA!+vxwadcO)E{2d%un+$fXcmB|H(8)6!f%+)R2Yk) zDlZnwgQH>;>X|gYw_D0m^3_AZvfhs~Nsrn#pa<_Er2@@tfRk*ll}|Wp0dEs~Sc>;# z!HBa-5O~XDV^~?))!#<8z1r65W8}1xB!XLy7oaqaLX)9c=_pg~otf>h#8ZEmsD@7% zb;;}34Q9+5=<*(xV1xrwb7ZXU4bJWa+6XvehHxL*(3Wch1(AxVX4=}82Y;k z|20dr(^JJKE_)tiJ*WcRICp;Z51eR%AWLtiKQXobV8d(6nz#?MSKQ#K+s}eEC>*Or zs~&i3^x0z-wj4dhfn?A3LY3AQML+BJtTNU!$|x3;|HU%~|MO)&7TCzeUzCuJxmL5O z<+r46E6k+3COLo-6r$bko}@?ck{2upeC6RuiqX=)qgxggyjtjxqB?O7{d9Bg>UmzQ z?0mmPciNJ1eI351`XP!sumN}z3i0e=ul&&CxjJP z$BN^Q2FKnQc6ROdtHeBW>D&M44Eu_qc-EsVs4Q|P zI=4+j%$6FBYegA3zvZl}S1h0S*~=(Rk$X$adRy;#$(-?|K{MKX%zAK;mTGpC1J0AI zt$i2IH;IS&_%HW)M1N^t0QE2XIT%DjC_MeYnXNs~?*H(_m|3id<&YGx^RZqH3Y>&Rf?4^S^}my1yW_Jy0Z7 zaiIzDlqXP*84AuGv>BwSJ6Ej*v4J%^+_o113@q#zbC?{tu(C1+#MVgKx7RVCrGoLn z?;6mFPY!g;fJES?cV=URfpevI0sNNq03ULcZKJzpPPpx`F!}+esly6Q3NaBD@ z*0#sOsp3)FQk=qT;%SFUA8U}_6%d>B8Ff$ZP9RlSxJk*L>xv|1Kpn9Xw}fHQxx(JQ z$-9Wh>fvv;>f=9 ze4q|1`}=qAfAPedpe_(&Fj_9KgC~0NfU|#j=?LWdb98hIxMaB8&XFE>mke%~=2E06 z2^zNj^vh9T`%7K!&k2#EW`WzZxLu7;P4!TfHwzjXl7Oky07aUhu!w7;QH~t-so^_F zQctY%1$F6uh!W>6fO-yKGH!;9A;@WI@zP+18i23u8LgBxM`udMCQJIK2D6 zKNdm47;alm0EU*jZ#}k7jl3)3UUjzW!6YSHyvh3z<;*OPvpJTM`Kne>zK40{&Py;~ zYeB@vmjTvrHbA|NM>nemY1hUj>2eDS$PXOS($e4W)ZOGa4_sUaxfXC<$_&|^dy z*%(uUlPq9jF|zEM@qf*S$$}fgvJd0i!{5@B{(UfXGkA-%sho-9EwTNyycy)PdzvK+ zCZa^MDIN?P6efNITMF>kHo&=y*;!dxqkG@Jeg(B@Sw%%(nT$t34jhyhFG+))2>J(Y zg2Ray9A-2bGXTUP8VQ!eI|5!@uQF3?5DSBbEqxIObJb)PM)Deogs`OA;8aS0m5jtG zYb9|+Lj8X6Tb2}0{pzTAJRXnFg}d!(Q}JXg!)rh7Y(MRl6L&Vd_xQU^65eh!V~AY1 zv90;njSgTY6hOZjm)o6u4%c&XP#~6HP!K%od08!$&VAFoTU=1^XIkCLu*3J&b7K}% zG_;eIAc9lSH^%O$kjMh2r!O%7sjHl6X*@*KPN!n+hh(eVrJG+l2(SB;uD(7%HB_1|Q$Bk@# zhY4c5;y7q+4|np?QOnnLIFdSCo-r}}%nw)^Gr<`FSY@!QYCA6sMsg4Z&yB$5e=bJ^ zO&a7?Rr@ua7UOK#&Af&Z8T>%wmW&#+ndpp+(XnhX)h0)pt0lK1h;yKRy94Ua$0gS~ z3_LwO$B#UuCon;Ab-rvyINuRXWN@ zbhR^x$SM5e#PTRFrNs{r=_THhWG8x5lAF(l8fvr7>SV$(vLc(92IZP}M;8 z2eEdM9wH-;=JwZD;h5tR^~mFhg}djv9nHN~Ws9eok3J|)xPJ1Jj4gH>alu6vix}k? z?EtMSW|*T=snEZz48&0ZI|5qlIA1L~scyube!!1d1BYZ_;^0UYGAEhgu$p@hZgeiS zxP|Th6mCEb5w^a&w15an5)0~zI&Cc~0#`#IhvfFHNzCQZv#=NvhY1M@QA}x?efbhv ziaa$nMG-=ByhuKuhKT(9&spo7_NE)Wf4?XAOCng_RZh{fVyX z1hax?@TxWY_aaJE5!K7N{(cE58JSgZ0Jz#2dvJV}@hE;l(bxGpD}5s)=%OM)MMd#w ze-&yYZe=B&NhEbFG2hvYY03iPLLDAb=D{#bvPDNn5lOV^5v?WL`zhl$6s9KI6O*r+j?8BDA)& zuu%jty{{74@X9%Q$@9))f3{Lz`j(FMRgx4k5)zFu7*mH1BEaAZ3Jd$UarZbYCKXzpKjg!ifsep z8>ngX%cULr)rYGDUQ<0DT}BCEVG)Xkqn;J(^$oI4F30`$>uYv!`Y*8F!1BhNVFtrU zyhm&&%W!`w5q&(ub+pcft7cqlwQSi;OGDH1=g)gkm;MrhTX|fV8r(}*r2puu>r0K` z#E)16q=qVwJ4cgb=;EmX-*>{|Lpr=}m!V9tu}(ny_g3ono#OR2wi`qT2Y($O8iJ!n zhXt^sROz3_#OP?`*tj@>=$u%gvXJ2Ip3ChqA}J}U9Mo&o^7^4Ta6xnyd4*ajIUU`o zI-Fw@9%~9s_Ll@<;m`MinTWi1`%DnteQN?>Nv9JHl>17P^0oc2>c5iJu20Dp4-PIs zeB~!Fd*BE zL{18S9>bVa-5Tw%6$4Xh1knJ$P{# zpxhX|s9Hz#!L?FRSy^c2;>XdemoK=TkJ}5X8l8@`z;V?i#gAPp^nrnap}dXdq(Q&yY zSv`&@+3)Z8AihkH-QdFhkcA-$FmP;aY;rO`7R%}RmPAC9U$IyW6B850wceSY zOe%_kufP5p*RNmCs-3Dy&@@2T6W9Kh4ty~%0$m534L^nJ@Ncl~_@AK)$)w1Mh^Ww2 zR#qYu3IRyW9(H$kV{&rRwDHEr$I;#0ZOmAPLLnxTL`3Vz)2B}{Ffd?T>z(PzFm)Yu6yla#qV(v!y5sWLd_wYu8L0gQ!?--n2#u{rNy|`yPWKqJaOVg)(NGi0h%U^3jqB0|BJ(CJ8<}H2L|r_51KBZ zYMISUb~SgSMF@z#KJ*D0J~z zZr!?NEI~ChnN0Q_30+M9zcAsp{P_3$}GBFaOwKY9GjYuQ{AhEB0VqyYT zt2O1{)Y#aVvEN=*Res-3BWKCvjT<)*3WdqfG!4iOO%QLZKT>MDu?i^ZJJLQ_*y8Sg>1SS+Zo=Z7OI4!W)ziDWDm!*}0( zhbK>-z+$nWq@=`nP6&ZuFo@C7Q2>CZX+}Fr$Vn!4{rYtb4i2KRu`%Oy^r|XB*MSeO z{tI)LGVAk_$=F&PYt+<&w*C%WGG-fl(b?%Y?zhfeQ`&n89XN+mtEtMmU_3uMFV0!! z>hFX{@^C3D5fKrkwSWJ9SS%Lkx{m4TY5efR4{Lr!B9V-i^;s+yyz#~xa5x+}_{xb^ zFA|9udmw|sV9MWfi^T$)&6e_fC=@b^y-iO~8*K@&E&s^s+`M@+>qHU&Vj{83_2cd@ z@#8b6jr++ZugTZyie@J3aO#{J9nBKD+&;*C?YJ!a;Hj68nAmPZkGKq=4wpp_yiz@+ zj%3?5^oVw>?u3t~dE>d^^R)q2SJf#I5fQBuH8nLjd-g2G#>Vm;3SN8dH71f&RFeB7 zW3gD;nMSMCy5M-IKp+68(+MF26h(pEZqG@qg-#MCr`7`l15gwNM~@!Os@(^_ID+%P zys_jnLI79(a2&t7^zYS#SQvV}kS^|q+_&09m56fT&Ye4`+PXXCUX82FwDE?Ahf!Nw zYg+%s>gm&``1I3HQC(e)k&zKRd-e=FckV<*Ma6<=Yiny!SC`p$Sij$o;o;#0_al)A zMn*>9a5%7Y=S~EJL7X{rhR1^t5fuqd)A0E5V*rW$_VdpVPD)qIZQs6q0D$uHa(>^R zW%|tI!Gi}^)K1k?XCW7(7iCc;KRP{^@T0zDQJ`LUo4erl$xI}Ph_X;wS&7!xRscYE zcQ<5NPTB9W){=d{`s%A_YFf0c8xau|sI{0!%k(&r^}zIGa;0=3;ltmb#Oyjy2qa!6 zf5q(I1FOkZ%*;`T_K$YMBS~nUz2o-Dv&WGT5z$Jx-EIT|0XQ6v1JY)6IN`V6M7$^ojO-M?pmN!lU7K>55s-mJI?K0PN$z)mC^Q|oN3-qjK`8ZdDh=|BE)z#H$ z?{C?%CF4F8dv>wDiHN9pl$MqPNNio$v}seydqRk`t6R2h+Xf&pE6L(J&;1`EdnZCT Smx|;70000$#=vCT~j>UIysz|74oD5lhXhiBm(`a-1 z=8R7E&%F=sJbjV<;`?>Y`HKqyp=6e1CCiv(6>vQ>RD>q^v}5gJI<}V|c6xpRa%dG+ zJxFKe2=iz=>}rrj93Fo9SYKaXUJ0{v(wsBy-k-F%onNhvIVL-9ULIZXOC3=hhTwjF z1palR#Vn58o^OS!B8)Vbm+7P;46V9}lepijL=;k1Gm3?w~usxBhdH?5l_VK}k ztB1OxaXEaXJdZBQ>4j~J>D;WYZf=jo6E z{rgKCr#c6JqT#^;e>eP^%S_Z80AmO~u&D0tJ?tUaVlJRHs~X-B+%x*f>aB+qgJHE{ zR%m|k?pOCb>;2;_UgL?0u5k1Peew48@{YVwQr?8Rx@YOPf|yYSvMI%vk5V48d=$ht zdxqxqT*3HSls>&my+XyQLVMYDAmThTqwHh*p1v zJ+yji&r?ys^&mglove9qMp(5HHrs*og!ut}JD+K_mMZ)ljzaoayJql_JDEEDTGklL%y?zHP2TXVdbe3&NUZHBH> z^6_C+HV`YFH0-ID`}JkUm)xbC=lonS|LsvBd)|a(HMeJzytYX7R+>2n8_VPt$y4#I zX}tzp1wHGAOGWOQ-_cPWHYYe;%)5_SJfRgNY5v@BkmlY+yUEzA*Z_T6_h(No%)%W(6hBxK-c^DiGBD~Oi z9K%wr{4m1GV}Qi7P82k!~zdkGRV;B`BD(gLB z(@RaNO4)pd?`3bRf2#uGug);mU0cnK%I!4}Ni3{naS3^QVfjIR!-_x z6V)FZzBvM6va4Xk^M9znckPrz`&agJu2J8!Pr0DRKbq)#6H_(;jjHr=DxB&|qpIKz zfBpmL)oiYoF5V_vhyrJJe51^-hQICdo2>OXSI|ji(6@x4lkTfJ=%hMOzrrOSVhZ@y zUm$ib~(R`+@x*C@m?(#)t0J?(Ak?72ZD7I;2jUY5uEcXF_eI+>~8h> z-KIu!P3N{3)UOua9I+qc!Fhc}nXj$BFvLY(u+nNwIj%6fvi?x@T(1y+){$T$A_pmU z^zyg$LI?U&xNXbVTsn(r!(u6mkV=FP$ZIgC5RMJawOZXey4EQX)t3@kl^ zYFYv%{G6<88sbq@iR2D*xD)y>Zhn|AjOTt>%0ES~&j9!K>6s#H4e{hRgBCj2JS2=Y zYK)tR7Yblwy<7cWT5itFR*!zjHD`tU)ZMYeYR*eLb1Z|us+4E%6I9UK%>G5$mOp#LZxm&LK|2(wFl-zQ`k))Sj>hVr&h?E)z zv=6nXH?!bHma{QvG3y8_w{2Z+?&a4isB(g7!%3BMWgc#B<0j!+>xn@X-HrYEWv7s4 zU5AJ4@cv8*WPVPXxc7$xj!fkR3oXvtMOWI8o6vbRQMw_s6pGT(7hO7*CH%PpLs<@e z8FEeq-WFdA506%D%sKGae1=}F^9YJD#E8Hk+-L^ zTI&)r@y5AoMC-pVI&zv4G0l>l{jR%flj$@MXxgg#8gaH6#CTL>arCHJ9JkWWuJx6* z(#n@h2i{)KZQfmHy;tp2V_3a873i^P#B0b)!86k=8lD)utGes5;8K`VV+}-A}t?!~g6W9NIkV6d0ofT^antMs(M2QYeEp!K$~nw?52GU45X0(W-n;g4B-5 z;jD0?Ru`pl4IZaIuD6lzt|9jN(q+&!d}NW$aPscA1SaQ}+@{Tr2k!)Vb1E#6CuiD5P4*4k|~rKJs#OXm2rbmJzRULt0@8#A2{$Y;vwod0N{tvXY_R0pZiyOc{F}O9Pj2f~$Bf91%DHZ51jKEB$5n^q?;6%6SP83a(HUh^eZe?Z#*= z*45rz4gV@4P{sS%(7lI+_S<`FMI@J}?`_cH|BEuBhd4>fih+;At(f|ZqD422b{^rb zaHVl4jmb2f^k#nf^Md!C&xB1hGQfG#Q3U<3sM+kDCvpBa&!0khY4TbQiw@}HEwJjC)Xd0; zys@$ISQP7(PHuEWv8Y#rR4lr$M4}KYAe?9TuS_-n{m7;m$N3iyaa&$(8~XL_5gQIN zUYa6!P8N(hC#E_Lx)*}FHpS~FMU@z>?zMG!#N0t#F{mwYgVGW8N z+jQ62SwtDssq=2!x>rE9~K?8{v0+u_o zuKZRs*A&E9$Qgu_3&pL-9MB5IRG#UvCfAMLxyCcq+g@*5`MUL~)2bu@WV;=AFP*nZ$ zt6@7V$U|nf@wRG}OsOM&02Bas&nz`m!T!OyubjY76`)+>(KS784~n$gOds{*VWMM}GA{pm z>qnJ9T=EVBTgL#g!+3qNl$Qw$lK|ao{MHw$oB85+f-Cl;7C%lg;Sn%&?^~ms0;E1MT6Oc3 z{lq)g)}-5R0!WsWv8~oB(1{jf1NFhJOY6PEk-Wc4O|g|i$AODd6Afm6L!#F1@u@Ij z{y-J*856Q`;STfp7yul(Iq2c4KVL6AtYYw{;l6VoXmXqG(FtV(0f7}MLi7YK;$w#2 z3jm1|Msvb=qA0u`gwI0W+>9R+{SN&Izxlgi6wleLAw2CGhXF-YAjRxt0nhg{*?CS@ zFC()DxZc(G9+~z1adGW2|F2QM*&y1pw4#P&J=@#pP2FHlmQatC)V-O`7wAHP2^eV0 zFaZTyc@>a-pSxt>{VPu{lAMfCRd*e7o*?6&*Xp1leGI7!WKj~1KPumKw?O%)n9?~Z z`iq!3Z4s}9NJ(?JU6e~C#dL~!UZymLY6~PE-%Be5Pcv1H?;n_^T7W)ZP!zoOTc2GH z2{hIF%4^-StvYh5XD~y!cmKpX5o(ZRPq4_bLitCgntlALBcQd;uB2dHl}yHorXz({ zf!n0*^zjNfu2heWFq1i;XIR54z(N>sAHDQO>JVR5zoy1=*Vd5w0^NSa0?P zlWq^tz3Fg{=Zqrngw;|wphZ=B28{flJYlQR^=v9FCiE8_SgrgMx`X1%PUE7UDf}Lo zbAEV-<|bX2LyGcp(A2u4GIp$+%4Xd;Pbuy~;Mr;J@=u<;uxLN$!cL$T136eDC=}@t z*J+}o`$Jou=6l@5ueG9i48fq%0>y95OSBVb`;2f6 zOIq42#W`2vdCsz-g`!sd+ZE$PZG;7fZRgS|8GJ#-z9DPkZG?6`W4L&5cUG^6*JfV* zH|7I4TzU&KfcJ*hw%>1Q(J?-&wEw+T)_1ecanj`sA@wOBzW^bVoR07(5ZNWSBksl8 zydv4h0B|E3G{`e{7b*o@YHwPw6e+ zr1ez9VRJFTEO5fPkV=1e3)phUj#O#oETb52deEAX1>!-jK1ZCMWhP2Cu$OIbpbV4X zJ8n6^y@Mk%3NO=n5HTq_u_Xi{wDb*i61a=+51DwmY)96}k-Duft?(zImp8>?xo23g zEM@&QbfrR#`irpoD*%dM(7oKZlY>=W^Ih5KFJY)wbo}x8wsqNyny(M`HUmPx+c-fb zluDoSe^UBqK7y*MiZG}drEeoUNJtf4`WyLRA4H{>a?;qZ1kAkmwWMVrL{Fc83=KZj zeOJ~WIa;S6uZ7jw;@|W=e==y7+{2TKKi_=vlNwthUWOoPC}?;1J~%KBYcTJr8F5S@LRR1Ff*JdJL&+C0NE5FNHGWHaqGz6KFp zIL@xllqdIkywcX#nA@>1yzzAO5d-&!hw5PPr)Ih8Ug>)Dfkm^+a=fO!Vj>3u3RwrR zbHUVpgOTGC;*d8B$4jT>g1d~B5`@5PW&p&vu~8qLbUgCaD+zM#_$3kIpw4uG8mV+c zI%YLKe@eGGBQh*%Y7Rz33x|0=cngCd5q9tf`g3N4M1)+z*U&liP@mMv%eG(TnFX)& z{`fdi2c>e+LzH01k1(uEV!9@_x6;Y7_LjF&vd(mQK@f?`s=iRYmB<0d?>Ztj;$?JQLgsAUj)8A8w4V44QTb{_P*TeqQ7r1zL; z%CWRc(}?P9UwR&OWPH73Ave-Sd9kSpl22y4lKn-0AJ;p}i_A_SYlPw@5q^%-#v!$s z30Wb93?U`043JRv?zr0FMXLQHt!2Gbd*?vwm$i2Xt zG9qifO@!n^{$p^?H9 z4da5eXD5t=qAB-w5?`7rje~E7KP)WY*|S>j#JWW@c}z;gXH3nk)%aGT4jLKQHM=cb z5%Rn^+*0!~L-P6V1_j~rebuBwKjr!zRrW3U3CKLn5&3Z&h>Q6ZdRsL*9EVDInAZ2z zPr#u?!wo5Hym$J?h@Hg*sJN-hJ|d-1eVzN!oz}VYOg<7zeW|7Pd-&WAAIyQRf!kBg znq3+vRn?p>H%%^Lge94%;&=&n5sDf4uh<+BghUV0bkHvbw}Ve@ zvnPuKC+tf^`o0R9PWaFl543cTL+?(0_Lr5{`9J6dajv~=w{vb6AUp@b-yd49SS$)- z{G8n$Sz*t5gK`mv>GamMZ48F#dzWedM-(&HtJP7LWjQ84OKTSG?8a-M5R;;T`T6Zi z8-`JP6JU%@j@iS)UDMKQEYV*H}@SyCZQ? zL=@7OS`$QcJakhF*UUukyLHd>O{}@M*GIc%?!N`SNTG2^E3G|GQuU~>yxnetxic_+ zg7rE?Rra@)0@?N zk#culRPGj%SBzdug?<6PHg+JIOK|hew0Ii+wLIkcxL>4~*{UUcq2$->(H$)0(QW#| zFP(3mP`ZE>mZriZY^r(ULA)BrKN%X2$bX}A<4|`v`NM}JhAcm#urRN$(dHks zF(St|Yc%w>wa&_8?A{O42uQP+B@~`IZ6B+1pA)T4jkPfQuCgCIf2z=5%u-cMoZ#SS z`>yTBNdipKK;pfMx1+unP9t-J|N7e|^|8D;OTE&GF(NZCnMQh~Z(%6M3&!4t`f#VB z(k1)D1>3{dz)|3hYKo3Kf-4Oxd$<%9L#Ltajz5f3pBLlXO^k<#ER42fr9m+MymK8} zoyFu;gKQ2*JCCG}cxiYOLlYccL+dcrXH3nOdhKiGhCL3|RuJVE{SeVppXjoRs`Pcb z=!VK?sIQUiy>Yf9tz|W#J+B(Z2}dAzGk{oS+K+xYoB{Jcd`#(tc}U7TOK4cl4Rv5? z@MWehu>VLYb)8i@)wg>4bhr7CPks#wJPmJfs-o#$x+ve??Ic}mBfMQ>2BmNVS3wDS zmRfT+JUc8V9UX&DrCwWks=E^&+kYIN7~9DTf7m8k4Jks0liYZ!OJ*JyJfU+3JY4xw zo4a|p!t`J=jA`K(qwB1W{f!2`OEku^e$LVupZxy`z`jn*#P()0kGHgcsd~z|h{B@u zh}Zuof$k(M5*sG&J=otbo!!XD$k=AIYLDw2Ad0eRJTJK3-`Qw2y3WG7>qZ}#nmi00@!i1`%ng_KrM985xsoLuW|H(T4Et_7< zU8z{~8oXfd?Wk%buLGt|(J3y3*B%#Twcs4r#j?Z&;Axqdd^b~PsgZjg^mF(rv(u=9-`lX)Va;Z+&BXFzKqH63zI3N(L;R7{Klwou?Th5Pn@v4wxyO8o6kblTMPEmT*Cam>HPC?CLc^{kin*ITB=7`tf#3}d~ z7^5t5U)2&O>RzBKkZSaYynuc#rSn|L@AD~PQj*;czGQSnLZs*Om-Q{!(`8Xl0LKIPI&ofWX?Eh2jFoocA z9zB>EK`#xYny4Ik2b2oxS%Ws&!T#Z8C*6awPJKu#Y=)rNeW{}~L#H;|L>qTCA7I^G z>z!N`R2K`C3p8g6IaNe1?tHJb%$s`Y9D!;Nv=?{q2gGs0zGN{cKqd7*%>jGT?d(JL z4IG)L)_knEB+Tkx@)+JfFl;C5?rW zx3)E|QRyJ{=|^vbk#54wdLOjtueEO)x5L?XPxI1davZfLF;g91YDZ+02`z#e>y8?S2P1Cgd_fBwQR=EllNuORZ8`! z2|CbfZ~l!c0siE{8jhn0Xq|!Aw}!Zt9zx=oj`uP8H_Arreb25Py9c<7P81Oy!>n6h z)jY6H06lwtD=`K(flqXdJGQ_j5~aKTuI-Vl;b1*owbaX5zb5=X<(R}d3hm7Oi~lcB z#`w&U5d2!n#WV|Vm*YjlKaOQ&AI_o=&`P85hzY*G7!Ce-^t;BlXH8lPOSgnJ;89td zLiJz1&?~nbhwHtx&b5z{l~<(3?lC0+Er&gDQ^DJ=a|bI!C-8@|V$YG%EV^zQ@+4Ij zk~81Q;c>}0dm++@i2hH^7`&A?`N7>p-DirUuiY|whAfqVb)ZTF@Aw(Y6APfE{go`E z<`{vqK>V^P6Wf%v%o019hi`zS)37M%C_YD^9^I+r6NBm7U0|z|vs2ywVySoV;xC;O z^g`u1ua($4KAygbU@?C2rw;V)hI7D2zZ-bR#A6)EJ#tvz_C*$BZF6U9e5Sj8_`J0b zHava=_xlTlwfYOq8XRPP2~MTVD}(r-RrZswbW9!p)7uc-IG(C%?%4gk_hA~D z+hO1L#u?nQ)}W}Vds{4F#CJlK7qZ90`WJ(ik@`L1_H@!-IA^~sOTu|RtyYkdd%d;T zI`)h97*5A+7^D-?pT7R$vS#!$W>)OkM~G0M>4D|$e4wA(phCs{?|#Z68-~ySloIGZ z#0jp%LKzp4jebsNUM=?h%jrEwh;uWHE$O7v;r`17=>O=kZey9=6Wp`XvhqDYoi_zq zPK;D4YPx$Fz(M5gy~g}y)J?M0ebMK%(XFuSSh{>-eEKDMNug$O9V>DW6> z1Yk_CaXR(w=@F9csl`;7UNEzO%GopD2y{8!#u`j?^D`7+B~co2!$@7W4+xN=avf&t zS4+7Tg4?v0i;f?FoO)tZ6P`Hw!hqpiPmPlxuJ~*2SdGcLmGJP(--k8vF$1Qpw(eS5 zxVI(rEr^PFVplfz9-EnpIdq+|y`*x2Q0;!Kr8pK<TnbUf_(S|*%3^WJe2}4O9;PSKBsF;D7 z*67f1`9J-XEN(A9sX?^{tlF}2rA|5GgzQK4vX$+8JKoVO*c~nHmK+t84c!(xE`Qw+ zHmCaXMq%Xd){pbs!y%?72YAK?Ep%VPskLA4G>}c1^ixpN{S=A|4ceYESh)DuxnCF7 z5QRKDDrsXfXlam$l$Qlk+dxUYMlzcj13s8+9M8-)3N=s7MAP+$lRa?Z0D!9t&UcXq z#Uu$Gp~@q$k3Hob5WvQve=4g-rMoZEy}bF{Jt*lBU#-oZ9PZvqyr9C9uX=AWosHE< z2&J4;ueU+P{li(kRy$9(Jn4M|3pb{)7VeK8t@#-;N0T5^@S&?5;pfku9w<{19BHrf zkaD)gMPR`+7E<2vH+eHULqGX;$qQ>xkJ~y&aRAw^Cx#4UlJ=R3ETa`!9}7`$rhiT8`&h zcAQe+`Dz8zz{Oj4HNZG4g-E%?Vy?gaIVO57=7COkA`C*~Ihn?|;b={je#pT8 zfCZFSpGrM|DR@8EH?E6VTo>VC9ux6wW6b{yBIqX=5p;VMRBk6>_mxCO^AYbo!P2LG zYX0B2J!k&GO7ra{U1ii$)7Y5UNQs`;NNuNdk&Vms%NQ9;dH}kDv%Kk1Go}#v%(CeS z_!fwU8G2&Bn$C94+SxA#vDop)R^*srM_X!$@nqvR1c=HCEYyRq$V1#T{`)7nX{vR z+@4XSK=kdFPNGcn>?5Z>-;DWvLPxlFC{KB$X6rEy=3ct^0$$tYhNPunOjdI?c=56Q zE8urY7sA0Nf6exn@{KZ|AQ(=Di1Fu0nTsScXIesq-2`-M%els| z8OsOCN^5)X^giKxgXXdq%ut=#$CynoF%bOVXwCHCZK;SN)! z>Nl1-Nd}TfP4da6rUMUU9c=SXc>b7~Ab4dNurfj|{;jZ(OeR5Va5|`OTDJ zLNY^5hYWr|&gpFMBUT>cCLbxPH8&7w?_ge0li+O~ zAHpF4j*DRz`=KgEQiv0}uEv_XgNQTL6MeBErk`0--}v?@FKlA-3DwS@_uu>0wYa_Y z?V;tw{)@@2D3{xvduLnnFNWRtpm^e#;ptwj`-bM=*fSu%{WL{J4J^#dju|8aojE_f zp71HJw6Vib7#0Gi1~MwM5V}}}KQXUoxQXC|0VWAZcrN(-C+^OkTHB; zCGxw!SM(mJ3M;&UzsT0X^03FQ;8EB2ucX*!%DBErHv5-9G4UpypNm+YbU|G(S)bAE zI6lVI*j6gPuv=Uhv}j>oD#q%8;XO<=#~d_LHUz&rMt`&Ka5`rGkXBF{34^q6{m-9^DzMvxS4Zcnx=PqgHEZ6P19OpBRt;;U_W?Sv?#0Nm z`Sm+;8^@Myp_1tqJFdai+@Y!rVvC_axbO*~c~YKrqwBJHZwptR`bWEYAJ)PqX+A!_ zt@PcE4Z4J-XDOG>0 zyL^UDE=KjxqyLdqUMi=UZE;{fq2ZBHTw>y5-E18xYp2l>?Z&sStZV|k9zIMMH|+!9 zyW#mGhb%7IE_>9$q&Hmb~Jh(I#A4+s^^A>LF`ag|94GP+cqLMbDLq!gZ`xRglsDbxIQbsP#YXjy0;{TzBV z-fh|o6^S-(Zobdwxzx4t%90G5)_h6wVeDp??fqzHHWI}DF;os8!76K#G;Z0=*Xchb zs^#P)xYD9sJg)S#*Yy9Z8x@Nb2N1QVOdt)?zrOue5Hkl z%kzMhWEyy!={E=bZQ0%@0j*UxV}!R0-28|315Z$hRbN-<(xW^F$ZC@wNf4<+8X_j+y0eB z|FZZ4n7OShO|BTDTacgiQp*qtiZraY(D+|U(9N!!1S?nak%$Qnn+<_x$_l&A z{7bU=0zil<47+##Rm}Uh|0^MB{G|-(Gh&&sSl&!7cd?Ozb8oF0z2Q+g0>Jkf6dX%1 zQVM0bGQ? z{EwW92|?u~#QUrZi1IVMb;<6bUQdN9Gx*j0SOdc!1*~lT+@eXK88n7vym{1~{!f|am@QAO?$nF=@X97Jao8BvLaCB^ zWt0&N64$$>CMKt!ZtM@*ZMF4$H8Os#dq8+Q@ybHH1kdEW5t_9R?#TMwsy+h|hcsLf zc<$ARoXMfeLByE8wXGE_yT7on`H>Mq{xX(DJOBFc?wme##pv%9+3L!9JT?%WPG{C* z_yAck?vhydI9pc~w{qS;&io@kKeWDH8t39HD_IA9DTXH@BWoA!^T@rW8&He84+fMW zq1G?{)l<$>e>rb8OKg4c&+$La=lpLE_IJ4xg>1U|n=RM=%aIBa+zk3x>qEaVykq;R z_ApA0zX3#Wx<5?<|1X)WvqX?INWyg$hxlK%Qiu^43xRkWg}{ zz5M$d*Z*$&f8}}q$6{U7@)))^HoDwmuWUGHY;UO}wy4KT17LU}#d&3PLyxd<`p+Se z{lBHQyJBxt8l{D1~%!XS@K}vjvLV)YL9J6;MIv#b4!9 zbXsyKAo@ht*mtL5mge6bIz`SX{>al)3<~s@p)vL{eRcZro4^VLeGa4gbY)y6QqGIl zuxCbQ9aa8nE~hJrxEpe|!smK{T3h?Oj{Y?N3ls>|161>c2vEfVy%vIdQ^lfMT3QS} zFL&0H_OO9@Qt1%o1hM8;X^pQ;fx-K3RnZ^ zXy_`0Z^6C80hbEOro)gs!z^_vh?a@lpAOTIcXs&lGY=s4Z7-PtPqNuayD^#~?aMsF zC0JH^!2f59g$+J&yhnE&%*EU7PV;Afn#Vm$;)H=cDPr>;#@-jC4aM({q4w~!v*2I3K6tL?IoM^dvU8|JhPiU6K@OnJ)iw7DK?x2IOo(VRI^k;CaDk5r^%3H zrZ}xeG+V2vWr`pN#G-_@zLR*v&MAVXaab+%CYPxsO9y6K$0Ge5YA|;8<_ng~7h!mQZ6z$o z0pU3NdUH?KBnh8rW%b<+>HQxg(x`Napq;r+Guq{J-<$RR5jpBIt)Z%_X|5~rhUF)B z+5Ikv0jNXT*a4}`jkS!94I#>L^zmKZMsv3afr}X~qP^4eX{XjB&|Wxjx&ENvs^!-W z(BVR;ns({{iO)F z;@N2<ch+}R z&`#;Ph1Pf@oR-Vsc_s8NSnJ4@x7as{VNti?A{Stp$~nSoieQ;r&yQy+;Igxv4GgUb#C$q?=pH6ohE9O$_OCo^ zec^z*=!stOM_>C<+?Y6e<5rP2*ua$9*4cm(A+p?Y3?l2w@wj~FJp@!0t@^2=u?{WT~Bxoabuql zayKa&?mgZ962y?PHzT(_Y5)6WeVdG50*5Em2=k4fv)@|kx%Ir-nQ5XUC!h@pA#05e zy3Xj3-06KC_m+WMN) z>-+IRA6S<4t%rWjw(Rnt{W2>+^Y!?I1Y>FVuGIi2M(0%QrA)J{1x4xB zBhVldxd~*{Ds%P@uTp9QFir6GC;T%DWlA9uzO|(rgt7Uc1T9~L%klWnBzv_CWRgBwtS&3qrl3Z>h(xLD;jO&S^L+pYFaf!Wp7 zv?IduD@`4~_y=WHtol9rWtMv#vKIm`yDt*QLmYgPpcK;6u%Ci1&dYET>FM$$qAgx4 z$y6^tefrbcLw-JH!)~6aUKQp$jI#;{qbt%(l4G8mmivd@+uB5F7fV9cyFVi{XZ2eU zeHxkMfQ~8{D4K@zSG7>-D9-@%b;1py-6q62eME|VlI>bqVcy%S-MyQX5XT=`i-o?o zh>o0Fa1lnHGx3LO&6}`;709$R7y5WQ1Te)BH;<<|Od?|T^6Y878{h9pdMkCIp`=H; z2w-xjK0xdUZ&u=rndR*0w*NU?IE~5c!IN%sNRwyxZZ41I0%OrBc(Jcz+ZKy9>Egi} z;1f!Kko7&BIsfgafRpuWEa~FSiY$J;iX3WiNA%Lgti3GevX!hVJXhj`q|B4J?-=$L z(Urs}X&;<*gfVfxu^B=#hfS~KTKN7TWURyEz(n?3HL1(%NUrF#J!4kI{=16M{>tv# zQbF>@3rR}8`uAlVfY*x_i2|nGx96Y0MEz0o_<4qD^=>k0ca5Fz9BpgPh~+&g-M|b! z7lDeQJ#nG+=_Bmke7=d9JUA^-oxB2K=7`lb?^RhV3Z;2wJ8AK4^#<%FrkF{X|#({Q4fk699 zNsYlX$Y9RxGj*>u4SxQHO)&wQPs1V`aD%U-}w*~`~`paL0w=EM|en~MM#DhV>8x%#ZtuRt^?GoPSg z&0j(pyyvv+>XKw}bR_L7xw`QVsf0I>v5T%|*E73dSwHpuxfPwu_+bNm_ri?itaGf_ zJs7AuULX>Q#@4^hK@5g@XK5zvTSHbC>9HK@&YQnE)zUW?mcMDGNsqP?tf?+;Orra( z`ja~+MmXb&fgTL%qXa?}xsKW+jklOHQQBuwyQ|-7Yv7wfzwP~FYLhjS!;=^0PwLLr zhmeF6d#T?wOptwF12zpHWCYeX>zI>UmWo60XDEURf`Ck1baoh{y z?K4UoDYO@DK>b0!tI~I&;(_qS2RBKnDZhmSGQHK|k??^~;CxX$ytTHu@5#9_!Wa9k z*tE^Ei*`PhEaYZ#J-i3qb)N><@=eRHD(pR(o~KNy+r0Ea7L6CE1GKw^P~JA&osy*) zZ(edepKiq8O+k%TzZfp*48}?7nKRm19c`^@(@|iYZHE={a!9_D9-hx5N8W7uA-k6K z!(Z8V#!yfqZ+d}W4+0QNz0xYWoL>L#JN3+mIjJDF_sm zn}AVfk6u@e(-inHlTXt@4{5Xu@?lU+AeghoiZFelYO=nOhA;=JNTiQFaiIH@z^EAT zY-1#0_S_8Ni`Rpn$~k=#HKkVf*mkzw=j;8(H=9I0)T?5{;(KG+w>g^t zRx;&pUU$BipC?8SG|dZq_f9B2KF;zyU!bYBb*L8PIFT9iPu(N*nHjl76PMornElcB z+sLTj@7&?QmASSy<=Da%HCeij)_SW=OtE)O_9do=aqk`{{qLlGrL6rI9b%Ao)+uQs zswyMDq-|fPSP8IS6QYV`S7kI&LG?%rdlFOlZPmRzKU2b3Ql6g$JiOQMG>RbT@Ov9_ zlldcY9;HQhqRXAUnI6=u8G*)x7SwdfzFzl4f0Qq~CTJ?=z7GPYRn|%=|o1 zpGNu{waG;Uh zDm*~G`0NG-C3s$(S$Me$G%8j)Lwo!9VO(eO+WSTxGPmkYT<0tjU0W}vvd6aP_mcb0 zjNXzSlaW}tTFsC*Qpf8@@oG`P&_9SQwT=p9nvV<+@SN`#9i91H;#()Y#=d>?CtH1A zZ_LCb{!mPH4y8EwX#e|n(QX}PT-u30#;X@Gq(}mUtCkHDlbF!_;BboaPL@?*o&6)ze7wtVekhMYI zHU7QcNDy)%6vQ~*XVi~w*2*BmFK2YAA=vVe4aKET*gw;*vz}u)>y^L&$PbE^3g6Yh z7uv?C6@f|J$8bkm@~8n?B;G6*=Al+8k;jSz!|!+xzf?D(!S*3c9dB5c+p@5B^M+WL z`6h9B;(qE^9I2D(D6E}r&>-7Y54_!18uT8IDq2@1Z=!O!a^z5V!3T%2CFe@d=Ttm? znh-_#A1D<>wGTMn`qpm)6~`7ql;kJnBv$nSlqvOg-A`jrXAXs8`vade8#vN=i;uXx zpQ}f)xl{CJ2|Em1Y~@4|L2kFjXM_r^j465^w6b+Xb+xm_Sca_r`Zn-O8hyyal0P?v zuM4KiyWLi>wJX^Y!BwpGbLI9g^RM^5GyA>nRAp#?2j*jD-0WWhqTTT+*;SS?Ntjj3 zyBo9$guADwn?Z37JZlqc_ zOmCS1tM*Mr`UDpaNaXoG$V)aD0!r$sA{06mE0~TO+N)Za`b-znTx1m8G`--&Hhob6 zHCA?#Di4y@-J@lye{VY7Qbq)7j+qP^&@}xG_rn+hG$jcktr)D?Y(NAu)E>tChd5{t zzt5fWGm_p6cc{jN^=vu8O5#(C%66CFVwd2$b=V2W+v6z5ZoDLrgt4&<c<`SvKfPr88JQbgs59xaS&{H-!3Nlxe_n%xI;(Q!MgdAORvD%klua z(uHz3)J}+HpU0sZH%uoT-x@_#v-Xg~I%HutG8(#7tw+J2xvH28ddxRbmseJf z2v_%Vx6dV!w^EJY^C7d_$K=~;jZxt`*Q#m@T zPebs-C~B8Dd>Cv@0L`Bf2W`TtYU$EZ=zV`QYx~cr8;r^ALWr|ZoNK_Qn%MmZXVa+O zT99A{5X~{C_Ve7xAoG{a)XeEb%(kZ&TXSRRoDW?Q{cr1Bo^)_qtu(E;<4m)km<1TG z)TyGsNHI@C(iJXer4Xd;8t~co^AV2Yd0L$%fX;xxX{5Cr<`r0{)7T{YuDG}zMA*01 zc;1oSJssO;g#FtP!w~Rrx@Akp4El)BSi+4L4W4JLWJ&vV9JB_9X-4f3wf1oAZPu;r zKhoA8t~`-alZ@Kv0r&Zd-M0}E+6iT0K|B#$;h18!m^^ATb8IVC3Vp1s9?lmLm zfW%B|nZVk_tqLBr5h%-+*c(r z3=_>Hw|gUZ}rVLbV&OcHx>q;GO0 zWmLPnMD$CW1$uZhUno=(?|yF(N>NEn{io&&(XD~Dsdw6uq2Bd2FLnTT_6+@SXW&C@ z9mn5%LcdzQx0|q#&xuZH=owE{Sh>so*e6bJ-$*oOL_A?zFXhzCGN9SSk{@R;eE9T8 z+KcTq{~QVoIlxEuB7}sfKV+LUSEo*SHXbm&NeMwT!2EC;gT3kll^Ngp2T`d)!lq8l za3lQngHKkRui-5rUFL3J?xVS=Lo;Qbxvbd5!*}Jy{Z~o*S$wKsYtg5sgmYtcC1QD% zurF}1bQx0x0Y`f}iqQPlh1UQ2*D^!m!FdxsFtr+YzLzdnT4s|U_)xNoftd&Vy<2!F{3L?D>a zAuH!3$dp4OWP%o|va*J639s>Z%_kX_S`#6Qx>oYd*r}+@Hu-20`fICwpkAzuLG}l* zy-xNcNBZ#w5tu=}8)6?3$KYSb98?b_0fP20z6A3lajNHhcZ(MWK_|`yYoMq0P8gtB z)=d!fTw@pwpH92uEUF0?v|2Ssfiv#Aw&T^4y6eKz^NOmDfftsV$;SwxVDTqLj%WHc zuDZTL&5870O!}=v_t7tSLs!JT&&hfuA{dJ2$#Oy9p^hX(Yi+yKyfFWHh&N^ zqJGDI+_g@=5~pB?rM+C*P#ZBh0A}%r)Dzag4F&BpsoyTgY~eq;b!jCf|rPy!AMiXYA0Mr->E4aoH_J@vGlncbJdIo!*1iL!?Yh_ z=K3`}ZTK2B_uN(k-r8P+SFZ<7{j^8HnQ+A|5eICvKVt)14Tw0sO7uXd;{ztNli3j&6<7s7t>;AIY1*`aFD~lK{a^`fOe?#nVBZtagf~}~AmUC>s<;(PLniiUXT&70o zo_j*f#n=6q7AR%Q!TL2S2(VHAIZaPX(}bgAwd-bIky&HtlJJ}tLx6z)1%ux;nG(rN z6Q00aZ6t+&(*m#x_78Wx9*kj=>~F7y;dfs5Hc56@63%xc{PTV?(VUMCp-KE@y;^El zTdMnlw>g?tk7vdsVfvTbKWB65OyeRCNSMsrQdRgs(?K4v>wntdbv&-OpDWOWiH3#- z3eYoyJc2bNSvk#`!*47ys~zw8g!6oHG0lSK{@7ahb0c_g6y(wMPG!rxyc+Q^w22D5 z@C8K6Ikg|^p`bfx{L<>e_r_wQ{03{c4w=&Ae|~l16cCN#HA-M(V&MZl5D$}>Lox?c zDxS`MP`l~9X=(OYeJY2WZwsylF&#NvA9^xr!y_n&A*T^NU`-I!oq6V`8w)s1KSHyh z+{v!SdrI}lgzo)Mf#3YI1p3^2p-XC}-+NmoyDXRH(YS+%d}O1D%#hSwXf$nRkkzgH z(`-Ii)zN#c3996a%Jim431lVoJ09m{3n)NfPaJ)xk;r%6O~4=dTVg>8dPdcF>4-9O znA@=DemWQ2;(y}2w{QumwraXQ^m6K3dRm%cBuQl6c{Q_C_`-7?Y5jE9p|gP-}jwbU@b~In?$!!2&;-Ie4mcGlL0Dyz|fXt@G69+xtJk6>7l<*=q<$uk@X zkG&1P&xQ-i{)@tnF+S|QJ4Gb4zT^1Snv#)GYViYt*;iiSw=YZq#TCcsy+V{T?i`x9{6k`+y3m>4Joo2Y zsPK+fI#T=WT21^cd)M~1b+Qp}kjV!W2r~s*d=RMdv{@{T>+rDZQ|u}aB?c`%@I%_= zS1@ODgeY5jkScD^Rr&60akBz7P*Arpw{8rLE%X5@#>1g3?W^g<${g>92@+cKU)01u zGNt=fuwq<~<%#R~r{50Ho4jOdmX`glt=hxLX%tY)X=h6t8|;D@c5#&FwGyYd->U`< zYcWNp_oX)hSGX?OJnZ$1dereC*Y%A-`=l#~%@sY{Thz@1OKOQI=gi`vGEG}WuEmV7 zjc9P9K1_4h*g(nntS zYGZ+TkkgsgMKF?K0yNj2nWf}N4|0xC!H3@6Z5BxfGBrE2~n%eZaR zh$?@2^A#{!?or~JS0P+t!P-dJzAyA|LgLHRw&h*OJ(^S>tm~yURaDT4tV0iCZ)8fRH?9l}d*@5&u19mP%*eI8FP-Qqz| z=pSZl38H(T8Q1P@YD6rImRj&3yZtcVWwoen`V~5^Q}U>Q>(N*MV}R&~4JMGmXa!n%&2?T|dgF&m&(ZN?07FG>M}<;Cbsr&eUr| zqH2ybwt{>$P3(wq&3L;?%zc_z9*#muDg5q3(CYQ&(IE&IS0@P4gvZWgO*u#yPLtG8 zcOcARafP{r9+=(s(-PD|RTmD{T04@gGKF+i_6hQdWthou=so!Kr7xb=`+}z* zhhyO=tnV#s1)Zjij(wr*(%RZ-SEL$GO4%w8#Eh?!r!c6cIb` zVFdC$nTgag6aFXxJ1lnN!2fRIIR`kY0AR7Dfyr@Z-~M&s?TQ)ad+oSOl_VO@G#I;w zp^D<}#%S(QqV}ndlj+SEqL%Hfj;`M^ty9~jaq#>x;D7Lx(cDvpt1|Xa<*krjkCUwj z%Y(cY@FQQNK;9ZjjPQWW7mu(imX??Y(!0*+7BDi>)e}X(aXDXLJjJ8w`WRO*MNwPw z_4`qsjJ{Jo!!i5&4W>c!t6|jlkxs%#QC8@4!mjRUYc9hG%|9r0m-5ah_Jeo(LGs9v z;u(p=+5EzvPv?7{Bs<>)nxRb1`Z3$I_YtLExx8tcdSx!bLdF;+qXVr zH%(69c8qKm;heD)%JJ@pfh6&@Yy^00?q>kgH97OWE>q}7*DRtDDdYSlDVMr~K_PI1 zhz&!vCs71S8Yl@Oqz?8w62+xp*ov#VbQOIr@GhjiX5{>*=zBaaZJP&wt&Rqc+MYzJ z2+18uiMqZ0;o%+N-(HuQ6~*WGtP@Gf7a9E@w<)G6el;`~agAI+X*{Xi8s;&;4thxt?*TsG{+QzRN| zQ8b8AKo#sVpR<$6=4<`YXs%|=ez)OqPMC!54L;bbhMro?fIkcopTyOQPfdL!-j5s( zo{6yB8CsZ&>y47Bd_!9eWu*ST7}B*msWNjybq5)=Mj2Loomz0%phq#f6CoZcgNvUOT=>qp5Ns;~S3B~jfm24d0s=5*@PF@W zp?)_ivi}ofy^|8UYnw&_H}n6iH~swl!3yhgVyJdzlhS@(Ky0EkqVQX9DA?^xwNJ~c zqeFf|ArCP>&@5VC@YW~2v~9^?shgL^%0r23Jcr8gXEUes;TWUXh1hK1Wlc08T^OV~ zj`aF30zO%ME_)#Y$i>K*mA@l+}(A#`6 zMbnNi_KOXVkz1U;CdCpR6w~s)haJ{B=Z00++lFc9FS%^3jVfp!_&T>ZGq%j5h!CXd zWH1Xok*=}Y&E0+QDS4^X5nATNRodMuU04q-VS0nj63RmsXX-K^IopiZ-+bJ(ty`TL zcs%#VPkd`qY2Gz;B&CI)yuACANd|K{{t3pgz`OiJX~U$FmWp;F#n(2pMHY(EDw&GQ z@wAxoNxaYGfopye5@QbIx!IE*S5jsS`iZ^G(6s9KRz%vzqF=c2Gy*yh3qHqdfjh(3I616LT`Jo zQlJyY^5JCL>v}o|AYyN|vnx1t$jaY5tZ+4MtmE6G8h)R%o4osh^+cSF_R#=sqHY=S z`=yiLZz;9mN*Eylzh2kKe()ehi|a@$$G(t1To|%7sG;jmVNm!nS-$>E%|r3=nye; z)QJ#GBB4@af;Se7?5~E|Bio+AO8N_V+c^6Uchuk~LJ1o-De5bvuPTbud7^rvwI(*e z6Y1DGk&}ZLn-J2Xhn>Qw-~sW1^d7|8=oY=vU=92g^v!FkGqJ4Q`ltdUW_fuwGxJ3a z*{~vRy&PH&y5>hE8zK!|kv6MG{L2ik2%2Qkw4}8RnJ*lM~SMPp6nDqITw{I4ne z7=wWn`%$^o)NFKt2uNcJd_b*LltndzritCSe*-#5izv3#YpVKiFED$riDsFCc z`%;)|JB7_eGk*WU1AF9nVqvP^SOJ$K*w);;bfwuv(|2r&`g~rsZ@hS`<=J+~m#EE4 zqdeu)=F+jDtEA1L@r{IJ@bX0Z&Ng5Irz;y<$FAFCmRAaD%^6KD2P4VNg&d=wn#3mD zHmhbUQuTH#Yc5+)g%3>A&V>)sR#U2n9L~$;POHzYtx{vzD%zJOv8Q?zQcnn|hdjFX zfu+PhZ9{!NqPq3$jkm%1I5^#7<4gT^W%+USVU01=yL9_-<~sS$R{iwn?L>W3|0dhH zZeg=a+g$<#B-G?rD>JIF87VOSMH6UH{ zlN?)WuKXozN~6B;ce~phZ*9~-PI{fEd|KAFyNfp+5$ES!-Of1k+x7vY`~4O)MR3t; zV0hlyWHMJe5%G|}pl4H~H3m=RhAL~z-sk=~>Gu@&NE83d*+F`y?4XcbwLH2lFP{9m z0*2AJ)>7QtFMGu?ghftS??ew?%^mdM6LNx4=)2C524!EBzVweVh=IAZ;sz11!hP;p zrLb?LAN4dh&@uNF@7uGg7btHdiI6fYEAi5d86ag4#xb@!q7vNq_K&@cI14?^3z>39 zJZWhDvw`FxZD*?Sl`@FWu}#woSr*(L!@@xpGy&0V2RA(5w8^#WF#wigKe9l{>v5gz zLk$gddRu0l^N(OCX{$bSR@57>k}RMJCJNwO@10Sn^TcXLkn~4%dj0Ct!e-d<1|oye zO=&M~?+;j%jh#N2XUsZe->Zf#(x!9^)+6pd88x;|HPOidnRQP;S@oF#8|^ZibI?eC z8+oL`iD-gE0<&GS{NVhr={}O$ee|OF_xQ;wyw!SYfg|d5-4N@>49KG@weFJBg=@4O zx4HYs>iJ));XkgP3O;M+QrF7C-Kg%ExZSO7x&-TJ?_&Im<>B~xAO`{Ud@U0!mM0d} zYAOA$Y}xn&=rOwFwfLNjn|&r&S<$_J4drKjglk|4{-ZwImNoMYTSbz;y%>oy=bATO zGi}?i!VAuT!&7see7Rsf8OEI+m>7}B`Gz(k%-1#(nJ*`}XqEzS0N;O~_aL-|CM%5z zWT-qVJ#wrxsz}$vf=q~HWq3SW$k85rb~A`s%Sk=G_%GZEFJJ`hY-v16kOA$;vftZ2C9d?bRT%cmi{R>(c2V2 zy(G2rpFFqsWhOp|b28RTU8yV05+0qI-f4=`DJ|m7wF)YuiPsjg_S4`blMuBdA0OT? zE{j)qQYu)L-d#ECBI<4i^>En>RJY|0#mRU&1&bCD%Wcl3NL-6_>3e z4#aY+U7OGvEX{0HJ65hhBGW)NKZ#e|M#j_)$)Oupg(9+1ozdv1{ynJ!GRg3+p`n-y$#Sso;Xc_&} zcv8NJC!N+aHe*{AO-NuuB{R76sUmYJiIu^q!WeDsU3cZ2SlXEZ)Fa~0Zv16F2N-4Z z&!~7L*dy&cG2lv_fDF;)%RXdtUU<^-^xSZ*f`jb%2MZRlT;Ml-d8ek_?RCLjt%2s> zhv%(ZUb8=*uNQoD?CFcF;r+hv8K{?3q7PS{*BS78z~?)&UF89hs69&ZpKY@84k7;R zZFy8?paVw9D774~hY3!|1ysFuVv1{+RrrZTY)`v((2(IIxx;7XMNFVSwOOTx=wHi9 zbDFk+UFLFdOn+-5d|%1c&M;d8T)ft z>|BsOaGuGTYJtv{+PX|xqLeNB0~Azwq|%S&U`1@uLW{CqkcPabEK5xL=XaaWNsk2v zi|SwuLsv(3>3Yz5uA!7}WYIib^lz!qo`>|dTV(1{H6(zu&pB8Rcq{)U)m{c

C?7%QxgsLqyB55};4~s&0RrA=9bv&>?;63h~;^ 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 SsTj}(& + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-11-27 Meco Man porting for rt_vsnprintf as the fully functional version + */ + +/** + * @author (c) Eyal Rozenberg + * 2021, Haifa, Palestine/Israel + * @author (c) Marco Paland (info@paland.com) + * 2014-2019, PALANDesign Hannover, Germany + * + * @note Others have made smaller contributions to this file: see the + * contributors page at https://github.com/eyalroz/printf/graphs/contributors + * or ask one of the authors. + * + * @brief Small stand-alone implementation of the printf family of functions + * (`(v)printf`, `(v)s(n)printf` etc., geared towards use on embedded systems with + * a very limited resources. + * + * @note the implementations are thread-safe; re-entrant; use no functions from + * the standard library; and do not dynamically allocate any memory. + * + * @license The MIT License (MIT) + * + * 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 + +// 'ntoa' conversion buffer size, this must be big enough to hold one converted +// numeric number including padded zeros (dynamically created on stack) +#ifndef PRINTF_INTEGER_BUFFER_SIZE +#define PRINTF_INTEGER_BUFFER_SIZE 32 +#endif + +// 'ftoa' conversion buffer size, this must be big enough to hold one converted +// float number including padded zeros (dynamically created on stack) +#ifndef PRINTF_FTOA_BUFFER_SIZE +#define PRINTF_FTOA_BUFFER_SIZE 32 +#endif + +// Support for the decimal notation floating point conversion specifiers (%f, %F) +#ifndef PRINTF_SUPPORT_DECIMAL_SPECIFIERS +#define PRINTF_SUPPORT_DECIMAL_SPECIFIERS 1 +#endif + +// Support for the exponential notatin floating point conversion specifiers (%e, %g, %E, %G) +#ifndef PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS +#define PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS 1 +#endif + +// Default precision for the floating point conversion specifiers (the C standard sets this at 6) +#ifndef PRINTF_DEFAULT_FLOAT_PRECISION +#define PRINTF_DEFAULT_FLOAT_PRECISION 6 +#endif + +// According to the C languages standard, printf() and related functions must be able to print any +// integral number in floating-point notation, regardless of length, when using the %f specifier - +// possibly hundreds of characters, potentially overflowing your buffers. In this implementation, +// all values beyond this threshold are switched to exponential notation. +#ifndef PRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL +#define PRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL 9 +#endif + +// Support for the long long integral types (with the ll, z and t length modifiers for specifiers +// %d,%i,%o,%x,%X,%u, and with the %p specifier). Note: 'L' (long double) is not supported. +#ifndef PRINTF_SUPPORT_LONG_LONG +#define PRINTF_SUPPORT_LONG_LONG 1 +#endif + +#if PRINTF_SUPPORT_LONG_LONG +typedef unsigned long long printf_unsigned_value_t; +typedef long long printf_signed_value_t; +#else +typedef unsigned long printf_unsigned_value_t; +typedef long printf_signed_value_t; +#endif + +#define PRINTF_PREFER_DECIMAL false +#define PRINTF_PREFER_EXPONENTIAL true + +/////////////////////////////////////////////////////////////////////////////// + +// The following will convert the number-of-digits into an exponential-notation literal +#define PRINTF_CONCATENATE(s1, s2) s1##s2 +#define PRINTF_EXPAND_THEN_CONCATENATE(s1, s2) PRINTF_CONCATENATE(s1, s2) +#define PRINTF_FLOAT_NOTATION_THRESHOLD PRINTF_EXPAND_THEN_CONCATENATE(1e,PRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL) + +// internal flag definitions +#define FLAGS_ZEROPAD (1U << 0U) +#define FLAGS_LEFT (1U << 1U) +#define FLAGS_PLUS (1U << 2U) +#define FLAGS_SPACE (1U << 3U) +#define FLAGS_HASH (1U << 4U) +#define FLAGS_UPPERCASE (1U << 5U) +#define FLAGS_CHAR (1U << 6U) +#define FLAGS_SHORT (1U << 7U) +#define FLAGS_LONG (1U << 8U) +#define FLAGS_LONG_LONG (1U << 9U) +#define FLAGS_PRECISION (1U << 10U) +#define FLAGS_ADAPT_EXP (1U << 11U) +#define FLAGS_POINTER (1U << 12U) +// Note: Similar, but not identical, effect as FLAGS_HASH + +#define BASE_BINARY 2 +#define BASE_OCTAL 8 +#define BASE_DECIMAL 10 +#define BASE_HEX 16 + +typedef uint8_t numeric_base_t; + +#if (PRINTF_SUPPORT_DECIMAL_SPECIFIERS || PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS) +#include +#if FLT_RADIX != 2 +#error "Non-binary-radix floating-point types are unsupported." +#endif + +#if DBL_MANT_DIG == 24 + +#define DOUBLE_SIZE_IN_BITS 32 +typedef uint32_t double_uint_t; +#define DOUBLE_EXPONENT_MASK 0xFFU +#define DOUBLE_BASE_EXPONENT 127 + +#elif DBL_MANT_DIG == 53 + +#define DOUBLE_SIZE_IN_BITS 64 +typedef uint64_t double_uint_t; +#define DOUBLE_EXPONENT_MASK 0x7FFU +#define DOUBLE_BASE_EXPONENT 1023 + +#else +#error "Unsupported double type configuration" +#endif +#define DOUBLE_STORED_MANTISSA_BITS (DBL_MANT_DIG - 1) + +typedef union { + double_uint_t U; + double F; +} double_with_bit_access; + +// This is unnecessary in C99, since compound initializers can be used, +// but: 1. Some compilers are finicky about this; 2. Some people may want to convert this to C89; +// 3. If you try to use it as C++, only C++20 supports compound literals +static inline double_with_bit_access get_bit_access(double x) +{ + double_with_bit_access dwba; + dwba.F = x; + return dwba; +} + +static inline int get_sign(double x) +{ + // The sign is stored in the highest bit + return get_bit_access(x).U >> (DOUBLE_SIZE_IN_BITS - 1); +} + +static inline int get_exp2(double_with_bit_access x) +{ + // The exponent in an IEEE-754 floating-point number occupies a contiguous + // sequence of bits (e.g. 52..62 for 64-bit doubles), but with a non-trivial representation: An + // unsigned offset from some negative value (with the extremal offset values reserved for + // special use). + return (int)((x.U >> DOUBLE_STORED_MANTISSA_BITS ) & DOUBLE_EXPONENT_MASK) - DOUBLE_BASE_EXPONENT; +} +#define PRINTF_ABS(_x) ( (_x) > 0 ? (_x) : -(_x) ) + +#endif // (PRINTF_SUPPORT_DECIMAL_SPECIFIERS || PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS) + +// Note in particular the behavior here on LONG_MIN or LLONG_MIN; it is valid +// and well-defined, but if you're not careful you can easily trigger undefined +// behavior with -LONG_MIN or -LLONG_MIN +#define ABS_FOR_PRINTING(_x) ((printf_unsigned_value_t) ( (_x) > 0 ? (_x) : -((printf_signed_value_t)_x) )) + +// output function type +typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen); + + +// wrapper (used as buffer) for output function type +typedef struct { + void (*fct)(char character, void* arg); + void* arg; +} out_function_wrapper_type; + + +// internal buffer output +static inline void out_buffer(char character, void* buffer, size_t idx, size_t maxlen) +{ + if (idx < maxlen) { + ((char*)buffer)[idx] = character; + } +} + + +// internal null output +static inline void out_discard(char character, void* buffer, size_t idx, size_t maxlen) +{ + (void)character; (void)buffer; (void)idx; (void)maxlen; +} + + +// internal secure strlen +// @return The length of the string (excluding the terminating 0) limited by 'maxsize' +static inline unsigned int strnlen_s_(const char* str, size_t maxsize) +{ + const char* s; + for (s = str; *s && maxsize--; ++s); + return (unsigned int)(s - str); +} + + +// internal test if char is a digit (0-9) +// @return true if char is a digit +static inline bool is_digit_(char ch) +{ + return (ch >= '0') && (ch <= '9'); +} + + +// internal ASCII string to unsigned int conversion +static unsigned int atoi_(const char** str) +{ + unsigned int i = 0U; + while (is_digit_(**str)) { + i = i * 10U + (unsigned int)(*((*str)++) - '0'); + } + return i; +} + + +// output the specified string in reverse, taking care of any zero-padding +static size_t out_rev_(out_fct_type out, char* buffer, size_t idx, size_t maxlen, const char* buf, size_t len, unsigned int width, unsigned int flags) +{ + const size_t start_idx = idx; + + // pad spaces up to given width + if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) { + for (size_t i = len; i < width; i++) { + out(' ', buffer, idx++, maxlen); + } + } + + // reverse string + while (len) { + out(buf[--len], buffer, idx++, maxlen); + } + + // append pad spaces up to given width + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) { + out(' ', buffer, idx++, maxlen); + } + } + + return idx; +} + + +// Invoked by print_integer after the actual number has been printed, performing necessary +// work on the number's prefix (as the number is initially printed in reverse order) +static size_t print_integer_finalization(out_fct_type out, char* buffer, size_t idx, size_t maxlen, char* buf, size_t len, bool negative, numeric_base_t base, unsigned int precision, unsigned int width, unsigned int flags) +{ + size_t unpadded_len = len; + + // pad with leading zeros + { + if (!(flags & FLAGS_LEFT)) { + if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_INTEGER_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + while ((len < precision) && (len < PRINTF_INTEGER_BUFFER_SIZE)) { + buf[len++] = '0'; + } + + if (base == BASE_OCTAL && (len > unpadded_len)) { + // Since we've written some zeros, we've satisfied the alternative format leading space requirement + flags &= ~FLAGS_HASH; + } + } + + // handle hash + if (flags & (FLAGS_HASH | FLAGS_POINTER)) { + if (!(flags & FLAGS_PRECISION) && len && ((len == precision) || (len == width))) { + // Let's take back some padding digits to fit in what will eventually + // be the format-specific prefix + if (unpadded_len < len) { + len--; + } + if (len && (base == BASE_HEX)) { + if (unpadded_len < len) { + len--; + } + } + } + if ((base == BASE_HEX) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_INTEGER_BUFFER_SIZE)) { + buf[len++] = 'x'; + } + else if ((base == BASE_HEX) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_INTEGER_BUFFER_SIZE)) { + buf[len++] = 'X'; + } + else if ((base == BASE_BINARY) && (len < PRINTF_INTEGER_BUFFER_SIZE)) { + buf[len++] = 'b'; + } + if (len < PRINTF_INTEGER_BUFFER_SIZE) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_INTEGER_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } + else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } + else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return out_rev_(out, buffer, idx, maxlen, buf, len, width, flags); +} + +// An internal itoa-like function +static size_t print_integer(out_fct_type out, char* buffer, size_t idx, size_t maxlen, printf_unsigned_value_t value, bool negative, numeric_base_t base, unsigned int precision, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_INTEGER_BUFFER_SIZE]; + size_t len = 0U; + + if (!value) { + if ( !(flags & FLAGS_PRECISION) ) { + buf[len++] = '0'; + flags &= ~FLAGS_HASH; + // We drop this flag this since either the alternative and regular modes of the specifier + // don't differ on 0 values, or (in the case of octal) we've already provided the special + // handling for this mode. + } + else if (base == BASE_HEX) { + flags &= ~FLAGS_HASH; + // We drop this flag this since either the alternative and regular modes of the specifier + // don't differ on 0 values + } + } + else { + do { + const char digit = (char)(value % base); + buf[len++] = (char)(digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10); + value /= base; + } while (value && (len < PRINTF_INTEGER_BUFFER_SIZE)); + } + + return print_integer_finalization(out, buffer, idx, maxlen, buf, len, negative, base, precision, width, flags); +} + +#if (PRINTF_SUPPORT_DECIMAL_SPECIFIERS || PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS) + +struct double_components { + int_fast64_t integral; + int_fast64_t fractional; + bool is_negative; +}; + +#define NUM_DECIMAL_DIGITS_IN_INT64_T 18 +#define PRINTF_MAX_PRECOMPUTED_POWER_OF_10 NUM_DECIMAL_DIGITS_IN_INT64_T +static const double powers_of_10[NUM_DECIMAL_DIGITS_IN_INT64_T] = { + 1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, + 1e09, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17 +}; + +#define PRINTF_MAX_SUPPORTED_PRECISION NUM_DECIMAL_DIGITS_IN_INT64_T - 1 + + +// Break up a double number - which is known to be a finite non-negative number - +// into its base-10 parts: integral - before the decimal point, and fractional - after it. +// Taken the precision into account, but does not change it even internally. +static struct double_components get_components(double number, unsigned int precision) +{ + struct double_components number_; + number_.is_negative = get_sign(number); + double abs_number = (number_.is_negative) ? -number : number; + number_.integral = (int_fast64_t)abs_number; + double remainder = (abs_number - number_.integral) * powers_of_10[precision]; + number_.fractional = (int_fast64_t)remainder; + + remainder -= (double) number_.fractional; + + if (remainder > 0.5) { + ++number_.fractional; + // handle rollover, e.g. case 0.99 with precision 1 is 1.0 + if ((double) number_.fractional >= powers_of_10[precision]) { + number_.fractional = 0; + ++number_.integral; + } + } + else if (remainder == 0.5) { + if ((number_.fractional == 0U) || (number_.fractional & 1U)) { + // if halfway, round up if odd OR if last digit is 0 + ++number_.fractional; + } + } + + if (precision == 0U) { + remainder = abs_number - (double) number_.integral; + if ((!(remainder < 0.5) || (remainder > 0.5)) && (number_.integral & 1)) { + // exactly 0.5 and ODD, then round up + // 1.5 -> 2, but 2.5 -> 2 + ++number_.integral; + } + } + return number_; +} + +struct scaling_factor { + double raw_factor; + bool multiply; // if true, need to multiply by raw_factor; otherwise need to divide by it +}; + +double apply_scaling(double num, struct scaling_factor normalization) +{ + return normalization.multiply ? num * normalization.raw_factor : num / normalization.raw_factor; +} + +double unapply_scaling(double normalized, struct scaling_factor normalization) +{ + return normalization.multiply ? normalized / normalization.raw_factor : normalized * normalization.raw_factor; +} + +struct scaling_factor update_normalization(struct scaling_factor sf, double extra_multiplicative_factor) +{ + struct scaling_factor result; + if (sf.multiply) { + result.multiply = true; + result.raw_factor = sf.raw_factor * extra_multiplicative_factor; + } + else { + int factor_exp2 = get_exp2(get_bit_access(sf.raw_factor)); + int extra_factor_exp2 = get_exp2(get_bit_access(extra_multiplicative_factor)); + + // Divide the larger-exponent raw raw_factor by the smaller + if (PRINTF_ABS(factor_exp2) > PRINTF_ABS(extra_factor_exp2)) { + result.multiply = false; + result.raw_factor = sf.raw_factor / extra_multiplicative_factor; + } + else { + result.multiply = true; + result.raw_factor = extra_multiplicative_factor / sf.raw_factor; + } + } + return result; +} + +#if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS +static struct double_components get_normalized_components(bool negative, unsigned int precision, double non_normalized, struct scaling_factor normalization) +{ + struct double_components components; + components.is_negative = negative; + components.integral = (int_fast64_t) apply_scaling(non_normalized, normalization); + double remainder = non_normalized - unapply_scaling((double) components.integral, normalization); + double prec_power_of_10 = powers_of_10[precision]; + struct scaling_factor account_for_precision = update_normalization(normalization, prec_power_of_10); + double scaled_remainder = apply_scaling(remainder, account_for_precision); + double rounding_threshold = 0.5; + + if (precision == 0U) { + components.fractional = 0; + components.integral += (scaled_remainder >= rounding_threshold); + if (scaled_remainder == rounding_threshold) { + // banker's rounding: Round towards the even number (making the mean error 0) + components.integral &= ~((int_fast64_t) 0x1); + } + } + else { + components.fractional = (int_fast64_t) scaled_remainder; + scaled_remainder -= components.fractional; + + components.fractional += (scaled_remainder >= rounding_threshold); + if (scaled_remainder == rounding_threshold) { + // banker's rounding: Round towards the even number (making the mean error 0) + components.fractional &= ~((int_fast64_t) 0x1); + } + // handle rollover, e.g. the case of 0.99 with precision 1 becoming (0,100), + // and must then be corrected into (1, 0). + if ((double) components.fractional >= prec_power_of_10) { + components.fractional = 0; + ++components.integral; + } + } + return components; +} +#endif + +static size_t print_broken_up_decimal( + struct double_components number_, out_fct_type out, char *buffer, size_t idx, size_t maxlen, unsigned int precision, + unsigned int width, unsigned int flags, char *buf, size_t len) +{ + if (precision != 0U) { + // do fractional part, as an unsigned number + + unsigned int count = precision; + + if (flags & FLAGS_ADAPT_EXP && !(flags & FLAGS_HASH)) { + // %g/%G mandates we skip the trailing 0 digits... + if (number_.fractional > 0) { + while(true) { + int_fast64_t digit = number_.fractional % 10U; + if (digit != 0) { + break; + } + --count; + number_.fractional /= 10U; + } + + } + // ... and even the decimal point if there are no + // non-zero fractional part digits (see below) + } + + if (number_.fractional > 0 || !(flags & FLAGS_ADAPT_EXP) || (flags & FLAGS_HASH) ) { + while (len < PRINTF_FTOA_BUFFER_SIZE) { + --count; + buf[len++] = (char)('0' + number_.fractional % 10U); + if (!(number_.fractional /= 10U)) { + break; + } + } + // add extra 0s + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) { + buf[len++] = '0'; + } + if (len < PRINTF_FTOA_BUFFER_SIZE) { + buf[len++] = '.'; + } + } + } + else { + if (flags & FLAGS_HASH) { + if (len < PRINTF_FTOA_BUFFER_SIZE) { + buf[len++] = '.'; + } + } + } + + // Write the integer part of the number (it comes after the fractional + // since the character order is reversed) + while (len < PRINTF_FTOA_BUFFER_SIZE) { + buf[len++] = (char)('0' + (number_.integral % 10)); + if (!(number_.integral /= 10)) { + break; + } + } + + // pad leading zeros + if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) { + if (width && (number_.is_negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_FTOA_BUFFER_SIZE) { + if (number_.is_negative) { + buf[len++] = '-'; + } + else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } + else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return out_rev_(out, buffer, idx, maxlen, buf, len, width, flags); +} + + // internal ftoa for fixed decimal floating point +static size_t print_decimal_number(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double number, unsigned int precision, unsigned int width, unsigned int flags, char* buf, size_t len) +{ + struct double_components value_ = get_components(number, precision); + return print_broken_up_decimal(value_, out, buffer, idx, maxlen, precision, width, flags, buf, len); +} + +#if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS +// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse +static size_t print_exponential_number(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double number, unsigned int precision, unsigned int width, unsigned int flags, char* buf, size_t len) +{ + const bool negative = get_sign(number); + // This number will decrease gradually (by factors of 10) as we "extract" the exponent out of it + double abs_number = negative ? -number : number; + + int exp10; + bool abs_exp10_covered_by_powers_table; + struct scaling_factor normalization; + + + // Determine the decimal exponent + if (abs_number == 0.0) { + // TODO: This is a special-case for 0.0 (and -0.0); but proper handling is required for denormals more generally. + exp10 = 0; // ... and no need to set a normalization factor or check the powers table + } + else { + double_with_bit_access conv = get_bit_access(abs_number); + { + // based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c) + int exp2 = get_exp2(conv); + // drop the exponent, so conv.F comes into the range [1,2) + conv.U = (conv.U & (( (double_uint_t)(1) << DOUBLE_STORED_MANTISSA_BITS) - 1U)) | ((double_uint_t) DOUBLE_BASE_EXPONENT << DOUBLE_STORED_MANTISSA_BITS); + // now approximate log10 from the log2 integer part and an expansion of ln around 1.5 + exp10 = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168); + // now we want to compute 10^exp10 but we want to be sure it won't overflow + exp2 = (int)(exp10 * 3.321928094887362 + 0.5); + const double z = exp10 * 2.302585092994046 - exp2 * 0.6931471805599453; + const double z2 = z * z; + conv.U = ((double_uint_t)(exp2) + DOUBLE_BASE_EXPONENT) << DOUBLE_STORED_MANTISSA_BITS; + // compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex + conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14))))); + // correct for rounding errors + if (abs_number < conv.F) { + exp10--; + conv.F /= 10; + } + } + abs_exp10_covered_by_powers_table = PRINTF_ABS(exp10) < PRINTF_MAX_PRECOMPUTED_POWER_OF_10; + normalization.raw_factor = abs_exp10_covered_by_powers_table ? powers_of_10[PRINTF_ABS(exp10)] : conv.F; + } + + // We now begin accounting for the widths of the two parts of our printed field: + // the decimal part after decimal exponent extraction, and the base-10 exponent part. + // For both of these, the value of 0 has a special meaning, but not the same one: + // a 0 exponent-part width means "don't print the exponent"; a 0 decimal-part width + // means "use as many characters as necessary". + + bool fall_back_to_decimal_only_mode = false; + if (flags & FLAGS_ADAPT_EXP) { + int required_significant_digits = (precision == 0) ? 1 : (int) precision; + // Should we want to fall-back to "%f" mode, and only print the decimal part? + fall_back_to_decimal_only_mode = (exp10 >= -4 && exp10 < required_significant_digits); + // Now, let's adjust the precision + // This also decided how we adjust the precision value - as in "%g" mode, + // "precision" is the number of _significant digits_, and this is when we "translate" + // the precision value to an actual number of decimal digits. + int precision_ = (fall_back_to_decimal_only_mode) ? + (int) precision - 1 - exp10 : + (int) precision - 1; // the presence of the exponent ensures only one significant digit comes before the decimal point + precision = (precision_ > 0 ? (unsigned) precision_ : 0U); + flags |= FLAGS_PRECISION; // make sure print_broken_up_decimal respects our choice above + } + + normalization.multiply = (exp10 < 0 && abs_exp10_covered_by_powers_table); + bool should_skip_normalization = (fall_back_to_decimal_only_mode || exp10 == 0); + struct double_components decimal_part_components = + should_skip_normalization ? + get_components(negative ? -abs_number : abs_number, precision) : + get_normalized_components(negative, precision, abs_number, normalization); + + // Account for roll-over, e.g. rounding from 9.99 to 100.0 - which effects + // the exponent and may require additional tweaking of the parts + if (fall_back_to_decimal_only_mode) { + if ( (flags & FLAGS_ADAPT_EXP) && exp10 >= -1 && decimal_part_components.integral == powers_of_10[exp10 + 1]) { + exp10++; // Not strictly necessary, since exp10 is no longer really used + precision--; + // ... and it should already be the case that decimal_part_components.fractional == 0 + } + // TODO: What about rollover strictly within the fractional part? + } + else { + if (decimal_part_components.integral >= 10) { + exp10++; + decimal_part_components.integral = 1; + decimal_part_components.fractional = 0; + } + } + + // the exp10 format is "E%+03d" and largest possible exp10 value for a 64-bit double + // is "307" (for 2^1023), so we set aside 4-5 characters overall + unsigned int exp10_part_width = fall_back_to_decimal_only_mode ? 0U : (PRINTF_ABS(exp10) < 100) ? 4U : 5U; + + unsigned int decimal_part_width = + ((flags & FLAGS_LEFT) && exp10_part_width) ? + // We're padding on the right, so the width constraint is the exponent part's + // problem, not the decimal part's, so we'll use as many characters as we need: + 0U : + // We're padding on the left; so the width constraint is the decimal part's + // problem. Well, can both the decimal part and the exponent part fit within our overall width? + ((width > exp10_part_width) ? + // Yes, so we limit our decimal part's width. + // (Note this is trivially valid even if we've fallen back to "%f" mode) + width - exp10_part_width : + // No; we just give up on any restriction on the decimal part and use as many + // characters as we need + 0U); + + const size_t start_idx = idx; + idx = print_broken_up_decimal(decimal_part_components, out, buffer, idx, maxlen, precision, decimal_part_width, flags, buf, len); + + if (! fall_back_to_decimal_only_mode) { + out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen); + idx = print_integer(out, buffer, idx, maxlen, + ABS_FOR_PRINTING(exp10), + exp10 < 0, 10, 0, exp10_part_width - 1, + FLAGS_ZEROPAD | FLAGS_PLUS); + if (flags & FLAGS_LEFT) { + // We need to right-pad with spaces to meet the width requirement + while (idx - start_idx < width) out(' ', buffer, idx++, maxlen); + } + } + return idx; +} +#endif // PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS + + +static size_t print_floating_point(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int precision, unsigned int width, unsigned int flags, bool prefer_exponential) +{ + char buf[PRINTF_FTOA_BUFFER_SIZE]; + size_t len = 0U; + + // test for special values + if (value != value) + return out_rev_(out, buffer, idx, maxlen, "nan", 3, width, flags); + if (value < -DBL_MAX) + return out_rev_(out, buffer, idx, maxlen, "fni-", 4, width, flags); + if (value > DBL_MAX) + return out_rev_(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags); + + if (!prefer_exponential && ((value > PRINTF_FLOAT_NOTATION_THRESHOLD) || (value < -PRINTF_FLOAT_NOTATION_THRESHOLD))) { + // The required behavior of standard printf is to print _every_ integral-part digit -- which could mean + // printing hundreds of characters, overflowing any fixed internal buffer and necessitating a more complicated + // implementation. +#if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS + return print_exponential_number(out, buffer, idx, maxlen, value, precision, width, flags, buf, len); +#else + return 0U; +#endif + } + + // set default precision, if not set explicitly + if (!(flags & FLAGS_PRECISION)) { + precision = PRINTF_DEFAULT_FLOAT_PRECISION; + } + + // limit precision so that our integer holding the fractional part does not overflow + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (precision > PRINTF_MAX_SUPPORTED_PRECISION)) { + buf[len++] = '0'; // This respects the precision in terms of result length only + precision--; + } + + return +#if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS + prefer_exponential ? + print_exponential_number(out, buffer, idx, maxlen, value, precision, width, flags, buf, len) : +#endif + print_decimal_number(out, buffer, idx, maxlen, value, precision, width, flags, buf, len); +} + +#endif // (PRINTF_SUPPORT_DECIMAL_SPECIFIERS || PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS) + +// internal vsnprintf +static int __vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va) +{ + unsigned int flags, width, precision, n; + size_t idx = 0U; + + if (!buffer) { + // use null output function + out = out_discard; + } + + while (*format) + { + // format specifier? %[flags][width][.precision][length] + if (*format != '%') { + // no + out(*format, buffer, idx++, maxlen); + format++; + continue; + } + else { + // yes, evaluate it + format++; + } + + // evaluate flags + flags = 0U; + do { + switch (*format) { + case '0': flags |= FLAGS_ZEROPAD; format++; n = 1U; break; + case '-': flags |= FLAGS_LEFT; format++; n = 1U; break; + case '+': flags |= FLAGS_PLUS; format++; n = 1U; break; + case ' ': flags |= FLAGS_SPACE; format++; n = 1U; break; + case '#': flags |= FLAGS_HASH; format++; n = 1U; break; + default : n = 0U; break; + } + } while (n); + + // evaluate width field + width = 0U; + if (is_digit_(*format)) { + width = atoi_(&format); + } + else if (*format == '*') { + const int w = va_arg(va, int); + if (w < 0) { + flags |= FLAGS_LEFT; // reverse padding + width = (unsigned int)-w; + } + else { + width = (unsigned int)w; + } + format++; + } + + // evaluate precision field + precision = 0U; + if (*format == '.') { + flags |= FLAGS_PRECISION; + format++; + if (is_digit_(*format)) { + precision = atoi_(&format); + } + else if (*format == '*') { + const int precision_ = (int)va_arg(va, int); + precision = precision_ > 0 ? (unsigned int)precision_ : 0U; + format++; + } + } + + // evaluate length field + switch (*format) { + case 'l' : + flags |= FLAGS_LONG; + format++; + if (*format == 'l') { + flags |= FLAGS_LONG_LONG; + format++; + } + break; + case 'h' : + flags |= FLAGS_SHORT; + format++; + if (*format == 'h') { + flags |= FLAGS_CHAR; + format++; + } + break; + case 't' : + flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + case 'j' : + flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + case 'z' : + flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + default: + break; + } + + // evaluate specifier + switch (*format) { + case 'd' : + case 'i' : + case 'u' : + case 'x' : + case 'X' : + case 'o' : + case 'b' : { + // set the base + numeric_base_t base; + if (*format == 'x' || *format == 'X') { + base = BASE_HEX; + } + else if (*format == 'o') { + base = BASE_OCTAL; + } + else if (*format == 'b') { + base = BASE_BINARY; + } + else { + base = BASE_DECIMAL; + flags &= ~FLAGS_HASH; // no hash for dec format + } + // uppercase + if (*format == 'X') { + flags |= FLAGS_UPPERCASE; + } + + // no plus or space flag for u, x, X, o, b + if ((*format != 'i') && (*format != 'd')) { + flags &= ~(FLAGS_PLUS | FLAGS_SPACE); + } + + // ignore '0' flag when precision is given + if (flags & FLAGS_PRECISION) { + flags &= ~FLAGS_ZEROPAD; + } + + // convert the integer + if ((*format == 'i') || (*format == 'd')) { + // signed + if (flags & FLAGS_LONG_LONG) { +#if PRINTF_SUPPORT_LONG_LONG + const long long value = va_arg(va, long long); + idx = print_integer(out, buffer, idx, maxlen, ABS_FOR_PRINTING(value), value < 0, base, precision, width, flags); +#endif + } + else if (flags & FLAGS_LONG) { + const long value = va_arg(va, long); + idx = print_integer(out, buffer, idx, maxlen, ABS_FOR_PRINTING(value), value < 0, base, precision, width, flags); + } + else { + const int value = (flags & FLAGS_CHAR) ? (signed char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int); + idx = print_integer(out, buffer, idx, maxlen, ABS_FOR_PRINTING(value), value < 0, base, precision, width, flags); + } + } + else { + // unsigned + if (flags & FLAGS_LONG_LONG) { +#if PRINTF_SUPPORT_LONG_LONG + idx = print_integer(out, buffer, idx, maxlen, (printf_unsigned_value_t) va_arg(va, unsigned long long), false, base, precision, width, flags); +#endif + } + else if (flags & FLAGS_LONG) { + idx = print_integer(out, buffer, idx, maxlen, (printf_unsigned_value_t) va_arg(va, unsigned long), false, base, precision, width, flags); + } + else { + const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int); + idx = print_integer(out, buffer, idx, maxlen, (printf_unsigned_value_t) value, false, base, precision, width, flags); + } + } + format++; + break; + } +#if PRINTF_SUPPORT_DECIMAL_SPECIFIERS + case 'f' : + case 'F' : + if (*format == 'F') flags |= FLAGS_UPPERCASE; + idx = print_floating_point(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags, PRINTF_PREFER_DECIMAL); + format++; + break; +#endif +#if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS + case 'e': + case 'E': + case 'g': + case 'G': + if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP; + if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE; + idx = print_floating_point(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags, PRINTF_PREFER_EXPONENTIAL); + format++; + break; +#endif // PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS + case 'c' : { + unsigned int l = 1U; + // pre padding + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // char output + out((char)va_arg(va, int), buffer, idx++, maxlen); + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 's' : { + const char* p = va_arg(va, char*); + if (p == NULL) { + idx = out_rev_(out, buffer, idx, maxlen, ")llun(", 6, width, flags); + } + else { + unsigned int l = strnlen_s_(p, precision ? precision : (size_t)-1); + // pre padding + if (flags & FLAGS_PRECISION) { + l = (l < precision ? l : precision); + } + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // string output + while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) { + out(*(p++), buffer, idx++, maxlen); + } + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + } + format++; + break; + } + + case 'p' : { + width = sizeof(void*) * 2U + 2; // 2 hex chars per byte + the "0x" prefix + flags |= FLAGS_ZEROPAD | FLAGS_POINTER; + uintptr_t value = (uintptr_t)va_arg(va, void*); + idx = (value == (uintptr_t) NULL) ? + out_rev_(out, buffer, idx, maxlen, ")lin(", 5, width, flags) : + print_integer(out, buffer, idx, maxlen, (printf_unsigned_value_t) value, false, BASE_HEX, precision, width, flags); + format++; + break; + } + + case '%' : + out('%', buffer, idx++, maxlen); + format++; + break; + + default : + out(*format, buffer, idx++, maxlen); + format++; + break; + } + } + + // termination + out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen); + + // return written chars without terminating \0 + return (int)idx; +} + +/** + * This function will fill a formatted string to buffer. + * + * @param buf is the buffer to save formatted string. + * + * @param size is the size of buffer. + * + * @param fmt is the format parameters. + * + * @param args is a list of variable parameters. + * + * @return The number of characters actually written to buffer. + */ +#if (RTTHREAD_VERSION >= 40100) || (RTTHREAD_VERSION < 40000 && RTTHREAD_VERSION >= 30106) +int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list args) +#else +rt_int32_t rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list args) +#endif +{ + return __vsnprintf(out_buffer, buf, size, fmt, args); +} + +#ifdef RT_VSNPRINTF_FULL_REPLACING_VSNPRINTF +int vsnprintf(char * s, size_t n, const char * format, va_list arg) +{ + return rt_vsnprintf(s, n, format, arg); +} +#endif + +#ifdef RT_VSNPRINTF_FULL_REPLACING_VSPRINTF +int vsprintf(char * s, const char * format, va_list arg) +{ + return rt_vsprintf(s, format, arg); +} +#endif diff --git a/project.uvoptx b/project.uvoptx index ad705cd..237fb5e 100644 --- a/project.uvoptx +++ b/project.uvoptx @@ -303,8 +303,8 @@ 0 0 0 - rt-thread\components\libc\cplusplus\cxx_Semaphore.cpp - cxx_Semaphore.cpp + rt-thread\components\libc\cplusplus\cxx_Mutex.cpp + cxx_Mutex.cpp 0 0 @@ -315,20 +315,20 @@ 0 0 0 - rt-thread\components\libc\cplusplus\cxx_Thread.cpp - cxx_Thread.cpp + rt-thread\components\libc\cplusplus\cxx_Semaphore.cpp + cxx_Semaphore.cpp 0 0 2 11 - 1 + 8 0 0 0 - rt-thread\components\libc\cplusplus\cxx_crt_init.c - cxx_crt_init.c + rt-thread\components\libc\cplusplus\cxx_Thread.cpp + cxx_Thread.cpp 0 0 @@ -347,12 +347,12 @@ 2 13 - 8 + 1 0 0 0 - rt-thread\components\libc\cplusplus\cxx_Mutex.cpp - cxx_Mutex.cpp + rt-thread\components\libc\cplusplus\cxx_crt_init.c + cxx_crt_init.c 0 0 @@ -683,8 +683,8 @@ 0 0 0 - rt-thread\components\fal\src\fal.c - fal.c + rt-thread\components\fal\src\fal_partition.c + fal_partition.c 0 0 @@ -695,23 +695,23 @@ 0 0 0 - rt-thread\components\fal\src\fal_flash.c - fal_flash.c - 0 - 0 - - - 6 - 40 - 1 - 0 - 0 - 0 rt-thread\components\fal\src\fal_rtt.c fal_rtt.c 0 0 + + 6 + 40 + 1 + 0 + 0 + 0 + rt-thread\components\fal\src\fal.c + fal.c + 0 + 0 + 6 41 @@ -719,8 +719,8 @@ 0 0 0 - rt-thread\components\fal\src\fal_partition.c - fal_partition.c + rt-thread\components\fal\src\fal_flash.c + fal_flash.c 0 0 @@ -784,7 +784,7 @@ IAP - 1 + 0 0 0 0 @@ -1251,7 +1251,7 @@ - Utilities + rt_kprintf 0 0 0 @@ -1263,14 +1263,34 @@ 0 0 0 + packages\rt_vsnprintf_full-latest\rt_vsnprintf.c + rt_vsnprintf.c + 0 + 0 + + + + + Utilities + 1 + 0 + 0 + 0 + + 12 + 84 + 1 + 0 + 0 + 0 rt-thread\components\utilities\ulog\backend\console_be.c console_be.c 0 0 - 11 - 84 + 12 + 85 1 0 0 @@ -1281,8 +1301,8 @@ 0 - 11 - 85 + 12 + 86 1 0 0 diff --git a/project.uvprojx b/project.uvprojx index 1df6120..792e52b 100644 --- a/project.uvprojx +++ b/project.uvprojx @@ -82,7 +82,7 @@ 1 0 - move_lib.bat + E:\xyfc\413\work\stm32f413\move_lib.bat 0 0 @@ -428,6 +428,11 @@ CPlusPlus + + cxx_Mutex.cpp + 8 + rt-thread\components\libc\cplusplus\cxx_Mutex.cpp + cxx_Semaphore.cpp 8 @@ -438,20 +443,15 @@ 8 rt-thread\components\libc\cplusplus\cxx_Thread.cpp - - cxx_crt_init.c - 1 - rt-thread\components\libc\cplusplus\cxx_crt_init.c - cxx_crt.cpp 8 rt-thread\components\libc\cplusplus\cxx_crt.cpp - cxx_Mutex.cpp - 8 - rt-thread\components\libc\cplusplus\cxx_Mutex.cpp + cxx_crt_init.c + 1 + rt-thread\components\libc\cplusplus\cxx_crt_init.c @@ -593,6 +593,16 @@ Fal + + fal_partition.c + 1 + rt-thread\components\fal\src\fal_partition.c + + + fal_rtt.c + 1 + rt-thread\components\fal\src\fal_rtt.c + fal.c 1 @@ -603,16 +613,6 @@ 1 rt-thread\components\fal\src\fal_flash.c - - fal_rtt.c - 1 - rt-thread\components\fal\src\fal_rtt.c - - - fal_partition.c - 1 - rt-thread\components\fal\src\fal_partition.c - @@ -840,6 +840,16 @@ + + rt_kprintf + + + rt_vsnprintf.c + 1 + packages\rt_vsnprintf_full-latest\rt_vsnprintf.c + + + Utilities diff --git a/rt-thread/src/kservice.c b/rt-thread/src/kservice.c index 2fd38d3..efcc362 100644 --- a/rt-thread/src/kservice.c +++ b/rt-thread/src/kservice.c @@ -645,501 +645,6 @@ void rt_show_version(void) } RTM_EXPORT(rt_show_version); -/* private function */ -#define _ISDIGIT(c) ((unsigned)((c) - '0') < 10) - -/** - * This function will duplicate a string. - * - * @param n is the string to be duplicated. - * - * @param base is support divide instructions value. - * - * @return the duplicated string pointer. - */ -#ifdef RT_KPRINTF_USING_LONGLONG -rt_inline int divide(long long *n, int base) -#else -rt_inline int divide(long *n, int base) -#endif /* RT_KPRINTF_USING_LONGLONG */ -{ - int res; - - /* optimized for processor which does not support divide instructions. */ -#ifdef RT_KPRINTF_USING_LONGLONG - res = (int)(((unsigned long long)*n) % base); - *n = (long long)(((unsigned long long)*n) / base); -#else - res = (int)(((unsigned long)*n) % base); - *n = (long)(((unsigned long)*n) / base); -#endif - - return res; -} - -rt_inline int skip_atoi(const char **s) -{ - int i = 0; - while (_ISDIGIT(**s)) - i = i * 10 + *((*s)++) - '0'; - - return i; -} - -#define ZEROPAD (1 << 0) /* pad with zero */ -#define SIGN (1 << 1) /* unsigned/signed long */ -#define PLUS (1 << 2) /* show plus */ -#define SPACE (1 << 3) /* space if plus */ -#define LEFT (1 << 4) /* left justified */ -#define SPECIAL (1 << 5) /* 0x */ -#define LARGE (1 << 6) /* use 'ABCDEF' instead of 'abcdef' */ - -static char *print_number(char *buf, - char *end, -#ifdef RT_KPRINTF_USING_LONGLONG - long long num, -#else - long num, -#endif /* RT_KPRINTF_USING_LONGLONG */ - int base, - int s, -#ifdef RT_PRINTF_PRECISION - int precision, -#endif /* RT_PRINTF_PRECISION */ - int type) -{ - char c, sign; -#ifdef RT_KPRINTF_USING_LONGLONG - char tmp[64]; -#else - char tmp[32]; -#endif /* RT_KPRINTF_USING_LONGLONG */ - int precision_bak = precision; - const char *digits; - static const char small_digits[] = "0123456789abcdef"; - static const char large_digits[] = "0123456789ABCDEF"; - int i, size; - - size = s; - - digits = (type & LARGE) ? large_digits : small_digits; - if (type & LEFT) - type &= ~ZEROPAD; - - c = (type & ZEROPAD) ? '0' : ' '; - - /* get sign */ - sign = 0; - if (type & SIGN) - { - if (num < 0) - { - sign = '-'; - num = -num; - } - else if (type & PLUS) - sign = '+'; - else if (type & SPACE) - sign = ' '; - } - -#ifdef RT_PRINTF_SPECIAL - if (type & SPECIAL) - { - if (base == 2 || base == 16) - size -= 2; - else if (base == 8) - size--; - } -#endif /* RT_PRINTF_SPECIAL */ - - i = 0; - if (num == 0) - tmp[i++] = '0'; - else - { - while (num != 0) - tmp[i++] = digits[divide(&num, base)]; - } - -#ifdef RT_PRINTF_PRECISION - if (i > precision) - precision = i; - size -= precision; -#else - size -= i; -#endif /* RT_PRINTF_PRECISION */ - - if (!(type & (ZEROPAD | LEFT))) - { - if ((sign) && (size > 0)) - size--; - - while (size-- > 0) - { - if (buf < end) - *buf = ' '; - ++ buf; - } - } - - if (sign) - { - if (buf < end) - { - *buf = sign; - } - -- size; - ++ buf; - } - -#ifdef RT_PRINTF_SPECIAL - if (type & SPECIAL) - { - if (base == 2) - { - if (buf < end) - *buf = '0'; - ++ buf; - if (buf < end) - *buf = 'b'; - ++ buf; - } - else if (base == 8) - { - if (buf < end) - *buf = '0'; - ++ buf; - } - else if (base == 16) - { - if (buf < end) - *buf = '0'; - ++ buf; - if (buf < end) - { - *buf = type & LARGE ? 'X' : 'x'; - } - ++ buf; - } - } -#endif /* RT_PRINTF_SPECIAL */ - - /* no align to the left */ - if (!(type & LEFT)) - { - while (size-- > 0) - { - if (buf < end) - *buf = c; - ++ buf; - } - } - -#ifdef RT_PRINTF_PRECISION - while (i < precision--) - { - if (buf < end) - *buf = '0'; - ++ buf; - } -#endif /* RT_PRINTF_PRECISION */ - - /* put number in the temporary buffer */ - while (i-- > 0 && (precision_bak != 0)) - { - if (buf < end) - *buf = tmp[i]; - ++ buf; - } - - while (size-- > 0) - { - if (buf < end) - *buf = ' '; - ++ buf; - } - - return buf; -} - -/** - * This function will fill a formatted string to buffer. - * - * @param buf is the buffer to save formatted string. - * - * @param size is the size of buffer. - * - * @param fmt is the format parameters. - * - * @param args is a list of variable parameters. - * - * @return The number of characters actually written to buffer. - */ -RT_WEAK int rt_vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list args) -{ -#ifdef RT_KPRINTF_USING_LONGLONG - unsigned long long num; -#else - rt_uint32_t num; -#endif /* RT_KPRINTF_USING_LONGLONG */ - int i, len; - char *str, *end, c; - const char *s; - - rt_uint8_t base; /* the base of number */ - rt_uint8_t flags; /* flags to print number */ - rt_uint8_t qualifier; /* 'h', 'l', or 'L' for integer fields */ - rt_int32_t field_width; /* width of output field */ - -#ifdef RT_PRINTF_PRECISION - int precision; /* min. # of digits for integers and max for a string */ -#endif /* RT_PRINTF_PRECISION */ - - str = buf; - end = buf + size; - - /* Make sure end is always >= buf */ - if (end < buf) - { - end = ((char *) - 1); - size = end - buf; - } - - for (; *fmt ; ++fmt) - { - if (*fmt != '%') - { - if (str < end) - *str = *fmt; - ++ str; - continue; - } - - /* process flags */ - flags = 0; - - while (1) - { - /* skips the first '%' also */ - ++ fmt; - if (*fmt == '-') flags |= LEFT; - else if (*fmt == '+') flags |= PLUS; - else if (*fmt == ' ') flags |= SPACE; - else if (*fmt == '#') flags |= SPECIAL; - else if (*fmt == '0') flags |= ZEROPAD; - else break; - } - - /* get field width */ - field_width = -1; - if (_ISDIGIT(*fmt)) field_width = skip_atoi(&fmt); - else if (*fmt == '*') - { - ++ fmt; - /* it's the next argument */ - field_width = va_arg(args, int); - if (field_width < 0) - { - field_width = -field_width; - flags |= LEFT; - } - } - -#ifdef RT_PRINTF_PRECISION - /* get the precision */ - precision = -1; - if (*fmt == '.') - { - ++ fmt; - if (_ISDIGIT(*fmt)) precision = skip_atoi(&fmt); - else if (*fmt == '*') - { - ++ fmt; - /* it's the next argument */ - precision = va_arg(args, int); - } - if (precision < 0) precision = 0; - } -#endif /* RT_PRINTF_PRECISION */ - /* get the conversion qualifier */ - qualifier = 0; -#ifdef RT_KPRINTF_USING_LONGLONG - if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') -#else - if (*fmt == 'h' || *fmt == 'l') -#endif /* RT_KPRINTF_USING_LONGLONG */ - { - qualifier = *fmt; - ++ fmt; -#ifdef RT_KPRINTF_USING_LONGLONG - if (qualifier == 'l' && *fmt == 'l') - { - qualifier = 'L'; - ++ fmt; - } -#endif /* RT_KPRINTF_USING_LONGLONG */ - } - - /* the default base */ - base = 10; - - switch (*fmt) - { - case 'c': - if (!(flags & LEFT)) - { - while (--field_width > 0) - { - if (str < end) *str = ' '; - ++ str; - } - } - - /* get character */ - c = (rt_uint8_t)va_arg(args, int); - if (str < end) *str = c; - ++ str; - - /* put width */ - while (--field_width > 0) - { - if (str < end) *str = ' '; - ++ str; - } - continue; - - case 's': - s = va_arg(args, char *); - if (!s) s = "(NULL)"; - - for (len = 0; (len != field_width) && (s[len] != '\0'); len++); -#ifdef RT_PRINTF_PRECISION - if (precision > 0 && len > precision) len = precision; -#endif /* RT_PRINTF_PRECISION */ - - if (!(flags & LEFT)) - { - while (len < field_width--) - { - if (str < end) *str = ' '; - ++ str; - } - } - - for (i = 0; i < len; ++i) - { - if (str < end) *str = *s; - ++ str; - ++ s; - } - - while (len < field_width--) - { - if (str < end) *str = ' '; - ++ str; - } - continue; - - case 'p': - if (field_width == -1) - { - field_width = sizeof(void *) << 1; - flags |= ZEROPAD; - } -#ifdef RT_PRINTF_PRECISION - str = print_number(str, end, - (long)va_arg(args, void *), - 16, field_width, precision, flags); -#else - str = print_number(str, end, - (long)va_arg(args, void *), - 16, field_width, flags); -#endif /* RT_PRINTF_PRECISION */ - continue; - - case '%': - if (str < end) *str = '%'; - ++ str; - continue; - - /* integer number formats - set up the flags and "break" */ - case 'b': - base = 2; - break; - case 'o': - base = 8; - break; - - case 'X': - flags |= LARGE; - case 'x': - base = 16; - break; - - case 'd': - case 'i': - flags |= SIGN; - case 'u': - break; - - default: - if (str < end) *str = '%'; - ++ str; - - if (*fmt) - { - if (str < end) *str = *fmt; - ++ str; - } - else - { - -- fmt; - } - continue; - } - -#ifdef RT_KPRINTF_USING_LONGLONG - if (qualifier == 'L') num = va_arg(args, long long); - else if (qualifier == 'l') -#else - if (qualifier == 'l') -#endif /* RT_KPRINTF_USING_LONGLONG */ - { - num = va_arg(args, rt_uint32_t); - if (flags & SIGN) num = (rt_int32_t)num; - } - else if (qualifier == 'h') - { - num = (rt_uint16_t)va_arg(args, int); - if (flags & SIGN) num = (rt_int16_t)num; - } - else - { - num = va_arg(args, rt_uint32_t); - if (flags & SIGN) num = (rt_int32_t)num; - } -#ifdef RT_PRINTF_PRECISION - str = print_number(str, end, num, base, field_width, precision, flags); -#else - str = print_number(str, end, num, base, field_width, flags); -#endif /* RT_PRINTF_PRECISION */ - } - - if (size > 0) - { - if (str < end) *str = '\0'; - else - { - end[-1] = '\0'; - } - } - - /* the trailing null byte doesn't count towards the total - * ++str; - */ - return str - buf; -} RTM_EXPORT(rt_vsnprintf); /** diff --git a/rtconfig.h b/rtconfig.h index bcd4247..a915ab7 100644 --- a/rtconfig.h +++ b/rtconfig.h @@ -124,6 +124,7 @@ /* log format */ +#define ULOG_OUTPUT_FLOAT #define ULOG_USING_COLOR #define ULOG_OUTPUT_TIME #define ULOG_OUTPUT_LEVEL @@ -175,6 +176,8 @@ /* enhanced kernel services */ +#define PKG_USING_RT_VSNPRINTF_FULL +#define PKG_USING_RT_VSNPRINTF_FULL_LATEST_VERSION /* acceleration: Assembly language or algorithmic acceleration packages */ @@ -187,6 +190,11 @@ /* peripheral libraries and drivers */ +/* sensors drivers */ + + +/* touch drivers */ + /* Kendryte SDK */ @@ -194,6 +202,9 @@ /* AI packages */ +/* Signal Processing and Control Algorithm Packages */ + + /* miscellaneous packages */ /* project laboratory */ @@ -207,6 +218,9 @@ /* Arduino libraries */ +/* Projects */ + + /* Sensors */ @@ -216,7 +230,23 @@ /* Timing */ -/* Projects */ +/* Data Processing */ + + +/* Data Storage */ + +/* Communication */ + + +/* Device Control */ + + +/* Other */ + +/* Signal IO */ + + +/* Uncategorized */ #define SOC_FAMILY_STM32 #define SOC_SERIES_STM32F4