diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 05e193f0e9..1905b233cf 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,9 +8,9 @@ repos: hooks: - id: check-yaml - id: end-of-file-fixer - exclude: '^(tests/.*\.toml|tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*|ports/espressif/esp-idf-config/.*|ports/espressif/boards/.*/sdkconfig)' + exclude: '^(tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*|ports/espressif/esp-idf-config/.*|ports/espressif/boards/.*/sdkconfig)' - id: trailing-whitespace - exclude: '^(tests/.*\.toml|tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*|lib/mbedtls_errors/.*)' + exclude: '^(tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*|lib/mbedtls_errors/.*)' - repo: local hooks: - id: translations diff --git a/ports/unix/main.c b/ports/unix/main.c index e423634e58..5ebcf9193b 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -420,13 +420,6 @@ STATIC void set_sys_argv(char *argv[], int argc, int start_arg) { #define PATHLIST_SEP_CHAR ':' #endif -mp_obj_t common_hal_os_getenv_path(const char *path, const char *key, mp_obj_t default_); -STATIC mp_obj_t getenv_from_file(mp_obj_t path_in, mp_obj_t key_to_get_in) { - return common_hal_os_getenv_path(mp_obj_str_get_str(path_in), - mp_obj_str_get_str(key_to_get_in), mp_const_none); -} -MP_DEFINE_CONST_FUN_OBJ_2(getenv_from_file_obj, getenv_from_file); - MP_NOINLINE int main_(int argc, char **argv); int main(int argc, char **argv) { @@ -547,7 +540,6 @@ MP_NOINLINE int main_(int argc, char **argv) { MP_DECLARE_CONST_FUN_OBJ_0(extra_cpp_coverage_obj); mp_store_global(MP_QSTR_extra_coverage, MP_OBJ_FROM_PTR(&extra_coverage_obj)); mp_store_global(MP_QSTR_extra_cpp_coverage, MP_OBJ_FROM_PTR(&extra_cpp_coverage_obj)); - mp_store_global(MP_QSTR_getenv_from_file, MP_OBJ_FROM_PTR(&getenv_from_file_obj)); } #endif diff --git a/ports/unix/modos.c b/ports/unix/modos.c index 6241dfa6c3..deea3bfc91 100644 --- a/ports/unix/modos.c +++ b/ports/unix/modos.c @@ -193,7 +193,12 @@ STATIC mp_obj_t mod_os_system(mp_obj_t cmd_in) { } MP_DEFINE_CONST_FUN_OBJ_1(mod_os_system_obj, mod_os_system); +mp_obj_t common_hal_os_getenv(const char *key, mp_obj_t default_); STATIC mp_obj_t mod_os_getenv(mp_obj_t var_in) { + mp_obj_t result = common_hal_os_getenv(mp_obj_str_get_str(var_in), mp_const_none); + if (result != mp_const_none) { + return result; + } const char *s = getenv(mp_obj_str_get_str(var_in)); if (s == NULL) { return mp_const_none; diff --git a/shared-module/os/getenv.c b/shared-module/os/getenv.c index 09dc19748d..0112a8a5cd 100644 --- a/shared-module/os/getenv.c +++ b/shared-module/os/getenv.c @@ -39,43 +39,29 @@ #include "supervisor/filesystem.h" #include "supervisor/memory.h" -#define GETENV_PATH "settings.toml" +#define GETENV_PATH "/settings.toml" -#if defined(UNIX) -typedef FILE *file_arg; -STATIC bool open_file(const char *name, file_arg *active_file) { - FILE *result = fopen(name, "r"); - if (result) { - *active_file = result; - } - return result != NULL; -} -STATIC void close_file(file_arg *active_file) { - fclose(*active_file); -} -STATIC bool is_eof(file_arg *active_file) { - return feof(*active_file); -} -STATIC uint8_t get_next_byte(file_arg *active_file) { - int value = fgetc(*active_file); - if (value == EOF) { - return 0; - } - return value; -} -__attribute__((unused)) -STATIC void seek_eof(file_arg *active_file) { - fseek(*active_file, 0, SEEK_END); - (void)fgetc(*active_file); -} -#else #include "extmod/vfs.h" #include "extmod/vfs_fat.h" typedef FIL file_arg; STATIC bool open_file(const char *name, file_arg *active_file) { + #if defined(UNIX) + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_obj_t file_obj = mp_call_function_2(MP_OBJ_FROM_PTR(&mp_builtin_open_obj), mp_obj_new_str(name, strlen(name)), MP_ROM_QSTR(MP_QSTR_rb)); + mp_arg_validate_type(file_obj, &mp_type_vfs_fat_fileio, MP_QSTR_file); + pyb_file_obj_t *file = MP_OBJ_TO_PTR(file_obj); + *active_file = file->fp; + nlr_pop(); + return true; + } else { + return false; + } + #else FATFS *fs = filesystem_circuitpy(); FRESULT result = f_open(fs, active_file, name, FA_READ); return result == FR_OK; + #endif } STATIC void close_file(file_arg *active_file) { // nothing @@ -95,7 +81,6 @@ STATIC uint8_t get_next_byte(FIL *active_file) { STATIC void seek_eof(file_arg *active_file) { f_lseek(active_file, f_size(active_file)); } -#endif // For a fixed buffer, record the required size rather than throwing STATIC void vstr_add_byte_nonstd(vstr_t *vstr, byte b) { @@ -363,7 +348,7 @@ mp_obj_t common_hal_os_getenv_path(const char *path, const char *key, mp_obj_t d vstr_init(&buf, 64); os_getenv_err_t result = os_getenv_vstr(path, key, &buf, "ed); - if (result == GETENV_ERR_NOT_FOUND) { + if (result == GETENV_ERR_NOT_FOUND || result == GETENV_ERR_OPEN) { return default_; } throw_getenv_error(result); diff --git a/tests/circuitpython/bad1.toml b/tests/circuitpython/bad1.toml deleted file mode 100644 index fce8db1800..0000000000 --- a/tests/circuitpython/bad1.toml +++ /dev/null @@ -1 +0,0 @@ -string = " diff --git a/tests/circuitpython/bad2.toml b/tests/circuitpython/bad2.toml deleted file mode 100644 index 666c573716..0000000000 --- a/tests/circuitpython/bad2.toml +++ /dev/null @@ -1 +0,0 @@ -string = """ diff --git a/tests/circuitpython/bad3.toml b/tests/circuitpython/bad3.toml deleted file mode 100644 index 705443a1c6..0000000000 --- a/tests/circuitpython/bad3.toml +++ /dev/null @@ -1 +0,0 @@ -string = diff --git a/tests/circuitpython/bad4.toml b/tests/circuitpython/bad4.toml deleted file mode 100644 index befe224084..0000000000 --- a/tests/circuitpython/bad4.toml +++ /dev/null @@ -1 +0,0 @@ -string=" \ No newline at end of file diff --git a/tests/circuitpython/getenv_test.py b/tests/circuitpython/getenv_test.py index d3735cc260..2f80e465e3 100644 --- a/tests/circuitpython/getenv_test.py +++ b/tests/circuitpython/getenv_test.py @@ -1,20 +1,78 @@ -def run_test(f, k=None): +import uos + +uos.umount("/") + + +class RAMBlockDevice: + ERASE_BLOCK_SIZE = 512 + + def __init__(self, blocks): + self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE) + + def readblocks(self, block, buf, off=0): + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + buf[i] = self.data[addr + i] + + def writeblocks(self, block, buf, off=None): + if off is None: + # erase, then write + off = 0 + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + self.data[addr + i] = buf[i] + + def ioctl(self, op, arg): + if op == 4: # block count + return len(self.data) // self.ERASE_BLOCK_SIZE + if op == 5: # block size + return self.ERASE_BLOCK_SIZE + if op == 6: # erase block + return 0 + + +bdev = RAMBlockDevice(64) +uos.VfsFat.mkfs(bdev) +uos.mount(uos.VfsFat(bdev), "/") + +content_good = """ +# comment +key0 = "hello world" +key1 = 7 + cstring = "hello comment" # comment + cnumber = 0x7f # comment +key2= "\n" +key3 ="\u00c1x" +key4 = "\U000000c1x" +key5 = "\f\"\\" +key6 = "\t\r\b" +key7 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +key8 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +[section] +subvalue = "hi" +""" + +content_bad = [ + 'key = "\n', + 'key = """\n', + "key =\n", + 'key="', +] + + +def run_test(key, content): + with open("/settings.toml", "w") as f: + f.write(content) + try: - v = getenv_from_file(f"{BASE}/{f}.toml", k or f) - print(f, k, repr(v)) + v = uos.getenv(key) + print(key, repr(v)) except Exception as e: - print(f, k, str(e)) + print(key, str(e)) -BASE = __file__.rpartition("/")[0] or "." +for i in range(9): + run_test(f"key{i}", content_good) -run_test("good", "notpresent") -run_test("good", "string") -run_test("good", "number") -run_test("good", "cstring") -run_test("good", "cnumber") -run_test("good", "subvalue") -for i in range(8): - run_test("good", f"string{i}") -for i in range(1, 5): - run_test(f"bad{i}", f"string") +for content in content_bad: + run_test("key", content) diff --git a/tests/circuitpython/getenv_test.py.exp b/tests/circuitpython/getenv_test.py.exp index e7c58666c2..b09c376d19 100644 --- a/tests/circuitpython/getenv_test.py.exp +++ b/tests/circuitpython/getenv_test.py.exp @@ -1,18 +1,13 @@ -good.toml notpresent None -good.toml string 'hello world' -good.toml number 7 -good.toml cstring 'hello comment' -good.toml cnumber 127 -good.toml subvalue None -good.toml string0 None -good.toml string1 '\n' -good.toml string2 'Áx' -good.toml string3 'Áx' -good.toml string4 '\x0c"\\' -good.toml string5 '\t\r\x08' -good.toml string6 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' -good.toml string7 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' -bad1.toml.bin string Invalid byte '\n' -bad2.toml.bin string Invalid byte '"' -bad3.toml.bin string invalid syntax for integer with base 10: '' -bad4.toml.bin string Invalid byte 'EOF' +key0 'hello world' +key1 7 +key2 Invalid byte '\n' +key3 'Áx' +key4 'Áx' +key5 Invalid byte '\\' +key6 '\t\r\x08' +key7 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' +key8 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' +key Invalid byte '\n' +key Invalid byte '"' +key invalid syntax for integer with base 10: '' +key Invalid byte 'EOF' diff --git a/tests/circuitpython/good.toml b/tests/circuitpython/good.toml deleted file mode 100644 index 17e5c054f4..0000000000 --- a/tests/circuitpython/good.toml +++ /dev/null @@ -1,14 +0,0 @@ -# comment -string = "hello world" -number = 7 - cstring = "hello comment" # comment - cnumber = 0x7f # comment -string1= "\n" -string2 ="\u00c1x" -string3 = "\U000000c1x" -string4 = "\f\"\\" -string5 = "\t\r\b" -string6 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -string7 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -[section] -subvalue = "hi"