| #include "asn1c_internal.h" |
| #include "asn1c_naming.h" |
| #include "asn1c_misc.h" |
| #include "asn1c_misc.h" |
| #include <asn1_buffer.h> |
| |
| struct intl_name { |
| asn1p_expr_t *expr; |
| asn1p_expr_t *clashes_with; |
| const char *name; |
| TQ_ENTRY(struct intl_name) next; |
| }; |
| static TQ_HEAD(struct intl_name) used_names; |
| |
| void |
| c_name_clash_finder_init() { |
| TQ_INIT(&used_names); |
| } |
| |
| void |
| c_name_clash_finder_destroy() { |
| struct intl_name *n; |
| |
| while((n = TQ_REMOVE(&used_names, next))) { |
| 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); |
| } |
| } |
| |
| static void |
| register_global_name(asn1p_expr_t *expr, const char *name) { |
| struct intl_name *n; |
| |
| TQ_FOR(n, &used_names, next) { |
| if(strcmp(n->name, name) == 0) { |
| if(!(expr->_mark & TM_NAMEGIVEN) && expr != n->expr) { |
| n->clashes_with = expr; |
| expr->ref_cnt++; |
| return; |
| } |
| } |
| } |
| |
| if(expr->_mark & TM_NAMEGIVEN) |
| return; |
| |
| n = calloc(1, sizeof(*n)); |
| assert(n); |
| n->expr = expr; |
| expr->ref_cnt++; |
| n->name = strdup(name); |
| TQ_ADD(&used_names, n, next); |
| } |
| |
| int |
| c_name_clash(arg_t *arg) { |
| struct intl_name *n; |
| size_t n_clashes = 0; |
| const size_t max_clashes = 5; |
| |
| TQ_FOR(n, &used_names, next) { |
| 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); |
| } |
| } |
| |
| 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) { |
| const char *id; |
| |
| assert(buf); |
| |
| if(compound_names && expr->parent_expr) { |
| construct_base_name(buf, expr->parent_expr, compound_names, 0); |
| if(buf->length) { |
| abuf_str(buf, "__"); /* component separator */ |
| } |
| } |
| |
| id = asn1c_make_identifier( |
| ((avoid_keywords && !buf->length) ? AMI_CHECK_RESERVED : 0), 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); |
| construct_base_name(&b_part_name, expr, 0, 0); |
| construct_base_name(&b_base_name, expr, compound_names, avoid_keywords); |
| construct_base_name(&b_as_member, expr, 0, 1); |
| |
| static abuf tmp_compoundable_part_name; |
| abuf_clear(&tmp_compoundable_part_name); |
| construct_base_name(&tmp_compoundable_part_name, expr, compound_names, 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); |
| |
| 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; |
| |
| /* 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, 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); |
| |
| 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; |
| } |
| |