NativeEnumerated.c vars NULL init and check
[com/asn1c.git] / libasn1compiler / asn1c_naming.c
1 #include "asn1c_internal.h"
2 #include "asn1c_naming.h"
3 #include "asn1c_misc.h"
4 #include <asn1_buffer.h>
5 #include <genhash.h>
6
7 struct 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 };
13
14 genhash_t *used_names_hash;
15
16 static void
17 name_entry_destroy(void *np) {
18     struct intl_name *n = np;
19
20     union {
21         const char *c_buf;
22         char *nc_buf;
23     } const_cast;
24
25     asn1p_expr_free(n->expr);
26     asn1p_expr_free(n->clashes_with);
27     const_cast.c_buf = n->name;
28     free(const_cast.nc_buf);
29     free(n);
30 }
31
32 void
33 c_name_clash_finder_init() {
34     assert(used_names_hash == NULL);
35     used_names_hash =
36         genhash_new(cmpf_string, hashf_string, NULL, name_entry_destroy);
37     assert(used_names_hash);
38 }
39
40 void
41 c_name_clash_finder_destroy() {
42     genhash_destroy(used_names_hash);
43     used_names_hash = NULL;
44 }
45
46 static void
47 register_global_name(asn1p_expr_t *expr, const char *name) {
48     struct intl_name *n;
49
50     n = genhash_get(used_names_hash, (const void *)name);
51     if(n) {
52         if(!(expr->_mark & TM_NAMEGIVEN) && (expr != n->expr)) {
53             n->clashes_with = expr;
54             expr->ref_cnt++;
55             return;
56         }
57     }
58
59     if(expr->_mark & TM_NAMEGIVEN)
60         return;
61
62     char *name_copy = strdup(name);
63
64     n = calloc(1, sizeof(*n));
65     assert(n);
66     n->expr = expr;
67     expr->ref_cnt++;
68     n->name = name_copy;
69     int ret = genhash_add(used_names_hash, name_copy, n);
70     assert(ret == 0);
71 }
72
73 int
74 c_name_clash(arg_t *arg) {
75     struct intl_name *n;
76     size_t n_clashes = 0;
77     const size_t max_clashes = 5;
78
79     genhash_iter_t iter;
80
81     genhash_iter_init(&iter, used_names_hash, 0);
82     while(genhash_iter(&iter, NULL, (void *)&n)) {
83         if(n->clashes_with) {
84             if(n_clashes++ > max_clashes) continue;
85             FATAL(
86                 "Name \"%s\" is generated by %s.%s at line %s:%d and "
87                 "%s.%s at line %s:%d",
88                 n->name, n->expr->module->ModuleName, n->expr->Identifier,
89                 n->expr->module->source_file_name, n->expr->_lineno,
90                 n->clashes_with->module->ModuleName,
91                 n->clashes_with->Identifier,
92                 n->clashes_with->module->source_file_name,
93                 n->clashes_with->_lineno);
94         }
95     }
96
97     genhash_iter_done(&iter);
98
99     if(n_clashes > max_clashes) {
100         FATAL("... %zu more name clashes not shown", n_clashes - max_clashes);
101     }
102
103     return n_clashes > 0;
104 }
105
106
107 static abuf *
108 construct_base_name(abuf *buf, asn1p_expr_t *expr, int compound_names,
109                     int avoid_keywords, enum ami_flags_e flag) {
110     const char *id;
111
112     assert(buf);
113
114     if(compound_names && expr->parent_expr) {
115         construct_base_name(buf, expr->parent_expr, compound_names, 0, flag);
116         if(buf->length) {
117             abuf_str(buf, "__"); /* component separator */
118         }
119     }
120
121     id = asn1c_make_identifier(
122         ((avoid_keywords && !buf->length) ? AMI_CHECK_RESERVED : 0) | flag, expr, 0);
123
124     abuf_str(buf, id);
125
126     return buf;
127 }
128
129 static struct c_names
130 c_name_impl(arg_t *arg, asn1p_expr_t *expr, int avoid_keywords) {
131     asn1p_expr_type_e expr_type = expr->expr_type;
132     struct c_names names;
133     int compound_names = 0;
134
135     static abuf b_type_asn_name;
136     static abuf b_type_part_name;
137     static abuf b_type_base_name;
138     static abuf b_type_c_name;
139     static abuf b_type_constrained_c_name;
140     static abuf b_asn_name;
141     static abuf b_part_name;
142     static abuf b_base_name;
143     static abuf b_short_name;
144     static abuf b_full_name;
145     static abuf b_as_member;
146     static abuf b_presence_enum;
147     static abuf b_presence_name;
148     static abuf b_members_enum;
149     static abuf b_members_name;
150
151     abuf_clear(&b_type_asn_name);
152     abuf_clear(&b_type_part_name);
153     abuf_clear(&b_type_base_name);
154     abuf_clear(&b_type_c_name);
155     abuf_clear(&b_type_constrained_c_name);
156     abuf_clear(&b_asn_name);
157     abuf_clear(&b_base_name);
158     abuf_clear(&b_part_name);
159     abuf_clear(&b_short_name);
160     abuf_clear(&b_full_name);
161     abuf_clear(&b_as_member);
162     abuf_clear(&b_presence_enum);
163     abuf_clear(&b_presence_name);
164     abuf_clear(&b_members_enum);
165     abuf_clear(&b_members_name);
166
167     abuf_str(&b_type_asn_name, asn1c_type_name(arg, expr, TNF_UNMODIFIED));
168     abuf_str(&b_type_part_name, asn1c_type_name(arg, expr, TNF_SAFE));
169     abuf_str(&b_type_base_name, asn1c_type_name(arg, expr, TNF_SAFE));
170     abuf_str(&b_type_c_name, asn1c_type_name(arg, expr, TNF_CTYPE));
171     abuf_str(&b_type_constrained_c_name,
172              asn1c_type_name(arg, expr, TNF_CONSTYPE));
173
174
175     if((arg->flags & A1C_COMPOUND_NAMES)) {
176         if((expr_type & ASN_CONSTR_MASK)
177            || expr_type == ASN_BASIC_ENUMERATED
178            || ((expr_type == ASN_BASIC_INTEGER
179                 || expr_type == ASN_BASIC_BIT_STRING))) {
180             compound_names = 1;
181         }
182     }
183
184     construct_base_name(&b_asn_name, expr, 0, 0, 0);
185     construct_base_name(&b_part_name, expr, 0, 0, AMI_USE_PREFIX);
186     construct_base_name(&b_base_name, expr, compound_names, avoid_keywords, 0);
187     construct_base_name(&b_as_member, expr, 0, 1, 0);
188
189     static abuf tmp_compoundable_part_name;
190     static abuf compound_part_name;
191     abuf_clear(&tmp_compoundable_part_name);
192     abuf_clear(&compound_part_name);
193     construct_base_name(&tmp_compoundable_part_name, expr, compound_names, 0, 0);
194     construct_base_name(&compound_part_name, expr, 1, 0, 0);
195
196     if(strlen(asn1c_prefix()) == 0) {
197         if(!expr->_anonymous_type) {
198             if(arg->embed) {
199                 abuf_printf(&b_short_name, "%s", b_as_member.buffer);
200             } else {
201                 abuf_printf(&b_short_name, "%s_t", b_as_member.buffer);
202             }
203         }
204         abuf_printf(&b_full_name, "struct %s", b_base_name.buffer);
205         abuf_printf(&b_presence_enum, "enum %s_PR", tmp_compoundable_part_name.buffer);
206         abuf_printf(&b_presence_name, "%s_PR", tmp_compoundable_part_name.buffer);
207         abuf_printf(&b_members_enum, "enum %s", b_base_name.buffer);
208         abuf_printf(&b_members_name, "e_%s", tmp_compoundable_part_name.buffer);
209    } else {
210         if(!expr->_anonymous_type) {
211             if(arg->embed) {
212                 abuf_printf(&b_short_name, "%s%s", asn1c_prefix(), b_as_member.buffer);
213             } else {
214                 abuf_printf(&b_short_name, "%s%s_t", asn1c_prefix(), b_as_member.buffer);
215             }
216         }
217         abuf_printf(&b_full_name, "struct %s%s", asn1c_prefix(), b_base_name.buffer);
218         abuf_printf(&b_presence_enum, "enum %s%s_PR", asn1c_prefix(), tmp_compoundable_part_name.buffer);
219         abuf_printf(&b_presence_name, "%s%s_PR", asn1c_prefix(), tmp_compoundable_part_name.buffer);
220         abuf_printf(&b_members_enum, "enum %s%s", asn1c_prefix(), b_base_name.buffer);
221         abuf_printf(&b_members_name, "e_%s%s", asn1c_prefix(), tmp_compoundable_part_name.buffer);
222     }
223
224     names.type.asn_name = b_type_asn_name.buffer;
225     names.type.base_name = b_type_base_name.buffer;
226     names.type.part_name = b_type_part_name.buffer;
227     names.type.c_name = b_type_c_name.buffer;
228     names.type.constrained_c_name = b_type_constrained_c_name.buffer;
229     names.asn_name = b_asn_name.buffer;
230     names.part_name = b_part_name.buffer;
231     names.base_name = b_base_name.buffer;
232     names.short_name = b_short_name.buffer;
233     names.full_name = b_full_name.buffer;
234     names.as_member = b_as_member.buffer;
235     names.presence_enum = b_presence_enum.buffer;
236     names.presence_name = b_presence_name.buffer;
237     names.members_enum = b_members_enum.buffer;
238     names.members_name = b_members_name.buffer;
239     names.compound_name = compound_part_name.buffer;
240
241     /* A _subset_ of names is checked against being globally unique */
242     register_global_name(expr, names.base_name);
243     register_global_name(expr, names.full_name);
244     register_global_name(expr, names.presence_enum);
245     register_global_name(expr, names.presence_name);
246     register_global_name(expr, names.members_enum);
247     register_global_name(expr, names.members_name);
248
249     expr->_mark |= TM_NAMEGIVEN;
250
251     return names;
252 }
253
254 struct c_names
255 c_name(arg_t *arg) {
256     return c_name_impl(arg, arg->expr, 1);
257 }
258
259 struct c_names
260 c_expr_name(arg_t *arg, asn1p_expr_t *expr) {
261     return c_name_impl(arg, expr, 1);
262 }
263
264 const char *
265 c_member_name(arg_t *arg, asn1p_expr_t *expr) {
266     static abuf ab;
267
268     abuf_clear(&ab);
269
270     /* NB: do not use part_name, doesn't work for -fcompound-names */
271     abuf_str(&ab, asn1c_prefix());
272     abuf_str(&ab, c_name_impl(arg, arg->expr, 0).base_name);
273     abuf_str(&ab, "_");
274     abuf_str(&ab, asn1c_make_identifier(0, expr, 0));
275
276     return ab.buffer;
277 }
278
279
280 const char *
281 c_presence_name(arg_t *arg, asn1p_expr_t *expr) {
282     static abuf ab;
283
284     abuf_clear(&ab);
285
286     abuf_str(&ab, asn1c_prefix());
287     if(expr) {
288         /* NB: do not use part_name, doesn't work for -fcompound-names */
289         abuf_str(&ab, c_name_impl(arg, arg->expr, 0).base_name);
290         abuf_str(&ab, "_PR_");
291         abuf_str(&ab, asn1c_make_identifier(0, expr, 0));
292     } else {
293         abuf_printf(&ab, "%s_PR_NOTHING",
294                     c_name_impl(arg, arg->expr, 0).base_name);
295     }
296
297     return ab.buffer;
298 }
299
300 const char *
301 c_names_format(struct c_names ns) {
302     static abuf nbuf;
303     abuf_clear(&nbuf);
304
305 #define FMT_COMPONENT(x) abuf_printf(&nbuf, " ." #x "=\"%s\",", ns.x);
306
307     abuf_str(&nbuf, "{");
308     FMT_COMPONENT(type.asn_name);
309     FMT_COMPONENT(type.part_name);
310     FMT_COMPONENT(type.base_name);
311     FMT_COMPONENT(type.c_name);
312     FMT_COMPONENT(type.constrained_c_name);
313     FMT_COMPONENT(asn_name);
314     FMT_COMPONENT(part_name);
315     FMT_COMPONENT(base_name);
316     FMT_COMPONENT(full_name);
317     FMT_COMPONENT(short_name);
318     FMT_COMPONENT(full_name);
319     FMT_COMPONENT(as_member);
320     FMT_COMPONENT(presence_enum);
321     FMT_COMPONENT(presence_name);
322     FMT_COMPONENT(members_enum);
323     FMT_COMPONENT(members_name);
324     abuf_printf(&nbuf, " .members_name=\"%s\" }", ns.members_name);
325     return nbuf.buffer;
326 }
327