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