X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=libasn1compiler%2Fasn1c_naming.c;fp=libasn1compiler%2Fasn1c_naming.c;h=c892fcf8f8c093f70e9692bf1dc7a57152c39185;hb=70ee6fc793ec8e828067a3569849b6c216054497;hp=0000000000000000000000000000000000000000;hpb=59f84608ec15c016958a6e0e0ddd813f376c0925;p=com%2Fasn1c.git diff --git a/libasn1compiler/asn1c_naming.c b/libasn1compiler/asn1c_naming.c new file mode 100644 index 0000000..c892fcf --- /dev/null +++ b/libasn1compiler/asn1c_naming.c @@ -0,0 +1,327 @@ +#include "asn1c_internal.h" +#include "asn1c_naming.h" +#include "asn1c_misc.h" +#include +#include + +struct intl_name { + asn1p_expr_t *expr; + asn1p_expr_t *clashes_with; + const char *name; + TQ_ENTRY(struct intl_name) next; +}; + +genhash_t *used_names_hash; + +static void +name_entry_destroy(void *np) { + struct intl_name *n = np; + + union { + const char *c_buf; + char *nc_buf; + } const_cast; + + asn1p_expr_free(n->expr); + asn1p_expr_free(n->clashes_with); + const_cast.c_buf = n->name; + free(const_cast.nc_buf); + free(n); +} + +void +c_name_clash_finder_init() { + assert(used_names_hash == NULL); + used_names_hash = + genhash_new(cmpf_string, hashf_string, NULL, name_entry_destroy); + assert(used_names_hash); +} + +void +c_name_clash_finder_destroy() { + genhash_destroy(used_names_hash); + used_names_hash = NULL; +} + +static void +register_global_name(asn1p_expr_t *expr, const char *name) { + struct intl_name *n; + + n = genhash_get(used_names_hash, (const void *)name); + if(n) { + if(!(expr->_mark & TM_NAMEGIVEN) && (expr != n->expr)) { + n->clashes_with = expr; + expr->ref_cnt++; + return; + } + } + + if(expr->_mark & TM_NAMEGIVEN) + return; + + char *name_copy = strdup(name); + + n = calloc(1, sizeof(*n)); + assert(n); + n->expr = expr; + expr->ref_cnt++; + n->name = name_copy; + int ret = genhash_add(used_names_hash, name_copy, n); + assert(ret == 0); +} + +int +c_name_clash(arg_t *arg) { + struct intl_name *n; + size_t n_clashes = 0; + const size_t max_clashes = 5; + + genhash_iter_t iter; + + genhash_iter_init(&iter, used_names_hash, 0); + while(genhash_iter(&iter, NULL, (void *)&n)) { + if(n->clashes_with) { + if(n_clashes++ > max_clashes) continue; + FATAL( + "Name \"%s\" is generated by %s.%s at line %s:%d and " + "%s.%s at line %s:%d", + n->name, n->expr->module->ModuleName, n->expr->Identifier, + n->expr->module->source_file_name, n->expr->_lineno, + n->clashes_with->module->ModuleName, + n->clashes_with->Identifier, + n->clashes_with->module->source_file_name, + n->clashes_with->_lineno); + } + } + + genhash_iter_done(&iter); + + if(n_clashes > max_clashes) { + FATAL("... %zu more name clashes not shown", n_clashes - max_clashes); + } + + return n_clashes > 0; +} + + +static abuf * +construct_base_name(abuf *buf, asn1p_expr_t *expr, int compound_names, + int avoid_keywords, enum ami_flags_e flag) { + const char *id; + + assert(buf); + + if(compound_names && expr->parent_expr) { + construct_base_name(buf, expr->parent_expr, compound_names, 0, flag); + if(buf->length) { + abuf_str(buf, "__"); /* component separator */ + } + } + + id = asn1c_make_identifier( + ((avoid_keywords && !buf->length) ? AMI_CHECK_RESERVED : 0) | flag, expr, 0); + + abuf_str(buf, id); + + return buf; +} + +static struct c_names +c_name_impl(arg_t *arg, asn1p_expr_t *expr, int avoid_keywords) { + asn1p_expr_type_e expr_type = expr->expr_type; + struct c_names names; + int compound_names = 0; + + static abuf b_type_asn_name; + static abuf b_type_part_name; + static abuf b_type_base_name; + static abuf b_type_c_name; + static abuf b_type_constrained_c_name; + static abuf b_asn_name; + static abuf b_part_name; + static abuf b_base_name; + static abuf b_short_name; + static abuf b_full_name; + static abuf b_as_member; + static abuf b_presence_enum; + static abuf b_presence_name; + static abuf b_members_enum; + static abuf b_members_name; + + abuf_clear(&b_type_asn_name); + abuf_clear(&b_type_part_name); + abuf_clear(&b_type_base_name); + abuf_clear(&b_type_c_name); + abuf_clear(&b_type_constrained_c_name); + abuf_clear(&b_asn_name); + abuf_clear(&b_base_name); + abuf_clear(&b_part_name); + abuf_clear(&b_short_name); + abuf_clear(&b_full_name); + abuf_clear(&b_as_member); + abuf_clear(&b_presence_enum); + abuf_clear(&b_presence_name); + abuf_clear(&b_members_enum); + abuf_clear(&b_members_name); + + abuf_str(&b_type_asn_name, asn1c_type_name(arg, expr, TNF_UNMODIFIED)); + abuf_str(&b_type_part_name, asn1c_type_name(arg, expr, TNF_SAFE)); + abuf_str(&b_type_base_name, asn1c_type_name(arg, expr, TNF_SAFE)); + abuf_str(&b_type_c_name, asn1c_type_name(arg, expr, TNF_CTYPE)); + abuf_str(&b_type_constrained_c_name, + asn1c_type_name(arg, expr, TNF_CONSTYPE)); + + + if((arg->flags & A1C_COMPOUND_NAMES)) { + if((expr_type & ASN_CONSTR_MASK) + || expr_type == ASN_BASIC_ENUMERATED + || ((expr_type == ASN_BASIC_INTEGER + || expr_type == ASN_BASIC_BIT_STRING))) { + compound_names = 1; + } + } + + construct_base_name(&b_asn_name, expr, 0, 0, 0); + construct_base_name(&b_part_name, expr, 0, 0, AMI_USE_PREFIX); + construct_base_name(&b_base_name, expr, compound_names, avoid_keywords, 0); + construct_base_name(&b_as_member, expr, 0, 1, 0); + + static abuf tmp_compoundable_part_name; + static abuf compound_part_name; + abuf_clear(&tmp_compoundable_part_name); + abuf_clear(&compound_part_name); + construct_base_name(&tmp_compoundable_part_name, expr, compound_names, 0, 0); + construct_base_name(&compound_part_name, expr, 1, 0, 0); + + if(strlen(asn1c_prefix()) == 0) { + if(!expr->_anonymous_type) { + if(arg->embed) { + abuf_printf(&b_short_name, "%s", b_as_member.buffer); + } else { + abuf_printf(&b_short_name, "%s_t", b_as_member.buffer); + } + } + abuf_printf(&b_full_name, "struct %s", b_base_name.buffer); + abuf_printf(&b_presence_enum, "enum %s_PR", tmp_compoundable_part_name.buffer); + abuf_printf(&b_presence_name, "%s_PR", tmp_compoundable_part_name.buffer); + abuf_printf(&b_members_enum, "enum %s", b_base_name.buffer); + abuf_printf(&b_members_name, "e_%s", tmp_compoundable_part_name.buffer); + } else { + if(!expr->_anonymous_type) { + if(arg->embed) { + abuf_printf(&b_short_name, "%s%s", asn1c_prefix(), b_as_member.buffer); + } else { + abuf_printf(&b_short_name, "%s%s_t", asn1c_prefix(), b_as_member.buffer); + } + } + abuf_printf(&b_full_name, "struct %s%s", asn1c_prefix(), b_base_name.buffer); + abuf_printf(&b_presence_enum, "enum %s%s_PR", asn1c_prefix(), tmp_compoundable_part_name.buffer); + abuf_printf(&b_presence_name, "%s%s_PR", asn1c_prefix(), tmp_compoundable_part_name.buffer); + abuf_printf(&b_members_enum, "enum %s%s", asn1c_prefix(), b_base_name.buffer); + abuf_printf(&b_members_name, "e_%s%s", asn1c_prefix(), tmp_compoundable_part_name.buffer); + } + + names.type.asn_name = b_type_asn_name.buffer; + names.type.base_name = b_type_base_name.buffer; + names.type.part_name = b_type_part_name.buffer; + names.type.c_name = b_type_c_name.buffer; + names.type.constrained_c_name = b_type_constrained_c_name.buffer; + names.asn_name = b_asn_name.buffer; + names.part_name = b_part_name.buffer; + names.base_name = b_base_name.buffer; + names.short_name = b_short_name.buffer; + names.full_name = b_full_name.buffer; + names.as_member = b_as_member.buffer; + names.presence_enum = b_presence_enum.buffer; + names.presence_name = b_presence_name.buffer; + names.members_enum = b_members_enum.buffer; + names.members_name = b_members_name.buffer; + names.compound_name = compound_part_name.buffer; + + /* A _subset_ of names is checked against being globally unique */ + register_global_name(expr, names.base_name); + register_global_name(expr, names.full_name); + register_global_name(expr, names.presence_enum); + register_global_name(expr, names.presence_name); + register_global_name(expr, names.members_enum); + register_global_name(expr, names.members_name); + + expr->_mark |= TM_NAMEGIVEN; + + return names; +} + +struct c_names +c_name(arg_t *arg) { + return c_name_impl(arg, arg->expr, 1); +} + +struct c_names +c_expr_name(arg_t *arg, asn1p_expr_t *expr) { + return c_name_impl(arg, expr, 1); +} + +const char * +c_member_name(arg_t *arg, asn1p_expr_t *expr) { + static abuf ab; + + abuf_clear(&ab); + + /* NB: do not use part_name, doesn't work for -fcompound-names */ + abuf_str(&ab, asn1c_prefix()); + abuf_str(&ab, c_name_impl(arg, arg->expr, 0).base_name); + abuf_str(&ab, "_"); + abuf_str(&ab, asn1c_make_identifier(0, expr, 0)); + + return ab.buffer; +} + + +const char * +c_presence_name(arg_t *arg, asn1p_expr_t *expr) { + static abuf ab; + + abuf_clear(&ab); + + abuf_str(&ab, asn1c_prefix()); + if(expr) { + /* NB: do not use part_name, doesn't work for -fcompound-names */ + abuf_str(&ab, c_name_impl(arg, arg->expr, 0).base_name); + abuf_str(&ab, "_PR_"); + abuf_str(&ab, asn1c_make_identifier(0, expr, 0)); + } else { + abuf_printf(&ab, "%s_PR_NOTHING", + c_name_impl(arg, arg->expr, 0).base_name); + } + + return ab.buffer; +} + +const char * +c_names_format(struct c_names ns) { + static abuf nbuf; + abuf_clear(&nbuf); + +#define FMT_COMPONENT(x) abuf_printf(&nbuf, " ." #x "=\"%s\",", ns.x); + + abuf_str(&nbuf, "{"); + FMT_COMPONENT(type.asn_name); + FMT_COMPONENT(type.part_name); + FMT_COMPONENT(type.base_name); + FMT_COMPONENT(type.c_name); + FMT_COMPONENT(type.constrained_c_name); + FMT_COMPONENT(asn_name); + FMT_COMPONENT(part_name); + FMT_COMPONENT(base_name); + FMT_COMPONENT(full_name); + FMT_COMPONENT(short_name); + FMT_COMPONENT(full_name); + FMT_COMPONENT(as_member); + FMT_COMPONENT(presence_enum); + FMT_COMPONENT(presence_name); + FMT_COMPONENT(members_enum); + FMT_COMPONENT(members_name); + abuf_printf(&nbuf, " .members_name=\"%s\" }", ns.members_name); + return nbuf.buffer; +} +