mirror of https://gerrit.osmocom.org/asn1c
208 lines
5.7 KiB
C
208 lines
5.7 KiB
C
#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);
|
|
}
|
|
|
|
static void
|
|
register_global_name(arg_t *arg, const char *name) {
|
|
struct intl_name *n;
|
|
|
|
TQ_FOR(n, &used_names, next) {
|
|
if(strcmp(n->name, name) == 0) {
|
|
if(!(arg->expr->_mark & TM_NAMEGIVEN) && arg->expr != n->expr) {
|
|
n->clashes_with = arg->expr;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
n = calloc(1, sizeof(*n));
|
|
assert(n);
|
|
n->expr = arg->expr;
|
|
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, arg_t *arg, int compound_names,
|
|
int avoid_keywords) {
|
|
const char *id;
|
|
|
|
if(!buf) buf = abuf_new();
|
|
|
|
if(compound_names && arg->expr->parent_expr) {
|
|
arg_t tmparg = *arg;
|
|
tmparg.expr = arg->expr->parent_expr;
|
|
construct_base_name(buf, &tmparg, compound_names, 0);
|
|
if(buf->length) {
|
|
abuf_str(buf, "__"); /* component separator */
|
|
}
|
|
}
|
|
|
|
id = asn1c_make_identifier(
|
|
((avoid_keywords && !buf->length) ? AMI_CHECK_RESERVED : 0), arg->expr,
|
|
0);
|
|
|
|
abuf_str(buf, id);
|
|
|
|
return buf;
|
|
}
|
|
|
|
static struct c_names
|
|
c_name_impl(arg_t *arg, int avoid_keywords) {
|
|
asn1p_expr_type_e expr_type = arg->expr->expr_type;
|
|
struct c_names names;
|
|
int compound_names = 0;
|
|
|
|
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_base_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);
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
abuf *base_name =
|
|
construct_base_name(NULL, arg, compound_names, avoid_keywords);
|
|
abuf *part_name =
|
|
construct_base_name(NULL, arg, compound_names, 0);
|
|
abuf *member_name =
|
|
construct_base_name(NULL, arg, 0, 1);
|
|
|
|
abuf_printf(&b_base_name, "%s", base_name->buffer);
|
|
if(!arg->expr->_anonymous_type) {
|
|
if(arg->embed) {
|
|
abuf_printf(&b_short_name, "%s", member_name->buffer);
|
|
} else {
|
|
abuf_printf(&b_short_name, "%s_t", member_name->buffer);
|
|
}
|
|
}
|
|
abuf_printf(&b_full_name, "struct %s", base_name->buffer);
|
|
abuf_printf(&b_as_member, "%s", member_name->buffer);
|
|
abuf_printf(&b_presence_enum, "enum %s_PR", part_name->buffer);
|
|
abuf_printf(&b_presence_name, "%s_PR", part_name->buffer);
|
|
abuf_printf(&b_members_enum, "enum %s", base_name->buffer);
|
|
abuf_printf(&b_members_name, "e_%s", 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;
|
|
|
|
abuf_free(base_name);
|
|
abuf_free(part_name);
|
|
abuf_free(member_name);
|
|
|
|
/* A _subset_ of names is checked against being globally unique */
|
|
register_global_name(arg, names.base_name);
|
|
register_global_name(arg, names.full_name);
|
|
register_global_name(arg, names.presence_enum);
|
|
register_global_name(arg, names.presence_name);
|
|
register_global_name(arg, names.members_enum);
|
|
register_global_name(arg, names.members_name);
|
|
|
|
arg->expr->_mark |= TM_NAMEGIVEN;
|
|
|
|
return names;
|
|
}
|
|
|
|
struct c_names
|
|
c_name(arg_t *arg) {
|
|
return c_name_impl(arg, 1);
|
|
}
|
|
|
|
const char *
|
|
c_member_name(arg_t *arg, asn1p_expr_t *expr) {
|
|
static abuf ab;
|
|
|
|
abuf_clear(&ab);
|
|
|
|
abuf_printf(&ab, "%s_%s", c_name_impl(arg, 0).base_name,
|
|
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) {
|
|
abuf_printf(&ab, "%s_PR_%s", c_name_impl(arg, 0).base_name,
|
|
asn1c_make_identifier(0, expr, 0));
|
|
} else {
|
|
abuf_printf(&ab, "%s_PR_NOTHING", c_name_impl(arg, 0).base_name);
|
|
}
|
|
|
|
return ab.buffer;
|
|
}
|