NativeEnumerated.c vars NULL init and check
[com/asn1c.git] / libasn1compiler / asn1c_C.c
1 /*
2  * Don't look into this file. First, because it's a mess, and second, because
3  * it's a brain of the compiler, and you don't wanna mess with brains do you? ;)
4  */
5 #include "asn1c_internal.h"
6 #include "asn1c_C.h"
7 #include "asn1c_constraint.h"
8 #include "asn1c_out.h"
9 #include "asn1c_misc.h"
10 #include "asn1c_ioc.h"
11 #include "asn1c_naming.h"
12 #include <asn1print.h>
13 #include <asn1fix_crange.h>     /* constraint groker from libasn1fix */
14 #include <asn1fix_export.h>     /* other exportables from libasn1fix */
15 #include <asn1parser.h>
16
17 typedef struct tag2el_s {
18         struct asn1p_type_tag_s el_tag;
19         int el_no;
20         int toff_first;
21         int toff_last;
22         asn1p_expr_t *from_expr;
23 } tag2el_t;
24
25 typedef enum fte {
26         FTE_ALLTAGS,
27         FTE_CANONICAL_XER,
28 } fte_e;
29 static int _fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags);
30 static int _add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags);
31
32 enum onc_flags {
33         ONC_noflags             = 0x00,
34         ONC_avoid_keywords      = 0x01,
35         ONC_force_compound_name = 0x02,
36 };
37 static int out_name_chain(arg_t *arg, enum onc_flags);
38 static int asn1c_lang_C_type_SEQUENCE_def(
39     arg_t *arg, asn1c_ioc_table_and_objset_t *);
40 static int asn1c_lang_C_type_SET_def(arg_t *arg);
41 static int asn1c_lang_C_type_CHOICE_def(arg_t *arg);
42 static int asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of);
43 static int asn1c_lang_C_OpenType(arg_t *arg, asn1c_ioc_table_and_objset_t *opt_ioc, const char *column_name);
44 static int _print_tag(arg_t *arg, struct asn1p_type_tag_s *tag_p);
45 static int compute_extensions_start(asn1p_expr_t *expr);
46 static int expr_break_recursion(arg_t *arg, asn1p_expr_t *expr);
47 static int expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr);
48 static int expr_elements_count(arg_t *arg, asn1p_expr_t *expr);
49 static int emit_single_member_OER_constraint_value(arg_t *arg, asn1cnst_range_t *range);
50 static int emit_single_member_OER_constraint_size(arg_t *arg, asn1cnst_range_t *range);
51 static int emit_single_member_PER_constraint(arg_t *arg, asn1cnst_range_t *range, int juscountvalues, const char *type);
52 static int emit_member_OER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx);
53 static int emit_member_PER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx);
54 static int emit_member_table(arg_t *arg, asn1p_expr_t *expr,
55                              asn1c_ioc_table_and_objset_t *);
56 static int emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier);
57 static int emit_include_dependencies(arg_t *arg);
58 static asn1p_expr_t *terminal_structable(arg_t *arg, asn1p_expr_t *expr);
59 static int expr_defined_recursively(arg_t *arg, asn1p_expr_t *expr);
60 static int asn1c_recurse(arg_t *arg, asn1p_expr_t *expr, int (*callback)(arg_t *arg, void *key), void *key);
61 static asn1p_expr_type_e expr_get_type(arg_t *arg, asn1p_expr_t *expr);
62 static int try_inline_default(arg_t *arg, asn1p_expr_t *expr, int out);
63 static int *compute_canonical_members_order(arg_t *arg, int el_count);
64
65 enum tvm_compat {
66         _TVM_SAME       = 0,    /* tags and all_tags are same */
67         _TVM_SUBSET     = 1,    /* tags are subset of all_tags */
68         _TVM_DIFFERENT  = 2,    /* tags and all_tags are different */
69 };
70 static enum tvm_compat emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tc, int *atc);
71
72 enum etd_spec {
73         ETD_NO_SPECIFICS,
74         ETD_HAS_SPECIFICS
75 };
76 static int emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, enum tvm_compat tv_mode, int tags_count, int all_tags_count, int elements_count, enum etd_spec);
77
78 #define C99_MODE        (!(arg->flags & A1C_NO_C99))
79 #define UNNAMED_UNIONS  (arg->flags & A1C_UNNAMED_UNIONS)
80 #define HIDE_INNER_DEFS (arg->embed && !(arg->flags & A1C_ALL_DEFS_GLOBAL))
81
82 #define PCTX_DEF INDENTED(              \
83         OUT("\n");                      \
84         OUT("/* Context for parsing across buffer boundaries */\n");    \
85         OUT("asn_struct_ctx_t _asn_ctx;\n"));
86
87
88 #define DEPENDENCIES    do {                                            \
89         emit_include_dependencies(arg);                                 \
90         if(expr->expr_type == ASN_CONSTR_SET_OF)                        \
91                 GEN_INCLUDE_STD("asn_SET_OF");                          \
92         if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF)                   \
93                 GEN_INCLUDE_STD("asn_SEQUENCE_OF");                     \
94 } while(0)
95
96 /* MKID_safe() without checking for reserved keywords */
97 #define MKID(expr)      (asn1c_make_identifier(AMI_USE_PREFIX, expr, 0))
98 #define MKID_safe(expr) (asn1c_make_identifier(AMI_CHECK_RESERVED, expr, 0))
99
100 int
101 asn1c_lang_C_type_REAL(arg_t *arg) {
102         return asn1c_lang_C_type_SIMPLE_TYPE(arg);
103 }
104
105 struct value2enum {
106         asn1c_integer_t  value;
107         const char      *name;
108         int              idx;
109 };
110 static int compar_enumMap_byName(const void *ap, const void *bp) {
111         const struct value2enum *a = (const struct value2enum *)ap;
112         const struct value2enum *b = (const struct value2enum *)bp;
113         return strcmp(a->name, b->name);
114 }
115 static int compar_enumMap_byValue(const void *ap, const void *bp) {
116         const struct value2enum *a = (const struct value2enum *)ap;
117         const struct value2enum *b = (const struct value2enum *)bp;
118         if(a->value < b->value)
119                 return -1;
120         else if(a->value == b->value)
121                 return 0;
122         return 1;
123 }
124
125 int
126 asn1c_lang_C_type_common_INTEGER(arg_t *arg) {
127         asn1p_expr_t *expr = arg->expr;
128         asn1p_expr_t *v;
129         int el_count = expr_elements_count(arg, expr);
130         struct value2enum *v2e;
131         int map_extensions = (expr->expr_type == ASN_BASIC_INTEGER);
132         int eidx;
133         int saved_target = arg->target->target;
134
135         v2e = calloc(el_count + 1, sizeof(*v2e));
136         assert(v2e);
137
138         /*
139          * For all ENUMERATED types and for those INTEGER types which
140          * have identifiers, print out an enumeration table.
141          */
142         if(expr->expr_type == ASN_BASIC_ENUMERATED || el_count) {
143                 eidx = 0;
144                 REDIR(OT_DEPS);
145                 OUT("typedef %s {\n", c_name(arg).members_enum);
146                 TQ_FOR(v, &(expr->members), next) {
147                         switch(v->expr_type) {
148                         case A1TC_UNIVERVAL:
149                                 OUT("\t");
150                                 OUT("%s", c_member_name(arg, v));
151                                 OUT("\t= %s%s\n",
152                                         asn1p_itoa(v->value->value.v_integer),
153                                         (eidx+1 < el_count) ? "," : "");
154                                 v2e[eidx].name = v->Identifier;
155                                 v2e[eidx].value = v->value->value.v_integer;
156                                 eidx++;
157                                 break;
158                         case A1TC_EXTENSIBLE:
159                                 OUT("\t/*\n");
160                                 OUT("\t * Enumeration is extensible\n");
161                                 OUT("\t */\n");
162                                 if(!map_extensions)
163                                         map_extensions = eidx + 1;
164                                 break;
165                         default:
166                                 free(v2e);
167                                 return -1;
168                         }
169                 }
170                 OUT("} %s;\n", c_name(arg).members_name);
171                 assert(eidx == el_count);
172         }
173
174         /*
175          * For all ENUMERATED types print out a mapping table
176          * between identifiers and associated values.
177          * This is prohibited for INTEGER types by by X.693:8.3.4.
178          */
179         if(expr->expr_type == ASN_BASIC_ENUMERATED) {
180
181                 /*
182                  * Generate a enumerationName<->value map for XER codec.
183                  */
184                 REDIR(OT_STAT_DEFS);
185
186                 OUT("static const asn_INTEGER_enum_map_t asn_MAP_%s_value2enum_%d[] = {\n",
187                         MKID(expr), expr->_type_unique_index);
188                 qsort(v2e, el_count, sizeof(v2e[0]), compar_enumMap_byValue);
189                 for(eidx = 0; eidx < el_count; eidx++) {
190                         v2e[eidx].idx = eidx;
191                         OUT("\t{ %s,\t%ld,\t\"%s\" }%s\n",
192                                 asn1p_itoa(v2e[eidx].value),
193                                 (long)strlen(v2e[eidx].name), v2e[eidx].name,
194                                 (eidx + 1 < el_count) ? "," : "");
195                 }
196                 if(map_extensions)
197                         OUT("\t/* This list is extensible */\n");
198                 OUT("};\n");
199
200                 OUT("static const unsigned int asn_MAP_%s_enum2value_%d[] = {\n",
201                         MKID(expr), expr->_type_unique_index);
202                 qsort(v2e, el_count, sizeof(v2e[0]), compar_enumMap_byName);
203                 for(eidx = 0; eidx < el_count; eidx++) {
204                         OUT("\t%d%s\t/* %s(%s) */\n",
205                                 v2e[eidx].idx,
206                                 (eidx + 1 < el_count) ? "," : "",
207                                 v2e[eidx].name, asn1p_itoa(v2e[eidx].value));
208                 }
209                 if(map_extensions)
210                         OUT("\t/* This list is extensible */\n");
211                 OUT("};\n");
212
213                 if(!(expr->_type_referenced)) OUT("static ");
214                 OUT("const asn_INTEGER_specifics_t asn_SPC_%s_specs_%d = {\n",
215                         MKID(expr), expr->_type_unique_index);
216                 INDENT(+1);
217                 OUT("asn_MAP_%s_value2enum_%d,\t"
218                         "/* \"tag\" => N; sorted by tag */\n",
219                         MKID(expr),
220                         expr->_type_unique_index);
221                 OUT("asn_MAP_%s_enum2value_%d,\t"
222                         "/* N => \"tag\"; sorted by N */\n",
223                         MKID(expr),
224                         expr->_type_unique_index);
225                 OUT("%d,\t/* Number of elements in the maps */\n",
226                         el_count);
227                 if(map_extensions) {
228                         OUT("%d,\t/* Extensions before this member */\n",
229                                 map_extensions);
230                 } else {
231                         OUT("0,\t/* Enumeration is not extensible */\n");
232                 }
233                 if(expr->expr_type == ASN_BASIC_ENUMERATED)
234                         OUT("1,\t/* Strict enumeration */\n");
235                 else
236                         OUT("0,\n");
237                 OUT("0,\t/* Native long size */\n");
238                 OUT("0\n");
239                 INDENT(-1);
240                 OUT("};\n");
241         }
242
243         if(expr->expr_type == ASN_BASIC_INTEGER
244         && asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN) {
245                 REDIR(OT_STAT_DEFS);
246                 if(!(expr->_type_referenced)) OUT("static ");
247                 OUT("const asn_INTEGER_specifics_t asn_SPC_%s_specs_%d = {\n",
248                         MKID(expr), expr->_type_unique_index);
249                 INDENT(+1);
250                 OUT("0,\t");
251                 OUT("0,\t");
252                 OUT("0,\t");
253                 OUT("0,\t");
254                 OUT("0,\n");
255                 OUT("0,\t/* Native long size */\n");
256                 OUT("1\t/* Unsigned representation */\n");
257                 INDENT(-1);
258                 OUT("};\n");
259         }
260
261         REDIR(saved_target);
262
263         free(v2e);
264         return asn1c_lang_C_type_SIMPLE_TYPE(arg);
265 }
266
267 int
268 asn1c_lang_C_type_BIT_STRING(arg_t *arg) {
269         asn1p_expr_t *expr = arg->expr;
270         asn1p_expr_t *v;
271         int el_count = expr_elements_count(arg, expr);
272         int saved_target = arg->target->target;
273
274         if(el_count) {
275                 int eidx = 0;
276                 REDIR(OT_DEPS);
277                 OUT("typedef %s {\n", c_name(arg).members_enum);
278                 TQ_FOR(v, &(expr->members), next) {
279                         if(v->expr_type != A1TC_UNIVERVAL) {
280                                 OUT("/* Unexpected BIT STRING element: %s */\n",
281                                 v->Identifier);
282                                 continue;
283                         }
284                         eidx++;
285                         OUT("\t");
286                         OUT("%s", c_member_name(arg, v));
287                         OUT("\t= %s%s\n",
288                                 asn1p_itoa(v->value->value.v_integer),
289                                 (eidx < el_count) ? "," : "");
290                 }
291                 OUT("} %s;\n", c_name(arg).members_name);
292                 assert(eidx == el_count);
293         }
294
295         REDIR(saved_target);
296
297         return asn1c_lang_C_type_SIMPLE_TYPE(arg);
298 }
299
300 /*
301  * Check if it is a true open type. That is, type is taken from
302  * the Information Object Set driven constraints.
303  */
304 static int
305 is_open_type(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_objset_t *opt_ioc) {
306
307     (void)arg;
308
309     if(!opt_ioc) {
310         return 0;
311     }
312
313     if(expr->meta_type == AMT_TYPEREF
314        && expr->expr_type == A1TC_REFERENCE
315        && expr->reference->comp_count == 2
316        && expr->reference->components[1].lex_type
317               == RLT_AmpUppercase) {
318         DEBUG("%s is a true open type", MKID(expr));
319         return 1;
320     }
321
322     return 0;
323 }
324
325 int
326 asn1c_lang_C_type_SEQUENCE(arg_t *arg) {
327         asn1p_expr_t *expr = arg->expr;
328         asn1p_expr_t *v;
329         int comp_mode = 0;      /* {root,ext=1,root,root,...} */
330         int saved_target = arg->target->target;
331     asn1c_ioc_table_and_objset_t ioc_tao;
332         int ext_num = 1;
333
334         DEPENDENCIES;
335
336     ioc_tao = asn1c_get_ioc_table(arg);
337     if(ioc_tao.ioct) {
338         if(emit_ioc_table(arg, expr, ioc_tao)) {
339             return -1;
340         }
341     } else if(ioc_tao.fatal_error) {
342         return -1;
343     }
344
345         if(arg->embed) {
346
347                 /* Use _anonymous_type field to indicate it's called from
348                  * asn1c_lang_C_type_SEx_OF() */
349                 if (expr->_anonymous_type) {
350                         REDIR(OT_FWD_DEFS);
351                         OUT("typedef ");
352                 }
353                 OUT("%s {\n", c_name(arg).full_name);
354         } else {
355                 REDIR(OT_TYPE_DECLS);
356                 OUT("typedef %s {\n", c_name(arg).full_name);
357         }
358
359         TQ_FOR(v, &(expr->members), next) {
360                 if(v->expr_type == A1TC_EXTENSIBLE)
361                         if(comp_mode < 3) comp_mode++;
362                 if(comp_mode == 1)
363                         v->marker.flags |= EM_OMITABLE | EM_INDIRECT;
364                 try_inline_default(arg, v, 1);
365         if(is_open_type(arg, v, ioc_tao.ioct ? &ioc_tao : 0)) {
366             arg_t tmp_arg = *arg;
367             tmp_arg.embed++;
368             INDENT(+1);
369             tmp_arg.expr = v;
370             const char *column_name = v->reference->components[1].name;
371             if(asn1c_lang_C_OpenType(&tmp_arg, &ioc_tao, column_name)) {
372                 return -1;
373             }
374             INDENT(-1);
375             tmp_arg.embed--;
376         } else {
377             char ext_name[20];
378
379             if((v->expr_type == ASN_CONSTR_SEQUENCE) &&
380                (v->marker.flags & EM_OPTIONAL) &&
381                (v->Identifier == NULL)) {
382                 sprintf(ext_name, "ext%d", ext_num++);
383                 v->Identifier = strdup(ext_name);
384             }
385
386             EMBED_WITH_IOCT(v, ioc_tao);
387         }
388         }
389
390         PCTX_DEF;
391
392         if (arg->embed && expr->_anonymous_type) {
393                 OUT("} %s%s;\n", (expr->marker.flags & EM_INDIRECT)?"*":"",
394                         c_name(arg).base_name);
395
396                 REDIR(saved_target);
397
398                 OUT("%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
399                         c_name(arg).base_name);
400         } else {
401                 OUT("} %s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
402                         arg->embed ? c_name(arg).as_member : c_name(arg).short_name);
403                 if(!expr->_anonymous_type) OUT(";\n");
404         }
405
406         return asn1c_lang_C_type_SEQUENCE_def(arg, ioc_tao.ioct ? &ioc_tao : 0);
407 }
408
409 static void
410 emit_tag2member_reference(arg_t *arg, asn1p_expr_t *expr,
411                           unsigned tag2el_count) {
412     if(tag2el_count) {
413         if(C99_MODE) OUT(".tag2el = ");
414         OUT("asn_MAP_%s_tag2el_%d,\n", MKID(expr), expr->_type_unique_index);
415         if(C99_MODE) OUT(".tag2el_count = ");
416         OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
417     } else {
418         OUT("0,\t/* No top level tags */\n");
419         OUT("0,\t/* No tags in the map */\n");
420     }
421 }
422
423 static int
424 asn1c_lang_C_type_SEQUENCE_def(arg_t *arg, asn1c_ioc_table_and_objset_t *opt_ioc) {
425         asn1p_expr_t *expr = arg->expr;
426         asn1p_expr_t *v;
427         int elements;   /* Number of elements */
428         int first_extension = -1;
429         tag2el_t *tag2el = NULL;
430         int tag2el_count = 0;
431         int tags_count;
432         int all_tags_count;
433         enum tvm_compat tv_mode;
434         int roms_count;         /* Root optional members */
435         int aoms_count;         /* Additions optional members */
436         int saved_target = arg->target->target;
437
438         /*
439          * Fetch every inner tag from the tag to elements map.
440          */
441         if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
442                 if(tag2el) free(tag2el);
443                 return -1;
444         }
445
446         GEN_INCLUDE_STD("constr_SEQUENCE");
447         if(!arg->embed)
448                 GEN_DECLARE("SEQUENCE", expr);  /* asn_DEF_xxx */
449
450         REDIR(OT_STAT_DEFS);
451
452         /*
453          * Print out the table according to which parsing is performed.
454          */
455         if(expr_elements_count(arg, expr)) {
456                 int comp_mode = 0;      /* {root,ext=1,root,root,...} */
457
458                 if(!(expr->_type_referenced)) OUT("static ");
459                 OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
460                         c_name(arg).part_name, expr->_type_unique_index);
461
462                 elements = 0;
463                 roms_count = 0;
464                 aoms_count = 0;
465                 INDENTED(TQ_FOR(v, &(expr->members), next) {
466                         if(v->expr_type == A1TC_EXTENSIBLE) {
467                                 if((++comp_mode) == 1)
468                                         first_extension = elements;
469                                 continue;
470                         }
471                         if(v->marker.flags & EM_OMITABLE)
472                             comp_mode == 1 ? ++aoms_count : ++roms_count;
473                         if(emit_member_table(arg, v, opt_ioc) < 0)
474                                 return -1;
475                         elements++;
476                 });
477                 OUT("};\n");
478
479                 if((roms_count + aoms_count) && (arg->flags & (A1C_GEN_OER|A1C_GEN_PER))) {
480                         int elm = 0;
481                         int comma = 0;
482                         comp_mode = 0;
483                         OUT("static const int asn_MAP_%s_oms_%d[] = {",
484                                 MKID(expr),
485                                 expr->_type_unique_index);
486                         TQ_FOR(v, &(expr->members), next) {
487                                 if(v->expr_type == A1TC_EXTENSIBLE) {
488                                         ++comp_mode;
489                                         continue;
490                                 }
491                                 if((v->marker.flags & EM_OMITABLE)
492                                 && comp_mode != 1) {
493                                         if(!comma) comma++;
494                                         else OUT(",");
495                                         OUT(" %d", elm);
496                                 }
497                                 ++elm;
498                         }
499                         elm = 0;
500                         comp_mode = 0;
501                         TQ_FOR(v, &(expr->members), next) {
502                                 if(v->expr_type == A1TC_EXTENSIBLE) {
503                                         ++comp_mode;
504                                         continue;
505                                 }
506                                 if((v->marker.flags & EM_OMITABLE)
507                                 && comp_mode == 1) {
508                                         if(!comma) comma++;
509                                         else OUT(",");
510                                         OUT(" %d", elm);
511                                 }
512                                 ++elm;
513                         }
514                         OUT(" };\n");
515                         if(roms_count > 65536) {
516                                 FATAL("Too many optional elements in %s "
517                                         "at line %d!",
518                                         arg->expr->Identifier,
519                                         arg->expr->_lineno);
520                 return -1;
521             }
522                 } else {
523                         roms_count = 0;
524                         aoms_count = 0;
525                 }
526         } else {
527                 elements = 0;
528                 roms_count = 0;
529                 aoms_count = 0;
530         }
531
532         /*
533          * Print out asn_DEF_<type>_[all_]tags[] vectors.
534          */
535         tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
536
537         /*
538          * Tags to elements map.
539          */
540         emit_tag2member_map(arg, tag2el, tag2el_count, 0);
541
542         if(!(expr->_type_referenced)) OUT("static ");
543         OUT("asn_SEQUENCE_specifics_t asn_SPC_%s_specs_%d = {\n",
544                 MKID(expr), expr->_type_unique_index);
545         INDENT(+1);
546         OUT("sizeof(%s),\n", c_name(arg).full_name);
547         OUT("offsetof(%s, _asn_ctx),\n", c_name(arg).full_name);
548     emit_tag2member_reference(arg, expr, tag2el_count);
549         if(roms_count + aoms_count) {
550                 OUT("asn_MAP_%s_oms_%d,\t/* Optional members */\n",
551                         MKID(expr), expr->_type_unique_index);
552                 OUT("%d, %d,\t/* Root/Additions */\n", roms_count, aoms_count);
553         } else {
554                 OUT("0, 0, 0,\t/* Optional elements (not needed) */\n");
555         }
556         OUT("%d,\t/* First extension addition */\n", first_extension);
557         INDENT(-1);
558         OUT("};\n");
559
560         /*
561          * Emit asn_DEF_xxx table.
562          */
563         emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
564                         ETD_HAS_SPECIFICS);
565
566         REDIR(saved_target);
567
568         if(tag2el) free(tag2el);
569
570         return 0;
571 } /* _SEQUENCE_def() */
572
573 int
574 asn1c_lang_C_type_SET(arg_t *arg) {
575         asn1p_expr_t *expr = arg->expr;
576         asn1p_expr_t *v;
577         long mcount;
578         const char *id;
579         int comp_mode = 0;      /* {root,ext=1,root,root,...} */
580         int saved_target = arg->target->target;
581         int ext_num = 1;
582
583         DEPENDENCIES;
584
585         REDIR(OT_DEPS);
586
587         OUT("\n");
588         OUT("/*\n");
589         OUT(" * Method of determining the components presence\n");
590         OUT(" */\n");
591         mcount = 0;
592         OUT("typedef %s {\n", c_name(arg).presence_enum);
593         TQ_FOR(v, &(expr->members), next) {
594                 if(v->expr_type == A1TC_EXTENSIBLE) continue;
595                 INDENTED(
596                         OUT("%s,", c_presence_name(arg, v));
597                         OUT("\t/* Member %s is present */\n", MKID(v));
598                 );
599                 mcount++;
600         }
601         OUT("} %s;\n", c_name(arg).presence_name);
602
603         REDIR(saved_target);
604
605         if(arg->embed) {
606                 if (expr->_anonymous_type) {
607                         REDIR(OT_FWD_DEFS);
608                         OUT("typedef ");
609                 }
610                 OUT("%s {\n", c_name(arg).full_name);
611         } else {
612                 REDIR(OT_TYPE_DECLS);
613                 OUT("typedef %s {\n", c_name(arg).full_name);
614         }
615
616         TQ_FOR(v, &(expr->members), next) {
617                 char ext_name[20];
618
619                 if(v->expr_type == A1TC_EXTENSIBLE)
620                         if(comp_mode < 3) comp_mode++;
621                 if(comp_mode == 1)
622                         v->marker.flags |= EM_OMITABLE | EM_INDIRECT;
623                 try_inline_default(arg, v, 1);
624
625                 if((v->expr_type == ASN_CONSTR_SEQUENCE) &&
626                    (v->marker.flags & EM_OPTIONAL) &&
627                    (v->Identifier == NULL)) {
628                         sprintf(ext_name, "ext%d", ext_num++);
629                         v->Identifier = strdup(ext_name);
630                 }
631                 EMBED(v);
632         }
633
634         INDENTED(
635                 id = MKID(expr);
636                 OUT("\n");
637                 OUT("/* Presence bitmask: ASN_SET_ISPRESENT(p%s, %s_PR_x) */\n",
638                         id, id);
639                 OUT("unsigned int _presence_map\n");
640                 OUT("\t[((%ld+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))];\n", mcount);
641         );
642
643         PCTX_DEF;
644
645         if (arg->embed && expr->_anonymous_type) {
646                 OUT("} %s%s;\n", (expr->marker.flags & EM_INDIRECT)?"*":"",
647                         c_name(arg).base_name);
648
649                 REDIR(saved_target);
650
651                 OUT("%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
652                         c_name(arg).base_name);
653         } else {
654                 OUT("} %s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
655                         arg->embed ? c_name(arg).as_member : c_name(arg).short_name);
656                 if(!expr->_anonymous_type) OUT(";\n");
657         }
658
659         return asn1c_lang_C_type_SET_def(arg);
660 }
661
662 static int
663 asn1c_lang_C_type_SET_def(arg_t *arg) {
664         asn1p_expr_t *expr = arg->expr;
665         asn1p_expr_t *v;
666         int elements;
667         tag2el_t *tag2el = NULL;
668         int tag2el_count = 0;
669         tag2el_t *tag2el_cxer = NULL;
670         int tag2el_cxer_count = 0;
671         int tags_count;
672         int all_tags_count;
673         enum tvm_compat tv_mode;
674         const char *p;
675         int saved_target = arg->target->target;
676
677         /*
678          * Fetch every inner tag from the tag to elements map.
679          */
680         if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
681                 if(tag2el) free(tag2el);
682                 return -1;
683         }
684         if(_fill_tag2el_map(arg, &tag2el_cxer, &tag2el_cxer_count, -1, FTE_CANONICAL_XER)) {
685                 if(tag2el) free(tag2el);
686                 if(tag2el_cxer) free(tag2el_cxer);
687                 return -1;
688         }
689         if(tag2el_cxer_count == tag2el_count
690         && memcmp(tag2el, tag2el_cxer, tag2el_count) == 0) {
691                 free(tag2el_cxer);
692                 tag2el_cxer = 0;
693         }
694
695         GEN_INCLUDE_STD("constr_SET");
696         if(!arg->embed)
697                 GEN_DECLARE("SET", expr);       /* asn_DEF_xxx */
698
699         REDIR(OT_STAT_DEFS);
700
701         /*
702          * Print out the table according to which parsing is performed.
703          */
704         if(expr_elements_count(arg, expr)) {
705                 int comp_mode = 0;      /* {root,ext=1,root,root,...} */
706
707                 if(!(expr->_type_referenced)) OUT("static ");
708                 OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
709                         c_name(arg).part_name, expr->_type_unique_index);
710
711                 elements = 0;
712                 INDENTED(TQ_FOR(v, &(expr->members), next) {
713                         if(v->expr_type == A1TC_EXTENSIBLE) {
714                                 if(comp_mode < 3) comp_mode++;
715                         } else {
716                                 emit_member_table(arg, v, NULL);
717                                 elements++;
718                         }
719                 });
720                 OUT("};\n");
721         } else {
722                 elements = 0;
723         }
724
725         /*
726          * Print out asn_DEF_<type>_[all_]tags[] vectors.
727          */
728         tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
729
730         /*
731          * Tags to elements map.
732          */
733         emit_tag2member_map(arg, tag2el, tag2el_count, 0);
734         if(tag2el_cxer)
735         emit_tag2member_map(arg, tag2el_cxer, tag2el_cxer_count, "_cxer");
736
737         /*
738          * Emit a map of mandatory elements.
739          */
740         OUT("static const uint8_t asn_MAP_%s_mmap_%d",
741                 MKID(expr), expr->_type_unique_index);
742         p = MKID_safe(expr);
743         OUT("[(%d + (8 * sizeof(unsigned int)) - 1) / 8]", elements);
744         OUT(" = {\n");
745         INDENTED(
746         if(elements) {
747                 int el = 0;
748                 TQ_FOR(v, &(expr->members), next) {
749                         if(v->expr_type == A1TC_EXTENSIBLE) continue;
750                         if(el) {
751                                 if((el % 8) == 0)
752                                         OUT(",\n");
753                                 else
754                                         OUT(" | ");
755                         }
756                         OUT("(%d << %d)",
757                                 (v->marker.flags & EM_OMITABLE) != EM_OMITABLE,
758                                 7 - (el % 8));
759                         el++;
760                 }
761         } else {
762                 OUT("0");
763         }
764         );
765         OUT("\n");
766         OUT("};\n");
767
768         if(!(expr->_type_referenced)) OUT("static \n");
769         OUT("asn_SET_specifics_t asn_SPC_%s_specs_%d = {\n",
770                 MKID(expr), expr->_type_unique_index);
771         INDENTED(
772                 OUT("sizeof(%s),\n", c_name(arg).full_name);
773                 OUT("offsetof(%s, _asn_ctx),\n", c_name(arg).full_name);
774                 OUT("offsetof(%s, _presence_map),\n", c_name(arg).full_name);
775                 emit_tag2member_reference(arg, expr, tag2el_count);
776                 p = MKID(expr);
777                 if(tag2el_cxer)
778                         OUT("asn_MAP_%s_tag2el_cxer_%d,\n",
779                                 p, expr->_type_unique_index);
780                 else
781                         OUT("asn_MAP_%s_tag2el_%d,\t/* Same as above */\n",
782                                 p, expr->_type_unique_index);
783                 OUT("%d,\t/* Count of tags in the CXER map */\n",
784                         tag2el_cxer_count);
785                 OUT("%d,\t/* Whether extensible */\n",
786                         compute_extensions_start(expr) == -1 ? 0 : 1);
787                 OUT("(const unsigned int *)asn_MAP_%s_mmap_%d\t/* Mandatory elements map */\n",
788                         p, expr->_type_unique_index);
789         );
790         OUT("};\n");
791
792         /*
793          * Emit asn_DEF_xxx table.
794          */
795         emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
796                         ETD_HAS_SPECIFICS);
797
798         REDIR(saved_target);
799
800         if (tag2el) free(tag2el);
801         if (tag2el_cxer) free(tag2el_cxer);
802
803         return 0;
804 } /* _SET_def() */
805
806 int
807 asn1c_lang_C_type_SEx_OF(arg_t *arg) {
808         asn1p_expr_t *expr = arg->expr;
809         asn1p_expr_t *memb = TQ_FIRST(&expr->members);
810         int saved_target = arg->target->target;
811
812         DEPENDENCIES;
813
814         if(arg->embed) {
815                 if (expr->_anonymous_type) {
816                         REDIR(OT_FWD_DEFS);
817                         OUT("typedef ");
818                 }
819                 OUT("%s {\n", c_name(arg).full_name);
820         } else {
821                 OUT("typedef %s {\n", c_name(arg).full_name);
822         }
823
824         INDENT(+1);
825         OUT("A_%s_OF(",
826                 (arg->expr->expr_type == ASN_CONSTR_SET_OF)
827                         ? "SET" : "SEQUENCE");
828
829         /*
830          * README README
831          * The implementation of the A_SET_OF() macro is already indirect.
832          */
833         memb->marker.flags |= EM_INDIRECT;
834
835         if(memb->expr_type & ASN_CONSTR_MASK
836         || ((memb->expr_type == ASN_BASIC_ENUMERATED
837                 || (0 /* -- prohibited by X.693:8.3.4 */
838                         && memb->expr_type == ASN_BASIC_INTEGER))
839                 && expr_elements_count(arg, memb))) {
840                 arg_t tmp;
841                 asn1p_expr_t *tmp_memb = memb;
842                 enum asn1p_expr_marker_e flags = memb->marker.flags;
843                 arg->embed++;
844                         tmp = *arg;
845                         tmp.expr = tmp_memb;
846                         tmp_memb->marker.flags &= ~EM_INDIRECT;
847                         tmp_memb->_anonymous_type = 1;
848                         if(tmp_memb->Identifier == 0) {
849                                 tmp_memb->Identifier = strdup("Member");
850                                 if(0)
851                                 tmp_memb->Identifier = strdup(
852                                         asn1c_make_identifier(0,
853                                                 expr, "Member", 0));
854                                 assert(tmp_memb->Identifier);
855                         }
856                         tmp.default_cb(&tmp, NULL);
857                         tmp_memb->marker.flags = flags;
858                 arg->embed--;
859                 assert(arg->target->target == OT_TYPE_DECLS ||
860                                 arg->target->target == OT_FWD_DEFS);
861         } else {
862                 OUT("%s", asn1c_type_name(arg, memb,
863                         (memb->marker.flags & EM_UNRECURSE)
864                                 ? TNF_RSAFE : TNF_CTYPE));
865         }
866         /* README README (above) */
867         if(0 && (memb->marker.flags & EM_INDIRECT))
868                 OUT(" *");
869         OUT(") list;\n");
870         INDENT(-1);
871
872         PCTX_DEF;
873
874         if (arg->embed && expr->_anonymous_type) {
875                 OUT("} %s%s;\n", (expr->marker.flags & EM_INDIRECT)?"*":"",
876                         c_name(arg).base_name);
877
878                 REDIR(saved_target);
879
880                 OUT("%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
881                         c_name(arg).base_name);
882         } else {
883                 OUT("} %s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
884                         arg->embed ? c_name(arg).as_member : c_name(arg).short_name);
885                 if(!expr->_anonymous_type) OUT(";\n");
886         }
887
888         /*
889          * SET OF/SEQUENCE OF definition
890          */
891         return asn1c_lang_C_type_SEx_OF_def(arg,
892                 (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF));
893 }
894
895 static int
896 asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
897         asn1p_expr_t *expr = arg->expr;
898         asn1p_expr_t *v;
899         int tags_count;
900         int all_tags_count;
901         enum tvm_compat tv_mode;
902         int saved_target = arg->target->target;
903
904         /*
905          * Print out the table according to which parsing is performed.
906          */
907         if(seq_of) {
908                 GEN_INCLUDE_STD("constr_SEQUENCE_OF");
909         } else {
910                 GEN_INCLUDE_STD("constr_SET_OF");
911         }
912         if(!arg->embed)
913                 GEN_DECLARE("SET_OF", expr);    /* asn_DEF_xxx */
914
915         REDIR(OT_STAT_DEFS);
916
917         /*
918          * Print out the table according to which parsing is performed.
919          */
920         if(!(expr->_type_referenced)) OUT("static ");
921         OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
922                 c_name(arg).part_name, expr->_type_unique_index);
923         INDENT(+1);
924                 v = TQ_FIRST(&(expr->members));
925                 if(!v->Identifier) {
926                         v->Identifier = strdup("Member");
927                         assert(v->Identifier);
928                 }
929                 v->_anonymous_type = 1;
930                 arg->embed++;
931                 emit_member_table(arg, v, NULL);
932                 arg->embed--;
933                 free(v->Identifier);
934                 v->Identifier = (char *)NULL;
935         INDENT(-1);
936         OUT("};\n");
937
938         /*
939          * Print out asn_DEF_<type>_[all_]tags[] vectors.
940          */
941         tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
942
943         if(!(expr->_type_referenced)) OUT("static ");
944         OUT("asn_SET_OF_specifics_t asn_SPC_%s_specs_%d = {\n",
945                 MKID(expr), expr->_type_unique_index);
946         INDENTED(
947                 OUT("sizeof(%s),\n", c_name(arg).full_name);
948                 OUT("offsetof(%s, _asn_ctx),\n", c_name(arg).full_name);
949                 {
950                 int as_xvl = expr_as_xmlvaluelist(arg, v);
951                 OUT("%d,\t/* XER encoding is %s */\n",
952                         as_xvl,
953                         as_xvl ? "XMLValueList" : "XMLDelimitedItemList");
954                 }
955         );
956         OUT("};\n");
957
958         /*
959          * Emit asn_DEF_xxx table.
960          */
961         emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, 1,
962                         ETD_HAS_SPECIFICS);
963
964         REDIR(saved_target);
965
966         return 0;
967 } /* _SEx_OF_def() */
968
969 int
970 asn1c_lang_C_type_CHOICE(arg_t *arg) {
971         asn1p_expr_t *expr = arg->expr;
972         asn1p_expr_t *v;
973         int saved_target = arg->target->target;
974
975         DEPENDENCIES;
976
977         REDIR(OT_DEPS);
978
979         OUT("typedef %s {\n", c_name(arg).presence_enum);
980         INDENTED(
981                 int skipComma = 1;
982                 OUT("%s", c_presence_name(arg, 0));
983                 OUT("%s\t/* No components present */\n", !TQ_FIRST(&(expr->members)) ? "" : ",");
984                 TQ_FOR(v, &(expr->members), next) {
985                         if(skipComma) skipComma = 0;
986                         else if (v->expr_type == A1TC_EXTENSIBLE && !TQ_NEXT(v, next)) OUT("\n");
987                         else OUT(",\n");
988                         if(v->expr_type == A1TC_EXTENSIBLE) {
989                                 OUT("/* Extensions may appear below */\n");
990                                 skipComma = 1;
991                                 continue;
992                         }
993             OUT("%s", c_presence_name(arg, v));
994                 }
995                 OUT("\n");
996         );
997         OUT("} %s;\n", c_name(arg).presence_name);
998
999         REDIR(saved_target);
1000
1001         if(arg->embed) {
1002                 if (expr->_anonymous_type) {
1003                         REDIR(OT_FWD_DEFS);
1004                         OUT("typedef ");
1005                 }
1006                 OUT("%s {\n", c_name(arg).full_name);
1007         } else {
1008                 REDIR(OT_TYPE_DECLS);
1009                 OUT("typedef %s {\n", c_name(arg).full_name);
1010         }
1011
1012         INDENTED(
1013                 OUT("%s present;\n", c_name(arg).presence_name);
1014                 OUT("union ");
1015                 if(UNNAMED_UNIONS == 0) {
1016                         out_name_chain(arg, ONC_force_compound_name);
1017                         OUT("_u ");
1018                 }
1019                 OUT("{\n");
1020                 TQ_FOR(v, &(expr->members), next) {
1021                         EMBED(v);
1022                 }
1023                 if(UNNAMED_UNIONS)      OUT("};\n");
1024                 else                    OUT("} choice;\n");
1025         );
1026
1027         PCTX_DEF;
1028
1029         if (arg->embed && expr->_anonymous_type) {
1030                 OUT("} %s%s;\n", (expr->marker.flags & EM_INDIRECT)?"*":"",
1031                         c_name(arg).base_name);
1032
1033                 REDIR(saved_target);
1034
1035                 OUT("%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
1036                         c_name(arg).base_name);
1037         } else {
1038                 OUT("} %s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
1039                         arg->embed ? c_name(arg).as_member : c_name(arg).short_name);
1040         }
1041         if(!expr->_anonymous_type) OUT(";\n");
1042
1043         return asn1c_lang_C_type_CHOICE_def(arg);
1044 }
1045
1046 static ssize_t
1047 find_column_index(arg_t *arg, asn1c_ioc_table_and_objset_t *opt_ioc, const char *column_name) {
1048     (void)arg;
1049
1050     if(!opt_ioc || !opt_ioc->ioct || !column_name) {
1051         return -1;
1052     }
1053
1054     if(opt_ioc->ioct->rows == 0) {
1055         return 0;   /* No big deal. Just no data */
1056     } else {
1057         for(size_t clmn = 0; clmn < opt_ioc->ioct->row[0]->columns; clmn++) {
1058             if(strcmp(opt_ioc->ioct->row[0]->column[clmn].field->Identifier,
1059                       column_name) == 0) {
1060                 return clmn;
1061             }
1062         }
1063         return -1;
1064     }
1065
1066 }
1067
1068 static int
1069 asn1c_lang_C_OpenType(arg_t *arg, asn1c_ioc_table_and_objset_t *opt_ioc,
1070                       const char *column_name) {
1071     arg_t tmp_arg = *arg;
1072
1073     ssize_t column_index = find_column_index(arg, opt_ioc, column_name);
1074     if(column_index < 0) {
1075         FATAL("Open type generation attempted for %s, incomplete", column_name);
1076         return -1;
1077     }
1078
1079     asn1p_expr_t *open_type_choice =
1080         asn1p_expr_new(arg->expr->_lineno, arg->expr->module);
1081
1082     open_type_choice->Identifier = strdup(arg->expr->Identifier);
1083     open_type_choice->meta_type = AMT_TYPE;
1084     open_type_choice->expr_type = ASN_CONSTR_OPEN_TYPE;
1085     open_type_choice->_type_unique_index = arg->expr->_type_unique_index;
1086     open_type_choice->parent_expr = arg->expr->parent_expr;
1087
1088     for(size_t row = 0; row < opt_ioc->ioct->rows; row++) {
1089         struct asn1p_ioc_cell_s *cell =
1090             &opt_ioc->ioct->row[row]->column[column_index];
1091
1092         if(!cell->value) continue;
1093
1094         if(asn1p_lookup_child(open_type_choice, cell->value->Identifier))
1095             continue;
1096
1097         asn1p_expr_t *m = asn1p_expr_clone(cell->value, 0);
1098         asn1p_expr_add(open_type_choice, m);
1099     }
1100
1101     tmp_arg.expr = open_type_choice;
1102     GEN_INCLUDE_STD("OPEN_TYPE");
1103     asn1c_lang_C_type_CHOICE(&tmp_arg);
1104     asn1p_expr_free(tmp_arg.expr);
1105     return 0;
1106 }
1107
1108 static int
1109 asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
1110         asn1p_expr_t *expr = arg->expr;
1111         asn1p_expr_t *v;
1112         int elements;   /* Number of elements */
1113         tag2el_t *tag2el = NULL;
1114         int tag2el_count = 0;
1115         int tags_count;
1116         int all_tags_count;
1117         enum tvm_compat tv_mode;
1118         int *cmap = 0;
1119         int saved_target = arg->target->target;
1120
1121         /*
1122          * Fetch every inner tag from the tag to elements map.
1123          */
1124         if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
1125                 if(tag2el) free(tag2el);
1126                 return -1;
1127         }
1128
1129         GEN_INCLUDE_STD("constr_CHOICE");
1130         if(!arg->embed)
1131                 GEN_DECLARE("CHOICE", expr);    /* asn_DEF_xxx */
1132
1133         REDIR(OT_STAT_DEFS);
1134
1135         /*
1136          * Print out the table according to which parsing is performed.
1137          */
1138         if(expr_elements_count(arg, expr)) {
1139
1140                 if(!(expr->_type_referenced)) OUT("static ");
1141                 OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
1142                         c_name(arg).part_name, expr->_type_unique_index);
1143
1144                 elements = 0;
1145                 INDENTED(TQ_FOR(v, &(expr->members), next) {
1146                         if(v->expr_type == A1TC_EXTENSIBLE)
1147                                 continue;
1148                         emit_member_table(arg, v, NULL);
1149                         elements++;
1150                 });
1151                 OUT("};\n");
1152         } else {
1153                 elements = 0;
1154         }
1155
1156     /* Create a canonical elements map */
1157     if(elements && (arg->flags & A1C_GEN_PER)) {
1158         cmap = compute_canonical_members_order(arg, elements);
1159         if(cmap) {
1160             OUT("static const unsigned asn_MAP_%s_to_canonical_%d[] = {",
1161                 MKID(expr), expr->_type_unique_index);
1162             for(int i = 0; i < elements; i++) {
1163                 if(i) OUT(",");
1164                 OUT(" %d", cmap[i]);
1165             }
1166             OUT(" };\n");
1167             OUT("static const unsigned asn_MAP_%s_from_canonical_%d[] = {",
1168                 MKID(expr), expr->_type_unique_index);
1169             for(int i = 0; i < elements; i++) {
1170                 if(i) OUT(",");
1171                 int j;
1172                 for(j = 0; j < elements; j++) {
1173                     if(cmap[j] == i) {
1174                         OUT(" %d", j);
1175                         break;
1176                     }
1177                 }
1178                 assert(j < elements);
1179             }
1180             OUT(" };\n");
1181             free(cmap);
1182         }
1183     }
1184
1185         if(arg->embed) {
1186                 /*
1187                  * Our parent structure has already taken this into account.
1188                  */
1189                 tv_mode = _TVM_SAME;
1190                 tags_count = all_tags_count = 0;
1191         } else {
1192                 tv_mode = emit_tags_vectors(arg, expr,
1193                         &tags_count, &all_tags_count);
1194         }
1195
1196         /*
1197          * Tags to elements map.
1198          */
1199         emit_tag2member_map(arg, tag2el, tag2el_count, 0);
1200
1201     if(!(expr->_type_referenced)) OUT("static ");
1202     OUT("asn_CHOICE_specifics_t asn_SPC_%s_specs_%d = {\n", MKID(expr),
1203         expr->_type_unique_index);
1204     INDENTED(
1205         OUT("sizeof(%s),\n", c_name(arg).full_name);
1206         OUT("offsetof(%s, _asn_ctx),\n", c_name(arg).full_name);
1207         OUT("offsetof(%s, present),\n", c_name(arg).full_name);
1208         OUT("sizeof(((%s *)0)->present),\n", c_name(arg).full_name);
1209         emit_tag2member_reference(arg, expr, tag2el_count);
1210         if(cmap) {
1211             if(C99_MODE) OUT(".to_canonical_order = ");
1212             OUT("asn_MAP_%s_to_canonical_%d,\n", MKID(expr),
1213                 expr->_type_unique_index);
1214             if(C99_MODE) OUT(".from_canonical_order = ");
1215             OUT("asn_MAP_%s_from_canonical_%d,\n", MKID(expr),
1216                 expr->_type_unique_index);
1217         } else { OUT("0, 0,\n"); }
1218         if(C99_MODE) OUT(".first_extension = ");
1219         OUT("%d\t/* Extensions start */\n", compute_extensions_start(expr));
1220     );
1221     OUT("};\n");
1222
1223         /*
1224          * Emit asn_DEF_xxx table.
1225          */
1226         emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
1227                         ETD_HAS_SPECIFICS);
1228
1229         REDIR(saved_target);
1230
1231         if (tag2el) free(tag2el);
1232
1233         return 0;
1234 } /* _CHOICE_def() */
1235
1236 int
1237 asn1c_lang_C_type_REFERENCE_Value(arg_t *arg) {
1238         arg_t tmp = *arg;
1239         asn1p_expr_t *expr, *ref_type;
1240         int saved_target;
1241
1242         expr = arg->expr;
1243         ref_type = WITH_MODULE_NAMESPACE(
1244                         tmp.expr->module, expr_ns,
1245                         asn1f_lookup_symbol_ex(tmp.asn, expr_ns, tmp.expr,
1246                         arg->expr->reference));
1247         if(!ref_type)
1248                 return 0;
1249
1250         if(!ref_type->data)
1251                 asn1c_attach_streams(ref_type);
1252
1253         arg->target = ref_type->data;
1254         saved_target = arg->target->target;
1255         REDIR(OT_FUNC_DECLS);
1256
1257         if((ref_type->expr_type == ASN_BASIC_INTEGER) ||
1258                 (ref_type->expr_type == ASN_BASIC_ENUMERATED)) {
1259                 OUT("#define %s_", MKID(ref_type));
1260                 OUT("%s\t", c_name(arg).base_name);
1261                 OUT("((%s)", asn1c_type_name(arg, expr, TNF_CTYPE));
1262                 OUT("%s)\n", asn1p_itoa(expr->value->value.v_integer));
1263         }
1264
1265         REDIR(saved_target);
1266         arg->target = tmp.target;
1267         return 0;
1268 }
1269
1270 int
1271 asn1c_lang_C_type_REFERENCE(arg_t *arg) {
1272         asn1p_ref_t *ref;
1273
1274         ref = arg->expr->reference;
1275         if(ref->components[ref->comp_count-1].name[0] == '&') {
1276                 asn1p_expr_t *extract;
1277                 arg_t tmp;
1278                 int ret;
1279
1280         extract = WITH_MODULE_NAMESPACE(
1281             arg->expr->module, expr_ns,
1282             asn1f_class_access_ex(arg->asn, arg->expr->module, expr_ns,
1283                                   arg->expr, arg->expr->rhs_pspecs, ref));
1284         if(extract == NULL)
1285                         return -1;
1286
1287                 extract = asn1p_expr_clone(extract, 0);
1288                 if(extract) {
1289                         free(extract->Identifier);
1290                         extract->Identifier = strdup(arg->expr->Identifier);
1291                         if(extract->Identifier == NULL) {
1292                                 asn1p_expr_free(extract);
1293                                 return -1;
1294                         }
1295                 } else {
1296                         return -1;
1297                 }
1298
1299                 tmp = *arg;
1300                 tmp.asn = arg->asn;
1301                 tmp.expr = extract;
1302
1303                 ret = arg->default_cb(&tmp, NULL);
1304
1305                 asn1p_expr_free(extract);
1306
1307                 return ret;
1308         }
1309
1310
1311         return asn1c_lang_C_type_SIMPLE_TYPE(arg);
1312 }
1313
1314 int
1315 asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
1316         asn1p_expr_t *expr = arg->expr;
1317         int tags_count;
1318         int all_tags_count;
1319         enum tvm_compat tv_mode;
1320         enum etd_spec etd_spec;
1321         const char *p;
1322         int saved_target = arg->target->target;
1323
1324         if(arg->embed) {
1325                 enum tnfmt tnfmt = TNF_CTYPE;
1326
1327                 /*
1328                  * If this is an optional compound type,
1329                  * refer it using "struct X" convention,
1330                  * as it may recursively include the current structure.
1331                  */
1332                 if(expr->marker.flags & (EM_INDIRECT | EM_UNRECURSE)) {
1333                         if(terminal_structable(arg, expr)) {
1334                                 tnfmt = TNF_RSAFE;
1335                                 if(saved_target != OT_FWD_DECLS) {
1336                                         REDIR(OT_FWD_DECLS);
1337                                         OUT("%s;\n",
1338                                                 asn1c_type_name(arg, arg->expr, tnfmt));
1339                                 }
1340                                 REDIR(saved_target);
1341                         }
1342                 }
1343
1344                 OUT("%s", asn1c_type_name(arg, arg->expr, tnfmt));
1345
1346                 if(!expr->_anonymous_type) {
1347                         OUT("%s", (expr->marker.flags&EM_INDIRECT)?"\t*":"\t ");
1348                         OUT("%s;", MKID_safe(expr));
1349                         if((expr->marker.flags & (EM_DEFAULT & ~EM_INDIRECT))
1350                                         == (EM_DEFAULT & ~EM_INDIRECT))
1351                                 OUT("\t/* DEFAULT %s */",
1352                                         asn1f_printable_value(
1353                                                 expr->marker.default_value));
1354                         else if((expr->marker.flags & EM_OPTIONAL)
1355                                         == EM_OPTIONAL)
1356                                 OUT("\t/* OPTIONAL */");
1357                         OUT("\n");
1358                 }
1359
1360         } else {
1361                 GEN_POS_INCLUDE_BASE(OT_INCLUDES, expr);
1362
1363                 REDIR(OT_TYPE_DECLS);
1364
1365                 OUT("typedef %s\t",
1366                         asn1c_type_name(arg, arg->expr, TNF_CTYPE));
1367                 OUT("%s%s_t%s",
1368                         (expr->marker.flags & EM_INDIRECT)?"*":" ",
1369                         MKID(expr),
1370                         expr->_anonymous_type ? "":";\n");
1371         }
1372
1373         if((expr->expr_type == ASN_BASIC_ENUMERATED)
1374         || (0 /* -- prohibited by X.693:8.3.4 */
1375                 && expr->expr_type == ASN_BASIC_INTEGER
1376                 && expr_elements_count(arg, expr))
1377         || (expr->expr_type == ASN_BASIC_INTEGER
1378                 && asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN)
1379         || asn1c_REAL_fits(arg, expr) == RL_FITS_FLOAT32
1380         )
1381                 etd_spec = ETD_HAS_SPECIFICS;
1382         else
1383                 etd_spec = ETD_NO_SPECIFICS;
1384
1385         /*
1386          * If this type just blindly refers the other type, alias it.
1387          *      Type1 ::= Type2
1388          */
1389         if(arg->embed && etd_spec == ETD_NO_SPECIFICS) {
1390                 REDIR(saved_target);
1391                 return 0;
1392         }
1393
1394         REDIR(OT_CODE);
1395
1396         /*
1397          * Constraint checking.
1398          */
1399         if(!(arg->flags & A1C_NO_CONSTRAINTS) && expr->combined_constraints) {
1400                 p = MKID(expr);
1401                 if(HIDE_INNER_DEFS) OUT("static ");
1402                 OUT("int\n");
1403                 OUT("%s", p);
1404                 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1405                 OUT("_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,\n");
1406                 INDENT(+1);
1407                 OUT("\t\tasn_app_constraint_failed_f *ctfailcb, void *app_key) {");
1408                 OUT("\n");
1409                 DEBUG("expr constraint checking code for %s", p);
1410                 if(asn1c_emit_constraint_checking_code(arg) == 1) {
1411                         OUT("return td->encoding_constraints.general_constraints"
1412                                 "(td, sptr, ctfailcb, app_key);\n");
1413                 }
1414                 INDENT(-1);
1415                 OUT("}\n");
1416                 OUT("\n");
1417         }
1418
1419         REDIR(OT_STAT_DEFS);
1420
1421     /*
1422      * By default, NativeReal is double. We only override this if
1423      * (OER) constraints suggested that we may use float.
1424      */
1425         if(asn1c_REAL_fits(arg, expr) == RL_FITS_FLOAT32) {
1426                 if(!(expr->_type_referenced)) OUT("static ");
1427                 OUT("const asn_NativeReal_specifics_t asn_SPC_%s_specs_%d = {\n",
1428                         MKID(expr), expr->_type_unique_index);
1429                 INDENT(+1);
1430                 OUT("4\t/* Use 'float' type. */\n");
1431                 INDENT(-1);
1432                 OUT("};\n");
1433         }
1434
1435         /*
1436          * Print out asn_DEF_<type>_[all_]tags[] vectors.
1437          */
1438         tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
1439         DEBUG("emit tag vectors for %s %d, %d, %d", expr->Identifier,
1440                 tv_mode, tags_count, all_tags_count);
1441
1442         emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count,
1443                 0, etd_spec);
1444
1445         REDIR(OT_CODE);
1446
1447         /*
1448          * Emit suicidal functions.
1449          */
1450
1451         /*
1452          * This function replaces certain fields from the definition
1453          * of a type with the corresponding fields from the basic type
1454          * (from which the current type is inherited).
1455          */
1456         OUT("/*\n");
1457         OUT(" * This type is implemented using %s,\n", c_name(arg).type.base_name);
1458         OUT(" * so here we adjust the DEF accordingly.\n");
1459         OUT(" */\n");
1460
1461         REDIR(OT_FUNC_DECLS);
1462
1463         p = MKID(expr);
1464         if(HIDE_INNER_DEFS) {
1465                 OUT("/* extern asn_TYPE_descriptor_t asn_DEF_%s_%d;"
1466                         "\t// (Use -fall-defs-global to expose) */\n",
1467                         p, expr->_type_unique_index);
1468         } else {
1469                 OUT("extern asn_TYPE_descriptor_t asn_DEF_%s;\n", p);
1470         if(etd_spec == ETD_HAS_SPECIFICS && expr->_type_referenced) {
1471             if((expr->expr_type == ASN_BASIC_ENUMERATED)
1472                || (expr->expr_type == ASN_BASIC_INTEGER)) {
1473                 OUT("extern const asn_INTEGER_specifics_t "
1474                     "asn_SPC_%s_specs_%d;\n",
1475                     c_name(arg).base_name, expr->_type_unique_index);
1476             } else {
1477                 asn1p_expr_t *terminal = WITH_MODULE_NAMESPACE(
1478                     expr->module, expr_ns,
1479                     asn1f_find_terminal_type_ex(arg->asn, expr_ns, expr));
1480                 OUT("extern const asn_%s_specifics_t ",
1481                     asn1c_type_name(arg, terminal, TNF_SAFE));
1482                 OUT("asn_SPC_%s_specs_%d;\n", MKID(expr),
1483                     expr->_type_unique_index);
1484             }
1485         }
1486                 OUT("asn_struct_free_f %s_free;\n", p);
1487                 OUT("asn_struct_print_f %s_print;\n", p);
1488                 OUT("asn_constr_check_f %s_constraint;\n", p);
1489                 OUT("ber_type_decoder_f %s_decode_ber;\n", p);
1490                 OUT("der_type_encoder_f %s_encode_der;\n", p);
1491                 OUT("xer_type_decoder_f %s_decode_xer;\n", p);
1492                 OUT("xer_type_encoder_f %s_encode_xer;\n", p);
1493                 if(arg->flags & A1C_GEN_OER) {
1494                         OUT("oer_type_decoder_f %s_decode_oer;\n", p);
1495                         OUT("oer_type_encoder_f %s_encode_oer;\n", p);
1496                 }
1497                 if(arg->flags & A1C_GEN_PER) {
1498                         OUT("per_type_decoder_f %s_decode_uper;\n", p);
1499                         OUT("per_type_encoder_f %s_encode_uper;\n", p);
1500                         OUT("per_type_decoder_f %s_decode_aper;\n", p);
1501                         OUT("per_type_encoder_f %s_encode_aper;\n", p);
1502                 }
1503         }
1504
1505         REDIR(saved_target);
1506
1507         return 0;
1508 }
1509
1510 int
1511 asn1c_lang_C_type_EXTENSIBLE(arg_t *arg) {
1512
1513         OUT("/*\n");
1514         OUT(" * This type is extensible,\n");
1515         OUT(" * possible extensions are below.\n");
1516         OUT(" */\n");
1517
1518         return 0;
1519 }
1520
1521 static int
1522 compute_extensions_start(asn1p_expr_t *expr) {
1523         asn1p_expr_t *v;
1524         int eidx = 0;
1525         TQ_FOR(v, &(expr->members), next) {
1526                 if(v->expr_type == A1TC_EXTENSIBLE)
1527                         return eidx;
1528                 eidx++;
1529         }
1530         return -1;
1531 }
1532
1533 static int
1534 _print_tag(arg_t *arg, struct asn1p_type_tag_s *tag) {
1535
1536         OUT("(");
1537         switch(tag->tag_class) {
1538         case TC_UNIVERSAL:              OUT("ASN_TAG_CLASS_UNIVERSAL"); break;
1539         case TC_APPLICATION:            OUT("ASN_TAG_CLASS_APPLICATION"); break;
1540         case TC_CONTEXT_SPECIFIC:       OUT("ASN_TAG_CLASS_CONTEXT"); break;
1541         case TC_PRIVATE:                OUT("ASN_TAG_CLASS_PRIVATE"); break;
1542         case TC_NOCLASS:
1543                 break;
1544         }
1545         OUT(" | (%s << 2))", asn1p_itoa(tag->tag_value));
1546
1547         return 0;
1548 }
1549
1550
1551 static int
1552 _tag2el_cmp(const void *ap, const void *bp) {
1553         const tag2el_t *a = ap;
1554         const tag2el_t *b = bp;
1555         const struct asn1p_type_tag_s *ta = &a->el_tag;
1556         const struct asn1p_type_tag_s *tb = &b->el_tag;
1557
1558         if(ta->tag_class == tb->tag_class) {
1559                 if(ta->tag_value == tb->tag_value) {
1560                         /*
1561                          * Sort by their respective positions.
1562                          */
1563                         if(a->el_no < b->el_no)
1564                                 return -1;
1565                         else if(a->el_no > b->el_no)
1566                                 return 1;
1567                         return 0;
1568                 } else if(ta->tag_value < tb->tag_value)
1569                         return -1;
1570                 else
1571                         return 1;
1572         } else if(ta->tag_class < tb->tag_class) {
1573                 return -1;
1574         } else {
1575                 return 1;
1576         }
1577 }
1578
1579 /*
1580  * For constructed types, number of external tags may be greater than
1581  * number of elements in the type because of CHOICE type.
1582  * T ::= SET {          -- Three possible tags:
1583  *     a INTEGER,       -- One tag is here...
1584  *     b Choice1        -- ... and two more tags are there.
1585  * }
1586  * Choice1 ::= CHOICE {
1587  *     s1 IA5String,
1588  *     s2 ObjectDescriptor
1589  * }
1590  */
1591 static int
1592 _fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
1593         asn1p_expr_t *expr = arg->expr;
1594         arg_t tmparg = *arg;
1595         asn1p_expr_t *v;
1596         int element = 0;
1597         int original_count = *count;
1598         int sort_until = -1;
1599
1600         TQ_FOR(v, &(expr->members), next) {
1601                 if(v->expr_type == A1TC_EXTENSIBLE) {
1602                         /*
1603                          * CXER mandates sorting
1604                          * only for the root part.
1605                          */
1606                         if(flags == FTE_CANONICAL_XER
1607                         && sort_until == -1)
1608                                 sort_until = *count;
1609                         continue;
1610                 }
1611
1612                 tmparg.expr = v;
1613
1614                 if(_add_tag2el_member(&tmparg, tag2el, count,
1615                                 (el_no==-1)?element:el_no, flags)) {
1616                         return -1;
1617                 }
1618
1619                 element++;
1620         }
1621
1622
1623         if(flags == FTE_CANONICAL_XER) {
1624                 if(sort_until == -1) sort_until = *count;
1625                 qsort((*tag2el) + original_count,
1626                         sort_until - original_count,
1627                                 sizeof(**tag2el), _tag2el_cmp);
1628                 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1629                 && (sort_until - original_count) >= 1) {
1630                         /* Only take in account the root component */
1631                         *count = original_count + 1;
1632                 }
1633         } else {
1634                 /*
1635                  * Sort the map according to canonical order of their
1636                  * tags and element numbers.
1637                  */
1638                 qsort(*tag2el, *count, sizeof(**tag2el), _tag2el_cmp);
1639         }
1640
1641         /*
1642          * Initialize .toff_{first|last} members.
1643          */
1644         if(*count) {
1645                 struct asn1p_type_tag_s *cur_tag = 0;
1646                 tag2el_t *cur = *tag2el;
1647                 tag2el_t *end = cur + *count;
1648                 int occur, i;
1649                 for(occur = 0; cur < end; cur++) {
1650                         if(cur_tag == 0
1651                         || cur_tag->tag_value != cur->el_tag.tag_value
1652                         || cur_tag->tag_class != cur->el_tag.tag_class) {
1653                                 cur_tag = &cur->el_tag;
1654                                 occur = 0;
1655                         } else {
1656                                 occur++;
1657                         }
1658                         cur->toff_first = -occur;
1659                         for(i = 0; i >= -occur; i--)
1660                                 cur[i].toff_last = -i;
1661                 }
1662         }
1663
1664         return 0;
1665 }
1666
1667 static int
1668 _add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
1669         struct asn1p_type_tag_s tag;
1670         int ret;
1671
1672         assert(el_no >= 0);
1673
1674     ret = WITH_MODULE_NAMESPACE(
1675         arg->expr->module, expr_ns,
1676         asn1f_fetch_outmost_tag(arg->asn, expr_ns, arg->expr->module, arg->expr,
1677                                 &tag, AFT_IMAGINARY_ANY));
1678     if(ret == 0) {
1679                 tag2el_t *te;
1680                 int new_count = (*count) + 1;
1681                 void *p;
1682
1683                 if(tag.tag_value == -1) {
1684                         /*
1685                          * This is an untagged ANY type,
1686                          * proceed without adding a tag
1687                          */
1688                         return 0;
1689                 }
1690
1691                 p = realloc(*tag2el, new_count * sizeof(tag2el_t));
1692                 if(p)   *tag2el = p;
1693                 else    return -1;
1694
1695                 if(0) DEBUG("Found tag for %s: %ld",
1696                         arg->expr->Identifier,
1697                         (long)tag.tag_value);
1698
1699                 te = &((*tag2el)[*count]);
1700                 te->el_tag = tag;
1701                 te->el_no = el_no;
1702                 te->from_expr = arg->expr;
1703                 *count = new_count;
1704                 return 0;
1705         }
1706
1707         DEBUG("Searching tag in complex expression %s:%x at line %d",
1708                 arg->expr->Identifier,
1709                 arg->expr->expr_type,
1710                 arg->expr->_lineno);
1711
1712         /*
1713          * Iterate over members of CHOICE type.
1714          */
1715         if(arg->expr->expr_type == ASN_CONSTR_CHOICE) {
1716                 return _fill_tag2el_map(arg, tag2el, count, el_no, flags);
1717         }
1718
1719         if(arg->expr->expr_type == A1TC_REFERENCE) {
1720                 arg_t tmp = *arg;
1721                 asn1p_expr_t *expr;
1722         expr = WITH_MODULE_NAMESPACE(
1723             tmp.expr->module, expr_ns,
1724             asn1f_lookup_symbol_ex(tmp.asn, expr_ns, tmp.expr,
1725                                    arg->expr->reference));
1726         if(expr) {
1727                         tmp.expr = expr;
1728                         return _add_tag2el_member(&tmp, tag2el, count, el_no, flags);
1729                 } else {
1730                         FATAL("Cannot dereference %s at line %d",
1731                                 arg->expr->Identifier,
1732                                 arg->expr->_lineno);
1733                         return -1;
1734                 }
1735         }
1736
1737         DEBUG("No tag for %s at line %d",
1738                 arg->expr->Identifier,
1739                 arg->expr->_lineno);
1740
1741         return -1;
1742 }
1743
1744 static int
1745 emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier) {
1746         asn1p_expr_t *expr = arg->expr;
1747         int i;
1748
1749         if(!tag2el_count) return 0;     /* No top level tags */
1750
1751         OUT("static const asn_TYPE_tag2member_t asn_MAP_%s_tag2el%s_%d[] = {\n",
1752                 MKID(expr), opt_modifier?opt_modifier:"",
1753                 expr->_type_unique_index);
1754         for(i = 0; i < tag2el_count; i++) {
1755                 OUT("    { ");
1756                 _print_tag(arg, &tag2el[i].el_tag);
1757                 OUT(", ");
1758                 OUT("%d, ", tag2el[i].el_no);
1759                 OUT("%d, ", tag2el[i].toff_first);
1760                 OUT("%d ", tag2el[i].toff_last);
1761                 OUT("}%s /* %s",
1762                         (i + 1 < tag2el_count) ? "," : "",
1763                         tag2el[i].from_expr->Identifier);
1764         if(arg->flags & A1C_LINE_REFS)
1765             OUT("at %d", tag2el[i].from_expr->_lineno);
1766         OUT(" */\n");
1767         }
1768         OUT("};\n");
1769
1770         return 0;
1771 }
1772
1773 static enum tvm_compat
1774 emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tags_count_r, int *all_tags_count_r) {
1775         struct asn1p_type_tag_s *tags = 0;      /* Effective tags */
1776         struct asn1p_type_tag_s *all_tags = 0;  /* The full array */
1777         int tags_count = 0;
1778         int all_tags_count = 0;
1779         enum tvm_compat tv_mode = _TVM_SAME;
1780         int i;
1781
1782         /* Cleanup before proceeding. */
1783         *tags_count_r = 0;
1784         *all_tags_count_r = 0;
1785
1786         /* Fetch a chain of tags */
1787     tags_count = WITH_MODULE_NAMESPACE(
1788         expr->module, expr_ns,
1789         asn1f_fetch_tags(arg->asn, expr_ns, expr->module, expr, &tags, 0));
1790     if(tags_count < 0) {
1791                 DEBUG("fail to fetch tags for %s", expr->Identifier);
1792                 return -1;
1793         }
1794
1795         /* Fetch a chain of tags */
1796     all_tags_count = WITH_MODULE_NAMESPACE(
1797         expr->module, expr_ns,
1798         asn1f_fetch_tags(arg->asn, expr_ns, expr->module, expr, &all_tags,
1799                          AFT_FULL_COLLECT));
1800     if(all_tags_count < 0) {
1801                 free(tags);
1802                 DEBUG("fail to fetch tags chain for %s", expr->Identifier);
1803                 return -1;
1804         }
1805
1806         assert(tags_count <= all_tags_count);
1807         assert((tags_count?0:1) == (all_tags_count?0:1));
1808
1809         if(tags_count <= all_tags_count) {
1810                 for(i = 0; i < tags_count; i++) {
1811                         if(tags[i].tag_value != all_tags[i].tag_value
1812                         || tags[i].tag_class != all_tags[i].tag_class) {
1813                                 tv_mode = _TVM_DIFFERENT;
1814                                 break;
1815                         }
1816                 }
1817                 if(i == tags_count && tags_count < all_tags_count)
1818                         tv_mode = _TVM_SUBSET;
1819         } else {
1820                 tv_mode = _TVM_DIFFERENT;
1821         }
1822
1823 #define EMIT_TAGS_TABLE(name, tags, tags_count) do {                    \
1824                 OUT("static const ber_tlv_tag_t asn_DEF_%s%s_tags_%d[] = {\n",\
1825                         MKID(expr), name,                       \
1826                         expr->_type_unique_index);                      \
1827                 INDENT(+1);                                             \
1828                 /* Print the array of collected tags */                 \
1829                 for(i = 0; i < tags_count; i++) {                       \
1830                         if(i) OUT(",\n");                               \
1831                         _print_tag(arg, &tags[i]);                      \
1832                 }                                                       \
1833                 OUT("\n");                                              \
1834                 INDENT(-1);                                             \
1835                 OUT("};\n");                                            \
1836         } while(0)
1837
1838         if(tags_count) {
1839                 if(tv_mode == _TVM_SUBSET)
1840                         EMIT_TAGS_TABLE("", all_tags, all_tags_count);
1841                 else
1842                         EMIT_TAGS_TABLE("", tags, tags_count);
1843         }
1844
1845         if(all_tags_count) {
1846                 if(tv_mode == _TVM_DIFFERENT)
1847                         EMIT_TAGS_TABLE("_all", all_tags, all_tags_count);
1848         }
1849
1850         free(tags);
1851         free(all_tags);
1852
1853         *tags_count_r = tags_count;
1854         *all_tags_count_r = all_tags_count;
1855
1856         return tv_mode;
1857 }
1858
1859 static int
1860 expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
1861         asn1p_expr_t *topmost_parent;
1862         asn1p_expr_t *v;
1863         int elements = 0;
1864
1865     topmost_parent = WITH_MODULE_NAMESPACE(
1866         expr->module, expr_ns,
1867         asn1f_find_terminal_type_ex(arg->asn, expr_ns, expr));
1868     if(!topmost_parent) return 0;
1869
1870         if(!(topmost_parent->expr_type & ASN_CONSTR_MASK)
1871         && !(topmost_parent->expr_type == ASN_BASIC_INTEGER)
1872         && !(topmost_parent->expr_type == ASN_BASIC_ENUMERATED)
1873         && !(topmost_parent->expr_type == ASN_BASIC_BIT_STRING))
1874                 return 0;
1875
1876         TQ_FOR(v, &(topmost_parent->members), next) {
1877                 if(v->expr_type != A1TC_EXTENSIBLE)
1878                         elements++;
1879         }
1880
1881         return elements;
1882 }
1883
1884 static asn1p_expr_type_e
1885 expr_get_type(arg_t *arg, asn1p_expr_t *expr) {
1886         asn1p_expr_t *terminal;
1887         terminal = asn1f_find_terminal_type_ex(arg->asn, arg->ns, expr);
1888         if(terminal) return terminal->expr_type;
1889         return A1TC_INVALID;
1890 }
1891
1892 static asn1c_integer_t
1893 PER_FROM_alphabet_characters(asn1cnst_range_t *range) {
1894         asn1c_integer_t numchars = 0;
1895         if(range->el_count) {
1896                 int i;
1897                 for(i = 0; i < range->el_count; i++)
1898                         numchars
1899                         += PER_FROM_alphabet_characters(range->elements[i]);
1900         } else {
1901                 assert(range->left.type == ARE_VALUE);
1902                 assert(range->right.type == ARE_VALUE);
1903                 numchars = 1 + (range->right.value - range->left.value);
1904         }
1905         return numchars;
1906 }
1907
1908 static void
1909 emit_single_member_OER_constraint_comment(arg_t *arg, asn1cnst_range_t *range, char *type) {
1910
1911         /*
1912          * Print some courtesy debug information.
1913          */
1914     if(range
1915        && (range->left.type == ARE_VALUE || range->right.type == ARE_VALUE)) {
1916         OUT("\t/* ");
1917                 if(type) OUT("(%s", type);
1918                 OUT("(");
1919                 if(range->left.type == ARE_VALUE)
1920                         OUT("%s", asn1p_itoa(range->left.value));
1921                 else
1922                         OUT("MIN");
1923                 OUT("..");
1924                 if(range->right.type == ARE_VALUE)
1925                         OUT("%s", asn1p_itoa(range->right.value));
1926                 else
1927                         OUT("MAX");
1928                 if(range->extensible) OUT(",...");
1929                 if(type) OUT(")");
1930                 OUT(") */");
1931         }
1932 }
1933
1934 static int
1935 emit_single_member_OER_constraint_value(arg_t *arg, asn1cnst_range_t *range) {
1936     if(!range) {
1937         /* oer_support.h: asn_oer_constraint_s */
1938         OUT("{ 0, 0 }");
1939         return 0;
1940     }
1941
1942         if(range->incompatible || range->not_OER_visible) {
1943                 OUT("{ 0, 0 }");
1944     } else if(expr_get_type(arg, arg->expr) == ASN_BASIC_REAL) {
1945         if(range->narrowing == NARROW_FLOAT32) {
1946             OUT("{ sizeof(float), 0 }");
1947         } else if(range->narrowing == NARROW_DOUBLE64) {
1948             OUT("{ sizeof(double), 0 }");
1949         } else {
1950             OUT("{ 0, 0 }");
1951         }
1952     } else if(range->left.type == ARE_VALUE && range->left.value >= 0
1953               && range->right.type == ARE_MAX) {
1954         OUT("{ 0, 1 }");
1955         } else if(range->left.type == ARE_VALUE &&
1956             range->right.type == ARE_VALUE) {
1957         asn1c_integer_t lb = range->left.value;
1958         asn1c_integer_t ub = range->right.value;
1959         unsigned width = 0;
1960         unsigned positive = 0;
1961
1962
1963         if(lb >= 0) {
1964             /* X.969 08/2015 10.2(a) */
1965             if(ub <= 255) {
1966                 width = 1;
1967             } else if(ub <= 65535) {
1968                 width = 2;
1969             } else if((unsigned long long)ub <= 4294967295UL) {
1970                 width = 4;
1971             } else if((unsigned long long)ub <= 18446744073709551615ULL) {
1972                 width = 8;
1973             }
1974             positive = 1;
1975         } else {
1976             positive = 0;
1977             /* X.969 08/2015 10.2(b) - no lower bound or negative lower bound */
1978             if(lb >= -128 && ub <= 127) {
1979                 width = 1;
1980             } else if(lb >= -32768 && ub <= 32767) {
1981                 width = 2;
1982             } else if(lb >= -2147483648L && ub <= 2147483647L) {
1983                 width = 4;
1984             } else if(lb >= (-9223372036854775807LL-1)
1985                       && ub <= 9223372036854775807LL) {
1986                 width = 8;
1987             }
1988         }
1989         OUT("{ %u, %u }", width, positive);
1990     } else {
1991         OUT("{ 0, 0 }");
1992     }
1993
1994     return 0;
1995 }
1996
1997 static int
1998 emit_single_member_OER_constraint_size(arg_t *arg, asn1cnst_range_t *range) {
1999     if(!range) {
2000         /* oer_support.h: asn_oer_constraint_s */
2001                 OUT("-1");
2002                 return 0;
2003     }
2004
2005     if(range->incompatible || range->not_OER_visible) {
2006         OUT("-1");
2007     } else {
2008         if(range->left.type == ARE_VALUE && range->right.type == ARE_VALUE
2009            && range->left.value == range->right.value
2010            && range->left.value >= 0) {
2011             OUT("%s", asn1p_itoa(range->left.value));
2012         } else {
2013             OUT("-1");
2014         }
2015     }
2016
2017         return 0;
2018 }
2019
2020 static int
2021 emit_single_member_PER_constraint(arg_t *arg, asn1cnst_range_t *range, int alphabetsize, const char *type) {
2022     if(!range || range->incompatible || range->not_PER_visible) {
2023         OUT("{ APC_UNCONSTRAINED,\t-1, -1,  0,  0 }");
2024                 return 0;
2025     }
2026
2027     if(expr_get_type(arg, arg->expr) == ASN_BASIC_REAL) {
2028         /* Unsupported */
2029         OUT("{ APC_UNCONSTRAINED,\t-1, -1,  0,  0 }");
2030         return 0;
2031     }
2032
2033     if(range->left.type == ARE_VALUE) {
2034                 if(range->right.type == ARE_VALUE) {
2035                         asn1c_integer_t cover = 1;
2036                         asn1c_integer_t r = 1 + range->right.value
2037                                               - range->left.value;
2038                         size_t rbits;   /* Value range bits */
2039                         ssize_t ebits;  /* Value effective range bits */
2040
2041                         if(range->empty_constraint)
2042                                 r = 0;
2043
2044                         if(alphabetsize) {
2045                                 /* X.691: 27.5.2 */
2046                                 r = PER_FROM_alphabet_characters(range);
2047                         }
2048
2049                         /* Compute real constraint */
2050                         for(rbits = 0; rbits < (8 * sizeof(r)); rbits++) {
2051                                 if(r <= cover)
2052                                         break;
2053                                 cover *= 2;     /* Can't do shifting */
2054                                 if(cover < 0) {
2055                                         FATAL("Constraint at line %d too wide "
2056                                                 "for %d-bits integer type",
2057                                                 arg->expr->_lineno,
2058                                                 sizeof(r) * 8);
2059                                         rbits = sizeof(r);
2060                                         break;
2061                                 }
2062                         }
2063
2064                         if(alphabetsize) {
2065                                 ebits = rbits;
2066                         } else {
2067                                 /* X.691, #10.9.4.1 */
2068                                 for(ebits = 0; ebits <= 16; ebits++)
2069                                         if(r <= 1 << ebits) break;
2070                                 if(ebits == 17
2071                                 || range->right.value >= 65536)
2072                                         ebits = -1;
2073                         if(0) {
2074                                 /* X.691, #10.5.7.1 */
2075                                 for(ebits = 0; ebits <= 8; ebits++)
2076                                         if(r <= 1 << ebits) break;
2077                                 if(ebits == 9) {
2078                                         if(r <= 65536)
2079                                                 ebits = 16;
2080                                         else
2081                                                 ebits = -1;
2082                                 }
2083                         }
2084                         }
2085
2086                         OUT("{ APC_CONSTRAINED%s,%s% d, % d, ",
2087                                 range->extensible
2088                                         ? " | APC_EXTENSIBLE" : "",
2089                                 range->extensible ? " " : "\t", (int)rbits, (int)ebits);
2090
2091                         if(alphabetsize) {
2092                                 asn1c_integer_t lv = range->left.value;
2093                                 asn1c_integer_t rv = range->right.value;
2094                                 int gcmt = 0;
2095                                 if(lv > 0x7fffffff) { lv = 0x7fffffff; gcmt++; }
2096                                 if(rv > 0x7fffffff) { rv = 0x7fffffff; gcmt++; }
2097                                 if(gcmt) {
2098                                         OINTS(lv); OUT(", "); OINTS(rv); OUT(" }");
2099                                         goto pcmt;
2100                                 }
2101                         }
2102                 } else {
2103                         if(range->extensible) {
2104                                 OUT("{ APC_SEMI_CONSTRAINED | APC_EXTENSIBLE, "
2105                                         "-1, -1, ");
2106                         } else {
2107                                 OUT("{ APC_SEMI_CONSTRAINED,\t-1, -1, ");
2108                         }
2109                 }
2110                 OINTS(range->left.value); OUT(", ");
2111                 OINTS(range->right.value); OUT(" }");
2112         } else {
2113                 OUT("{ APC_UNCONSTRAINED,\t-1, -1,  0,  0 }");
2114         }
2115
2116   pcmt:
2117
2118         /*
2119          * Print some courtesy debug information.
2120          */
2121         if(range->left.type == ARE_VALUE
2122         || range->right.type == ARE_VALUE) {
2123                 OUT("\t/* ");
2124                 if(type) OUT("(%s", type);
2125                 OUT("(");
2126                 if(range->left.type == ARE_VALUE)
2127                         OUT("%s", asn1p_itoa(range->left.value));
2128                 else
2129                         OUT("MIN");
2130                 OUT("..");
2131                 if(range->right.type == ARE_VALUE)
2132                         OUT("%s", asn1p_itoa(range->right.value));
2133                 else
2134                         OUT("MAX");
2135                 if(range->extensible) OUT(",...");
2136                 if(type) OUT(")");
2137                 OUT(") */");
2138         }
2139
2140         return 0;
2141 }
2142
2143 static int
2144 emit_member_OER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx) {
2145     int save_target = arg->target->target;
2146     asn1cnst_range_t *range;
2147         asn1p_expr_type_e etype;
2148
2149     etype = expr_get_type(arg, expr);
2150
2151     if((arg->flags & A1C_GEN_OER)
2152        && (expr->combined_constraints || etype == ASN_BASIC_ENUMERATED
2153            || etype == ASN_CONSTR_CHOICE)) {
2154         /* Fall through */
2155     } else {
2156         return 0;
2157     }
2158
2159     REDIR(OT_CTDEFS);
2160
2161     OUT("static asn_oer_constraints_t "
2162         "asn_OER_%s_%s_constr_%d CC_NOTUSED = {\n",
2163         pfx, MKID(expr), expr->_type_unique_index);
2164
2165     INDENT(+1);
2166
2167     /* .value{.width,.positive} */
2168     range = asn1constraint_compute_OER_range(expr->Identifier, etype,
2169                                              expr->combined_constraints,
2170                                              ACT_EL_RANGE, 0, 0, 0);
2171     if(emit_single_member_OER_constraint_value(arg, range)) {
2172         return -1;
2173     }
2174     emit_single_member_OER_constraint_comment(arg, range, 0);
2175     asn1constraint_range_free(range);
2176
2177         OUT(",\n");
2178
2179     /* .size */
2180     range = asn1constraint_compute_OER_range(expr->Identifier, etype,
2181                                              expr->combined_constraints,
2182                                              ACT_CT_SIZE, 0, 0, 0);
2183     if(emit_single_member_OER_constraint_size(arg, range)) {
2184         return -1;
2185     }
2186     emit_single_member_OER_constraint_comment(arg, range, "SIZE");
2187     asn1constraint_range_free(range);
2188
2189     INDENT(-1);
2190
2191     OUT("};\n");
2192
2193     REDIR(save_target);
2194
2195     return 0;
2196 }
2197
2198 static int
2199 emit_member_PER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx) {
2200         int save_target = arg->target->target;
2201         asn1cnst_range_t *range;
2202         asn1p_expr_type_e etype;
2203
2204         etype = expr_get_type(arg, expr);
2205
2206         if((arg->flags & A1C_GEN_PER)
2207         && (expr->combined_constraints
2208                 || etype == ASN_BASIC_ENUMERATED
2209                 || etype == ASN_CONSTR_CHOICE
2210                 || (etype & ASN_STRING_KM_MASK)
2211         )
2212         ) {
2213                 /* Fall through */
2214         } else {
2215                 return 0;
2216         }
2217
2218         if(expr->_type_referenced) {
2219                 REDIR(OT_FUNC_DECLS);
2220
2221                 OUT("extern asn_per_constraints_t "
2222                         "asn_PER_%s_%s_constr_%d;\n",
2223                         pfx, MKID(expr), expr->_type_unique_index);
2224         }
2225
2226         REDIR(OT_CTDEFS);
2227
2228         if(!(expr->_type_referenced)) OUT("static ");
2229         OUT("asn_per_constraints_t "
2230                 "asn_PER_%s_%s_constr_%d CC_NOTUSED = {\n",
2231                 pfx, MKID(expr), expr->_type_unique_index);
2232
2233         INDENT(+1);
2234
2235         /*
2236          * ENUMERATED and CHOICE are special.
2237          */
2238         if(etype == ASN_BASIC_ENUMERATED
2239         || etype == ASN_CONSTR_CHOICE) {
2240                 asn1cnst_range_t tmprng;
2241                 asn1p_expr_t *v;
2242                 int extensible = 0;
2243                 int eidx = -1;
2244
2245                 expr = asn1f_find_terminal_type_ex(arg->asn, arg->ns, expr);
2246                 assert(expr);
2247
2248                 TQ_FOR(v, &(expr->members), next) {
2249                         if(v->expr_type == A1TC_EXTENSIBLE) {
2250                                 extensible++;
2251                                 break;
2252                         }
2253                         eidx++;
2254                 }
2255
2256                 memset(&tmprng, 0, sizeof (tmprng));
2257                 tmprng.extensible = extensible;
2258                 if(eidx < 0) tmprng.empty_constraint = 1;
2259                 tmprng.left.type = ARE_VALUE;
2260                 tmprng.left.value = 0;
2261                 tmprng.right.type = ARE_VALUE;
2262                 tmprng.right.value = eidx < 0 ? 0 : eidx;
2263                 if(emit_single_member_PER_constraint(arg, &tmprng, 0, 0))
2264                         return -1;
2265         } else if(etype & ASN_STRING_KM_MASK) {
2266                 range = asn1constraint_compute_PER_range(expr->Identifier, etype,
2267                                 expr->combined_constraints, ACT_CT_FROM,
2268                                 0, 0, 0);
2269                 DEBUG("Emitting FROM constraint for %s", expr->Identifier);
2270
2271                 if((range->left.type == ARE_MIN && range->right.type == ARE_MAX)
2272                 || range->not_PER_visible) {
2273                         switch(etype) {
2274                         case ASN_STRING_BMPString:
2275                                 range->left.type = ARE_VALUE;
2276                                 range->left.value = 0;
2277                                 range->right.type = ARE_VALUE;
2278                                 range->right.value = 65535;
2279                                 range->not_PER_visible = 0;
2280                                 range->extensible = 0;
2281                                 break;
2282                         case ASN_STRING_UniversalString:
2283                                 OUT("{ APC_CONSTRAINED,\t32, 32,"
2284                                         " 0, 2147483647 }"
2285                                         " /* special case 1 */\n");
2286                                 goto avoid;
2287                         default:
2288                                 break;
2289                         }
2290                 }
2291                 if(emit_single_member_PER_constraint(arg, range, 1, 0))
2292                         return -1;
2293                 avoid:
2294                 asn1constraint_range_free(range);
2295         } else {
2296                 range = asn1constraint_compute_PER_range(expr->Identifier, etype,
2297                                 expr->combined_constraints, ACT_EL_RANGE,
2298                                 0, 0, 0);
2299                 if(emit_single_member_PER_constraint(arg, range, 0, 0))
2300                         return -1;
2301                 asn1constraint_range_free(range);
2302         }
2303         OUT(",\n");
2304
2305         range = asn1constraint_compute_PER_range(expr->Identifier, etype,
2306                         expr->combined_constraints, ACT_CT_SIZE, 0, 0, 0);
2307         if(emit_single_member_PER_constraint(arg, range, 0, "SIZE"))
2308                 return -1;
2309         asn1constraint_range_free(range);
2310         OUT(",\n");
2311
2312         if((etype & ASN_STRING_KM_MASK) && (expr->_mark & TM_PERFROMCT)) {
2313                 int old_target = arg->target->target;
2314                 REDIR(OT_CODE);
2315
2316                 OUT("static int asn_PER_MAP_%s_%d_v2c(unsigned int value) {\n",
2317                         MKID(expr), expr->_type_unique_index);
2318                 OUT("\tif(value >= sizeof(permitted_alphabet_table_%d)/"
2319                         "sizeof(permitted_alphabet_table_%d[0]))\n",
2320                         expr->_type_unique_index,
2321                         expr->_type_unique_index);
2322                 OUT("\t\treturn -1;\n");
2323                 OUT("\treturn permitted_alphabet_table_%d[value] - 1;\n",
2324                         expr->_type_unique_index);
2325                 OUT("}\n");
2326
2327                 OUT("static int asn_PER_MAP_%s_%d_c2v(unsigned int code) {\n",
2328                         MKID(expr), expr->_type_unique_index);
2329                 OUT("\tif(code >= sizeof(permitted_alphabet_code2value_%d)/"
2330                         "sizeof(permitted_alphabet_code2value_%d[0]))\n",
2331                         expr->_type_unique_index,
2332                         expr->_type_unique_index);
2333                 OUT("\t\treturn -1;\n");
2334                 OUT("\treturn permitted_alphabet_code2value_%d[code];\n",
2335                         expr->_type_unique_index);
2336                 OUT("}\n");
2337
2338                 REDIR(old_target);
2339
2340                 OUT("asn_PER_MAP_%s_%d_v2c,\t/* Value to PER code map */\n",
2341                         MKID(expr), expr->_type_unique_index);
2342                 OUT("asn_PER_MAP_%s_%d_c2v\t/* PER code to value map */\n",
2343                         MKID(expr), expr->_type_unique_index);
2344         } else if(etype & ASN_STRING_KM_MASK) {
2345                 DEBUG("No PER value map necessary for %s", MKID(expr));
2346                 OUT("0, 0\t/* No PER character map necessary */\n");
2347         } else {
2348                 OUT("0, 0\t/* No PER value map */\n");
2349         }
2350
2351         INDENT(-1);
2352
2353         OUT("};\n");
2354
2355         REDIR(save_target);
2356
2357         return 0;
2358 }
2359
2360 static int
2361 safe_string(const uint8_t *buf, int size) {
2362         const uint8_t *end = buf + size;
2363         for(; buf < end; buf++) {
2364                 int ch = *buf;
2365                 if((ch < 0x20 || ch > 0x7e) || ch == '"')
2366                         return 0;
2367         }
2368         return 1;
2369 }
2370
2371 static void
2372 emit_default_string_value(arg_t *arg, asn1p_value_t *v) {
2373
2374         OUT("static const uint8_t defv[] = ");
2375         assert(v->type == ATV_STRING);
2376
2377         if(safe_string(v->value.string.buf, v->value.string.size)) {
2378                 OUT("\"%s\";\n", v->value.string.buf);
2379         } else {
2380                 uint8_t *b = v->value.string.buf;
2381                 uint8_t *e = v->value.string.size + b;
2382                 OUT("{ ");
2383                 for(;b < e; b++)
2384                         OUT("0x%02x, ", *b);
2385                 OUT("0 };\n");
2386         }
2387 }
2388
2389 static int
2390 try_inline_default(arg_t *arg, asn1p_expr_t *expr, int out) {
2391         int save_target = arg->target->target;
2392         asn1p_expr_type_e etype = expr_get_type(arg, expr);
2393         int fits_long = 0;
2394
2395         switch(etype) {
2396         case ASN_BASIC_BOOLEAN:
2397                 fits_long = 1;
2398         /* Fall through */
2399         case ASN_BASIC_INTEGER:
2400         case ASN_BASIC_ENUMERATED:
2401                 if(expr->marker.default_value == NULL
2402                 || (expr->marker.default_value->type != ATV_INTEGER &&
2403                     expr->marker.default_value->type != ATV_TRUE &&
2404                     expr->marker.default_value->type != ATV_FALSE))
2405                         break;
2406                 if(!fits_long)
2407                         fits_long = asn1c_type_fits_long(arg, expr)!=FL_NOTFIT;
2408                 if(fits_long && !expr->marker.default_value->value.v_integer)
2409                         expr->marker.flags &= ~EM_INDIRECT;
2410                 if(!out) {
2411             if(C99_MODE) OUT(".default_value_cmp = ");
2412                         OUT("&asn_DFL_%d_cmp_%s,",
2413                                 expr->_type_unique_index,
2414                                 asn1p_itoa(expr->marker.default_value->value.v_integer));
2415             OUT("\t/* Compare DEFAULT %s */\n",
2416                                 asn1p_itoa(expr->marker.default_value->value.v_integer));
2417             if(C99_MODE) OUT(".default_value_set = ");
2418                         OUT("&asn_DFL_%d_set_%s,",
2419                                 expr->_type_unique_index,
2420                                 asn1p_itoa(expr->marker.default_value->value.v_integer));
2421             OUT("\t/* Set DEFAULT %s */\n",
2422                                 asn1p_itoa(expr->marker.default_value->value.v_integer));
2423                         return 1;
2424                 }
2425                 REDIR(OT_STAT_DEFS);
2426
2427                 OUT("static int asn_DFL_%d_cmp_%s(const void *sptr) {\n",
2428                         expr->_type_unique_index,
2429                         asn1p_itoa(expr->marker.default_value->value.v_integer));
2430                 INDENT(+1);
2431                 OUT("const %s *st = sptr;\n", asn1c_type_name(arg, expr, TNF_CTYPE));
2432                 OUT("\n");
2433                 OUT("if(!st) {\n");
2434         OUT("\treturn -1; /* No value is not a default value */\n");
2435                 OUT("}\n");
2436                 OUT("\n");
2437                 OUT("/* Test default value %s */\n",
2438                         asn1p_itoa(expr->marker.default_value->value.v_integer));
2439                 if(fits_long) {
2440                         OUT("return (*st != %s);\n",
2441                                 asn1p_itoa(expr->marker.default_value->value.v_integer));
2442                 } else {
2443                         OUT("long value;\n");
2444                         OUT("if(asn_INTEGER2long(st, &value))\n");
2445                         OUT("\treturn -1;\n");
2446                         OUT("return (value != %s);\n",
2447                                 asn1p_itoa(expr->marker.default_value->value.v_integer));
2448                 }
2449                 INDENT(-1);
2450                 OUT("}\n");
2451
2452                 OUT("static int asn_DFL_%d_set_%s(void **sptr) {\n",
2453                         expr->_type_unique_index,
2454                         asn1p_itoa(expr->marker.default_value->value.v_integer));
2455                 INDENT(+1);
2456                 OUT("%s *st = *sptr;\n", asn1c_type_name(arg, expr, TNF_CTYPE));
2457                 OUT("\n");
2458                 OUT("if(!st) {\n");
2459                 OUT("\tst = (*sptr = CALLOC(1, sizeof(*st)));\n");
2460                 OUT("\tif(!st) return -1;\n");
2461                 OUT("}\n");
2462                 OUT("\n");
2463                 OUT("/* Install default value %s */\n",
2464                         asn1p_itoa(expr->marker.default_value->value.v_integer));
2465                 if(fits_long) {
2466                         OUT("*st = ");
2467                         OINT(expr->marker.default_value->value.v_integer);
2468                         OUT(";\n");
2469                         OUT("return 0;\n");
2470                 } else {
2471                         OUT("return asn_long2INTEGER(st, ");
2472                         OINT(expr->marker.default_value->value.v_integer);
2473                         OUT(");\n");
2474                 }
2475                 INDENT(-1);
2476                 OUT("}\n");
2477
2478                 REDIR(save_target);
2479                 return 1;
2480         case ASN_BASIC_NULL:
2481                 //expr->marker.flags &= ~EM_INDIRECT;
2482                 return 0;
2483         default:
2484           if(etype & ASN_STRING_KM_MASK) {
2485                 if(expr->marker.default_value == NULL
2486                 || expr->marker.default_value->type != ATV_STRING)
2487                         break;
2488                 if(!out) {
2489             if(C99_MODE) OUT(".default_value_cmp = ");
2490                         OUT("&asn_DFL_%d_cmp,\t/* Compare DEFAULT \"%s\" */\n",
2491                                 expr->_type_unique_index,
2492                                 expr->marker.default_value->value.string.buf);
2493             if(C99_MODE) OUT(".default_value_set = ");
2494                         OUT("&asn_DFL_%d_set,\t/* Set DEFAULT \"%s\" */\n",
2495                                 expr->_type_unique_index,
2496                                 expr->marker.default_value->value.string.buf);
2497                         return 1;
2498                 }
2499                 REDIR(OT_STAT_DEFS);
2500
2501         OUT("static int asn_DFL_%d_cmp(const void *sptr) {\n",
2502             expr->_type_unique_index);
2503         INDENT(+1);
2504         emit_default_string_value(arg, expr->marker.default_value);
2505         OUT("const %s *st = sptr;\n", asn1c_type_name(arg, expr, TNF_CTYPE));
2506         OUT("\n");
2507         OUT("if(!st) {\n");
2508         OUT("\treturn -1; /* No value is not a default value */\n");
2509         OUT("}\n");
2510                 OUT("\n");
2511         OUT("if(st->size == (sizeof(defv) - 1)\n");
2512         OUT("&& memcmp(st->buf, &defv, sizeof(defv) - 1) == 0)\n");
2513         OUT("\treturn 0;\n");
2514         OUT("return 1;\n");
2515                 INDENT(-1);
2516                 OUT("}\n");
2517
2518         OUT("static int asn_DFL_%d_set(void **sptr) {\n",
2519             expr->_type_unique_index);
2520         INDENT(+1);
2521                 emit_default_string_value(arg, expr->marker.default_value);
2522                 OUT("%s *st = *sptr;\n", asn1c_type_name(arg, expr, TNF_CTYPE));
2523         OUT("uint8_t *nstr = MALLOC(sizeof(defv));\n");
2524                 OUT("\n");
2525         OUT("if(!nstr) return -1;\n");
2526         OUT("memcpy(nstr, defv, sizeof(defv));\n");
2527         OUT("\n");
2528                 OUT("if(st) {\n");
2529                 OUT("\tFREEMEM(st->buf);\n");
2530                 OUT("} else {\n");
2531                 OUT("\tst = (*sptr = CALLOC(1, sizeof(*st)));\n");
2532                 OUT("\tif(!st) { FREEMEM(nstr); return -1; }\n");
2533                 OUT("}\n");
2534                 OUT("st->buf = nstr;\n");
2535         OUT("st->size = sizeof(defv) - 1;\n");
2536                 OUT("\n");
2537                 OUT("return 0;\n");
2538                 INDENT(-1);
2539                 OUT("}\n");
2540
2541                 REDIR(save_target);
2542                 return 1;
2543           }
2544           break;
2545         }
2546         return 0;
2547 }
2548
2549 static int
2550 emit_member_type_selector(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_objset_t *opt_ioc) {
2551         int save_target = arg->target->target;
2552     asn1p_expr_t *parent_expr = arg->expr;
2553
2554     const asn1p_constraint_t *crc =
2555         asn1p_get_component_relation_constraint(expr->combined_constraints);
2556     if(!crc || crc->el_count <= 1) {
2557         /* Not an Open Type, it seems. */
2558         OUT("0");
2559         return 0;
2560     }
2561
2562     const asn1p_ref_t *objset_ref =
2563         asn1c_get_information_object_set_reference_from_constraint(arg, crc);
2564
2565     if(!objset_ref) {
2566         FATAL("Constraint %s does not look like it referst to a set type %s",
2567               asn1p_constraint_string(crc),
2568               opt_ioc->objset->Identifier);
2569         return -1;
2570     }
2571
2572     const char *objset_name;
2573     if(objset_ref->comp_count == 1) {
2574         objset_name = objset_ref->components[0].name;
2575     } else if(objset_ref->comp_count == 2) {
2576         if(strcmp(objset_ref->components[0].name,
2577                   opt_ioc->objset->module->ModuleName)
2578            != 0) {
2579             FATAL(
2580                 "Composite reference %s (from %s) does not look like it refers "
2581                 "to the same module as %s from an object set type %s",
2582                 asn1p_ref_string(objset_ref), asn1p_constraint_string(crc),
2583                 opt_ioc->objset->module->ModuleName,
2584                 opt_ioc->objset->Identifier);
2585             return -1;
2586         }
2587         objset_name = objset_ref->components[1].name;
2588     } else {
2589         FATAL("Reference %s (from %s) does not look like an object set type %s",
2590               asn1p_ref_string(objset_ref), asn1p_constraint_string(crc),
2591               opt_ioc->objset->Identifier);
2592         return -1;
2593     }
2594     if(strcmp(objset_name, opt_ioc->objset->Identifier) != 0) {
2595         FATAL("Object Set references do not match: %s != %s", objset_name,
2596               opt_ioc->objset->Identifier);
2597         return -1;
2598     }
2599
2600     if(crc->el_count != 2 || crc->elements[1]->type != ACT_EL_VALUE
2601        || crc->elements[1]->value->type != ATV_REFERENCED
2602        || crc->elements[1]->value->value.reference->comp_count != 1) {
2603         FATAL(
2604             "Do not know how to handle complex IoS constraints (%d components "
2605             "of constraint, %d components of reference %s) for %s at line "
2606             "%d",
2607             crc->el_count,
2608             crc->el_count >= 2 && crc->elements[1]->type == ACT_EL_VALUE
2609                     && crc->elements[1]->value->type == ATV_REFERENCED
2610                 ? (signed)crc->elements[1]->value->value.reference->comp_count
2611                 : -1,
2612             crc->el_count >= 2 && crc->elements[1]->type == ACT_EL_VALUE
2613                     && crc->elements[1]->value->type == ATV_REFERENCED
2614                 ? asn1p_ref_string(crc->elements[1]->value->value.reference)
2615                 : "?",
2616             MKID(parent_expr), parent_expr->_lineno);
2617         OUT("0");
2618         return -1;
2619     }
2620
2621     const asn1p_ref_t *cref = crc->elements[1]->value->value.reference;
2622     const char *cname = cref->components[0].name;
2623     if(cname[0] == '@' && cname[1] != '.') {
2624         cname += 1;
2625     } else if(cname[0] == '@' && cname[1] == '.' && cname[2] != '.') {
2626         cname += 2;
2627     } else {
2628         FATAL("Complex IoS reference %s can not be processed",
2629               asn1p_ref_string(cref));
2630         OUT("0");
2631         return -1;
2632     }
2633
2634     assert(opt_ioc != NULL);
2635
2636     asn1p_expr_t *constraining_memb = NULL;
2637     TQ_FOR(constraining_memb, &(parent_expr->members), next) {
2638         if(strcmp(constraining_memb->Identifier, cname) == 0) {
2639             break;
2640         }
2641     }
2642     if(!constraining_memb) {
2643         FATAL("Can not find \"%s\" in %s at line %d", cname, MKID(parent_expr),
2644               parent_expr->_lineno);
2645         return -1;
2646     }
2647
2648     if(constraining_memb->meta_type != AMT_TYPEREF
2649        || constraining_memb->expr_type != A1TC_REFERENCE
2650        || constraining_memb->reference->comp_count != 2
2651        || constraining_memb->reference->components[1].lex_type
2652               != RLT_Amplowercase) {
2653         FATAL(
2654             "Does not look like %s is a CLASS field reference (%s) on line "
2655             "%d",
2656             MKID(constraining_memb),
2657             constraining_memb->reference
2658                 ? asn1p_ref_string(constraining_memb->reference)
2659                 : "<no reference>",
2660             constraining_memb->_lineno);
2661         return -1;
2662     }
2663     const char *cfield = constraining_memb->reference->components[1].name;
2664
2665     ssize_t constraining_column = -1;
2666     for(size_t cn = 0; cn < opt_ioc->ioct->rows ? opt_ioc->ioct->row[0]->columns : 0;
2667         cn++) {
2668         if(strcmp(cfield, opt_ioc->ioct->row[0]->column[cn].field->Identifier)
2669            == 0) {
2670             constraining_column = cn;
2671             break;
2672         }
2673     }
2674     if(constraining_column < 0) {
2675         if(opt_ioc->ioct->rows == 0) {
2676             OUT("0");
2677             return 0;
2678         } else {
2679             FATAL("Can not find referenced object class %s column %s\n",
2680                   asn1p_ref_string(objset_ref), cfield);
2681             return -1;
2682         }
2683     }
2684
2685     if(expr->meta_type != AMT_TYPEREF
2686        || expr->expr_type != A1TC_REFERENCE
2687        || expr->reference->comp_count != 2
2688        || ((expr->reference->components[1].lex_type
2689               != RLT_AmpUppercase)
2690             && (expr->reference->components[1].lex_type
2691                    != RLT_Amplowercase))) {
2692         FATAL(
2693             "Does not look like %s is a CLASS field reference (%s) denoting a type on line "
2694             "%d",
2695             MKID(expr),
2696             expr->reference
2697                 ? asn1p_ref_string(expr->reference)
2698                 : "<no reference>",
2699             expr->_lineno);
2700         return -1;
2701     }
2702     const char *for_field = expr->reference->components[1].name;
2703
2704     ssize_t for_column = -1;
2705     for(size_t cn = 0; cn < (opt_ioc->ioct->rows ? opt_ioc->ioct->row[0]->columns : 0);
2706         cn++) {
2707         if(strcmp(for_field,
2708                   opt_ioc->ioct->row[0]->column[cn].field->Identifier)
2709            == 0) {
2710             for_column = cn;
2711             break;
2712         }
2713     }
2714     if(for_column < 0) {
2715         FATAL("Can not find referenced object class column %s\n", for_field);
2716         return -1;
2717     }
2718
2719     REDIR(OT_CODE);
2720     OUT("static asn_type_selector_result_t\n");
2721     OUT("select_%s_", c_name(arg).compound_name);
2722     OUT("%s_type(const asn_TYPE_descriptor_t *parent_type, const void *parent_sptr) {\n", MKID(expr));
2723     INDENT(+1);
2724
2725     OUT("asn_type_selector_result_t result = {0, 0};\n");
2726     OUT("const asn_ioc_set_t *itable = asn_IOS_%s_%d;\n", MKID(opt_ioc->objset),
2727         opt_ioc->objset->_type_unique_index);
2728     OUT("size_t constraining_column = %zu; /* %s */\n", constraining_column, cfield);
2729     OUT("size_t for_column = %zu; /* %s */\n", for_column, for_field);
2730     OUT("size_t row, presence_index = 0;\n");
2731
2732     const char *tname = asn1c_type_name(arg, constraining_memb, TNF_SAFE);
2733     if(constraining_memb->marker.flags & EM_INDIRECT) {
2734         OUT("const void *memb_ptr = *(const void **)");
2735         OUT("((const char *)parent_sptr + offsetof(%s", c_name(arg).full_name);
2736         OUT(", %s));", MKID_safe(constraining_memb));
2737         OUT("if(!memb_ptr) return result;\n");
2738         OUT("\n");
2739     }
2740
2741     switch(asn1c_type_fits_long(arg, constraining_memb)) {
2742     case FL_NOTFIT:
2743         OUT("const %s_t *constraining_value = (const %s_t *)", tname, tname);
2744         break;
2745     case FL_PRESUMED:
2746     case FL_FITS_SIGNED:
2747         OUT("const long *constraining_value = (const long *)");
2748         break;
2749     case FL_FITS_UNSIGN:
2750         OUT("const unsigned long *constraining_value = (const unsigned long *)");
2751         break;
2752     }
2753     if(constraining_memb->marker.flags & EM_INDIRECT) {
2754         OUT("memb_ptr;\n");
2755     } else {
2756         OUT("((const char *)parent_sptr + offsetof(%s", c_name(arg).full_name);
2757         OUT(", %s));\n", MKID_safe(constraining_memb));
2758     }
2759     OUT("\n");
2760
2761     OUT("for(row=0; row < itable->rows_count; row++) {\n");
2762     OUT("    const asn_ioc_cell_t *constraining_cell = &itable->rows[row * itable->columns_count + constraining_column];\n");
2763     OUT("    const asn_ioc_cell_t *type_cell = &itable->rows[row * itable->columns_count + for_column];\n");
2764     OUT("\n");
2765     OUT("    if(type_cell->cell_kind == aioc__undefined)\n");
2766     OUT("        continue;\n");
2767     OUT("\n");
2768     OUT("    presence_index++;\n");
2769     OUT("    if(constraining_cell->type_descriptor->op->compare_struct(constraining_cell->type_descriptor, constraining_value, constraining_cell->value_sptr) == 0) {\n");
2770     OUT("        result.type_descriptor = type_cell->type_descriptor;\n");
2771     OUT("        result.presence_index = presence_index;\n");
2772     OUT("        break;\n");
2773     OUT("    }\n");
2774     OUT("}\n");
2775
2776
2777     OUT("\n");
2778     OUT("return result;\n");
2779     INDENT(-1);
2780     OUT("}\n");
2781     OUT("\n");
2782
2783     REDIR(save_target);
2784     OUT("select_%s_", c_name(arg).compound_name);
2785     OUT("%s_type", MKID(expr));
2786
2787     return 0;
2788 }
2789
2790 static int
2791 emit_member_table(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_objset_t *opt_ioc) {
2792         int save_target;
2793         arg_t tmp_arg;
2794         struct asn1p_type_tag_s outmost_tag_s;
2795         struct asn1p_type_tag_s *outmost_tag;
2796         int complex_contents;
2797         const char *p;
2798
2799     if(WITH_MODULE_NAMESPACE(
2800            expr->module, expr_ns,
2801            asn1f_fetch_outmost_tag(arg->asn, expr_ns, expr->module, expr,
2802                                    &outmost_tag_s, AFT_IMAGINARY_ANY))) {
2803         outmost_tag = 0;
2804         } else {
2805                 outmost_tag = &outmost_tag_s;
2806         }
2807
2808         OUT("{ ");
2809
2810     if(is_open_type(arg, expr, opt_ioc)) {
2811         OUT("ATF_OPEN_TYPE | ");
2812     } else if(outmost_tag && outmost_tag->tag_value == -1) {
2813         OUT("ATF_ANY_TYPE | ");
2814     }
2815     OUT("%s, ",
2816                 (expr->marker.flags & EM_INDIRECT)?"ATF_POINTER":"ATF_NOFLAGS");
2817         if((expr->marker.flags & EM_OMITABLE) == EM_OMITABLE) {
2818                 asn1p_expr_t *tv;
2819                 int opts = 0;
2820                 for(tv = expr;
2821                         tv && (tv->marker.flags & EM_OMITABLE) == EM_OMITABLE;
2822                         tv = TQ_NEXT(tv, next), opts++) {
2823                         if(tv->expr_type == A1TC_EXTENSIBLE)
2824                                 opts--;
2825                 }
2826                 OUT("%d, ", opts);
2827         } else {
2828                 OUT("0, ");
2829         }
2830     if(expr->_anonymous_type) {
2831         assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
2832                || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
2833         OUT("0,\n");
2834     } else {
2835         OUT("offsetof(%s, ", c_name(arg).full_name);
2836         if((arg->expr->expr_type == ASN_CONSTR_CHOICE
2837             || arg->expr->expr_type == ASN_CONSTR_OPEN_TYPE)
2838            && (!UNNAMED_UNIONS))
2839             OUT("choice.");
2840         OUT("%s),\n", MKID_safe(expr));
2841     }
2842
2843     INDENT(+1);
2844         if(C99_MODE) OUT(".tag = ");
2845         if(outmost_tag) {
2846                 if(outmost_tag->tag_value == -1)
2847                         OUT("-1 /* Ambiguous tag (ANY?) */");
2848                 else
2849                         _print_tag(arg, outmost_tag);
2850         } else {
2851                 OUT("-1 /* Ambiguous tag (CHOICE?) */");
2852         }
2853
2854         OUT(",\n");
2855         if(C99_MODE) OUT(".tag_mode = ");
2856         if((!(expr->expr_type &  ASN_CONSTR_MASK)
2857            || expr->expr_type == ASN_CONSTR_CHOICE)
2858         && expr->tag.tag_class) {
2859                 if(expr->tag.tag_mode == TM_IMPLICIT)
2860                 OUT("-1,\t/* IMPLICIT tag at current level */\n");
2861                 else
2862                 OUT("+1,\t/* EXPLICIT tag at current level */\n");
2863         } else {
2864                 OUT("0,\n");
2865         }
2866
2867         complex_contents =
2868                 is_open_type(arg, expr, opt_ioc)
2869                 || (expr->expr_type & ASN_CONSTR_MASK)
2870                 || expr->expr_type == ASN_BASIC_ENUMERATED
2871                 || (0 /* -- prohibited by X.693:8.3.4 */
2872                         && expr->expr_type == ASN_BASIC_INTEGER
2873                         && expr_elements_count(arg, expr))
2874                 || (expr->expr_type == ASN_BASIC_INTEGER
2875                         && asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN);
2876         if(C99_MODE) OUT(".type = ");
2877
2878     OUT("&asn_DEF_");
2879     if(complex_contents) {
2880         OUT("%s", MKID(expr));
2881         if(!(arg->flags & A1C_ALL_DEFS_GLOBAL))
2882             OUT("_%d", expr->_type_unique_index);
2883     } else {
2884         OUT("%s", asn1c_type_name(arg, expr, TNF_SAFE));
2885     }
2886     OUT(",\n");
2887
2888
2889     if(C99_MODE) OUT(".type_selector = ");
2890     if(opt_ioc) {
2891         if(emit_member_type_selector(arg, expr, opt_ioc) < 0)
2892             return -1;
2893     } else {
2894         OUT("0");
2895     }
2896         OUT(",\n");
2897
2898     OUT("{ ");
2899         if(C99_MODE) OUT(".oer_constraints = ");
2900         if(arg->flags & A1C_GEN_OER) {
2901                 if(expr->constraints) {
2902                         OUT("&asn_OER_memb_%s_constr_%d",
2903                                 MKID(expr),
2904                                 expr->_type_unique_index);
2905                 } else {
2906                         OUT("0");
2907                 }
2908         } else {
2909         OUT("0");
2910         }
2911     OUT(", ");
2912         if(C99_MODE) OUT(".per_constraints = ");
2913         if(arg->flags & A1C_GEN_PER) {
2914                 if(expr->constraints) {
2915                         OUT("&asn_PER_memb_%s_constr_%d",
2916                                 MKID(expr),
2917                                 expr->_type_unique_index);
2918                 } else {
2919                         OUT("0");
2920                 }
2921         } else {
2922                 OUT("0");
2923         }
2924     OUT(", ");
2925         if(C99_MODE) OUT(".general_constraints = ");
2926         if(expr->constraints) {
2927                 if(arg->flags & A1C_NO_CONSTRAINTS) {
2928                         OUT("0");
2929                 } else {
2930                         const char *id = MKID(expr);
2931                         if(expr->_anonymous_type
2932                                         && !strcmp(expr->Identifier, "Member"))
2933                                 id = asn1c_type_name(arg, expr, TNF_SAFE);
2934                         OUT(" memb_%s_constraint_%d", id,
2935                                 arg->expr->_type_unique_index);
2936                 }
2937         } else {
2938                 OUT("0");
2939         }
2940     OUT(" },\n");
2941
2942         if(try_inline_default(arg, expr, 0)) {
2943         } else {
2944                 OUT("0, 0, /* No default value */\n");
2945         }
2946         if(C99_MODE) OUT(".name = ");
2947         if(expr->_anonymous_type && !strcmp(expr->Identifier, "Member")) {
2948                 OUT("\"\"\n");
2949         } else {
2950                 OUT("\"%s\"\n", expr->Identifier);
2951         }
2952         OUT("},\n");
2953         INDENT(-1);
2954
2955         if(!expr->constraints || (arg->flags & A1C_NO_CONSTRAINTS))
2956                 return 0;
2957
2958         save_target = arg->target->target;
2959         REDIR(OT_CODE);
2960
2961         if(expr->_anonymous_type && !strcmp(expr->Identifier, "Member"))
2962                 p = asn1c_type_name(arg, expr, TNF_SAFE);
2963         else
2964                 p = MKID(expr);
2965         OUT("static int\n");
2966         OUT("memb_%s_constraint_%d(const asn_TYPE_descriptor_t *td, const void *sptr,\n", p, arg->expr->_type_unique_index);
2967         INDENT(+1);
2968         OUT("\t\tasn_app_constraint_failed_f *ctfailcb, void *app_key) {\n");
2969         tmp_arg = *arg;
2970         tmp_arg.expr = expr;
2971         DEBUG("member constraint checking code for %s", p);
2972         if(asn1c_emit_constraint_checking_code(&tmp_arg) == 1) {
2973                 OUT("return td->encoding_constraints.general_constraints"
2974                         "(td, sptr, ctfailcb, app_key);\n");
2975         }
2976         INDENT(-1);
2977         OUT("}\n");
2978         OUT("\n");
2979
2980         if(emit_member_OER_constraints(arg, expr, "memb"))
2981                 return -1;
2982
2983         if(emit_member_PER_constraints(arg, expr, "memb"))
2984                 return -1;
2985
2986         REDIR(save_target);
2987
2988         return 0;
2989 }
2990
2991 /*
2992  * Generate "asn_DEF_XXX" type definition.
2993  */
2994 static int
2995 emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, enum tvm_compat tv_mode, int tags_count, int all_tags_count, int elements_count, enum etd_spec spec) {
2996         asn1p_expr_t *terminal;
2997         int using_type_name = 0;
2998         char *expr_id = strdup(MKID(expr));
2999         char *p = expr_id;
3000         char *p2 = (char *)0;
3001
3002         terminal = asn1f_find_terminal_type_ex(arg->asn, arg->ns, expr);
3003
3004         if(emit_member_OER_constraints(arg, expr, "type"))
3005                 return -1;
3006
3007         if(emit_member_PER_constraints(arg, expr, "type"))
3008                 return -1;
3009
3010         if(HIDE_INNER_DEFS)
3011                 OUT("static /* Use -fall-defs-global to expose */\n");
3012         OUT("asn_TYPE_descriptor_t asn_DEF_%s", p);
3013     if(HIDE_INNER_DEFS || (arg->flags & A1C_ALL_DEFS_GLOBAL))
3014         OUT("_%d", expr->_type_unique_index);
3015     OUT(" = {\n");
3016         INDENT(+1);
3017
3018                 if(expr->_anonymous_type) {
3019                         p = strdup(ASN_EXPR_TYPE2STR(expr->expr_type));
3020                         OUT("\"%s\",\n", p?p:"");
3021                         OUT("\"%s\",\n",
3022                                 p ? asn1c_make_identifier(AMI_CHECK_RESERVED,
3023                                         0, p, 0) : "");
3024                 } else {
3025                         OUT("\"%s\",\n", expr->Identifier);
3026                         OUT("\"%s\",\n", expr->Identifier);
3027                 }
3028
3029                 if(expr->expr_type & ASN_CONSTR_MASK) {
3030                         using_type_name = 1;
3031                         p = strdup(asn1c_type_name(arg, arg->expr, TNF_SAFE));
3032                 } else {
3033                         if (expr->expr_type == A1TC_REFERENCE) {
3034                                 p2 = strdup(asn1c_type_name(arg, terminal, TNF_SAFE));
3035                         } else {
3036                                 p2 = strdup(asn1c_type_name(arg, expr, TNF_SAFE));
3037                         }
3038                         p = strdup(expr_id);
3039                 }
3040                 if (!p2)
3041                         p2 = strdup(p);
3042
3043         OUT("&asn_OP_%s,\n", p2);
3044
3045                 if(tags_count) {
3046                         OUT("asn_DEF_%s_tags_%d,\n",
3047                                 expr_id, expr->_type_unique_index);
3048                         OUT("sizeof(asn_DEF_%s_tags_%d)\n",
3049                                 expr_id, expr->_type_unique_index);
3050                         OUT("\t/sizeof(asn_DEF_%s_tags_%d[0])",
3051                                 expr_id, expr->_type_unique_index);
3052                         if(tv_mode == _TVM_SUBSET
3053                         && tags_count != all_tags_count)
3054                                 OUT(" - %d", all_tags_count - tags_count);
3055                         OUT(", /* %d */\n", tags_count);
3056                 } else {
3057                         OUT("0,\t/* No effective tags (pointer) */\n");
3058                         OUT("0,\t/* No effective tags (count) */\n");
3059                 }
3060
3061                 if(all_tags_count && tv_mode == _TVM_DIFFERENT) {
3062                         OUT("asn_DEF_%s_all_tags_%d,\n",
3063                                 expr_id, expr->_type_unique_index);
3064                         OUT("sizeof(asn_DEF_%s_all_tags_%d)\n",
3065                                 expr_id, expr->_type_unique_index);
3066                         OUT("\t/sizeof(asn_DEF_%s_all_tags_%d[0]), /* %d */\n",
3067                                 expr_id, expr->_type_unique_index, all_tags_count);
3068                 } else if(all_tags_count) {
3069                         OUT("asn_DEF_%s_tags_%d,\t/* Same as above */\n",
3070                                 expr_id, expr->_type_unique_index);
3071                         OUT("sizeof(asn_DEF_%s_tags_%d)\n",
3072                                 expr_id, expr->_type_unique_index);
3073                         OUT("\t/sizeof(asn_DEF_%s_tags_%d[0]), /* %d */\n",
3074                                 expr_id, expr->_type_unique_index, all_tags_count);
3075                 } else {
3076                         OUT("0,\t/* No tags (pointer) */\n");
3077                         OUT("0,\t/* No tags (count) */\n");
3078                 }
3079
3080                 OUT("{ ");
3081                 if(arg->flags & A1C_GEN_OER) {
3082                         if(expr->combined_constraints
3083                         || expr->expr_type == ASN_BASIC_ENUMERATED
3084                         || expr->expr_type == ASN_CONSTR_CHOICE) {
3085                                 OUT("&asn_OER_type_%s_constr_%d",
3086                                         expr_id, expr->_type_unique_index);
3087                         } else {
3088                                 OUT("0");
3089                         }
3090                 } else {
3091                         OUT("0");
3092                 }
3093         OUT(", ");
3094
3095                 if(arg->flags & A1C_GEN_PER) {
3096             if(expr->combined_constraints
3097                || expr->expr_type == ASN_BASIC_ENUMERATED
3098                || expr->expr_type == ASN_CONSTR_CHOICE
3099                || (expr->expr_type & ASN_STRING_KM_MASK)) {
3100                 OUT("&asn_PER_type_%s_constr_%d",
3101                                         expr_id, expr->_type_unique_index);
3102                         } else {
3103                                 OUT("0");
3104                         }
3105                 } else {
3106                         OUT("0");
3107                 }
3108                 OUT(", ");
3109 #define FUNCREF(foo)                              \
3110     do {                                          \
3111         OUT("%s", p);                             \
3112         if(HIDE_INNER_DEFS && !using_type_name)   \
3113             OUT("_%d", expr->_type_unique_index); \
3114         OUT("_" #foo "");                         \
3115     } while(0)
3116
3117 #define FUNCREF2(foo)  \
3118     do {               \
3119         OUT("%s", p2); \
3120         OUT("_" #foo); \
3121     } while(0)
3122
3123         if (arg->flags & A1C_NO_CONSTRAINTS) {
3124                         OUT("0");
3125                 } else {
3126                         if (!expr->combined_constraints)
3127                                 FUNCREF2(constraint);
3128                         else
3129                                 FUNCREF(constraint);
3130                 }
3131         OUT(" },\n");
3132
3133         free(p);
3134         p = NULL;
3135         free(p2);
3136         p2 = NULL;
3137         free(expr_id);
3138         expr_id = NULL;
3139
3140                 if(elements_count ||
3141                         ((expr->expr_type == A1TC_REFERENCE) &&
3142                                 (terminal->expr_type & ASN_CONSTR_MASK) &&
3143                                 expr_elements_count(arg, terminal))) {
3144
3145                         if (expr->expr_type == A1TC_REFERENCE) {
3146                                 OUT("asn_MBR_%s_%d,\n", MKID(terminal), terminal->_type_unique_index);
3147
3148                                 if(terminal->expr_type == ASN_CONSTR_SEQUENCE_OF
3149                                 || terminal->expr_type == ASN_CONSTR_SET_OF) {
3150                                         OUT("%d,\t/* Single element */\n",
3151                                                 expr_elements_count(arg, terminal));
3152                                         assert(expr_elements_count(arg, terminal) == 1);
3153                                 } else {
3154                                         OUT("%d,\t/* Elements count */\n",
3155                                                 expr_elements_count(arg, terminal));
3156                                 }
3157                         } else {
3158                 OUT("asn_MBR_%s_%d,\n", c_name(arg).part_name,
3159                     expr->_type_unique_index);
3160
3161                 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF
3162                                 || expr->expr_type == ASN_CONSTR_SET_OF) {
3163                                         OUT("%d,\t/* Single element */\n",
3164                                                 elements_count);
3165                                         assert(elements_count == 1);
3166                                 } else {
3167                                         OUT("%d,\t/* Elements count */\n",
3168                                                 elements_count);
3169                                 }
3170                         }
3171                 } else {
3172                         if(expr_elements_count(arg, expr))
3173                                 OUT("0, 0,\t/* Defined elsewhere */\n");
3174                         else
3175                                 OUT("0, 0,\t/* No members */\n");
3176                 }
3177
3178                 switch(spec) {
3179                 case ETD_NO_SPECIFICS:
3180                         if ((expr->expr_type == A1TC_REFERENCE) &&
3181                                 ((terminal->expr_type & ASN_CONSTR_MASK) ||
3182                                 (terminal->expr_type == ASN_BASIC_ENUMERATED) ||
3183                                 ((terminal->expr_type == ASN_BASIC_INTEGER) &&
3184                                 (asn1c_type_fits_long(arg, terminal) == FL_FITS_UNSIGN)))) {
3185                 OUT("&asn_SPC_%s_specs_%d\t/* Additional specs */\n",
3186                     c_expr_name(arg, terminal).part_name,
3187                     terminal->_type_unique_index);
3188             } else if ((expr->expr_type == ASN_TYPE_ANY) ||
3189                                         (expr->expr_type == ASN_BASIC_BIT_STRING) ||
3190                                         (expr->expr_type == ASN_STRING_BMPString) ||
3191                                         (expr->expr_type == ASN_BASIC_OCTET_STRING) ||
3192                                         (expr->expr_type == ASN_STRING_UniversalString)) {
3193                 OUT("&asn_SPC_%s_specs\t/* Additional specs */\n",
3194                     c_name(arg).type.part_name);
3195             } else if ((expr->expr_type == A1TC_REFERENCE) &&
3196                                         ((terminal->expr_type == ASN_TYPE_ANY) ||
3197                                         (terminal->expr_type == ASN_BASIC_BIT_STRING) ||
3198                                         (terminal->expr_type == ASN_STRING_BMPString) ||
3199                                         (terminal->expr_type == ASN_BASIC_OCTET_STRING) ||
3200                                         (terminal->expr_type == ASN_STRING_UniversalString))) {
3201                 OUT("&asn_SPC_%s_specs\t/* Additional specs */\n",
3202                     c_expr_name(arg, terminal).type.part_name);
3203             } else {
3204                                 OUT("0\t/* No specifics */\n");
3205                         }
3206                         break;
3207                 case ETD_HAS_SPECIFICS:
3208                         OUT("&asn_SPC_%s_specs_%d\t/* Additional specs */\n",
3209                                 c_name(arg).part_name, expr->_type_unique_index);
3210                 }
3211         INDENT(-1);
3212         OUT("};\n");
3213         OUT("\n");
3214
3215         return 0;
3216 }
3217
3218 static int
3219 expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr) {
3220         /*
3221          * X.680, 25.5, Table 5
3222          */
3223         switch(expr_get_type(arg, expr)) {
3224         case ASN_BASIC_BOOLEAN:
3225         case ASN_BASIC_ENUMERATED:
3226         case ASN_BASIC_NULL:
3227                 return 1;
3228         case ASN_CONSTR_CHOICE:
3229                 return 2;
3230         default:
3231                 return 0;
3232         }
3233 }
3234
3235 static int
3236 out_name_chain(arg_t *arg, enum onc_flags onc_flags) {
3237         asn1p_expr_t *expr = arg->expr;
3238         const char *id;
3239
3240         if((arg->flags & A1C_COMPOUND_NAMES
3241            || onc_flags & ONC_force_compound_name
3242            || (0 && arg->embed /* Not yet */))
3243         && ((expr->expr_type & ASN_CONSTR_MASK)
3244            || expr->expr_type == ASN_BASIC_ENUMERATED
3245            || ((expr->expr_type == ASN_BASIC_INTEGER
3246                 || expr->expr_type == ASN_BASIC_BIT_STRING)
3247                 && expr_elements_count(arg, expr))
3248            )
3249         && expr->parent_expr) {
3250
3251                 arg_t tmparg = *arg;
3252
3253                 tmparg.expr = expr->parent_expr;
3254                 if(0) tmparg.flags &= ~A1C_COMPOUND_NAMES;
3255
3256                 out_name_chain(&tmparg, onc_flags);
3257
3258                 if(expr->parent_expr->Identifier) OUT("__");    /* a separator between id components */
3259
3260                 /* Fall through */
3261         }
3262
3263         if(onc_flags & ONC_avoid_keywords)
3264                 id = MKID_safe(expr);
3265         else
3266                 id = MKID(expr);
3267         OUT("%s", id);
3268
3269         return 0;
3270 }
3271
3272 static int
3273 emit_include_dependencies(arg_t *arg) {
3274         asn1p_expr_t *expr = arg->expr;
3275         asn1p_expr_t *memb;
3276
3277         /* Avoid recursive definitions. */
3278         TQ_FOR(memb, &(expr->members), next) {
3279                 expr_break_recursion(arg, memb);
3280         }
3281
3282         TQ_FOR(memb, &(expr->members), next) {
3283
3284                 if(memb->marker.flags & (EM_INDIRECT | EM_UNRECURSE)) {
3285                         if(terminal_structable(arg, memb)) {
3286                                 int saved_target = arg->target->target;
3287                                 if(saved_target != OT_FWD_DECLS) {
3288                                         REDIR(OT_FWD_DECLS);
3289                                         OUT("%s;\n",
3290                                                 asn1c_type_name(arg, memb, TNF_RSAFE));
3291                                 }
3292                                 REDIR(saved_target);
3293                         }
3294                 }
3295
3296                 if((!(memb->expr_type & ASN_CONSTR_MASK)
3297                         && memb->expr_type > ASN_CONSTR_MASK)
3298                 || memb->meta_type == AMT_TYPEREF) {
3299                         GEN_POS_INCLUDE_BASE((memb->marker.flags & EM_UNRECURSE) ?
3300                                         OT_POST_INCLUDE : OT_INCLUDES, memb);
3301                 }
3302         }
3303
3304         return 0;
3305 }
3306
3307 /*
3308  * Check if it is better to make this type indirectly accessed via
3309  * a pointer.
3310  * This may be the case for the following recursive definition:
3311  * Type ::= CHOICE { member Type };
3312  */
3313 static int
3314 expr_break_recursion(arg_t *arg, asn1p_expr_t *expr) {
3315         int ret;
3316
3317         if(expr->marker.flags & EM_UNRECURSE)
3318                 return 1;       /* Already broken */
3319
3320         /* -findirect-choice compiles members of CHOICE as indirect pointers */
3321         if((arg->flags & A1C_INDIRECT_CHOICE)
3322          && arg->expr->expr_type == ASN_CONSTR_CHOICE
3323          && (expr_get_type(arg, expr) & ASN_CONSTR_MASK)
3324         ) {
3325                 /* Break cross-reference */
3326                 expr->marker.flags |= EM_INDIRECT | EM_UNRECURSE;
3327                 return 1;
3328         }
3329
3330         if((expr->marker.flags & EM_INDIRECT)
3331         || arg->expr->expr_type == ASN_CONSTR_SET_OF
3332         || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF) {
3333                 if(terminal_structable(arg, expr)) {
3334                         expr->marker.flags |= EM_UNRECURSE;
3335
3336                         if(arg->expr->expr_type == ASN_CONSTR_SET_OF
3337                         || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF) {
3338                                 /* Don't put EM_INDIRECT even if recursion */
3339                                 return 1;
3340                         }
3341
3342                         /* Fall through */
3343                 }
3344         }
3345
3346         /* Look for recursive back-references */
3347         ret = expr_defined_recursively(arg, expr);
3348         switch(ret) {
3349         case 2: /* Explicitly break the recursion */
3350         case 1: /* Use safer typing */
3351                 expr->marker.flags |= EM_INDIRECT;
3352                 expr->marker.flags |= EM_UNRECURSE;
3353                 break;
3354         }
3355
3356         return 0;
3357 }
3358
3359 /*
3360  * Check if the type can be represented using simple `struct TYPE`.
3361  */
3362 static asn1p_expr_t *
3363 terminal_structable(arg_t *arg, asn1p_expr_t *expr) {
3364     asn1p_expr_t *terminal =
3365         asn1f_find_terminal_type_ex(arg->asn, arg->ns, expr);
3366     if(terminal
3367         && !terminal->parent_expr
3368         && (terminal->expr_type & ASN_CONSTR_MASK)) {
3369                 return terminal;
3370         }
3371         return 0;
3372 }
3373
3374 static int
3375 asn1c_recurse(arg_t *arg, asn1p_expr_t *expr, int (*callback)(arg_t *arg, void *key), void *key) {
3376         arg_t tmp = *arg;
3377         int maxret = 0;
3378         int ret;
3379
3380         if(expr->_mark & TM_RECURSION) return 0;
3381         expr->_mark |= TM_RECURSION;
3382
3383         /* Invoke callback for every type going into recursion */
3384         tmp.expr = expr;
3385         maxret = callback(&tmp, key);
3386         if(maxret <= 1) {
3387                 /*
3388                  * Recursively invoke myself and the callbacks.
3389                  */
3390                 TQ_FOR(tmp.expr, &(expr->members), next) {
3391                         ret = asn1c_recurse(&tmp, tmp.expr, callback, key);
3392                         if(ret > maxret)
3393                                 maxret = ret;
3394                         if(maxret > 1) break;
3395                 }
3396         }
3397
3398         expr->_mark &= ~TM_RECURSION;
3399         return maxret;
3400 }
3401
3402 static int
3403 check_is_refer_to(arg_t *arg, void *key) {
3404         asn1p_expr_t *terminal = terminal_structable(arg, arg->expr);
3405         if(terminal == key) {
3406                 if(arg->expr->marker.flags & EM_INDIRECT)
3407                         return 1; /* This is almost safe indirection */
3408                 return 2;
3409         } else if(terminal) {
3410                 /* This might be N-step circular loop. Dive into it. */
3411                 return asn1c_recurse(arg, terminal, check_is_refer_to, key);
3412         }
3413         return 0;
3414 }
3415
3416 /*
3417  * Check if the possibly inner expression defined recursively.
3418  */
3419 static int
3420 expr_defined_recursively(arg_t *arg, asn1p_expr_t *expr) {
3421         asn1p_expr_t *terminal;
3422         asn1p_expr_t *topmost;
3423
3424         /* If expression is top-level, there's no way it can be recursive. */
3425         if(expr->parent_expr == 0) return 0;
3426         if(expr->expr_type != A1TC_REFERENCE)
3427                 return 0;       /* Basic types are never recursive */
3428
3429         terminal = terminal_structable(arg, expr);
3430         if(!terminal) return 0; /* Terminal cannot be indirected */
3431
3432         /* Search for the parent container for the given expression */
3433         topmost = expr;
3434         while(topmost->parent_expr)
3435                 topmost = topmost->parent_expr;
3436
3437         /* Look inside the terminal type if it mentions the parent expression */
3438         return asn1c_recurse(arg, terminal, check_is_refer_to, topmost);
3439 }
3440
3441 struct canonical_map_element {
3442         int eidx;
3443         asn1p_expr_t *expr;
3444 };
3445 static int compar_cameo(const void *ap, const void *bp);
3446 static arg_t *cameo_arg;
3447 static int *
3448 compute_canonical_members_order(arg_t *arg, int el_count) {
3449         struct canonical_map_element *cmap;
3450         int *rmap;
3451         asn1p_expr_t *v;
3452         int eidx = 0;
3453         int first_extension = -1;
3454         int nextmax = -1;
3455         int already_sorted = 1;
3456
3457         cmap = calloc(el_count, sizeof *cmap);
3458         assert(cmap);
3459
3460         TQ_FOR(v, &(arg->expr->members), next) {
3461                 if(v->expr_type != A1TC_EXTENSIBLE) {
3462                         cmap[eidx].eidx = eidx;
3463                         cmap[eidx].expr = v;
3464                         eidx++;
3465                 } else if(first_extension == -1)
3466                         first_extension = eidx;
3467         }
3468
3469         cameo_arg = arg;
3470         if(first_extension == -1) {
3471                 /* Sort the whole thing */
3472                 qsort(cmap, el_count, sizeof(*cmap), compar_cameo);
3473         } else {
3474                 /* Sort root and extensions independently */
3475                 qsort(cmap, first_extension, sizeof(*cmap), compar_cameo);
3476                 qsort(cmap + first_extension, el_count - first_extension,
3477                         sizeof(*cmap), compar_cameo);
3478         }
3479
3480         /* move data back to a simpler map */
3481         rmap = calloc(el_count, sizeof *rmap);
3482         assert(rmap);
3483         for(eidx = 0; eidx < el_count; eidx++) {
3484                 rmap[eidx] = cmap[eidx].eidx;
3485                 if(rmap[eidx] <= nextmax)
3486                         already_sorted = 0;
3487                 else
3488                         nextmax = rmap[eidx];
3489         }
3490         free(cmap);
3491
3492         if(already_sorted) { free(rmap); rmap = 0; }
3493         return rmap;
3494 }
3495 static int compar_cameo(const void *ap, const void *bp) {
3496         const struct canonical_map_element *a = (const void *)ap;
3497         const struct canonical_map_element *b = (const void *)bp;
3498         struct asn1p_type_tag_s atag, btag;
3499         arg_t *arg = cameo_arg;
3500
3501     if(WITH_MODULE_NAMESPACE(a->expr->module, expr_ns,
3502                              asn1f_fetch_outmost_tag(
3503                                  arg->asn, expr_ns, a->expr->module, a->expr,
3504                                  &atag, AFT_IMAGINARY_ANY | AFT_CANON_CHOICE)))
3505         return 1;
3506
3507     if(WITH_MODULE_NAMESPACE(
3508            b->expr->module, expr_ns,
3509            asn1f_fetch_outmost_tag(arg->asn, expr_ns, b->expr->module, b->expr,
3510                                    &btag,
3511                                    AFT_IMAGINARY_ANY | AFT_CANON_CHOICE))) {
3512         return -1;
3513     }
3514
3515     if(atag.tag_class < btag.tag_class)
3516                 return -1;
3517         if(atag.tag_class > btag.tag_class)
3518                 return 1;
3519         if(atag.tag_value < btag.tag_value)
3520                 return -1;
3521         if(atag.tag_value > btag.tag_value)
3522                 return 1;
3523         return 0;
3524
3525 }