diff options
Diffstat (limited to 'libctf/ctf-create.c')
-rw-r--r-- | libctf/ctf-create.c | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c index d674603..a754495 100644 --- a/libctf/ctf-create.c +++ b/libctf/ctf-create.c @@ -1071,7 +1071,13 @@ ctf_add_enumerator (ctf_dict_t *fp, ctf_id_t enid, const char *name, if the enum they are part of is a root-visible type. */ if (root == CTF_ADD_ROOT && ctf_dynhash_lookup (fp->ctf_names, name)) - return (ctf_set_errno (ofp, ECTF_DUPLICATE)); + { + if (fp->ctf_flags & LCTF_STRICT_NO_DUP_ENUMERATORS) + return (ctf_set_errno (ofp, ECTF_DUPLICATE)); + + if (ctf_track_enumerator (fp, enid, name) < 0) + return (ctf_set_errno (ofp, ctf_errno (fp))); + } if (kind != CTF_K_ENUM) return (ctf_set_errno (ofp, ECTF_NOTENUM)); @@ -1094,7 +1100,7 @@ ctf_add_enumerator (ctf_dict_t *fp, ctf_id_t enid, const char *name, non-root-visible types, since the duplicate detection above does the job for root-visible types just fine. */ - if (root == CTF_ADD_NONROOT) + if (root == CTF_ADD_NONROOT && (fp->ctf_flags & LCTF_STRICT_NO_DUP_ENUMERATORS)) { size_t i; @@ -1429,6 +1435,42 @@ ctf_add_func_sym (ctf_dict_t *fp, const char *name, ctf_id_t id) return (ctf_add_funcobjt_sym (fp, 1, name, id)); } +/* Add an enumeration constant observed in a given enum type as an identifier. + They appear as names that cite the enum type. + + Constants that appear in more than one enum, or which are already the names + of types, appear in ctf_conflicting_enums as well. + + This is done for all enumeration types at open time, and for newly-added ones + as well: if the strict-enum flag is turned on, this table must be kept up to + date with enums added in the interim. */ + +int +ctf_track_enumerator (ctf_dict_t *fp, ctf_id_t type, const char *cte_name) +{ + int err; + + if (ctf_dynhash_lookup_type (fp->ctf_names, cte_name) == 0) + { + uint32_t name = ctf_str_add (fp, cte_name); + + if (name == 0) + return -1; /* errno is set for us. */ + + err = ctf_dynhash_insert_type (fp, fp->ctf_names, type, name); + } + else + { + err = ctf_dynset_insert (fp->ctf_conflicting_enums, (void *) + cte_name); + if (err != 0) + ctf_set_errno (fp, err * -1); + } + if (err != 0) + return -1; /* errno is set for us. */ + return 0; +} + typedef struct ctf_bundle { ctf_dict_t *ctb_dict; /* CTF dict handle. */ |