#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; }