blob: 223fa6d973158f50526ddc41655369099ba29448 [file] [log] [blame]
Lev Walkinb46156d2017-09-05 02:53:05 -07001#include "asn1c_internal.h"
2#include "asn1c_naming.h"
3#include "asn1c_misc.h"
4#include "asn1c_misc.h"
5#include <asn1_buffer.h>
6
Lev Walkin5efafc52017-09-05 03:43:00 -07007struct intl_name {
8 asn1p_expr_t *expr;
9 asn1p_expr_t *clashes_with;
10 const char *name;
11 TQ_ENTRY(struct intl_name) next;
12};
13static TQ_HEAD(struct intl_name) used_names;
14
15void
16c_name_clash_finder_init() {
17 TQ_INIT(&used_names);
18}
19
20static void
21register_global_name(arg_t *arg, const char *name) {
22 struct intl_name *n;
23
24 TQ_FOR(n, &used_names, next) {
25 if(strcmp(n->name, name) == 0) {
26 if(!(arg->expr->_mark & TM_NAMEGIVEN) && arg->expr != n->expr) {
27 n->clashes_with = arg->expr;
28 return;
29 }
30 }
31 }
32
33 n = calloc(1, sizeof(*n));
34 assert(n);
35 n->expr = arg->expr;
36 n->name = strdup(name);
37 TQ_ADD(&used_names, n, next);
38}
39
40int
41c_name_clash(arg_t *arg) {
42 struct intl_name *n;
43 size_t n_clashes = 0;
44 const size_t max_clashes = 5;
45
46 TQ_FOR(n, &used_names, next) {
47 if(n->clashes_with) {
48 if(n_clashes++ > max_clashes) continue;
49 FATAL(
50 "Name \"%s\" is generated by %s.%s at line %s:%d and "
51 "%s.%s at line %s:%d",
52 n->name, n->expr->module->ModuleName, n->expr->Identifier,
53 n->expr->module->source_file_name, n->expr->_lineno,
54 n->clashes_with->module->ModuleName,
55 n->clashes_with->Identifier,
56 n->clashes_with->module->source_file_name,
57 n->clashes_with->_lineno);
58 }
59 }
60
61 if(n_clashes > max_clashes) {
62 FATAL("... %zu more name clashes not shown", n_clashes - max_clashes);
63 }
64
65 return n_clashes > 0;
66}
67
68
Lev Walkinb46156d2017-09-05 02:53:05 -070069static abuf *
70construct_base_name(abuf *buf, arg_t *arg, int compound_names,
71 int avoid_keywords) {
72 const char *id;
73
74 if(!buf) buf = abuf_new();
75
76 if(compound_names && arg->expr->parent_expr) {
77 arg_t tmparg = *arg;
78 tmparg.expr = arg->expr->parent_expr;
79 construct_base_name(buf, &tmparg, compound_names, 0);
80 if(buf->length) {
81 abuf_str(buf, "__"); /* component separator */
82 }
83 }
84
85 id = asn1c_make_identifier(
86 ((avoid_keywords && !buf->length) ? AMI_CHECK_RESERVED : 0), arg->expr,
87 0);
88
89 abuf_str(buf, id);
90
91 return buf;
92}
93
94static struct c_names
95c_name_impl(arg_t *arg, int avoid_keywords) {
96 asn1p_expr_type_e expr_type = arg->expr->expr_type;
97 struct c_names names;
98 int compound_names = 0;
99
100 static abuf b_base_name;
101 static abuf b_short_name;
102 static abuf b_full_name;
103 static abuf b_as_member;
104 static abuf b_presence_enum;
105 static abuf b_presence_name;
106 static abuf b_members_enum;
107 static abuf b_members_name;
108
109 abuf_clear(&b_base_name);
110 abuf_clear(&b_short_name);
111 abuf_clear(&b_full_name);
112 abuf_clear(&b_as_member);
113 abuf_clear(&b_presence_enum);
114 abuf_clear(&b_presence_name);
115 abuf_clear(&b_members_enum);
116 abuf_clear(&b_members_name);
117
118 if((arg->flags & A1C_COMPOUND_NAMES)) {
119 if((expr_type & ASN_CONSTR_MASK)
120 || expr_type == ASN_BASIC_ENUMERATED
121 || ((expr_type == ASN_BASIC_INTEGER
122 || expr_type == ASN_BASIC_BIT_STRING))) {
123 compound_names = 1;
124 }
125 }
126
127 abuf *base_name =
128 construct_base_name(NULL, arg, compound_names, avoid_keywords);
129 abuf *part_name =
130 construct_base_name(NULL, arg, compound_names, 0);
131 abuf *member_name =
132 construct_base_name(NULL, arg, 0, 1);
133
134 abuf_printf(&b_base_name, "%s", base_name->buffer);
135 if(!arg->expr->_anonymous_type) {
136 if(arg->embed) {
137 abuf_printf(&b_short_name, "%s", member_name->buffer);
138 } else {
139 abuf_printf(&b_short_name, "%s_t", member_name->buffer);
140 }
141 }
142 abuf_printf(&b_full_name, "struct %s", base_name->buffer);
143 abuf_printf(&b_as_member, "%s", member_name->buffer);
144 abuf_printf(&b_presence_enum, "enum %s_PR", part_name->buffer);
145 abuf_printf(&b_presence_name, "%s_PR", part_name->buffer);
146 abuf_printf(&b_members_enum, "enum %s", base_name->buffer);
147 abuf_printf(&b_members_name, "e_%s", part_name->buffer);
148
149 names.base_name = b_base_name.buffer;
150 names.short_name = b_short_name.buffer;
151 names.full_name = b_full_name.buffer;
152 names.as_member = b_as_member.buffer;
153 names.presence_enum = b_presence_enum.buffer;
154 names.presence_name = b_presence_name.buffer;
155 names.members_enum = b_members_enum.buffer;
156 names.members_name = b_members_name.buffer;
157
158 abuf_free(base_name);
159 abuf_free(part_name);
160 abuf_free(member_name);
161
Lev Walkin5efafc52017-09-05 03:43:00 -0700162 /* A _subset_ of names is checked against being globally unique */
163 register_global_name(arg, names.base_name);
164 register_global_name(arg, names.full_name);
165 register_global_name(arg, names.presence_enum);
166 register_global_name(arg, names.presence_name);
167 register_global_name(arg, names.members_enum);
168 register_global_name(arg, names.members_name);
169
170 arg->expr->_mark |= TM_NAMEGIVEN;
171
Lev Walkinb46156d2017-09-05 02:53:05 -0700172 return names;
173}
174
175struct c_names
176c_name(arg_t *arg) {
177 return c_name_impl(arg, 1);
178}
179
180const char *
181c_member_name(arg_t *arg, asn1p_expr_t *expr) {
182 static abuf ab;
183
184 abuf_clear(&ab);
185
Lev Walkin9023dea2017-09-11 08:40:15 -0700186 abuf_str(&ab, c_name_impl(arg, 0).base_name);
187 abuf_str(&ab, "_");
188 abuf_str(&ab, asn1c_make_identifier(0, expr, 0));
Lev Walkinb46156d2017-09-05 02:53:05 -0700189
190 return ab.buffer;
191}
192
193
194const char *
195c_presence_name(arg_t *arg, asn1p_expr_t *expr) {
196 static abuf ab;
197
198 abuf_clear(&ab);
199
200 if(expr) {
Lev Walkin9023dea2017-09-11 08:40:15 -0700201 abuf_str(&ab, c_name_impl(arg, 0).base_name);
202 abuf_str(&ab, "_PR_");
203 abuf_str(&ab, asn1c_make_identifier(0, expr, 0));
Lev Walkinb46156d2017-09-05 02:53:05 -0700204 } else {
205 abuf_printf(&ab, "%s_PR_NOTHING", c_name_impl(arg, 0).base_name);
206 }
207
208 return ab.buffer;
209}