diff options
Diffstat (limited to 'libctf')
-rw-r--r-- | libctf/ChangeLog | 25 | ||||
-rw-r--r-- | libctf/ctf-create.c | 94 | ||||
-rw-r--r-- | libctf/ctf-impl.h | 3 | ||||
-rw-r--r-- | libctf/ctf-serialize.c | 39 | ||||
-rw-r--r-- | libctf/ctf-string.c | 17 | ||||
-rw-r--r-- | libctf/ctf-types.c | 110 | ||||
-rw-r--r-- | libctf/testsuite/libctf-lookup/enum-many-ctf.c | 10 | ||||
-rw-r--r-- | libctf/testsuite/libctf-lookup/enum-many.lk | 101 |
8 files changed, 277 insertions, 122 deletions
diff --git a/libctf/ChangeLog b/libctf/ChangeLog index b4da040..fa333d5 100644 --- a/libctf/ChangeLog +++ b/libctf/ChangeLog @@ -1,5 +1,30 @@ 2021-03-18 Nick Alcock <nick.alcock@oracle.com> + * ctf-impl.h (ctf_dtdef_t) <dtd_vlen_alloc>: New. + (ctf_str_move_pending): Declare. + * ctf-string.c (ctf_str_add_ref_internal): Fix error return. + (ctf_str_move_pending): New. + * ctf-create.c (ctf_grow_vlen): New. + (ctf_dtd_delete): Zero out the vlen_alloc after free. Free the + vlen later: iterate over it and free enum name refs first. + (ctf_add_generic): Populate dtd_vlen_alloc from vlen. + (ctf_add_enum): populate the vlen; do it by hand if promoting + forwards. + (ctf_add_enumerator): Set up the vlen rather than the dmd. Expand + it as needed, repointing string refs via ctf_str_move_pending. Add + the enumerand names as pending strings. + * ctf-serialize.c (ctf_copy_emembers): Remove. + (ctf_emit_type_sect): Copy the vlen into place and ref the + strings. + * ctf-types.c (ctf_enum_next): The dynamic portion now uses + the same code as the non-dynamic. + (ctf_enum_name): Likewise. + (ctf_enum_value): Likewise. + * testsuite/libctf-lookup/enum-many-ctf.c: New test. + * testsuite/libctf-lookup/enum-many.lk: New test. + +2021-03-18 Nick Alcock <nick.alcock@oracle.com> + * ctf-hash.c (ctf_dynset_elements): New. * ctf-impl.h (ctf_dynset_elements): Declare it. (ctf_str_add_pending): Likewise. diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c index ea2c148..3218e3e 100644 --- a/libctf/ctf-create.c +++ b/libctf/ctf-create.c @@ -64,6 +64,30 @@ ctf_grow_ptrtab (ctf_dict_t *fp) return 0; } +/* Make sure a vlen has enough space: expand it otherwise. Unlike the ptrtab, + which grows quite slowly, the vlen grows in big jumps because it is quite + expensive to expand: the caller has to scan the old vlen for string refs + first and remove them, then re-add them afterwards. The initial size is + more or less arbitrary. */ +static int +ctf_grow_vlen (ctf_dict_t *fp, ctf_dtdef_t *dtd, size_t vlen) +{ + unsigned char *old = dtd->dtd_vlen; + + if (dtd->dtd_vlen_alloc > vlen) + return 0; + + if ((dtd->dtd_vlen = realloc (dtd->dtd_vlen, + dtd->dtd_vlen_alloc * 2)) == NULL) + { + dtd->dtd_vlen = old; + return (ctf_set_errno (fp, ENOMEM)); + } + memset (dtd->dtd_vlen + dtd->dtd_vlen_alloc, 0, dtd->dtd_vlen_alloc); + dtd->dtd_vlen_alloc *= 2; + return 0; +} + /* To create an empty CTF dict, we just declare a zeroed header and call ctf_bufopen() on it. If ctf_bufopen succeeds, we mark the new dict r/w and initialize the dynamic members. We start assigning type IDs at 1 because @@ -222,17 +246,16 @@ ctf_dtd_delete (ctf_dict_t *fp, ctf_dtdef_t *dtd) { ctf_dmdef_t *dmd, *nmd; int kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info); + size_t vlen = LCTF_INFO_VLEN (fp, dtd->dtd_data.ctt_info); int name_kind = kind; const char *name; ctf_dynhash_remove (fp->ctf_dthash, (void *) (uintptr_t) dtd->dtd_type); - free (dtd->dtd_vlen); switch (kind) { case CTF_K_STRUCT: case CTF_K_UNION: - case CTF_K_ENUM: for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members); dmd != NULL; dmd = nmd) { @@ -242,10 +265,22 @@ ctf_dtd_delete (ctf_dict_t *fp, ctf_dtdef_t *dtd) free (dmd); } break; + case CTF_K_ENUM: + { + ctf_enum_t *en = (ctf_enum_t *) dtd->dtd_vlen; + size_t i; + + for (i = 0; i < vlen; i++) + ctf_str_remove_ref (fp, ctf_strraw (fp, en[i].cte_name), + &en[i].cte_name); + } + break; case CTF_K_FORWARD: name_kind = dtd->dtd_data.ctt_type; break; } + free (dtd->dtd_vlen); + dtd->dtd_vlen_alloc = 0; if (dtd->dtd_data.ctt_name && (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL @@ -402,6 +437,9 @@ ctf_rollback (ctf_dict_t *fp, ctf_snapshot_id_t id) return 0; } +/* Note: vlen is the amount of space *allocated* for the vlen. It may well not + be the amount of space used (yet): the space used is declared in per-kind + fashion in the dtd_data's info word. */ static ctf_id_t ctf_add_generic (ctf_dict_t *fp, uint32_t flag, const char *name, int kind, size_t vlen, ctf_dtdef_t **rp) @@ -428,6 +466,7 @@ ctf_add_generic (ctf_dict_t *fp, uint32_t flag, const char *name, int kind, if ((dtd = calloc (1, sizeof (ctf_dtdef_t))) == NULL) return (ctf_set_errno (fp, EAGAIN)); + dtd->dtd_vlen_alloc = vlen; if (vlen > 0) { if ((dtd->dtd_vlen = calloc (1, vlen)) == NULL) @@ -831,6 +870,7 @@ ctf_add_enum (ctf_dict_t *fp, uint32_t flag, const char *name) { ctf_dtdef_t *dtd; ctf_id_t type = 0; + size_t initial_vlen = sizeof (ctf_enum_t) * 16; /* Promote root-visible forwards to enums. */ if (name != NULL) @@ -839,9 +879,17 @@ ctf_add_enum (ctf_dict_t *fp, uint32_t flag, const char *name) if (type != 0 && ctf_type_kind (fp, type) == CTF_K_FORWARD) dtd = ctf_dtd_lookup (fp, type); else if ((type = ctf_add_generic (fp, flag, name, CTF_K_ENUM, - 0, &dtd)) == CTF_ERR) + initial_vlen, &dtd)) == CTF_ERR) return CTF_ERR; /* errno is set for us. */ + /* Forwards won't have any vlen yet. */ + if (dtd->dtd_vlen_alloc == 0) + { + if ((dtd->dtd_vlen = calloc (1, initial_vlen)) == NULL) + return (ctf_set_errno (fp, ENOMEM)); + dtd->dtd_vlen_alloc = initial_vlen; + } + dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_ENUM, flag, 0); dtd->dtd_data.ctt_size = fp->ctf_dmodel->ctd_int; @@ -956,10 +1004,11 @@ ctf_add_enumerator (ctf_dict_t *fp, ctf_id_t enid, const char *name, int value) { ctf_dtdef_t *dtd = ctf_dtd_lookup (fp, enid); - ctf_dmdef_t *dmd; + unsigned char *old_vlen; + ctf_enum_t *en; + size_t i; uint32_t kind, vlen, root; - char *s; if (name == NULL) return (ctf_set_errno (fp, EINVAL)); @@ -980,29 +1029,32 @@ ctf_add_enumerator (ctf_dict_t *fp, ctf_id_t enid, const char *name, if (vlen == CTF_MAX_VLEN) return (ctf_set_errno (fp, ECTF_DTFULL)); - for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members); - dmd != NULL; dmd = ctf_list_next (dmd)) + old_vlen = dtd->dtd_vlen; + if (ctf_grow_vlen (fp, dtd, sizeof (ctf_enum_t) * (vlen + 1)) < 0) + return -1; /* errno is set for us. */ + en = (ctf_enum_t *) dtd->dtd_vlen; + + if (dtd->dtd_vlen != old_vlen) { - if (strcmp (dmd->dmd_name, name) == 0) - return (ctf_set_errno (fp, ECTF_DUPLICATE)); - } + ptrdiff_t move = (signed char *) dtd->dtd_vlen - (signed char *) old_vlen; - if ((dmd = malloc (sizeof (ctf_dmdef_t))) == NULL) - return (ctf_set_errno (fp, EAGAIN)); + /* Remove pending refs in the old vlen region and reapply them. */ - if ((s = strdup (name)) == NULL) - { - free (dmd); - return (ctf_set_errno (fp, EAGAIN)); + for (i = 0; i < vlen; i++) + ctf_str_move_pending (fp, &en[i].cte_name, move); } - dmd->dmd_name = s; - dmd->dmd_type = CTF_ERR; - dmd->dmd_offset = 0; - dmd->dmd_value = value; + for (i = 0; i < vlen; i++) + if (strcmp (ctf_strptr (fp, en[i].cte_name), name) == 0) + return (ctf_set_errno (fp, ECTF_DUPLICATE)); + + en[i].cte_name = ctf_str_add_pending (fp, name, &en[i].cte_name); + en[i].cte_value = value; + + if (en[i].cte_name == 0 && name != NULL && name[0] != '\0') + return -1; /* errno is set for us. */ dtd->dtd_data.ctt_info = CTF_TYPE_INFO (kind, root, vlen + 1); - ctf_list_append (&dtd->dtd_u.dtu_members, dmd); fp->ctf_flags |= LCTF_DIRTY; diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h index a319d7f..9a82d95 100644 --- a/libctf/ctf-impl.h +++ b/libctf/ctf-impl.h @@ -29,6 +29,7 @@ #include <sys/types.h> #include <stdlib.h> #include <stdarg.h> +#include <stddef.h> #include <stdio.h> #include <stdint.h> #include <limits.h> @@ -192,6 +193,7 @@ typedef struct ctf_dtdef ctf_list_t dtd_list; /* List forward/back pointers. */ ctf_id_t dtd_type; /* Type identifier for this definition. */ ctf_type_t dtd_data; /* Type node, including name. */ + size_t dtd_vlen_alloc; /* Total vlen space allocated. */ unsigned char *dtd_vlen; /* Variable-length data for this type. */ union { @@ -734,6 +736,7 @@ extern void ctf_str_free_atoms (ctf_dict_t *); extern uint32_t ctf_str_add (ctf_dict_t *, const char *); extern uint32_t ctf_str_add_ref (ctf_dict_t *, const char *, uint32_t *ref); extern uint32_t ctf_str_add_pending (ctf_dict_t *, const char *, uint32_t *); +extern int ctf_str_move_pending (ctf_dict_t *, uint32_t *, ptrdiff_t); extern int ctf_str_add_external (ctf_dict_t *, const char *, uint32_t offset); extern void ctf_str_remove_ref (ctf_dict_t *, const char *, uint32_t *ref); extern void ctf_str_rollback (ctf_dict_t *, ctf_snapshot_id_t); diff --git a/libctf/ctf-serialize.c b/libctf/ctf-serialize.c index 0eff0e1..5d94f44 100644 --- a/libctf/ctf-serialize.c +++ b/libctf/ctf-serialize.c @@ -770,26 +770,6 @@ ctf_copy_lmembers (ctf_dict_t *fp, ctf_dtdef_t *dtd, unsigned char *t) return t; } -static unsigned char * -ctf_copy_emembers (ctf_dict_t *fp, ctf_dtdef_t *dtd, unsigned char *t) -{ - ctf_dmdef_t *dmd = ctf_list_next (&dtd->dtd_u.dtu_members); - ctf_enum_t cte; - - for (; dmd != NULL; dmd = ctf_list_next (dmd)) - { - ctf_enum_t *copied; - - cte.cte_value = dmd->dmd_value; - memcpy (t, &cte, sizeof (cte)); - copied = (ctf_enum_t *) t; - ctf_str_add_ref (fp, dmd->dmd_name, &copied->cte_name); - t += sizeof (cte); - } - - return t; -} - /* Iterate through the dynamic type definition list and compute the size of the CTF type section. */ @@ -860,6 +840,7 @@ ctf_emit_type_sect (ctf_dict_t *fp, unsigned char **tptr) size_t len; ctf_stype_t *copied; const char *name; + size_t i; if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT) len = sizeof (ctf_stype_t); @@ -908,8 +889,22 @@ ctf_emit_type_sect (ctf_dict_t *fp, unsigned char **tptr) break; case CTF_K_ENUM: - t = ctf_copy_emembers (fp, dtd, t); - break; + { + ctf_enum_t *dtd_vlen = (struct ctf_enum *) dtd->dtd_vlen; + ctf_enum_t *t_vlen = (struct ctf_enum *) t; + + memcpy (t, dtd->dtd_vlen, sizeof (struct ctf_enum) * vlen); + for (i = 0; i < vlen; i++) + { + const char *name = ctf_strraw (fp, dtd_vlen[i].cte_name); + + ctf_str_add_ref (fp, name, &t_vlen[i].cte_name); + ctf_str_add_ref (fp, name, &dtd_vlen[i].cte_name); + } + t += sizeof (struct ctf_enum) * vlen; + + break; + } } } diff --git a/libctf/ctf-string.c b/libctf/ctf-string.c index 9f0e540..2e98484 100644 --- a/libctf/ctf-string.c +++ b/libctf/ctf-string.c @@ -19,6 +19,7 @@ #include <ctf-impl.h> #include <string.h> +#include <assert.h> /* Convert an encoded CTF string name into a pointer to a C string, using an explicit internal strtab rather than the fp-based one. */ @@ -228,6 +229,7 @@ ctf_str_add_ref_internal (ctf_dict_t *fp, const char *str, free (atom); free (aref); free (newstr); + ctf_set_errno (fp, ENOMEM); return NULL; } @@ -288,6 +290,21 @@ ctf_str_add_pending (ctf_dict_t *fp, const char *str, uint32_t *ref) return atom->csa_offset; } +/* Note that a pending ref now located at NEW_REF has moved by BYTES bytes. */ +int +ctf_str_move_pending (ctf_dict_t *fp, uint32_t *new_ref, ptrdiff_t bytes) +{ + if (bytes == 0) + return 0; + + if (ctf_dynset_insert (fp->ctf_str_pending_ref, (void *) new_ref) < 0) + return (ctf_set_errno (fp, ENOMEM)); + + ctf_dynset_remove (fp->ctf_str_pending_ref, + (void *) ((signed char *) new_ref - bytes)); + return 0; +} + /* Add an external strtab reference at OFFSET. Returns zero if the addition failed, nonzero otherwise. */ int diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c index 1e1ce8e..49264eb 100644 --- a/libctf/ctf-types.c +++ b/libctf/ctf-types.c @@ -318,22 +318,13 @@ ctf_enum_next (ctf_dict_t *fp, ctf_id_t type, ctf_next_t **it, dtd = ctf_dynamic_type (fp, type); i->ctn_iter_fun = (void (*) (void)) ctf_enum_next; - - /* We depend below on the RDWR state indicating whether the DTD-related - fields or the DMD-related fields have been initialized. */ - - assert ((dtd && (fp->ctf_flags & LCTF_RDWR)) - || (!dtd && (!(fp->ctf_flags & LCTF_RDWR)))); + i->ctn_n = LCTF_INFO_VLEN (fp, tp->ctt_info); if (dtd == NULL) - { - i->ctn_n = LCTF_INFO_VLEN (fp, tp->ctt_info); - - i->u.ctn_en = (const ctf_enum_t *) ((uintptr_t) tp + - i->ctn_increment); - } + i->u.ctn_en = (const ctf_enum_t *) ((uintptr_t) tp + + i->ctn_increment); else - i->u.ctn_dmd = ctf_list_next (&dtd->dtd_u.dtu_members); + i->u.ctn_en = (const ctf_enum_t *) dtd->dtd_vlen; *it = i; } @@ -357,27 +348,14 @@ ctf_enum_next (ctf_dict_t *fp, ctf_id_t type, ctf_next_t **it, return NULL; } - if (!(fp->ctf_flags & LCTF_RDWR)) - { - if (i->ctn_n == 0) - goto end_iter; - - name = ctf_strptr (fp, i->u.ctn_en->cte_name); - if (val) - *val = i->u.ctn_en->cte_value; - i->u.ctn_en++; - i->ctn_n--; - } - else - { - if (i->u.ctn_dmd == NULL) - goto end_iter; + if (i->ctn_n == 0) + goto end_iter; - name = i->u.ctn_dmd->dmd_name; - if (val) - *val = i->u.ctn_dmd->dmd_value; - i->u.ctn_dmd = ctf_list_next (i->u.ctn_dmd); - } + name = ctf_strptr (fp, i->u.ctn_en->cte_name); + if (val) + *val = i->u.ctn_en->cte_value; + i->u.ctn_en++; + i->ctn_n--; return name; @@ -1554,35 +1532,24 @@ ctf_enum_name (ctf_dict_t *fp, ctf_id_t type, int value) if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ENUM) { - (void) ctf_set_errno (ofp, ECTF_NOTENUM); + ctf_set_errno (ofp, ECTF_NOTENUM); return NULL; } - (void) ctf_get_ctt_size (fp, tp, NULL, &increment); + ctf_get_ctt_size (fp, tp, NULL, &increment); if ((dtd = ctf_dynamic_type (ofp, type)) == NULL) - { - ep = (const ctf_enum_t *) ((uintptr_t) tp + increment); - - for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++) - { - if (ep->cte_value == value) - return (ctf_strptr (fp, ep->cte_name)); - } - } + ep = (const ctf_enum_t *) ((uintptr_t) tp + increment); else - { - ctf_dmdef_t *dmd; + ep = (const ctf_enum_t *) dtd->dtd_vlen; - for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members); - dmd != NULL; dmd = ctf_list_next (dmd)) - { - if (dmd->dmd_value == value) - return dmd->dmd_name; - } + for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++) + { + if (ep->cte_value == value) + return (ctf_strptr (fp, ep->cte_name)); } - (void) ctf_set_errno (ofp, ECTF_NOENUMNAM); + ctf_set_errno (ofp, ECTF_NOENUMNAM); return NULL; } @@ -1590,7 +1557,7 @@ ctf_enum_name (ctf_dict_t *fp, ctf_id_t type, int value) matching name can be found. Otherwise CTF_ERR is returned. */ int -ctf_enum_value (ctf_dict_t * fp, ctf_id_t type, const char *name, int *valp) +ctf_enum_value (ctf_dict_t *fp, ctf_id_t type, const char *name, int *valp) { ctf_dict_t *ofp = fp; const ctf_type_t *tp; @@ -1611,39 +1578,24 @@ ctf_enum_value (ctf_dict_t * fp, ctf_id_t type, const char *name, int *valp) return -1; } - (void) ctf_get_ctt_size (fp, tp, NULL, &increment); - - ep = (const ctf_enum_t *) ((uintptr_t) tp + increment); + ctf_get_ctt_size (fp, tp, NULL, &increment); if ((dtd = ctf_dynamic_type (ofp, type)) == NULL) - { - for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++) - { - if (strcmp (ctf_strptr (fp, ep->cte_name), name) == 0) - { - if (valp != NULL) - *valp = ep->cte_value; - return 0; - } - } - } + ep = (const ctf_enum_t *) ((uintptr_t) tp + increment); else - { - ctf_dmdef_t *dmd; + ep = (const ctf_enum_t *) dtd->dtd_vlen; - for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members); - dmd != NULL; dmd = ctf_list_next (dmd)) + for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++) + { + if (strcmp (ctf_strptr (fp, ep->cte_name), name) == 0) { - if (strcmp (dmd->dmd_name, name) == 0) - { - if (valp != NULL) - *valp = dmd->dmd_value; - return 0; - } + if (valp != NULL) + *valp = ep->cte_value; + return 0; } } - (void) ctf_set_errno (ofp, ECTF_NOENUMNAM); + ctf_set_errno (ofp, ECTF_NOENUMNAM); return -1; } diff --git a/libctf/testsuite/libctf-lookup/enum-many-ctf.c b/libctf/testsuite/libctf-lookup/enum-many-ctf.c new file mode 100644 index 0000000..f2297d7 --- /dev/null +++ b/libctf/testsuite/libctf-lookup/enum-many-ctf.c @@ -0,0 +1,10 @@ +/* Looked up item by item. */ +enum e { ENUMSAMPLE_1 = 0, ENUMSAMPLE_2 = 1 }; + +/* Looked up via both sorts of iterator in turn. */ +enum ie { IE_0 = -10, IE_1, IE_2, IE_3, IE_4, IE_5, IE_6, IE_7, IE_8, IE_9, IE_A, IE_B, IE_C, IE_D, IE_E, IE_F, + IE_10, IE_11, IE_12, IE_13, IE_14, IE_15, IE_16, IE_17, IE_18, IE_19, IE_1A, IE_1B, IE_1C, IE_1D, IE_1E, IE_1F, + IE_20, IE_21, IE_22, IE_23, IE_24, IE_25, IE_26, IE_27, IE_28, IE_29, IE_2A, IE_2B, IE_2C, IE_2D, IE_2E, IE_2F}; + +enum e foo; +enum ie bar; diff --git a/libctf/testsuite/libctf-lookup/enum-many.lk b/libctf/testsuite/libctf-lookup/enum-many.lk new file mode 100644 index 0000000..17eca66 --- /dev/null +++ b/libctf/testsuite/libctf-lookup/enum-many.lk @@ -0,0 +1,101 @@ +# source: enum-many-ctf.c +# lookup: enum.c +# link: on +Enum e enumerand ENUMSAMPLE_1 has value 0 +Enum e enumerand ENUMSAMPLE_2 has value 1 +iter test: IE_0 has value -10 +iter test: IE_1 has value -9 +iter test: IE_2 has value -8 +iter test: IE_3 has value -7 +iter test: IE_4 has value -6 +iter test: IE_5 has value -5 +iter test: IE_6 has value -4 +iter test: IE_7 has value -3 +iter test: IE_8 has value -2 +iter test: IE_9 has value -1 +iter test: IE_A has value 0 +iter test: IE_B has value 1 +iter test: IE_C has value 2 +iter test: IE_D has value 3 +iter test: IE_E has value 4 +iter test: IE_F has value 5 +iter test: IE_10 has value 6 +iter test: IE_11 has value 7 +iter test: IE_12 has value 8 +iter test: IE_13 has value 9 +iter test: IE_14 has value 10 +iter test: IE_15 has value 11 +iter test: IE_16 has value 12 +iter test: IE_17 has value 13 +iter test: IE_18 has value 14 +iter test: IE_19 has value 15 +iter test: IE_1A has value 16 +iter test: IE_1B has value 17 +iter test: IE_1C has value 18 +iter test: IE_1D has value 19 +iter test: IE_1E has value 20 +iter test: IE_1F has value 21 +iter test: IE_20 has value 22 +iter test: IE_21 has value 23 +iter test: IE_22 has value 24 +iter test: IE_23 has value 25 +iter test: IE_24 has value 26 +iter test: IE_25 has value 27 +iter test: IE_26 has value 28 +iter test: IE_27 has value 29 +iter test: IE_28 has value 30 +iter test: IE_29 has value 31 +iter test: IE_2A has value 32 +iter test: IE_2B has value 33 +iter test: IE_2C has value 34 +iter test: IE_2D has value 35 +iter test: IE_2E has value 36 +iter test: IE_2F has value 37 +next test: IE_0 has value -10 +next test: IE_1 has value -9 +next test: IE_2 has value -8 +next test: IE_3 has value -7 +next test: IE_4 has value -6 +next test: IE_5 has value -5 +next test: IE_6 has value -4 +next test: IE_7 has value -3 +next test: IE_8 has value -2 +next test: IE_9 has value -1 +next test: IE_A has value 0 +next test: IE_B has value 1 +next test: IE_C has value 2 +next test: IE_D has value 3 +next test: IE_E has value 4 +next test: IE_F has value 5 +next test: IE_10 has value 6 +next test: IE_11 has value 7 +next test: IE_12 has value 8 +next test: IE_13 has value 9 +next test: IE_14 has value 10 +next test: IE_15 has value 11 +next test: IE_16 has value 12 +next test: IE_17 has value 13 +next test: IE_18 has value 14 +next test: IE_19 has value 15 +next test: IE_1A has value 16 +next test: IE_1B has value 17 +next test: IE_1C has value 18 +next test: IE_1D has value 19 +next test: IE_1E has value 20 +next test: IE_1F has value 21 +next test: IE_20 has value 22 +next test: IE_21 has value 23 +next test: IE_22 has value 24 +next test: IE_23 has value 25 +next test: IE_24 has value 26 +next test: IE_25 has value 27 +next test: IE_26 has value 28 +next test: IE_27 has value 29 +next test: IE_28 has value 30 +next test: IE_29 has value 31 +next test: IE_2A has value 32 +next test: IE_2B has value 33 +next test: IE_2C has value 34 +next test: IE_2D has value 35 +next test: IE_2E has value 36 +next test: IE_2F has value 37 |