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