blob: 54025d3679ed831c9a651dd008296342a3831e23 [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001/*
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"
Lev Walkin84cd58e2004-08-19 13:29:46 +00007#include "asn1c_constraint.h"
Lev Walkin59004fa2004-08-20 13:37:01 +00008#include "asn1c_out.h"
9#include "asn1c_misc.h"
Lev Walkin59b176e2005-11-26 11:25:14 +000010#include <asn1fix_crange.h> /* constraint groker from libasn1fix */
11#include <asn1fix_export.h> /* other exportables from libasn1fix */
Lev Walkinda997b12017-08-04 01:38:41 -070012#include <asn1parser.h>
Lev Walkinf15320b2004-06-03 03:38:44 +000013
Lev Walkinfd171ef2004-06-06 07:20:17 +000014typedef struct tag2el_s {
15 struct asn1p_type_tag_s el_tag;
16 int el_no;
Lev Walkin38abe792004-06-14 13:09:45 +000017 int toff_first;
18 int toff_last;
Lev Walkinfd171ef2004-06-06 07:20:17 +000019 asn1p_expr_t *from_expr;
20} tag2el_t;
21
Lev Walkin33d5d3c2004-10-03 09:13:30 +000022typedef enum fte {
23 FTE_ALLTAGS,
24 FTE_CANONICAL_XER,
25} fte_e;
26static int _fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags);
27static int _add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags);
Lev Walkinfd171ef2004-06-06 07:20:17 +000028
Lev Walkin0f5d74c2005-08-14 15:03:31 +000029enum onc_flags {
30 ONC_noflags = 0x00,
31 ONC_avoid_keywords = 0x01,
32 ONC_force_compound_name = 0x02,
33};
34static int out_name_chain(arg_t *arg, enum onc_flags);
Lev Walkinf15320b2004-06-03 03:38:44 +000035static int asn1c_lang_C_type_SEQUENCE_def(arg_t *arg);
36static int asn1c_lang_C_type_SET_def(arg_t *arg);
37static int asn1c_lang_C_type_CHOICE_def(arg_t *arg);
38static int asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of);
Lev Walkinc3e29402004-09-10 06:07:18 +000039static int _print_tag(arg_t *arg, struct asn1p_type_tag_s *tag_p);
Lev Walkin59b176e2005-11-26 11:25:14 +000040static int compute_extensions_start(asn1p_expr_t *expr);
Lev Walkinda9a3b82005-08-16 17:00:21 +000041static int expr_break_recursion(arg_t *arg, asn1p_expr_t *expr);
Lev Walkina9cc46e2004-09-22 16:06:28 +000042static int expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr);
Lev Walkin59964be2004-08-25 02:03:12 +000043static int expr_elements_count(arg_t *arg, asn1p_expr_t *expr);
Lev Walkinb9e98cb2017-08-02 12:53:44 -070044static int emit_single_member_OER_constraint_value(arg_t *arg, asn1cnst_range_t *range);
45static int emit_single_member_OER_constraint_size(arg_t *arg, asn1cnst_range_t *range);
46static int emit_single_member_PER_constraint(arg_t *arg, asn1cnst_range_t *range, int juscountvalues, const char *type);
Lev Walkin98eabc12017-07-19 08:51:11 +040047static int emit_member_OER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx);
Lev Walkin4b5dae32006-10-09 12:27:44 +000048static int emit_member_PER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx);
Lev Walkin59964be2004-08-25 02:03:12 +000049static int emit_member_table(arg_t *arg, asn1p_expr_t *expr);
Lev Walkin33d5d3c2004-10-03 09:13:30 +000050static int emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier);
Lev Walkinc8285712005-03-04 22:18:20 +000051static int emit_include_dependencies(arg_t *arg);
Lev Walkinb85a8132005-08-18 13:38:19 +000052static asn1p_expr_t *terminal_structable(arg_t *arg, asn1p_expr_t *expr);
53static int expr_defined_recursively(arg_t *arg, asn1p_expr_t *expr);
54static int asn1c_recurse(arg_t *arg, asn1p_expr_t *expr, int (*callback)(arg_t *arg, void *key), void *key);
Lev Walkin59b176e2005-11-26 11:25:14 +000055static asn1p_expr_type_e expr_get_type(arg_t *arg, asn1p_expr_t *expr);
56static int try_inline_default(arg_t *arg, asn1p_expr_t *expr, int out);
57static int *compute_canonical_members_order(arg_t *arg, int el_count);
Lev Walkinf15320b2004-06-03 03:38:44 +000058
Lev Walkin188ed2c2004-09-13 08:31:01 +000059enum tvm_compat {
60 _TVM_SAME = 0, /* tags and all_tags are same */
61 _TVM_SUBSET = 1, /* tags are subset of all_tags */
62 _TVM_DIFFERENT = 2, /* tags and all_tags are different */
63};
64static enum tvm_compat emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tc, int *atc);
65
Lev Walkin59964be2004-08-25 02:03:12 +000066enum etd_spec {
67 ETD_NO_SPECIFICS,
68 ETD_HAS_SPECIFICS
69};
Lev Walkin8de2ab22004-09-26 13:11:31 +000070static 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);
Lev Walkin59964be2004-08-25 02:03:12 +000071
Lev Walkin59004fa2004-08-20 13:37:01 +000072#define C99_MODE (!(arg->flags & A1C_NO_C99))
Lev Walkinf15320b2004-06-03 03:38:44 +000073#define UNNAMED_UNIONS (arg->flags & A1C_UNNAMED_UNIONS)
Lev Walkindd32b592004-09-06 08:07:29 +000074#define HIDE_INNER_DEFS (arg->embed && !(arg->flags & A1C_ALL_DEFS_GLOBAL))
Lev Walkinf15320b2004-06-03 03:38:44 +000075
76#define PCTX_DEF INDENTED( \
77 OUT("\n"); \
78 OUT("/* Context for parsing across buffer boundaries */\n"); \
Lev Walkin05363a72004-09-29 13:16:40 +000079 OUT("asn_struct_ctx_t _asn_ctx;\n"));
Lev Walkinf15320b2004-06-03 03:38:44 +000080
Lev Walkinc8285712005-03-04 22:18:20 +000081
Lev Walkin3dcaafa2004-08-11 05:21:32 +000082#define DEPENDENCIES do { \
Lev Walkinc8285712005-03-04 22:18:20 +000083 emit_include_dependencies(arg); \
Lev Walkin3dcaafa2004-08-11 05:21:32 +000084 if(expr->expr_type == ASN_CONSTR_SET_OF) \
Lev Walkin22b5ed42006-09-13 02:51:20 +000085 GEN_INCLUDE_STD("asn_SET_OF"); \
Lev Walkin3dcaafa2004-08-11 05:21:32 +000086 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF) \
Lev Walkin22b5ed42006-09-13 02:51:20 +000087 GEN_INCLUDE_STD("asn_SEQUENCE_OF"); \
Lev Walkin3dcaafa2004-08-11 05:21:32 +000088} while(0)
Lev Walkinf15320b2004-06-03 03:38:44 +000089
Lev Walkincaf0d5a2005-03-04 23:48:19 +000090/* MKID_safe() without checking for reserved keywords */
Lev Walkina00d6b32006-03-21 03:40:38 +000091#define MKID(expr) (asn1c_make_identifier(0, expr, 0))
92#define MKID_safe(expr) (asn1c_make_identifier(AMI_CHECK_RESERVED, expr, 0))
Lev Walkinf15320b2004-06-03 03:38:44 +000093
94int
Lev Walkinc78cbfb2004-09-14 12:47:45 +000095asn1c_lang_C_type_REAL(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +000096 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
97}
98
Lev Walkine0b56e02005-02-25 12:10:27 +000099struct value2enum {
100 asn1c_integer_t value;
101 const char *name;
102 int idx;
103};
104static int compar_enumMap_byName(const void *ap, const void *bp) {
105 const struct value2enum *a = (const struct value2enum *)ap;
106 const struct value2enum *b = (const struct value2enum *)bp;
107 return strcmp(a->name, b->name);
108}
109static int compar_enumMap_byValue(const void *ap, const void *bp) {
110 const struct value2enum *a = (const struct value2enum *)ap;
111 const struct value2enum *b = (const struct value2enum *)bp;
112 if(a->value < b->value)
113 return -1;
114 else if(a->value == b->value)
115 return 0;
116 return 1;
117}
118
Lev Walkinf15320b2004-06-03 03:38:44 +0000119int
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000120asn1c_lang_C_type_common_INTEGER(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000121 asn1p_expr_t *expr = arg->expr;
122 asn1p_expr_t *v;
Lev Walkine0b56e02005-02-25 12:10:27 +0000123 int el_count = expr_elements_count(arg, expr);
124 struct value2enum *v2e;
Lev Walkin59b176e2005-11-26 11:25:14 +0000125 int map_extensions = (expr->expr_type == ASN_BASIC_INTEGER);
Lev Walkin414b0782005-08-13 23:30:24 +0000126 int eidx;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800127 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000128
Lev Walkine0b56e02005-02-25 12:10:27 +0000129 v2e = alloca((el_count + 1) * sizeof(*v2e));
Lev Walkinf15320b2004-06-03 03:38:44 +0000130
Lev Walkine0b56e02005-02-25 12:10:27 +0000131 /*
Lev Walkin414b0782005-08-13 23:30:24 +0000132 * For all ENUMERATED types and for those INTEGER types which
133 * have identifiers, print out an enumeration table.
Lev Walkine0b56e02005-02-25 12:10:27 +0000134 */
Lev Walkin414b0782005-08-13 23:30:24 +0000135 if(expr->expr_type == ASN_BASIC_ENUMERATED || el_count) {
136 eidx = 0;
Lev Walkine0b56e02005-02-25 12:10:27 +0000137 REDIR(OT_DEPS);
Lev Walkin21d00002005-03-04 08:48:53 +0000138 OUT("typedef enum ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000139 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000140 OUT(" {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000141 TQ_FOR(v, &(expr->members), next) {
142 switch(v->expr_type) {
143 case A1TC_UNIVERVAL:
Lev Walkin21d00002005-03-04 08:48:53 +0000144 OUT("\t");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000145 out_name_chain(arg, ONC_noflags);
Lev Walkina00d6b32006-03-21 03:40:38 +0000146 OUT("_%s", MKID(v));
Lev Walkinda997b12017-08-04 01:38:41 -0700147 OUT("\t= %s%s\n",
148 asn1p_itoa(v->value->value.v_integer),
Lev Walkin21d00002005-03-04 08:48:53 +0000149 (eidx+1 < el_count) ? "," : "");
Lev Walkine0b56e02005-02-25 12:10:27 +0000150 v2e[eidx].name = v->Identifier;
151 v2e[eidx].value = v->value->value.v_integer;
152 eidx++;
Lev Walkinf15320b2004-06-03 03:38:44 +0000153 break;
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000154 case A1TC_EXTENSIBLE:
155 OUT("\t/*\n");
156 OUT("\t * Enumeration is extensible\n");
157 OUT("\t */\n");
Lev Walkin59b176e2005-11-26 11:25:14 +0000158 if(!map_extensions)
159 map_extensions = eidx + 1;
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000160 break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000161 default:
162 return -1;
163 }
164 }
Lev Walkin171487e2006-03-21 07:25:18 +0000165 OUT("} e_");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000166 out_name_chain(arg, ONC_noflags);
Lev Walkin171487e2006-03-21 07:25:18 +0000167 OUT(";\n");
Lev Walkine0b56e02005-02-25 12:10:27 +0000168 assert(eidx == el_count);
Lev Walkin414b0782005-08-13 23:30:24 +0000169 }
170
171 /*
172 * For all ENUMERATED types print out a mapping table
173 * between identifiers and associated values.
174 * This is prohibited for INTEGER types by by X.693:8.3.4.
175 */
176 if(expr->expr_type == ASN_BASIC_ENUMERATED) {
Lev Walkine0b56e02005-02-25 12:10:27 +0000177
178 /*
179 * Generate a enumerationName<->value map for XER codec.
180 */
181 REDIR(OT_STAT_DEFS);
182
Wim Lewisfb6344e2014-07-28 12:16:01 -0700183 OUT("static const asn_INTEGER_enum_map_t asn_MAP_%s_value2enum_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000184 MKID(expr), expr->_type_unique_index);
Lev Walkine0b56e02005-02-25 12:10:27 +0000185 qsort(v2e, el_count, sizeof(v2e[0]), compar_enumMap_byValue);
186 for(eidx = 0; eidx < el_count; eidx++) {
187 v2e[eidx].idx = eidx;
Lev Walkinda997b12017-08-04 01:38:41 -0700188 OUT("\t{ %s,\t%ld,\t\"%s\" }%s\n",
189 asn1p_itoa(v2e[eidx].value),
Lev Walkine0b56e02005-02-25 12:10:27 +0000190 (long)strlen(v2e[eidx].name), v2e[eidx].name,
191 (eidx + 1 < el_count) ? "," : "");
192 }
Lev Walkin59b176e2005-11-26 11:25:14 +0000193 if(map_extensions)
Lev Walkine0b56e02005-02-25 12:10:27 +0000194 OUT("\t/* This list is extensible */\n");
195 OUT("};\n");
196
Wim Lewisfb6344e2014-07-28 12:16:01 -0700197 OUT("static const unsigned int asn_MAP_%s_enum2value_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000198 MKID(expr), expr->_type_unique_index);
Lev Walkine0b56e02005-02-25 12:10:27 +0000199 qsort(v2e, el_count, sizeof(v2e[0]), compar_enumMap_byName);
200 for(eidx = 0; eidx < el_count; eidx++) {
Lev Walkinda997b12017-08-04 01:38:41 -0700201 OUT("\t%d%s\t/* %s(%s) */\n",
Lev Walkine0b56e02005-02-25 12:10:27 +0000202 v2e[eidx].idx,
203 (eidx + 1 < el_count) ? "," : "",
Lev Walkinda997b12017-08-04 01:38:41 -0700204 v2e[eidx].name, asn1p_itoa(v2e[eidx].value));
Lev Walkine0b56e02005-02-25 12:10:27 +0000205 }
Lev Walkin59b176e2005-11-26 11:25:14 +0000206 if(map_extensions)
Lev Walkine0b56e02005-02-25 12:10:27 +0000207 OUT("\t/* This list is extensible */\n");
208 OUT("};\n");
209
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800210 if(!(expr->_type_referenced)) OUT("static ");
211 OUT("const asn_INTEGER_specifics_t asn_SPC_%s_specs_%d = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000212 MKID(expr), expr->_type_unique_index);
Lev Walkine0b56e02005-02-25 12:10:27 +0000213 INDENT(+1);
Lev Walkin59b176e2005-11-26 11:25:14 +0000214 OUT("asn_MAP_%s_value2enum_%d,\t"
Lev Walkine0b56e02005-02-25 12:10:27 +0000215 "/* \"tag\" => N; sorted by tag */\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000216 MKID(expr),
Lev Walkin21d00002005-03-04 08:48:53 +0000217 expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +0000218 OUT("asn_MAP_%s_enum2value_%d,\t"
Lev Walkine0b56e02005-02-25 12:10:27 +0000219 "/* N => \"tag\"; sorted by N */\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000220 MKID(expr),
Lev Walkin21d00002005-03-04 08:48:53 +0000221 expr->_type_unique_index);
Lev Walkine0b56e02005-02-25 12:10:27 +0000222 OUT("%d,\t/* Number of elements in the maps */\n",
223 el_count);
Lev Walkin59b176e2005-11-26 11:25:14 +0000224 if(map_extensions) {
225 OUT("%d,\t/* Extensions before this member */\n",
226 map_extensions);
227 } else {
228 OUT("0,\t/* Enumeration is not extensible */\n");
229 }
Lev Walkine0b56e02005-02-25 12:10:27 +0000230 if(expr->expr_type == ASN_BASIC_ENUMERATED)
Lev Walkin8bb57a22007-12-03 13:41:36 +0000231 OUT("1,\t/* Strict enumeration */\n");
Lev Walkine0b56e02005-02-25 12:10:27 +0000232 else
Lev Walkin8bb57a22007-12-03 13:41:36 +0000233 OUT("0,\n");
234 OUT("0,\t/* Native long size */\n");
235 OUT("0\n");
236 INDENT(-1);
237 OUT("};\n");
238 }
239
240 if(expr->expr_type == ASN_BASIC_INTEGER
241 && asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN) {
242 REDIR(OT_STAT_DEFS);
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800243 if(!(expr->_type_referenced)) OUT("static ");
244 OUT("const asn_INTEGER_specifics_t asn_SPC_%s_specs_%d = {\n",
Lev Walkin8bb57a22007-12-03 13:41:36 +0000245 MKID(expr), expr->_type_unique_index);
246 INDENT(+1);
247 OUT("0,\t");
248 OUT("0,\t");
249 OUT("0,\t");
250 OUT("0,\t");
251 OUT("0,\n");
252 OUT("0,\t/* Native long size */\n");
253 OUT("1\t/* Unsigned representation */\n");
Lev Walkine0b56e02005-02-25 12:10:27 +0000254 INDENT(-1);
255 OUT("};\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000256 }
257
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800258 REDIR(saved_target);
259
Lev Walkinf15320b2004-06-03 03:38:44 +0000260 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
261}
262
263int
Lev Walkinb02a8832005-08-13 23:51:47 +0000264asn1c_lang_C_type_BIT_STRING(arg_t *arg) {
265 asn1p_expr_t *expr = arg->expr;
266 asn1p_expr_t *v;
267 int el_count = expr_elements_count(arg, expr);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800268 int saved_target = arg->target->target;
Lev Walkinb02a8832005-08-13 23:51:47 +0000269
270 if(el_count) {
Lev Walkin082cadc2005-08-14 02:18:27 +0000271 int eidx = 0;
Lev Walkinb02a8832005-08-13 23:51:47 +0000272 REDIR(OT_DEPS);
273 OUT("typedef enum ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000274 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkinb02a8832005-08-13 23:51:47 +0000275 OUT(" {\n");
276 TQ_FOR(v, &(expr->members), next) {
Lev Walkin082cadc2005-08-14 02:18:27 +0000277 if(v->expr_type != A1TC_UNIVERVAL) {
Lev Walkinb02a8832005-08-13 23:51:47 +0000278 OUT("/* Unexpected BIT STRING element: %s */\n",
279 v->Identifier);
Lev Walkin082cadc2005-08-14 02:18:27 +0000280 continue;
Lev Walkinb02a8832005-08-13 23:51:47 +0000281 }
Lev Walkin0f8d4a42006-08-26 03:29:15 +0000282 eidx++;
Lev Walkin082cadc2005-08-14 02:18:27 +0000283 OUT("\t");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000284 out_name_chain(arg, ONC_noflags);
Lev Walkina00d6b32006-03-21 03:40:38 +0000285 OUT("_%s", MKID(v));
Lev Walkinda997b12017-08-04 01:38:41 -0700286 OUT("\t= %s%s\n",
287 asn1p_itoa(v->value->value.v_integer),
Lev Walkin082cadc2005-08-14 02:18:27 +0000288 (eidx < el_count) ? "," : "");
Lev Walkinb02a8832005-08-13 23:51:47 +0000289 }
Lev Walkin171487e2006-03-21 07:25:18 +0000290 OUT("} e_");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000291 out_name_chain(arg, ONC_noflags);
Lev Walkin171487e2006-03-21 07:25:18 +0000292 OUT(";\n");
Lev Walkinb02a8832005-08-13 23:51:47 +0000293 assert(eidx == el_count);
294 }
295
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800296 REDIR(saved_target);
297
Lev Walkinb02a8832005-08-13 23:51:47 +0000298 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
299}
300
301int
Lev Walkinf15320b2004-06-03 03:38:44 +0000302asn1c_lang_C_type_SEQUENCE(arg_t *arg) {
303 asn1p_expr_t *expr = arg->expr;
304 asn1p_expr_t *v;
305 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800306 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000307
308 DEPENDENCIES;
309
310 if(arg->embed) {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800311
312 /* Use _anonymous_type field to indicate it's called from
313 * asn1c_lang_C_type_SEx_OF() */
314 if (expr->_anonymous_type) {
315 REDIR(OT_FWD_DEFS);
316 OUT("typedef ");
317 }
Lev Walkin21d00002005-03-04 08:48:53 +0000318 OUT("struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000319 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000320 OUT(" {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000321 } else {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800322 REDIR(OT_TYPE_DECLS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000323 OUT("typedef struct %s {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000324 MKID_safe(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +0000325 }
326
327 TQ_FOR(v, &(expr->members), next) {
Lev Walkinda9a3b82005-08-16 17:00:21 +0000328 if(v->expr_type == A1TC_EXTENSIBLE)
Lev Walkinf15320b2004-06-03 03:38:44 +0000329 if(comp_mode < 3) comp_mode++;
Lev Walkinda9a3b82005-08-16 17:00:21 +0000330 if(comp_mode == 1)
Lev Walkin59b176e2005-11-26 11:25:14 +0000331 v->marker.flags |= EM_OMITABLE | EM_INDIRECT;
332 try_inline_default(arg, v, 1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000333 EMBED(v);
334 }
335
336 PCTX_DEF;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800337
338 if (arg->embed && expr->_anonymous_type) {
339 OUT("} %s", (expr->marker.flags & EM_INDIRECT)?"*":"");
340 out_name_chain(arg, ONC_avoid_keywords);
341 OUT("%s;\n", arg->embed ? "" : "_t");
342
343 REDIR(saved_target);
344
345 OUT("%s", (expr->marker.flags & EM_INDIRECT)?"*":"");
346 out_name_chain(arg, ONC_avoid_keywords);
347 } else {
348 OUT("} %s%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000349 expr->_anonymous_type ? "" :
350 arg->embed
Lev Walkina00d6b32006-03-21 03:40:38 +0000351 ? MKID_safe(expr)
352 : MKID(expr),
Lev Walkin08079b02004-08-22 03:25:24 +0000353 arg->embed ? "" : "_t");
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800354 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000355
356 return asn1c_lang_C_type_SEQUENCE_def(arg);
357}
358
359static int
360asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
361 asn1p_expr_t *expr = arg->expr;
362 asn1p_expr_t *v;
363 int elements; /* Number of elements */
Lev Walkin33af5c32007-06-23 20:05:49 +0000364 int ext_start = -2;
365 int ext_stop = -2;
Lev Walkinfd171ef2004-06-06 07:20:17 +0000366 tag2el_t *tag2el = NULL;
367 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000368 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000369 int all_tags_count;
370 enum tvm_compat tv_mode;
Lev Walkin59b176e2005-11-26 11:25:14 +0000371 int roms_count; /* Root optional members */
372 int aoms_count; /* Additions optional members */
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800373 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000374
Lev Walkinfd171ef2004-06-06 07:20:17 +0000375 /*
376 * Fetch every inner tag from the tag to elements map.
377 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000378 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
Lev Walkinfd171ef2004-06-06 07:20:17 +0000379 if(tag2el) free(tag2el);
380 return -1;
381 }
382
Lev Walkin22b5ed42006-09-13 02:51:20 +0000383 GEN_INCLUDE_STD("constr_SEQUENCE");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000384 if(!arg->embed)
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800385 GEN_DECLARE("SEQUENCE", expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000386
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000387 REDIR(OT_STAT_DEFS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000388
389 /*
Lev Walkin59b176e2005-11-26 11:25:14 +0000390 * Print out the table according to which parsing is performed.
Lev Walkinf15320b2004-06-03 03:38:44 +0000391 */
Lev Walkina9cc46e2004-09-22 16:06:28 +0000392 if(expr_elements_count(arg, expr)) {
393 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Lev Walkinf15320b2004-06-03 03:38:44 +0000394
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800395 if(!(expr->_type_referenced)) OUT("static ");
396 OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000397 MKID(expr), expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000398
399 elements = 0;
Lev Walkin59b176e2005-11-26 11:25:14 +0000400 roms_count = 0;
401 aoms_count = 0;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000402 INDENTED(TQ_FOR(v, &(expr->members), next) {
403 if(v->expr_type == A1TC_EXTENSIBLE) {
404 if((++comp_mode) == 1)
405 ext_start = elements - 1;
406 else
407 ext_stop = elements - 1;
408 continue;
409 }
Lev Walkin59b176e2005-11-26 11:25:14 +0000410 if(v->marker.flags & EM_OMITABLE)
411 comp_mode == 1 ? ++aoms_count : ++roms_count;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000412 emit_member_table(arg, v);
Lev Walkinda9a3b82005-08-16 17:00:21 +0000413 elements++;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000414 });
415 OUT("};\n");
Lev Walkin59b176e2005-11-26 11:25:14 +0000416
Lev Walkin3c5d9412017-07-24 01:49:24 +0400417 if((roms_count + aoms_count) && (arg->flags & (A1C_GEN_OER|A1C_GEN_PER))) {
Lev Walkin59b176e2005-11-26 11:25:14 +0000418 int elm = 0;
419 int comma = 0;
420 comp_mode = 0;
Wim Lewisfb6344e2014-07-28 12:16:01 -0700421 OUT("static const int asn_MAP_%s_oms_%d[] = {",
Lev Walkina00d6b32006-03-21 03:40:38 +0000422 MKID(expr),
Lev Walkin59b176e2005-11-26 11:25:14 +0000423 expr->_type_unique_index);
424 TQ_FOR(v, &(expr->members), next) {
425 if(v->expr_type == A1TC_EXTENSIBLE) {
426 ++comp_mode;
427 continue;
428 }
429 if((v->marker.flags & EM_OMITABLE)
430 && comp_mode != 1) {
431 if(!comma) comma++;
432 else OUT(",");
433 OUT(" %d", elm);
434 }
435 ++elm;
436 }
437 elm = 0;
438 comp_mode = 0;
439 TQ_FOR(v, &(expr->members), next) {
440 if(v->expr_type == A1TC_EXTENSIBLE) {
441 ++comp_mode;
442 continue;
443 }
444 if((v->marker.flags & EM_OMITABLE)
445 && comp_mode == 1) {
446 if(!comma) comma++;
447 else OUT(",");
448 OUT(" %d", elm);
449 }
450 ++elm;
451 }
452 OUT(" };\n");
453 if(roms_count > 65536)
454 FATAL("Too many optional elements in %s "
455 "at line %d!",
456 arg->expr->Identifier,
457 arg->expr->_lineno);
458 } else {
459 roms_count = 0;
460 aoms_count = 0;
461 }
Lev Walkina9cc46e2004-09-22 16:06:28 +0000462 } else {
463 elements = 0;
Lev Walkin59b176e2005-11-26 11:25:14 +0000464 roms_count = 0;
465 aoms_count = 0;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000466 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000467
Lev Walkin27ea3802004-06-28 21:13:46 +0000468 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000469 * Print out asn_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +0000470 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000471 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000472
Lev Walkinfd171ef2004-06-06 07:20:17 +0000473 /*
474 * Tags to elements map.
475 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000476 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
Lev Walkinfd171ef2004-06-06 07:20:17 +0000477
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800478 if(!(expr->_type_referenced)) OUT("static ");
479 OUT("asn_SEQUENCE_specifics_t asn_SPC_%s_specs_%d = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000480 MKID(expr), expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +0000481 INDENT(+1);
482 OUT("sizeof(struct ");
483 out_name_chain(arg, ONC_avoid_keywords); OUT("),\n");
484 OUT("offsetof(struct ");
485 out_name_chain(arg, ONC_avoid_keywords); OUT(", _asn_ctx),\n");
Lev Walkin21d00002005-03-04 08:48:53 +0000486
Lev Walkin59b176e2005-11-26 11:25:14 +0000487 if(tag2el_count) {
488 OUT("asn_MAP_%s_tag2el_%d,\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000489 MKID(expr),
Lev Walkin59b176e2005-11-26 11:25:14 +0000490 expr->_type_unique_index);
491 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
492 } else {
493 OUT("0,\t/* No top level tags */\n");
494 OUT("0,\t/* No tags in the map */\n");
495 }
496 if(roms_count + aoms_count) {
497 OUT("asn_MAP_%s_oms_%d,\t/* Optional members */\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000498 MKID(expr), expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +0000499 OUT("%d, %d,\t/* Root/Additions */\n", roms_count, aoms_count);
500 } else {
501 OUT("0, 0, 0,\t/* Optional elements (not needed) */\n");
502 }
503 OUT("%d,\t/* Start extensions */\n",
Lev Walkin33af5c32007-06-23 20:05:49 +0000504 ext_start<0 ? -1 : ext_start);
Lev Walkin59b176e2005-11-26 11:25:14 +0000505 OUT("%d\t/* Stop extensions */\n",
Lev Walkin33af5c32007-06-23 20:05:49 +0000506 (ext_stop<ext_start)?elements+1:(ext_stop<0?-1:ext_stop));
Lev Walkin59b176e2005-11-26 11:25:14 +0000507 INDENT(-1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000508 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000509
510 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000511 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +0000512 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000513 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
Lev Walkin8de2ab22004-09-26 13:11:31 +0000514 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000515
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800516 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +0000517
Bi-Ruei, Chiu12021b52016-11-04 11:59:45 +0800518 if(tag2el) free(tag2el);
519
Lev Walkinf15320b2004-06-03 03:38:44 +0000520 return 0;
Lev Walkinb0b33412005-01-17 11:57:48 +0000521} /* _SEQUENCE_def() */
Lev Walkinf15320b2004-06-03 03:38:44 +0000522
523int
Lev Walkinf15320b2004-06-03 03:38:44 +0000524asn1c_lang_C_type_SET(arg_t *arg) {
525 asn1p_expr_t *expr = arg->expr;
526 asn1p_expr_t *v;
527 long mcount;
528 char *id;
529 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800530 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000531
532 DEPENDENCIES;
533
534 REDIR(OT_DEPS);
535
536 OUT("\n");
537 OUT("/*\n");
538 OUT(" * Method of determining the components presence\n");
539 OUT(" */\n");
540 mcount = 0;
Lev Walkin21d00002005-03-04 08:48:53 +0000541 OUT("typedef enum ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000542 out_name_chain(arg, ONC_noflags);
Lev Walkin21d00002005-03-04 08:48:53 +0000543 OUT("_PR {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000544 TQ_FOR(v, &(expr->members), next) {
545 if(v->expr_type == A1TC_EXTENSIBLE) continue;
546 INDENTED(
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000547 out_name_chain(arg, ONC_noflags);
Lev Walkin801fabc2005-01-28 12:18:50 +0000548 OUT("_PR_");
Lev Walkina00d6b32006-03-21 03:40:38 +0000549 id = MKID(v);
Lev Walkinf15320b2004-06-03 03:38:44 +0000550 OUT("%s,\t/* Member %s is present */\n",
551 id, id)
552 );
553 mcount++;
554 }
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000555 OUT("} "); out_name_chain(arg, ONC_noflags); OUT("_PR;\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000556
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800557 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +0000558
559 if(arg->embed) {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800560 if (expr->_anonymous_type) {
561 REDIR(OT_FWD_DEFS);
562 OUT("typedef ");
563 }
Lev Walkin21d00002005-03-04 08:48:53 +0000564 OUT("struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000565 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000566 OUT(" {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000567 } else {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800568 REDIR(OT_TYPE_DECLS);
Lev Walkin59b176e2005-11-26 11:25:14 +0000569 OUT("typedef struct %s {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000570 MKID_safe(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +0000571 }
572
573 TQ_FOR(v, &(expr->members), next) {
Lev Walkin59b176e2005-11-26 11:25:14 +0000574 if(v->expr_type == A1TC_EXTENSIBLE)
Lev Walkinf15320b2004-06-03 03:38:44 +0000575 if(comp_mode < 3) comp_mode++;
Lev Walkinda9a3b82005-08-16 17:00:21 +0000576 if(comp_mode == 1)
Lev Walkin59b176e2005-11-26 11:25:14 +0000577 v->marker.flags |= EM_OMITABLE | EM_INDIRECT;
578 try_inline_default(arg, v, 1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000579 EMBED(v);
580 }
581
582 INDENTED(
Lev Walkina00d6b32006-03-21 03:40:38 +0000583 id = MKID(expr);
Lev Walkinf15320b2004-06-03 03:38:44 +0000584 OUT("\n");
585 OUT("/* Presence bitmask: ASN_SET_ISPRESENT(p%s, %s_PR_x) */\n",
586 id, id);
587 OUT("unsigned int _presence_map\n");
588 OUT("\t[((%ld+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))];\n", mcount);
589 );
590
591 PCTX_DEF;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800592
593 if (arg->embed && expr->_anonymous_type) {
594 OUT("} %s", (expr->marker.flags & EM_INDIRECT)?"*":"");
595 out_name_chain(arg, ONC_avoid_keywords);
596 OUT("%s;\n", arg->embed ? "" : "_t");
597
598 REDIR(saved_target);
599
600 OUT("%s", (expr->marker.flags & EM_INDIRECT)?"*":"");
601 out_name_chain(arg, ONC_avoid_keywords);
602 } else {
603 OUT("} %s%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
604 expr->_anonymous_type ? "" : MKID_safe(expr),
605 arg->embed ? "" : "_t");
606 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000607
608 return asn1c_lang_C_type_SET_def(arg);
609}
610
Lev Walkinf15320b2004-06-03 03:38:44 +0000611static int
612asn1c_lang_C_type_SET_def(arg_t *arg) {
613 asn1p_expr_t *expr = arg->expr;
614 asn1p_expr_t *v;
615 int elements;
Lev Walkinf15320b2004-06-03 03:38:44 +0000616 tag2el_t *tag2el = NULL;
617 int tag2el_count = 0;
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000618 tag2el_t *tag2el_cxer = NULL;
619 int tag2el_cxer_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000620 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000621 int all_tags_count;
622 enum tvm_compat tv_mode;
Lev Walkinf15320b2004-06-03 03:38:44 +0000623 char *p;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800624 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000625
626 /*
627 * Fetch every inner tag from the tag to elements map.
628 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000629 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000630 if(tag2el) free(tag2el);
631 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000632 }
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000633 if(_fill_tag2el_map(arg, &tag2el_cxer, &tag2el_cxer_count, -1, FTE_CANONICAL_XER)) {
634 if(tag2el) free(tag2el);
635 if(tag2el_cxer) free(tag2el_cxer);
636 return -1;
637 }
638 if(tag2el_cxer_count == tag2el_count
639 && memcmp(tag2el, tag2el_cxer, tag2el_count) == 0) {
640 free(tag2el_cxer);
641 tag2el_cxer = 0;
642 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000643
Lev Walkin22b5ed42006-09-13 02:51:20 +0000644 GEN_INCLUDE_STD("constr_SET");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000645 if(!arg->embed)
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800646 GEN_DECLARE("SET", expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000647
648 REDIR(OT_STAT_DEFS);
649
Lev Walkinf15320b2004-06-03 03:38:44 +0000650 /*
Lev Walkin59b176e2005-11-26 11:25:14 +0000651 * Print out the table according to which parsing is performed.
Lev Walkinf15320b2004-06-03 03:38:44 +0000652 */
Lev Walkina9cc46e2004-09-22 16:06:28 +0000653 if(expr_elements_count(arg, expr)) {
654 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Lev Walkinf15320b2004-06-03 03:38:44 +0000655
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800656 if(!(expr->_type_referenced)) OUT("static ");
657 OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000658 MKID(expr), expr->_type_unique_index);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800659
Lev Walkina9cc46e2004-09-22 16:06:28 +0000660 elements = 0;
661 INDENTED(TQ_FOR(v, &(expr->members), next) {
662 if(v->expr_type == A1TC_EXTENSIBLE) {
663 if(comp_mode < 3) comp_mode++;
664 } else {
Lev Walkina9cc46e2004-09-22 16:06:28 +0000665 emit_member_table(arg, v);
Lev Walkinda9a3b82005-08-16 17:00:21 +0000666 elements++;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000667 }
668 });
669 OUT("};\n");
670 } else {
671 elements = 0;
672 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000673
Lev Walkin27ea3802004-06-28 21:13:46 +0000674 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000675 * Print out asn_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +0000676 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000677 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000678
679 /*
680 * Tags to elements map.
681 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000682 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
683 if(tag2el_cxer)
684 emit_tag2member_map(arg, tag2el_cxer, tag2el_cxer_count, "_cxer");
Lev Walkinf15320b2004-06-03 03:38:44 +0000685
686 /*
687 * Emit a map of mandatory elements.
688 */
Wim Lewisfb6344e2014-07-28 12:16:01 -0700689 OUT("static const uint8_t asn_MAP_%s_mmap_%d",
Lev Walkina00d6b32006-03-21 03:40:38 +0000690 MKID(expr), expr->_type_unique_index);
691 p = MKID_safe(expr);
Lev Walkinf15320b2004-06-03 03:38:44 +0000692 OUT("[(%d + (8 * sizeof(unsigned int)) - 1) / 8]", elements);
Lev Walkin21d00002005-03-04 08:48:53 +0000693 OUT(" = {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000694 INDENTED(
695 if(elements) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000696 int el = 0;
697 TQ_FOR(v, &(expr->members), next) {
698 if(v->expr_type == A1TC_EXTENSIBLE) continue;
Lev Walkinac760bf2005-10-05 08:59:03 +0000699 if(el) {
700 if((el % 8) == 0)
701 OUT(",\n");
702 else
703 OUT(" | ");
Lev Walkinf15320b2004-06-03 03:38:44 +0000704 }
Lev Walkincc93b0f2004-09-10 09:18:20 +0000705 OUT("(%d << %d)",
Lev Walkinb85a8132005-08-18 13:38:19 +0000706 (v->marker.flags & EM_OMITABLE) != EM_OMITABLE,
Lev Walkincc93b0f2004-09-10 09:18:20 +0000707 7 - (el % 8));
Lev Walkinf15320b2004-06-03 03:38:44 +0000708 el++;
709 }
710 } else {
711 OUT("0");
712 }
713 );
714 OUT("\n");
715 OUT("};\n");
716
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800717 if(!(expr->_type_referenced)) OUT("static \n");
718 OUT("asn_SET_specifics_t asn_SPC_%s_specs_%d = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000719 MKID(expr), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +0000720 INDENTED(
Lev Walkin21d00002005-03-04 08:48:53 +0000721 OUT("sizeof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000722 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000723 OUT("),\n");
724 OUT("offsetof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000725 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000726 OUT(", _asn_ctx),\n");
727 OUT("offsetof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000728 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000729 OUT(", _presence_map),\n");
Lev Walkina00d6b32006-03-21 03:40:38 +0000730 p = MKID(expr);
Lev Walkin59b176e2005-11-26 11:25:14 +0000731 OUT("asn_MAP_%s_tag2el_%d,\n", p, expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +0000732 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000733 if(tag2el_cxer)
Lev Walkin59b176e2005-11-26 11:25:14 +0000734 OUT("asn_MAP_%s_tag2el_cxer_%d,\n",
Lev Walkin21d00002005-03-04 08:48:53 +0000735 p, expr->_type_unique_index);
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000736 else
Lev Walkin59b176e2005-11-26 11:25:14 +0000737 OUT("asn_MAP_%s_tag2el_%d,\t/* Same as above */\n",
Lev Walkin21d00002005-03-04 08:48:53 +0000738 p, expr->_type_unique_index);
739 OUT("%d,\t/* Count of tags in the CXER map */\n",
740 tag2el_cxer_count);
Lev Walkin35631482004-07-01 00:52:50 +0000741 OUT("%d,\t/* Whether extensible */\n",
Lev Walkin59b176e2005-11-26 11:25:14 +0000742 compute_extensions_start(expr) == -1 ? 0 : 1);
Lev Walkin46ef3f32017-07-06 08:47:53 -0700743 OUT("(const unsigned int *)asn_MAP_%s_mmap_%d\t/* Mandatory elements map */\n",
Lev Walkin21d00002005-03-04 08:48:53 +0000744 p, expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +0000745 );
746 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000747
748 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000749 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +0000750 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000751 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
Lev Walkin8de2ab22004-09-26 13:11:31 +0000752 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000753
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800754 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +0000755
Bi-Ruei, Chiu12021b52016-11-04 11:59:45 +0800756 if (tag2el) free(tag2el);
757 if (tag2el_cxer) free(tag2el_cxer);
758
Lev Walkinf15320b2004-06-03 03:38:44 +0000759 return 0;
Lev Walkinb0b33412005-01-17 11:57:48 +0000760} /* _SET_def() */
Lev Walkinf15320b2004-06-03 03:38:44 +0000761
762int
Lev Walkin08079b02004-08-22 03:25:24 +0000763asn1c_lang_C_type_SEx_OF(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000764 asn1p_expr_t *expr = arg->expr;
Lev Walkinc8285712005-03-04 22:18:20 +0000765 asn1p_expr_t *memb = TQ_FIRST(&expr->members);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800766 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000767
768 DEPENDENCIES;
769
770 if(arg->embed) {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800771 if (expr->_anonymous_type) {
772 REDIR(OT_FWD_DEFS);
773 OUT("typedef ");
774 }
Lev Walkin21d00002005-03-04 08:48:53 +0000775 OUT("struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000776 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000777 OUT(" {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000778 } else {
Lev Walkina00d6b32006-03-21 03:40:38 +0000779 OUT("typedef struct %s {\n", MKID_safe(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +0000780 }
781
Lev Walkin08079b02004-08-22 03:25:24 +0000782 INDENT(+1);
783 OUT("A_%s_OF(",
784 (arg->expr->expr_type == ASN_CONSTR_SET_OF)
785 ? "SET" : "SEQUENCE");
Lev Walkinda9a3b82005-08-16 17:00:21 +0000786
787 /*
788 * README README
789 * The implementation of the A_SET_OF() macro is already indirect.
790 */
791 memb->marker.flags |= EM_INDIRECT;
792
Lev Walkine0b56e02005-02-25 12:10:27 +0000793 if(memb->expr_type & ASN_CONSTR_MASK
794 || ((memb->expr_type == ASN_BASIC_ENUMERATED
Lev Walkin8ecf9db2005-03-03 21:28:12 +0000795 || (0 /* -- prohibited by X.693:8.3.4 */
796 && memb->expr_type == ASN_BASIC_INTEGER))
797 && expr_elements_count(arg, memb))) {
Lev Walkin08079b02004-08-22 03:25:24 +0000798 arg_t tmp;
799 asn1p_expr_t tmp_memb;
800 arg->embed++;
801 tmp = *arg;
802 tmp.expr = &tmp_memb;
803 tmp_memb = *memb;
Lev Walkinda9a3b82005-08-16 17:00:21 +0000804 tmp_memb.marker.flags &= ~EM_INDIRECT;
Lev Walkin08079b02004-08-22 03:25:24 +0000805 tmp_memb._anonymous_type = 1;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000806 if(tmp_memb.Identifier == 0) {
Lev Walkin21d00002005-03-04 08:48:53 +0000807 tmp_memb.Identifier = "Member";
808 if(0)
Lev Walkina9cc46e2004-09-22 16:06:28 +0000809 tmp_memb.Identifier = strdup(
810 asn1c_make_identifier(0,
Lev Walkina00d6b32006-03-21 03:40:38 +0000811 expr, "Member", 0));
Lev Walkina9cc46e2004-09-22 16:06:28 +0000812 assert(tmp_memb.Identifier);
813 }
Lev Walkin08079b02004-08-22 03:25:24 +0000814 tmp.default_cb(&tmp);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000815 if(tmp_memb.Identifier != memb->Identifier)
Lev Walkin21d00002005-03-04 08:48:53 +0000816 if(0) free(tmp_memb.Identifier);
Lev Walkin08079b02004-08-22 03:25:24 +0000817 arg->embed--;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800818 assert(arg->target->target == OT_TYPE_DECLS ||
819 arg->target->target == OT_FWD_DEFS);
Lev Walkin08079b02004-08-22 03:25:24 +0000820 } else {
Lev Walkinfe7f6ec2005-03-04 22:38:22 +0000821 OUT("%s", asn1c_type_name(arg, memb,
822 (memb->marker.flags & EM_UNRECURSE)
823 ? TNF_RSAFE : TNF_CTYPE));
Lev Walkinf15320b2004-06-03 03:38:44 +0000824 }
Lev Walkinda9a3b82005-08-16 17:00:21 +0000825 /* README README (above) */
826 if(0 && (memb->marker.flags & EM_INDIRECT))
827 OUT(" *");
Lev Walkin08079b02004-08-22 03:25:24 +0000828 OUT(") list;\n");
829 INDENT(-1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000830
831 PCTX_DEF;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800832
833 if (arg->embed && expr->_anonymous_type) {
834 OUT("} %s", (expr->marker.flags & EM_INDIRECT)?"*":"");
835 out_name_chain(arg, ONC_avoid_keywords);
836 OUT("%s;\n", arg->embed ? "" : "_t");
837
838 REDIR(saved_target);
839
840 OUT("%s", (expr->marker.flags & EM_INDIRECT)?"*":"");
841 out_name_chain(arg, ONC_avoid_keywords);
842 } else {
843 OUT("} %s%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
844 expr->_anonymous_type ? "" : MKID_safe(expr),
845 arg->embed ? "" : "_t");
846 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000847
848 /*
Lev Walkin08079b02004-08-22 03:25:24 +0000849 * SET OF/SEQUENCE OF definition
Lev Walkinf15320b2004-06-03 03:38:44 +0000850 */
Lev Walkin08079b02004-08-22 03:25:24 +0000851 return asn1c_lang_C_type_SEx_OF_def(arg,
852 (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF));
Lev Walkinf15320b2004-06-03 03:38:44 +0000853}
854
855static int
856asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
857 asn1p_expr_t *expr = arg->expr;
858 asn1p_expr_t *v;
Lev Walkin64399722004-08-11 07:17:22 +0000859 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000860 int all_tags_count;
861 enum tvm_compat tv_mode;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800862 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000863
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000864 /*
Lev Walkin59b176e2005-11-26 11:25:14 +0000865 * Print out the table according to which parsing is performed.
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000866 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000867 if(seq_of) {
Lev Walkin22b5ed42006-09-13 02:51:20 +0000868 GEN_INCLUDE_STD("constr_SEQUENCE_OF");
Lev Walkinf15320b2004-06-03 03:38:44 +0000869 } else {
Lev Walkin22b5ed42006-09-13 02:51:20 +0000870 GEN_INCLUDE_STD("constr_SET_OF");
Lev Walkinf15320b2004-06-03 03:38:44 +0000871 }
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000872 if(!arg->embed)
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800873 GEN_DECLARE("SET_OF", expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000874
875 REDIR(OT_STAT_DEFS);
876
877 /*
Lev Walkin59b176e2005-11-26 11:25:14 +0000878 * Print out the table according to which parsing is performed.
Lev Walkinf15320b2004-06-03 03:38:44 +0000879 */
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800880 if(!(expr->_type_referenced)) OUT("static ");
881 OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000882 MKID(expr), expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000883 INDENT(+1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000884 v = TQ_FIRST(&(expr->members));
Lev Walkina9cc46e2004-09-22 16:06:28 +0000885 if(!v->Identifier) {
Lev Walkin152a91e2005-02-14 20:41:29 +0000886 v->Identifier = strdup("Member");
Lev Walkina9cc46e2004-09-22 16:06:28 +0000887 assert(v->Identifier);
888 }
889 v->_anonymous_type = 1;
890 arg->embed++;
Lev Walkin59964be2004-08-25 02:03:12 +0000891 emit_member_table(arg, v);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000892 arg->embed--;
Bi-Ruei, Chiu9b780832016-11-07 22:19:10 +0800893 free(v->Identifier);
894 v->Identifier = (char *)NULL;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000895 INDENT(-1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000896 OUT("};\n");
897
Lev Walkin27ea3802004-06-28 21:13:46 +0000898 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000899 * Print out asn_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +0000900 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000901 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000902
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800903 if(!(expr->_type_referenced)) OUT("static ");
904 OUT("asn_SET_OF_specifics_t asn_SPC_%s_specs_%d = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000905 MKID(expr), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +0000906 INDENTED(
Lev Walkin21d00002005-03-04 08:48:53 +0000907 OUT("sizeof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000908 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000909 OUT("),\n");
910 OUT("offsetof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000911 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000912 OUT(", _asn_ctx),\n");
Lev Walkind1bfea62005-11-08 03:06:16 +0000913 {
914 int as_xvl = expr_as_xmlvaluelist(arg, v);
915 OUT("%d,\t/* XER encoding is %s */\n",
916 as_xvl,
917 as_xvl ? "XMLValueList" : "XMLDelimitedItemList");
918 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000919 );
920 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000921
922 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000923 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +0000924 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000925 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, 1,
Lev Walkin8de2ab22004-09-26 13:11:31 +0000926 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000927
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800928 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +0000929
930 return 0;
Lev Walkinb0b33412005-01-17 11:57:48 +0000931} /* _SEx_OF_def() */
Lev Walkinf15320b2004-06-03 03:38:44 +0000932
933int
934asn1c_lang_C_type_CHOICE(arg_t *arg) {
935 asn1p_expr_t *expr = arg->expr;
936 asn1p_expr_t *v;
Lev Walkin08079b02004-08-22 03:25:24 +0000937 char *id;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800938 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000939
940 DEPENDENCIES;
941
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000942 REDIR(OT_DEPS);
943
Lev Walkin21d00002005-03-04 08:48:53 +0000944 OUT("typedef enum ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000945 out_name_chain(arg, ONC_noflags);
Lev Walkin21d00002005-03-04 08:48:53 +0000946 OUT("_PR {\n");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000947 INDENTED(
Lev Walkin11380fb2006-08-18 01:38:40 +0000948 int skipComma = 1;
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000949 out_name_chain(arg, ONC_noflags);
Lev Walkin801fabc2005-01-28 12:18:50 +0000950 OUT("_PR_NOTHING,\t/* No components present */\n");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000951 TQ_FOR(v, &(expr->members), next) {
Lev Walkin11380fb2006-08-18 01:38:40 +0000952 if(skipComma) skipComma = 0;
johvik792216e2017-04-11 10:42:21 +0200953 else if (v->expr_type == A1TC_EXTENSIBLE && !TQ_NEXT(v, next)) OUT("\n");
Lev Walkin1dc85292006-08-18 01:32:26 +0000954 else OUT(",\n");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000955 if(v->expr_type == A1TC_EXTENSIBLE) {
956 OUT("/* Extensions may appear below */\n");
Lev Walkin11380fb2006-08-18 01:38:40 +0000957 skipComma = 1;
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000958 continue;
959 }
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000960 out_name_chain(arg, ONC_noflags);
Lev Walkina00d6b32006-03-21 03:40:38 +0000961 id = MKID(v);
Lev Walkin1dc85292006-08-18 01:32:26 +0000962 OUT("_PR_%s", id);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000963 }
Lev Walkin1dc85292006-08-18 01:32:26 +0000964 OUT("\n");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000965 );
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000966 OUT("} "); out_name_chain(arg, ONC_noflags); OUT("_PR;\n");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000967
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800968 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +0000969
970 if(arg->embed) {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800971 if (expr->_anonymous_type) {
972 REDIR(OT_FWD_DEFS);
973 OUT("typedef ");
974 }
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000975 OUT("struct "); out_name_chain(arg, ONC_avoid_keywords); OUT(" {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000976 } else {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800977 REDIR(OT_TYPE_DECLS);
Lev Walkina00d6b32006-03-21 03:40:38 +0000978 OUT("typedef struct %s {\n", MKID_safe(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +0000979 }
980
981 INDENTED(
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000982 out_name_chain(arg, ONC_noflags);
Lev Walkin801fabc2005-01-28 12:18:50 +0000983 OUT("_PR present;\n");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000984 OUT("union ");
985 if(UNNAMED_UNIONS == 0) {
986 out_name_chain(arg, ONC_force_compound_name);
987 OUT("_u ");
988 }
989 OUT("{\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000990 TQ_FOR(v, &(expr->members), next) {
991 EMBED(v);
992 }
993 if(UNNAMED_UNIONS) OUT("};\n");
994 else OUT("} choice;\n");
995 );
996
997 PCTX_DEF;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800998
999 if (arg->embed && expr->_anonymous_type) {
1000 OUT("} %s", (expr->marker.flags & EM_INDIRECT)?"*":"");
1001 out_name_chain(arg, ONC_avoid_keywords);
1002 OUT("%s;\n", arg->embed ? "" : "_t");
1003
1004 REDIR(saved_target);
1005
1006 OUT("%s", (expr->marker.flags & EM_INDIRECT)?"*":"");
1007 out_name_chain(arg, ONC_avoid_keywords);
1008 } else {
1009 OUT("} %s%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
1010 expr->_anonymous_type ? "" :
1011 arg->embed
1012 ? MKID_safe(expr)
1013 : MKID(expr),
1014 arg->embed ? "" : "_t");
1015 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001016
1017 return asn1c_lang_C_type_CHOICE_def(arg);
1018}
1019
1020static int
1021asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
1022 asn1p_expr_t *expr = arg->expr;
1023 asn1p_expr_t *v;
1024 int elements; /* Number of elements */
Lev Walkinf15320b2004-06-03 03:38:44 +00001025 tag2el_t *tag2el = NULL;
1026 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +00001027 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +00001028 int all_tags_count;
1029 enum tvm_compat tv_mode;
Lev Walkin59b176e2005-11-26 11:25:14 +00001030 int *cmap = 0;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001031 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +00001032
1033 /*
1034 * Fetch every inner tag from the tag to elements map.
1035 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001036 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001037 if(tag2el) free(tag2el);
1038 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +00001039 }
1040
Lev Walkin22b5ed42006-09-13 02:51:20 +00001041 GEN_INCLUDE_STD("constr_CHOICE");
Lev Walkin3dcaafa2004-08-11 05:21:32 +00001042 if(!arg->embed)
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001043 GEN_DECLARE("CHOICE", expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +00001044
Lev Walkin3dcaafa2004-08-11 05:21:32 +00001045 REDIR(OT_STAT_DEFS);
Lev Walkinf15320b2004-06-03 03:38:44 +00001046
1047 /*
Lev Walkin59b176e2005-11-26 11:25:14 +00001048 * Print out the table according to which parsing is performed.
Lev Walkinf15320b2004-06-03 03:38:44 +00001049 */
Lev Walkina9cc46e2004-09-22 16:06:28 +00001050 if(expr_elements_count(arg, expr)) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001051
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001052 if(!(expr->_type_referenced)) OUT("static ");
1053 OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00001054 MKID(expr), expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +00001055
1056 elements = 0;
1057 INDENTED(TQ_FOR(v, &(expr->members), next) {
Lev Walkin659c63b2005-01-17 11:40:49 +00001058 if(v->expr_type == A1TC_EXTENSIBLE)
1059 continue;
Lev Walkin659c63b2005-01-17 11:40:49 +00001060 emit_member_table(arg, v);
Lev Walkinda9a3b82005-08-16 17:00:21 +00001061 elements++;
Lev Walkina9cc46e2004-09-22 16:06:28 +00001062 });
1063 OUT("};\n");
1064 } else {
1065 elements = 0;
1066 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001067
Lev Walkin59b176e2005-11-26 11:25:14 +00001068 /* Create a canonical elements map */
1069 if(elements && (arg->flags & A1C_GEN_PER)) {
1070 int i;
1071 cmap = compute_canonical_members_order(arg, elements);
1072 if(cmap) {
Wim Lewisfb6344e2014-07-28 12:16:01 -07001073 OUT("static const int asn_MAP_%s_cmap_%d[] = {",
Lev Walkina00d6b32006-03-21 03:40:38 +00001074 MKID(expr),
Lev Walkin59b176e2005-11-26 11:25:14 +00001075 expr->_type_unique_index);
1076 for(i = 0; i < elements; i++) {
1077 if(i) OUT(",");
1078 OUT(" %d", cmap[i]);
1079 }
1080 OUT(" };\n");
1081 free(cmap);
1082 }
1083 }
Lev Walkin64399722004-08-11 07:17:22 +00001084
Lev Walkinf15320b2004-06-03 03:38:44 +00001085 if(arg->embed) {
1086 /*
1087 * Our parent structure has already taken this into account.
1088 */
Lev Walkin188ed2c2004-09-13 08:31:01 +00001089 tv_mode = _TVM_SAME;
1090 tags_count = all_tags_count = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +00001091 } else {
Lev Walkin188ed2c2004-09-13 08:31:01 +00001092 tv_mode = emit_tags_vectors(arg, expr,
1093 &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +00001094 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001095
1096 /*
1097 * Tags to elements map.
1098 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001099 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +00001100
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001101 if(!(expr->_type_referenced)) OUT("static ");
1102 OUT("asn_CHOICE_specifics_t asn_SPC_%s_specs_%d = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00001103 MKID(expr), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +00001104 INDENTED(
Lev Walkin21d00002005-03-04 08:48:53 +00001105 OUT("sizeof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +00001106 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +00001107 OUT("),\n");
1108 OUT("offsetof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +00001109 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +00001110 OUT(", _asn_ctx),\n");
1111 OUT("offsetof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +00001112 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +00001113 OUT(", present),\n");
1114 OUT("sizeof(((struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +00001115 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +00001116 OUT(" *)0)->present),\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00001117 OUT("asn_MAP_%s_tag2el_%d,\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00001118 MKID(expr), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +00001119 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
Lev Walkin59b176e2005-11-26 11:25:14 +00001120 if(C99_MODE) OUT(".canonical_order = ");
1121 if(cmap) OUT("asn_MAP_%s_cmap_%d,\t/* Canonically sorted */\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00001122 MKID(expr), expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00001123 else OUT("0,\n");
1124 if(C99_MODE) OUT(".ext_start = ");
1125 OUT("%d\t/* Extensions start */\n",
1126 compute_extensions_start(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +00001127 );
1128 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +00001129
1130 /*
Lev Walkin05363a72004-09-29 13:16:40 +00001131 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +00001132 */
Lev Walkin188ed2c2004-09-13 08:31:01 +00001133 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
Lev Walkin8de2ab22004-09-26 13:11:31 +00001134 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +00001135
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001136 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +00001137
Bi-Ruei, Chiu12021b52016-11-04 11:59:45 +08001138 if (tag2el) free(tag2el);
1139
Lev Walkinf15320b2004-06-03 03:38:44 +00001140 return 0;
Lev Walkinb0b33412005-01-17 11:57:48 +00001141} /* _CHOICE_def() */
Lev Walkinf15320b2004-06-03 03:38:44 +00001142
1143int
1144asn1c_lang_C_type_REFERENCE(arg_t *arg) {
1145 asn1p_ref_t *ref;
1146
1147 ref = arg->expr->reference;
1148 if(ref->components[ref->comp_count-1].name[0] == '&') {
Lev Walkinf15320b2004-06-03 03:38:44 +00001149 asn1p_expr_t *extract;
1150 arg_t tmp;
1151 int ret;
1152
Lev Walkina9cc46e2004-09-22 16:06:28 +00001153 extract = asn1f_class_access_ex(arg->asn, arg->expr->module,
Lev Walkina00d6b32006-03-21 03:40:38 +00001154 arg->expr, arg->expr->rhs_pspecs, ref);
Lev Walkinf15320b2004-06-03 03:38:44 +00001155 if(extract == NULL)
1156 return -1;
1157
Lev Walkin08079b02004-08-22 03:25:24 +00001158 extract = asn1p_expr_clone(extract, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +00001159 if(extract) {
Lev Walkind8b83642016-03-14 02:00:27 -07001160 free(extract->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +00001161 extract->Identifier = strdup(arg->expr->Identifier);
1162 if(extract->Identifier == NULL) {
1163 asn1p_expr_free(extract);
1164 return -1;
1165 }
1166 } else {
1167 return -1;
1168 }
1169
1170 tmp = *arg;
1171 tmp.asn = arg->asn;
Lev Walkinf15320b2004-06-03 03:38:44 +00001172 tmp.expr = extract;
1173
1174 ret = arg->default_cb(&tmp);
1175
1176 asn1p_expr_free(extract);
1177
1178 return ret;
1179 }
1180
1181
1182 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
1183}
1184
1185int
1186asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
1187 asn1p_expr_t *expr = arg->expr;
Lev Walkin64399722004-08-11 07:17:22 +00001188 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +00001189 int all_tags_count;
1190 enum tvm_compat tv_mode;
Lev Walkine0b56e02005-02-25 12:10:27 +00001191 enum etd_spec etd_spec;
Lev Walkinf15320b2004-06-03 03:38:44 +00001192 char *p;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001193 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +00001194
1195 if(arg->embed) {
Lev Walkin05363a72004-09-29 13:16:40 +00001196 enum tnfmt tnfmt = TNF_CTYPE;
1197
1198 /*
1199 * If this is an optional compound type,
1200 * refer it using "struct X" convention,
1201 * as it may recursively include the current structure.
1202 */
Lev Walkinc8285712005-03-04 22:18:20 +00001203 if(expr->marker.flags & (EM_INDIRECT | EM_UNRECURSE)) {
Lev Walkinb85a8132005-08-18 13:38:19 +00001204 if(terminal_structable(arg, expr)) {
Lev Walkinc8285712005-03-04 22:18:20 +00001205 tnfmt = TNF_RSAFE;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001206 if(saved_target != OT_FWD_DECLS) {
1207 REDIR(OT_FWD_DECLS);
1208 OUT("%s;\n",
1209 asn1c_type_name(arg, arg->expr, tnfmt));
1210 }
1211 REDIR(saved_target);
Lev Walkin05363a72004-09-29 13:16:40 +00001212 }
1213 }
1214
Lev Walkinf15320b2004-06-03 03:38:44 +00001215
Lev Walkinc8285712005-03-04 22:18:20 +00001216 OUT("%s", asn1c_type_name(arg, arg->expr, tnfmt));
Lev Walkine0b56e02005-02-25 12:10:27 +00001217 if(!expr->_anonymous_type) {
Lev Walkinc8285712005-03-04 22:18:20 +00001218 OUT("%s", (expr->marker.flags&EM_INDIRECT)?"\t*":"\t ");
Lev Walkina00d6b32006-03-21 03:40:38 +00001219 OUT("%s", MKID_safe(expr));
Lev Walkin59b176e2005-11-26 11:25:14 +00001220 if((expr->marker.flags & (EM_DEFAULT & ~EM_INDIRECT))
1221 == (EM_DEFAULT & ~EM_INDIRECT))
Lev Walkine0b56e02005-02-25 12:10:27 +00001222 OUT("\t/* DEFAULT %s */",
1223 asn1f_printable_value(
1224 expr->marker.default_value));
Lev Walkin59b176e2005-11-26 11:25:14 +00001225 else if((expr->marker.flags & EM_OPTIONAL)
1226 == EM_OPTIONAL)
Lev Walkine0b56e02005-02-25 12:10:27 +00001227 OUT("\t/* OPTIONAL */");
1228 }
1229
1230 } else {
1231 GEN_INCLUDE(asn1c_type_name(arg, expr, TNF_INCLUDE));
Lev Walkin59004fa2004-08-20 13:37:01 +00001232
1233 REDIR(OT_TYPE_DECLS);
Lev Walkine0b56e02005-02-25 12:10:27 +00001234
1235 OUT("typedef %s\t",
Lev Walkinc8285712005-03-04 22:18:20 +00001236 asn1c_type_name(arg, arg->expr, TNF_CTYPE));
Lev Walkine0b56e02005-02-25 12:10:27 +00001237 OUT("%s%s_t",
Lev Walkinc8285712005-03-04 22:18:20 +00001238 (expr->marker.flags & EM_INDIRECT)?"*":" ",
Lev Walkina00d6b32006-03-21 03:40:38 +00001239 MKID(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +00001240 }
1241
Lev Walkine0b56e02005-02-25 12:10:27 +00001242 if((expr->expr_type == ASN_BASIC_ENUMERATED)
Lev Walkin8ecf9db2005-03-03 21:28:12 +00001243 || (0 /* -- prohibited by X.693:8.3.4 */
1244 && expr->expr_type == ASN_BASIC_INTEGER
Lev Walkin8bb57a22007-12-03 13:41:36 +00001245 && expr_elements_count(arg, expr))
1246 || (expr->expr_type == ASN_BASIC_INTEGER
1247 && asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN)
1248 )
Lev Walkine0b56e02005-02-25 12:10:27 +00001249 etd_spec = ETD_HAS_SPECIFICS;
1250 else
1251 etd_spec = ETD_NO_SPECIFICS;
Lev Walkinf15320b2004-06-03 03:38:44 +00001252
Lev Walkin8de2ab22004-09-26 13:11:31 +00001253 /*
1254 * If this type just blindly refers the other type, alias it.
1255 * Type1 ::= Type2
1256 */
Lev Walkine0b56e02005-02-25 12:10:27 +00001257 if(arg->embed && etd_spec == ETD_NO_SPECIFICS) {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001258 REDIR(saved_target);
Lev Walkine0b56e02005-02-25 12:10:27 +00001259 return 0;
1260 }
Lev Walkin8de2ab22004-09-26 13:11:31 +00001261 if((!expr->constraints || (arg->flags & A1C_NO_CONSTRAINTS))
Lev Walkine0b56e02005-02-25 12:10:27 +00001262 && (arg->embed || expr->tag.tag_class == TC_NOCLASS)
Lev Walkin6938d042005-03-04 23:23:50 +00001263 && etd_spec == ETD_NO_SPECIFICS
1264 && 0 /* This shortcut is incompatible with XER */
1265 ) {
Lev Walkin8de2ab22004-09-26 13:11:31 +00001266 char *type_name;
1267 REDIR(OT_FUNC_DECLS);
1268 type_name = asn1c_type_name(arg, expr, TNF_SAFE);
1269 OUT("/* This type is equivalent to %s */\n", type_name);
Lev Walkin8de2ab22004-09-26 13:11:31 +00001270 if(HIDE_INNER_DEFS) OUT("/* ");
Lev Walkina00d6b32006-03-21 03:40:38 +00001271 OUT("#define\tasn_DEF_%s\t", MKID(expr));
Lev Walkin8de2ab22004-09-26 13:11:31 +00001272 type_name = asn1c_type_name(arg, expr, TNF_SAFE);
Lev Walkine0b56e02005-02-25 12:10:27 +00001273 OUT("asn_DEF_%s", type_name);
Lev Walkin8de2ab22004-09-26 13:11:31 +00001274 if(HIDE_INNER_DEFS)
Lev Walkine0b56e02005-02-25 12:10:27 +00001275 OUT("\t// (Use -fall-defs-global to expose) */");
1276 OUT("\n");
Lev Walkin8de2ab22004-09-26 13:11:31 +00001277 REDIR(OT_CODE);
1278 OUT("/* This type is equivalent to %s */\n", type_name);
1279 OUT("\n");
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001280 REDIR(saved_target);
Lev Walkin8de2ab22004-09-26 13:11:31 +00001281 return 0;
1282 }
1283
Lev Walkin59004fa2004-08-20 13:37:01 +00001284 REDIR(OT_CODE);
1285
Lev Walkinf15320b2004-06-03 03:38:44 +00001286 /*
1287 * Constraint checking.
1288 */
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001289 if(!(arg->flags & A1C_NO_CONSTRAINTS) && expr->combined_constraints) {
Lev Walkina00d6b32006-03-21 03:40:38 +00001290 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001291 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkin8de2ab22004-09-26 13:11:31 +00001292 OUT("int\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001293 OUT("%s", p);
1294 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1295 OUT("_constraint(asn_TYPE_descriptor_t *td, const void *sptr,\n");
Lev Walkin8de2ab22004-09-26 13:11:31 +00001296 INDENT(+1);
Lev Walkin1eded352006-07-13 11:19:01 +00001297 OUT("\t\tasn_app_constraint_failed_f *ctfailcb, void *app_key) {");
Lev Walkin8de2ab22004-09-26 13:11:31 +00001298 OUT("\n");
Lev Walkin725883b2006-10-09 12:07:58 +00001299 DEBUG("expr constraint checking code for %s", p);
Lev Walkin8de2ab22004-09-26 13:11:31 +00001300 if(asn1c_emit_constraint_checking_code(arg) == 1) {
1301 OUT("/* Replace with underlying type checker */\n");
1302 OUT("td->check_constraints "
Lev Walkin05363a72004-09-29 13:16:40 +00001303 "= asn_DEF_%s.check_constraints;\n",
Lev Walkin8de2ab22004-09-26 13:11:31 +00001304 asn1c_type_name(arg, expr, TNF_SAFE));
1305 OUT("return td->check_constraints"
Lev Walkin1eded352006-07-13 11:19:01 +00001306 "(td, sptr, ctfailcb, app_key);\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +00001307 }
Lev Walkin8de2ab22004-09-26 13:11:31 +00001308 INDENT(-1);
1309 OUT("}\n");
1310 OUT("\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001311 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001312
Lev Walkin725883b2006-10-09 12:07:58 +00001313 REDIR(OT_STAT_DEFS);
1314
1315 /*
1316 * Print out asn_DEF_<type>_[all_]tags[] vectors.
1317 */
1318 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
1319 DEBUG("emit tag vectors for %s %d, %d, %d", expr->Identifier,
1320 tv_mode, tags_count, all_tags_count);
1321
1322 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count,
1323 0, etd_spec);
1324
1325 REDIR(OT_CODE);
1326
Lev Walkinf15320b2004-06-03 03:38:44 +00001327 /*
1328 * Emit suicidal functions.
1329 */
1330
Lev Walkinf15320b2004-06-03 03:38:44 +00001331 /*
1332 * This function replaces certain fields from the definition
1333 * of a type with the corresponding fields from the basic type
1334 * (from which the current type is inherited).
1335 */
Lev Walkinf15320b2004-06-03 03:38:44 +00001336 OUT("/*\n");
Lev Walkin59004fa2004-08-20 13:37:01 +00001337 OUT(" * This type is implemented using %s,\n",
1338 asn1c_type_name(arg, expr, TNF_SAFE));
Lev Walkinb65b3002004-09-23 22:20:47 +00001339 OUT(" * so here we adjust the DEF accordingly.\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001340 OUT(" */\n");
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001341
1342#if 0 /* remove unnecessary functions */
Lev Walkinf15320b2004-06-03 03:38:44 +00001343 OUT("static void\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001344 OUT("%s_%d_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00001345 MKID(expr), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +00001346 INDENT(+1);
Lev Walkine0b56e02005-02-25 12:10:27 +00001347 {
Lev Walkina9cc46e2004-09-22 16:06:28 +00001348 asn1p_expr_t *terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
Lev Walkin59004fa2004-08-20 13:37:01 +00001349 char *type_name = asn1c_type_name(arg, expr, TNF_SAFE);
Lev Walkin05363a72004-09-29 13:16:40 +00001350 OUT("td->free_struct = asn_DEF_%s.free_struct;\n", type_name);
1351 OUT("td->print_struct = asn_DEF_%s.print_struct;\n", type_name);
Lev Walkin6169b8d2013-12-07 11:02:44 -08001352 OUT("td->check_constraints = asn_DEF_%s.check_constraints;\n", type_name);
Lev Walkin05363a72004-09-29 13:16:40 +00001353 OUT("td->ber_decoder = asn_DEF_%s.ber_decoder;\n", type_name);
1354 OUT("td->der_encoder = asn_DEF_%s.der_encoder;\n", type_name);
1355 OUT("td->xer_decoder = asn_DEF_%s.xer_decoder;\n", type_name);
1356 OUT("td->xer_encoder = asn_DEF_%s.xer_encoder;\n", type_name);
Lev Walkin59b176e2005-11-26 11:25:14 +00001357 OUT("td->uper_decoder = asn_DEF_%s.uper_decoder;\n", type_name);
Lev Walkin1dc85292006-08-18 01:32:26 +00001358 OUT("td->uper_encoder = asn_DEF_%s.uper_encoder;\n", type_name);
Lev Walkinba68c912017-07-06 07:52:39 -07001359 OUT("td->oer_decoder = asn_DEF_%s.oer_decoder;\n", type_name);
1360 OUT("td->oer_encoder = asn_DEF_%s.oer_encoder;\n", type_name);
Lev Walkin906654e2004-09-10 15:49:15 +00001361 if(!terminal && !tags_count) {
Lev Walkin188ed2c2004-09-13 08:31:01 +00001362 OUT("/* The next four lines are here because of -fknown-extern-type */\n");
Lev Walkin05363a72004-09-29 13:16:40 +00001363 OUT("td->tags = asn_DEF_%s.tags;\n", type_name);
1364 OUT("td->tags_count = asn_DEF_%s.tags_count;\n", type_name);
1365 OUT("td->all_tags = asn_DEF_%s.all_tags;\n", type_name);
1366 OUT("td->all_tags_count = asn_DEF_%s.all_tags_count;\n",type_name);
Lev Walkin906654e2004-09-10 15:49:15 +00001367 OUT("/* End of these lines */\n");
1368 }
Lev Walkinb33425f2017-07-14 14:59:52 +04001369 OUT("if(!td->oer_constraints)\n");
1370 OUT("\ttd->oer_constraints = asn_DEF_%s.oer_constraints;\n",
1371 type_name);
Lev Walkin59b176e2005-11-26 11:25:14 +00001372 OUT("if(!td->per_constraints)\n");
1373 OUT("\ttd->per_constraints = asn_DEF_%s.per_constraints;\n",
1374 type_name);
Lev Walkin05363a72004-09-29 13:16:40 +00001375 OUT("td->elements = asn_DEF_%s.elements;\n", type_name);
1376 OUT("td->elements_count = asn_DEF_%s.elements_count;\n", type_name);
Lev Walkine0b56e02005-02-25 12:10:27 +00001377 if(etd_spec != ETD_NO_SPECIFICS) {
1378 INDENT(-1);
Lev Walkin7ef83a42005-03-29 19:04:24 +00001379 OUT(" /* ");
Lev Walkin59004fa2004-08-20 13:37:01 +00001380 }
Lev Walkine0b56e02005-02-25 12:10:27 +00001381 OUT("td->specifics = asn_DEF_%s.specifics;", type_name);
1382 if(etd_spec == ETD_NO_SPECIFICS) {
1383 INDENT(-1);
1384 OUT("\n");
1385 } else {
1386 OUT("\t// Defined explicitly */\n");
1387 }
1388 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001389 OUT("}\n");
1390 OUT("\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001391
Lev Walkina00d6b32006-03-21 03:40:38 +00001392 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001393 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001394 OUT("void\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001395 OUT("%s", p);
1396 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1397 OUT("_free(asn_TYPE_descriptor_t *td,\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001398 INDENTED(
Lev Walkina9cc46e2004-09-22 16:06:28 +00001399 OUT("\tvoid *struct_ptr, int contents_only) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001400 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1401 p, expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +00001402 OUT("td->free_struct(td, struct_ptr, contents_only);\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001403 );
1404 OUT("}\n");
1405 OUT("\n");
1406
Lev Walkina00d6b32006-03-21 03:40:38 +00001407 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001408 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkinf15320b2004-06-03 03:38:44 +00001409 OUT("int\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001410 OUT("%s", p);
1411 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1412 OUT("_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001413 INDENTED(
1414 OUT("\tint ilevel, asn_app_consume_bytes_f *cb, void *app_key) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001415 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1416 p, expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +00001417 OUT("return td->print_struct(td, struct_ptr, ilevel, cb, app_key);\n");
1418 );
1419 OUT("}\n");
1420 OUT("\n");
1421
Lev Walkina00d6b32006-03-21 03:40:38 +00001422 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001423 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkindc06f6b2004-10-20 15:50:55 +00001424 OUT("asn_dec_rval_t\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001425 OUT("%s", p);
1426 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1427 OUT("_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001428 INDENTED(
Lev Walkindd1512e2005-03-17 21:56:00 +00001429 OUT("\tvoid **structure, const void *bufptr, size_t size, int tag_mode) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001430 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1431 p, expr->_type_unique_index);
Lev Walkin05363a72004-09-29 13:16:40 +00001432 OUT("return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);\n");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001433 );
1434 OUT("}\n");
1435 OUT("\n");
1436
Lev Walkina00d6b32006-03-21 03:40:38 +00001437 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001438 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001439 OUT("asn_enc_rval_t\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001440 OUT("%s", p);
1441 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1442 OUT("_encode_der(asn_TYPE_descriptor_t *td,\n");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001443 INDENTED(
1444 OUT("\tvoid *structure, int tag_mode, ber_tlv_tag_t tag,\n");
1445 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001446 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1447 p, expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +00001448 OUT("return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);\n");
1449 );
1450 OUT("}\n");
1451 OUT("\n");
1452
Lev Walkina00d6b32006-03-21 03:40:38 +00001453 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001454 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkinca47c292004-10-23 13:34:00 +00001455 OUT("asn_dec_rval_t\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001456 OUT("%s", p);
1457 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1458 OUT("_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n");
Lev Walkinca47c292004-10-23 13:34:00 +00001459 INDENTED(
Lev Walkindd1512e2005-03-17 21:56:00 +00001460 OUT("\tvoid **structure, const char *opt_mname, const void *bufptr, size_t size) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001461 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1462 p, expr->_type_unique_index);
Lev Walkinca47c292004-10-23 13:34:00 +00001463 OUT("return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size);\n");
1464 );
1465 OUT("}\n");
1466 OUT("\n");
1467
Lev Walkina00d6b32006-03-21 03:40:38 +00001468 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001469 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001470 OUT("asn_enc_rval_t\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001471 OUT("%s", p);
1472 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1473 OUT("_encode_xer(asn_TYPE_descriptor_t *td, void *structure,\n");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001474 INDENTED(
1475 OUT("\tint ilevel, enum xer_encoder_flags_e flags,\n");
1476 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001477 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1478 p, expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +00001479 OUT("return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001480 );
1481 OUT("}\n");
1482 OUT("\n");
1483
Lev Walkinb33425f2017-07-14 14:59:52 +04001484 if(arg->flags & A1C_GEN_OER) {
1485 p = MKID(expr);
1486
1487 if(HIDE_INNER_DEFS) OUT("static ");
1488 OUT("asn_dec_rval_t\n");
1489 OUT("%s", p);
1490 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1491 OUT("_decode_oer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n");
1492 INDENTED(
1493 OUT("\tasn_oer_constraints_t *constraints, void **structure, const void *buffer, size_t size) {\n");
1494 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1495 p, expr->_type_unique_index);
1496 OUT("return td->oer_decoder(opt_codec_ctx, td, constraints, structure, buffer, size);\n");
1497 );
1498 OUT("}\n");
1499 OUT("\n");
1500
1501 p = MKID(expr);
1502 if(HIDE_INNER_DEFS) OUT("static ");
1503 OUT("asn_enc_rval_t\n");
1504 OUT("%s", p);
1505 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1506 OUT("_encode_oer(asn_TYPE_descriptor_t *td,\n");
1507 INDENTED(
1508 OUT("\tasn_oer_constraints_t *constraints,\n");
1509 OUT("\tvoid *structure, asn_app_consume_bytes_f *cb, void *app_key) {\n");
1510 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1511 p, expr->_type_unique_index);
1512 OUT("return td->uper_encoder(td, constraints, structure, cb, app_key);\n");
1513 );
1514 OUT("}\n");
1515 OUT("\n");
1516 }
1517
Lev Walkin59b176e2005-11-26 11:25:14 +00001518 if(arg->flags & A1C_GEN_PER) {
Lev Walkina00d6b32006-03-21 03:40:38 +00001519 p = MKID(expr);
Lev Walkin1dc85292006-08-18 01:32:26 +00001520
Lev Walkin59b176e2005-11-26 11:25:14 +00001521 if(HIDE_INNER_DEFS) OUT("static ");
1522 OUT("asn_dec_rval_t\n");
1523 OUT("%s", p);
1524 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1525 OUT("_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n");
1526 INDENTED(
1527 OUT("\tasn_per_constraints_t *constraints, void **structure, asn_per_data_t *per_data) {\n");
1528 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1529 p, expr->_type_unique_index);
1530 OUT("return td->uper_decoder(opt_codec_ctx, td, constraints, structure, per_data);\n");
1531 );
1532 OUT("}\n");
1533 OUT("\n");
Lev Walkin1dc85292006-08-18 01:32:26 +00001534
1535 p = MKID(expr);
1536 if(HIDE_INNER_DEFS) OUT("static ");
1537 OUT("asn_enc_rval_t\n");
1538 OUT("%s", p);
1539 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1540 OUT("_encode_uper(asn_TYPE_descriptor_t *td,\n");
1541 INDENTED(
1542 OUT("\tasn_per_constraints_t *constraints,\n");
1543 OUT("\tvoid *structure, asn_per_outp_t *per_out) {\n");
1544 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1545 p, expr->_type_unique_index);
1546 OUT("return td->uper_encoder(td, constraints, structure, per_out);\n");
1547 );
1548 OUT("}\n");
1549 OUT("\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00001550 }
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001551#endif
Lev Walkinf15320b2004-06-03 03:38:44 +00001552 REDIR(OT_FUNC_DECLS);
1553
Lev Walkina00d6b32006-03-21 03:40:38 +00001554 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001555 if(HIDE_INNER_DEFS) {
Lev Walkin21d00002005-03-04 08:48:53 +00001556 OUT("/* extern asn_TYPE_descriptor_t asn_DEF_%s_%d;"
1557 "\t// (Use -fall-defs-global to expose) */\n",
1558 p, expr->_type_unique_index);
Lev Walkine0b56e02005-02-25 12:10:27 +00001559 } else {
1560 OUT("extern asn_TYPE_descriptor_t asn_DEF_%s;\n", p);
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001561 if (etd_spec == ETD_HAS_SPECIFICS) {
1562 if((expr->expr_type == ASN_BASIC_ENUMERATED) ||
1563 (expr->expr_type == ASN_BASIC_INTEGER)) {
1564 if(expr->_type_referenced) {
1565 OUT("extern asn_INTEGER_specifics_t "
1566 "asn_SPC_%s_specs_%d;\n", p, expr->_type_unique_index);
1567 }
1568 } else {
1569 asn1p_expr_t *terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
1570
1571 OUT("extern asn_%s_specifics_t ", asn1c_type_name(arg, terminal, TNF_SAFE));
1572 OUT("asn_SPC_%s_specs_%d;\n", MKID(expr), expr->_type_unique_index);
1573 }
1574 }
Lev Walkine0b56e02005-02-25 12:10:27 +00001575 OUT("asn_struct_free_f %s_free;\n", p);
1576 OUT("asn_struct_print_f %s_print;\n", p);
1577 OUT("asn_constr_check_f %s_constraint;\n", p);
1578 OUT("ber_type_decoder_f %s_decode_ber;\n", p);
1579 OUT("der_type_encoder_f %s_encode_der;\n", p);
1580 OUT("xer_type_decoder_f %s_decode_xer;\n", p);
1581 OUT("xer_type_encoder_f %s_encode_xer;\n", p);
Lev Walkinb33425f2017-07-14 14:59:52 +04001582 if(arg->flags & A1C_GEN_OER) {
1583 OUT("oer_type_decoder_f %s_decode_oer;\n", p);
1584 OUT("oer_type_encoder_f %s_encode_oer;\n", p);
1585 }
Lev Walkin1dc85292006-08-18 01:32:26 +00001586 if(arg->flags & A1C_GEN_PER) {
Lev Walkin59b176e2005-11-26 11:25:14 +00001587 OUT("per_type_decoder_f %s_decode_uper;\n", p);
Lev Walkin1dc85292006-08-18 01:32:26 +00001588 OUT("per_type_encoder_f %s_encode_uper;\n", p);
1589 }
Lev Walkine0b56e02005-02-25 12:10:27 +00001590 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001591
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001592 REDIR(saved_target);
Lev Walkin3dcaafa2004-08-11 05:21:32 +00001593
Lev Walkinf15320b2004-06-03 03:38:44 +00001594 return 0;
1595}
1596
1597int
1598asn1c_lang_C_type_EXTENSIBLE(arg_t *arg) {
1599
1600 OUT("/*\n");
1601 OUT(" * This type is extensible,\n");
1602 OUT(" * possible extensions are below.\n");
1603 OUT(" */\n");
1604
1605 return 0;
1606}
1607
Lev Walkin59b176e2005-11-26 11:25:14 +00001608static int
1609compute_extensions_start(asn1p_expr_t *expr) {
Lev Walkin35631482004-07-01 00:52:50 +00001610 asn1p_expr_t *v;
Lev Walkin59b176e2005-11-26 11:25:14 +00001611 int eidx = 0;
Lev Walkin35631482004-07-01 00:52:50 +00001612 TQ_FOR(v, &(expr->members), next) {
Lev Walkin59b176e2005-11-26 11:25:14 +00001613 if(v->expr_type == A1TC_EXTENSIBLE)
1614 return eidx;
1615 eidx++;
Lev Walkin35631482004-07-01 00:52:50 +00001616 }
Lev Walkin59b176e2005-11-26 11:25:14 +00001617 return -1;
Lev Walkin35631482004-07-01 00:52:50 +00001618}
1619
Lev Walkinf15320b2004-06-03 03:38:44 +00001620static int
Lev Walkinc3e29402004-09-10 06:07:18 +00001621_print_tag(arg_t *arg, struct asn1p_type_tag_s *tag) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001622
1623 OUT("(");
Lev Walkinc3e29402004-09-10 06:07:18 +00001624 switch(tag->tag_class) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001625 case TC_UNIVERSAL: OUT("ASN_TAG_CLASS_UNIVERSAL"); break;
1626 case TC_APPLICATION: OUT("ASN_TAG_CLASS_APPLICATION"); break;
1627 case TC_CONTEXT_SPECIFIC: OUT("ASN_TAG_CLASS_CONTEXT"); break;
1628 case TC_PRIVATE: OUT("ASN_TAG_CLASS_PRIVATE"); break;
1629 case TC_NOCLASS:
1630 break;
1631 }
Lev Walkinda997b12017-08-04 01:38:41 -07001632 OUT(" | (%s << 2))", asn1p_itoa(tag->tag_value));
Lev Walkinf15320b2004-06-03 03:38:44 +00001633
1634 return 0;
1635}
1636
Lev Walkinfd171ef2004-06-06 07:20:17 +00001637
1638static int
1639_tag2el_cmp(const void *ap, const void *bp) {
1640 const tag2el_t *a = ap;
1641 const tag2el_t *b = bp;
1642 const struct asn1p_type_tag_s *ta = &a->el_tag;
1643 const struct asn1p_type_tag_s *tb = &b->el_tag;
1644
1645 if(ta->tag_class == tb->tag_class) {
1646 if(ta->tag_value == tb->tag_value) {
1647 /*
1648 * Sort by their respective positions.
1649 */
1650 if(a->el_no < b->el_no)
1651 return -1;
1652 else if(a->el_no > b->el_no)
1653 return 1;
1654 return 0;
1655 } else if(ta->tag_value < tb->tag_value)
1656 return -1;
1657 else
1658 return 1;
1659 } else if(ta->tag_class < tb->tag_class) {
1660 return -1;
1661 } else {
1662 return 1;
1663 }
1664}
1665
Lev Walkinf15320b2004-06-03 03:38:44 +00001666/*
1667 * For constructed types, number of external tags may be greater than
1668 * number of elements in the type because of CHOICE type.
1669 * T ::= SET { -- Three possible tags:
1670 * a INTEGER, -- One tag is here...
1671 * b Choice1 -- ... and two more tags are there.
1672 * }
1673 * Choice1 ::= CHOICE {
1674 * s1 IA5String,
1675 * s2 ObjectDescriptor
1676 * }
1677 */
1678static int
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001679_fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001680 asn1p_expr_t *expr = arg->expr;
1681 arg_t tmparg = *arg;
1682 asn1p_expr_t *v;
1683 int element = 0;
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001684 int original_count = *count;
1685 int sort_until = -1;
Lev Walkinf15320b2004-06-03 03:38:44 +00001686
1687 TQ_FOR(v, &(expr->members), next) {
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001688 if(v->expr_type == A1TC_EXTENSIBLE) {
1689 /*
Lev Walkine0b56e02005-02-25 12:10:27 +00001690 * CXER mandates sorting
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001691 * only for the root part.
1692 */
1693 if(flags == FTE_CANONICAL_XER
1694 && sort_until == -1)
1695 sort_until = *count;
Lev Walkinf15320b2004-06-03 03:38:44 +00001696 continue;
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001697 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001698
1699 tmparg.expr = v;
1700
1701 if(_add_tag2el_member(&tmparg, tag2el, count,
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001702 (el_no==-1)?element:el_no, flags)) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001703 return -1;
1704 }
1705
1706 element++;
1707 }
1708
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001709
1710 if(flags == FTE_CANONICAL_XER) {
1711 if(sort_until == -1) sort_until = *count;
1712 qsort((*tag2el) + original_count,
1713 sort_until - original_count,
1714 sizeof(**tag2el), _tag2el_cmp);
1715 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1716 && (sort_until - original_count) >= 1) {
1717 /* Only take in account the root component */
1718 *count = original_count + 1;
1719 }
1720 } else {
1721 /*
1722 * Sort the map according to canonical order of their
1723 * tags and element numbers.
1724 */
1725 qsort(*tag2el, *count, sizeof(**tag2el), _tag2el_cmp);
1726 }
Lev Walkinfd171ef2004-06-06 07:20:17 +00001727
Lev Walkin38abe792004-06-14 13:09:45 +00001728 /*
1729 * Initialize .toff_{first|last} members.
1730 */
1731 if(*count) {
1732 struct asn1p_type_tag_s *cur_tag = 0;
1733 tag2el_t *cur = *tag2el;
1734 tag2el_t *end = cur + *count;
1735 int occur, i;
1736 for(occur = 0; cur < end; cur++) {
1737 if(cur_tag == 0
1738 || cur_tag->tag_value != cur->el_tag.tag_value
1739 || cur_tag->tag_class != cur->el_tag.tag_class) {
1740 cur_tag = &cur->el_tag;
1741 occur = 0;
1742 } else {
1743 occur++;
1744 }
1745 cur->toff_first = -occur;
1746 for(i = 0; i >= -occur; i--)
1747 cur[i].toff_last = -i;
1748 }
1749 }
1750
Lev Walkinf15320b2004-06-03 03:38:44 +00001751 return 0;
1752}
1753
1754static int
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001755_add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001756 struct asn1p_type_tag_s tag;
1757 int ret;
1758
1759 assert(el_no >= 0);
1760
Lev Walkina9cc46e2004-09-22 16:06:28 +00001761 ret = asn1f_fetch_outmost_tag(arg->asn, arg->expr->module,
Lev Walkin59b176e2005-11-26 11:25:14 +00001762 arg->expr, &tag, AFT_IMAGINARY_ANY);
Lev Walkinf15320b2004-06-03 03:38:44 +00001763 if(ret == 0) {
Lev Walkin201943e2004-09-04 04:42:29 +00001764 tag2el_t *te;
1765 int new_count = (*count) + 1;
Lev Walkinf15320b2004-06-03 03:38:44 +00001766 void *p;
Lev Walkin201943e2004-09-04 04:42:29 +00001767
Lev Walkinac7e2292004-09-05 10:42:33 +00001768 if(tag.tag_value == -1) {
1769 /*
1770 * This is an untagged ANY type,
1771 * proceed without adding a tag
1772 */
1773 return 0;
1774 }
1775
Lev Walkin201943e2004-09-04 04:42:29 +00001776 p = realloc(*tag2el, new_count * sizeof(tag2el_t));
Lev Walkinf15320b2004-06-03 03:38:44 +00001777 if(p) *tag2el = p;
1778 else return -1;
1779
Lev Walkin725883b2006-10-09 12:07:58 +00001780 if(0) DEBUG("Found tag for %s: %ld",
Lev Walkinf15320b2004-06-03 03:38:44 +00001781 arg->expr->Identifier,
1782 (long)tag.tag_value);
1783
Lev Walkin201943e2004-09-04 04:42:29 +00001784 te = &((*tag2el)[*count]);
1785 te->el_tag = tag;
1786 te->el_no = el_no;
1787 te->from_expr = arg->expr;
1788 *count = new_count;
Lev Walkinf15320b2004-06-03 03:38:44 +00001789 return 0;
1790 }
1791
1792 DEBUG("Searching tag in complex expression %s:%x at line %d",
1793 arg->expr->Identifier,
1794 arg->expr->expr_type,
1795 arg->expr->_lineno);
1796
1797 /*
1798 * Iterate over members of CHOICE type.
1799 */
1800 if(arg->expr->expr_type == ASN_CONSTR_CHOICE) {
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001801 return _fill_tag2el_map(arg, tag2el, count, el_no, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +00001802 }
1803
1804 if(arg->expr->expr_type == A1TC_REFERENCE) {
1805 arg_t tmp = *arg;
1806 asn1p_expr_t *expr;
Lev Walkinb85a8132005-08-18 13:38:19 +00001807 expr = asn1f_lookup_symbol_ex(tmp.asn, tmp.expr,
Lev Walkinf15320b2004-06-03 03:38:44 +00001808 arg->expr->reference);
1809 if(expr) {
1810 tmp.expr = expr;
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001811 return _add_tag2el_member(&tmp, tag2el, count, el_no, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +00001812 } else {
1813 FATAL("Cannot dereference %s at line %d",
1814 arg->expr->Identifier,
1815 arg->expr->_lineno);
1816 return -1;
1817 }
1818 }
1819
1820 DEBUG("No tag for %s at line %d",
1821 arg->expr->Identifier,
1822 arg->expr->_lineno);
1823
1824 return -1;
1825}
1826
1827static int
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001828emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier) {
Lev Walkinfd171ef2004-06-06 07:20:17 +00001829 asn1p_expr_t *expr = arg->expr;
Lev Walkinf3b29b12005-06-02 05:21:37 +00001830 int i;
1831
1832 if(!tag2el_count) return 0; /* No top level tags */
Lev Walkinfd171ef2004-06-06 07:20:17 +00001833
Wim Lewisfb6344e2014-07-28 12:16:01 -07001834 OUT("static const asn_TYPE_tag2member_t asn_MAP_%s_tag2el%s_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00001835 MKID(expr), opt_modifier?opt_modifier:"",
Lev Walkin59b176e2005-11-26 11:25:14 +00001836 expr->_type_unique_index);
Lev Walkinf3b29b12005-06-02 05:21:37 +00001837 for(i = 0; i < tag2el_count; i++) {
1838 OUT(" { ");
1839 _print_tag(arg, &tag2el[i].el_tag);
1840 OUT(", ");
1841 OUT("%d, ", tag2el[i].el_no);
1842 OUT("%d, ", tag2el[i].toff_first);
1843 OUT("%d ", tag2el[i].toff_last);
Lev Walkin4062b012013-10-11 14:29:38 -07001844 OUT("}%s /* %s",
Lev Walkinf3b29b12005-06-02 05:21:37 +00001845 (i + 1 < tag2el_count) ? "," : "",
Lev Walkin4062b012013-10-11 14:29:38 -07001846 tag2el[i].from_expr->Identifier);
1847 if(arg->flags & A1C_LINE_REFS)
1848 OUT("at %d", tag2el[i].from_expr->_lineno);
1849 OUT(" */\n");
Lev Walkinfd171ef2004-06-06 07:20:17 +00001850 }
1851 OUT("};\n");
1852
Lev Walkinf3b29b12005-06-02 05:21:37 +00001853 return 0;
Lev Walkinfd171ef2004-06-06 07:20:17 +00001854}
1855
Lev Walkin188ed2c2004-09-13 08:31:01 +00001856static enum tvm_compat
1857emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tags_count_r, int *all_tags_count_r) {
1858 struct asn1p_type_tag_s *tags = 0; /* Effective tags */
1859 struct asn1p_type_tag_s *all_tags = 0; /* The full array */
Lev Walkin64399722004-08-11 07:17:22 +00001860 int tags_count = 0;
Lev Walkin188ed2c2004-09-13 08:31:01 +00001861 int all_tags_count = 0;
1862 enum tvm_compat tv_mode = _TVM_SAME;
Lev Walkin906654e2004-09-10 15:49:15 +00001863 int i;
Lev Walkin27ea3802004-06-28 21:13:46 +00001864
Lev Walkin6d1220a2004-09-14 14:10:10 +00001865 /* Cleanup before proceeding. */
1866 *tags_count_r = 0;
1867 *all_tags_count_r = 0;
1868
Lev Walkin906654e2004-09-10 15:49:15 +00001869 /* Fetch a chain of tags */
Lev Walkina9cc46e2004-09-22 16:06:28 +00001870 tags_count = asn1f_fetch_tags(arg->asn, expr->module, expr, &tags, 0);
Lev Walkin725883b2006-10-09 12:07:58 +00001871 if(tags_count < 0) {
1872 DEBUG("fail to fetch tags for %s", expr->Identifier);
Lev Walkin6d1220a2004-09-14 14:10:10 +00001873 return -1;
Lev Walkin725883b2006-10-09 12:07:58 +00001874 }
Lev Walkin64399722004-08-11 07:17:22 +00001875
Lev Walkin188ed2c2004-09-13 08:31:01 +00001876 /* Fetch a chain of tags */
Lev Walkina9cc46e2004-09-22 16:06:28 +00001877 all_tags_count = asn1f_fetch_tags(arg->asn, expr->module, expr,
Lev Walkin188ed2c2004-09-13 08:31:01 +00001878 &all_tags, AFT_FULL_COLLECT);
1879 if(all_tags_count < 0) {
Lev Walkind8b83642016-03-14 02:00:27 -07001880 free(tags);
Lev Walkin725883b2006-10-09 12:07:58 +00001881 DEBUG("fail to fetch tags chain for %s", expr->Identifier);
Lev Walkin188ed2c2004-09-13 08:31:01 +00001882 return -1;
Lev Walkin5a8219a2004-09-08 00:28:57 +00001883 }
Lev Walkin906654e2004-09-10 15:49:15 +00001884
Lev Walkin188ed2c2004-09-13 08:31:01 +00001885 assert(tags_count <= all_tags_count);
1886 assert((tags_count?0:1) == (all_tags_count?0:1));
Lev Walkin27ea3802004-06-28 21:13:46 +00001887
Lev Walkin188ed2c2004-09-13 08:31:01 +00001888 if(tags_count <= all_tags_count) {
1889 for(i = 0; i < tags_count; i++) {
1890 if(tags[i].tag_value != all_tags[i].tag_value
1891 || tags[i].tag_class != all_tags[i].tag_class) {
1892 tv_mode = _TVM_DIFFERENT;
1893 break;
1894 }
1895 }
1896 if(i == tags_count && tags_count < all_tags_count)
1897 tv_mode = _TVM_SUBSET;
1898 } else {
1899 tv_mode = _TVM_DIFFERENT;
1900 }
1901
1902#define EMIT_TAGS_TABLE(name, tags, tags_count) do { \
Wim Lewisfb6344e2014-07-28 12:16:01 -07001903 OUT("static const ber_tlv_tag_t asn_DEF_%s%s_tags_%d[] = {\n",\
Lev Walkina00d6b32006-03-21 03:40:38 +00001904 MKID(expr), name, \
Lev Walkin59b176e2005-11-26 11:25:14 +00001905 expr->_type_unique_index); \
Lev Walkin188ed2c2004-09-13 08:31:01 +00001906 INDENT(+1); \
1907 /* Print the array of collected tags */ \
1908 for(i = 0; i < tags_count; i++) { \
1909 if(i) OUT(",\n"); \
1910 _print_tag(arg, &tags[i]); \
1911 } \
1912 OUT("\n"); \
1913 INDENT(-1); \
1914 OUT("};\n"); \
1915 } while(0)
1916
1917 if(tags_count) {
1918 if(tv_mode == _TVM_SUBSET)
1919 EMIT_TAGS_TABLE("", all_tags, all_tags_count);
1920 else
1921 EMIT_TAGS_TABLE("", tags, tags_count);
1922 }
1923
1924 if(all_tags_count) {
1925 if(tv_mode == _TVM_DIFFERENT)
1926 EMIT_TAGS_TABLE("_all", all_tags, all_tags_count);
1927 }
1928
Lev Walkind8b83642016-03-14 02:00:27 -07001929 free(tags);
1930 free(all_tags);
Lev Walkin188ed2c2004-09-13 08:31:01 +00001931
1932 *tags_count_r = tags_count;
1933 *all_tags_count_r = all_tags_count;
1934
1935 return tv_mode;
Lev Walkin27ea3802004-06-28 21:13:46 +00001936}
Lev Walkin59004fa2004-08-20 13:37:01 +00001937
1938static int
Lev Walkin59964be2004-08-25 02:03:12 +00001939expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin59004fa2004-08-20 13:37:01 +00001940 asn1p_expr_t *topmost_parent;
1941 asn1p_expr_t *v;
1942 int elements = 0;
1943
Lev Walkina9cc46e2004-09-22 16:06:28 +00001944 topmost_parent = asn1f_find_terminal_type_ex(arg->asn, expr);
Lev Walkin59004fa2004-08-20 13:37:01 +00001945 if(!topmost_parent) return 0;
1946
Lev Walkine0b56e02005-02-25 12:10:27 +00001947 if(!(topmost_parent->expr_type & ASN_CONSTR_MASK)
Lev Walkin1b3a1352016-01-10 13:15:02 -08001948 && !(topmost_parent->expr_type == ASN_BASIC_INTEGER)
Lev Walkin0f262452016-01-10 13:33:08 -08001949 && !(topmost_parent->expr_type == ASN_BASIC_ENUMERATED)
1950 && !(topmost_parent->expr_type == ASN_BASIC_BIT_STRING))
Lev Walkin59004fa2004-08-20 13:37:01 +00001951 return 0;
1952
1953 TQ_FOR(v, &(topmost_parent->members), next) {
1954 if(v->expr_type != A1TC_EXTENSIBLE)
1955 elements++;
1956 }
1957
1958 return elements;
1959}
1960
Lev Walkin59b176e2005-11-26 11:25:14 +00001961static asn1p_expr_type_e
1962expr_get_type(arg_t *arg, asn1p_expr_t *expr) {
1963 asn1p_expr_t *terminal;
1964 terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
1965 if(terminal) return terminal->expr_type;
1966 return A1TC_INVALID;
1967}
1968
Lev Walkin725883b2006-10-09 12:07:58 +00001969static asn1c_integer_t
1970PER_FROM_alphabet_characters(asn1cnst_range_t *range) {
1971 asn1c_integer_t numchars = 0;
1972 if(range->el_count) {
1973 int i;
1974 for(i = 0; i < range->el_count; i++)
1975 numchars
1976 += PER_FROM_alphabet_characters(range->elements[i]);
1977 } else {
1978 assert(range->left.type == ARE_VALUE);
1979 assert(range->right.type == ARE_VALUE);
1980 numchars = 1 + (range->right.value - range->left.value);
1981 }
1982 return numchars;
1983}
1984
Lev Walkin4118ccf2017-08-02 10:37:31 -07001985static void
1986emit_single_member_OER_constraint_comment(arg_t *arg, asn1cnst_range_t *range, char *type) {
1987
1988 /*
1989 * Print some courtesy debug information.
1990 */
1991 if(range
1992 && (range->left.type == ARE_VALUE || range->right.type == ARE_VALUE)) {
1993 OUT("\t/* ");
1994 if(type) OUT("(%s", type);
1995 OUT("(");
1996 if(range->left.type == ARE_VALUE)
Lev Walkinda997b12017-08-04 01:38:41 -07001997 OUT("%s", asn1p_itoa(range->left.value));
Lev Walkin4118ccf2017-08-02 10:37:31 -07001998 else
1999 OUT("MIN");
2000 OUT("..");
2001 if(range->right.type == ARE_VALUE)
Lev Walkinda997b12017-08-04 01:38:41 -07002002 OUT("%s", asn1p_itoa(range->right.value));
Lev Walkin4118ccf2017-08-02 10:37:31 -07002003 else
2004 OUT("MAX");
2005 if(range->extensible) OUT(",...");
2006 if(type) OUT(")");
2007 OUT(") */");
2008 }
2009}
2010
2011static int
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002012emit_single_member_OER_constraint_value(arg_t *arg, asn1cnst_range_t *range) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07002013 if(!range) {
2014 /* oer_support.h: asn_oer_constraint_s */
2015 OUT("{ 0, 0 }");
2016 return 0;
2017 }
2018
2019 if(range->incompatible || range->not_OER_visible) {
2020 OUT("{ 0, 0 }");
2021 } else if(range->left.type == ARE_VALUE &&
2022 range->right.type == ARE_VALUE) {
2023 asn1c_integer_t lb = range->left.value;
2024 asn1c_integer_t ub = range->right.value;
2025 unsigned width = 0;
2026 unsigned positive = 0;
2027
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002028
Lev Walkin4118ccf2017-08-02 10:37:31 -07002029 if(lb >= 0) {
2030 /* X.969 08/2015 10.2(a) */
2031 if(ub <= 255) {
2032 width = 1;
2033 } else if(ub <= 65535) {
2034 width = 2;
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002035 } else if((unsigned long long)ub <= 4294967295UL) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07002036 width = 4;
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002037 } else if((unsigned long long)ub <= 18446744073709551615ULL) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07002038 width = 8;
2039 }
2040 positive = 1;
2041 } else {
2042 positive = 0;
2043 /* X.969 08/2015 10.2(b) - no lower bound or negative lower bound */
2044 if(lb >= -128 && ub <= 127) {
2045 width = 1;
2046 } else if(lb >= -32768 && ub <= 32767) {
2047 width = 2;
2048 } else if(lb >= -2147483648L && ub <= 2147483647L) {
2049 width = 4;
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002050 } else if(lb >= (-9223372036854775807LL-1)
Lev Walkin4118ccf2017-08-02 10:37:31 -07002051 && ub <= 9223372036854775807LL) {
2052 width = 8;
2053 }
2054 }
2055 OUT("{ %u, %u }", width, positive);
2056 } else {
2057 OUT("{ 0, 0 }");
2058 }
2059
2060 return 0;
2061}
2062
2063static int
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002064emit_single_member_OER_constraint_size(arg_t *arg, asn1cnst_range_t *range) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07002065 if(!range) {
2066 /* oer_support.h: asn_oer_constraint_s */
2067 OUT("-1");
2068 return 0;
2069 }
2070
2071 if(range->incompatible || range->not_OER_visible) {
2072 OUT("-1");
2073 } else {
2074 if(range->left.type == ARE_VALUE && range->right.type == ARE_VALUE
2075 && range->left.value == range->right.value
2076 && range->left.value >= 0) {
Lev Walkinda997b12017-08-04 01:38:41 -07002077 OUT("%s", asn1p_itoa(range->left.value));
Lev Walkin4118ccf2017-08-02 10:37:31 -07002078 } else {
2079 OUT("-1");
2080 }
2081 }
2082
2083 return 0;
2084}
2085
Lev Walkin59b176e2005-11-26 11:25:14 +00002086static int
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002087emit_single_member_PER_constraint(arg_t *arg, asn1cnst_range_t *range, int alphabetsize, const char *type) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07002088 if(!range || range->incompatible || range->not_PER_visible) {
2089 OUT("{ APC_UNCONSTRAINED,\t-1, -1, 0, 0 }");
Lev Walkin59b176e2005-11-26 11:25:14 +00002090 return 0;
Lev Walkin4118ccf2017-08-02 10:37:31 -07002091 }
Lev Walkin59b176e2005-11-26 11:25:14 +00002092
Lev Walkin4118ccf2017-08-02 10:37:31 -07002093 if(range->left.type == ARE_VALUE) {
Lev Walkin59b176e2005-11-26 11:25:14 +00002094 if(range->right.type == ARE_VALUE) {
2095 asn1c_integer_t cover = 1;
2096 asn1c_integer_t r = 1 + range->right.value
2097 - range->left.value;
Lev Walkinc46b7cb2006-08-18 02:27:55 +00002098 size_t rbits; /* Value range bits */
2099 ssize_t ebits; /* Value effective range bits */
Lev Walkin59b176e2005-11-26 11:25:14 +00002100
2101 if(range->empty_constraint)
2102 r = 0;
2103
Lev Walkin725883b2006-10-09 12:07:58 +00002104 if(alphabetsize) {
2105 /* X.691: 27.5.2 */
2106 r = PER_FROM_alphabet_characters(range);
2107 }
2108
Lev Walkin59b176e2005-11-26 11:25:14 +00002109 /* Compute real constraint */
2110 for(rbits = 0; rbits < (8 * sizeof(r)); rbits++) {
2111 if(r <= cover)
2112 break;
2113 cover *= 2; /* Can't do shifting */
2114 if(cover < 0) {
2115 FATAL("Constraint at line %d too wide "
2116 "for %d-bits integer type",
2117 arg->expr->_lineno,
2118 sizeof(r) * 8);
2119 rbits = sizeof(r);
2120 break;
2121 }
2122 }
2123
Lev Walkin3a4689a2006-11-24 11:20:27 +00002124 if(alphabetsize) {
2125 ebits = rbits;
2126 } else {
Lev Walkin59b176e2005-11-26 11:25:14 +00002127 /* X.691, #10.9.4.1 */
2128 for(ebits = 0; ebits <= 16; ebits++)
2129 if(r <= 1 << ebits) break;
2130 if(ebits == 17
2131 || range->right.value >= 65536)
2132 ebits = -1;
Lev Walkin3a4689a2006-11-24 11:20:27 +00002133 if(0) {
Lev Walkin59b176e2005-11-26 11:25:14 +00002134 /* X.691, #10.5.7.1 */
2135 for(ebits = 0; ebits <= 8; ebits++)
2136 if(r <= 1 << ebits) break;
2137 if(ebits == 9) {
2138 if(r <= 65536)
2139 ebits = 16;
2140 else
2141 ebits = -1;
2142 }
2143 }
Lev Walkin3a4689a2006-11-24 11:20:27 +00002144 }
Lev Walkin725883b2006-10-09 12:07:58 +00002145
Lev Walkin59b176e2005-11-26 11:25:14 +00002146 OUT("{ APC_CONSTRAINED%s,%s% d, % d, ",
2147 range->extensible
2148 ? " | APC_EXTENSIBLE" : "",
2149 range->extensible ? " " : "\t", rbits, ebits);
Lev Walkin3a4689a2006-11-24 11:20:27 +00002150
2151 if(alphabetsize) {
2152 asn1c_integer_t lv = range->left.value;
2153 asn1c_integer_t rv = range->right.value;
2154 int gcmt = 0;
2155 if(lv > 0x7fffffff) { lv = 0x7fffffff; gcmt++; }
2156 if(rv > 0x7fffffff) { rv = 0x7fffffff; gcmt++; }
2157 if(gcmt) {
Lev Walkin63b41262007-11-06 01:48:46 +00002158 OINTS(lv); OUT(", "); OINTS(rv); OUT(" }");
Lev Walkin3a4689a2006-11-24 11:20:27 +00002159 goto pcmt;
2160 }
2161 }
Lev Walkin59b176e2005-11-26 11:25:14 +00002162 } else {
2163 if(range->extensible) {
2164 OUT("{ APC_SEMI_CONSTRAINED | APC_EXTENSIBLE, "
2165 "-1, ");
2166 } else {
2167 OUT("{ APC_SEMI_CONSTRAINED,\t-1, -1, ");
2168 }
2169 }
Lev Walkin63b41262007-11-06 01:48:46 +00002170 OINTS(range->left.value); OUT(", ");
2171 OINTS(range->right.value); OUT(" }");
Lev Walkin59b176e2005-11-26 11:25:14 +00002172 } else {
2173 OUT("{ APC_UNCONSTRAINED,\t-1, -1, 0, 0 }");
2174 }
2175
Lev Walkin3a4689a2006-11-24 11:20:27 +00002176 pcmt:
2177
Lev Walkin59b176e2005-11-26 11:25:14 +00002178 /*
2179 * Print some courtesy debug information.
2180 */
2181 if(range->left.type == ARE_VALUE
2182 || range->right.type == ARE_VALUE) {
2183 OUT("\t/* ");
2184 if(type) OUT("(%s", type);
2185 OUT("(");
2186 if(range->left.type == ARE_VALUE)
Lev Walkinda997b12017-08-04 01:38:41 -07002187 OUT("%s", asn1p_itoa(range->left.value));
Lev Walkin59b176e2005-11-26 11:25:14 +00002188 else
2189 OUT("MIN");
2190 OUT("..");
2191 if(range->right.type == ARE_VALUE)
Lev Walkinda997b12017-08-04 01:38:41 -07002192 OUT("%s", asn1p_itoa(range->right.value));
Lev Walkin59b176e2005-11-26 11:25:14 +00002193 else
2194 OUT("MAX");
2195 if(range->extensible) OUT(",...");
2196 if(type) OUT(")");
2197 OUT(") */");
2198 }
2199
2200 return 0;
2201}
2202
2203static int
Lev Walkin98eabc12017-07-19 08:51:11 +04002204emit_member_OER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx) {
2205 int save_target = arg->target->target;
2206 asn1cnst_range_t *range;
2207 asn1p_expr_type_e etype;
2208
2209 etype = expr_get_type(arg, expr);
2210
2211 if((arg->flags & A1C_GEN_OER)
2212 && (expr->constraints || etype == ASN_BASIC_ENUMERATED
2213 || etype == ASN_CONSTR_CHOICE)) {
2214 /* Fall through */
2215 } else {
2216 return 0;
2217 }
2218
2219 REDIR(OT_CTDEFS);
2220
2221 OUT("static asn_oer_constraints_t "
2222 "asn_OER_%s_%s_constr_%d GCC_NOTUSED = {\n",
2223 pfx, MKID(expr), expr->_type_unique_index);
2224
2225 INDENT(+1);
2226
Lev Walkin4118ccf2017-08-02 10:37:31 -07002227 /* .value{.width,.positive} */
Lev Walkina28cbb92017-07-31 20:20:17 -07002228 range = asn1constraint_compute_OER_range(expr->Identifier, etype,
2229 expr->combined_constraints,
Lev Walkin98eabc12017-07-19 08:51:11 +04002230 ACT_EL_RANGE, 0, 0, 0);
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002231 if(emit_single_member_OER_constraint_value(arg, range)) {
Lev Walkin98eabc12017-07-19 08:51:11 +04002232 return -1;
2233 }
Lev Walkin4118ccf2017-08-02 10:37:31 -07002234 emit_single_member_OER_constraint_comment(arg, range, 0);
Lev Walkin98eabc12017-07-19 08:51:11 +04002235 asn1constraint_range_free(range);
2236
2237 OUT(",\n");
2238
Lev Walkin4118ccf2017-08-02 10:37:31 -07002239 /* .size */
Lev Walkina28cbb92017-07-31 20:20:17 -07002240 range = asn1constraint_compute_OER_range(expr->Identifier, etype,
2241 expr->combined_constraints,
Lev Walkin98eabc12017-07-19 08:51:11 +04002242 ACT_CT_SIZE, 0, 0, 0);
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002243 if(emit_single_member_OER_constraint_size(arg, range)) {
Lev Walkin98eabc12017-07-19 08:51:11 +04002244 return -1;
2245 }
Lev Walkin4118ccf2017-08-02 10:37:31 -07002246 emit_single_member_OER_constraint_comment(arg, range, "SIZE");
Lev Walkin98eabc12017-07-19 08:51:11 +04002247 asn1constraint_range_free(range);
2248
2249 INDENT(-1);
2250
2251 OUT("};\n");
2252
2253 REDIR(save_target);
2254
2255 return 0;
2256}
2257
2258static int
Lev Walkin4b5dae32006-10-09 12:27:44 +00002259emit_member_PER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx) {
Lev Walkin725883b2006-10-09 12:07:58 +00002260 int save_target = arg->target->target;
Lev Walkin59b176e2005-11-26 11:25:14 +00002261 asn1cnst_range_t *range;
2262 asn1p_expr_type_e etype;
2263
Lev Walkin07aaa342006-10-09 12:52:15 +00002264 etype = expr_get_type(arg, expr);
2265
Lev Walkin725883b2006-10-09 12:07:58 +00002266 if((arg->flags & A1C_GEN_PER)
2267 && (expr->constraints
Lev Walkin07aaa342006-10-09 12:52:15 +00002268 || etype == ASN_BASIC_ENUMERATED
2269 || etype == ASN_CONSTR_CHOICE)
Lev Walkin725883b2006-10-09 12:07:58 +00002270 ) {
2271 /* Fall through */
2272 } else {
2273 return 0;
2274 }
2275
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002276 if(expr->_type_referenced) {
2277 REDIR(OT_FUNC_DECLS);
2278
2279 OUT("extern asn_per_constraints_t "
2280 "asn_PER_%s_%s_constr_%d;\n",
2281 pfx, MKID(expr), expr->_type_unique_index);
2282 }
2283
Lev Walkin725883b2006-10-09 12:07:58 +00002284 REDIR(OT_CTDEFS);
2285
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002286 if(!(expr->_type_referenced)) OUT("static ");
2287 OUT("asn_per_constraints_t "
Lev Walkin1715b322013-03-28 04:02:13 -07002288 "asn_PER_%s_%s_constr_%d GCC_NOTUSED = {\n",
Lev Walkin4b5dae32006-10-09 12:27:44 +00002289 pfx, MKID(expr), expr->_type_unique_index);
Lev Walkin725883b2006-10-09 12:07:58 +00002290
Lev Walkin59b176e2005-11-26 11:25:14 +00002291 INDENT(+1);
2292
2293 /*
2294 * ENUMERATED and CHOICE are special.
2295 */
2296 if(etype == ASN_BASIC_ENUMERATED
2297 || etype == ASN_CONSTR_CHOICE) {
2298 asn1cnst_range_t tmprng;
2299 asn1p_expr_t *v;
2300 int extensible = 0;
2301 int eidx = -1;
2302
2303 expr = asn1f_find_terminal_type_ex(arg->asn, expr);
2304 assert(expr);
2305
2306 TQ_FOR(v, &(expr->members), next) {
2307 if(v->expr_type == A1TC_EXTENSIBLE) {
2308 extensible++;
2309 break;
2310 }
2311 eidx++;
2312 }
2313
2314 memset(&tmprng, 0, sizeof (tmprng));
2315 tmprng.extensible = extensible;
2316 if(eidx < 0) tmprng.empty_constraint = 1;
2317 tmprng.left.type = ARE_VALUE;
2318 tmprng.left.value = 0;
2319 tmprng.right.type = ARE_VALUE;
2320 tmprng.right.value = eidx < 0 ? 0 : eidx;
Lev Walkin725883b2006-10-09 12:07:58 +00002321 if(emit_single_member_PER_constraint(arg, &tmprng, 0, 0))
Lev Walkin59b176e2005-11-26 11:25:14 +00002322 return -1;
Lev Walkin729eb862006-09-21 01:50:13 +00002323 } else if(etype & ASN_STRING_KM_MASK) {
Lev Walkina28cbb92017-07-31 20:20:17 -07002324 range = asn1constraint_compute_PER_range(expr->Identifier, etype,
Lev Walkin729eb862006-09-21 01:50:13 +00002325 expr->combined_constraints, ACT_CT_FROM,
2326 0, 0, 0);
Lev Walkin725883b2006-10-09 12:07:58 +00002327 DEBUG("Emitting FROM constraint for %s", expr->Identifier);
Lev Walkin3a4689a2006-11-24 11:20:27 +00002328
2329 if((range->left.type == ARE_MIN && range->right.type == ARE_MAX)
2330 || range->not_PER_visible) {
2331 switch(etype) {
2332 case ASN_STRING_BMPString:
2333 range->left.type = ARE_VALUE;
2334 range->left.value = 0;
2335 range->right.type = ARE_VALUE;
2336 range->right.value = 65535;
2337 range->not_PER_visible = 0;
2338 range->extensible = 0;
2339 break;
2340 case ASN_STRING_UniversalString:
2341 OUT("{ APC_CONSTRAINED,\t32, 32,"
2342 " 0, 2147483647 }"
2343 " /* special case 1 */\n");
2344 goto avoid;
2345 default:
2346 break;
2347 }
2348 }
Lev Walkin725883b2006-10-09 12:07:58 +00002349 if(emit_single_member_PER_constraint(arg, range, 1, 0))
Lev Walkin729eb862006-09-21 01:50:13 +00002350 return -1;
Lev Walkin3a4689a2006-11-24 11:20:27 +00002351 avoid:
Lev Walkin729eb862006-09-21 01:50:13 +00002352 asn1constraint_range_free(range);
Lev Walkin59b176e2005-11-26 11:25:14 +00002353 } else {
Lev Walkina28cbb92017-07-31 20:20:17 -07002354 range = asn1constraint_compute_PER_range(expr->Identifier, etype,
Lev Walkin59b176e2005-11-26 11:25:14 +00002355 expr->combined_constraints, ACT_EL_RANGE,
2356 0, 0, 0);
Lev Walkin725883b2006-10-09 12:07:58 +00002357 if(emit_single_member_PER_constraint(arg, range, 0, 0))
Lev Walkin59b176e2005-11-26 11:25:14 +00002358 return -1;
2359 asn1constraint_range_free(range);
2360 }
2361 OUT(",\n");
2362
Lev Walkina28cbb92017-07-31 20:20:17 -07002363 range = asn1constraint_compute_PER_range(expr->Identifier, etype,
Lev Walkin59b176e2005-11-26 11:25:14 +00002364 expr->combined_constraints, ACT_CT_SIZE, 0, 0, 0);
Lev Walkin725883b2006-10-09 12:07:58 +00002365 if(emit_single_member_PER_constraint(arg, range, 0, "SIZE"))
Lev Walkin59b176e2005-11-26 11:25:14 +00002366 return -1;
2367 asn1constraint_range_free(range);
Lev Walkin725883b2006-10-09 12:07:58 +00002368 OUT(",\n");
2369
2370 if((etype & ASN_STRING_KM_MASK) && (expr->_mark & TM_PERFROMCT)) {
2371 int old_target = arg->target->target;
2372 REDIR(OT_CODE);
2373
2374 OUT("static int asn_PER_MAP_%s_%d_v2c(unsigned int value) {\n",
2375 MKID(expr), expr->_type_unique_index);
2376 OUT("\tif(value >= sizeof(permitted_alphabet_table_%d)/"
2377 "sizeof(permitted_alphabet_table_%d[0]))\n",
2378 expr->_type_unique_index,
2379 expr->_type_unique_index);
2380 OUT("\t\treturn -1;\n");
2381 OUT("\treturn permitted_alphabet_table_%d[value] - 1;\n",
2382 expr->_type_unique_index);
2383 OUT("}\n");
2384
2385 OUT("static int asn_PER_MAP_%s_%d_c2v(unsigned int code) {\n",
2386 MKID(expr), expr->_type_unique_index);
2387 OUT("\tif(code >= sizeof(permitted_alphabet_code2value_%d)/"
2388 "sizeof(permitted_alphabet_code2value_%d[0]))\n",
2389 expr->_type_unique_index,
2390 expr->_type_unique_index);
2391 OUT("\t\treturn -1;\n");
2392 OUT("\treturn permitted_alphabet_code2value_%d[code];\n",
2393 expr->_type_unique_index);
2394 OUT("}\n");
2395
2396 REDIR(old_target);
2397
2398 OUT("asn_PER_MAP_%s_%d_v2c,\t/* Value to PER code map */\n",
2399 MKID(expr), expr->_type_unique_index);
2400 OUT("asn_PER_MAP_%s_%d_c2v\t/* PER code to value map */\n",
2401 MKID(expr), expr->_type_unique_index);
2402 } else if(etype & ASN_STRING_KM_MASK) {
2403 DEBUG("No PER value map necessary for %s", MKID(expr));
2404 OUT("0, 0\t/* No PER character map necessary */\n");
2405 } else {
2406 OUT("0, 0\t/* No PER value map */\n");
2407 }
Lev Walkin59b176e2005-11-26 11:25:14 +00002408
2409 INDENT(-1);
2410
Lev Walkin725883b2006-10-09 12:07:58 +00002411 OUT("};\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002412
Lev Walkin725883b2006-10-09 12:07:58 +00002413 REDIR(save_target);
Lev Walkin59b176e2005-11-26 11:25:14 +00002414
2415 return 0;
2416}
2417
2418static int
Lev Walkin8032f7a2007-06-27 01:54:57 +00002419safe_string(const uint8_t *buf, int size) {
2420 const uint8_t *end = buf + size;
2421 for(; buf < end; buf++) {
2422 int ch = *buf;
2423 if((ch < 0x20 || ch > 0x7e) || ch == '"')
2424 return 0;
2425 }
2426 return 1;
2427}
2428
2429static void
2430emit_default_value(arg_t *arg, asn1p_value_t *v) {
2431
2432 OUT("static uint8_t defv[] = ");
2433 assert(v->type == ATV_STRING);
2434
2435 if(safe_string(v->value.string.buf, v->value.string.size)) {
2436 OUT("\"%s\";\n", v->value.string.buf);
2437 } else {
2438 uint8_t *b = v->value.string.buf;
2439 uint8_t *e = v->value.string.size + b;
2440 OUT("{ ");
2441 for(;b < e; b++)
2442 OUT("0x%02x, ", *b);
2443 OUT("0 };\n");
2444 }
2445}
2446
2447static int
Lev Walkin59b176e2005-11-26 11:25:14 +00002448try_inline_default(arg_t *arg, asn1p_expr_t *expr, int out) {
2449 int save_target = arg->target->target;
2450 asn1p_expr_type_e etype = expr_get_type(arg, expr);
2451 int fits_long = 0;
2452
2453 switch(etype) {
2454 case ASN_BASIC_BOOLEAN:
2455 fits_long = 1;
2456 case ASN_BASIC_INTEGER:
2457 case ASN_BASIC_ENUMERATED:
2458 if(expr->marker.default_value == NULL
2459 || expr->marker.default_value->type != ATV_INTEGER)
2460 break;
2461 if(!fits_long)
2462 fits_long = asn1c_type_fits_long(arg, expr)!=FL_NOTFIT;
2463 if(fits_long && !expr->marker.default_value->value.v_integer)
2464 expr->marker.flags &= ~EM_INDIRECT;
Lev Walkin8032f7a2007-06-27 01:54:57 +00002465 if(!out) {
Lev Walkinda997b12017-08-04 01:38:41 -07002466 OUT("asn_DFL_%d_set_%s,",
Lev Walkin8032f7a2007-06-27 01:54:57 +00002467 expr->_type_unique_index,
Lev Walkinda997b12017-08-04 01:38:41 -07002468 asn1p_itoa(expr->marker.default_value->value.v_integer));
2469 OUT("\t/* DEFAULT %s */\n",
2470 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin8032f7a2007-06-27 01:54:57 +00002471 return 1;
2472 }
Lev Walkin59b176e2005-11-26 11:25:14 +00002473 REDIR(OT_STAT_DEFS);
Lev Walkinda997b12017-08-04 01:38:41 -07002474 OUT("static int asn_DFL_%d_set_%s(int set_value, void **sptr) {\n",
Lev Walkin59b176e2005-11-26 11:25:14 +00002475 expr->_type_unique_index,
Lev Walkinda997b12017-08-04 01:38:41 -07002476 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin59b176e2005-11-26 11:25:14 +00002477 INDENT(+1);
2478 OUT("%s *st = *sptr;\n", asn1c_type_name(arg, expr, TNF_CTYPE));
2479 OUT("\n");
2480 OUT("if(!st) {\n");
Lev Walkin1dc85292006-08-18 01:32:26 +00002481 OUT("\tif(!set_value) return -1;\t/* Not a default value */\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002482 OUT("\tst = (*sptr = CALLOC(1, sizeof(*st)));\n");
2483 OUT("\tif(!st) return -1;\n");
2484 OUT("}\n");
2485 OUT("\n");
Lev Walkin1dc85292006-08-18 01:32:26 +00002486 OUT("if(set_value) {\n");
2487 INDENT(+1);
Lev Walkinda997b12017-08-04 01:38:41 -07002488 OUT("/* Install default value %s */\n",
2489 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin59b176e2005-11-26 11:25:14 +00002490 if(fits_long) {
Lev Walkin63b41262007-11-06 01:48:46 +00002491 OUT("*st = ");
2492 OINT(expr->marker.default_value->value.v_integer);
2493 OUT(";\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002494 OUT("return 0;\n");
2495 } else {
Lev Walkin63b41262007-11-06 01:48:46 +00002496 OUT("return asn_long2INTEGER(st, ");
2497 OINT(expr->marker.default_value->value.v_integer);
2498 OUT(");\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002499 }
2500 INDENT(-1);
Lev Walkin1dc85292006-08-18 01:32:26 +00002501 OUT("} else {\n");
2502 INDENT(+1);
Lev Walkinda997b12017-08-04 01:38:41 -07002503 OUT("/* Test default value %s */\n",
2504 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin1dc85292006-08-18 01:32:26 +00002505 if(fits_long) {
Lev Walkinda997b12017-08-04 01:38:41 -07002506 OUT("return (*st == %s);\n",
2507 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin1dc85292006-08-18 01:32:26 +00002508 } else {
2509 OUT("long value;\n");
2510 OUT("if(asn_INTEGER2long(st, &value))\n");
2511 OUT("\treturn -1;\n");
Lev Walkinda997b12017-08-04 01:38:41 -07002512 OUT("return (value == %s);\n",
2513 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin1dc85292006-08-18 01:32:26 +00002514 }
2515 INDENT(-1);
2516 OUT("}\n");
2517 INDENT(-1);
Lev Walkin59b176e2005-11-26 11:25:14 +00002518 OUT("}\n");
2519 REDIR(save_target);
2520 return 1;
2521 case ASN_BASIC_NULL:
2522 //expr->marker.flags &= ~EM_INDIRECT;
2523 return 0;
2524 default:
Lev Walkin8032f7a2007-06-27 01:54:57 +00002525 if(etype & ASN_STRING_KM_MASK) {
2526 if(expr->marker.default_value == NULL
2527 || expr->marker.default_value->type != ATV_STRING)
2528 break;
2529 if(!out) {
2530 OUT("asn_DFL_%d_set,\t/* DEFAULT \"%s\" */\n",
2531 expr->_type_unique_index,
2532 expr->marker.default_value->value.string.buf);
2533 return 1;
2534 }
2535 REDIR(OT_STAT_DEFS);
2536 OUT("static int asn_DFL_%d_set(int set_value, void **sptr) {\n", expr->_type_unique_index);
2537 INDENT(+1);
2538 emit_default_value(arg, expr->marker.default_value);
2539 OUT("%s *st = *sptr;\n", asn1c_type_name(arg, expr, TNF_CTYPE));
2540 OUT("\n");
2541 OUT("if(!st) {\n");
2542 OUT("\tif(!set_value) return -1;\t/* Not a default value */\n");
2543 OUT("\tst = (*sptr = CALLOC(1, sizeof(*st)));\n");
2544 OUT("\tif(!st) return -1;\n");
2545 OUT("}\n");
2546 OUT("\n");
2547 OUT("if(set_value) {\n");
2548 INDENT(+1);
2549 OUT("uint8_t *ptr = MALLOC(sizeof(defv));\n");
2550 OUT("if(!ptr) return -1;\n");
2551 OUT("memcpy(ptr, &defv, sizeof(defv));\n");
2552 OUT("FREEMEM(st->buf);\n");
2553 OUT("st->buf = ptr;\n");
2554 OUT("st->size = sizeof(defv) - 1;\n");
2555 OUT("return 0;\n");
2556 INDENT(-1);
2557 OUT("} else {\n");
2558 INDENT(+1);
2559 OUT("if(st->size != (sizeof(defv) - 1)\n");
2560 OUT("|| memcmp(st->buf, &defv, sizeof(defv) - 1))\n");
2561 OUT("\treturn 0;\n");
2562 OUT("return 1;\n");
2563 INDENT(-1);
2564 OUT("}\n"); OUT("\n");
2565 INDENT(-1);
2566 OUT("}\n");
2567 REDIR(save_target);
2568 return 1;
2569 }
2570 break;
Lev Walkin59b176e2005-11-26 11:25:14 +00002571 }
2572 return 0;
2573}
2574
Lev Walkin59004fa2004-08-20 13:37:01 +00002575static int
Lev Walkin59964be2004-08-25 02:03:12 +00002576emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin59004fa2004-08-20 13:37:01 +00002577 int save_target;
2578 arg_t tmp_arg;
Lev Walkinb9189732004-09-10 09:37:12 +00002579 struct asn1p_type_tag_s outmost_tag_s;
2580 struct asn1p_type_tag_s *outmost_tag;
Lev Walkine0b56e02005-02-25 12:10:27 +00002581 int complex_contents;
Lev Walkin59004fa2004-08-20 13:37:01 +00002582 char *p;
2583
Lev Walkinb9189732004-09-10 09:37:12 +00002584 if(asn1f_fetch_outmost_tag(arg->asn,
Lev Walkin59b176e2005-11-26 11:25:14 +00002585 expr->module, expr, &outmost_tag_s,
2586 AFT_IMAGINARY_ANY)) {
Lev Walkinb9189732004-09-10 09:37:12 +00002587 outmost_tag = 0;
2588 } else {
2589 outmost_tag = &outmost_tag_s;
2590 }
2591
Lev Walkin59004fa2004-08-20 13:37:01 +00002592 OUT("{ ");
Lev Walkinb9189732004-09-10 09:37:12 +00002593
2594 if(outmost_tag && outmost_tag->tag_value == -1)
2595 OUT("ATF_OPEN_TYPE | ");
Lev Walkinc8285712005-03-04 22:18:20 +00002596 OUT("%s, ",
2597 (expr->marker.flags & EM_INDIRECT)?"ATF_POINTER":"ATF_NOFLAGS");
Lev Walkinb85a8132005-08-18 13:38:19 +00002598 if((expr->marker.flags & EM_OMITABLE) == EM_OMITABLE) {
Lev Walkin59004fa2004-08-20 13:37:01 +00002599 asn1p_expr_t *tv;
2600 int opts = 0;
Lev Walkinb85a8132005-08-18 13:38:19 +00002601 for(tv = expr;
2602 tv && (tv->marker.flags & EM_OMITABLE) == EM_OMITABLE;
Lev Walkin59004fa2004-08-20 13:37:01 +00002603 tv = TQ_NEXT(tv, next), opts++) {
2604 if(tv->expr_type == A1TC_EXTENSIBLE)
2605 opts--;
2606 }
2607 OUT("%d, ", opts);
2608 } else {
2609 OUT("0, ");
2610 }
Lev Walkina9cc46e2004-09-22 16:06:28 +00002611 if(expr->_anonymous_type) {
2612 assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
2613 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
2614 OUT("0,\n");
2615 } else {
Lev Walkin21d00002005-03-04 08:48:53 +00002616 OUT("offsetof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +00002617 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +00002618 OUT(", ");
Lev Walkin59004fa2004-08-20 13:37:01 +00002619 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
2620 && (!UNNAMED_UNIONS)) OUT("choice.");
Lev Walkina00d6b32006-03-21 03:40:38 +00002621 OUT("%s),\n", MKID_safe(expr));
Lev Walkin59004fa2004-08-20 13:37:01 +00002622 }
2623 INDENT(+1);
2624 if(C99_MODE) OUT(".tag = ");
Lev Walkinb9189732004-09-10 09:37:12 +00002625 if(outmost_tag) {
2626 if(outmost_tag->tag_value == -1)
2627 OUT("-1 /* Ambiguous tag (ANY?) */");
2628 else
2629 _print_tag(arg, outmost_tag);
Lev Walkinc3e29402004-09-10 06:07:18 +00002630 } else {
Lev Walkinb9189732004-09-10 09:37:12 +00002631 OUT("-1 /* Ambiguous tag (CHOICE?) */");
Lev Walkinc3e29402004-09-10 06:07:18 +00002632 }
Lev Walkinb9189732004-09-10 09:37:12 +00002633
Lev Walkin59004fa2004-08-20 13:37:01 +00002634 OUT(",\n");
2635 if(C99_MODE) OUT(".tag_mode = ");
Lev Walkin9ab21b82006-10-19 02:46:01 +00002636 if((!(expr->expr_type & ASN_CONSTR_MASK)
2637 || expr->expr_type == ASN_CONSTR_CHOICE)
2638 && expr->tag.tag_class) {
Lev Walkin59004fa2004-08-20 13:37:01 +00002639 if(expr->tag.tag_mode == TM_IMPLICIT)
2640 OUT("-1,\t/* IMPLICIT tag at current level */\n");
2641 else
2642 OUT("+1,\t/* EXPLICIT tag at current level */\n");
2643 } else {
2644 OUT("0,\n");
2645 }
Lev Walkine0b56e02005-02-25 12:10:27 +00002646
2647 complex_contents =
2648 (expr->expr_type & ASN_CONSTR_MASK)
2649 || expr->expr_type == ASN_BASIC_ENUMERATED
Lev Walkin8ecf9db2005-03-03 21:28:12 +00002650 || (0 /* -- prohibited by X.693:8.3.4 */
2651 && expr->expr_type == ASN_BASIC_INTEGER
Lev Walkin8bb57a22007-12-03 13:41:36 +00002652 && expr_elements_count(arg, expr))
2653 || (expr->expr_type == ASN_BASIC_INTEGER
2654 && asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN);
Lev Walkin59004fa2004-08-20 13:37:01 +00002655 if(C99_MODE) OUT(".type = ");
Lev Walkinae7bf3f2005-08-29 10:31:14 +00002656 OUT("&asn_DEF_");
Lev Walkin21d00002005-03-04 08:48:53 +00002657 if(complex_contents) {
Lev Walkina00d6b32006-03-21 03:40:38 +00002658 OUT("%s", MKID(expr));
Lev Walkin21d00002005-03-04 08:48:53 +00002659 if(!(arg->flags & A1C_ALL_DEFS_GLOBAL))
2660 OUT("_%d", expr->_type_unique_index);
Lev Walkin08079b02004-08-22 03:25:24 +00002661 } else {
Lev Walkin21d00002005-03-04 08:48:53 +00002662 OUT("%s", asn1c_type_name(arg, expr, TNF_SAFE));
Lev Walkin08079b02004-08-22 03:25:24 +00002663 }
Lev Walkin21d00002005-03-04 08:48:53 +00002664 OUT(",\n");
Lev Walkin59004fa2004-08-20 13:37:01 +00002665 if(C99_MODE) OUT(".memb_constraints = ");
2666 if(expr->constraints) {
Lev Walkin8de2ab22004-09-26 13:11:31 +00002667 if(arg->flags & A1C_NO_CONSTRAINTS) {
2668 OUT("0,\t/* No check because of -fno-constraints */\n");
2669 } else {
Lev Walkina00d6b32006-03-21 03:40:38 +00002670 char *id = MKID(expr);
Lev Walkin8de2ab22004-09-26 13:11:31 +00002671 if(expr->_anonymous_type
Lev Walkin152a91e2005-02-14 20:41:29 +00002672 && !strcmp(expr->Identifier, "Member"))
Lev Walkin8de2ab22004-09-26 13:11:31 +00002673 id = asn1c_type_name(arg, expr, TNF_SAFE);
Lev Walkin59b176e2005-11-26 11:25:14 +00002674 OUT("memb_%s_constraint_%d,\n", id,
Lev Walkin21d00002005-03-04 08:48:53 +00002675 arg->expr->_type_unique_index);
Lev Walkin8de2ab22004-09-26 13:11:31 +00002676 }
Lev Walkin59004fa2004-08-20 13:37:01 +00002677 } else {
Lev Walkinb7bfd1a2005-01-17 12:16:58 +00002678 OUT("0,\t/* Defer constraints checking to the member type */\n");
Lev Walkin59004fa2004-08-20 13:37:01 +00002679 }
Lev Walkinb33425f2017-07-14 14:59:52 +04002680 if(C99_MODE) OUT(".oer_constraints = ");
2681 if(arg->flags & A1C_GEN_OER) {
2682 if(expr->constraints) {
2683 OUT("&asn_OER_memb_%s_constr_%d,\n",
2684 MKID(expr),
2685 expr->_type_unique_index);
2686 } else {
2687 OUT("0,\t/* No OER visible constraints */\n");
2688 }
2689 } else {
2690 OUT("0,\t/* OER is not compiled, use -gen-OER */\n");
2691 }
Lev Walkin59b176e2005-11-26 11:25:14 +00002692 if(C99_MODE) OUT(".per_constraints = ");
2693 if(arg->flags & A1C_GEN_PER) {
Lev Walkin07aaa342006-10-09 12:52:15 +00002694 if(expr->constraints) {
Lev Walkin4b5dae32006-10-09 12:27:44 +00002695 OUT("&asn_PER_memb_%s_constr_%d,\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00002696 MKID(expr),
Lev Walkin59b176e2005-11-26 11:25:14 +00002697 expr->_type_unique_index);
2698 } else {
2699 OUT("0,\t/* No PER visible constraints */\n");
2700 }
Lev Walkin152a91e2005-02-14 20:41:29 +00002701 } else {
Lev Walkin59b176e2005-11-26 11:25:14 +00002702 OUT("0,\t/* PER is not compiled, use -gen-PER */\n");
2703 }
2704 if(C99_MODE) OUT(".default_value = ");
2705 if(try_inline_default(arg, expr, 0)) {
Lev Walkin59b176e2005-11-26 11:25:14 +00002706 } else {
2707 OUT("0,\n");
2708 }
2709 if(C99_MODE) OUT(".name = ");
2710 if(expr->_anonymous_type && !strcmp(expr->Identifier, "Member")) {
2711 OUT("\"\"\n");
2712 } else {
2713 OUT("\"%s\"\n", expr->Identifier);
Lev Walkin152a91e2005-02-14 20:41:29 +00002714 }
Lev Walkin59004fa2004-08-20 13:37:01 +00002715 OUT("},\n");
2716 INDENT(-1);
2717
Lev Walkin8de2ab22004-09-26 13:11:31 +00002718 if(!expr->constraints || (arg->flags & A1C_NO_CONSTRAINTS))
Lev Walkin59004fa2004-08-20 13:37:01 +00002719 return 0;
2720
2721 save_target = arg->target->target;
2722 REDIR(OT_CODE);
2723
Lev Walkin152a91e2005-02-14 20:41:29 +00002724 if(expr->_anonymous_type && !strcmp(expr->Identifier, "Member"))
Lev Walkin59004fa2004-08-20 13:37:01 +00002725 p = asn1c_type_name(arg, expr, TNF_SAFE);
Lev Walkina9cc46e2004-09-22 16:06:28 +00002726 else
Lev Walkina00d6b32006-03-21 03:40:38 +00002727 p = MKID(expr);
Lev Walkin59004fa2004-08-20 13:37:01 +00002728 OUT("static int\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002729 OUT("memb_%s_constraint_%d(asn_TYPE_descriptor_t *td, const void *sptr,\n", p, arg->expr->_type_unique_index);
Lev Walkin59004fa2004-08-20 13:37:01 +00002730 INDENT(+1);
Lev Walkin1eded352006-07-13 11:19:01 +00002731 OUT("\t\tasn_app_constraint_failed_f *ctfailcb, void *app_key) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +00002732 tmp_arg = *arg;
2733 tmp_arg.expr = expr;
Lev Walkin725883b2006-10-09 12:07:58 +00002734 DEBUG("member constraint checking code for %s", p);
Lev Walkin59004fa2004-08-20 13:37:01 +00002735 if(asn1c_emit_constraint_checking_code(&tmp_arg) == 1) {
Lev Walkin8de2ab22004-09-26 13:11:31 +00002736 OUT("return td->check_constraints"
Lev Walkin1eded352006-07-13 11:19:01 +00002737 "(td, sptr, ctfailcb, app_key);\n");
Lev Walkin59004fa2004-08-20 13:37:01 +00002738 }
2739 INDENT(-1);
2740 OUT("}\n");
2741 OUT("\n");
2742
Lev Walkin98eabc12017-07-19 08:51:11 +04002743 if(emit_member_OER_constraints(arg, expr, "memb"))
2744 return -1;
2745
Lev Walkin4b5dae32006-10-09 12:27:44 +00002746 if(emit_member_PER_constraints(arg, expr, "memb"))
Lev Walkin725883b2006-10-09 12:07:58 +00002747 return -1;
2748
Lev Walkin59004fa2004-08-20 13:37:01 +00002749 REDIR(save_target);
2750
2751 return 0;
2752}
Lev Walkin59964be2004-08-25 02:03:12 +00002753
Lev Walkindc06f6b2004-10-20 15:50:55 +00002754/*
2755 * Generate "asn_DEF_XXX" type definition.
2756 */
Lev Walkin59964be2004-08-25 02:03:12 +00002757static int
Lev Walkin8de2ab22004-09-26 13:11:31 +00002758emit_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) {
Lev Walkin8c2ca0b2006-09-17 06:31:08 +00002759 asn1p_expr_t *terminal;
Lev Walkin21d00002005-03-04 08:48:53 +00002760 int using_type_name = 0;
Lev Walkina00d6b32006-03-21 03:40:38 +00002761 char *p = MKID(expr);
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002762 char *p2 = (char *)0;
Lev Walkin59b176e2005-11-26 11:25:14 +00002763
Lev Walkin8c2ca0b2006-09-17 06:31:08 +00002764 terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
2765
Lev Walkin01582a72017-07-26 18:47:08 -07002766 if(emit_member_OER_constraints(arg, expr, "type"))
2767 return -1;
2768
Lev Walkin4b5dae32006-10-09 12:27:44 +00002769 if(emit_member_PER_constraints(arg, expr, "type"))
Lev Walkin725883b2006-10-09 12:07:58 +00002770 return -1;
Lev Walkin59964be2004-08-25 02:03:12 +00002771
Lev Walkindd32b592004-09-06 08:07:29 +00002772 if(HIDE_INNER_DEFS)
2773 OUT("static /* Use -fall-defs-global to expose */\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002774 OUT("asn_TYPE_descriptor_t asn_DEF_%s", p);
Lev Walkin21d00002005-03-04 08:48:53 +00002775 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
2776 OUT(" = {\n");
Lev Walkin188ed2c2004-09-13 08:31:01 +00002777 INDENT(+1);
Lev Walkin59b176e2005-11-26 11:25:14 +00002778
2779 if(expr->_anonymous_type) {
2780 p = ASN_EXPR_TYPE2STR(expr->expr_type);
2781 OUT("\"%s\",\n", p?p:"");
Lev Walkina00d6b32006-03-21 03:40:38 +00002782 OUT("\"%s\",\n",
2783 p ? asn1c_make_identifier(AMI_CHECK_RESERVED,
2784 0, p, 0) : "");
Lev Walkin59b176e2005-11-26 11:25:14 +00002785 } else {
2786 OUT("\"%s\",\n", expr->Identifier);
2787 OUT("\"%s\",\n", expr->Identifier);
2788 }
Lev Walkin59964be2004-08-25 02:03:12 +00002789
2790 if(expr->expr_type & ASN_CONSTR_MASK) {
Lev Walkin21d00002005-03-04 08:48:53 +00002791 using_type_name = 1;
Lev Walkin59964be2004-08-25 02:03:12 +00002792 p = asn1c_type_name(arg, arg->expr, TNF_SAFE);
Lev Walkin59b176e2005-11-26 11:25:14 +00002793 } else {
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002794 if (expr->expr_type == A1TC_REFERENCE) {
2795 p2 = strdup(asn1c_type_name(arg, terminal, TNF_SAFE));
2796 } else {
2797 p2 = strdup(asn1c_type_name(arg, expr, TNF_SAFE));
2798 }
Lev Walkina00d6b32006-03-21 03:40:38 +00002799 p = MKID(expr);
Lev Walkin59964be2004-08-25 02:03:12 +00002800 }
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002801 if (!p2)
2802 p2 = strdup(p);
Lev Walkin59964be2004-08-25 02:03:12 +00002803
Lev Walkin21d00002005-03-04 08:48:53 +00002804#define FUNCREF(foo) do { \
2805 OUT("%s", p); \
2806 if(HIDE_INNER_DEFS && !using_type_name) \
2807 OUT("_%d", expr->_type_unique_index); \
2808 OUT("_" #foo ",\n"); \
2809} while(0)
2810
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002811#define FUNCREF2(foo) \
2812do { \
2813 OUT("%s", p2); \
2814 OUT("_" #foo ",\n"); \
2815} while(0)
2816
2817 FUNCREF2(free);
2818 FUNCREF2(print);
2819 if (!expr->combined_constraints)
2820 FUNCREF2(constraint);
2821 else
2822 FUNCREF(constraint);
2823 FUNCREF2(decode_ber);
2824 FUNCREF2(encode_der);
2825 FUNCREF2(decode_xer);
2826 FUNCREF2(encode_xer);
Lev Walkinb33425f2017-07-14 14:59:52 +04002827
2828 if(arg->flags & A1C_GEN_OER) {
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002829 FUNCREF2(decode_oer);
2830 FUNCREF2(encode_oer);
Lev Walkinb33425f2017-07-14 14:59:52 +04002831 } else {
2832 OUT("0, 0,\t/* No OER support, "
2833 "use \"-gen-OER\" to enable */\n");
2834 }
Lev Walkin1dc85292006-08-18 01:32:26 +00002835 if(arg->flags & A1C_GEN_PER) {
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002836 FUNCREF2(decode_uper);
2837 FUNCREF2(encode_uper);
Lev Walkin1dc85292006-08-18 01:32:26 +00002838 } else {
2839 OUT("0, 0,\t/* No PER support, "
2840 "use \"-gen-PER\" to enable */\n");
2841 }
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002842 if (p2) free(p2);
Lev Walkin59964be2004-08-25 02:03:12 +00002843
Lev Walkin8c2ca0b2006-09-17 06:31:08 +00002844 if(!terminal || terminal->expr_type == ASN_CONSTR_CHOICE) {
2845 //if(expr->expr_type == ASN_CONSTR_CHOICE) {
Lev Walkin59964be2004-08-25 02:03:12 +00002846 OUT("CHOICE_outmost_tag,\n");
2847 } else {
2848 OUT("0,\t/* Use generic outmost tag fetcher */\n");
2849 }
2850
Lev Walkina00d6b32006-03-21 03:40:38 +00002851 p = MKID(expr);
Lev Walkin59964be2004-08-25 02:03:12 +00002852 if(tags_count) {
Lev Walkin59b176e2005-11-26 11:25:14 +00002853 OUT("asn_DEF_%s_tags_%d,\n",
Lev Walkin21d00002005-03-04 08:48:53 +00002854 p, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00002855 OUT("sizeof(asn_DEF_%s_tags_%d)\n",
Lev Walkin21d00002005-03-04 08:48:53 +00002856 p, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00002857 OUT("\t/sizeof(asn_DEF_%s_tags_%d[0])",
Lev Walkin21d00002005-03-04 08:48:53 +00002858 p, expr->_type_unique_index);
Lev Walkin188ed2c2004-09-13 08:31:01 +00002859 if(tv_mode == _TVM_SUBSET
2860 && tags_count != all_tags_count)
2861 OUT(" - %d", all_tags_count - tags_count);
2862 OUT(", /* %d */\n", tags_count);
Lev Walkin59964be2004-08-25 02:03:12 +00002863 } else {
Lev Walkin188ed2c2004-09-13 08:31:01 +00002864 OUT("0,\t/* No effective tags (pointer) */\n");
2865 OUT("0,\t/* No effective tags (count) */\n");
2866 }
2867
2868 if(all_tags_count && tv_mode == _TVM_DIFFERENT) {
Lev Walkin59b176e2005-11-26 11:25:14 +00002869 OUT("asn_DEF_%s_all_tags_%d,\n",
Lev Walkin21d00002005-03-04 08:48:53 +00002870 p, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00002871 OUT("sizeof(asn_DEF_%s_all_tags_%d)\n",
Lev Walkin21d00002005-03-04 08:48:53 +00002872 p, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00002873 OUT("\t/sizeof(asn_DEF_%s_all_tags_%d[0]), /* %d */\n",
Lev Walkin21d00002005-03-04 08:48:53 +00002874 p, expr->_type_unique_index, all_tags_count);
Lev Walkin188ed2c2004-09-13 08:31:01 +00002875 } else if(all_tags_count) {
Lev Walkin59b176e2005-11-26 11:25:14 +00002876 OUT("asn_DEF_%s_tags_%d,\t/* Same as above */\n",
Lev Walkin21d00002005-03-04 08:48:53 +00002877 p, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00002878 OUT("sizeof(asn_DEF_%s_tags_%d)\n",
Lev Walkin21d00002005-03-04 08:48:53 +00002879 p, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00002880 OUT("\t/sizeof(asn_DEF_%s_tags_%d[0]), /* %d */\n",
Lev Walkin21d00002005-03-04 08:48:53 +00002881 p, expr->_type_unique_index, all_tags_count);
Lev Walkin188ed2c2004-09-13 08:31:01 +00002882 } else {
2883 OUT("0,\t/* No tags (pointer) */\n");
2884 OUT("0,\t/* No tags (count) */\n");
Lev Walkin59964be2004-08-25 02:03:12 +00002885 }
2886
Lev Walkinb33425f2017-07-14 14:59:52 +04002887 if(arg->flags & A1C_GEN_OER) {
2888 if(expr->constraints
2889 || expr->expr_type == ASN_BASIC_ENUMERATED
2890 || expr->expr_type == ASN_CONSTR_CHOICE) {
2891 OUT("&asn_OER_type_%s_constr_%d,\n",
2892 p, expr->_type_unique_index);
2893 } else {
2894 OUT("0,\t/* No OER visible constraints */\n");
2895 }
2896 } else {
2897 OUT("0,\t/* No OER visible constraints */\n");
2898 }
2899
Lev Walkin59b176e2005-11-26 11:25:14 +00002900 if(arg->flags & A1C_GEN_PER) {
2901 if(expr->constraints
2902 || expr->expr_type == ASN_BASIC_ENUMERATED
2903 || expr->expr_type == ASN_CONSTR_CHOICE) {
Lev Walkin4b5dae32006-10-09 12:27:44 +00002904 OUT("&asn_PER_type_%s_constr_%d,\n",
Lev Walkin59b176e2005-11-26 11:25:14 +00002905 p, expr->_type_unique_index);
2906 } else {
2907 OUT("0,\t/* No PER visible constraints */\n");
2908 }
2909 } else {
2910 OUT("0,\t/* No PER visible constraints */\n");
2911 }
2912
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002913 if(elements_count ||
2914 ((expr->expr_type == A1TC_REFERENCE) &&
2915 (terminal->expr_type & ASN_CONSTR_MASK) &&
2916 expr_elements_count(arg, terminal))) {
2917
2918 if (expr->expr_type == A1TC_REFERENCE) {
2919 OUT("asn_MBR_%s_%d,\n", MKID(terminal), terminal->_type_unique_index);
2920
2921 if(terminal->expr_type == ASN_CONSTR_SEQUENCE_OF
2922 || terminal->expr_type == ASN_CONSTR_SET_OF) {
2923 OUT("%d,\t/* Single element */\n",
2924 expr_elements_count(arg, terminal));
2925 assert(expr_elements_count(arg, terminal) == 1);
2926 } else {
2927 OUT("%d,\t/* Elements count */\n",
2928 expr_elements_count(arg, terminal));
2929 }
Lev Walkin59964be2004-08-25 02:03:12 +00002930 } else {
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002931 OUT("asn_MBR_%s_%d,\n", p, expr->_type_unique_index);
2932
2933 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF
2934 || expr->expr_type == ASN_CONSTR_SET_OF) {
2935 OUT("%d,\t/* Single element */\n",
2936 elements_count);
2937 assert(elements_count == 1);
2938 } else {
2939 OUT("%d,\t/* Elements count */\n",
2940 elements_count);
2941 }
Lev Walkin59964be2004-08-25 02:03:12 +00002942 }
2943 } else {
Lev Walkin59964be2004-08-25 02:03:12 +00002944 if(expr_elements_count(arg, expr))
2945 OUT("0, 0,\t/* Defined elsewhere */\n");
2946 else
2947 OUT("0, 0,\t/* No members */\n");
2948 }
2949
2950 switch(spec) {
2951 case ETD_NO_SPECIFICS:
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002952 if ((expr->expr_type == A1TC_REFERENCE) &&
2953 ((terminal->expr_type & ASN_CONSTR_MASK) ||
2954 (terminal->expr_type == ASN_BASIC_ENUMERATED) ||
2955 ((terminal->expr_type == ASN_BASIC_INTEGER) &&
2956 (asn1c_type_fits_long(arg, terminal) == FL_FITS_UNSIGN)))) {
2957 OUT("&asn_SPC_%s_specs_%d\t/* Additional specs */\n", MKID(terminal), terminal->_type_unique_index);
2958 } else if ((expr->expr_type == ASN_TYPE_ANY) ||
2959 (expr->expr_type == ASN_BASIC_BIT_STRING) ||
2960 (expr->expr_type == ASN_STRING_BMPString) ||
2961 (expr->expr_type == ASN_BASIC_OCTET_STRING) ||
2962 (expr->expr_type == ASN_STRING_UniversalString)) {
2963 OUT("&asn_SPC_%s_specs\t/* Additional specs */\n", asn1c_type_name(arg, expr, TNF_SAFE));
2964 } else if ((expr->expr_type == A1TC_REFERENCE) &&
2965 ((terminal->expr_type == ASN_TYPE_ANY) ||
2966 (terminal->expr_type == ASN_BASIC_BIT_STRING) ||
2967 (terminal->expr_type == ASN_STRING_BMPString) ||
2968 (terminal->expr_type == ASN_BASIC_OCTET_STRING) ||
2969 (terminal->expr_type == ASN_STRING_UniversalString))) {
2970 OUT("&asn_SPC_%s_specs\t/* Additional specs */\n", asn1c_type_name(arg, terminal, TNF_SAFE));
2971 } else {
2972 OUT("0\t/* No specifics */\n");
2973 }
Lev Walkin59964be2004-08-25 02:03:12 +00002974 break;
2975 case ETD_HAS_SPECIFICS:
Lev Walkin59b176e2005-11-26 11:25:14 +00002976 OUT("&asn_SPC_%s_specs_%d\t/* Additional specs */\n",
Lev Walkin21d00002005-03-04 08:48:53 +00002977 p, expr->_type_unique_index);
Lev Walkin59964be2004-08-25 02:03:12 +00002978 }
Lev Walkin188ed2c2004-09-13 08:31:01 +00002979 INDENT(-1);
Lev Walkin59964be2004-08-25 02:03:12 +00002980 OUT("};\n");
2981 OUT("\n");
Lev Walkin97298782004-08-26 06:20:34 +00002982
2983 return 0;
Lev Walkin59964be2004-08-25 02:03:12 +00002984}
Lev Walkincc93b0f2004-09-10 09:18:20 +00002985
Lev Walkina9cc46e2004-09-22 16:06:28 +00002986static int
2987expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkind1bfea62005-11-08 03:06:16 +00002988 /*
2989 * X.680, 25.5, Table 5
2990 */
Lev Walkin59b176e2005-11-26 11:25:14 +00002991 switch(expr_get_type(arg, expr)) {
Lev Walkina9cc46e2004-09-22 16:06:28 +00002992 case ASN_BASIC_BOOLEAN:
2993 case ASN_BASIC_ENUMERATED:
2994 case ASN_BASIC_NULL:
2995 return 1;
Lev Walkind1bfea62005-11-08 03:06:16 +00002996 case ASN_CONSTR_CHOICE:
2997 return 2;
Lev Walkina9cc46e2004-09-22 16:06:28 +00002998 default:
2999 return 0;
3000 }
3001}
Lev Walkin801fabc2005-01-28 12:18:50 +00003002
3003static int
Lev Walkin0f5d74c2005-08-14 15:03:31 +00003004out_name_chain(arg_t *arg, enum onc_flags onc_flags) {
Lev Walkin801fabc2005-01-28 12:18:50 +00003005 asn1p_expr_t *expr = arg->expr;
3006 char *id;
3007
3008 assert(expr->Identifier);
3009
Lev Walkin0f5d74c2005-08-14 15:03:31 +00003010 if((arg->flags & A1C_COMPOUND_NAMES
3011 || onc_flags & ONC_force_compound_name)
Lev Walkin21d00002005-03-04 08:48:53 +00003012 && ((expr->expr_type & ASN_CONSTR_MASK)
3013 || expr->expr_type == ASN_BASIC_ENUMERATED
Lev Walkinb02a8832005-08-13 23:51:47 +00003014 || ((expr->expr_type == ASN_BASIC_INTEGER
3015 || expr->expr_type == ASN_BASIC_BIT_STRING)
Lev Walkin21d00002005-03-04 08:48:53 +00003016 && expr_elements_count(arg, expr))
3017 )
Lev Walkin801fabc2005-01-28 12:18:50 +00003018 && expr->parent_expr
3019 && expr->parent_expr->Identifier) {
3020 arg_t tmparg = *arg;
3021
3022 tmparg.expr = expr->parent_expr;
Lev Walkin21d00002005-03-04 08:48:53 +00003023 if(0) tmparg.flags &= ~A1C_COMPOUND_NAMES;
3024
Lev Walkin0f5d74c2005-08-14 15:03:31 +00003025 out_name_chain(&tmparg, onc_flags);
Lev Walkin801fabc2005-01-28 12:18:50 +00003026
Lev Walkin01633092005-03-05 00:08:41 +00003027 OUT("__"); /* a separator between id components */
Lev Walkin21d00002005-03-04 08:48:53 +00003028
Lev Walkin801fabc2005-01-28 12:18:50 +00003029 /* Fall through */
3030 }
3031
Lev Walkin0f5d74c2005-08-14 15:03:31 +00003032 if(onc_flags & ONC_avoid_keywords)
Lev Walkina00d6b32006-03-21 03:40:38 +00003033 id = MKID_safe(expr);
Lev Walkin801fabc2005-01-28 12:18:50 +00003034 else
Lev Walkina00d6b32006-03-21 03:40:38 +00003035 id = MKID(expr);
Lev Walkin801fabc2005-01-28 12:18:50 +00003036 OUT("%s", id);
3037
3038 return 0;
3039}
Lev Walkinb85a8132005-08-18 13:38:19 +00003040
3041static int
3042emit_include_dependencies(arg_t *arg) {
3043 asn1p_expr_t *expr = arg->expr;
3044 asn1p_expr_t *memb;
3045
3046 /* Avoid recursive definitions. */
3047 TQ_FOR(memb, &(expr->members), next) {
3048 expr_break_recursion(arg, memb);
3049 }
3050
3051 TQ_FOR(memb, &(expr->members), next) {
3052
3053 if(memb->marker.flags & (EM_INDIRECT | EM_UNRECURSE)) {
3054 if(terminal_structable(arg, memb)) {
3055 int saved_target = arg->target->target;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08003056 if(saved_target != OT_FWD_DECLS) {
3057 REDIR(OT_FWD_DECLS);
3058 OUT("%s;\n",
3059 asn1c_type_name(arg, memb, TNF_RSAFE));
3060 }
Lev Walkinb85a8132005-08-18 13:38:19 +00003061 REDIR(saved_target);
3062 }
3063 }
3064
3065 if((!(memb->expr_type & ASN_CONSTR_MASK)
3066 && memb->expr_type > ASN_CONSTR_MASK)
3067 || memb->meta_type == AMT_TYPEREF) {
3068 if(memb->marker.flags & EM_UNRECURSE) {
3069 GEN_POSTINCLUDE(asn1c_type_name(arg,
3070 memb, TNF_INCLUDE));
3071 } else {
3072 GEN_INCLUDE(asn1c_type_name(arg,
3073 memb, TNF_INCLUDE));
3074 }
3075 }
3076 }
3077
3078 return 0;
3079}
3080
3081/*
3082 * Check if it is better to make this type indirectly accessed via
3083 * a pointer.
3084 * This may be the case for the following recursive definition:
3085 * Type ::= CHOICE { member Type };
3086 */
3087static int
3088expr_break_recursion(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkinb85a8132005-08-18 13:38:19 +00003089 int ret;
3090
3091 if(expr->marker.flags & EM_UNRECURSE)
3092 return 1; /* Already broken */
3093
Lev Walkinb85a8132005-08-18 13:38:19 +00003094 /* -findirect-choice compiles members of CHOICE as indirect pointers */
3095 if((arg->flags & A1C_INDIRECT_CHOICE)
3096 && arg->expr->expr_type == ASN_CONSTR_CHOICE
Lev Walkin59b176e2005-11-26 11:25:14 +00003097 && (expr_get_type(arg, expr) & ASN_CONSTR_MASK)
Lev Walkinb85a8132005-08-18 13:38:19 +00003098 ) {
3099 /* Break cross-reference */
3100 expr->marker.flags |= EM_INDIRECT | EM_UNRECURSE;
3101 return 1;
3102 }
3103
3104 if((expr->marker.flags & EM_INDIRECT)
3105 || arg->expr->expr_type == ASN_CONSTR_SET_OF
3106 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF) {
3107 if(terminal_structable(arg, expr)) {
3108 expr->marker.flags |= EM_UNRECURSE;
3109
3110 if(arg->expr->expr_type == ASN_CONSTR_SET_OF
3111 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF) {
3112 /* Don't put EM_INDIRECT even if recursion */
3113 return 1;
3114 }
3115
3116 /* Fall through */
3117 }
3118 }
3119
3120 /* Look for recursive back-references */
3121 ret = expr_defined_recursively(arg, expr);
3122 switch(ret) {
3123 case 2: /* Explicitly break the recursion */
3124 case 1: /* Use safer typing */
3125 expr->marker.flags |= EM_INDIRECT;
3126 expr->marker.flags |= EM_UNRECURSE;
3127 break;
3128 }
3129
3130 return 0;
3131}
3132
3133/*
3134 * Check if the type can be represented using simple `struct TYPE`.
3135 */
3136static asn1p_expr_t *
3137terminal_structable(arg_t *arg, asn1p_expr_t *expr) {
3138 asn1p_expr_t *terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
3139 if(terminal
3140 && !terminal->parent_expr
3141 && (terminal->expr_type & ASN_CONSTR_MASK)) {
3142 return terminal;
3143 }
3144 return 0;
3145}
3146
3147static int
3148asn1c_recurse(arg_t *arg, asn1p_expr_t *expr, int (*callback)(arg_t *arg, void *key), void *key) {
3149 arg_t tmp = *arg;
3150 int maxret = 0;
3151 int ret;
3152
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +08003153 if(expr->_mark & TM_RECURSION) return 0;
Lev Walkinb85a8132005-08-18 13:38:19 +00003154 expr->_mark |= TM_RECURSION;
3155
3156 /* Invoke callback for every type going into recursion */
3157 tmp.expr = expr;
3158 maxret = callback(&tmp, key);
3159 if(maxret <= 1) {
3160 /*
3161 * Recursively invoke myself and the callbacks.
3162 */
3163 TQ_FOR(tmp.expr, &(expr->members), next) {
3164 ret = asn1c_recurse(&tmp, tmp.expr, callback, key);
3165 if(ret > maxret)
3166 maxret = ret;
3167 if(maxret > 1) break;
3168 }
3169 }
3170
3171 expr->_mark &= ~TM_RECURSION;
3172 return maxret;
3173}
3174
3175static int
3176check_is_refer_to(arg_t *arg, void *key) {
3177 asn1p_expr_t *terminal = terminal_structable(arg, arg->expr);
3178 if(terminal == key) {
3179 if(arg->expr->marker.flags & EM_INDIRECT)
3180 return 1; /* This is almost safe indirection */
3181 return 2;
3182 } else if(terminal) {
3183 /* This might be N-step circular loop. Dive into it. */
3184 return asn1c_recurse(arg, terminal, check_is_refer_to, key);
3185 }
3186 return 0;
3187}
3188
3189/*
3190 * Check if the possibly inner expression defined recursively.
3191 */
3192static int
3193expr_defined_recursively(arg_t *arg, asn1p_expr_t *expr) {
3194 asn1p_expr_t *terminal;
3195 asn1p_expr_t *topmost;
3196
3197 /* If expression is top-level, there's no way it can be recursive. */
3198 if(expr->parent_expr == 0) return 0;
3199 if(expr->expr_type != A1TC_REFERENCE)
3200 return 0; /* Basic types are never recursive */
3201
3202 terminal = terminal_structable(arg, expr);
3203 if(!terminal) return 0; /* Terminal cannot be indirected */
3204
3205 /* Search for the parent container for the given expression */
3206 topmost = expr;
3207 while(topmost->parent_expr)
3208 topmost = topmost->parent_expr;
3209
3210 /* Look inside the terminal type if it mentions the parent expression */
3211 return asn1c_recurse(arg, terminal, check_is_refer_to, topmost);
3212}
Lev Walkin59b176e2005-11-26 11:25:14 +00003213
3214struct canonical_map_element {
3215 int eidx;
3216 asn1p_expr_t *expr;
3217};
3218static int compar_cameo(const void *ap, const void *bp);
3219static arg_t *cameo_arg;
3220static int *
3221compute_canonical_members_order(arg_t *arg, int el_count) {
3222 struct canonical_map_element *cmap;
3223 int *rmap;
3224 asn1p_expr_t *v;
3225 int eidx = 0;
3226 int ext_start = -1;
3227 int nextmax = -1;
3228 int already_sorted = 1;
3229
3230 cmap = calloc(el_count, sizeof *cmap);
3231 assert(cmap);
3232
3233 TQ_FOR(v, &(arg->expr->members), next) {
3234 if(v->expr_type != A1TC_EXTENSIBLE) {
3235 cmap[eidx].eidx = eidx;
3236 cmap[eidx].expr = v;
3237 eidx++;
3238 } else if(ext_start == -1)
3239 ext_start = eidx;
3240 }
3241
3242 cameo_arg = arg;
3243 if(ext_start == -1) {
3244 /* Sort the whole thing */
3245 qsort(cmap, el_count, sizeof(*cmap), compar_cameo);
3246 } else {
3247 /* Sort root and extensions independently */
3248 qsort(cmap, ext_start, sizeof(*cmap), compar_cameo);
3249 qsort(cmap + ext_start, el_count - ext_start,
3250 sizeof(*cmap), compar_cameo);
3251 }
3252
3253 /* move data back to a simpler map */
3254 rmap = calloc(el_count, sizeof *rmap);
3255 assert(rmap);
3256 for(eidx = 0; eidx < el_count; eidx++) {
3257 rmap[eidx] = cmap[eidx].eidx;
3258 if(rmap[eidx] <= nextmax)
3259 already_sorted = 0;
3260 else
3261 nextmax = rmap[eidx];
3262 }
3263 free(cmap);
3264
3265 if(already_sorted) { free(rmap); rmap = 0; }
3266 return rmap;
3267}
3268static int compar_cameo(const void *ap, const void *bp) {
3269 const struct canonical_map_element *a = (const void *)ap;
3270 const struct canonical_map_element *b = (const void *)bp;
3271 struct asn1p_type_tag_s atag, btag;
3272 arg_t *arg = cameo_arg;
3273
3274 if(asn1f_fetch_outmost_tag(arg->asn, a->expr->module, a->expr,
3275 &atag, AFT_IMAGINARY_ANY | AFT_CANON_CHOICE))
3276 return 1;
3277
3278 if(asn1f_fetch_outmost_tag(arg->asn, b->expr->module, b->expr,
3279 &btag, AFT_IMAGINARY_ANY | AFT_CANON_CHOICE))
3280 return -1;
3281
3282 if(atag.tag_class < btag.tag_class)
3283 return -1;
3284 if(atag.tag_class > btag.tag_class)
3285 return 1;
3286 if(atag.tag_value < btag.tag_value)
3287 return -1;
3288 if(atag.tag_value > btag.tag_value)
3289 return 1;
3290 return 0;
3291
3292}