asn1c_naming.c 8.08 KB
Newer Older
Lev Walkin's avatar
Lev Walkin committed
1 2 3 4 5 6
#include "asn1c_internal.h"
#include "asn1c_naming.h"
#include "asn1c_misc.h"
#include "asn1c_misc.h"
#include <asn1_buffer.h>

7 8 9 10 11 12 13 14 15 16 17 18 19
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);
}

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
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);
    }
}

38
static void
Lev Walkin's avatar
Lev Walkin committed
39
register_global_name(asn1p_expr_t *expr, const char *name) {
40 41 42 43
    struct intl_name *n;

    TQ_FOR(n, &used_names, next) {
        if(strcmp(n->name, name) == 0) {
Lev Walkin's avatar
Lev Walkin committed
44 45 46
            if(!(expr->_mark & TM_NAMEGIVEN) && expr != n->expr) {
                n->clashes_with = expr;
                expr->ref_cnt++;
47 48 49 50 51
                return;
            }
        }
    }

Lev Walkin's avatar
Lev Walkin committed
52
    if(expr->_mark & TM_NAMEGIVEN)
53 54
        return;

55 56
    n = calloc(1, sizeof(*n));
    assert(n);
Lev Walkin's avatar
Lev Walkin committed
57 58
    n->expr = expr;
    expr->ref_cnt++;
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
    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;
}


Lev Walkin's avatar
Lev Walkin committed
92
static abuf *
Lev Walkin's avatar
Lev Walkin committed
93
construct_base_name(abuf *buf, asn1p_expr_t *expr, int compound_names,
Lev Walkin's avatar
Lev Walkin committed
94 95 96
                    int avoid_keywords) {
    const char *id;

Lev Walkin's avatar
Lev Walkin committed
97
    assert(buf);
Lev Walkin's avatar
Lev Walkin committed
98

Lev Walkin's avatar
Lev Walkin committed
99 100
    if(compound_names && expr->parent_expr) {
        construct_base_name(buf, expr->parent_expr, compound_names, 0);
Lev Walkin's avatar
Lev Walkin committed
101 102 103 104 105 106
        if(buf->length) {
            abuf_str(buf, "__"); /* component separator */
        }
    }

    id = asn1c_make_identifier(
Lev Walkin's avatar
Lev Walkin committed
107
        ((avoid_keywords && !buf->length) ? AMI_CHECK_RESERVED : 0), expr, 0);
Lev Walkin's avatar
Lev Walkin committed
108 109 110 111 112 113 114

    abuf_str(buf, id);

    return buf;
}

static struct c_names
Lev Walkin's avatar
Lev Walkin committed
115 116
c_name_impl(arg_t *arg, asn1p_expr_t *expr, int avoid_keywords) {
    asn1p_expr_type_e expr_type = expr->expr_type;
Lev Walkin's avatar
Lev Walkin committed
117 118 119
    struct c_names names;
    int compound_names = 0;

Lev Walkin's avatar
Lev Walkin committed
120 121 122 123 124 125
    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_asn_name;
    static abuf b_part_name;
Lev Walkin's avatar
Lev Walkin committed
126 127 128 129 130 131 132 133 134
    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;

Lev Walkin's avatar
Lev Walkin committed
135 136 137 138 139
    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_asn_name);
Lev Walkin's avatar
Lev Walkin committed
140
    abuf_clear(&b_base_name);
Lev Walkin's avatar
Lev Walkin committed
141
    abuf_clear(&b_part_name);
Lev Walkin's avatar
Lev Walkin committed
142 143 144 145 146 147 148 149
    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);

Lev Walkin's avatar
Lev Walkin committed
150 151 152 153 154 155 156

    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));


Lev Walkin's avatar
Lev Walkin committed
157 158 159 160 161 162 163 164 165
    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;
        }
    }

Lev Walkin's avatar
Lev Walkin committed
166 167 168 169 170 171 172 173
    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);
Lev Walkin's avatar
Lev Walkin committed
174

Lev Walkin's avatar
Lev Walkin committed
175
    if(!expr->_anonymous_type) {
Lev Walkin's avatar
Lev Walkin committed
176
        if(arg->embed) {
Lev Walkin's avatar
Lev Walkin committed
177
            abuf_printf(&b_short_name, "%s", b_as_member.buffer);
Lev Walkin's avatar
Lev Walkin committed
178
        } else {
Lev Walkin's avatar
Lev Walkin committed
179
            abuf_printf(&b_short_name, "%s_t", b_as_member.buffer);
Lev Walkin's avatar
Lev Walkin committed
180 181
        }
    }
Lev Walkin's avatar
Lev Walkin committed
182 183 184 185 186 187 188 189 190 191 192 193
    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.asn_name = b_asn_name.buffer;
    names.part_name = b_part_name.buffer;
Lev Walkin's avatar
Lev Walkin committed
194 195 196 197 198 199 200 201 202
    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;

203
    /* A _subset_ of names is checked against being globally unique */
Lev Walkin's avatar
Lev Walkin committed
204 205 206 207 208 209
    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);
210

Lev Walkin's avatar
Lev Walkin committed
211
    expr->_mark |= TM_NAMEGIVEN;
212

Lev Walkin's avatar
Lev Walkin committed
213 214 215 216 217
    return names;
}

struct c_names
c_name(arg_t *arg) {
Lev Walkin's avatar
Lev Walkin committed
218 219 220 221 222 223
    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);
Lev Walkin's avatar
Lev Walkin committed
224 225 226 227 228 229 230 231
}

const char *
c_member_name(arg_t *arg, asn1p_expr_t *expr) {
    static abuf ab;

    abuf_clear(&ab);

Lev Walkin's avatar
Lev Walkin committed
232 233
    /* NB: do not use part_name, doesn't work for -fcompound-names */
    abuf_str(&ab, c_name_impl(arg, arg->expr, 0).base_name);
Lev Walkin's avatar
Lev Walkin committed
234 235
    abuf_str(&ab, "_");
    abuf_str(&ab, asn1c_make_identifier(0, expr, 0));
Lev Walkin's avatar
Lev Walkin committed
236 237 238 239 240 241 242 243 244 245 246 247

    return ab.buffer;
}


const char *
c_presence_name(arg_t *arg, asn1p_expr_t *expr) {
    static abuf ab;

    abuf_clear(&ab);

    if(expr) {
Lev Walkin's avatar
Lev Walkin committed
248 249
        /* NB: do not use part_name, doesn't work for -fcompound-names */
        abuf_str(&ab, c_name_impl(arg, arg->expr, 0).base_name);
Lev Walkin's avatar
Lev Walkin committed
250 251
        abuf_str(&ab, "_PR_");
        abuf_str(&ab, asn1c_make_identifier(0, expr, 0));
Lev Walkin's avatar
Lev Walkin committed
252
    } else {
Lev Walkin's avatar
Lev Walkin committed
253 254
        abuf_printf(&ab, "%s_PR_NOTHING",
                    c_name_impl(arg, arg->expr, 0).base_name);
Lev Walkin's avatar
Lev Walkin committed
255 256 257 258
    }

    return ab.buffer;
}
Lev Walkin's avatar
Lev Walkin committed
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286

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