blob: 4d7a2149ca9264fb1ab22a18c6b66a7ea63ae62a [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 Walkinad0d6372017-08-08 02:02:42 -070010#include "asn1c_ioc.h"
Lev Walkinb46156d2017-09-05 02:53:05 -070011#include "asn1c_naming.h"
Lev Walkind8e07c52017-08-23 07:38:30 -070012#include <asn1print.h>
Lev Walkin59b176e2005-11-26 11:25:14 +000013#include <asn1fix_crange.h> /* constraint groker from libasn1fix */
14#include <asn1fix_export.h> /* other exportables from libasn1fix */
Lev Walkinda997b12017-08-04 01:38:41 -070015#include <asn1parser.h>
Lev Walkinf15320b2004-06-03 03:38:44 +000016
Lev Walkinfd171ef2004-06-06 07:20:17 +000017typedef struct tag2el_s {
18 struct asn1p_type_tag_s el_tag;
19 int el_no;
Lev Walkin38abe792004-06-14 13:09:45 +000020 int toff_first;
21 int toff_last;
Lev Walkinfd171ef2004-06-06 07:20:17 +000022 asn1p_expr_t *from_expr;
23} tag2el_t;
24
Lev Walkin33d5d3c2004-10-03 09:13:30 +000025typedef enum fte {
26 FTE_ALLTAGS,
27 FTE_CANONICAL_XER,
28} fte_e;
29static int _fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags);
30static 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 +000031
Lev Walkin0f5d74c2005-08-14 15:03:31 +000032enum onc_flags {
33 ONC_noflags = 0x00,
34 ONC_avoid_keywords = 0x01,
35 ONC_force_compound_name = 0x02,
36};
37static int out_name_chain(arg_t *arg, enum onc_flags);
Lev Walkin9de6cd82017-08-10 05:47:46 -070038static int asn1c_lang_C_type_SEQUENCE_def(
39 arg_t *arg, asn1c_ioc_table_and_objset_t *);
Lev Walkinf15320b2004-06-03 03:38:44 +000040static int asn1c_lang_C_type_SET_def(arg_t *arg);
41static int asn1c_lang_C_type_CHOICE_def(arg_t *arg);
42static int asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of);
Lev Walkinf6853ce2017-08-11 00:50:27 -070043static int asn1c_lang_C_OpenType(arg_t *arg, asn1c_ioc_table_and_objset_t *opt_ioc, const char *column_name);
Lev Walkinc3e29402004-09-10 06:07:18 +000044static int _print_tag(arg_t *arg, struct asn1p_type_tag_s *tag_p);
Lev Walkin59b176e2005-11-26 11:25:14 +000045static int compute_extensions_start(asn1p_expr_t *expr);
Lev Walkinda9a3b82005-08-16 17:00:21 +000046static int expr_break_recursion(arg_t *arg, asn1p_expr_t *expr);
Lev Walkina9cc46e2004-09-22 16:06:28 +000047static int expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr);
Lev Walkin59964be2004-08-25 02:03:12 +000048static int expr_elements_count(arg_t *arg, asn1p_expr_t *expr);
Lev Walkinb9e98cb2017-08-02 12:53:44 -070049static int emit_single_member_OER_constraint_value(arg_t *arg, asn1cnst_range_t *range);
50static int emit_single_member_OER_constraint_size(arg_t *arg, asn1cnst_range_t *range);
51static 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 +040052static int emit_member_OER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx);
Lev Walkin4b5dae32006-10-09 12:27:44 +000053static int emit_member_PER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx);
Lev Walkin9de6cd82017-08-10 05:47:46 -070054static int emit_member_table(arg_t *arg, asn1p_expr_t *expr,
55 asn1c_ioc_table_and_objset_t *);
Lev Walkin33d5d3c2004-10-03 09:13:30 +000056static int emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier);
Lev Walkinc8285712005-03-04 22:18:20 +000057static int emit_include_dependencies(arg_t *arg);
Lev Walkinb85a8132005-08-18 13:38:19 +000058static asn1p_expr_t *terminal_structable(arg_t *arg, asn1p_expr_t *expr);
59static int expr_defined_recursively(arg_t *arg, asn1p_expr_t *expr);
60static 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 +000061static asn1p_expr_type_e expr_get_type(arg_t *arg, asn1p_expr_t *expr);
62static int try_inline_default(arg_t *arg, asn1p_expr_t *expr, int out);
63static int *compute_canonical_members_order(arg_t *arg, int el_count);
Lev Walkinf15320b2004-06-03 03:38:44 +000064
Lev Walkin188ed2c2004-09-13 08:31:01 +000065enum tvm_compat {
66 _TVM_SAME = 0, /* tags and all_tags are same */
67 _TVM_SUBSET = 1, /* tags are subset of all_tags */
68 _TVM_DIFFERENT = 2, /* tags and all_tags are different */
69};
70static enum tvm_compat emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tc, int *atc);
71
Lev Walkin59964be2004-08-25 02:03:12 +000072enum etd_spec {
73 ETD_NO_SPECIFICS,
74 ETD_HAS_SPECIFICS
75};
Lev Walkin8de2ab22004-09-26 13:11:31 +000076static 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 +000077
Lev Walkin59004fa2004-08-20 13:37:01 +000078#define C99_MODE (!(arg->flags & A1C_NO_C99))
Lev Walkinf15320b2004-06-03 03:38:44 +000079#define UNNAMED_UNIONS (arg->flags & A1C_UNNAMED_UNIONS)
Lev Walkindd32b592004-09-06 08:07:29 +000080#define HIDE_INNER_DEFS (arg->embed && !(arg->flags & A1C_ALL_DEFS_GLOBAL))
Lev Walkinf15320b2004-06-03 03:38:44 +000081
82#define PCTX_DEF INDENTED( \
83 OUT("\n"); \
84 OUT("/* Context for parsing across buffer boundaries */\n"); \
Lev Walkin05363a72004-09-29 13:16:40 +000085 OUT("asn_struct_ctx_t _asn_ctx;\n"));
Lev Walkinf15320b2004-06-03 03:38:44 +000086
Lev Walkinc8285712005-03-04 22:18:20 +000087
Lev Walkin3dcaafa2004-08-11 05:21:32 +000088#define DEPENDENCIES do { \
Lev Walkinc8285712005-03-04 22:18:20 +000089 emit_include_dependencies(arg); \
Lev Walkin3dcaafa2004-08-11 05:21:32 +000090 if(expr->expr_type == ASN_CONSTR_SET_OF) \
Lev Walkin22b5ed42006-09-13 02:51:20 +000091 GEN_INCLUDE_STD("asn_SET_OF"); \
Lev Walkin3dcaafa2004-08-11 05:21:32 +000092 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF) \
Lev Walkin22b5ed42006-09-13 02:51:20 +000093 GEN_INCLUDE_STD("asn_SEQUENCE_OF"); \
Lev Walkin3dcaafa2004-08-11 05:21:32 +000094} while(0)
Lev Walkinf15320b2004-06-03 03:38:44 +000095
Lev Walkincaf0d5a2005-03-04 23:48:19 +000096/* MKID_safe() without checking for reserved keywords */
Lev Walkina00d6b32006-03-21 03:40:38 +000097#define MKID(expr) (asn1c_make_identifier(0, expr, 0))
98#define MKID_safe(expr) (asn1c_make_identifier(AMI_CHECK_RESERVED, expr, 0))
Lev Walkinf15320b2004-06-03 03:38:44 +000099
100int
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000101asn1c_lang_C_type_REAL(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000102 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
103}
104
Lev Walkine0b56e02005-02-25 12:10:27 +0000105struct value2enum {
106 asn1c_integer_t value;
107 const char *name;
108 int idx;
109};
110static int compar_enumMap_byName(const void *ap, const void *bp) {
111 const struct value2enum *a = (const struct value2enum *)ap;
112 const struct value2enum *b = (const struct value2enum *)bp;
113 return strcmp(a->name, b->name);
114}
115static int compar_enumMap_byValue(const void *ap, const void *bp) {
116 const struct value2enum *a = (const struct value2enum *)ap;
117 const struct value2enum *b = (const struct value2enum *)bp;
118 if(a->value < b->value)
119 return -1;
120 else if(a->value == b->value)
121 return 0;
122 return 1;
123}
124
Lev Walkinf15320b2004-06-03 03:38:44 +0000125int
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000126asn1c_lang_C_type_common_INTEGER(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000127 asn1p_expr_t *expr = arg->expr;
128 asn1p_expr_t *v;
Lev Walkine0b56e02005-02-25 12:10:27 +0000129 int el_count = expr_elements_count(arg, expr);
130 struct value2enum *v2e;
Lev Walkin59b176e2005-11-26 11:25:14 +0000131 int map_extensions = (expr->expr_type == ASN_BASIC_INTEGER);
Lev Walkin414b0782005-08-13 23:30:24 +0000132 int eidx;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800133 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000134
Lev Walkine0b56e02005-02-25 12:10:27 +0000135 v2e = alloca((el_count + 1) * sizeof(*v2e));
Lev Walkinf15320b2004-06-03 03:38:44 +0000136
Lev Walkine0b56e02005-02-25 12:10:27 +0000137 /*
Lev Walkin414b0782005-08-13 23:30:24 +0000138 * For all ENUMERATED types and for those INTEGER types which
139 * have identifiers, print out an enumeration table.
Lev Walkine0b56e02005-02-25 12:10:27 +0000140 */
Lev Walkin414b0782005-08-13 23:30:24 +0000141 if(expr->expr_type == ASN_BASIC_ENUMERATED || el_count) {
142 eidx = 0;
Lev Walkine0b56e02005-02-25 12:10:27 +0000143 REDIR(OT_DEPS);
Lev Walkinb46156d2017-09-05 02:53:05 -0700144 OUT("typedef %s {\n", c_name(arg).members_enum);
Lev Walkinf15320b2004-06-03 03:38:44 +0000145 TQ_FOR(v, &(expr->members), next) {
146 switch(v->expr_type) {
147 case A1TC_UNIVERVAL:
Lev Walkin21d00002005-03-04 08:48:53 +0000148 OUT("\t");
Lev Walkinb46156d2017-09-05 02:53:05 -0700149 OUT("%s", c_member_name(arg, v));
Lev Walkinda997b12017-08-04 01:38:41 -0700150 OUT("\t= %s%s\n",
151 asn1p_itoa(v->value->value.v_integer),
Lev Walkin21d00002005-03-04 08:48:53 +0000152 (eidx+1 < el_count) ? "," : "");
Lev Walkine0b56e02005-02-25 12:10:27 +0000153 v2e[eidx].name = v->Identifier;
154 v2e[eidx].value = v->value->value.v_integer;
155 eidx++;
Lev Walkinf15320b2004-06-03 03:38:44 +0000156 break;
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000157 case A1TC_EXTENSIBLE:
158 OUT("\t/*\n");
159 OUT("\t * Enumeration is extensible\n");
160 OUT("\t */\n");
Lev Walkin59b176e2005-11-26 11:25:14 +0000161 if(!map_extensions)
162 map_extensions = eidx + 1;
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000163 break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000164 default:
165 return -1;
166 }
167 }
Lev Walkinb46156d2017-09-05 02:53:05 -0700168 OUT("} %s;\n", c_name(arg).members_name);
Lev Walkine0b56e02005-02-25 12:10:27 +0000169 assert(eidx == el_count);
Lev Walkin414b0782005-08-13 23:30:24 +0000170 }
171
172 /*
173 * For all ENUMERATED types print out a mapping table
174 * between identifiers and associated values.
175 * This is prohibited for INTEGER types by by X.693:8.3.4.
176 */
177 if(expr->expr_type == ASN_BASIC_ENUMERATED) {
Lev Walkine0b56e02005-02-25 12:10:27 +0000178
179 /*
180 * Generate a enumerationName<->value map for XER codec.
181 */
182 REDIR(OT_STAT_DEFS);
183
Wim Lewisfb6344e2014-07-28 12:16:01 -0700184 OUT("static const asn_INTEGER_enum_map_t asn_MAP_%s_value2enum_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000185 MKID(expr), expr->_type_unique_index);
Lev Walkine0b56e02005-02-25 12:10:27 +0000186 qsort(v2e, el_count, sizeof(v2e[0]), compar_enumMap_byValue);
187 for(eidx = 0; eidx < el_count; eidx++) {
188 v2e[eidx].idx = eidx;
Lev Walkinda997b12017-08-04 01:38:41 -0700189 OUT("\t{ %s,\t%ld,\t\"%s\" }%s\n",
190 asn1p_itoa(v2e[eidx].value),
Lev Walkine0b56e02005-02-25 12:10:27 +0000191 (long)strlen(v2e[eidx].name), v2e[eidx].name,
192 (eidx + 1 < el_count) ? "," : "");
193 }
Lev Walkin59b176e2005-11-26 11:25:14 +0000194 if(map_extensions)
Lev Walkine0b56e02005-02-25 12:10:27 +0000195 OUT("\t/* This list is extensible */\n");
196 OUT("};\n");
197
Wim Lewisfb6344e2014-07-28 12:16:01 -0700198 OUT("static const unsigned int asn_MAP_%s_enum2value_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000199 MKID(expr), expr->_type_unique_index);
Lev Walkine0b56e02005-02-25 12:10:27 +0000200 qsort(v2e, el_count, sizeof(v2e[0]), compar_enumMap_byName);
201 for(eidx = 0; eidx < el_count; eidx++) {
Lev Walkinda997b12017-08-04 01:38:41 -0700202 OUT("\t%d%s\t/* %s(%s) */\n",
Lev Walkine0b56e02005-02-25 12:10:27 +0000203 v2e[eidx].idx,
204 (eidx + 1 < el_count) ? "," : "",
Lev Walkinda997b12017-08-04 01:38:41 -0700205 v2e[eidx].name, asn1p_itoa(v2e[eidx].value));
Lev Walkine0b56e02005-02-25 12:10:27 +0000206 }
Lev Walkin59b176e2005-11-26 11:25:14 +0000207 if(map_extensions)
Lev Walkine0b56e02005-02-25 12:10:27 +0000208 OUT("\t/* This list is extensible */\n");
209 OUT("};\n");
210
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800211 if(!(expr->_type_referenced)) OUT("static ");
212 OUT("const asn_INTEGER_specifics_t asn_SPC_%s_specs_%d = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000213 MKID(expr), expr->_type_unique_index);
Lev Walkine0b56e02005-02-25 12:10:27 +0000214 INDENT(+1);
Lev Walkin59b176e2005-11-26 11:25:14 +0000215 OUT("asn_MAP_%s_value2enum_%d,\t"
Lev Walkine0b56e02005-02-25 12:10:27 +0000216 "/* \"tag\" => N; sorted by tag */\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000217 MKID(expr),
Lev Walkin21d00002005-03-04 08:48:53 +0000218 expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +0000219 OUT("asn_MAP_%s_enum2value_%d,\t"
Lev Walkine0b56e02005-02-25 12:10:27 +0000220 "/* N => \"tag\"; sorted by N */\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000221 MKID(expr),
Lev Walkin21d00002005-03-04 08:48:53 +0000222 expr->_type_unique_index);
Lev Walkine0b56e02005-02-25 12:10:27 +0000223 OUT("%d,\t/* Number of elements in the maps */\n",
224 el_count);
Lev Walkin59b176e2005-11-26 11:25:14 +0000225 if(map_extensions) {
226 OUT("%d,\t/* Extensions before this member */\n",
227 map_extensions);
228 } else {
229 OUT("0,\t/* Enumeration is not extensible */\n");
230 }
Lev Walkine0b56e02005-02-25 12:10:27 +0000231 if(expr->expr_type == ASN_BASIC_ENUMERATED)
Lev Walkin8bb57a22007-12-03 13:41:36 +0000232 OUT("1,\t/* Strict enumeration */\n");
Lev Walkine0b56e02005-02-25 12:10:27 +0000233 else
Lev Walkin8bb57a22007-12-03 13:41:36 +0000234 OUT("0,\n");
235 OUT("0,\t/* Native long size */\n");
236 OUT("0\n");
237 INDENT(-1);
238 OUT("};\n");
239 }
240
241 if(expr->expr_type == ASN_BASIC_INTEGER
242 && asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN) {
243 REDIR(OT_STAT_DEFS);
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800244 if(!(expr->_type_referenced)) OUT("static ");
245 OUT("const asn_INTEGER_specifics_t asn_SPC_%s_specs_%d = {\n",
Lev Walkin8bb57a22007-12-03 13:41:36 +0000246 MKID(expr), expr->_type_unique_index);
247 INDENT(+1);
248 OUT("0,\t");
249 OUT("0,\t");
250 OUT("0,\t");
251 OUT("0,\t");
252 OUT("0,\n");
253 OUT("0,\t/* Native long size */\n");
254 OUT("1\t/* Unsigned representation */\n");
Lev Walkine0b56e02005-02-25 12:10:27 +0000255 INDENT(-1);
256 OUT("};\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000257 }
258
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800259 REDIR(saved_target);
260
Lev Walkinf15320b2004-06-03 03:38:44 +0000261 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
262}
263
264int
Lev Walkinb02a8832005-08-13 23:51:47 +0000265asn1c_lang_C_type_BIT_STRING(arg_t *arg) {
266 asn1p_expr_t *expr = arg->expr;
267 asn1p_expr_t *v;
268 int el_count = expr_elements_count(arg, expr);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800269 int saved_target = arg->target->target;
Lev Walkinb02a8832005-08-13 23:51:47 +0000270
271 if(el_count) {
Lev Walkin082cadc2005-08-14 02:18:27 +0000272 int eidx = 0;
Lev Walkinb02a8832005-08-13 23:51:47 +0000273 REDIR(OT_DEPS);
Lev Walkinb46156d2017-09-05 02:53:05 -0700274 OUT("typedef %s {\n", c_name(arg).members_enum);
Lev Walkinb02a8832005-08-13 23:51:47 +0000275 TQ_FOR(v, &(expr->members), next) {
Lev Walkin082cadc2005-08-14 02:18:27 +0000276 if(v->expr_type != A1TC_UNIVERVAL) {
Lev Walkinb02a8832005-08-13 23:51:47 +0000277 OUT("/* Unexpected BIT STRING element: %s */\n",
278 v->Identifier);
Lev Walkin082cadc2005-08-14 02:18:27 +0000279 continue;
Lev Walkinb02a8832005-08-13 23:51:47 +0000280 }
Lev Walkin0f8d4a42006-08-26 03:29:15 +0000281 eidx++;
Lev Walkin082cadc2005-08-14 02:18:27 +0000282 OUT("\t");
Lev Walkinb46156d2017-09-05 02:53:05 -0700283 OUT("%s", c_member_name(arg, v));
Lev Walkinda997b12017-08-04 01:38:41 -0700284 OUT("\t= %s%s\n",
285 asn1p_itoa(v->value->value.v_integer),
Lev Walkin082cadc2005-08-14 02:18:27 +0000286 (eidx < el_count) ? "," : "");
Lev Walkinb02a8832005-08-13 23:51:47 +0000287 }
Lev Walkinb46156d2017-09-05 02:53:05 -0700288 OUT("} %s;\n", c_name(arg).members_name);
Lev Walkinb02a8832005-08-13 23:51:47 +0000289 assert(eidx == el_count);
290 }
291
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800292 REDIR(saved_target);
293
Lev Walkinb02a8832005-08-13 23:51:47 +0000294 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
295}
296
Lev Walkinf6853ce2017-08-11 00:50:27 -0700297/*
298 * Check if it is a true open type. That is, type is taken from
299 * the Information Object Set driven constraints.
300 */
301static int
302is_open_type(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_objset_t *opt_ioc) {
303
304 (void)arg;
305
306 if(!opt_ioc) {
307 return 0;
308 }
309
310 if(expr->meta_type == AMT_TYPEREF
311 && expr->expr_type == A1TC_REFERENCE
312 && expr->reference->comp_count == 2
313 && expr->reference->components[1].lex_type
314 == RLT_AmpUppercase) {
Lev Walkind8e07c52017-08-23 07:38:30 -0700315 DEBUG("%s is a true open type", MKID(expr));
Lev Walkinf6853ce2017-08-11 00:50:27 -0700316 return 1;
317 }
318
319 return 0;
320}
321
Lev Walkinb02a8832005-08-13 23:51:47 +0000322int
Lev Walkinf15320b2004-06-03 03:38:44 +0000323asn1c_lang_C_type_SEQUENCE(arg_t *arg) {
324 asn1p_expr_t *expr = arg->expr;
325 asn1p_expr_t *v;
326 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800327 int saved_target = arg->target->target;
Lev Walkinad0d6372017-08-08 02:02:42 -0700328 asn1c_ioc_table_and_objset_t ioc_tao;
Lev Walkinf15320b2004-06-03 03:38:44 +0000329
330 DEPENDENCIES;
331
Lev Walkinad0d6372017-08-08 02:02:42 -0700332 ioc_tao = asn1c_get_ioc_table(arg);
333 if(ioc_tao.ioct) {
334 if(emit_ioc_table(arg, expr, ioc_tao)) {
335 return -1;
336 }
337 } else if(ioc_tao.fatal_error) {
Lev Walkinea6635b2017-08-06 23:23:04 -0700338 return -1;
339 }
340
Lev Walkinf15320b2004-06-03 03:38:44 +0000341 if(arg->embed) {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800342
343 /* Use _anonymous_type field to indicate it's called from
344 * asn1c_lang_C_type_SEx_OF() */
345 if (expr->_anonymous_type) {
346 REDIR(OT_FWD_DEFS);
347 OUT("typedef ");
348 }
Lev Walkinb46156d2017-09-05 02:53:05 -0700349 OUT("%s {\n", c_name(arg).full_name);
Lev Walkinf15320b2004-06-03 03:38:44 +0000350 } else {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800351 REDIR(OT_TYPE_DECLS);
Lev Walkinb46156d2017-09-05 02:53:05 -0700352 OUT("typedef %s {\n", c_name(arg).full_name);
Lev Walkinf15320b2004-06-03 03:38:44 +0000353 }
354
355 TQ_FOR(v, &(expr->members), next) {
Lev Walkinda9a3b82005-08-16 17:00:21 +0000356 if(v->expr_type == A1TC_EXTENSIBLE)
Lev Walkinf15320b2004-06-03 03:38:44 +0000357 if(comp_mode < 3) comp_mode++;
Lev Walkinda9a3b82005-08-16 17:00:21 +0000358 if(comp_mode == 1)
Lev Walkin59b176e2005-11-26 11:25:14 +0000359 v->marker.flags |= EM_OMITABLE | EM_INDIRECT;
360 try_inline_default(arg, v, 1);
Lev Walkinf6853ce2017-08-11 00:50:27 -0700361 if(is_open_type(arg, v, ioc_tao.ioct ? &ioc_tao : 0)) {
362 arg_t tmp_arg = *arg;
363 tmp_arg.embed++;
364 INDENT(+1);
365 tmp_arg.expr = v;
366 const char *column_name = v->reference->components[1].name;
367 if(asn1c_lang_C_OpenType(&tmp_arg, &ioc_tao, column_name)) {
368 return -1;
369 }
370 INDENT(-1);
371 tmp_arg.embed--;
372 if(v->expr_type != A1TC_EXTENSIBLE) OUT(";\n");
373 } else {
374 EMBED_WITH_IOCT(v, ioc_tao);
375 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000376 }
377
378 PCTX_DEF;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800379
380 if (arg->embed && expr->_anonymous_type) {
Lev Walkinb46156d2017-09-05 02:53:05 -0700381 OUT("} %s%s;\n", (expr->marker.flags & EM_INDIRECT)?"*":"",
382 c_name(arg).base_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800383
384 REDIR(saved_target);
385
Lev Walkinb46156d2017-09-05 02:53:05 -0700386 OUT("%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
387 c_name(arg).base_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800388 } else {
Lev Walkinb46156d2017-09-05 02:53:05 -0700389 OUT("} %s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
390 c_name(arg).short_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800391 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000392
Lev Walkin9de6cd82017-08-10 05:47:46 -0700393 return asn1c_lang_C_type_SEQUENCE_def(arg, ioc_tao.ioct ? &ioc_tao : 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000394}
395
Lev Walkinade508c2017-08-23 10:19:30 -0700396static void
397emit_tag2member_reference(arg_t *arg, asn1p_expr_t *expr,
398 unsigned tag2el_count) {
399 if(tag2el_count) {
400 if(C99_MODE) OUT(".tag2el = ");
401 OUT("asn_MAP_%s_tag2el_%d,\n", MKID(expr), expr->_type_unique_index);
402 if(C99_MODE) OUT(".tag2el_count = ");
403 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
404 } else {
405 OUT("0,\t/* No top level tags */\n");
406 OUT("0,\t/* No tags in the map */\n");
407 }
408}
409
Lev Walkinf15320b2004-06-03 03:38:44 +0000410static int
Lev Walkin9de6cd82017-08-10 05:47:46 -0700411asn1c_lang_C_type_SEQUENCE_def(arg_t *arg, asn1c_ioc_table_and_objset_t *opt_ioc) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000412 asn1p_expr_t *expr = arg->expr;
413 asn1p_expr_t *v;
414 int elements; /* Number of elements */
Lev Walkin33af5c32007-06-23 20:05:49 +0000415 int ext_start = -2;
416 int ext_stop = -2;
Lev Walkinfd171ef2004-06-06 07:20:17 +0000417 tag2el_t *tag2el = NULL;
418 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000419 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000420 int all_tags_count;
421 enum tvm_compat tv_mode;
Lev Walkin59b176e2005-11-26 11:25:14 +0000422 int roms_count; /* Root optional members */
423 int aoms_count; /* Additions optional members */
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800424 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000425
Lev Walkinfd171ef2004-06-06 07:20:17 +0000426 /*
427 * Fetch every inner tag from the tag to elements map.
428 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000429 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
Lev Walkinfd171ef2004-06-06 07:20:17 +0000430 if(tag2el) free(tag2el);
431 return -1;
432 }
433
Lev Walkin22b5ed42006-09-13 02:51:20 +0000434 GEN_INCLUDE_STD("constr_SEQUENCE");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000435 if(!arg->embed)
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800436 GEN_DECLARE("SEQUENCE", expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000437
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000438 REDIR(OT_STAT_DEFS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000439
440 /*
Lev Walkin59b176e2005-11-26 11:25:14 +0000441 * Print out the table according to which parsing is performed.
Lev Walkinf15320b2004-06-03 03:38:44 +0000442 */
Lev Walkina9cc46e2004-09-22 16:06:28 +0000443 if(expr_elements_count(arg, expr)) {
444 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Lev Walkinf15320b2004-06-03 03:38:44 +0000445
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800446 if(!(expr->_type_referenced)) OUT("static ");
447 OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000448 MKID(expr), expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000449
450 elements = 0;
Lev Walkin59b176e2005-11-26 11:25:14 +0000451 roms_count = 0;
452 aoms_count = 0;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000453 INDENTED(TQ_FOR(v, &(expr->members), next) {
454 if(v->expr_type == A1TC_EXTENSIBLE) {
455 if((++comp_mode) == 1)
456 ext_start = elements - 1;
457 else
458 ext_stop = elements - 1;
459 continue;
460 }
Lev Walkin59b176e2005-11-26 11:25:14 +0000461 if(v->marker.flags & EM_OMITABLE)
462 comp_mode == 1 ? ++aoms_count : ++roms_count;
Lev Walkind8e07c52017-08-23 07:38:30 -0700463 if(emit_member_table(arg, v, opt_ioc) < 0)
464 return -1;
Lev Walkinda9a3b82005-08-16 17:00:21 +0000465 elements++;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000466 });
467 OUT("};\n");
Lev Walkin59b176e2005-11-26 11:25:14 +0000468
Lev Walkin3c5d9412017-07-24 01:49:24 +0400469 if((roms_count + aoms_count) && (arg->flags & (A1C_GEN_OER|A1C_GEN_PER))) {
Lev Walkin59b176e2005-11-26 11:25:14 +0000470 int elm = 0;
471 int comma = 0;
472 comp_mode = 0;
Wim Lewisfb6344e2014-07-28 12:16:01 -0700473 OUT("static const int asn_MAP_%s_oms_%d[] = {",
Lev Walkina00d6b32006-03-21 03:40:38 +0000474 MKID(expr),
Lev Walkin59b176e2005-11-26 11:25:14 +0000475 expr->_type_unique_index);
476 TQ_FOR(v, &(expr->members), next) {
477 if(v->expr_type == A1TC_EXTENSIBLE) {
478 ++comp_mode;
479 continue;
480 }
481 if((v->marker.flags & EM_OMITABLE)
482 && comp_mode != 1) {
483 if(!comma) comma++;
484 else OUT(",");
485 OUT(" %d", elm);
486 }
487 ++elm;
488 }
489 elm = 0;
490 comp_mode = 0;
491 TQ_FOR(v, &(expr->members), next) {
492 if(v->expr_type == A1TC_EXTENSIBLE) {
493 ++comp_mode;
494 continue;
495 }
496 if((v->marker.flags & EM_OMITABLE)
497 && comp_mode == 1) {
498 if(!comma) comma++;
499 else OUT(",");
500 OUT(" %d", elm);
501 }
502 ++elm;
503 }
504 OUT(" };\n");
Lev Walkinea6635b2017-08-06 23:23:04 -0700505 if(roms_count > 65536) {
Lev Walkin59b176e2005-11-26 11:25:14 +0000506 FATAL("Too many optional elements in %s "
507 "at line %d!",
508 arg->expr->Identifier,
509 arg->expr->_lineno);
Lev Walkinea6635b2017-08-06 23:23:04 -0700510 return -1;
511 }
Lev Walkin59b176e2005-11-26 11:25:14 +0000512 } else {
513 roms_count = 0;
514 aoms_count = 0;
515 }
Lev Walkina9cc46e2004-09-22 16:06:28 +0000516 } else {
517 elements = 0;
Lev Walkin59b176e2005-11-26 11:25:14 +0000518 roms_count = 0;
519 aoms_count = 0;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000520 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000521
Lev Walkin27ea3802004-06-28 21:13:46 +0000522 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000523 * Print out asn_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +0000524 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000525 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000526
Lev Walkinfd171ef2004-06-06 07:20:17 +0000527 /*
528 * Tags to elements map.
529 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000530 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
Lev Walkinfd171ef2004-06-06 07:20:17 +0000531
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800532 if(!(expr->_type_referenced)) OUT("static ");
533 OUT("asn_SEQUENCE_specifics_t asn_SPC_%s_specs_%d = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000534 MKID(expr), expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +0000535 INDENT(+1);
Lev Walkinb46156d2017-09-05 02:53:05 -0700536 OUT("sizeof(%s),\n", c_name(arg).full_name);
537 OUT("offsetof(%s, _asn_ctx),\n", c_name(arg).full_name);
Lev Walkinade508c2017-08-23 10:19:30 -0700538 emit_tag2member_reference(arg, expr, tag2el_count);
Lev Walkin59b176e2005-11-26 11:25:14 +0000539 if(roms_count + aoms_count) {
540 OUT("asn_MAP_%s_oms_%d,\t/* Optional members */\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000541 MKID(expr), expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +0000542 OUT("%d, %d,\t/* Root/Additions */\n", roms_count, aoms_count);
543 } else {
544 OUT("0, 0, 0,\t/* Optional elements (not needed) */\n");
545 }
546 OUT("%d,\t/* Start extensions */\n",
Lev Walkin33af5c32007-06-23 20:05:49 +0000547 ext_start<0 ? -1 : ext_start);
Lev Walkin59b176e2005-11-26 11:25:14 +0000548 OUT("%d\t/* Stop extensions */\n",
Lev Walkin33af5c32007-06-23 20:05:49 +0000549 (ext_stop<ext_start)?elements+1:(ext_stop<0?-1:ext_stop));
Lev Walkin59b176e2005-11-26 11:25:14 +0000550 INDENT(-1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000551 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000552
553 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000554 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +0000555 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000556 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
Lev Walkin8de2ab22004-09-26 13:11:31 +0000557 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000558
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800559 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +0000560
Bi-Ruei, Chiu12021b52016-11-04 11:59:45 +0800561 if(tag2el) free(tag2el);
562
Lev Walkinf15320b2004-06-03 03:38:44 +0000563 return 0;
Lev Walkinb0b33412005-01-17 11:57:48 +0000564} /* _SEQUENCE_def() */
Lev Walkinf15320b2004-06-03 03:38:44 +0000565
566int
Lev Walkinf15320b2004-06-03 03:38:44 +0000567asn1c_lang_C_type_SET(arg_t *arg) {
568 asn1p_expr_t *expr = arg->expr;
569 asn1p_expr_t *v;
570 long mcount;
Lev Walkinb46156d2017-09-05 02:53:05 -0700571 const char *id;
Lev Walkinf15320b2004-06-03 03:38:44 +0000572 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800573 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000574
575 DEPENDENCIES;
576
577 REDIR(OT_DEPS);
578
579 OUT("\n");
580 OUT("/*\n");
581 OUT(" * Method of determining the components presence\n");
582 OUT(" */\n");
583 mcount = 0;
Lev Walkinb46156d2017-09-05 02:53:05 -0700584 OUT("typedef %s {\n", c_name(arg).presence_enum);
Lev Walkinf15320b2004-06-03 03:38:44 +0000585 TQ_FOR(v, &(expr->members), next) {
586 if(v->expr_type == A1TC_EXTENSIBLE) continue;
587 INDENTED(
Lev Walkinb46156d2017-09-05 02:53:05 -0700588 OUT("%s,", c_presence_name(arg, v));
589 OUT("\t/* Member %s is present */\n", MKID(v));
Lev Walkinf15320b2004-06-03 03:38:44 +0000590 );
591 mcount++;
592 }
Lev Walkinb46156d2017-09-05 02:53:05 -0700593 OUT("} %s;\n", c_name(arg).presence_name);
Lev Walkinf15320b2004-06-03 03:38:44 +0000594
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800595 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +0000596
597 if(arg->embed) {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800598 if (expr->_anonymous_type) {
599 REDIR(OT_FWD_DEFS);
600 OUT("typedef ");
601 }
Lev Walkinb46156d2017-09-05 02:53:05 -0700602 OUT("%s {\n", c_name(arg).full_name);
Lev Walkinf15320b2004-06-03 03:38:44 +0000603 } else {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800604 REDIR(OT_TYPE_DECLS);
Lev Walkinb46156d2017-09-05 02:53:05 -0700605 OUT("typedef %s {\n", c_name(arg).full_name);
Lev Walkinf15320b2004-06-03 03:38:44 +0000606 }
607
608 TQ_FOR(v, &(expr->members), next) {
Lev Walkin59b176e2005-11-26 11:25:14 +0000609 if(v->expr_type == A1TC_EXTENSIBLE)
Lev Walkinf15320b2004-06-03 03:38:44 +0000610 if(comp_mode < 3) comp_mode++;
Lev Walkinda9a3b82005-08-16 17:00:21 +0000611 if(comp_mode == 1)
Lev Walkin59b176e2005-11-26 11:25:14 +0000612 v->marker.flags |= EM_OMITABLE | EM_INDIRECT;
613 try_inline_default(arg, v, 1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000614 EMBED(v);
615 }
616
617 INDENTED(
Lev Walkina00d6b32006-03-21 03:40:38 +0000618 id = MKID(expr);
Lev Walkinf15320b2004-06-03 03:38:44 +0000619 OUT("\n");
620 OUT("/* Presence bitmask: ASN_SET_ISPRESENT(p%s, %s_PR_x) */\n",
621 id, id);
622 OUT("unsigned int _presence_map\n");
623 OUT("\t[((%ld+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))];\n", mcount);
624 );
625
626 PCTX_DEF;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800627
628 if (arg->embed && expr->_anonymous_type) {
Lev Walkinb46156d2017-09-05 02:53:05 -0700629 OUT("} %s%s;\n", (expr->marker.flags & EM_INDIRECT)?"*":"",
630 c_name(arg).base_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800631
632 REDIR(saved_target);
633
Lev Walkinb46156d2017-09-05 02:53:05 -0700634 OUT("%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
635 c_name(arg).base_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800636 } else {
Lev Walkinb46156d2017-09-05 02:53:05 -0700637 OUT("} %s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
638 c_name(arg).short_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800639 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000640
641 return asn1c_lang_C_type_SET_def(arg);
642}
643
Lev Walkinf15320b2004-06-03 03:38:44 +0000644static int
645asn1c_lang_C_type_SET_def(arg_t *arg) {
646 asn1p_expr_t *expr = arg->expr;
647 asn1p_expr_t *v;
648 int elements;
Lev Walkinf15320b2004-06-03 03:38:44 +0000649 tag2el_t *tag2el = NULL;
650 int tag2el_count = 0;
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000651 tag2el_t *tag2el_cxer = NULL;
652 int tag2el_cxer_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000653 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000654 int all_tags_count;
655 enum tvm_compat tv_mode;
Lev Walkinb46156d2017-09-05 02:53:05 -0700656 const char *p;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800657 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000658
659 /*
660 * Fetch every inner tag from the tag to elements map.
661 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000662 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000663 if(tag2el) free(tag2el);
664 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000665 }
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000666 if(_fill_tag2el_map(arg, &tag2el_cxer, &tag2el_cxer_count, -1, FTE_CANONICAL_XER)) {
667 if(tag2el) free(tag2el);
668 if(tag2el_cxer) free(tag2el_cxer);
669 return -1;
670 }
671 if(tag2el_cxer_count == tag2el_count
672 && memcmp(tag2el, tag2el_cxer, tag2el_count) == 0) {
673 free(tag2el_cxer);
674 tag2el_cxer = 0;
675 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000676
Lev Walkin22b5ed42006-09-13 02:51:20 +0000677 GEN_INCLUDE_STD("constr_SET");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000678 if(!arg->embed)
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800679 GEN_DECLARE("SET", expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000680
681 REDIR(OT_STAT_DEFS);
682
Lev Walkinf15320b2004-06-03 03:38:44 +0000683 /*
Lev Walkin59b176e2005-11-26 11:25:14 +0000684 * Print out the table according to which parsing is performed.
Lev Walkinf15320b2004-06-03 03:38:44 +0000685 */
Lev Walkina9cc46e2004-09-22 16:06:28 +0000686 if(expr_elements_count(arg, expr)) {
687 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Lev Walkinf15320b2004-06-03 03:38:44 +0000688
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800689 if(!(expr->_type_referenced)) OUT("static ");
690 OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000691 MKID(expr), expr->_type_unique_index);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800692
Lev Walkina9cc46e2004-09-22 16:06:28 +0000693 elements = 0;
694 INDENTED(TQ_FOR(v, &(expr->members), next) {
695 if(v->expr_type == A1TC_EXTENSIBLE) {
696 if(comp_mode < 3) comp_mode++;
697 } else {
Lev Walkin9de6cd82017-08-10 05:47:46 -0700698 emit_member_table(arg, v, NULL);
Lev Walkinda9a3b82005-08-16 17:00:21 +0000699 elements++;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000700 }
701 });
702 OUT("};\n");
703 } else {
704 elements = 0;
705 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000706
Lev Walkin27ea3802004-06-28 21:13:46 +0000707 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000708 * Print out asn_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +0000709 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000710 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000711
712 /*
713 * Tags to elements map.
714 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000715 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
716 if(tag2el_cxer)
717 emit_tag2member_map(arg, tag2el_cxer, tag2el_cxer_count, "_cxer");
Lev Walkinf15320b2004-06-03 03:38:44 +0000718
719 /*
720 * Emit a map of mandatory elements.
721 */
Wim Lewisfb6344e2014-07-28 12:16:01 -0700722 OUT("static const uint8_t asn_MAP_%s_mmap_%d",
Lev Walkina00d6b32006-03-21 03:40:38 +0000723 MKID(expr), expr->_type_unique_index);
724 p = MKID_safe(expr);
Lev Walkinf15320b2004-06-03 03:38:44 +0000725 OUT("[(%d + (8 * sizeof(unsigned int)) - 1) / 8]", elements);
Lev Walkin21d00002005-03-04 08:48:53 +0000726 OUT(" = {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000727 INDENTED(
728 if(elements) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000729 int el = 0;
730 TQ_FOR(v, &(expr->members), next) {
731 if(v->expr_type == A1TC_EXTENSIBLE) continue;
Lev Walkinac760bf2005-10-05 08:59:03 +0000732 if(el) {
733 if((el % 8) == 0)
734 OUT(",\n");
735 else
736 OUT(" | ");
Lev Walkinf15320b2004-06-03 03:38:44 +0000737 }
Lev Walkincc93b0f2004-09-10 09:18:20 +0000738 OUT("(%d << %d)",
Lev Walkinb85a8132005-08-18 13:38:19 +0000739 (v->marker.flags & EM_OMITABLE) != EM_OMITABLE,
Lev Walkincc93b0f2004-09-10 09:18:20 +0000740 7 - (el % 8));
Lev Walkinf15320b2004-06-03 03:38:44 +0000741 el++;
742 }
743 } else {
744 OUT("0");
745 }
746 );
747 OUT("\n");
748 OUT("};\n");
749
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800750 if(!(expr->_type_referenced)) OUT("static \n");
751 OUT("asn_SET_specifics_t asn_SPC_%s_specs_%d = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000752 MKID(expr), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +0000753 INDENTED(
Lev Walkinb46156d2017-09-05 02:53:05 -0700754 OUT("sizeof(%s),\n", c_name(arg).full_name);
755 OUT("offsetof(%s, _asn_ctx),\n", c_name(arg).full_name);
756 OUT("offsetof(%s, _presence_map),\n", c_name(arg).full_name);
Lev Walkinade508c2017-08-23 10:19:30 -0700757 emit_tag2member_reference(arg, expr, tag2el_count);
Lev Walkina00d6b32006-03-21 03:40:38 +0000758 p = MKID(expr);
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000759 if(tag2el_cxer)
Lev Walkin59b176e2005-11-26 11:25:14 +0000760 OUT("asn_MAP_%s_tag2el_cxer_%d,\n",
Lev Walkin21d00002005-03-04 08:48:53 +0000761 p, expr->_type_unique_index);
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000762 else
Lev Walkin59b176e2005-11-26 11:25:14 +0000763 OUT("asn_MAP_%s_tag2el_%d,\t/* Same as above */\n",
Lev Walkin21d00002005-03-04 08:48:53 +0000764 p, expr->_type_unique_index);
765 OUT("%d,\t/* Count of tags in the CXER map */\n",
766 tag2el_cxer_count);
Lev Walkin35631482004-07-01 00:52:50 +0000767 OUT("%d,\t/* Whether extensible */\n",
Lev Walkin59b176e2005-11-26 11:25:14 +0000768 compute_extensions_start(expr) == -1 ? 0 : 1);
Lev Walkin46ef3f32017-07-06 08:47:53 -0700769 OUT("(const unsigned int *)asn_MAP_%s_mmap_%d\t/* Mandatory elements map */\n",
Lev Walkin21d00002005-03-04 08:48:53 +0000770 p, expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +0000771 );
772 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000773
774 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000775 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +0000776 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000777 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
Lev Walkin8de2ab22004-09-26 13:11:31 +0000778 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000779
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800780 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +0000781
Bi-Ruei, Chiu12021b52016-11-04 11:59:45 +0800782 if (tag2el) free(tag2el);
783 if (tag2el_cxer) free(tag2el_cxer);
784
Lev Walkinf15320b2004-06-03 03:38:44 +0000785 return 0;
Lev Walkinb0b33412005-01-17 11:57:48 +0000786} /* _SET_def() */
Lev Walkinf15320b2004-06-03 03:38:44 +0000787
788int
Lev Walkin08079b02004-08-22 03:25:24 +0000789asn1c_lang_C_type_SEx_OF(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000790 asn1p_expr_t *expr = arg->expr;
Lev Walkinc8285712005-03-04 22:18:20 +0000791 asn1p_expr_t *memb = TQ_FIRST(&expr->members);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800792 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000793
794 DEPENDENCIES;
795
796 if(arg->embed) {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800797 if (expr->_anonymous_type) {
798 REDIR(OT_FWD_DEFS);
799 OUT("typedef ");
800 }
Lev Walkinb46156d2017-09-05 02:53:05 -0700801 OUT("%s {\n", c_name(arg).full_name);
Lev Walkinf15320b2004-06-03 03:38:44 +0000802 } else {
Lev Walkinb46156d2017-09-05 02:53:05 -0700803 OUT("typedef %s {\n", c_name(arg).full_name);
Lev Walkinf15320b2004-06-03 03:38:44 +0000804 }
805
Lev Walkin08079b02004-08-22 03:25:24 +0000806 INDENT(+1);
807 OUT("A_%s_OF(",
808 (arg->expr->expr_type == ASN_CONSTR_SET_OF)
809 ? "SET" : "SEQUENCE");
Lev Walkinda9a3b82005-08-16 17:00:21 +0000810
811 /*
812 * README README
813 * The implementation of the A_SET_OF() macro is already indirect.
814 */
815 memb->marker.flags |= EM_INDIRECT;
816
Lev Walkine0b56e02005-02-25 12:10:27 +0000817 if(memb->expr_type & ASN_CONSTR_MASK
818 || ((memb->expr_type == ASN_BASIC_ENUMERATED
Lev Walkin8ecf9db2005-03-03 21:28:12 +0000819 || (0 /* -- prohibited by X.693:8.3.4 */
820 && memb->expr_type == ASN_BASIC_INTEGER))
821 && expr_elements_count(arg, memb))) {
Lev Walkin08079b02004-08-22 03:25:24 +0000822 arg_t tmp;
823 asn1p_expr_t tmp_memb;
824 arg->embed++;
825 tmp = *arg;
826 tmp.expr = &tmp_memb;
827 tmp_memb = *memb;
Lev Walkinda9a3b82005-08-16 17:00:21 +0000828 tmp_memb.marker.flags &= ~EM_INDIRECT;
Lev Walkin08079b02004-08-22 03:25:24 +0000829 tmp_memb._anonymous_type = 1;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000830 if(tmp_memb.Identifier == 0) {
Lev Walkin21d00002005-03-04 08:48:53 +0000831 tmp_memb.Identifier = "Member";
832 if(0)
Lev Walkina9cc46e2004-09-22 16:06:28 +0000833 tmp_memb.Identifier = strdup(
834 asn1c_make_identifier(0,
Lev Walkina00d6b32006-03-21 03:40:38 +0000835 expr, "Member", 0));
Lev Walkina9cc46e2004-09-22 16:06:28 +0000836 assert(tmp_memb.Identifier);
837 }
Lev Walkin9de6cd82017-08-10 05:47:46 -0700838 tmp.default_cb(&tmp, NULL);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000839 if(tmp_memb.Identifier != memb->Identifier)
Lev Walkin21d00002005-03-04 08:48:53 +0000840 if(0) free(tmp_memb.Identifier);
Lev Walkin08079b02004-08-22 03:25:24 +0000841 arg->embed--;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800842 assert(arg->target->target == OT_TYPE_DECLS ||
843 arg->target->target == OT_FWD_DEFS);
Lev Walkin08079b02004-08-22 03:25:24 +0000844 } else {
Lev Walkinfe7f6ec2005-03-04 22:38:22 +0000845 OUT("%s", asn1c_type_name(arg, memb,
846 (memb->marker.flags & EM_UNRECURSE)
847 ? TNF_RSAFE : TNF_CTYPE));
Lev Walkinf15320b2004-06-03 03:38:44 +0000848 }
Lev Walkinda9a3b82005-08-16 17:00:21 +0000849 /* README README (above) */
850 if(0 && (memb->marker.flags & EM_INDIRECT))
851 OUT(" *");
Lev Walkin08079b02004-08-22 03:25:24 +0000852 OUT(") list;\n");
853 INDENT(-1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000854
855 PCTX_DEF;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800856
857 if (arg->embed && expr->_anonymous_type) {
Lev Walkinb46156d2017-09-05 02:53:05 -0700858 OUT("} %s%s;\n", (expr->marker.flags & EM_INDIRECT)?"*":"",
859 c_name(arg).base_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800860
861 REDIR(saved_target);
862
Lev Walkinb46156d2017-09-05 02:53:05 -0700863 OUT("%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
864 c_name(arg).base_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800865 } else {
Lev Walkinb46156d2017-09-05 02:53:05 -0700866 OUT("} %s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
867 c_name(arg).short_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800868 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000869
870 /*
Lev Walkin08079b02004-08-22 03:25:24 +0000871 * SET OF/SEQUENCE OF definition
Lev Walkinf15320b2004-06-03 03:38:44 +0000872 */
Lev Walkin08079b02004-08-22 03:25:24 +0000873 return asn1c_lang_C_type_SEx_OF_def(arg,
874 (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF));
Lev Walkinf15320b2004-06-03 03:38:44 +0000875}
876
877static int
878asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
879 asn1p_expr_t *expr = arg->expr;
880 asn1p_expr_t *v;
Lev Walkin64399722004-08-11 07:17:22 +0000881 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000882 int all_tags_count;
883 enum tvm_compat tv_mode;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800884 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000885
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000886 /*
Lev Walkin59b176e2005-11-26 11:25:14 +0000887 * Print out the table according to which parsing is performed.
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000888 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000889 if(seq_of) {
Lev Walkin22b5ed42006-09-13 02:51:20 +0000890 GEN_INCLUDE_STD("constr_SEQUENCE_OF");
Lev Walkinf15320b2004-06-03 03:38:44 +0000891 } else {
Lev Walkin22b5ed42006-09-13 02:51:20 +0000892 GEN_INCLUDE_STD("constr_SET_OF");
Lev Walkinf15320b2004-06-03 03:38:44 +0000893 }
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000894 if(!arg->embed)
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800895 GEN_DECLARE("SET_OF", expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000896
897 REDIR(OT_STAT_DEFS);
898
899 /*
Lev Walkin59b176e2005-11-26 11:25:14 +0000900 * Print out the table according to which parsing is performed.
Lev Walkinf15320b2004-06-03 03:38:44 +0000901 */
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800902 if(!(expr->_type_referenced)) OUT("static ");
903 OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000904 MKID(expr), expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000905 INDENT(+1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000906 v = TQ_FIRST(&(expr->members));
Lev Walkina9cc46e2004-09-22 16:06:28 +0000907 if(!v->Identifier) {
Lev Walkin152a91e2005-02-14 20:41:29 +0000908 v->Identifier = strdup("Member");
Lev Walkina9cc46e2004-09-22 16:06:28 +0000909 assert(v->Identifier);
910 }
911 v->_anonymous_type = 1;
912 arg->embed++;
Lev Walkin9de6cd82017-08-10 05:47:46 -0700913 emit_member_table(arg, v, NULL);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000914 arg->embed--;
Bi-Ruei, Chiu9b780832016-11-07 22:19:10 +0800915 free(v->Identifier);
916 v->Identifier = (char *)NULL;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000917 INDENT(-1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000918 OUT("};\n");
919
Lev Walkin27ea3802004-06-28 21:13:46 +0000920 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000921 * Print out asn_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +0000922 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000923 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000924
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800925 if(!(expr->_type_referenced)) OUT("static ");
926 OUT("asn_SET_OF_specifics_t asn_SPC_%s_specs_%d = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000927 MKID(expr), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +0000928 INDENTED(
Lev Walkinb46156d2017-09-05 02:53:05 -0700929 OUT("sizeof(%s),\n", c_name(arg).full_name);
930 OUT("offsetof(%s, _asn_ctx),\n", c_name(arg).full_name);
Lev Walkind1bfea62005-11-08 03:06:16 +0000931 {
932 int as_xvl = expr_as_xmlvaluelist(arg, v);
933 OUT("%d,\t/* XER encoding is %s */\n",
934 as_xvl,
935 as_xvl ? "XMLValueList" : "XMLDelimitedItemList");
936 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000937 );
938 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000939
940 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000941 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +0000942 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000943 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, 1,
Lev Walkin8de2ab22004-09-26 13:11:31 +0000944 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000945
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800946 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +0000947
948 return 0;
Lev Walkinb0b33412005-01-17 11:57:48 +0000949} /* _SEx_OF_def() */
Lev Walkinf15320b2004-06-03 03:38:44 +0000950
951int
952asn1c_lang_C_type_CHOICE(arg_t *arg) {
953 asn1p_expr_t *expr = arg->expr;
954 asn1p_expr_t *v;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800955 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000956
957 DEPENDENCIES;
958
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000959 REDIR(OT_DEPS);
960
Lev Walkinb46156d2017-09-05 02:53:05 -0700961 OUT("typedef %s {\n", c_name(arg).presence_enum);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000962 INDENTED(
Lev Walkin11380fb2006-08-18 01:38:40 +0000963 int skipComma = 1;
Lev Walkinb46156d2017-09-05 02:53:05 -0700964 OUT("%s,\t/* No components present */\n", c_presence_name(arg, 0));
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000965 TQ_FOR(v, &(expr->members), next) {
Lev Walkin11380fb2006-08-18 01:38:40 +0000966 if(skipComma) skipComma = 0;
johvik792216e2017-04-11 10:42:21 +0200967 else if (v->expr_type == A1TC_EXTENSIBLE && !TQ_NEXT(v, next)) OUT("\n");
Lev Walkin1dc85292006-08-18 01:32:26 +0000968 else OUT(",\n");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000969 if(v->expr_type == A1TC_EXTENSIBLE) {
970 OUT("/* Extensions may appear below */\n");
Lev Walkin11380fb2006-08-18 01:38:40 +0000971 skipComma = 1;
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000972 continue;
973 }
Lev Walkinb46156d2017-09-05 02:53:05 -0700974 OUT("%s", c_presence_name(arg, v));
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000975 }
Lev Walkin1dc85292006-08-18 01:32:26 +0000976 OUT("\n");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000977 );
Lev Walkinb46156d2017-09-05 02:53:05 -0700978 OUT("} %s;\n", c_name(arg).presence_name);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000979
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800980 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +0000981
982 if(arg->embed) {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800983 if (expr->_anonymous_type) {
984 REDIR(OT_FWD_DEFS);
985 OUT("typedef ");
986 }
Lev Walkinb46156d2017-09-05 02:53:05 -0700987 OUT("%s {\n", c_name(arg).full_name);
Lev Walkinf15320b2004-06-03 03:38:44 +0000988 } else {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800989 REDIR(OT_TYPE_DECLS);
Lev Walkinb46156d2017-09-05 02:53:05 -0700990 OUT("typedef %s {\n", c_name(arg).full_name);
Lev Walkinf15320b2004-06-03 03:38:44 +0000991 }
992
993 INDENTED(
Lev Walkinb46156d2017-09-05 02:53:05 -0700994 OUT("%s present;\n", c_name(arg).presence_name);
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000995 OUT("union ");
996 if(UNNAMED_UNIONS == 0) {
997 out_name_chain(arg, ONC_force_compound_name);
998 OUT("_u ");
999 }
1000 OUT("{\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001001 TQ_FOR(v, &(expr->members), next) {
1002 EMBED(v);
1003 }
1004 if(UNNAMED_UNIONS) OUT("};\n");
1005 else OUT("} choice;\n");
1006 );
1007
1008 PCTX_DEF;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001009
1010 if (arg->embed && expr->_anonymous_type) {
Lev Walkinb46156d2017-09-05 02:53:05 -07001011 OUT("} %s%s;\n", (expr->marker.flags & EM_INDIRECT)?"*":"",
1012 c_name(arg).base_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001013
1014 REDIR(saved_target);
1015
Lev Walkinb46156d2017-09-05 02:53:05 -07001016 OUT("%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
1017 c_name(arg).base_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001018 } else {
Lev Walkinb46156d2017-09-05 02:53:05 -07001019 OUT("} %s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
1020 c_name(arg).short_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001021 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001022
1023 return asn1c_lang_C_type_CHOICE_def(arg);
1024}
1025
Lev Walkinf6853ce2017-08-11 00:50:27 -07001026static ssize_t
1027find_column_index(arg_t *arg, asn1c_ioc_table_and_objset_t *opt_ioc, const char *column_name) {
1028 (void)arg;
1029
1030 if(!opt_ioc || !opt_ioc->ioct || !column_name) {
1031 return -1;
1032 }
1033
1034 if(opt_ioc->ioct->rows == 0) {
1035 return 0; /* No big deal. Just no data */
1036 } else {
1037 for(size_t clmn = 0; clmn < opt_ioc->ioct->row[0]->columns; clmn++) {
1038 if(strcmp(opt_ioc->ioct->row[0]->column[clmn].field->Identifier,
1039 column_name) == 0) {
1040 return clmn;
1041 }
1042 }
1043 return -1;
1044 }
1045
1046}
1047
1048static int
1049asn1c_lang_C_OpenType(arg_t *arg, asn1c_ioc_table_and_objset_t *opt_ioc,
1050 const char *column_name) {
1051 arg_t tmp_arg = *arg;
1052
1053 ssize_t column_index = find_column_index(arg, opt_ioc, column_name);
1054 if(column_index < 0) {
1055 FATAL("Open type generation attempted for %s, incomplete", column_name);
1056 return -1;
1057 }
1058
1059 asn1p_expr_t *open_type_choice =
1060 asn1p_expr_new(arg->expr->_lineno, arg->expr->module);
1061
1062 open_type_choice->Identifier = strdup(arg->expr->Identifier);
1063 open_type_choice->meta_type = AMT_TYPE;
1064 open_type_choice->expr_type = ASN_CONSTR_OPEN_TYPE;
1065 open_type_choice->_type_unique_index = arg->expr->_type_unique_index;
1066
1067 for(size_t row = 0; row < opt_ioc->ioct->rows; row++) {
1068 struct asn1p_ioc_cell_s *cell =
1069 &opt_ioc->ioct->row[row]->column[column_index];
1070
1071 asn1p_expr_t *m = asn1p_expr_clone(cell->value, 0);
1072 asn1p_expr_add(open_type_choice, m);
1073 }
1074
1075 tmp_arg.expr = open_type_choice;
1076 GEN_INCLUDE_STD("OPEN_TYPE");
1077 asn1c_lang_C_type_CHOICE(&tmp_arg);
1078 asn1p_expr_free(tmp_arg.expr);
1079 return 0;
1080}
1081
Lev Walkinf15320b2004-06-03 03:38:44 +00001082static int
1083asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
1084 asn1p_expr_t *expr = arg->expr;
1085 asn1p_expr_t *v;
1086 int elements; /* Number of elements */
Lev Walkinf15320b2004-06-03 03:38:44 +00001087 tag2el_t *tag2el = NULL;
1088 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +00001089 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +00001090 int all_tags_count;
1091 enum tvm_compat tv_mode;
Lev Walkin59b176e2005-11-26 11:25:14 +00001092 int *cmap = 0;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001093 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +00001094
1095 /*
1096 * Fetch every inner tag from the tag to elements map.
1097 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001098 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001099 if(tag2el) free(tag2el);
1100 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +00001101 }
1102
Lev Walkin22b5ed42006-09-13 02:51:20 +00001103 GEN_INCLUDE_STD("constr_CHOICE");
Lev Walkin3dcaafa2004-08-11 05:21:32 +00001104 if(!arg->embed)
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001105 GEN_DECLARE("CHOICE", expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +00001106
Lev Walkin3dcaafa2004-08-11 05:21:32 +00001107 REDIR(OT_STAT_DEFS);
Lev Walkinf15320b2004-06-03 03:38:44 +00001108
1109 /*
Lev Walkin59b176e2005-11-26 11:25:14 +00001110 * Print out the table according to which parsing is performed.
Lev Walkinf15320b2004-06-03 03:38:44 +00001111 */
Lev Walkina9cc46e2004-09-22 16:06:28 +00001112 if(expr_elements_count(arg, expr)) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001113
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001114 if(!(expr->_type_referenced)) OUT("static ");
1115 OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00001116 MKID(expr), expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +00001117
1118 elements = 0;
1119 INDENTED(TQ_FOR(v, &(expr->members), next) {
Lev Walkin659c63b2005-01-17 11:40:49 +00001120 if(v->expr_type == A1TC_EXTENSIBLE)
1121 continue;
Lev Walkin9de6cd82017-08-10 05:47:46 -07001122 emit_member_table(arg, v, NULL);
Lev Walkinda9a3b82005-08-16 17:00:21 +00001123 elements++;
Lev Walkina9cc46e2004-09-22 16:06:28 +00001124 });
1125 OUT("};\n");
1126 } else {
1127 elements = 0;
1128 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001129
Lev Walkin59b176e2005-11-26 11:25:14 +00001130 /* Create a canonical elements map */
1131 if(elements && (arg->flags & A1C_GEN_PER)) {
1132 int i;
1133 cmap = compute_canonical_members_order(arg, elements);
1134 if(cmap) {
Lev Walkinf6853ce2017-08-11 00:50:27 -07001135 OUT("static const unsigned asn_MAP_%s_cmap_%d[] = {",
Lev Walkina00d6b32006-03-21 03:40:38 +00001136 MKID(expr),
Lev Walkin59b176e2005-11-26 11:25:14 +00001137 expr->_type_unique_index);
1138 for(i = 0; i < elements; i++) {
1139 if(i) OUT(",");
1140 OUT(" %d", cmap[i]);
1141 }
1142 OUT(" };\n");
1143 free(cmap);
1144 }
1145 }
Lev Walkin64399722004-08-11 07:17:22 +00001146
Lev Walkinf15320b2004-06-03 03:38:44 +00001147 if(arg->embed) {
1148 /*
1149 * Our parent structure has already taken this into account.
1150 */
Lev Walkin188ed2c2004-09-13 08:31:01 +00001151 tv_mode = _TVM_SAME;
1152 tags_count = all_tags_count = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +00001153 } else {
Lev Walkin188ed2c2004-09-13 08:31:01 +00001154 tv_mode = emit_tags_vectors(arg, expr,
1155 &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +00001156 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001157
1158 /*
1159 * Tags to elements map.
1160 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001161 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +00001162
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001163 if(!(expr->_type_referenced)) OUT("static ");
1164 OUT("asn_CHOICE_specifics_t asn_SPC_%s_specs_%d = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00001165 MKID(expr), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +00001166 INDENTED(
Lev Walkinb46156d2017-09-05 02:53:05 -07001167 OUT("sizeof(%s),\n", c_name(arg).full_name);
1168 OUT("offsetof(%s, _asn_ctx),\n", c_name(arg).full_name);
1169 OUT("offsetof(%s, present),\n", c_name(arg).full_name);
1170 OUT("sizeof(((%s *)0)->present),\n", c_name(arg).full_name);
Lev Walkinade508c2017-08-23 10:19:30 -07001171 emit_tag2member_reference(arg, expr, tag2el_count);
Lev Walkin59b176e2005-11-26 11:25:14 +00001172 if(C99_MODE) OUT(".canonical_order = ");
1173 if(cmap) OUT("asn_MAP_%s_cmap_%d,\t/* Canonically sorted */\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00001174 MKID(expr), expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00001175 else OUT("0,\n");
1176 if(C99_MODE) OUT(".ext_start = ");
1177 OUT("%d\t/* Extensions start */\n",
1178 compute_extensions_start(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +00001179 );
1180 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +00001181
1182 /*
Lev Walkin05363a72004-09-29 13:16:40 +00001183 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +00001184 */
Lev Walkin188ed2c2004-09-13 08:31:01 +00001185 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
Lev Walkin8de2ab22004-09-26 13:11:31 +00001186 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +00001187
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001188 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +00001189
Bi-Ruei, Chiu12021b52016-11-04 11:59:45 +08001190 if (tag2el) free(tag2el);
1191
Lev Walkinf15320b2004-06-03 03:38:44 +00001192 return 0;
Lev Walkinb0b33412005-01-17 11:57:48 +00001193} /* _CHOICE_def() */
Lev Walkinf15320b2004-06-03 03:38:44 +00001194
1195int
1196asn1c_lang_C_type_REFERENCE(arg_t *arg) {
1197 asn1p_ref_t *ref;
1198
1199 ref = arg->expr->reference;
1200 if(ref->components[ref->comp_count-1].name[0] == '&') {
Lev Walkinf15320b2004-06-03 03:38:44 +00001201 asn1p_expr_t *extract;
1202 arg_t tmp;
1203 int ret;
1204
Lev Walkinc0e03b92017-08-22 01:48:23 -07001205 extract = WITH_MODULE_NAMESPACE(
1206 arg->expr->module, expr_ns,
1207 asn1f_class_access_ex(arg->asn, arg->expr->module, expr_ns,
1208 arg->expr, arg->expr->rhs_pspecs, ref));
1209 if(extract == NULL)
Lev Walkinf15320b2004-06-03 03:38:44 +00001210 return -1;
1211
Lev Walkin08079b02004-08-22 03:25:24 +00001212 extract = asn1p_expr_clone(extract, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +00001213 if(extract) {
Lev Walkind8b83642016-03-14 02:00:27 -07001214 free(extract->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +00001215 extract->Identifier = strdup(arg->expr->Identifier);
1216 if(extract->Identifier == NULL) {
1217 asn1p_expr_free(extract);
1218 return -1;
1219 }
1220 } else {
1221 return -1;
1222 }
1223
1224 tmp = *arg;
1225 tmp.asn = arg->asn;
Lev Walkinf15320b2004-06-03 03:38:44 +00001226 tmp.expr = extract;
1227
Lev Walkin9de6cd82017-08-10 05:47:46 -07001228 ret = arg->default_cb(&tmp, NULL);
Lev Walkinf15320b2004-06-03 03:38:44 +00001229
1230 asn1p_expr_free(extract);
1231
1232 return ret;
1233 }
1234
1235
1236 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
1237}
1238
1239int
1240asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
1241 asn1p_expr_t *expr = arg->expr;
Lev Walkin64399722004-08-11 07:17:22 +00001242 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +00001243 int all_tags_count;
1244 enum tvm_compat tv_mode;
Lev Walkine0b56e02005-02-25 12:10:27 +00001245 enum etd_spec etd_spec;
Lev Walkinb46156d2017-09-05 02:53:05 -07001246 const char *p;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001247 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +00001248
1249 if(arg->embed) {
Lev Walkin05363a72004-09-29 13:16:40 +00001250 enum tnfmt tnfmt = TNF_CTYPE;
1251
1252 /*
1253 * If this is an optional compound type,
1254 * refer it using "struct X" convention,
1255 * as it may recursively include the current structure.
1256 */
Lev Walkinc8285712005-03-04 22:18:20 +00001257 if(expr->marker.flags & (EM_INDIRECT | EM_UNRECURSE)) {
Lev Walkinb85a8132005-08-18 13:38:19 +00001258 if(terminal_structable(arg, expr)) {
Lev Walkinc8285712005-03-04 22:18:20 +00001259 tnfmt = TNF_RSAFE;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001260 if(saved_target != OT_FWD_DECLS) {
1261 REDIR(OT_FWD_DECLS);
1262 OUT("%s;\n",
1263 asn1c_type_name(arg, arg->expr, tnfmt));
1264 }
1265 REDIR(saved_target);
Lev Walkin05363a72004-09-29 13:16:40 +00001266 }
1267 }
1268
Lev Walkinf15320b2004-06-03 03:38:44 +00001269
Lev Walkinc8285712005-03-04 22:18:20 +00001270 OUT("%s", asn1c_type_name(arg, arg->expr, tnfmt));
Lev Walkine0b56e02005-02-25 12:10:27 +00001271 if(!expr->_anonymous_type) {
Lev Walkinc8285712005-03-04 22:18:20 +00001272 OUT("%s", (expr->marker.flags&EM_INDIRECT)?"\t*":"\t ");
Lev Walkina00d6b32006-03-21 03:40:38 +00001273 OUT("%s", MKID_safe(expr));
Lev Walkin59b176e2005-11-26 11:25:14 +00001274 if((expr->marker.flags & (EM_DEFAULT & ~EM_INDIRECT))
1275 == (EM_DEFAULT & ~EM_INDIRECT))
Lev Walkine0b56e02005-02-25 12:10:27 +00001276 OUT("\t/* DEFAULT %s */",
1277 asn1f_printable_value(
1278 expr->marker.default_value));
Lev Walkin59b176e2005-11-26 11:25:14 +00001279 else if((expr->marker.flags & EM_OPTIONAL)
1280 == EM_OPTIONAL)
Lev Walkine0b56e02005-02-25 12:10:27 +00001281 OUT("\t/* OPTIONAL */");
1282 }
1283
1284 } else {
1285 GEN_INCLUDE(asn1c_type_name(arg, expr, TNF_INCLUDE));
Lev Walkin59004fa2004-08-20 13:37:01 +00001286
1287 REDIR(OT_TYPE_DECLS);
Lev Walkine0b56e02005-02-25 12:10:27 +00001288
1289 OUT("typedef %s\t",
Lev Walkinc8285712005-03-04 22:18:20 +00001290 asn1c_type_name(arg, arg->expr, TNF_CTYPE));
Lev Walkine0b56e02005-02-25 12:10:27 +00001291 OUT("%s%s_t",
Lev Walkinc8285712005-03-04 22:18:20 +00001292 (expr->marker.flags & EM_INDIRECT)?"*":" ",
Lev Walkina00d6b32006-03-21 03:40:38 +00001293 MKID(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +00001294 }
1295
Lev Walkine0b56e02005-02-25 12:10:27 +00001296 if((expr->expr_type == ASN_BASIC_ENUMERATED)
Lev Walkin8ecf9db2005-03-03 21:28:12 +00001297 || (0 /* -- prohibited by X.693:8.3.4 */
1298 && expr->expr_type == ASN_BASIC_INTEGER
Lev Walkin8bb57a22007-12-03 13:41:36 +00001299 && expr_elements_count(arg, expr))
1300 || (expr->expr_type == ASN_BASIC_INTEGER
1301 && asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN)
1302 )
Lev Walkine0b56e02005-02-25 12:10:27 +00001303 etd_spec = ETD_HAS_SPECIFICS;
1304 else
1305 etd_spec = ETD_NO_SPECIFICS;
Lev Walkinf15320b2004-06-03 03:38:44 +00001306
Lev Walkin8de2ab22004-09-26 13:11:31 +00001307 /*
1308 * If this type just blindly refers the other type, alias it.
1309 * Type1 ::= Type2
1310 */
Lev Walkine0b56e02005-02-25 12:10:27 +00001311 if(arg->embed && etd_spec == ETD_NO_SPECIFICS) {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001312 REDIR(saved_target);
Lev Walkine0b56e02005-02-25 12:10:27 +00001313 return 0;
1314 }
Lev Walkin8de2ab22004-09-26 13:11:31 +00001315 if((!expr->constraints || (arg->flags & A1C_NO_CONSTRAINTS))
Lev Walkine0b56e02005-02-25 12:10:27 +00001316 && (arg->embed || expr->tag.tag_class == TC_NOCLASS)
Lev Walkin6938d042005-03-04 23:23:50 +00001317 && etd_spec == ETD_NO_SPECIFICS
1318 && 0 /* This shortcut is incompatible with XER */
1319 ) {
Lev Walkincf3f6eb2017-08-23 04:34:15 -07001320 const char *type_name;
Lev Walkin8de2ab22004-09-26 13:11:31 +00001321 REDIR(OT_FUNC_DECLS);
1322 type_name = asn1c_type_name(arg, expr, TNF_SAFE);
1323 OUT("/* This type is equivalent to %s */\n", type_name);
Lev Walkin8de2ab22004-09-26 13:11:31 +00001324 if(HIDE_INNER_DEFS) OUT("/* ");
Lev Walkina00d6b32006-03-21 03:40:38 +00001325 OUT("#define\tasn_DEF_%s\t", MKID(expr));
Lev Walkin8de2ab22004-09-26 13:11:31 +00001326 type_name = asn1c_type_name(arg, expr, TNF_SAFE);
Lev Walkine0b56e02005-02-25 12:10:27 +00001327 OUT("asn_DEF_%s", type_name);
Lev Walkin8de2ab22004-09-26 13:11:31 +00001328 if(HIDE_INNER_DEFS)
Lev Walkine0b56e02005-02-25 12:10:27 +00001329 OUT("\t// (Use -fall-defs-global to expose) */");
1330 OUT("\n");
Lev Walkin8de2ab22004-09-26 13:11:31 +00001331 REDIR(OT_CODE);
1332 OUT("/* This type is equivalent to %s */\n", type_name);
1333 OUT("\n");
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001334 REDIR(saved_target);
Lev Walkin8de2ab22004-09-26 13:11:31 +00001335 return 0;
1336 }
1337
Lev Walkin59004fa2004-08-20 13:37:01 +00001338 REDIR(OT_CODE);
1339
Lev Walkinf15320b2004-06-03 03:38:44 +00001340 /*
1341 * Constraint checking.
1342 */
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001343 if(!(arg->flags & A1C_NO_CONSTRAINTS) && expr->combined_constraints) {
Lev Walkina00d6b32006-03-21 03:40:38 +00001344 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001345 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkin8de2ab22004-09-26 13:11:31 +00001346 OUT("int\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001347 OUT("%s", p);
1348 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1349 OUT("_constraint(asn_TYPE_descriptor_t *td, const void *sptr,\n");
Lev Walkin8de2ab22004-09-26 13:11:31 +00001350 INDENT(+1);
Lev Walkin1eded352006-07-13 11:19:01 +00001351 OUT("\t\tasn_app_constraint_failed_f *ctfailcb, void *app_key) {");
Lev Walkin8de2ab22004-09-26 13:11:31 +00001352 OUT("\n");
Lev Walkin725883b2006-10-09 12:07:58 +00001353 DEBUG("expr constraint checking code for %s", p);
Lev Walkin8de2ab22004-09-26 13:11:31 +00001354 if(asn1c_emit_constraint_checking_code(arg) == 1) {
1355 OUT("/* Replace with underlying type checker */\n");
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +08001356 // OUT("td->check_constraints "
1357 // "= asn_DEF_%s.check_constraints;\n",
1358 // asn1c_type_name(arg, expr, TNF_SAFE));
Lev Walkin154519a2017-09-06 23:34:40 -07001359 OUT("return td->check_constraints"
Lev Walkin1eded352006-07-13 11:19:01 +00001360 "(td, sptr, ctfailcb, app_key);\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +00001361 }
Lev Walkin8de2ab22004-09-26 13:11:31 +00001362 INDENT(-1);
1363 OUT("}\n");
1364 OUT("\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001365 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001366
Lev Walkin725883b2006-10-09 12:07:58 +00001367 REDIR(OT_STAT_DEFS);
1368
1369 /*
1370 * Print out asn_DEF_<type>_[all_]tags[] vectors.
1371 */
1372 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
1373 DEBUG("emit tag vectors for %s %d, %d, %d", expr->Identifier,
1374 tv_mode, tags_count, all_tags_count);
1375
1376 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count,
1377 0, etd_spec);
1378
1379 REDIR(OT_CODE);
1380
Lev Walkinf15320b2004-06-03 03:38:44 +00001381 /*
1382 * Emit suicidal functions.
1383 */
1384
Lev Walkinf15320b2004-06-03 03:38:44 +00001385 /*
1386 * This function replaces certain fields from the definition
1387 * of a type with the corresponding fields from the basic type
1388 * (from which the current type is inherited).
1389 */
Lev Walkinf15320b2004-06-03 03:38:44 +00001390 OUT("/*\n");
Lev Walkin59004fa2004-08-20 13:37:01 +00001391 OUT(" * This type is implemented using %s,\n",
1392 asn1c_type_name(arg, expr, TNF_SAFE));
Lev Walkinb65b3002004-09-23 22:20:47 +00001393 OUT(" * so here we adjust the DEF accordingly.\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001394 OUT(" */\n");
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001395
1396#if 0 /* remove unnecessary functions */
Lev Walkinf15320b2004-06-03 03:38:44 +00001397 OUT("static void\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001398 OUT("%s_%d_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00001399 MKID(expr), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +00001400 INDENT(+1);
Lev Walkine0b56e02005-02-25 12:10:27 +00001401 {
Lev Walkinc0e03b92017-08-22 01:48:23 -07001402 asn1p_expr_t *terminal = asn1f_find_terminal_type_ex(arg->asn, asn->ns, expr);
Lev Walkin59004fa2004-08-20 13:37:01 +00001403 char *type_name = asn1c_type_name(arg, expr, TNF_SAFE);
Lev Walkin05363a72004-09-29 13:16:40 +00001404 OUT("td->free_struct = asn_DEF_%s.free_struct;\n", type_name);
1405 OUT("td->print_struct = asn_DEF_%s.print_struct;\n", type_name);
Lev Walkin6169b8d2013-12-07 11:02:44 -08001406 OUT("td->check_constraints = asn_DEF_%s.check_constraints;\n", type_name);
Lev Walkin05363a72004-09-29 13:16:40 +00001407 OUT("td->ber_decoder = asn_DEF_%s.ber_decoder;\n", type_name);
1408 OUT("td->der_encoder = asn_DEF_%s.der_encoder;\n", type_name);
1409 OUT("td->xer_decoder = asn_DEF_%s.xer_decoder;\n", type_name);
1410 OUT("td->xer_encoder = asn_DEF_%s.xer_encoder;\n", type_name);
Lev Walkin59b176e2005-11-26 11:25:14 +00001411 OUT("td->uper_decoder = asn_DEF_%s.uper_decoder;\n", type_name);
Lev Walkin1dc85292006-08-18 01:32:26 +00001412 OUT("td->uper_encoder = asn_DEF_%s.uper_encoder;\n", type_name);
Lev Walkinba68c912017-07-06 07:52:39 -07001413 OUT("td->oer_decoder = asn_DEF_%s.oer_decoder;\n", type_name);
1414 OUT("td->oer_encoder = asn_DEF_%s.oer_encoder;\n", type_name);
Lev Walkin906654e2004-09-10 15:49:15 +00001415 if(!terminal && !tags_count) {
Lev Walkin188ed2c2004-09-13 08:31:01 +00001416 OUT("/* The next four lines are here because of -fknown-extern-type */\n");
Lev Walkin05363a72004-09-29 13:16:40 +00001417 OUT("td->tags = asn_DEF_%s.tags;\n", type_name);
1418 OUT("td->tags_count = asn_DEF_%s.tags_count;\n", type_name);
1419 OUT("td->all_tags = asn_DEF_%s.all_tags;\n", type_name);
1420 OUT("td->all_tags_count = asn_DEF_%s.all_tags_count;\n",type_name);
Lev Walkin906654e2004-09-10 15:49:15 +00001421 OUT("/* End of these lines */\n");
1422 }
Lev Walkinb33425f2017-07-14 14:59:52 +04001423 OUT("if(!td->oer_constraints)\n");
1424 OUT("\ttd->oer_constraints = asn_DEF_%s.oer_constraints;\n",
1425 type_name);
Lev Walkin59b176e2005-11-26 11:25:14 +00001426 OUT("if(!td->per_constraints)\n");
1427 OUT("\ttd->per_constraints = asn_DEF_%s.per_constraints;\n",
1428 type_name);
Lev Walkin05363a72004-09-29 13:16:40 +00001429 OUT("td->elements = asn_DEF_%s.elements;\n", type_name);
1430 OUT("td->elements_count = asn_DEF_%s.elements_count;\n", type_name);
Lev Walkine0b56e02005-02-25 12:10:27 +00001431 if(etd_spec != ETD_NO_SPECIFICS) {
1432 INDENT(-1);
Lev Walkin7ef83a42005-03-29 19:04:24 +00001433 OUT(" /* ");
Lev Walkin59004fa2004-08-20 13:37:01 +00001434 }
Lev Walkine0b56e02005-02-25 12:10:27 +00001435 OUT("td->specifics = asn_DEF_%s.specifics;", type_name);
1436 if(etd_spec == ETD_NO_SPECIFICS) {
1437 INDENT(-1);
1438 OUT("\n");
1439 } else {
1440 OUT("\t// Defined explicitly */\n");
1441 }
1442 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001443 OUT("}\n");
1444 OUT("\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001445
Lev Walkina00d6b32006-03-21 03:40:38 +00001446 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001447 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001448 OUT("void\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001449 OUT("%s", p);
1450 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1451 OUT("_free(asn_TYPE_descriptor_t *td,\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001452 INDENTED(
Lev Walkina9cc46e2004-09-22 16:06:28 +00001453 OUT("\tvoid *struct_ptr, int contents_only) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001454 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1455 p, expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +00001456 OUT("td->free_struct(td, struct_ptr, contents_only);\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001457 );
1458 OUT("}\n");
1459 OUT("\n");
1460
Lev Walkina00d6b32006-03-21 03:40:38 +00001461 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001462 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkinf15320b2004-06-03 03:38:44 +00001463 OUT("int\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001464 OUT("%s", p);
1465 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1466 OUT("_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001467 INDENTED(
1468 OUT("\tint ilevel, asn_app_consume_bytes_f *cb, void *app_key) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001469 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1470 p, expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +00001471 OUT("return td->print_struct(td, struct_ptr, ilevel, cb, app_key);\n");
1472 );
1473 OUT("}\n");
1474 OUT("\n");
1475
Lev Walkina00d6b32006-03-21 03:40:38 +00001476 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001477 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkindc06f6b2004-10-20 15:50:55 +00001478 OUT("asn_dec_rval_t\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001479 OUT("%s", p);
1480 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1481 OUT("_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001482 INDENTED(
Lev Walkindd1512e2005-03-17 21:56:00 +00001483 OUT("\tvoid **structure, const void *bufptr, size_t size, int tag_mode) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001484 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1485 p, expr->_type_unique_index);
Lev Walkin05363a72004-09-29 13:16:40 +00001486 OUT("return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);\n");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001487 );
1488 OUT("}\n");
1489 OUT("\n");
1490
Lev Walkina00d6b32006-03-21 03:40:38 +00001491 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001492 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001493 OUT("asn_enc_rval_t\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001494 OUT("%s", p);
1495 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1496 OUT("_encode_der(asn_TYPE_descriptor_t *td,\n");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001497 INDENTED(
1498 OUT("\tvoid *structure, int tag_mode, ber_tlv_tag_t tag,\n");
1499 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001500 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1501 p, expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +00001502 OUT("return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);\n");
1503 );
1504 OUT("}\n");
1505 OUT("\n");
1506
Lev Walkina00d6b32006-03-21 03:40:38 +00001507 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001508 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkinca47c292004-10-23 13:34:00 +00001509 OUT("asn_dec_rval_t\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001510 OUT("%s", p);
1511 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1512 OUT("_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n");
Lev Walkinca47c292004-10-23 13:34:00 +00001513 INDENTED(
Lev Walkindd1512e2005-03-17 21:56:00 +00001514 OUT("\tvoid **structure, const char *opt_mname, const void *bufptr, size_t size) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001515 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1516 p, expr->_type_unique_index);
Lev Walkinca47c292004-10-23 13:34:00 +00001517 OUT("return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size);\n");
1518 );
1519 OUT("}\n");
1520 OUT("\n");
1521
Lev Walkina00d6b32006-03-21 03:40:38 +00001522 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001523 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001524 OUT("asn_enc_rval_t\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001525 OUT("%s", p);
1526 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1527 OUT("_encode_xer(asn_TYPE_descriptor_t *td, void *structure,\n");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001528 INDENTED(
1529 OUT("\tint ilevel, enum xer_encoder_flags_e flags,\n");
1530 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001531 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1532 p, expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +00001533 OUT("return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001534 );
1535 OUT("}\n");
1536 OUT("\n");
1537
Lev Walkinb33425f2017-07-14 14:59:52 +04001538 if(arg->flags & A1C_GEN_OER) {
1539 p = MKID(expr);
1540
1541 if(HIDE_INNER_DEFS) OUT("static ");
1542 OUT("asn_dec_rval_t\n");
1543 OUT("%s", p);
1544 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1545 OUT("_decode_oer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n");
1546 INDENTED(
1547 OUT("\tasn_oer_constraints_t *constraints, void **structure, const void *buffer, size_t size) {\n");
1548 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1549 p, expr->_type_unique_index);
1550 OUT("return td->oer_decoder(opt_codec_ctx, td, constraints, structure, buffer, size);\n");
1551 );
1552 OUT("}\n");
1553 OUT("\n");
1554
1555 p = MKID(expr);
1556 if(HIDE_INNER_DEFS) OUT("static ");
1557 OUT("asn_enc_rval_t\n");
1558 OUT("%s", p);
1559 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1560 OUT("_encode_oer(asn_TYPE_descriptor_t *td,\n");
1561 INDENTED(
1562 OUT("\tasn_oer_constraints_t *constraints,\n");
1563 OUT("\tvoid *structure, asn_app_consume_bytes_f *cb, void *app_key) {\n");
1564 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1565 p, expr->_type_unique_index);
1566 OUT("return td->uper_encoder(td, constraints, structure, cb, app_key);\n");
1567 );
1568 OUT("}\n");
1569 OUT("\n");
1570 }
1571
Lev Walkin59b176e2005-11-26 11:25:14 +00001572 if(arg->flags & A1C_GEN_PER) {
Lev Walkina00d6b32006-03-21 03:40:38 +00001573 p = MKID(expr);
Lev Walkin1dc85292006-08-18 01:32:26 +00001574
Lev Walkin59b176e2005-11-26 11:25:14 +00001575 if(HIDE_INNER_DEFS) OUT("static ");
1576 OUT("asn_dec_rval_t\n");
1577 OUT("%s", p);
1578 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1579 OUT("_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n");
1580 INDENTED(
1581 OUT("\tasn_per_constraints_t *constraints, void **structure, asn_per_data_t *per_data) {\n");
1582 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1583 p, expr->_type_unique_index);
1584 OUT("return td->uper_decoder(opt_codec_ctx, td, constraints, structure, per_data);\n");
1585 );
1586 OUT("}\n");
1587 OUT("\n");
Lev Walkin1dc85292006-08-18 01:32:26 +00001588
1589 p = MKID(expr);
1590 if(HIDE_INNER_DEFS) OUT("static ");
1591 OUT("asn_enc_rval_t\n");
1592 OUT("%s", p);
1593 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1594 OUT("_encode_uper(asn_TYPE_descriptor_t *td,\n");
1595 INDENTED(
1596 OUT("\tasn_per_constraints_t *constraints,\n");
1597 OUT("\tvoid *structure, asn_per_outp_t *per_out) {\n");
1598 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1599 p, expr->_type_unique_index);
1600 OUT("return td->uper_encoder(td, constraints, structure, per_out);\n");
1601 );
1602 OUT("}\n");
1603 OUT("\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00001604 }
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001605#endif
Lev Walkinf15320b2004-06-03 03:38:44 +00001606 REDIR(OT_FUNC_DECLS);
1607
Lev Walkina00d6b32006-03-21 03:40:38 +00001608 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001609 if(HIDE_INNER_DEFS) {
Lev Walkin21d00002005-03-04 08:48:53 +00001610 OUT("/* extern asn_TYPE_descriptor_t asn_DEF_%s_%d;"
1611 "\t// (Use -fall-defs-global to expose) */\n",
1612 p, expr->_type_unique_index);
Lev Walkine0b56e02005-02-25 12:10:27 +00001613 } else {
1614 OUT("extern asn_TYPE_descriptor_t asn_DEF_%s;\n", p);
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001615 if (etd_spec == ETD_HAS_SPECIFICS) {
1616 if((expr->expr_type == ASN_BASIC_ENUMERATED) ||
1617 (expr->expr_type == ASN_BASIC_INTEGER)) {
1618 if(expr->_type_referenced) {
Lev Walkin792641e2017-08-22 20:41:58 -07001619 OUT("extern const asn_INTEGER_specifics_t "
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001620 "asn_SPC_%s_specs_%d;\n", p, expr->_type_unique_index);
1621 }
1622 } else {
Lev Walkinc0e03b92017-08-22 01:48:23 -07001623 asn1p_expr_t *terminal = WITH_MODULE_NAMESPACE(
1624 expr->module, expr_ns,
1625 asn1f_find_terminal_type_ex(arg->asn, expr_ns, expr));
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001626
Lev Walkinc0e03b92017-08-22 01:48:23 -07001627 OUT("extern asn_%s_specifics_t ", asn1c_type_name(arg, terminal, TNF_SAFE));
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001628 OUT("asn_SPC_%s_specs_%d;\n", MKID(expr), expr->_type_unique_index);
1629 }
1630 }
Lev Walkine0b56e02005-02-25 12:10:27 +00001631 OUT("asn_struct_free_f %s_free;\n", p);
1632 OUT("asn_struct_print_f %s_print;\n", p);
1633 OUT("asn_constr_check_f %s_constraint;\n", p);
1634 OUT("ber_type_decoder_f %s_decode_ber;\n", p);
1635 OUT("der_type_encoder_f %s_encode_der;\n", p);
1636 OUT("xer_type_decoder_f %s_decode_xer;\n", p);
1637 OUT("xer_type_encoder_f %s_encode_xer;\n", p);
Lev Walkinb33425f2017-07-14 14:59:52 +04001638 if(arg->flags & A1C_GEN_OER) {
1639 OUT("oer_type_decoder_f %s_decode_oer;\n", p);
1640 OUT("oer_type_encoder_f %s_encode_oer;\n", p);
1641 }
Lev Walkin1dc85292006-08-18 01:32:26 +00001642 if(arg->flags & A1C_GEN_PER) {
Lev Walkin59b176e2005-11-26 11:25:14 +00001643 OUT("per_type_decoder_f %s_decode_uper;\n", p);
Lev Walkin1dc85292006-08-18 01:32:26 +00001644 OUT("per_type_encoder_f %s_encode_uper;\n", p);
1645 }
Lev Walkine0b56e02005-02-25 12:10:27 +00001646 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001647
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001648 REDIR(saved_target);
Lev Walkin3dcaafa2004-08-11 05:21:32 +00001649
Lev Walkinf15320b2004-06-03 03:38:44 +00001650 return 0;
1651}
1652
1653int
1654asn1c_lang_C_type_EXTENSIBLE(arg_t *arg) {
1655
1656 OUT("/*\n");
1657 OUT(" * This type is extensible,\n");
1658 OUT(" * possible extensions are below.\n");
1659 OUT(" */\n");
1660
1661 return 0;
1662}
1663
Lev Walkin59b176e2005-11-26 11:25:14 +00001664static int
1665compute_extensions_start(asn1p_expr_t *expr) {
Lev Walkin35631482004-07-01 00:52:50 +00001666 asn1p_expr_t *v;
Lev Walkin59b176e2005-11-26 11:25:14 +00001667 int eidx = 0;
Lev Walkin35631482004-07-01 00:52:50 +00001668 TQ_FOR(v, &(expr->members), next) {
Lev Walkin59b176e2005-11-26 11:25:14 +00001669 if(v->expr_type == A1TC_EXTENSIBLE)
1670 return eidx;
1671 eidx++;
Lev Walkin35631482004-07-01 00:52:50 +00001672 }
Lev Walkin59b176e2005-11-26 11:25:14 +00001673 return -1;
Lev Walkin35631482004-07-01 00:52:50 +00001674}
1675
Lev Walkinf15320b2004-06-03 03:38:44 +00001676static int
Lev Walkinc3e29402004-09-10 06:07:18 +00001677_print_tag(arg_t *arg, struct asn1p_type_tag_s *tag) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001678
1679 OUT("(");
Lev Walkinc3e29402004-09-10 06:07:18 +00001680 switch(tag->tag_class) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001681 case TC_UNIVERSAL: OUT("ASN_TAG_CLASS_UNIVERSAL"); break;
1682 case TC_APPLICATION: OUT("ASN_TAG_CLASS_APPLICATION"); break;
1683 case TC_CONTEXT_SPECIFIC: OUT("ASN_TAG_CLASS_CONTEXT"); break;
1684 case TC_PRIVATE: OUT("ASN_TAG_CLASS_PRIVATE"); break;
1685 case TC_NOCLASS:
1686 break;
1687 }
Lev Walkinda997b12017-08-04 01:38:41 -07001688 OUT(" | (%s << 2))", asn1p_itoa(tag->tag_value));
Lev Walkinf15320b2004-06-03 03:38:44 +00001689
1690 return 0;
1691}
1692
Lev Walkinfd171ef2004-06-06 07:20:17 +00001693
1694static int
1695_tag2el_cmp(const void *ap, const void *bp) {
1696 const tag2el_t *a = ap;
1697 const tag2el_t *b = bp;
1698 const struct asn1p_type_tag_s *ta = &a->el_tag;
1699 const struct asn1p_type_tag_s *tb = &b->el_tag;
1700
1701 if(ta->tag_class == tb->tag_class) {
1702 if(ta->tag_value == tb->tag_value) {
1703 /*
1704 * Sort by their respective positions.
1705 */
1706 if(a->el_no < b->el_no)
1707 return -1;
1708 else if(a->el_no > b->el_no)
1709 return 1;
1710 return 0;
1711 } else if(ta->tag_value < tb->tag_value)
1712 return -1;
1713 else
1714 return 1;
1715 } else if(ta->tag_class < tb->tag_class) {
1716 return -1;
1717 } else {
1718 return 1;
1719 }
1720}
1721
Lev Walkinf15320b2004-06-03 03:38:44 +00001722/*
1723 * For constructed types, number of external tags may be greater than
1724 * number of elements in the type because of CHOICE type.
1725 * T ::= SET { -- Three possible tags:
1726 * a INTEGER, -- One tag is here...
1727 * b Choice1 -- ... and two more tags are there.
1728 * }
1729 * Choice1 ::= CHOICE {
1730 * s1 IA5String,
1731 * s2 ObjectDescriptor
1732 * }
1733 */
1734static int
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001735_fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001736 asn1p_expr_t *expr = arg->expr;
1737 arg_t tmparg = *arg;
1738 asn1p_expr_t *v;
1739 int element = 0;
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001740 int original_count = *count;
1741 int sort_until = -1;
Lev Walkinf15320b2004-06-03 03:38:44 +00001742
1743 TQ_FOR(v, &(expr->members), next) {
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001744 if(v->expr_type == A1TC_EXTENSIBLE) {
1745 /*
Lev Walkine0b56e02005-02-25 12:10:27 +00001746 * CXER mandates sorting
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001747 * only for the root part.
1748 */
1749 if(flags == FTE_CANONICAL_XER
1750 && sort_until == -1)
1751 sort_until = *count;
Lev Walkinf15320b2004-06-03 03:38:44 +00001752 continue;
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001753 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001754
1755 tmparg.expr = v;
1756
1757 if(_add_tag2el_member(&tmparg, tag2el, count,
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001758 (el_no==-1)?element:el_no, flags)) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001759 return -1;
1760 }
1761
1762 element++;
1763 }
1764
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001765
1766 if(flags == FTE_CANONICAL_XER) {
1767 if(sort_until == -1) sort_until = *count;
1768 qsort((*tag2el) + original_count,
1769 sort_until - original_count,
1770 sizeof(**tag2el), _tag2el_cmp);
1771 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1772 && (sort_until - original_count) >= 1) {
1773 /* Only take in account the root component */
1774 *count = original_count + 1;
1775 }
1776 } else {
1777 /*
1778 * Sort the map according to canonical order of their
1779 * tags and element numbers.
1780 */
1781 qsort(*tag2el, *count, sizeof(**tag2el), _tag2el_cmp);
1782 }
Lev Walkinfd171ef2004-06-06 07:20:17 +00001783
Lev Walkin38abe792004-06-14 13:09:45 +00001784 /*
1785 * Initialize .toff_{first|last} members.
1786 */
1787 if(*count) {
1788 struct asn1p_type_tag_s *cur_tag = 0;
1789 tag2el_t *cur = *tag2el;
1790 tag2el_t *end = cur + *count;
1791 int occur, i;
1792 for(occur = 0; cur < end; cur++) {
1793 if(cur_tag == 0
1794 || cur_tag->tag_value != cur->el_tag.tag_value
1795 || cur_tag->tag_class != cur->el_tag.tag_class) {
1796 cur_tag = &cur->el_tag;
1797 occur = 0;
1798 } else {
1799 occur++;
1800 }
1801 cur->toff_first = -occur;
1802 for(i = 0; i >= -occur; i--)
1803 cur[i].toff_last = -i;
1804 }
1805 }
1806
Lev Walkinf15320b2004-06-03 03:38:44 +00001807 return 0;
1808}
1809
1810static int
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001811_add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001812 struct asn1p_type_tag_s tag;
1813 int ret;
1814
1815 assert(el_no >= 0);
1816
Lev Walkinc0e03b92017-08-22 01:48:23 -07001817 ret = WITH_MODULE_NAMESPACE(
1818 arg->expr->module, expr_ns,
1819 asn1f_fetch_outmost_tag(arg->asn, expr_ns, arg->expr->module, arg->expr,
1820 &tag, AFT_IMAGINARY_ANY));
1821 if(ret == 0) {
Lev Walkin201943e2004-09-04 04:42:29 +00001822 tag2el_t *te;
1823 int new_count = (*count) + 1;
Lev Walkinf15320b2004-06-03 03:38:44 +00001824 void *p;
Lev Walkin201943e2004-09-04 04:42:29 +00001825
Lev Walkinac7e2292004-09-05 10:42:33 +00001826 if(tag.tag_value == -1) {
1827 /*
1828 * This is an untagged ANY type,
1829 * proceed without adding a tag
1830 */
1831 return 0;
1832 }
1833
Lev Walkin201943e2004-09-04 04:42:29 +00001834 p = realloc(*tag2el, new_count * sizeof(tag2el_t));
Lev Walkinf15320b2004-06-03 03:38:44 +00001835 if(p) *tag2el = p;
1836 else return -1;
1837
Lev Walkin725883b2006-10-09 12:07:58 +00001838 if(0) DEBUG("Found tag for %s: %ld",
Lev Walkinf15320b2004-06-03 03:38:44 +00001839 arg->expr->Identifier,
1840 (long)tag.tag_value);
1841
Lev Walkin201943e2004-09-04 04:42:29 +00001842 te = &((*tag2el)[*count]);
1843 te->el_tag = tag;
1844 te->el_no = el_no;
1845 te->from_expr = arg->expr;
1846 *count = new_count;
Lev Walkinf15320b2004-06-03 03:38:44 +00001847 return 0;
1848 }
1849
1850 DEBUG("Searching tag in complex expression %s:%x at line %d",
1851 arg->expr->Identifier,
1852 arg->expr->expr_type,
1853 arg->expr->_lineno);
1854
1855 /*
1856 * Iterate over members of CHOICE type.
1857 */
1858 if(arg->expr->expr_type == ASN_CONSTR_CHOICE) {
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001859 return _fill_tag2el_map(arg, tag2el, count, el_no, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +00001860 }
1861
1862 if(arg->expr->expr_type == A1TC_REFERENCE) {
1863 arg_t tmp = *arg;
1864 asn1p_expr_t *expr;
Lev Walkinc0e03b92017-08-22 01:48:23 -07001865 expr = WITH_MODULE_NAMESPACE(
1866 tmp.expr->module, expr_ns,
1867 asn1f_lookup_symbol_ex(tmp.asn, expr_ns, tmp.expr,
1868 arg->expr->reference));
1869 if(expr) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001870 tmp.expr = expr;
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001871 return _add_tag2el_member(&tmp, tag2el, count, el_no, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +00001872 } else {
1873 FATAL("Cannot dereference %s at line %d",
1874 arg->expr->Identifier,
1875 arg->expr->_lineno);
1876 return -1;
1877 }
1878 }
1879
1880 DEBUG("No tag for %s at line %d",
1881 arg->expr->Identifier,
1882 arg->expr->_lineno);
1883
1884 return -1;
1885}
1886
1887static int
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001888emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier) {
Lev Walkinfd171ef2004-06-06 07:20:17 +00001889 asn1p_expr_t *expr = arg->expr;
Lev Walkinf3b29b12005-06-02 05:21:37 +00001890 int i;
1891
1892 if(!tag2el_count) return 0; /* No top level tags */
Lev Walkinfd171ef2004-06-06 07:20:17 +00001893
Wim Lewisfb6344e2014-07-28 12:16:01 -07001894 OUT("static const asn_TYPE_tag2member_t asn_MAP_%s_tag2el%s_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00001895 MKID(expr), opt_modifier?opt_modifier:"",
Lev Walkin59b176e2005-11-26 11:25:14 +00001896 expr->_type_unique_index);
Lev Walkinf3b29b12005-06-02 05:21:37 +00001897 for(i = 0; i < tag2el_count; i++) {
1898 OUT(" { ");
1899 _print_tag(arg, &tag2el[i].el_tag);
1900 OUT(", ");
1901 OUT("%d, ", tag2el[i].el_no);
1902 OUT("%d, ", tag2el[i].toff_first);
1903 OUT("%d ", tag2el[i].toff_last);
Lev Walkin4062b012013-10-11 14:29:38 -07001904 OUT("}%s /* %s",
Lev Walkinf3b29b12005-06-02 05:21:37 +00001905 (i + 1 < tag2el_count) ? "," : "",
Lev Walkin4062b012013-10-11 14:29:38 -07001906 tag2el[i].from_expr->Identifier);
1907 if(arg->flags & A1C_LINE_REFS)
1908 OUT("at %d", tag2el[i].from_expr->_lineno);
1909 OUT(" */\n");
Lev Walkinfd171ef2004-06-06 07:20:17 +00001910 }
1911 OUT("};\n");
1912
Lev Walkinf3b29b12005-06-02 05:21:37 +00001913 return 0;
Lev Walkinfd171ef2004-06-06 07:20:17 +00001914}
1915
Lev Walkin188ed2c2004-09-13 08:31:01 +00001916static enum tvm_compat
1917emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tags_count_r, int *all_tags_count_r) {
1918 struct asn1p_type_tag_s *tags = 0; /* Effective tags */
1919 struct asn1p_type_tag_s *all_tags = 0; /* The full array */
Lev Walkin64399722004-08-11 07:17:22 +00001920 int tags_count = 0;
Lev Walkin188ed2c2004-09-13 08:31:01 +00001921 int all_tags_count = 0;
1922 enum tvm_compat tv_mode = _TVM_SAME;
Lev Walkin906654e2004-09-10 15:49:15 +00001923 int i;
Lev Walkin27ea3802004-06-28 21:13:46 +00001924
Lev Walkin6d1220a2004-09-14 14:10:10 +00001925 /* Cleanup before proceeding. */
1926 *tags_count_r = 0;
1927 *all_tags_count_r = 0;
1928
Lev Walkin906654e2004-09-10 15:49:15 +00001929 /* Fetch a chain of tags */
Lev Walkinc0e03b92017-08-22 01:48:23 -07001930 tags_count = WITH_MODULE_NAMESPACE(
1931 expr->module, expr_ns,
1932 asn1f_fetch_tags(arg->asn, expr_ns, expr->module, expr, &tags, 0));
1933 if(tags_count < 0) {
Lev Walkin725883b2006-10-09 12:07:58 +00001934 DEBUG("fail to fetch tags for %s", expr->Identifier);
Lev Walkin6d1220a2004-09-14 14:10:10 +00001935 return -1;
Lev Walkin725883b2006-10-09 12:07:58 +00001936 }
Lev Walkin64399722004-08-11 07:17:22 +00001937
Lev Walkin188ed2c2004-09-13 08:31:01 +00001938 /* Fetch a chain of tags */
Lev Walkinc0e03b92017-08-22 01:48:23 -07001939 all_tags_count = WITH_MODULE_NAMESPACE(
1940 expr->module, expr_ns,
1941 asn1f_fetch_tags(arg->asn, expr_ns, expr->module, expr, &all_tags,
1942 AFT_FULL_COLLECT));
1943 if(all_tags_count < 0) {
Lev Walkind8b83642016-03-14 02:00:27 -07001944 free(tags);
Lev Walkin725883b2006-10-09 12:07:58 +00001945 DEBUG("fail to fetch tags chain for %s", expr->Identifier);
Lev Walkin188ed2c2004-09-13 08:31:01 +00001946 return -1;
Lev Walkin5a8219a2004-09-08 00:28:57 +00001947 }
Lev Walkin906654e2004-09-10 15:49:15 +00001948
Lev Walkin188ed2c2004-09-13 08:31:01 +00001949 assert(tags_count <= all_tags_count);
1950 assert((tags_count?0:1) == (all_tags_count?0:1));
Lev Walkin27ea3802004-06-28 21:13:46 +00001951
Lev Walkin188ed2c2004-09-13 08:31:01 +00001952 if(tags_count <= all_tags_count) {
1953 for(i = 0; i < tags_count; i++) {
1954 if(tags[i].tag_value != all_tags[i].tag_value
1955 || tags[i].tag_class != all_tags[i].tag_class) {
1956 tv_mode = _TVM_DIFFERENT;
1957 break;
1958 }
1959 }
1960 if(i == tags_count && tags_count < all_tags_count)
1961 tv_mode = _TVM_SUBSET;
1962 } else {
1963 tv_mode = _TVM_DIFFERENT;
1964 }
1965
1966#define EMIT_TAGS_TABLE(name, tags, tags_count) do { \
Wim Lewisfb6344e2014-07-28 12:16:01 -07001967 OUT("static const ber_tlv_tag_t asn_DEF_%s%s_tags_%d[] = {\n",\
Lev Walkina00d6b32006-03-21 03:40:38 +00001968 MKID(expr), name, \
Lev Walkin59b176e2005-11-26 11:25:14 +00001969 expr->_type_unique_index); \
Lev Walkin188ed2c2004-09-13 08:31:01 +00001970 INDENT(+1); \
1971 /* Print the array of collected tags */ \
1972 for(i = 0; i < tags_count; i++) { \
1973 if(i) OUT(",\n"); \
1974 _print_tag(arg, &tags[i]); \
1975 } \
1976 OUT("\n"); \
1977 INDENT(-1); \
1978 OUT("};\n"); \
1979 } while(0)
1980
1981 if(tags_count) {
1982 if(tv_mode == _TVM_SUBSET)
1983 EMIT_TAGS_TABLE("", all_tags, all_tags_count);
1984 else
1985 EMIT_TAGS_TABLE("", tags, tags_count);
1986 }
1987
1988 if(all_tags_count) {
1989 if(tv_mode == _TVM_DIFFERENT)
1990 EMIT_TAGS_TABLE("_all", all_tags, all_tags_count);
1991 }
1992
Lev Walkind8b83642016-03-14 02:00:27 -07001993 free(tags);
1994 free(all_tags);
Lev Walkin188ed2c2004-09-13 08:31:01 +00001995
1996 *tags_count_r = tags_count;
1997 *all_tags_count_r = all_tags_count;
1998
1999 return tv_mode;
Lev Walkin27ea3802004-06-28 21:13:46 +00002000}
Lev Walkin59004fa2004-08-20 13:37:01 +00002001
2002static int
Lev Walkin59964be2004-08-25 02:03:12 +00002003expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin59004fa2004-08-20 13:37:01 +00002004 asn1p_expr_t *topmost_parent;
2005 asn1p_expr_t *v;
2006 int elements = 0;
2007
Lev Walkinc0e03b92017-08-22 01:48:23 -07002008 topmost_parent = WITH_MODULE_NAMESPACE(
2009 expr->module, expr_ns,
2010 asn1f_find_terminal_type_ex(arg->asn, expr_ns, expr));
2011 if(!topmost_parent) return 0;
Lev Walkin59004fa2004-08-20 13:37:01 +00002012
Lev Walkine0b56e02005-02-25 12:10:27 +00002013 if(!(topmost_parent->expr_type & ASN_CONSTR_MASK)
Lev Walkin1b3a1352016-01-10 13:15:02 -08002014 && !(topmost_parent->expr_type == ASN_BASIC_INTEGER)
Lev Walkin0f262452016-01-10 13:33:08 -08002015 && !(topmost_parent->expr_type == ASN_BASIC_ENUMERATED)
2016 && !(topmost_parent->expr_type == ASN_BASIC_BIT_STRING))
Lev Walkin59004fa2004-08-20 13:37:01 +00002017 return 0;
2018
2019 TQ_FOR(v, &(topmost_parent->members), next) {
2020 if(v->expr_type != A1TC_EXTENSIBLE)
2021 elements++;
2022 }
2023
2024 return elements;
2025}
2026
Lev Walkin59b176e2005-11-26 11:25:14 +00002027static asn1p_expr_type_e
2028expr_get_type(arg_t *arg, asn1p_expr_t *expr) {
2029 asn1p_expr_t *terminal;
Lev Walkinc0e03b92017-08-22 01:48:23 -07002030 terminal = asn1f_find_terminal_type_ex(arg->asn, arg->ns, expr);
Lev Walkin59b176e2005-11-26 11:25:14 +00002031 if(terminal) return terminal->expr_type;
2032 return A1TC_INVALID;
2033}
2034
Lev Walkin725883b2006-10-09 12:07:58 +00002035static asn1c_integer_t
2036PER_FROM_alphabet_characters(asn1cnst_range_t *range) {
2037 asn1c_integer_t numchars = 0;
2038 if(range->el_count) {
2039 int i;
2040 for(i = 0; i < range->el_count; i++)
2041 numchars
2042 += PER_FROM_alphabet_characters(range->elements[i]);
2043 } else {
2044 assert(range->left.type == ARE_VALUE);
2045 assert(range->right.type == ARE_VALUE);
2046 numchars = 1 + (range->right.value - range->left.value);
2047 }
2048 return numchars;
2049}
2050
Lev Walkin4118ccf2017-08-02 10:37:31 -07002051static void
2052emit_single_member_OER_constraint_comment(arg_t *arg, asn1cnst_range_t *range, char *type) {
2053
2054 /*
2055 * Print some courtesy debug information.
2056 */
2057 if(range
2058 && (range->left.type == ARE_VALUE || range->right.type == ARE_VALUE)) {
2059 OUT("\t/* ");
2060 if(type) OUT("(%s", type);
2061 OUT("(");
2062 if(range->left.type == ARE_VALUE)
Lev Walkinda997b12017-08-04 01:38:41 -07002063 OUT("%s", asn1p_itoa(range->left.value));
Lev Walkin4118ccf2017-08-02 10:37:31 -07002064 else
2065 OUT("MIN");
2066 OUT("..");
2067 if(range->right.type == ARE_VALUE)
Lev Walkinda997b12017-08-04 01:38:41 -07002068 OUT("%s", asn1p_itoa(range->right.value));
Lev Walkin4118ccf2017-08-02 10:37:31 -07002069 else
2070 OUT("MAX");
2071 if(range->extensible) OUT(",...");
2072 if(type) OUT(")");
2073 OUT(") */");
2074 }
2075}
2076
2077static int
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002078emit_single_member_OER_constraint_value(arg_t *arg, asn1cnst_range_t *range) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07002079 if(!range) {
2080 /* oer_support.h: asn_oer_constraint_s */
2081 OUT("{ 0, 0 }");
2082 return 0;
2083 }
2084
2085 if(range->incompatible || range->not_OER_visible) {
2086 OUT("{ 0, 0 }");
Lev Walkin6713bcb2017-08-30 19:41:03 -07002087 } else if(range->left.type == ARE_VALUE && range->left.value >= 0
2088 && range->right.type == ARE_MAX) {
2089 OUT("{ 0, 1 }");
Lev Walkin4118ccf2017-08-02 10:37:31 -07002090 } else if(range->left.type == ARE_VALUE &&
2091 range->right.type == ARE_VALUE) {
2092 asn1c_integer_t lb = range->left.value;
2093 asn1c_integer_t ub = range->right.value;
2094 unsigned width = 0;
2095 unsigned positive = 0;
2096
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002097
Lev Walkin4118ccf2017-08-02 10:37:31 -07002098 if(lb >= 0) {
2099 /* X.969 08/2015 10.2(a) */
2100 if(ub <= 255) {
2101 width = 1;
2102 } else if(ub <= 65535) {
2103 width = 2;
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002104 } else if((unsigned long long)ub <= 4294967295UL) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07002105 width = 4;
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002106 } else if((unsigned long long)ub <= 18446744073709551615ULL) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07002107 width = 8;
2108 }
2109 positive = 1;
2110 } else {
2111 positive = 0;
2112 /* X.969 08/2015 10.2(b) - no lower bound or negative lower bound */
2113 if(lb >= -128 && ub <= 127) {
2114 width = 1;
2115 } else if(lb >= -32768 && ub <= 32767) {
2116 width = 2;
2117 } else if(lb >= -2147483648L && ub <= 2147483647L) {
2118 width = 4;
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002119 } else if(lb >= (-9223372036854775807LL-1)
Lev Walkin4118ccf2017-08-02 10:37:31 -07002120 && ub <= 9223372036854775807LL) {
2121 width = 8;
2122 }
2123 }
2124 OUT("{ %u, %u }", width, positive);
2125 } else {
2126 OUT("{ 0, 0 }");
2127 }
2128
2129 return 0;
2130}
2131
2132static int
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002133emit_single_member_OER_constraint_size(arg_t *arg, asn1cnst_range_t *range) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07002134 if(!range) {
2135 /* oer_support.h: asn_oer_constraint_s */
2136 OUT("-1");
2137 return 0;
2138 }
2139
2140 if(range->incompatible || range->not_OER_visible) {
2141 OUT("-1");
2142 } else {
2143 if(range->left.type == ARE_VALUE && range->right.type == ARE_VALUE
2144 && range->left.value == range->right.value
2145 && range->left.value >= 0) {
Lev Walkinda997b12017-08-04 01:38:41 -07002146 OUT("%s", asn1p_itoa(range->left.value));
Lev Walkin4118ccf2017-08-02 10:37:31 -07002147 } else {
2148 OUT("-1");
2149 }
2150 }
2151
2152 return 0;
2153}
2154
Lev Walkin59b176e2005-11-26 11:25:14 +00002155static int
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002156emit_single_member_PER_constraint(arg_t *arg, asn1cnst_range_t *range, int alphabetsize, const char *type) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07002157 if(!range || range->incompatible || range->not_PER_visible) {
2158 OUT("{ APC_UNCONSTRAINED,\t-1, -1, 0, 0 }");
Lev Walkin59b176e2005-11-26 11:25:14 +00002159 return 0;
Lev Walkin4118ccf2017-08-02 10:37:31 -07002160 }
Lev Walkin59b176e2005-11-26 11:25:14 +00002161
Lev Walkin4118ccf2017-08-02 10:37:31 -07002162 if(range->left.type == ARE_VALUE) {
Lev Walkin59b176e2005-11-26 11:25:14 +00002163 if(range->right.type == ARE_VALUE) {
2164 asn1c_integer_t cover = 1;
2165 asn1c_integer_t r = 1 + range->right.value
2166 - range->left.value;
Lev Walkinc46b7cb2006-08-18 02:27:55 +00002167 size_t rbits; /* Value range bits */
2168 ssize_t ebits; /* Value effective range bits */
Lev Walkin59b176e2005-11-26 11:25:14 +00002169
2170 if(range->empty_constraint)
2171 r = 0;
2172
Lev Walkin725883b2006-10-09 12:07:58 +00002173 if(alphabetsize) {
2174 /* X.691: 27.5.2 */
2175 r = PER_FROM_alphabet_characters(range);
2176 }
2177
Lev Walkin59b176e2005-11-26 11:25:14 +00002178 /* Compute real constraint */
2179 for(rbits = 0; rbits < (8 * sizeof(r)); rbits++) {
2180 if(r <= cover)
2181 break;
2182 cover *= 2; /* Can't do shifting */
2183 if(cover < 0) {
2184 FATAL("Constraint at line %d too wide "
2185 "for %d-bits integer type",
2186 arg->expr->_lineno,
2187 sizeof(r) * 8);
2188 rbits = sizeof(r);
2189 break;
2190 }
2191 }
2192
Lev Walkin3a4689a2006-11-24 11:20:27 +00002193 if(alphabetsize) {
2194 ebits = rbits;
2195 } else {
Lev Walkin59b176e2005-11-26 11:25:14 +00002196 /* X.691, #10.9.4.1 */
2197 for(ebits = 0; ebits <= 16; ebits++)
2198 if(r <= 1 << ebits) break;
2199 if(ebits == 17
2200 || range->right.value >= 65536)
2201 ebits = -1;
Lev Walkin3a4689a2006-11-24 11:20:27 +00002202 if(0) {
Lev Walkin59b176e2005-11-26 11:25:14 +00002203 /* X.691, #10.5.7.1 */
2204 for(ebits = 0; ebits <= 8; ebits++)
2205 if(r <= 1 << ebits) break;
2206 if(ebits == 9) {
2207 if(r <= 65536)
2208 ebits = 16;
2209 else
2210 ebits = -1;
2211 }
2212 }
Lev Walkin3a4689a2006-11-24 11:20:27 +00002213 }
Lev Walkin725883b2006-10-09 12:07:58 +00002214
Lev Walkin59b176e2005-11-26 11:25:14 +00002215 OUT("{ APC_CONSTRAINED%s,%s% d, % d, ",
2216 range->extensible
2217 ? " | APC_EXTENSIBLE" : "",
2218 range->extensible ? " " : "\t", rbits, ebits);
Lev Walkin3a4689a2006-11-24 11:20:27 +00002219
2220 if(alphabetsize) {
2221 asn1c_integer_t lv = range->left.value;
2222 asn1c_integer_t rv = range->right.value;
2223 int gcmt = 0;
2224 if(lv > 0x7fffffff) { lv = 0x7fffffff; gcmt++; }
2225 if(rv > 0x7fffffff) { rv = 0x7fffffff; gcmt++; }
2226 if(gcmt) {
Lev Walkin63b41262007-11-06 01:48:46 +00002227 OINTS(lv); OUT(", "); OINTS(rv); OUT(" }");
Lev Walkin3a4689a2006-11-24 11:20:27 +00002228 goto pcmt;
2229 }
2230 }
Lev Walkin59b176e2005-11-26 11:25:14 +00002231 } else {
2232 if(range->extensible) {
2233 OUT("{ APC_SEMI_CONSTRAINED | APC_EXTENSIBLE, "
2234 "-1, ");
2235 } else {
2236 OUT("{ APC_SEMI_CONSTRAINED,\t-1, -1, ");
2237 }
2238 }
Lev Walkin63b41262007-11-06 01:48:46 +00002239 OINTS(range->left.value); OUT(", ");
2240 OINTS(range->right.value); OUT(" }");
Lev Walkin59b176e2005-11-26 11:25:14 +00002241 } else {
2242 OUT("{ APC_UNCONSTRAINED,\t-1, -1, 0, 0 }");
2243 }
2244
Lev Walkin3a4689a2006-11-24 11:20:27 +00002245 pcmt:
2246
Lev Walkin59b176e2005-11-26 11:25:14 +00002247 /*
2248 * Print some courtesy debug information.
2249 */
2250 if(range->left.type == ARE_VALUE
2251 || range->right.type == ARE_VALUE) {
2252 OUT("\t/* ");
2253 if(type) OUT("(%s", type);
2254 OUT("(");
2255 if(range->left.type == ARE_VALUE)
Lev Walkinda997b12017-08-04 01:38:41 -07002256 OUT("%s", asn1p_itoa(range->left.value));
Lev Walkin59b176e2005-11-26 11:25:14 +00002257 else
2258 OUT("MIN");
2259 OUT("..");
2260 if(range->right.type == ARE_VALUE)
Lev Walkinda997b12017-08-04 01:38:41 -07002261 OUT("%s", asn1p_itoa(range->right.value));
Lev Walkin59b176e2005-11-26 11:25:14 +00002262 else
2263 OUT("MAX");
2264 if(range->extensible) OUT(",...");
2265 if(type) OUT(")");
2266 OUT(") */");
2267 }
2268
2269 return 0;
2270}
2271
2272static int
Lev Walkin98eabc12017-07-19 08:51:11 +04002273emit_member_OER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx) {
2274 int save_target = arg->target->target;
2275 asn1cnst_range_t *range;
2276 asn1p_expr_type_e etype;
2277
2278 etype = expr_get_type(arg, expr);
2279
2280 if((arg->flags & A1C_GEN_OER)
Lev Walkin135d7dd2017-08-28 00:21:38 -07002281 && (expr->combined_constraints || etype == ASN_BASIC_ENUMERATED
Lev Walkin98eabc12017-07-19 08:51:11 +04002282 || etype == ASN_CONSTR_CHOICE)) {
2283 /* Fall through */
2284 } else {
2285 return 0;
2286 }
2287
2288 REDIR(OT_CTDEFS);
2289
2290 OUT("static asn_oer_constraints_t "
2291 "asn_OER_%s_%s_constr_%d GCC_NOTUSED = {\n",
2292 pfx, MKID(expr), expr->_type_unique_index);
2293
2294 INDENT(+1);
2295
Lev Walkin4118ccf2017-08-02 10:37:31 -07002296 /* .value{.width,.positive} */
Lev Walkina28cbb92017-07-31 20:20:17 -07002297 range = asn1constraint_compute_OER_range(expr->Identifier, etype,
2298 expr->combined_constraints,
Lev Walkin98eabc12017-07-19 08:51:11 +04002299 ACT_EL_RANGE, 0, 0, 0);
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002300 if(emit_single_member_OER_constraint_value(arg, range)) {
Lev Walkin98eabc12017-07-19 08:51:11 +04002301 return -1;
2302 }
Lev Walkin4118ccf2017-08-02 10:37:31 -07002303 emit_single_member_OER_constraint_comment(arg, range, 0);
Lev Walkin98eabc12017-07-19 08:51:11 +04002304 asn1constraint_range_free(range);
2305
2306 OUT(",\n");
2307
Lev Walkin4118ccf2017-08-02 10:37:31 -07002308 /* .size */
Lev Walkina28cbb92017-07-31 20:20:17 -07002309 range = asn1constraint_compute_OER_range(expr->Identifier, etype,
2310 expr->combined_constraints,
Lev Walkin98eabc12017-07-19 08:51:11 +04002311 ACT_CT_SIZE, 0, 0, 0);
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002312 if(emit_single_member_OER_constraint_size(arg, range)) {
Lev Walkin98eabc12017-07-19 08:51:11 +04002313 return -1;
2314 }
Lev Walkin4118ccf2017-08-02 10:37:31 -07002315 emit_single_member_OER_constraint_comment(arg, range, "SIZE");
Lev Walkin98eabc12017-07-19 08:51:11 +04002316 asn1constraint_range_free(range);
2317
2318 INDENT(-1);
2319
2320 OUT("};\n");
2321
2322 REDIR(save_target);
2323
2324 return 0;
2325}
2326
2327static int
Lev Walkin4b5dae32006-10-09 12:27:44 +00002328emit_member_PER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx) {
Lev Walkin725883b2006-10-09 12:07:58 +00002329 int save_target = arg->target->target;
Lev Walkin59b176e2005-11-26 11:25:14 +00002330 asn1cnst_range_t *range;
2331 asn1p_expr_type_e etype;
2332
Lev Walkin07aaa342006-10-09 12:52:15 +00002333 etype = expr_get_type(arg, expr);
2334
Lev Walkin725883b2006-10-09 12:07:58 +00002335 if((arg->flags & A1C_GEN_PER)
Lev Walkin135d7dd2017-08-28 00:21:38 -07002336 && (expr->combined_constraints
Lev Walkin07aaa342006-10-09 12:52:15 +00002337 || etype == ASN_BASIC_ENUMERATED
2338 || etype == ASN_CONSTR_CHOICE)
Lev Walkin725883b2006-10-09 12:07:58 +00002339 ) {
2340 /* Fall through */
2341 } else {
2342 return 0;
2343 }
2344
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002345 if(expr->_type_referenced) {
2346 REDIR(OT_FUNC_DECLS);
2347
2348 OUT("extern asn_per_constraints_t "
2349 "asn_PER_%s_%s_constr_%d;\n",
2350 pfx, MKID(expr), expr->_type_unique_index);
2351 }
2352
Lev Walkin725883b2006-10-09 12:07:58 +00002353 REDIR(OT_CTDEFS);
2354
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002355 if(!(expr->_type_referenced)) OUT("static ");
2356 OUT("asn_per_constraints_t "
Lev Walkin1715b322013-03-28 04:02:13 -07002357 "asn_PER_%s_%s_constr_%d GCC_NOTUSED = {\n",
Lev Walkin4b5dae32006-10-09 12:27:44 +00002358 pfx, MKID(expr), expr->_type_unique_index);
Lev Walkin725883b2006-10-09 12:07:58 +00002359
Lev Walkin59b176e2005-11-26 11:25:14 +00002360 INDENT(+1);
2361
2362 /*
2363 * ENUMERATED and CHOICE are special.
2364 */
2365 if(etype == ASN_BASIC_ENUMERATED
2366 || etype == ASN_CONSTR_CHOICE) {
2367 asn1cnst_range_t tmprng;
2368 asn1p_expr_t *v;
2369 int extensible = 0;
2370 int eidx = -1;
2371
Lev Walkinc0e03b92017-08-22 01:48:23 -07002372 expr = asn1f_find_terminal_type_ex(arg->asn, arg->ns, expr);
Lev Walkin59b176e2005-11-26 11:25:14 +00002373 assert(expr);
2374
2375 TQ_FOR(v, &(expr->members), next) {
2376 if(v->expr_type == A1TC_EXTENSIBLE) {
2377 extensible++;
2378 break;
2379 }
2380 eidx++;
2381 }
2382
2383 memset(&tmprng, 0, sizeof (tmprng));
2384 tmprng.extensible = extensible;
2385 if(eidx < 0) tmprng.empty_constraint = 1;
2386 tmprng.left.type = ARE_VALUE;
2387 tmprng.left.value = 0;
2388 tmprng.right.type = ARE_VALUE;
2389 tmprng.right.value = eidx < 0 ? 0 : eidx;
Lev Walkin725883b2006-10-09 12:07:58 +00002390 if(emit_single_member_PER_constraint(arg, &tmprng, 0, 0))
Lev Walkin59b176e2005-11-26 11:25:14 +00002391 return -1;
Lev Walkin729eb862006-09-21 01:50:13 +00002392 } else if(etype & ASN_STRING_KM_MASK) {
Lev Walkina28cbb92017-07-31 20:20:17 -07002393 range = asn1constraint_compute_PER_range(expr->Identifier, etype,
Lev Walkin729eb862006-09-21 01:50:13 +00002394 expr->combined_constraints, ACT_CT_FROM,
2395 0, 0, 0);
Lev Walkin725883b2006-10-09 12:07:58 +00002396 DEBUG("Emitting FROM constraint for %s", expr->Identifier);
Lev Walkin3a4689a2006-11-24 11:20:27 +00002397
2398 if((range->left.type == ARE_MIN && range->right.type == ARE_MAX)
2399 || range->not_PER_visible) {
2400 switch(etype) {
2401 case ASN_STRING_BMPString:
2402 range->left.type = ARE_VALUE;
2403 range->left.value = 0;
2404 range->right.type = ARE_VALUE;
2405 range->right.value = 65535;
2406 range->not_PER_visible = 0;
2407 range->extensible = 0;
2408 break;
2409 case ASN_STRING_UniversalString:
2410 OUT("{ APC_CONSTRAINED,\t32, 32,"
2411 " 0, 2147483647 }"
2412 " /* special case 1 */\n");
2413 goto avoid;
2414 default:
2415 break;
2416 }
2417 }
Lev Walkin725883b2006-10-09 12:07:58 +00002418 if(emit_single_member_PER_constraint(arg, range, 1, 0))
Lev Walkin729eb862006-09-21 01:50:13 +00002419 return -1;
Lev Walkin3a4689a2006-11-24 11:20:27 +00002420 avoid:
Lev Walkin729eb862006-09-21 01:50:13 +00002421 asn1constraint_range_free(range);
Lev Walkin59b176e2005-11-26 11:25:14 +00002422 } else {
Lev Walkina28cbb92017-07-31 20:20:17 -07002423 range = asn1constraint_compute_PER_range(expr->Identifier, etype,
Lev Walkin59b176e2005-11-26 11:25:14 +00002424 expr->combined_constraints, ACT_EL_RANGE,
2425 0, 0, 0);
Lev Walkin725883b2006-10-09 12:07:58 +00002426 if(emit_single_member_PER_constraint(arg, range, 0, 0))
Lev Walkin59b176e2005-11-26 11:25:14 +00002427 return -1;
2428 asn1constraint_range_free(range);
2429 }
2430 OUT(",\n");
2431
Lev Walkina28cbb92017-07-31 20:20:17 -07002432 range = asn1constraint_compute_PER_range(expr->Identifier, etype,
Lev Walkin59b176e2005-11-26 11:25:14 +00002433 expr->combined_constraints, ACT_CT_SIZE, 0, 0, 0);
Lev Walkin725883b2006-10-09 12:07:58 +00002434 if(emit_single_member_PER_constraint(arg, range, 0, "SIZE"))
Lev Walkin59b176e2005-11-26 11:25:14 +00002435 return -1;
2436 asn1constraint_range_free(range);
Lev Walkin725883b2006-10-09 12:07:58 +00002437 OUT(",\n");
2438
2439 if((etype & ASN_STRING_KM_MASK) && (expr->_mark & TM_PERFROMCT)) {
2440 int old_target = arg->target->target;
2441 REDIR(OT_CODE);
2442
2443 OUT("static int asn_PER_MAP_%s_%d_v2c(unsigned int value) {\n",
2444 MKID(expr), expr->_type_unique_index);
2445 OUT("\tif(value >= sizeof(permitted_alphabet_table_%d)/"
2446 "sizeof(permitted_alphabet_table_%d[0]))\n",
2447 expr->_type_unique_index,
2448 expr->_type_unique_index);
2449 OUT("\t\treturn -1;\n");
2450 OUT("\treturn permitted_alphabet_table_%d[value] - 1;\n",
2451 expr->_type_unique_index);
2452 OUT("}\n");
2453
2454 OUT("static int asn_PER_MAP_%s_%d_c2v(unsigned int code) {\n",
2455 MKID(expr), expr->_type_unique_index);
2456 OUT("\tif(code >= sizeof(permitted_alphabet_code2value_%d)/"
2457 "sizeof(permitted_alphabet_code2value_%d[0]))\n",
2458 expr->_type_unique_index,
2459 expr->_type_unique_index);
2460 OUT("\t\treturn -1;\n");
2461 OUT("\treturn permitted_alphabet_code2value_%d[code];\n",
2462 expr->_type_unique_index);
2463 OUT("}\n");
2464
2465 REDIR(old_target);
2466
2467 OUT("asn_PER_MAP_%s_%d_v2c,\t/* Value to PER code map */\n",
2468 MKID(expr), expr->_type_unique_index);
2469 OUT("asn_PER_MAP_%s_%d_c2v\t/* PER code to value map */\n",
2470 MKID(expr), expr->_type_unique_index);
2471 } else if(etype & ASN_STRING_KM_MASK) {
2472 DEBUG("No PER value map necessary for %s", MKID(expr));
2473 OUT("0, 0\t/* No PER character map necessary */\n");
2474 } else {
2475 OUT("0, 0\t/* No PER value map */\n");
2476 }
Lev Walkin59b176e2005-11-26 11:25:14 +00002477
2478 INDENT(-1);
2479
Lev Walkin725883b2006-10-09 12:07:58 +00002480 OUT("};\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002481
Lev Walkin725883b2006-10-09 12:07:58 +00002482 REDIR(save_target);
Lev Walkin59b176e2005-11-26 11:25:14 +00002483
2484 return 0;
2485}
2486
2487static int
Lev Walkin8032f7a2007-06-27 01:54:57 +00002488safe_string(const uint8_t *buf, int size) {
2489 const uint8_t *end = buf + size;
2490 for(; buf < end; buf++) {
2491 int ch = *buf;
2492 if((ch < 0x20 || ch > 0x7e) || ch == '"')
2493 return 0;
2494 }
2495 return 1;
2496}
2497
2498static void
2499emit_default_value(arg_t *arg, asn1p_value_t *v) {
2500
2501 OUT("static uint8_t defv[] = ");
2502 assert(v->type == ATV_STRING);
2503
2504 if(safe_string(v->value.string.buf, v->value.string.size)) {
2505 OUT("\"%s\";\n", v->value.string.buf);
2506 } else {
2507 uint8_t *b = v->value.string.buf;
2508 uint8_t *e = v->value.string.size + b;
2509 OUT("{ ");
2510 for(;b < e; b++)
2511 OUT("0x%02x, ", *b);
2512 OUT("0 };\n");
2513 }
2514}
2515
2516static int
Lev Walkin59b176e2005-11-26 11:25:14 +00002517try_inline_default(arg_t *arg, asn1p_expr_t *expr, int out) {
2518 int save_target = arg->target->target;
2519 asn1p_expr_type_e etype = expr_get_type(arg, expr);
2520 int fits_long = 0;
2521
2522 switch(etype) {
2523 case ASN_BASIC_BOOLEAN:
2524 fits_long = 1;
2525 case ASN_BASIC_INTEGER:
2526 case ASN_BASIC_ENUMERATED:
2527 if(expr->marker.default_value == NULL
Ryan Sleevia93d9972017-08-16 18:27:46 -04002528 || (expr->marker.default_value->type != ATV_INTEGER &&
2529 expr->marker.default_value->type != ATV_TRUE &&
2530 expr->marker.default_value->type != ATV_FALSE))
Lev Walkin59b176e2005-11-26 11:25:14 +00002531 break;
2532 if(!fits_long)
2533 fits_long = asn1c_type_fits_long(arg, expr)!=FL_NOTFIT;
2534 if(fits_long && !expr->marker.default_value->value.v_integer)
2535 expr->marker.flags &= ~EM_INDIRECT;
Lev Walkin8032f7a2007-06-27 01:54:57 +00002536 if(!out) {
Lev Walkinda997b12017-08-04 01:38:41 -07002537 OUT("asn_DFL_%d_set_%s,",
Lev Walkin8032f7a2007-06-27 01:54:57 +00002538 expr->_type_unique_index,
Lev Walkinda997b12017-08-04 01:38:41 -07002539 asn1p_itoa(expr->marker.default_value->value.v_integer));
2540 OUT("\t/* DEFAULT %s */\n",
2541 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin8032f7a2007-06-27 01:54:57 +00002542 return 1;
2543 }
Lev Walkin59b176e2005-11-26 11:25:14 +00002544 REDIR(OT_STAT_DEFS);
Lev Walkinda997b12017-08-04 01:38:41 -07002545 OUT("static int asn_DFL_%d_set_%s(int set_value, void **sptr) {\n",
Lev Walkin59b176e2005-11-26 11:25:14 +00002546 expr->_type_unique_index,
Lev Walkinda997b12017-08-04 01:38:41 -07002547 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin59b176e2005-11-26 11:25:14 +00002548 INDENT(+1);
2549 OUT("%s *st = *sptr;\n", asn1c_type_name(arg, expr, TNF_CTYPE));
2550 OUT("\n");
2551 OUT("if(!st) {\n");
Lev Walkin1dc85292006-08-18 01:32:26 +00002552 OUT("\tif(!set_value) return -1;\t/* Not a default value */\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002553 OUT("\tst = (*sptr = CALLOC(1, sizeof(*st)));\n");
2554 OUT("\tif(!st) return -1;\n");
2555 OUT("}\n");
2556 OUT("\n");
Lev Walkin1dc85292006-08-18 01:32:26 +00002557 OUT("if(set_value) {\n");
2558 INDENT(+1);
Lev Walkinda997b12017-08-04 01:38:41 -07002559 OUT("/* Install default value %s */\n",
2560 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin59b176e2005-11-26 11:25:14 +00002561 if(fits_long) {
Lev Walkin63b41262007-11-06 01:48:46 +00002562 OUT("*st = ");
2563 OINT(expr->marker.default_value->value.v_integer);
2564 OUT(";\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002565 OUT("return 0;\n");
2566 } else {
Lev Walkin63b41262007-11-06 01:48:46 +00002567 OUT("return asn_long2INTEGER(st, ");
2568 OINT(expr->marker.default_value->value.v_integer);
2569 OUT(");\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002570 }
2571 INDENT(-1);
Lev Walkin1dc85292006-08-18 01:32:26 +00002572 OUT("} else {\n");
2573 INDENT(+1);
Lev Walkinda997b12017-08-04 01:38:41 -07002574 OUT("/* Test default value %s */\n",
2575 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin1dc85292006-08-18 01:32:26 +00002576 if(fits_long) {
Lev Walkinda997b12017-08-04 01:38:41 -07002577 OUT("return (*st == %s);\n",
2578 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin1dc85292006-08-18 01:32:26 +00002579 } else {
2580 OUT("long value;\n");
2581 OUT("if(asn_INTEGER2long(st, &value))\n");
2582 OUT("\treturn -1;\n");
Lev Walkinda997b12017-08-04 01:38:41 -07002583 OUT("return (value == %s);\n",
2584 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin1dc85292006-08-18 01:32:26 +00002585 }
2586 INDENT(-1);
2587 OUT("}\n");
2588 INDENT(-1);
Lev Walkin59b176e2005-11-26 11:25:14 +00002589 OUT("}\n");
2590 REDIR(save_target);
2591 return 1;
2592 case ASN_BASIC_NULL:
2593 //expr->marker.flags &= ~EM_INDIRECT;
2594 return 0;
2595 default:
Lev Walkin8032f7a2007-06-27 01:54:57 +00002596 if(etype & ASN_STRING_KM_MASK) {
2597 if(expr->marker.default_value == NULL
2598 || expr->marker.default_value->type != ATV_STRING)
2599 break;
2600 if(!out) {
2601 OUT("asn_DFL_%d_set,\t/* DEFAULT \"%s\" */\n",
2602 expr->_type_unique_index,
2603 expr->marker.default_value->value.string.buf);
2604 return 1;
2605 }
2606 REDIR(OT_STAT_DEFS);
2607 OUT("static int asn_DFL_%d_set(int set_value, void **sptr) {\n", expr->_type_unique_index);
2608 INDENT(+1);
2609 emit_default_value(arg, expr->marker.default_value);
2610 OUT("%s *st = *sptr;\n", asn1c_type_name(arg, expr, TNF_CTYPE));
2611 OUT("\n");
2612 OUT("if(!st) {\n");
2613 OUT("\tif(!set_value) return -1;\t/* Not a default value */\n");
2614 OUT("\tst = (*sptr = CALLOC(1, sizeof(*st)));\n");
2615 OUT("\tif(!st) return -1;\n");
2616 OUT("}\n");
2617 OUT("\n");
2618 OUT("if(set_value) {\n");
2619 INDENT(+1);
2620 OUT("uint8_t *ptr = MALLOC(sizeof(defv));\n");
2621 OUT("if(!ptr) return -1;\n");
2622 OUT("memcpy(ptr, &defv, sizeof(defv));\n");
2623 OUT("FREEMEM(st->buf);\n");
2624 OUT("st->buf = ptr;\n");
2625 OUT("st->size = sizeof(defv) - 1;\n");
2626 OUT("return 0;\n");
2627 INDENT(-1);
2628 OUT("} else {\n");
2629 INDENT(+1);
2630 OUT("if(st->size != (sizeof(defv) - 1)\n");
2631 OUT("|| memcmp(st->buf, &defv, sizeof(defv) - 1))\n");
2632 OUT("\treturn 0;\n");
2633 OUT("return 1;\n");
2634 INDENT(-1);
2635 OUT("}\n"); OUT("\n");
2636 INDENT(-1);
2637 OUT("}\n");
2638 REDIR(save_target);
2639 return 1;
2640 }
2641 break;
Lev Walkin59b176e2005-11-26 11:25:14 +00002642 }
2643 return 0;
2644}
2645
Lev Walkin59004fa2004-08-20 13:37:01 +00002646static int
Lev Walkin9de6cd82017-08-10 05:47:46 -07002647emit_member_type_selector(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_objset_t *opt_ioc) {
2648 int save_target = arg->target->target;
2649 asn1p_expr_t *parent_expr = arg->expr;
2650
2651 const asn1p_constraint_t *crc =
2652 asn1p_get_component_relation_constraint(expr->combined_constraints);
2653 if(!crc || crc->el_count <= 1) {
2654 /* Not an Open Type, it seems. */
2655 OUT("0");
2656 return 0;
2657 }
2658
Lev Walkind8e07c52017-08-23 07:38:30 -07002659 const asn1p_ref_t *objset_ref =
2660 asn1c_get_information_object_set_reference_from_constraint(arg, crc);
2661
Lev Walkinade508c2017-08-23 10:19:30 -07002662 if(!objset_ref) {
2663 FATAL("Constraint %s does not look like it referst to a set type %s",
2664 asn1p_constraint_string(crc),
2665 opt_ioc->objset->Identifier);
Lev Walkin9de6cd82017-08-10 05:47:46 -07002666 return -1;
2667 }
2668
Lev Walkinade508c2017-08-23 10:19:30 -07002669 const char *objset_name;
2670 if(objset_ref->comp_count == 1) {
2671 objset_name = objset_ref->components[0].name;
2672 } else if(objset_ref->comp_count == 2) {
2673 if(strcmp(objset_ref->components[0].name,
2674 opt_ioc->objset->module->ModuleName)
2675 != 0) {
2676 FATAL(
2677 "Composite reference %s (from %s) does not look like it refers "
2678 "to the same module as %s from an object set type %s",
2679 asn1p_ref_string(objset_ref), asn1p_constraint_string(crc),
2680 opt_ioc->objset->module->ModuleName,
2681 opt_ioc->objset->Identifier);
2682 return -1;
2683 }
2684 objset_name = objset_ref->components[1].name;
2685 } else {
2686 FATAL("Reference %s (from %s) does not look like an object set type %s",
2687 asn1p_ref_string(objset_ref), asn1p_constraint_string(crc),
2688 opt_ioc->objset->Identifier);
2689 return -1;
2690 }
Lev Walkin9de6cd82017-08-10 05:47:46 -07002691 if(strcmp(objset_name, opt_ioc->objset->Identifier) != 0) {
2692 FATAL("Object Set references do not match: %s != %s", objset_name,
2693 opt_ioc->objset->Identifier);
2694 return -1;
2695 }
2696
2697 if(crc->el_count != 2 || crc->elements[1]->type != ACT_EL_VALUE
2698 || crc->elements[1]->value->type != ATV_REFERENCED
2699 || crc->elements[1]->value->value.reference->comp_count != 1) {
2700 FATAL(
2701 "Do not know how to handle complex IoS constraints (%d components "
2702 "of constraint, %d components of reference %s) for %s at line "
2703 "%d",
2704 crc->el_count,
2705 crc->el_count >= 2 && crc->elements[1]->type == ACT_EL_VALUE
2706 && crc->elements[1]->value->type == ATV_REFERENCED
Lev Walkin5d929d82017-08-10 15:17:44 -07002707 ? (signed)crc->elements[1]->value->value.reference->comp_count
Lev Walkin9de6cd82017-08-10 05:47:46 -07002708 : -1,
2709 crc->el_count >= 2 && crc->elements[1]->type == ACT_EL_VALUE
2710 && crc->elements[1]->value->type == ATV_REFERENCED
2711 ? asn1p_ref_string(crc->elements[1]->value->value.reference)
2712 : "?",
2713 MKID(parent_expr), parent_expr->_lineno);
2714 OUT("0");
2715 return -1;
2716 }
2717
2718 const asn1p_ref_t *cref = crc->elements[1]->value->value.reference;
2719 const char *cname = cref->components[0].name;
2720 if(cname[0] == '@' && cname[1] != '.') {
2721 cname += 1;
2722 } else if(cname[0] == '@' && cname[1] == '.' && cname[2] != '.') {
2723 cname += 2;
2724 } else {
2725 FATAL("Complex IoS reference %s can not be processed",
2726 asn1p_ref_string(cref));
2727 OUT("0");
2728 return -1;
2729 }
2730
2731 assert(opt_ioc != NULL);
2732
Lev Walkinf6853ce2017-08-11 00:50:27 -07002733 asn1p_expr_t *constraining_memb = NULL;
2734 TQ_FOR(constraining_memb, &(parent_expr->members), next) {
2735 if(strcmp(constraining_memb->Identifier, cname) == 0) {
Lev Walkin9de6cd82017-08-10 05:47:46 -07002736 break;
Lev Walkinf6853ce2017-08-11 00:50:27 -07002737 }
Lev Walkin9de6cd82017-08-10 05:47:46 -07002738 }
2739 if(!constraining_memb) {
2740 FATAL("Can not find \"%s\" in %s at line %d", cname, MKID(parent_expr),
2741 parent_expr->_lineno);
2742 return -1;
2743 }
2744
2745 if(constraining_memb->meta_type != AMT_TYPEREF
2746 || constraining_memb->expr_type != A1TC_REFERENCE
2747 || constraining_memb->reference->comp_count != 2
2748 || constraining_memb->reference->components[1].lex_type
2749 != RLT_Amplowercase) {
2750 FATAL(
2751 "Does not look like %s is a CLASS field reference (%s) on line "
2752 "%d",
2753 MKID(constraining_memb),
2754 constraining_memb->reference
2755 ? asn1p_ref_string(constraining_memb->reference)
2756 : "<no reference>",
2757 constraining_memb->_lineno);
2758 return -1;
2759 }
2760 const char *cfield = constraining_memb->reference->components[1].name;
2761
2762 ssize_t constraining_column = -1;
2763 for(size_t cn = 0; cn < opt_ioc->ioct->rows ? opt_ioc->ioct->row[0]->columns : 0;
2764 cn++) {
2765 if(strcmp(cfield, opt_ioc->ioct->row[0]->column[cn].field->Identifier)
2766 == 0) {
2767 constraining_column = cn;
2768 break;
2769 }
2770 }
2771 if(constraining_column < 0) {
Lev Walkin53a28a22017-08-23 09:56:53 -07002772 if(opt_ioc->ioct->rows == 0) {
2773 OUT("0");
2774 return 0;
2775 } else {
2776 FATAL("Can not find referenced object class %s column %s\n",
2777 asn1p_ref_string(objset_ref), cfield);
2778 return -1;
2779 }
Lev Walkin9de6cd82017-08-10 05:47:46 -07002780 }
2781
2782 if(expr->meta_type != AMT_TYPEREF
2783 || expr->expr_type != A1TC_REFERENCE
2784 || expr->reference->comp_count != 2
2785 || expr->reference->components[1].lex_type
2786 != RLT_AmpUppercase) {
2787 FATAL(
2788 "Does not look like %s is a CLASS field reference (%s) denoting a type on line "
2789 "%d",
2790 MKID(expr),
2791 expr->reference
2792 ? asn1p_ref_string(expr->reference)
2793 : "<no reference>",
2794 expr->_lineno);
2795 return -1;
2796 }
2797 const char *for_field = expr->reference->components[1].name;
2798
2799 ssize_t for_column = -1;
2800 for(size_t cn = 0; cn < opt_ioc->ioct->rows ? opt_ioc->ioct->row[0]->columns : 0;
2801 cn++) {
2802 if(strcmp(for_field,
2803 opt_ioc->ioct->row[0]->column[cn].field->Identifier)
2804 == 0) {
2805 for_column = cn;
2806 break;
2807 }
2808 }
2809 if(for_column < 0) {
2810 FATAL("Can not find referenced object class column %s\n", for_field);
2811 return -1;
2812 }
2813
2814
2815 REDIR(OT_CODE);
Lev Walkinf6853ce2017-08-11 00:50:27 -07002816 OUT("static asn_type_selector_result_t\n");
Lev Walkin9de6cd82017-08-10 05:47:46 -07002817 OUT("select_%s_type(const asn_TYPE_descriptor_t *parent_type, const void *parent_sptr) {\n", MKID_safe(expr));
2818 INDENT(+1);
2819
Lev Walkinf6853ce2017-08-11 00:50:27 -07002820 OUT("asn_type_selector_result_t result = {0, 0};\n");
Lev Walkin6aae7c62017-08-10 17:58:48 -07002821 OUT("const asn_ioc_set_t *itable = asn_IOS_%s_%d;\n", MKID(opt_ioc->objset),
Lev Walkin9de6cd82017-08-10 05:47:46 -07002822 opt_ioc->objset->_type_unique_index);
2823 OUT("size_t constraining_column = %zu; /* %s */\n", constraining_column, cfield);
2824 OUT("size_t for_column = %zu; /* %s */\n", for_column, for_field);
2825 OUT("size_t row;\n");
2826
2827 const char *tname = asn1c_type_name(arg, constraining_memb, TNF_SAFE);
2828 if(constraining_memb->marker.flags & EM_INDIRECT) {
Lev Walkin6aae7c62017-08-10 17:58:48 -07002829 OUT("const void *memb_ptr = *(const void **)");
Lev Walkinb46156d2017-09-05 02:53:05 -07002830 OUT("((const char *)parent_sptr + offsetof(%s", c_name(arg).full_name);
Lev Walkin9de6cd82017-08-10 05:47:46 -07002831 OUT(", %s));", MKID_safe(constraining_memb));
Lev Walkinf6853ce2017-08-11 00:50:27 -07002832 OUT("if(!memb_ptr) return result;\n");
Lev Walkin9de6cd82017-08-10 05:47:46 -07002833 OUT("\n");
2834 }
2835
2836 switch(asn1c_type_fits_long(arg, constraining_memb)) {
2837 case FL_NOTFIT:
2838 OUT("const %s_t *constraining_value = (const %s_t *)", tname, tname);
2839 break;
2840 case FL_PRESUMED:
2841 case FL_FITS_SIGNED:
2842 OUT("const long *constraining_value = (const long *)");
2843 break;
2844 case FL_FITS_UNSIGN:
2845 OUT("const unsigned long *constraining_value = (const unsigned long *)");
2846 break;
2847 }
2848 if(constraining_memb->marker.flags & EM_INDIRECT) {
2849 OUT("memb_ptr;\n");
2850 } else {
Lev Walkinb46156d2017-09-05 02:53:05 -07002851 OUT("((const char *)parent_sptr + offsetof(%s", c_name(arg).full_name);
Lev Walkin9de6cd82017-08-10 05:47:46 -07002852 OUT(", %s));\n", MKID_safe(constraining_memb));
2853 }
2854 OUT("\n");
2855
2856 OUT("for(row=0; row < itable->rows_count; row++) {\n");
Lev Walkin6aae7c62017-08-10 17:58:48 -07002857 OUT(" const asn_ioc_cell_t *constraining_cell = &itable->rows[row * itable->columns_count + constraining_column];\n");
2858 OUT(" const asn_ioc_cell_t *type_cell = &itable->rows[row * itable->columns_count + for_column];\n");
2859 OUT("\n");
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +08002860 OUT(" if(constraining_cell->type_descriptor->op->compare_struct(constraining_cell->type_descriptor, constraining_value, constraining_cell->value_sptr) == 0) {\n");
Lev Walkinf6853ce2017-08-11 00:50:27 -07002861 OUT(" result.type_descriptor = type_cell->type_descriptor;\n");
2862 OUT(" result.presence_index = row + 1;\n");
2863 OUT(" break;\n");
Lev Walkin9de6cd82017-08-10 05:47:46 -07002864 OUT(" }\n");
2865 OUT("}\n");
2866
2867
2868 OUT("\n");
Lev Walkinf6853ce2017-08-11 00:50:27 -07002869 OUT("return result;\n");
Lev Walkin9de6cd82017-08-10 05:47:46 -07002870 INDENT(-1);
2871 OUT("}\n");
2872 OUT("\n");
2873
2874 REDIR(save_target);
2875 OUT("select_%s_type", MKID_safe(expr));
2876
2877 return 0;
2878}
2879
2880static int
2881emit_member_table(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_objset_t *opt_ioc) {
Lev Walkin59004fa2004-08-20 13:37:01 +00002882 int save_target;
2883 arg_t tmp_arg;
Lev Walkinb9189732004-09-10 09:37:12 +00002884 struct asn1p_type_tag_s outmost_tag_s;
2885 struct asn1p_type_tag_s *outmost_tag;
Lev Walkine0b56e02005-02-25 12:10:27 +00002886 int complex_contents;
Lev Walkincf3f6eb2017-08-23 04:34:15 -07002887 const char *p;
Lev Walkin59004fa2004-08-20 13:37:01 +00002888
Lev Walkinc0e03b92017-08-22 01:48:23 -07002889 if(WITH_MODULE_NAMESPACE(
2890 expr->module, expr_ns,
2891 asn1f_fetch_outmost_tag(arg->asn, expr_ns, expr->module, expr,
2892 &outmost_tag_s, AFT_IMAGINARY_ANY))) {
2893 outmost_tag = 0;
Lev Walkinb9189732004-09-10 09:37:12 +00002894 } else {
2895 outmost_tag = &outmost_tag_s;
2896 }
2897
Lev Walkin59004fa2004-08-20 13:37:01 +00002898 OUT("{ ");
Lev Walkinb9189732004-09-10 09:37:12 +00002899
Lev Walkin14fd3e52017-08-27 01:38:45 -07002900 if(is_open_type(arg, expr, opt_ioc)) {
Lev Walkinf6853ce2017-08-11 00:50:27 -07002901 OUT("ATF_OPEN_TYPE | ");
Lev Walkin14fd3e52017-08-27 01:38:45 -07002902 } else if(outmost_tag && outmost_tag->tag_value == -1) {
2903 OUT("ATF_ANY_TYPE | ");
Lev Walkinf6853ce2017-08-11 00:50:27 -07002904 }
2905 OUT("%s, ",
Lev Walkinc8285712005-03-04 22:18:20 +00002906 (expr->marker.flags & EM_INDIRECT)?"ATF_POINTER":"ATF_NOFLAGS");
Lev Walkinb85a8132005-08-18 13:38:19 +00002907 if((expr->marker.flags & EM_OMITABLE) == EM_OMITABLE) {
Lev Walkin59004fa2004-08-20 13:37:01 +00002908 asn1p_expr_t *tv;
2909 int opts = 0;
Lev Walkinb85a8132005-08-18 13:38:19 +00002910 for(tv = expr;
2911 tv && (tv->marker.flags & EM_OMITABLE) == EM_OMITABLE;
Lev Walkin59004fa2004-08-20 13:37:01 +00002912 tv = TQ_NEXT(tv, next), opts++) {
2913 if(tv->expr_type == A1TC_EXTENSIBLE)
2914 opts--;
2915 }
2916 OUT("%d, ", opts);
2917 } else {
2918 OUT("0, ");
2919 }
Lev Walkinf6853ce2017-08-11 00:50:27 -07002920 if(expr->_anonymous_type) {
2921 assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
2922 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
2923 OUT("0,\n");
2924 } else {
Lev Walkinb46156d2017-09-05 02:53:05 -07002925 OUT("offsetof(%s, ", c_name(arg).full_name);
Lev Walkinf6853ce2017-08-11 00:50:27 -07002926 if((arg->expr->expr_type == ASN_CONSTR_CHOICE
2927 || arg->expr->expr_type == ASN_CONSTR_OPEN_TYPE)
2928 && (!UNNAMED_UNIONS))
2929 OUT("choice.");
2930 OUT("%s),\n", MKID_safe(expr));
2931 }
2932
2933 INDENT(+1);
Lev Walkin59004fa2004-08-20 13:37:01 +00002934 if(C99_MODE) OUT(".tag = ");
Lev Walkinb9189732004-09-10 09:37:12 +00002935 if(outmost_tag) {
2936 if(outmost_tag->tag_value == -1)
2937 OUT("-1 /* Ambiguous tag (ANY?) */");
2938 else
2939 _print_tag(arg, outmost_tag);
Lev Walkinc3e29402004-09-10 06:07:18 +00002940 } else {
Lev Walkinb9189732004-09-10 09:37:12 +00002941 OUT("-1 /* Ambiguous tag (CHOICE?) */");
Lev Walkinc3e29402004-09-10 06:07:18 +00002942 }
Lev Walkinb9189732004-09-10 09:37:12 +00002943
Lev Walkin59004fa2004-08-20 13:37:01 +00002944 OUT(",\n");
2945 if(C99_MODE) OUT(".tag_mode = ");
Lev Walkin9ab21b82006-10-19 02:46:01 +00002946 if((!(expr->expr_type & ASN_CONSTR_MASK)
2947 || expr->expr_type == ASN_CONSTR_CHOICE)
2948 && expr->tag.tag_class) {
Lev Walkin59004fa2004-08-20 13:37:01 +00002949 if(expr->tag.tag_mode == TM_IMPLICIT)
2950 OUT("-1,\t/* IMPLICIT tag at current level */\n");
2951 else
2952 OUT("+1,\t/* EXPLICIT tag at current level */\n");
2953 } else {
2954 OUT("0,\n");
2955 }
Lev Walkine0b56e02005-02-25 12:10:27 +00002956
2957 complex_contents =
Lev Walkinf6853ce2017-08-11 00:50:27 -07002958 is_open_type(arg, expr, opt_ioc)
2959 || (expr->expr_type & ASN_CONSTR_MASK)
Lev Walkine0b56e02005-02-25 12:10:27 +00002960 || expr->expr_type == ASN_BASIC_ENUMERATED
Lev Walkin8ecf9db2005-03-03 21:28:12 +00002961 || (0 /* -- prohibited by X.693:8.3.4 */
2962 && expr->expr_type == ASN_BASIC_INTEGER
Lev Walkin8bb57a22007-12-03 13:41:36 +00002963 && expr_elements_count(arg, expr))
2964 || (expr->expr_type == ASN_BASIC_INTEGER
2965 && asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN);
Lev Walkin59004fa2004-08-20 13:37:01 +00002966 if(C99_MODE) OUT(".type = ");
Lev Walkinf6853ce2017-08-11 00:50:27 -07002967
2968 OUT("&asn_DEF_");
2969 if(complex_contents) {
2970 OUT("%s", MKID(expr));
2971 if(!(arg->flags & A1C_ALL_DEFS_GLOBAL))
2972 OUT("_%d", expr->_type_unique_index);
2973 } else {
2974 OUT("%s", asn1c_type_name(arg, expr, TNF_SAFE));
2975 }
2976 OUT(",\n");
Lev Walkin9de6cd82017-08-10 05:47:46 -07002977
2978
2979 if(C99_MODE) OUT(".type_selector = ");
2980 if(opt_ioc) {
Lev Walkind8e07c52017-08-23 07:38:30 -07002981 if(emit_member_type_selector(arg, expr, opt_ioc) < 0)
2982 return -1;
Lev Walkin9de6cd82017-08-10 05:47:46 -07002983 } else {
2984 OUT("0");
2985 }
2986 OUT(",\n");
2987
Lev Walkin59004fa2004-08-20 13:37:01 +00002988 if(C99_MODE) OUT(".memb_constraints = ");
2989 if(expr->constraints) {
Lev Walkin8de2ab22004-09-26 13:11:31 +00002990 if(arg->flags & A1C_NO_CONSTRAINTS) {
2991 OUT("0,\t/* No check because of -fno-constraints */\n");
2992 } else {
Lev Walkincf3f6eb2017-08-23 04:34:15 -07002993 const char *id = MKID(expr);
Lev Walkin8de2ab22004-09-26 13:11:31 +00002994 if(expr->_anonymous_type
Lev Walkin152a91e2005-02-14 20:41:29 +00002995 && !strcmp(expr->Identifier, "Member"))
Lev Walkin8de2ab22004-09-26 13:11:31 +00002996 id = asn1c_type_name(arg, expr, TNF_SAFE);
Lev Walkin59b176e2005-11-26 11:25:14 +00002997 OUT("memb_%s_constraint_%d,\n", id,
Lev Walkin21d00002005-03-04 08:48:53 +00002998 arg->expr->_type_unique_index);
Lev Walkin8de2ab22004-09-26 13:11:31 +00002999 }
Lev Walkin59004fa2004-08-20 13:37:01 +00003000 } else {
Lev Walkinb7bfd1a2005-01-17 12:16:58 +00003001 OUT("0,\t/* Defer constraints checking to the member type */\n");
Lev Walkin59004fa2004-08-20 13:37:01 +00003002 }
Lev Walkinb33425f2017-07-14 14:59:52 +04003003 if(C99_MODE) OUT(".oer_constraints = ");
3004 if(arg->flags & A1C_GEN_OER) {
3005 if(expr->constraints) {
3006 OUT("&asn_OER_memb_%s_constr_%d,\n",
3007 MKID(expr),
3008 expr->_type_unique_index);
3009 } else {
3010 OUT("0,\t/* No OER visible constraints */\n");
3011 }
3012 } else {
3013 OUT("0,\t/* OER is not compiled, use -gen-OER */\n");
3014 }
Lev Walkin59b176e2005-11-26 11:25:14 +00003015 if(C99_MODE) OUT(".per_constraints = ");
3016 if(arg->flags & A1C_GEN_PER) {
Lev Walkin07aaa342006-10-09 12:52:15 +00003017 if(expr->constraints) {
Lev Walkin4b5dae32006-10-09 12:27:44 +00003018 OUT("&asn_PER_memb_%s_constr_%d,\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00003019 MKID(expr),
Lev Walkin59b176e2005-11-26 11:25:14 +00003020 expr->_type_unique_index);
3021 } else {
3022 OUT("0,\t/* No PER visible constraints */\n");
3023 }
Lev Walkin152a91e2005-02-14 20:41:29 +00003024 } else {
Lev Walkin59b176e2005-11-26 11:25:14 +00003025 OUT("0,\t/* PER is not compiled, use -gen-PER */\n");
3026 }
3027 if(C99_MODE) OUT(".default_value = ");
3028 if(try_inline_default(arg, expr, 0)) {
Lev Walkin59b176e2005-11-26 11:25:14 +00003029 } else {
3030 OUT("0,\n");
3031 }
3032 if(C99_MODE) OUT(".name = ");
3033 if(expr->_anonymous_type && !strcmp(expr->Identifier, "Member")) {
3034 OUT("\"\"\n");
3035 } else {
3036 OUT("\"%s\"\n", expr->Identifier);
Lev Walkin152a91e2005-02-14 20:41:29 +00003037 }
Lev Walkin59004fa2004-08-20 13:37:01 +00003038 OUT("},\n");
3039 INDENT(-1);
3040
Lev Walkin8de2ab22004-09-26 13:11:31 +00003041 if(!expr->constraints || (arg->flags & A1C_NO_CONSTRAINTS))
Lev Walkin59004fa2004-08-20 13:37:01 +00003042 return 0;
3043
3044 save_target = arg->target->target;
3045 REDIR(OT_CODE);
3046
Lev Walkin152a91e2005-02-14 20:41:29 +00003047 if(expr->_anonymous_type && !strcmp(expr->Identifier, "Member"))
Lev Walkin59004fa2004-08-20 13:37:01 +00003048 p = asn1c_type_name(arg, expr, TNF_SAFE);
Lev Walkina9cc46e2004-09-22 16:06:28 +00003049 else
Lev Walkina00d6b32006-03-21 03:40:38 +00003050 p = MKID(expr);
Lev Walkin59004fa2004-08-20 13:37:01 +00003051 OUT("static int\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00003052 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 +00003053 INDENT(+1);
Lev Walkin1eded352006-07-13 11:19:01 +00003054 OUT("\t\tasn_app_constraint_failed_f *ctfailcb, void *app_key) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +00003055 tmp_arg = *arg;
3056 tmp_arg.expr = expr;
Lev Walkin725883b2006-10-09 12:07:58 +00003057 DEBUG("member constraint checking code for %s", p);
Lev Walkin59004fa2004-08-20 13:37:01 +00003058 if(asn1c_emit_constraint_checking_code(&tmp_arg) == 1) {
Lev Walkin8de2ab22004-09-26 13:11:31 +00003059 OUT("return td->check_constraints"
Lev Walkin1eded352006-07-13 11:19:01 +00003060 "(td, sptr, ctfailcb, app_key);\n");
Lev Walkin59004fa2004-08-20 13:37:01 +00003061 }
3062 INDENT(-1);
3063 OUT("}\n");
3064 OUT("\n");
3065
Lev Walkin98eabc12017-07-19 08:51:11 +04003066 if(emit_member_OER_constraints(arg, expr, "memb"))
3067 return -1;
3068
Lev Walkin4b5dae32006-10-09 12:27:44 +00003069 if(emit_member_PER_constraints(arg, expr, "memb"))
Lev Walkin725883b2006-10-09 12:07:58 +00003070 return -1;
3071
Lev Walkin59004fa2004-08-20 13:37:01 +00003072 REDIR(save_target);
3073
3074 return 0;
3075}
Lev Walkin59964be2004-08-25 02:03:12 +00003076
Lev Walkindc06f6b2004-10-20 15:50:55 +00003077/*
3078 * Generate "asn_DEF_XXX" type definition.
3079 */
Lev Walkin59964be2004-08-25 02:03:12 +00003080static int
Lev Walkin8de2ab22004-09-26 13:11:31 +00003081emit_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 +00003082 asn1p_expr_t *terminal;
Lev Walkin21d00002005-03-04 08:48:53 +00003083 int using_type_name = 0;
Lev Walkincf3f6eb2017-08-23 04:34:15 -07003084 const char *p = MKID(expr);
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003085 char *p2 = (char *)0;
Lev Walkin59b176e2005-11-26 11:25:14 +00003086
Lev Walkinc0e03b92017-08-22 01:48:23 -07003087 terminal = asn1f_find_terminal_type_ex(arg->asn, arg->ns, expr);
Lev Walkin8c2ca0b2006-09-17 06:31:08 +00003088
Lev Walkin01582a72017-07-26 18:47:08 -07003089 if(emit_member_OER_constraints(arg, expr, "type"))
3090 return -1;
3091
Lev Walkin4b5dae32006-10-09 12:27:44 +00003092 if(emit_member_PER_constraints(arg, expr, "type"))
Lev Walkin725883b2006-10-09 12:07:58 +00003093 return -1;
Lev Walkin59964be2004-08-25 02:03:12 +00003094
Lev Walkindd32b592004-09-06 08:07:29 +00003095 if(HIDE_INNER_DEFS)
3096 OUT("static /* Use -fall-defs-global to expose */\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00003097 OUT("asn_TYPE_descriptor_t asn_DEF_%s", p);
Lev Walkinf6853ce2017-08-11 00:50:27 -07003098 if(HIDE_INNER_DEFS || (arg->flags & A1C_ALL_DEFS_GLOBAL))
3099 OUT("_%d", expr->_type_unique_index);
3100 OUT(" = {\n");
Lev Walkin188ed2c2004-09-13 08:31:01 +00003101 INDENT(+1);
Lev Walkin59b176e2005-11-26 11:25:14 +00003102
3103 if(expr->_anonymous_type) {
3104 p = ASN_EXPR_TYPE2STR(expr->expr_type);
3105 OUT("\"%s\",\n", p?p:"");
Lev Walkina00d6b32006-03-21 03:40:38 +00003106 OUT("\"%s\",\n",
3107 p ? asn1c_make_identifier(AMI_CHECK_RESERVED,
3108 0, p, 0) : "");
Lev Walkin59b176e2005-11-26 11:25:14 +00003109 } else {
3110 OUT("\"%s\",\n", expr->Identifier);
3111 OUT("\"%s\",\n", expr->Identifier);
3112 }
Lev Walkin59964be2004-08-25 02:03:12 +00003113
3114 if(expr->expr_type & ASN_CONSTR_MASK) {
Lev Walkin21d00002005-03-04 08:48:53 +00003115 using_type_name = 1;
Lev Walkin59964be2004-08-25 02:03:12 +00003116 p = asn1c_type_name(arg, arg->expr, TNF_SAFE);
Lev Walkin59b176e2005-11-26 11:25:14 +00003117 } else {
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003118 if (expr->expr_type == A1TC_REFERENCE) {
3119 p2 = strdup(asn1c_type_name(arg, terminal, TNF_SAFE));
3120 } else {
3121 p2 = strdup(asn1c_type_name(arg, expr, TNF_SAFE));
3122 }
Lev Walkina00d6b32006-03-21 03:40:38 +00003123 p = MKID(expr);
Lev Walkin59964be2004-08-25 02:03:12 +00003124 }
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003125 if (!p2)
3126 p2 = strdup(p);
Lev Walkin59964be2004-08-25 02:03:12 +00003127
Lev Walkin21d00002005-03-04 08:48:53 +00003128#define FUNCREF(foo) do { \
3129 OUT("%s", p); \
3130 if(HIDE_INNER_DEFS && !using_type_name) \
3131 OUT("_%d", expr->_type_unique_index); \
3132 OUT("_" #foo ",\n"); \
3133} while(0)
3134
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003135#define FUNCREF2(foo) \
3136do { \
3137 OUT("%s", p2); \
3138 OUT("_" #foo ",\n"); \
3139} while(0)
3140
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +08003141 OUT("&asn_OP_%s,\n", p2);
mattipeee0b99ab2017-08-04 11:44:04 +01003142 if (arg->flags & A1C_NO_CONSTRAINTS)
3143 OUT("0,\t/* No check because of -fno-constraints */\n");
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003144 else
mattipeee0b99ab2017-08-04 11:44:04 +01003145 {
3146 if (!expr->combined_constraints)
3147 FUNCREF2(constraint);
3148 else
3149 FUNCREF(constraint);
3150 }
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003151 if (p2) free(p2);
Lev Walkin59964be2004-08-25 02:03:12 +00003152
Lev Walkina00d6b32006-03-21 03:40:38 +00003153 p = MKID(expr);
Lev Walkin59964be2004-08-25 02:03:12 +00003154 if(tags_count) {
Lev Walkin59b176e2005-11-26 11:25:14 +00003155 OUT("asn_DEF_%s_tags_%d,\n",
Lev Walkin21d00002005-03-04 08:48:53 +00003156 p, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00003157 OUT("sizeof(asn_DEF_%s_tags_%d)\n",
Lev Walkin21d00002005-03-04 08:48:53 +00003158 p, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00003159 OUT("\t/sizeof(asn_DEF_%s_tags_%d[0])",
Lev Walkin21d00002005-03-04 08:48:53 +00003160 p, expr->_type_unique_index);
Lev Walkin188ed2c2004-09-13 08:31:01 +00003161 if(tv_mode == _TVM_SUBSET
3162 && tags_count != all_tags_count)
3163 OUT(" - %d", all_tags_count - tags_count);
3164 OUT(", /* %d */\n", tags_count);
Lev Walkin59964be2004-08-25 02:03:12 +00003165 } else {
Lev Walkin188ed2c2004-09-13 08:31:01 +00003166 OUT("0,\t/* No effective tags (pointer) */\n");
3167 OUT("0,\t/* No effective tags (count) */\n");
3168 }
3169
3170 if(all_tags_count && tv_mode == _TVM_DIFFERENT) {
Lev Walkin59b176e2005-11-26 11:25:14 +00003171 OUT("asn_DEF_%s_all_tags_%d,\n",
Lev Walkin21d00002005-03-04 08:48:53 +00003172 p, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00003173 OUT("sizeof(asn_DEF_%s_all_tags_%d)\n",
Lev Walkin21d00002005-03-04 08:48:53 +00003174 p, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00003175 OUT("\t/sizeof(asn_DEF_%s_all_tags_%d[0]), /* %d */\n",
Lev Walkin21d00002005-03-04 08:48:53 +00003176 p, expr->_type_unique_index, all_tags_count);
Lev Walkin188ed2c2004-09-13 08:31:01 +00003177 } else if(all_tags_count) {
Lev Walkin59b176e2005-11-26 11:25:14 +00003178 OUT("asn_DEF_%s_tags_%d,\t/* Same as above */\n",
Lev Walkin21d00002005-03-04 08:48:53 +00003179 p, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00003180 OUT("sizeof(asn_DEF_%s_tags_%d)\n",
Lev Walkin21d00002005-03-04 08:48:53 +00003181 p, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00003182 OUT("\t/sizeof(asn_DEF_%s_tags_%d[0]), /* %d */\n",
Lev Walkin21d00002005-03-04 08:48:53 +00003183 p, expr->_type_unique_index, all_tags_count);
Lev Walkin188ed2c2004-09-13 08:31:01 +00003184 } else {
3185 OUT("0,\t/* No tags (pointer) */\n");
3186 OUT("0,\t/* No tags (count) */\n");
Lev Walkin59964be2004-08-25 02:03:12 +00003187 }
3188
Lev Walkinb33425f2017-07-14 14:59:52 +04003189 if(arg->flags & A1C_GEN_OER) {
Lev Walkin135d7dd2017-08-28 00:21:38 -07003190 if(expr->combined_constraints
Lev Walkinb33425f2017-07-14 14:59:52 +04003191 || expr->expr_type == ASN_BASIC_ENUMERATED
3192 || expr->expr_type == ASN_CONSTR_CHOICE) {
3193 OUT("&asn_OER_type_%s_constr_%d,\n",
3194 p, expr->_type_unique_index);
3195 } else {
3196 OUT("0,\t/* No OER visible constraints */\n");
3197 }
3198 } else {
3199 OUT("0,\t/* No OER visible constraints */\n");
3200 }
3201
Lev Walkin59b176e2005-11-26 11:25:14 +00003202 if(arg->flags & A1C_GEN_PER) {
Lev Walkin135d7dd2017-08-28 00:21:38 -07003203 if(expr->combined_constraints
Lev Walkin59b176e2005-11-26 11:25:14 +00003204 || expr->expr_type == ASN_BASIC_ENUMERATED
3205 || expr->expr_type == ASN_CONSTR_CHOICE) {
Lev Walkin4b5dae32006-10-09 12:27:44 +00003206 OUT("&asn_PER_type_%s_constr_%d,\n",
Lev Walkin59b176e2005-11-26 11:25:14 +00003207 p, expr->_type_unique_index);
3208 } else {
3209 OUT("0,\t/* No PER visible constraints */\n");
3210 }
3211 } else {
3212 OUT("0,\t/* No PER visible constraints */\n");
3213 }
3214
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003215 if(elements_count ||
3216 ((expr->expr_type == A1TC_REFERENCE) &&
3217 (terminal->expr_type & ASN_CONSTR_MASK) &&
3218 expr_elements_count(arg, terminal))) {
3219
3220 if (expr->expr_type == A1TC_REFERENCE) {
3221 OUT("asn_MBR_%s_%d,\n", MKID(terminal), terminal->_type_unique_index);
3222
3223 if(terminal->expr_type == ASN_CONSTR_SEQUENCE_OF
3224 || terminal->expr_type == ASN_CONSTR_SET_OF) {
3225 OUT("%d,\t/* Single element */\n",
3226 expr_elements_count(arg, terminal));
3227 assert(expr_elements_count(arg, terminal) == 1);
3228 } else {
3229 OUT("%d,\t/* Elements count */\n",
3230 expr_elements_count(arg, terminal));
3231 }
Lev Walkin59964be2004-08-25 02:03:12 +00003232 } else {
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003233 OUT("asn_MBR_%s_%d,\n", p, expr->_type_unique_index);
3234
3235 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF
3236 || expr->expr_type == ASN_CONSTR_SET_OF) {
3237 OUT("%d,\t/* Single element */\n",
3238 elements_count);
3239 assert(elements_count == 1);
3240 } else {
3241 OUT("%d,\t/* Elements count */\n",
3242 elements_count);
3243 }
Lev Walkin59964be2004-08-25 02:03:12 +00003244 }
3245 } else {
Lev Walkin59964be2004-08-25 02:03:12 +00003246 if(expr_elements_count(arg, expr))
3247 OUT("0, 0,\t/* Defined elsewhere */\n");
3248 else
3249 OUT("0, 0,\t/* No members */\n");
3250 }
3251
3252 switch(spec) {
3253 case ETD_NO_SPECIFICS:
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003254 if ((expr->expr_type == A1TC_REFERENCE) &&
3255 ((terminal->expr_type & ASN_CONSTR_MASK) ||
3256 (terminal->expr_type == ASN_BASIC_ENUMERATED) ||
3257 ((terminal->expr_type == ASN_BASIC_INTEGER) &&
3258 (asn1c_type_fits_long(arg, terminal) == FL_FITS_UNSIGN)))) {
3259 OUT("&asn_SPC_%s_specs_%d\t/* Additional specs */\n", MKID(terminal), terminal->_type_unique_index);
3260 } else if ((expr->expr_type == ASN_TYPE_ANY) ||
3261 (expr->expr_type == ASN_BASIC_BIT_STRING) ||
3262 (expr->expr_type == ASN_STRING_BMPString) ||
3263 (expr->expr_type == ASN_BASIC_OCTET_STRING) ||
3264 (expr->expr_type == ASN_STRING_UniversalString)) {
3265 OUT("&asn_SPC_%s_specs\t/* Additional specs */\n", asn1c_type_name(arg, expr, TNF_SAFE));
3266 } else if ((expr->expr_type == A1TC_REFERENCE) &&
3267 ((terminal->expr_type == ASN_TYPE_ANY) ||
3268 (terminal->expr_type == ASN_BASIC_BIT_STRING) ||
3269 (terminal->expr_type == ASN_STRING_BMPString) ||
3270 (terminal->expr_type == ASN_BASIC_OCTET_STRING) ||
3271 (terminal->expr_type == ASN_STRING_UniversalString))) {
3272 OUT("&asn_SPC_%s_specs\t/* Additional specs */\n", asn1c_type_name(arg, terminal, TNF_SAFE));
3273 } else {
3274 OUT("0\t/* No specifics */\n");
3275 }
Lev Walkin59964be2004-08-25 02:03:12 +00003276 break;
3277 case ETD_HAS_SPECIFICS:
Lev Walkin59b176e2005-11-26 11:25:14 +00003278 OUT("&asn_SPC_%s_specs_%d\t/* Additional specs */\n",
Lev Walkin21d00002005-03-04 08:48:53 +00003279 p, expr->_type_unique_index);
Lev Walkin59964be2004-08-25 02:03:12 +00003280 }
Lev Walkin188ed2c2004-09-13 08:31:01 +00003281 INDENT(-1);
Lev Walkin59964be2004-08-25 02:03:12 +00003282 OUT("};\n");
3283 OUT("\n");
Lev Walkin97298782004-08-26 06:20:34 +00003284
3285 return 0;
Lev Walkin59964be2004-08-25 02:03:12 +00003286}
Lev Walkincc93b0f2004-09-10 09:18:20 +00003287
Lev Walkina9cc46e2004-09-22 16:06:28 +00003288static int
3289expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkind1bfea62005-11-08 03:06:16 +00003290 /*
3291 * X.680, 25.5, Table 5
3292 */
Lev Walkin59b176e2005-11-26 11:25:14 +00003293 switch(expr_get_type(arg, expr)) {
Lev Walkina9cc46e2004-09-22 16:06:28 +00003294 case ASN_BASIC_BOOLEAN:
3295 case ASN_BASIC_ENUMERATED:
3296 case ASN_BASIC_NULL:
3297 return 1;
Lev Walkind1bfea62005-11-08 03:06:16 +00003298 case ASN_CONSTR_CHOICE:
3299 return 2;
Lev Walkina9cc46e2004-09-22 16:06:28 +00003300 default:
3301 return 0;
3302 }
3303}
Lev Walkin801fabc2005-01-28 12:18:50 +00003304
3305static int
Lev Walkin0f5d74c2005-08-14 15:03:31 +00003306out_name_chain(arg_t *arg, enum onc_flags onc_flags) {
Lev Walkin801fabc2005-01-28 12:18:50 +00003307 asn1p_expr_t *expr = arg->expr;
Lev Walkinb46156d2017-09-05 02:53:05 -07003308 const char *id;
Lev Walkin801fabc2005-01-28 12:18:50 +00003309
Lev Walkin0f5d74c2005-08-14 15:03:31 +00003310 if((arg->flags & A1C_COMPOUND_NAMES
Denis Filatovdbb89902017-06-28 14:39:39 +02003311 || onc_flags & ONC_force_compound_name
Lev Walkinacdca412017-08-12 20:59:16 -07003312 || (0 && arg->embed /* Not yet */))
Lev Walkin21d00002005-03-04 08:48:53 +00003313 && ((expr->expr_type & ASN_CONSTR_MASK)
3314 || expr->expr_type == ASN_BASIC_ENUMERATED
Lev Walkinb02a8832005-08-13 23:51:47 +00003315 || ((expr->expr_type == ASN_BASIC_INTEGER
3316 || expr->expr_type == ASN_BASIC_BIT_STRING)
Lev Walkin21d00002005-03-04 08:48:53 +00003317 && expr_elements_count(arg, expr))
3318 )
Bi-Ruei, Chiu94f0b642017-06-29 01:34:23 +08003319 && expr->parent_expr) {
3320
Lev Walkin801fabc2005-01-28 12:18:50 +00003321 arg_t tmparg = *arg;
3322
3323 tmparg.expr = expr->parent_expr;
Lev Walkin21d00002005-03-04 08:48:53 +00003324 if(0) tmparg.flags &= ~A1C_COMPOUND_NAMES;
3325
Lev Walkin0f5d74c2005-08-14 15:03:31 +00003326 out_name_chain(&tmparg, onc_flags);
Lev Walkin801fabc2005-01-28 12:18:50 +00003327
Bi-Ruei, Chiu94f0b642017-06-29 01:34:23 +08003328 if(expr->parent_expr->Identifier) OUT("__"); /* a separator between id components */
Lev Walkin21d00002005-03-04 08:48:53 +00003329
Lev Walkin801fabc2005-01-28 12:18:50 +00003330 /* Fall through */
3331 }
3332
Lev Walkin0f5d74c2005-08-14 15:03:31 +00003333 if(onc_flags & ONC_avoid_keywords)
Lev Walkina00d6b32006-03-21 03:40:38 +00003334 id = MKID_safe(expr);
Lev Walkin801fabc2005-01-28 12:18:50 +00003335 else
Lev Walkina00d6b32006-03-21 03:40:38 +00003336 id = MKID(expr);
Lev Walkin801fabc2005-01-28 12:18:50 +00003337 OUT("%s", id);
3338
3339 return 0;
3340}
Lev Walkinb85a8132005-08-18 13:38:19 +00003341
3342static int
3343emit_include_dependencies(arg_t *arg) {
3344 asn1p_expr_t *expr = arg->expr;
3345 asn1p_expr_t *memb;
3346
3347 /* Avoid recursive definitions. */
3348 TQ_FOR(memb, &(expr->members), next) {
3349 expr_break_recursion(arg, memb);
3350 }
3351
3352 TQ_FOR(memb, &(expr->members), next) {
3353
3354 if(memb->marker.flags & (EM_INDIRECT | EM_UNRECURSE)) {
3355 if(terminal_structable(arg, memb)) {
3356 int saved_target = arg->target->target;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08003357 if(saved_target != OT_FWD_DECLS) {
3358 REDIR(OT_FWD_DECLS);
3359 OUT("%s;\n",
3360 asn1c_type_name(arg, memb, TNF_RSAFE));
3361 }
Lev Walkinb85a8132005-08-18 13:38:19 +00003362 REDIR(saved_target);
3363 }
3364 }
3365
3366 if((!(memb->expr_type & ASN_CONSTR_MASK)
3367 && memb->expr_type > ASN_CONSTR_MASK)
3368 || memb->meta_type == AMT_TYPEREF) {
3369 if(memb->marker.flags & EM_UNRECURSE) {
3370 GEN_POSTINCLUDE(asn1c_type_name(arg,
3371 memb, TNF_INCLUDE));
3372 } else {
3373 GEN_INCLUDE(asn1c_type_name(arg,
3374 memb, TNF_INCLUDE));
3375 }
3376 }
3377 }
3378
3379 return 0;
3380}
3381
3382/*
3383 * Check if it is better to make this type indirectly accessed via
3384 * a pointer.
3385 * This may be the case for the following recursive definition:
3386 * Type ::= CHOICE { member Type };
3387 */
3388static int
3389expr_break_recursion(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkinb85a8132005-08-18 13:38:19 +00003390 int ret;
3391
3392 if(expr->marker.flags & EM_UNRECURSE)
3393 return 1; /* Already broken */
3394
Lev Walkinb85a8132005-08-18 13:38:19 +00003395 /* -findirect-choice compiles members of CHOICE as indirect pointers */
3396 if((arg->flags & A1C_INDIRECT_CHOICE)
3397 && arg->expr->expr_type == ASN_CONSTR_CHOICE
Lev Walkin59b176e2005-11-26 11:25:14 +00003398 && (expr_get_type(arg, expr) & ASN_CONSTR_MASK)
Lev Walkinb85a8132005-08-18 13:38:19 +00003399 ) {
3400 /* Break cross-reference */
3401 expr->marker.flags |= EM_INDIRECT | EM_UNRECURSE;
3402 return 1;
3403 }
3404
3405 if((expr->marker.flags & EM_INDIRECT)
3406 || arg->expr->expr_type == ASN_CONSTR_SET_OF
3407 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF) {
3408 if(terminal_structable(arg, expr)) {
3409 expr->marker.flags |= EM_UNRECURSE;
3410
3411 if(arg->expr->expr_type == ASN_CONSTR_SET_OF
3412 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF) {
3413 /* Don't put EM_INDIRECT even if recursion */
3414 return 1;
3415 }
3416
3417 /* Fall through */
3418 }
3419 }
3420
3421 /* Look for recursive back-references */
3422 ret = expr_defined_recursively(arg, expr);
3423 switch(ret) {
3424 case 2: /* Explicitly break the recursion */
3425 case 1: /* Use safer typing */
3426 expr->marker.flags |= EM_INDIRECT;
3427 expr->marker.flags |= EM_UNRECURSE;
3428 break;
3429 }
3430
3431 return 0;
3432}
3433
3434/*
3435 * Check if the type can be represented using simple `struct TYPE`.
3436 */
3437static asn1p_expr_t *
3438terminal_structable(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkinc0e03b92017-08-22 01:48:23 -07003439 asn1p_expr_t *terminal =
3440 asn1f_find_terminal_type_ex(arg->asn, arg->ns, expr);
3441 if(terminal
Lev Walkinb85a8132005-08-18 13:38:19 +00003442 && !terminal->parent_expr
3443 && (terminal->expr_type & ASN_CONSTR_MASK)) {
3444 return terminal;
3445 }
3446 return 0;
3447}
3448
3449static int
3450asn1c_recurse(arg_t *arg, asn1p_expr_t *expr, int (*callback)(arg_t *arg, void *key), void *key) {
3451 arg_t tmp = *arg;
3452 int maxret = 0;
3453 int ret;
3454
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +08003455 if(expr->_mark & TM_RECURSION) return 0;
Lev Walkinb85a8132005-08-18 13:38:19 +00003456 expr->_mark |= TM_RECURSION;
3457
3458 /* Invoke callback for every type going into recursion */
3459 tmp.expr = expr;
3460 maxret = callback(&tmp, key);
3461 if(maxret <= 1) {
3462 /*
3463 * Recursively invoke myself and the callbacks.
3464 */
3465 TQ_FOR(tmp.expr, &(expr->members), next) {
3466 ret = asn1c_recurse(&tmp, tmp.expr, callback, key);
3467 if(ret > maxret)
3468 maxret = ret;
3469 if(maxret > 1) break;
3470 }
3471 }
3472
3473 expr->_mark &= ~TM_RECURSION;
3474 return maxret;
3475}
3476
3477static int
3478check_is_refer_to(arg_t *arg, void *key) {
3479 asn1p_expr_t *terminal = terminal_structable(arg, arg->expr);
3480 if(terminal == key) {
3481 if(arg->expr->marker.flags & EM_INDIRECT)
3482 return 1; /* This is almost safe indirection */
3483 return 2;
3484 } else if(terminal) {
3485 /* This might be N-step circular loop. Dive into it. */
3486 return asn1c_recurse(arg, terminal, check_is_refer_to, key);
3487 }
3488 return 0;
3489}
3490
3491/*
3492 * Check if the possibly inner expression defined recursively.
3493 */
3494static int
3495expr_defined_recursively(arg_t *arg, asn1p_expr_t *expr) {
3496 asn1p_expr_t *terminal;
3497 asn1p_expr_t *topmost;
3498
3499 /* If expression is top-level, there's no way it can be recursive. */
3500 if(expr->parent_expr == 0) return 0;
3501 if(expr->expr_type != A1TC_REFERENCE)
3502 return 0; /* Basic types are never recursive */
3503
3504 terminal = terminal_structable(arg, expr);
3505 if(!terminal) return 0; /* Terminal cannot be indirected */
3506
3507 /* Search for the parent container for the given expression */
3508 topmost = expr;
3509 while(topmost->parent_expr)
3510 topmost = topmost->parent_expr;
3511
3512 /* Look inside the terminal type if it mentions the parent expression */
3513 return asn1c_recurse(arg, terminal, check_is_refer_to, topmost);
3514}
Lev Walkin59b176e2005-11-26 11:25:14 +00003515
3516struct canonical_map_element {
3517 int eidx;
3518 asn1p_expr_t *expr;
3519};
3520static int compar_cameo(const void *ap, const void *bp);
3521static arg_t *cameo_arg;
3522static int *
3523compute_canonical_members_order(arg_t *arg, int el_count) {
3524 struct canonical_map_element *cmap;
3525 int *rmap;
3526 asn1p_expr_t *v;
3527 int eidx = 0;
3528 int ext_start = -1;
3529 int nextmax = -1;
3530 int already_sorted = 1;
3531
3532 cmap = calloc(el_count, sizeof *cmap);
3533 assert(cmap);
3534
3535 TQ_FOR(v, &(arg->expr->members), next) {
3536 if(v->expr_type != A1TC_EXTENSIBLE) {
3537 cmap[eidx].eidx = eidx;
3538 cmap[eidx].expr = v;
3539 eidx++;
3540 } else if(ext_start == -1)
3541 ext_start = eidx;
3542 }
3543
3544 cameo_arg = arg;
3545 if(ext_start == -1) {
3546 /* Sort the whole thing */
3547 qsort(cmap, el_count, sizeof(*cmap), compar_cameo);
3548 } else {
3549 /* Sort root and extensions independently */
3550 qsort(cmap, ext_start, sizeof(*cmap), compar_cameo);
3551 qsort(cmap + ext_start, el_count - ext_start,
3552 sizeof(*cmap), compar_cameo);
3553 }
3554
3555 /* move data back to a simpler map */
3556 rmap = calloc(el_count, sizeof *rmap);
3557 assert(rmap);
3558 for(eidx = 0; eidx < el_count; eidx++) {
3559 rmap[eidx] = cmap[eidx].eidx;
3560 if(rmap[eidx] <= nextmax)
3561 already_sorted = 0;
3562 else
3563 nextmax = rmap[eidx];
3564 }
3565 free(cmap);
3566
3567 if(already_sorted) { free(rmap); rmap = 0; }
3568 return rmap;
3569}
3570static int compar_cameo(const void *ap, const void *bp) {
3571 const struct canonical_map_element *a = (const void *)ap;
3572 const struct canonical_map_element *b = (const void *)bp;
3573 struct asn1p_type_tag_s atag, btag;
3574 arg_t *arg = cameo_arg;
3575
Lev Walkinc0e03b92017-08-22 01:48:23 -07003576 if(WITH_MODULE_NAMESPACE(a->expr->module, expr_ns,
3577 asn1f_fetch_outmost_tag(
3578 arg->asn, expr_ns, a->expr->module, a->expr,
3579 &atag, AFT_IMAGINARY_ANY | AFT_CANON_CHOICE)))
3580 return 1;
Lev Walkin59b176e2005-11-26 11:25:14 +00003581
Lev Walkinc0e03b92017-08-22 01:48:23 -07003582 if(WITH_MODULE_NAMESPACE(b->expr->module, expr_ns,
3583 asn1f_fetch_outmost_tag(
3584 arg->asn, expr_ns, b->expr->module, b->expr,
3585 &btag, AFT_IMAGINARY_ANY | AFT_CANON_CHOICE)))
3586 return -1;
Lev Walkin59b176e2005-11-26 11:25:14 +00003587
3588 if(atag.tag_class < btag.tag_class)
3589 return -1;
3590 if(atag.tag_class > btag.tag_class)
3591 return 1;
3592 if(atag.tag_value < btag.tag_value)
3593 return -1;
3594 if(atag.tag_value > btag.tag_value)
3595 return 1;
3596 return 0;
3597
3598}