blob: e2aece01464b7234b4bbb05a74f508708b557644 [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 Walkin59b176e2005-11-26 11:25:14 +000011#include <asn1fix_crange.h> /* constraint groker from libasn1fix */
12#include <asn1fix_export.h> /* other exportables from libasn1fix */
Lev Walkinda997b12017-08-04 01:38:41 -070013#include <asn1parser.h>
Lev Walkinf15320b2004-06-03 03:38:44 +000014
Lev Walkinfd171ef2004-06-06 07:20:17 +000015typedef struct tag2el_s {
16 struct asn1p_type_tag_s el_tag;
17 int el_no;
Lev Walkin38abe792004-06-14 13:09:45 +000018 int toff_first;
19 int toff_last;
Lev Walkinfd171ef2004-06-06 07:20:17 +000020 asn1p_expr_t *from_expr;
21} tag2el_t;
22
Lev Walkin33d5d3c2004-10-03 09:13:30 +000023typedef enum fte {
24 FTE_ALLTAGS,
25 FTE_CANONICAL_XER,
26} fte_e;
27static int _fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags);
28static 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 +000029
Lev Walkin0f5d74c2005-08-14 15:03:31 +000030enum onc_flags {
31 ONC_noflags = 0x00,
32 ONC_avoid_keywords = 0x01,
33 ONC_force_compound_name = 0x02,
34};
35static int out_name_chain(arg_t *arg, enum onc_flags);
Lev Walkin9de6cd82017-08-10 05:47:46 -070036static int asn1c_lang_C_type_SEQUENCE_def(
37 arg_t *arg, asn1c_ioc_table_and_objset_t *);
Lev Walkinf15320b2004-06-03 03:38:44 +000038static int asn1c_lang_C_type_SET_def(arg_t *arg);
39static int asn1c_lang_C_type_CHOICE_def(arg_t *arg);
40static int asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of);
Lev Walkinc3e29402004-09-10 06:07:18 +000041static int _print_tag(arg_t *arg, struct asn1p_type_tag_s *tag_p);
Lev Walkin59b176e2005-11-26 11:25:14 +000042static int compute_extensions_start(asn1p_expr_t *expr);
Lev Walkinda9a3b82005-08-16 17:00:21 +000043static int expr_break_recursion(arg_t *arg, asn1p_expr_t *expr);
Lev Walkina9cc46e2004-09-22 16:06:28 +000044static int expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr);
Lev Walkin59964be2004-08-25 02:03:12 +000045static int expr_elements_count(arg_t *arg, asn1p_expr_t *expr);
Lev Walkinb9e98cb2017-08-02 12:53:44 -070046static int emit_single_member_OER_constraint_value(arg_t *arg, asn1cnst_range_t *range);
47static int emit_single_member_OER_constraint_size(arg_t *arg, asn1cnst_range_t *range);
48static 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 +040049static int emit_member_OER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx);
Lev Walkin4b5dae32006-10-09 12:27:44 +000050static int emit_member_PER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx);
Lev Walkin9de6cd82017-08-10 05:47:46 -070051static int emit_member_table(arg_t *arg, asn1p_expr_t *expr,
52 asn1c_ioc_table_and_objset_t *);
Lev Walkin33d5d3c2004-10-03 09:13:30 +000053static int emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier);
Lev Walkinc8285712005-03-04 22:18:20 +000054static int emit_include_dependencies(arg_t *arg);
Lev Walkinb85a8132005-08-18 13:38:19 +000055static asn1p_expr_t *terminal_structable(arg_t *arg, asn1p_expr_t *expr);
56static int expr_defined_recursively(arg_t *arg, asn1p_expr_t *expr);
57static 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 +000058static asn1p_expr_type_e expr_get_type(arg_t *arg, asn1p_expr_t *expr);
59static int try_inline_default(arg_t *arg, asn1p_expr_t *expr, int out);
60static int *compute_canonical_members_order(arg_t *arg, int el_count);
Lev Walkinf15320b2004-06-03 03:38:44 +000061
Lev Walkin188ed2c2004-09-13 08:31:01 +000062enum tvm_compat {
63 _TVM_SAME = 0, /* tags and all_tags are same */
64 _TVM_SUBSET = 1, /* tags are subset of all_tags */
65 _TVM_DIFFERENT = 2, /* tags and all_tags are different */
66};
67static enum tvm_compat emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tc, int *atc);
68
Lev Walkin59964be2004-08-25 02:03:12 +000069enum etd_spec {
70 ETD_NO_SPECIFICS,
71 ETD_HAS_SPECIFICS
72};
Lev Walkin8de2ab22004-09-26 13:11:31 +000073static 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 +000074
Lev Walkin59004fa2004-08-20 13:37:01 +000075#define C99_MODE (!(arg->flags & A1C_NO_C99))
Lev Walkinf15320b2004-06-03 03:38:44 +000076#define UNNAMED_UNIONS (arg->flags & A1C_UNNAMED_UNIONS)
Lev Walkindd32b592004-09-06 08:07:29 +000077#define HIDE_INNER_DEFS (arg->embed && !(arg->flags & A1C_ALL_DEFS_GLOBAL))
Lev Walkinf15320b2004-06-03 03:38:44 +000078
79#define PCTX_DEF INDENTED( \
80 OUT("\n"); \
81 OUT("/* Context for parsing across buffer boundaries */\n"); \
Lev Walkin05363a72004-09-29 13:16:40 +000082 OUT("asn_struct_ctx_t _asn_ctx;\n"));
Lev Walkinf15320b2004-06-03 03:38:44 +000083
Lev Walkinc8285712005-03-04 22:18:20 +000084
Lev Walkin3dcaafa2004-08-11 05:21:32 +000085#define DEPENDENCIES do { \
Lev Walkinc8285712005-03-04 22:18:20 +000086 emit_include_dependencies(arg); \
Lev Walkin3dcaafa2004-08-11 05:21:32 +000087 if(expr->expr_type == ASN_CONSTR_SET_OF) \
Lev Walkin22b5ed42006-09-13 02:51:20 +000088 GEN_INCLUDE_STD("asn_SET_OF"); \
Lev Walkin3dcaafa2004-08-11 05:21:32 +000089 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF) \
Lev Walkin22b5ed42006-09-13 02:51:20 +000090 GEN_INCLUDE_STD("asn_SEQUENCE_OF"); \
Lev Walkin3dcaafa2004-08-11 05:21:32 +000091} while(0)
Lev Walkinf15320b2004-06-03 03:38:44 +000092
Lev Walkincaf0d5a2005-03-04 23:48:19 +000093/* MKID_safe() without checking for reserved keywords */
Lev Walkina00d6b32006-03-21 03:40:38 +000094#define MKID(expr) (asn1c_make_identifier(0, expr, 0))
95#define MKID_safe(expr) (asn1c_make_identifier(AMI_CHECK_RESERVED, expr, 0))
Lev Walkinf15320b2004-06-03 03:38:44 +000096
97int
Lev Walkinc78cbfb2004-09-14 12:47:45 +000098asn1c_lang_C_type_REAL(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +000099 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
100}
101
Lev Walkine0b56e02005-02-25 12:10:27 +0000102struct value2enum {
103 asn1c_integer_t value;
104 const char *name;
105 int idx;
106};
107static int compar_enumMap_byName(const void *ap, const void *bp) {
108 const struct value2enum *a = (const struct value2enum *)ap;
109 const struct value2enum *b = (const struct value2enum *)bp;
110 return strcmp(a->name, b->name);
111}
112static int compar_enumMap_byValue(const void *ap, const void *bp) {
113 const struct value2enum *a = (const struct value2enum *)ap;
114 const struct value2enum *b = (const struct value2enum *)bp;
115 if(a->value < b->value)
116 return -1;
117 else if(a->value == b->value)
118 return 0;
119 return 1;
120}
121
Lev Walkinf15320b2004-06-03 03:38:44 +0000122int
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000123asn1c_lang_C_type_common_INTEGER(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000124 asn1p_expr_t *expr = arg->expr;
125 asn1p_expr_t *v;
Lev Walkine0b56e02005-02-25 12:10:27 +0000126 int el_count = expr_elements_count(arg, expr);
127 struct value2enum *v2e;
Lev Walkin59b176e2005-11-26 11:25:14 +0000128 int map_extensions = (expr->expr_type == ASN_BASIC_INTEGER);
Lev Walkin414b0782005-08-13 23:30:24 +0000129 int eidx;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800130 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000131
Lev Walkine0b56e02005-02-25 12:10:27 +0000132 v2e = alloca((el_count + 1) * sizeof(*v2e));
Lev Walkinf15320b2004-06-03 03:38:44 +0000133
Lev Walkine0b56e02005-02-25 12:10:27 +0000134 /*
Lev Walkin414b0782005-08-13 23:30:24 +0000135 * For all ENUMERATED types and for those INTEGER types which
136 * have identifiers, print out an enumeration table.
Lev Walkine0b56e02005-02-25 12:10:27 +0000137 */
Lev Walkin414b0782005-08-13 23:30:24 +0000138 if(expr->expr_type == ASN_BASIC_ENUMERATED || el_count) {
139 eidx = 0;
Lev Walkine0b56e02005-02-25 12:10:27 +0000140 REDIR(OT_DEPS);
Lev Walkin21d00002005-03-04 08:48:53 +0000141 OUT("typedef enum ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000142 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000143 OUT(" {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000144 TQ_FOR(v, &(expr->members), next) {
145 switch(v->expr_type) {
146 case A1TC_UNIVERVAL:
Lev Walkin21d00002005-03-04 08:48:53 +0000147 OUT("\t");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000148 out_name_chain(arg, ONC_noflags);
Lev Walkina00d6b32006-03-21 03:40:38 +0000149 OUT("_%s", MKID(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 Walkin171487e2006-03-21 07:25:18 +0000168 OUT("} e_");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000169 out_name_chain(arg, ONC_noflags);
Lev Walkin171487e2006-03-21 07:25:18 +0000170 OUT(";\n");
Lev Walkine0b56e02005-02-25 12:10:27 +0000171 assert(eidx == el_count);
Lev Walkin414b0782005-08-13 23:30:24 +0000172 }
173
174 /*
175 * For all ENUMERATED types print out a mapping table
176 * between identifiers and associated values.
177 * This is prohibited for INTEGER types by by X.693:8.3.4.
178 */
179 if(expr->expr_type == ASN_BASIC_ENUMERATED) {
Lev Walkine0b56e02005-02-25 12:10:27 +0000180
181 /*
182 * Generate a enumerationName<->value map for XER codec.
183 */
184 REDIR(OT_STAT_DEFS);
185
Wim Lewisfb6344e2014-07-28 12:16:01 -0700186 OUT("static const asn_INTEGER_enum_map_t asn_MAP_%s_value2enum_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000187 MKID(expr), expr->_type_unique_index);
Lev Walkine0b56e02005-02-25 12:10:27 +0000188 qsort(v2e, el_count, sizeof(v2e[0]), compar_enumMap_byValue);
189 for(eidx = 0; eidx < el_count; eidx++) {
190 v2e[eidx].idx = eidx;
Lev Walkinda997b12017-08-04 01:38:41 -0700191 OUT("\t{ %s,\t%ld,\t\"%s\" }%s\n",
192 asn1p_itoa(v2e[eidx].value),
Lev Walkine0b56e02005-02-25 12:10:27 +0000193 (long)strlen(v2e[eidx].name), v2e[eidx].name,
194 (eidx + 1 < el_count) ? "," : "");
195 }
Lev Walkin59b176e2005-11-26 11:25:14 +0000196 if(map_extensions)
Lev Walkine0b56e02005-02-25 12:10:27 +0000197 OUT("\t/* This list is extensible */\n");
198 OUT("};\n");
199
Wim Lewisfb6344e2014-07-28 12:16:01 -0700200 OUT("static const unsigned int asn_MAP_%s_enum2value_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000201 MKID(expr), expr->_type_unique_index);
Lev Walkine0b56e02005-02-25 12:10:27 +0000202 qsort(v2e, el_count, sizeof(v2e[0]), compar_enumMap_byName);
203 for(eidx = 0; eidx < el_count; eidx++) {
Lev Walkinda997b12017-08-04 01:38:41 -0700204 OUT("\t%d%s\t/* %s(%s) */\n",
Lev Walkine0b56e02005-02-25 12:10:27 +0000205 v2e[eidx].idx,
206 (eidx + 1 < el_count) ? "," : "",
Lev Walkinda997b12017-08-04 01:38:41 -0700207 v2e[eidx].name, asn1p_itoa(v2e[eidx].value));
Lev Walkine0b56e02005-02-25 12:10:27 +0000208 }
Lev Walkin59b176e2005-11-26 11:25:14 +0000209 if(map_extensions)
Lev Walkine0b56e02005-02-25 12:10:27 +0000210 OUT("\t/* This list is extensible */\n");
211 OUT("};\n");
212
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800213 if(!(expr->_type_referenced)) OUT("static ");
214 OUT("const asn_INTEGER_specifics_t asn_SPC_%s_specs_%d = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000215 MKID(expr), expr->_type_unique_index);
Lev Walkine0b56e02005-02-25 12:10:27 +0000216 INDENT(+1);
Lev Walkin59b176e2005-11-26 11:25:14 +0000217 OUT("asn_MAP_%s_value2enum_%d,\t"
Lev Walkine0b56e02005-02-25 12:10:27 +0000218 "/* \"tag\" => N; sorted by tag */\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000219 MKID(expr),
Lev Walkin21d00002005-03-04 08:48:53 +0000220 expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +0000221 OUT("asn_MAP_%s_enum2value_%d,\t"
Lev Walkine0b56e02005-02-25 12:10:27 +0000222 "/* N => \"tag\"; sorted by N */\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000223 MKID(expr),
Lev Walkin21d00002005-03-04 08:48:53 +0000224 expr->_type_unique_index);
Lev Walkine0b56e02005-02-25 12:10:27 +0000225 OUT("%d,\t/* Number of elements in the maps */\n",
226 el_count);
Lev Walkin59b176e2005-11-26 11:25:14 +0000227 if(map_extensions) {
228 OUT("%d,\t/* Extensions before this member */\n",
229 map_extensions);
230 } else {
231 OUT("0,\t/* Enumeration is not extensible */\n");
232 }
Lev Walkine0b56e02005-02-25 12:10:27 +0000233 if(expr->expr_type == ASN_BASIC_ENUMERATED)
Lev Walkin8bb57a22007-12-03 13:41:36 +0000234 OUT("1,\t/* Strict enumeration */\n");
Lev Walkine0b56e02005-02-25 12:10:27 +0000235 else
Lev Walkin8bb57a22007-12-03 13:41:36 +0000236 OUT("0,\n");
237 OUT("0,\t/* Native long size */\n");
238 OUT("0\n");
239 INDENT(-1);
240 OUT("};\n");
241 }
242
243 if(expr->expr_type == ASN_BASIC_INTEGER
244 && asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN) {
245 REDIR(OT_STAT_DEFS);
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800246 if(!(expr->_type_referenced)) OUT("static ");
247 OUT("const asn_INTEGER_specifics_t asn_SPC_%s_specs_%d = {\n",
Lev Walkin8bb57a22007-12-03 13:41:36 +0000248 MKID(expr), expr->_type_unique_index);
249 INDENT(+1);
250 OUT("0,\t");
251 OUT("0,\t");
252 OUT("0,\t");
253 OUT("0,\t");
254 OUT("0,\n");
255 OUT("0,\t/* Native long size */\n");
256 OUT("1\t/* Unsigned representation */\n");
Lev Walkine0b56e02005-02-25 12:10:27 +0000257 INDENT(-1);
258 OUT("};\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000259 }
260
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800261 REDIR(saved_target);
262
Lev Walkinf15320b2004-06-03 03:38:44 +0000263 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
264}
265
266int
Lev Walkinb02a8832005-08-13 23:51:47 +0000267asn1c_lang_C_type_BIT_STRING(arg_t *arg) {
268 asn1p_expr_t *expr = arg->expr;
269 asn1p_expr_t *v;
270 int el_count = expr_elements_count(arg, expr);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800271 int saved_target = arg->target->target;
Lev Walkinb02a8832005-08-13 23:51:47 +0000272
273 if(el_count) {
Lev Walkin082cadc2005-08-14 02:18:27 +0000274 int eidx = 0;
Lev Walkinb02a8832005-08-13 23:51:47 +0000275 REDIR(OT_DEPS);
276 OUT("typedef enum ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000277 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkinb02a8832005-08-13 23:51:47 +0000278 OUT(" {\n");
279 TQ_FOR(v, &(expr->members), next) {
Lev Walkin082cadc2005-08-14 02:18:27 +0000280 if(v->expr_type != A1TC_UNIVERVAL) {
Lev Walkinb02a8832005-08-13 23:51:47 +0000281 OUT("/* Unexpected BIT STRING element: %s */\n",
282 v->Identifier);
Lev Walkin082cadc2005-08-14 02:18:27 +0000283 continue;
Lev Walkinb02a8832005-08-13 23:51:47 +0000284 }
Lev Walkin0f8d4a42006-08-26 03:29:15 +0000285 eidx++;
Lev Walkin082cadc2005-08-14 02:18:27 +0000286 OUT("\t");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000287 out_name_chain(arg, ONC_noflags);
Lev Walkina00d6b32006-03-21 03:40:38 +0000288 OUT("_%s", MKID(v));
Lev Walkinda997b12017-08-04 01:38:41 -0700289 OUT("\t= %s%s\n",
290 asn1p_itoa(v->value->value.v_integer),
Lev Walkin082cadc2005-08-14 02:18:27 +0000291 (eidx < el_count) ? "," : "");
Lev Walkinb02a8832005-08-13 23:51:47 +0000292 }
Lev Walkin171487e2006-03-21 07:25:18 +0000293 OUT("} e_");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000294 out_name_chain(arg, ONC_noflags);
Lev Walkin171487e2006-03-21 07:25:18 +0000295 OUT(";\n");
Lev Walkinb02a8832005-08-13 23:51:47 +0000296 assert(eidx == el_count);
297 }
298
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800299 REDIR(saved_target);
300
Lev Walkinb02a8832005-08-13 23:51:47 +0000301 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
302}
303
304int
Lev Walkinf15320b2004-06-03 03:38:44 +0000305asn1c_lang_C_type_SEQUENCE(arg_t *arg) {
306 asn1p_expr_t *expr = arg->expr;
307 asn1p_expr_t *v;
308 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800309 int saved_target = arg->target->target;
Lev Walkinad0d6372017-08-08 02:02:42 -0700310 asn1c_ioc_table_and_objset_t ioc_tao;
Lev Walkinf15320b2004-06-03 03:38:44 +0000311
312 DEPENDENCIES;
313
Lev Walkinad0d6372017-08-08 02:02:42 -0700314 ioc_tao = asn1c_get_ioc_table(arg);
315 if(ioc_tao.ioct) {
316 if(emit_ioc_table(arg, expr, ioc_tao)) {
317 return -1;
318 }
319 } else if(ioc_tao.fatal_error) {
Lev Walkinea6635b2017-08-06 23:23:04 -0700320 return -1;
321 }
322
Lev Walkinf15320b2004-06-03 03:38:44 +0000323 if(arg->embed) {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800324
325 /* Use _anonymous_type field to indicate it's called from
326 * asn1c_lang_C_type_SEx_OF() */
327 if (expr->_anonymous_type) {
328 REDIR(OT_FWD_DEFS);
329 OUT("typedef ");
330 }
Lev Walkin21d00002005-03-04 08:48:53 +0000331 OUT("struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000332 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000333 OUT(" {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000334 } else {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800335 REDIR(OT_TYPE_DECLS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000336 OUT("typedef struct %s {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000337 MKID_safe(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +0000338 }
339
340 TQ_FOR(v, &(expr->members), next) {
Lev Walkinda9a3b82005-08-16 17:00:21 +0000341 if(v->expr_type == A1TC_EXTENSIBLE)
Lev Walkinf15320b2004-06-03 03:38:44 +0000342 if(comp_mode < 3) comp_mode++;
Lev Walkinda9a3b82005-08-16 17:00:21 +0000343 if(comp_mode == 1)
Lev Walkin59b176e2005-11-26 11:25:14 +0000344 v->marker.flags |= EM_OMITABLE | EM_INDIRECT;
345 try_inline_default(arg, v, 1);
Lev Walkin9de6cd82017-08-10 05:47:46 -0700346 EMBED_WITH_IOCT(v, ioc_tao);
Lev Walkinf15320b2004-06-03 03:38:44 +0000347 }
348
349 PCTX_DEF;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800350
351 if (arg->embed && expr->_anonymous_type) {
352 OUT("} %s", (expr->marker.flags & EM_INDIRECT)?"*":"");
353 out_name_chain(arg, ONC_avoid_keywords);
354 OUT("%s;\n", arg->embed ? "" : "_t");
355
356 REDIR(saved_target);
357
358 OUT("%s", (expr->marker.flags & EM_INDIRECT)?"*":"");
359 out_name_chain(arg, ONC_avoid_keywords);
360 } else {
361 OUT("} %s%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000362 expr->_anonymous_type ? "" :
363 arg->embed
Lev Walkina00d6b32006-03-21 03:40:38 +0000364 ? MKID_safe(expr)
365 : MKID(expr),
Lev Walkin08079b02004-08-22 03:25:24 +0000366 arg->embed ? "" : "_t");
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800367 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000368
Lev Walkin9de6cd82017-08-10 05:47:46 -0700369 return asn1c_lang_C_type_SEQUENCE_def(arg, ioc_tao.ioct ? &ioc_tao : 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000370}
371
372static int
Lev Walkin9de6cd82017-08-10 05:47:46 -0700373asn1c_lang_C_type_SEQUENCE_def(arg_t *arg, asn1c_ioc_table_and_objset_t *opt_ioc) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000374 asn1p_expr_t *expr = arg->expr;
375 asn1p_expr_t *v;
376 int elements; /* Number of elements */
Lev Walkin33af5c32007-06-23 20:05:49 +0000377 int ext_start = -2;
378 int ext_stop = -2;
Lev Walkinfd171ef2004-06-06 07:20:17 +0000379 tag2el_t *tag2el = NULL;
380 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000381 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000382 int all_tags_count;
383 enum tvm_compat tv_mode;
Lev Walkin59b176e2005-11-26 11:25:14 +0000384 int roms_count; /* Root optional members */
385 int aoms_count; /* Additions optional members */
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800386 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000387
Lev Walkinfd171ef2004-06-06 07:20:17 +0000388 /*
389 * Fetch every inner tag from the tag to elements map.
390 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000391 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
Lev Walkinfd171ef2004-06-06 07:20:17 +0000392 if(tag2el) free(tag2el);
393 return -1;
394 }
395
Lev Walkin22b5ed42006-09-13 02:51:20 +0000396 GEN_INCLUDE_STD("constr_SEQUENCE");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000397 if(!arg->embed)
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800398 GEN_DECLARE("SEQUENCE", expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000399
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000400 REDIR(OT_STAT_DEFS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000401
402 /*
Lev Walkin59b176e2005-11-26 11:25:14 +0000403 * Print out the table according to which parsing is performed.
Lev Walkinf15320b2004-06-03 03:38:44 +0000404 */
Lev Walkina9cc46e2004-09-22 16:06:28 +0000405 if(expr_elements_count(arg, expr)) {
406 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Lev Walkinf15320b2004-06-03 03:38:44 +0000407
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800408 if(!(expr->_type_referenced)) OUT("static ");
409 OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000410 MKID(expr), expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000411
412 elements = 0;
Lev Walkin59b176e2005-11-26 11:25:14 +0000413 roms_count = 0;
414 aoms_count = 0;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000415 INDENTED(TQ_FOR(v, &(expr->members), next) {
416 if(v->expr_type == A1TC_EXTENSIBLE) {
417 if((++comp_mode) == 1)
418 ext_start = elements - 1;
419 else
420 ext_stop = elements - 1;
421 continue;
422 }
Lev Walkin59b176e2005-11-26 11:25:14 +0000423 if(v->marker.flags & EM_OMITABLE)
424 comp_mode == 1 ? ++aoms_count : ++roms_count;
Lev Walkin9de6cd82017-08-10 05:47:46 -0700425 emit_member_table(arg, v, opt_ioc);
Lev Walkinda9a3b82005-08-16 17:00:21 +0000426 elements++;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000427 });
428 OUT("};\n");
Lev Walkin59b176e2005-11-26 11:25:14 +0000429
Lev Walkin3c5d9412017-07-24 01:49:24 +0400430 if((roms_count + aoms_count) && (arg->flags & (A1C_GEN_OER|A1C_GEN_PER))) {
Lev Walkin59b176e2005-11-26 11:25:14 +0000431 int elm = 0;
432 int comma = 0;
433 comp_mode = 0;
Wim Lewisfb6344e2014-07-28 12:16:01 -0700434 OUT("static const int asn_MAP_%s_oms_%d[] = {",
Lev Walkina00d6b32006-03-21 03:40:38 +0000435 MKID(expr),
Lev Walkin59b176e2005-11-26 11:25:14 +0000436 expr->_type_unique_index);
437 TQ_FOR(v, &(expr->members), next) {
438 if(v->expr_type == A1TC_EXTENSIBLE) {
439 ++comp_mode;
440 continue;
441 }
442 if((v->marker.flags & EM_OMITABLE)
443 && comp_mode != 1) {
444 if(!comma) comma++;
445 else OUT(",");
446 OUT(" %d", elm);
447 }
448 ++elm;
449 }
450 elm = 0;
451 comp_mode = 0;
452 TQ_FOR(v, &(expr->members), next) {
453 if(v->expr_type == A1TC_EXTENSIBLE) {
454 ++comp_mode;
455 continue;
456 }
457 if((v->marker.flags & EM_OMITABLE)
458 && comp_mode == 1) {
459 if(!comma) comma++;
460 else OUT(",");
461 OUT(" %d", elm);
462 }
463 ++elm;
464 }
465 OUT(" };\n");
Lev Walkinea6635b2017-08-06 23:23:04 -0700466 if(roms_count > 65536) {
Lev Walkin59b176e2005-11-26 11:25:14 +0000467 FATAL("Too many optional elements in %s "
468 "at line %d!",
469 arg->expr->Identifier,
470 arg->expr->_lineno);
Lev Walkinea6635b2017-08-06 23:23:04 -0700471 return -1;
472 }
Lev Walkin59b176e2005-11-26 11:25:14 +0000473 } else {
474 roms_count = 0;
475 aoms_count = 0;
476 }
Lev Walkina9cc46e2004-09-22 16:06:28 +0000477 } else {
478 elements = 0;
Lev Walkin59b176e2005-11-26 11:25:14 +0000479 roms_count = 0;
480 aoms_count = 0;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000481 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000482
Lev Walkin27ea3802004-06-28 21:13:46 +0000483 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000484 * Print out asn_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +0000485 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000486 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000487
Lev Walkinfd171ef2004-06-06 07:20:17 +0000488 /*
489 * Tags to elements map.
490 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000491 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
Lev Walkinfd171ef2004-06-06 07:20:17 +0000492
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800493 if(!(expr->_type_referenced)) OUT("static ");
494 OUT("asn_SEQUENCE_specifics_t asn_SPC_%s_specs_%d = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000495 MKID(expr), expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +0000496 INDENT(+1);
497 OUT("sizeof(struct ");
498 out_name_chain(arg, ONC_avoid_keywords); OUT("),\n");
499 OUT("offsetof(struct ");
500 out_name_chain(arg, ONC_avoid_keywords); OUT(", _asn_ctx),\n");
Lev Walkin21d00002005-03-04 08:48:53 +0000501
Lev Walkin59b176e2005-11-26 11:25:14 +0000502 if(tag2el_count) {
503 OUT("asn_MAP_%s_tag2el_%d,\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000504 MKID(expr),
Lev Walkin59b176e2005-11-26 11:25:14 +0000505 expr->_type_unique_index);
506 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
507 } else {
508 OUT("0,\t/* No top level tags */\n");
509 OUT("0,\t/* No tags in the map */\n");
510 }
511 if(roms_count + aoms_count) {
512 OUT("asn_MAP_%s_oms_%d,\t/* Optional members */\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000513 MKID(expr), expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +0000514 OUT("%d, %d,\t/* Root/Additions */\n", roms_count, aoms_count);
515 } else {
516 OUT("0, 0, 0,\t/* Optional elements (not needed) */\n");
517 }
518 OUT("%d,\t/* Start extensions */\n",
Lev Walkin33af5c32007-06-23 20:05:49 +0000519 ext_start<0 ? -1 : ext_start);
Lev Walkin59b176e2005-11-26 11:25:14 +0000520 OUT("%d\t/* Stop extensions */\n",
Lev Walkin33af5c32007-06-23 20:05:49 +0000521 (ext_stop<ext_start)?elements+1:(ext_stop<0?-1:ext_stop));
Lev Walkin59b176e2005-11-26 11:25:14 +0000522 INDENT(-1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000523 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000524
525 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000526 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +0000527 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000528 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
Lev Walkin8de2ab22004-09-26 13:11:31 +0000529 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000530
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800531 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +0000532
Bi-Ruei, Chiu12021b52016-11-04 11:59:45 +0800533 if(tag2el) free(tag2el);
534
Lev Walkinf15320b2004-06-03 03:38:44 +0000535 return 0;
Lev Walkinb0b33412005-01-17 11:57:48 +0000536} /* _SEQUENCE_def() */
Lev Walkinf15320b2004-06-03 03:38:44 +0000537
538int
Lev Walkinf15320b2004-06-03 03:38:44 +0000539asn1c_lang_C_type_SET(arg_t *arg) {
540 asn1p_expr_t *expr = arg->expr;
541 asn1p_expr_t *v;
542 long mcount;
543 char *id;
544 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800545 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000546
547 DEPENDENCIES;
548
549 REDIR(OT_DEPS);
550
551 OUT("\n");
552 OUT("/*\n");
553 OUT(" * Method of determining the components presence\n");
554 OUT(" */\n");
555 mcount = 0;
Lev Walkin21d00002005-03-04 08:48:53 +0000556 OUT("typedef enum ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000557 out_name_chain(arg, ONC_noflags);
Lev Walkin21d00002005-03-04 08:48:53 +0000558 OUT("_PR {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000559 TQ_FOR(v, &(expr->members), next) {
560 if(v->expr_type == A1TC_EXTENSIBLE) continue;
561 INDENTED(
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000562 out_name_chain(arg, ONC_noflags);
Lev Walkin801fabc2005-01-28 12:18:50 +0000563 OUT("_PR_");
Lev Walkina00d6b32006-03-21 03:40:38 +0000564 id = MKID(v);
Lev Walkinf15320b2004-06-03 03:38:44 +0000565 OUT("%s,\t/* Member %s is present */\n",
566 id, id)
567 );
568 mcount++;
569 }
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000570 OUT("} "); out_name_chain(arg, ONC_noflags); OUT("_PR;\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000571
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800572 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +0000573
574 if(arg->embed) {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800575 if (expr->_anonymous_type) {
576 REDIR(OT_FWD_DEFS);
577 OUT("typedef ");
578 }
Lev Walkin21d00002005-03-04 08:48:53 +0000579 OUT("struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000580 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000581 OUT(" {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000582 } else {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800583 REDIR(OT_TYPE_DECLS);
Lev Walkin59b176e2005-11-26 11:25:14 +0000584 OUT("typedef struct %s {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000585 MKID_safe(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +0000586 }
587
588 TQ_FOR(v, &(expr->members), next) {
Lev Walkin59b176e2005-11-26 11:25:14 +0000589 if(v->expr_type == A1TC_EXTENSIBLE)
Lev Walkinf15320b2004-06-03 03:38:44 +0000590 if(comp_mode < 3) comp_mode++;
Lev Walkinda9a3b82005-08-16 17:00:21 +0000591 if(comp_mode == 1)
Lev Walkin59b176e2005-11-26 11:25:14 +0000592 v->marker.flags |= EM_OMITABLE | EM_INDIRECT;
593 try_inline_default(arg, v, 1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000594 EMBED(v);
595 }
596
597 INDENTED(
Lev Walkina00d6b32006-03-21 03:40:38 +0000598 id = MKID(expr);
Lev Walkinf15320b2004-06-03 03:38:44 +0000599 OUT("\n");
600 OUT("/* Presence bitmask: ASN_SET_ISPRESENT(p%s, %s_PR_x) */\n",
601 id, id);
602 OUT("unsigned int _presence_map\n");
603 OUT("\t[((%ld+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))];\n", mcount);
604 );
605
606 PCTX_DEF;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800607
608 if (arg->embed && expr->_anonymous_type) {
609 OUT("} %s", (expr->marker.flags & EM_INDIRECT)?"*":"");
610 out_name_chain(arg, ONC_avoid_keywords);
611 OUT("%s;\n", arg->embed ? "" : "_t");
612
613 REDIR(saved_target);
614
615 OUT("%s", (expr->marker.flags & EM_INDIRECT)?"*":"");
616 out_name_chain(arg, ONC_avoid_keywords);
617 } else {
618 OUT("} %s%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
619 expr->_anonymous_type ? "" : MKID_safe(expr),
620 arg->embed ? "" : "_t");
621 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000622
623 return asn1c_lang_C_type_SET_def(arg);
624}
625
Lev Walkinf15320b2004-06-03 03:38:44 +0000626static int
627asn1c_lang_C_type_SET_def(arg_t *arg) {
628 asn1p_expr_t *expr = arg->expr;
629 asn1p_expr_t *v;
630 int elements;
Lev Walkinf15320b2004-06-03 03:38:44 +0000631 tag2el_t *tag2el = NULL;
632 int tag2el_count = 0;
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000633 tag2el_t *tag2el_cxer = NULL;
634 int tag2el_cxer_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000635 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000636 int all_tags_count;
637 enum tvm_compat tv_mode;
Lev Walkinf15320b2004-06-03 03:38:44 +0000638 char *p;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800639 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000640
641 /*
642 * Fetch every inner tag from the tag to elements map.
643 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000644 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000645 if(tag2el) free(tag2el);
646 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000647 }
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000648 if(_fill_tag2el_map(arg, &tag2el_cxer, &tag2el_cxer_count, -1, FTE_CANONICAL_XER)) {
649 if(tag2el) free(tag2el);
650 if(tag2el_cxer) free(tag2el_cxer);
651 return -1;
652 }
653 if(tag2el_cxer_count == tag2el_count
654 && memcmp(tag2el, tag2el_cxer, tag2el_count) == 0) {
655 free(tag2el_cxer);
656 tag2el_cxer = 0;
657 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000658
Lev Walkin22b5ed42006-09-13 02:51:20 +0000659 GEN_INCLUDE_STD("constr_SET");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000660 if(!arg->embed)
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800661 GEN_DECLARE("SET", expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000662
663 REDIR(OT_STAT_DEFS);
664
Lev Walkinf15320b2004-06-03 03:38:44 +0000665 /*
Lev Walkin59b176e2005-11-26 11:25:14 +0000666 * Print out the table according to which parsing is performed.
Lev Walkinf15320b2004-06-03 03:38:44 +0000667 */
Lev Walkina9cc46e2004-09-22 16:06:28 +0000668 if(expr_elements_count(arg, expr)) {
669 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Lev Walkinf15320b2004-06-03 03:38:44 +0000670
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800671 if(!(expr->_type_referenced)) OUT("static ");
672 OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000673 MKID(expr), expr->_type_unique_index);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800674
Lev Walkina9cc46e2004-09-22 16:06:28 +0000675 elements = 0;
676 INDENTED(TQ_FOR(v, &(expr->members), next) {
677 if(v->expr_type == A1TC_EXTENSIBLE) {
678 if(comp_mode < 3) comp_mode++;
679 } else {
Lev Walkin9de6cd82017-08-10 05:47:46 -0700680 emit_member_table(arg, v, NULL);
Lev Walkinda9a3b82005-08-16 17:00:21 +0000681 elements++;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000682 }
683 });
684 OUT("};\n");
685 } else {
686 elements = 0;
687 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000688
Lev Walkin27ea3802004-06-28 21:13:46 +0000689 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000690 * Print out asn_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +0000691 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000692 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000693
694 /*
695 * Tags to elements map.
696 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000697 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
698 if(tag2el_cxer)
699 emit_tag2member_map(arg, tag2el_cxer, tag2el_cxer_count, "_cxer");
Lev Walkinf15320b2004-06-03 03:38:44 +0000700
701 /*
702 * Emit a map of mandatory elements.
703 */
Wim Lewisfb6344e2014-07-28 12:16:01 -0700704 OUT("static const uint8_t asn_MAP_%s_mmap_%d",
Lev Walkina00d6b32006-03-21 03:40:38 +0000705 MKID(expr), expr->_type_unique_index);
706 p = MKID_safe(expr);
Lev Walkinf15320b2004-06-03 03:38:44 +0000707 OUT("[(%d + (8 * sizeof(unsigned int)) - 1) / 8]", elements);
Lev Walkin21d00002005-03-04 08:48:53 +0000708 OUT(" = {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000709 INDENTED(
710 if(elements) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000711 int el = 0;
712 TQ_FOR(v, &(expr->members), next) {
713 if(v->expr_type == A1TC_EXTENSIBLE) continue;
Lev Walkinac760bf2005-10-05 08:59:03 +0000714 if(el) {
715 if((el % 8) == 0)
716 OUT(",\n");
717 else
718 OUT(" | ");
Lev Walkinf15320b2004-06-03 03:38:44 +0000719 }
Lev Walkincc93b0f2004-09-10 09:18:20 +0000720 OUT("(%d << %d)",
Lev Walkinb85a8132005-08-18 13:38:19 +0000721 (v->marker.flags & EM_OMITABLE) != EM_OMITABLE,
Lev Walkincc93b0f2004-09-10 09:18:20 +0000722 7 - (el % 8));
Lev Walkinf15320b2004-06-03 03:38:44 +0000723 el++;
724 }
725 } else {
726 OUT("0");
727 }
728 );
729 OUT("\n");
730 OUT("};\n");
731
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800732 if(!(expr->_type_referenced)) OUT("static \n");
733 OUT("asn_SET_specifics_t asn_SPC_%s_specs_%d = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000734 MKID(expr), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +0000735 INDENTED(
Lev Walkin21d00002005-03-04 08:48:53 +0000736 OUT("sizeof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000737 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000738 OUT("),\n");
739 OUT("offsetof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000740 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000741 OUT(", _asn_ctx),\n");
742 OUT("offsetof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000743 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000744 OUT(", _presence_map),\n");
Lev Walkina00d6b32006-03-21 03:40:38 +0000745 p = MKID(expr);
Lev Walkin59b176e2005-11-26 11:25:14 +0000746 OUT("asn_MAP_%s_tag2el_%d,\n", p, expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +0000747 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000748 if(tag2el_cxer)
Lev Walkin59b176e2005-11-26 11:25:14 +0000749 OUT("asn_MAP_%s_tag2el_cxer_%d,\n",
Lev Walkin21d00002005-03-04 08:48:53 +0000750 p, expr->_type_unique_index);
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000751 else
Lev Walkin59b176e2005-11-26 11:25:14 +0000752 OUT("asn_MAP_%s_tag2el_%d,\t/* Same as above */\n",
Lev Walkin21d00002005-03-04 08:48:53 +0000753 p, expr->_type_unique_index);
754 OUT("%d,\t/* Count of tags in the CXER map */\n",
755 tag2el_cxer_count);
Lev Walkin35631482004-07-01 00:52:50 +0000756 OUT("%d,\t/* Whether extensible */\n",
Lev Walkin59b176e2005-11-26 11:25:14 +0000757 compute_extensions_start(expr) == -1 ? 0 : 1);
Lev Walkin46ef3f32017-07-06 08:47:53 -0700758 OUT("(const unsigned int *)asn_MAP_%s_mmap_%d\t/* Mandatory elements map */\n",
Lev Walkin21d00002005-03-04 08:48:53 +0000759 p, expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +0000760 );
761 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000762
763 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000764 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +0000765 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000766 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
Lev Walkin8de2ab22004-09-26 13:11:31 +0000767 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000768
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800769 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +0000770
Bi-Ruei, Chiu12021b52016-11-04 11:59:45 +0800771 if (tag2el) free(tag2el);
772 if (tag2el_cxer) free(tag2el_cxer);
773
Lev Walkinf15320b2004-06-03 03:38:44 +0000774 return 0;
Lev Walkinb0b33412005-01-17 11:57:48 +0000775} /* _SET_def() */
Lev Walkinf15320b2004-06-03 03:38:44 +0000776
777int
Lev Walkin08079b02004-08-22 03:25:24 +0000778asn1c_lang_C_type_SEx_OF(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000779 asn1p_expr_t *expr = arg->expr;
Lev Walkinc8285712005-03-04 22:18:20 +0000780 asn1p_expr_t *memb = TQ_FIRST(&expr->members);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800781 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000782
783 DEPENDENCIES;
784
785 if(arg->embed) {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800786 if (expr->_anonymous_type) {
787 REDIR(OT_FWD_DEFS);
788 OUT("typedef ");
789 }
Lev Walkin21d00002005-03-04 08:48:53 +0000790 OUT("struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000791 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000792 OUT(" {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000793 } else {
Lev Walkina00d6b32006-03-21 03:40:38 +0000794 OUT("typedef struct %s {\n", MKID_safe(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +0000795 }
796
Lev Walkin08079b02004-08-22 03:25:24 +0000797 INDENT(+1);
798 OUT("A_%s_OF(",
799 (arg->expr->expr_type == ASN_CONSTR_SET_OF)
800 ? "SET" : "SEQUENCE");
Lev Walkinda9a3b82005-08-16 17:00:21 +0000801
802 /*
803 * README README
804 * The implementation of the A_SET_OF() macro is already indirect.
805 */
806 memb->marker.flags |= EM_INDIRECT;
807
Lev Walkine0b56e02005-02-25 12:10:27 +0000808 if(memb->expr_type & ASN_CONSTR_MASK
809 || ((memb->expr_type == ASN_BASIC_ENUMERATED
Lev Walkin8ecf9db2005-03-03 21:28:12 +0000810 || (0 /* -- prohibited by X.693:8.3.4 */
811 && memb->expr_type == ASN_BASIC_INTEGER))
812 && expr_elements_count(arg, memb))) {
Lev Walkin08079b02004-08-22 03:25:24 +0000813 arg_t tmp;
814 asn1p_expr_t tmp_memb;
815 arg->embed++;
816 tmp = *arg;
817 tmp.expr = &tmp_memb;
818 tmp_memb = *memb;
Lev Walkinda9a3b82005-08-16 17:00:21 +0000819 tmp_memb.marker.flags &= ~EM_INDIRECT;
Lev Walkin08079b02004-08-22 03:25:24 +0000820 tmp_memb._anonymous_type = 1;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000821 if(tmp_memb.Identifier == 0) {
Lev Walkin21d00002005-03-04 08:48:53 +0000822 tmp_memb.Identifier = "Member";
823 if(0)
Lev Walkina9cc46e2004-09-22 16:06:28 +0000824 tmp_memb.Identifier = strdup(
825 asn1c_make_identifier(0,
Lev Walkina00d6b32006-03-21 03:40:38 +0000826 expr, "Member", 0));
Lev Walkina9cc46e2004-09-22 16:06:28 +0000827 assert(tmp_memb.Identifier);
828 }
Lev Walkin9de6cd82017-08-10 05:47:46 -0700829 tmp.default_cb(&tmp, NULL);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000830 if(tmp_memb.Identifier != memb->Identifier)
Lev Walkin21d00002005-03-04 08:48:53 +0000831 if(0) free(tmp_memb.Identifier);
Lev Walkin08079b02004-08-22 03:25:24 +0000832 arg->embed--;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800833 assert(arg->target->target == OT_TYPE_DECLS ||
834 arg->target->target == OT_FWD_DEFS);
Lev Walkin08079b02004-08-22 03:25:24 +0000835 } else {
Lev Walkinfe7f6ec2005-03-04 22:38:22 +0000836 OUT("%s", asn1c_type_name(arg, memb,
837 (memb->marker.flags & EM_UNRECURSE)
838 ? TNF_RSAFE : TNF_CTYPE));
Lev Walkinf15320b2004-06-03 03:38:44 +0000839 }
Lev Walkinda9a3b82005-08-16 17:00:21 +0000840 /* README README (above) */
841 if(0 && (memb->marker.flags & EM_INDIRECT))
842 OUT(" *");
Lev Walkin08079b02004-08-22 03:25:24 +0000843 OUT(") list;\n");
844 INDENT(-1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000845
846 PCTX_DEF;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800847
848 if (arg->embed && expr->_anonymous_type) {
849 OUT("} %s", (expr->marker.flags & EM_INDIRECT)?"*":"");
850 out_name_chain(arg, ONC_avoid_keywords);
851 OUT("%s;\n", arg->embed ? "" : "_t");
852
853 REDIR(saved_target);
854
855 OUT("%s", (expr->marker.flags & EM_INDIRECT)?"*":"");
856 out_name_chain(arg, ONC_avoid_keywords);
857 } else {
858 OUT("} %s%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
859 expr->_anonymous_type ? "" : MKID_safe(expr),
860 arg->embed ? "" : "_t");
861 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000862
863 /*
Lev Walkin08079b02004-08-22 03:25:24 +0000864 * SET OF/SEQUENCE OF definition
Lev Walkinf15320b2004-06-03 03:38:44 +0000865 */
Lev Walkin08079b02004-08-22 03:25:24 +0000866 return asn1c_lang_C_type_SEx_OF_def(arg,
867 (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF));
Lev Walkinf15320b2004-06-03 03:38:44 +0000868}
869
870static int
871asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
872 asn1p_expr_t *expr = arg->expr;
873 asn1p_expr_t *v;
Lev Walkin64399722004-08-11 07:17:22 +0000874 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000875 int all_tags_count;
876 enum tvm_compat tv_mode;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800877 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000878
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000879 /*
Lev Walkin59b176e2005-11-26 11:25:14 +0000880 * Print out the table according to which parsing is performed.
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000881 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000882 if(seq_of) {
Lev Walkin22b5ed42006-09-13 02:51:20 +0000883 GEN_INCLUDE_STD("constr_SEQUENCE_OF");
Lev Walkinf15320b2004-06-03 03:38:44 +0000884 } else {
Lev Walkin22b5ed42006-09-13 02:51:20 +0000885 GEN_INCLUDE_STD("constr_SET_OF");
Lev Walkinf15320b2004-06-03 03:38:44 +0000886 }
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000887 if(!arg->embed)
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800888 GEN_DECLARE("SET_OF", expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000889
890 REDIR(OT_STAT_DEFS);
891
892 /*
Lev Walkin59b176e2005-11-26 11:25:14 +0000893 * Print out the table according to which parsing is performed.
Lev Walkinf15320b2004-06-03 03:38:44 +0000894 */
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800895 if(!(expr->_type_referenced)) OUT("static ");
896 OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000897 MKID(expr), expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000898 INDENT(+1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000899 v = TQ_FIRST(&(expr->members));
Lev Walkina9cc46e2004-09-22 16:06:28 +0000900 if(!v->Identifier) {
Lev Walkin152a91e2005-02-14 20:41:29 +0000901 v->Identifier = strdup("Member");
Lev Walkina9cc46e2004-09-22 16:06:28 +0000902 assert(v->Identifier);
903 }
904 v->_anonymous_type = 1;
905 arg->embed++;
Lev Walkin9de6cd82017-08-10 05:47:46 -0700906 emit_member_table(arg, v, NULL);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000907 arg->embed--;
Bi-Ruei, Chiu9b780832016-11-07 22:19:10 +0800908 free(v->Identifier);
909 v->Identifier = (char *)NULL;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000910 INDENT(-1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000911 OUT("};\n");
912
Lev Walkin27ea3802004-06-28 21:13:46 +0000913 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000914 * Print out asn_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +0000915 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000916 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000917
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800918 if(!(expr->_type_referenced)) OUT("static ");
919 OUT("asn_SET_OF_specifics_t asn_SPC_%s_specs_%d = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000920 MKID(expr), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +0000921 INDENTED(
Lev Walkin21d00002005-03-04 08:48:53 +0000922 OUT("sizeof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000923 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000924 OUT("),\n");
925 OUT("offsetof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000926 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000927 OUT(", _asn_ctx),\n");
Lev Walkind1bfea62005-11-08 03:06:16 +0000928 {
929 int as_xvl = expr_as_xmlvaluelist(arg, v);
930 OUT("%d,\t/* XER encoding is %s */\n",
931 as_xvl,
932 as_xvl ? "XMLValueList" : "XMLDelimitedItemList");
933 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000934 );
935 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000936
937 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000938 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +0000939 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000940 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, 1,
Lev Walkin8de2ab22004-09-26 13:11:31 +0000941 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000942
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800943 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +0000944
945 return 0;
Lev Walkinb0b33412005-01-17 11:57:48 +0000946} /* _SEx_OF_def() */
Lev Walkinf15320b2004-06-03 03:38:44 +0000947
948int
949asn1c_lang_C_type_CHOICE(arg_t *arg) {
950 asn1p_expr_t *expr = arg->expr;
951 asn1p_expr_t *v;
Lev Walkin08079b02004-08-22 03:25:24 +0000952 char *id;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800953 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000954
955 DEPENDENCIES;
956
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000957 REDIR(OT_DEPS);
958
Lev Walkin21d00002005-03-04 08:48:53 +0000959 OUT("typedef enum ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000960 out_name_chain(arg, ONC_noflags);
Lev Walkin21d00002005-03-04 08:48:53 +0000961 OUT("_PR {\n");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000962 INDENTED(
Lev Walkin11380fb2006-08-18 01:38:40 +0000963 int skipComma = 1;
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000964 out_name_chain(arg, ONC_noflags);
Lev Walkin801fabc2005-01-28 12:18:50 +0000965 OUT("_PR_NOTHING,\t/* No components present */\n");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000966 TQ_FOR(v, &(expr->members), next) {
Lev Walkin11380fb2006-08-18 01:38:40 +0000967 if(skipComma) skipComma = 0;
johvik792216e2017-04-11 10:42:21 +0200968 else if (v->expr_type == A1TC_EXTENSIBLE && !TQ_NEXT(v, next)) OUT("\n");
Lev Walkin1dc85292006-08-18 01:32:26 +0000969 else OUT(",\n");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000970 if(v->expr_type == A1TC_EXTENSIBLE) {
971 OUT("/* Extensions may appear below */\n");
Lev Walkin11380fb2006-08-18 01:38:40 +0000972 skipComma = 1;
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000973 continue;
974 }
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000975 out_name_chain(arg, ONC_noflags);
Lev Walkina00d6b32006-03-21 03:40:38 +0000976 id = MKID(v);
Lev Walkin1dc85292006-08-18 01:32:26 +0000977 OUT("_PR_%s", id);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000978 }
Lev Walkin1dc85292006-08-18 01:32:26 +0000979 OUT("\n");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000980 );
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000981 OUT("} "); out_name_chain(arg, ONC_noflags); OUT("_PR;\n");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000982
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800983 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +0000984
985 if(arg->embed) {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800986 if (expr->_anonymous_type) {
987 REDIR(OT_FWD_DEFS);
988 OUT("typedef ");
989 }
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000990 OUT("struct "); out_name_chain(arg, ONC_avoid_keywords); OUT(" {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000991 } else {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800992 REDIR(OT_TYPE_DECLS);
Lev Walkina00d6b32006-03-21 03:40:38 +0000993 OUT("typedef struct %s {\n", MKID_safe(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +0000994 }
995
996 INDENTED(
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000997 out_name_chain(arg, ONC_noflags);
Lev Walkin801fabc2005-01-28 12:18:50 +0000998 OUT("_PR present;\n");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000999 OUT("union ");
1000 if(UNNAMED_UNIONS == 0) {
1001 out_name_chain(arg, ONC_force_compound_name);
1002 OUT("_u ");
1003 }
1004 OUT("{\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001005 TQ_FOR(v, &(expr->members), next) {
1006 EMBED(v);
1007 }
1008 if(UNNAMED_UNIONS) OUT("};\n");
1009 else OUT("} choice;\n");
1010 );
1011
1012 PCTX_DEF;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001013
1014 if (arg->embed && expr->_anonymous_type) {
1015 OUT("} %s", (expr->marker.flags & EM_INDIRECT)?"*":"");
1016 out_name_chain(arg, ONC_avoid_keywords);
1017 OUT("%s;\n", arg->embed ? "" : "_t");
1018
1019 REDIR(saved_target);
1020
1021 OUT("%s", (expr->marker.flags & EM_INDIRECT)?"*":"");
1022 out_name_chain(arg, ONC_avoid_keywords);
1023 } else {
1024 OUT("} %s%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
1025 expr->_anonymous_type ? "" :
1026 arg->embed
1027 ? MKID_safe(expr)
1028 : MKID(expr),
1029 arg->embed ? "" : "_t");
1030 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001031
1032 return asn1c_lang_C_type_CHOICE_def(arg);
1033}
1034
1035static int
1036asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
1037 asn1p_expr_t *expr = arg->expr;
1038 asn1p_expr_t *v;
1039 int elements; /* Number of elements */
Lev Walkinf15320b2004-06-03 03:38:44 +00001040 tag2el_t *tag2el = NULL;
1041 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +00001042 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +00001043 int all_tags_count;
1044 enum tvm_compat tv_mode;
Lev Walkin59b176e2005-11-26 11:25:14 +00001045 int *cmap = 0;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001046 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +00001047
1048 /*
1049 * Fetch every inner tag from the tag to elements map.
1050 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001051 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001052 if(tag2el) free(tag2el);
1053 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +00001054 }
1055
Lev Walkin22b5ed42006-09-13 02:51:20 +00001056 GEN_INCLUDE_STD("constr_CHOICE");
Lev Walkin3dcaafa2004-08-11 05:21:32 +00001057 if(!arg->embed)
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001058 GEN_DECLARE("CHOICE", expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +00001059
Lev Walkin3dcaafa2004-08-11 05:21:32 +00001060 REDIR(OT_STAT_DEFS);
Lev Walkinf15320b2004-06-03 03:38:44 +00001061
1062 /*
Lev Walkin59b176e2005-11-26 11:25:14 +00001063 * Print out the table according to which parsing is performed.
Lev Walkinf15320b2004-06-03 03:38:44 +00001064 */
Lev Walkina9cc46e2004-09-22 16:06:28 +00001065 if(expr_elements_count(arg, expr)) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001066
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001067 if(!(expr->_type_referenced)) OUT("static ");
1068 OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00001069 MKID(expr), expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +00001070
1071 elements = 0;
1072 INDENTED(TQ_FOR(v, &(expr->members), next) {
Lev Walkin659c63b2005-01-17 11:40:49 +00001073 if(v->expr_type == A1TC_EXTENSIBLE)
1074 continue;
Lev Walkin9de6cd82017-08-10 05:47:46 -07001075 emit_member_table(arg, v, NULL);
Lev Walkinda9a3b82005-08-16 17:00:21 +00001076 elements++;
Lev Walkina9cc46e2004-09-22 16:06:28 +00001077 });
1078 OUT("};\n");
1079 } else {
1080 elements = 0;
1081 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001082
Lev Walkin59b176e2005-11-26 11:25:14 +00001083 /* Create a canonical elements map */
1084 if(elements && (arg->flags & A1C_GEN_PER)) {
1085 int i;
1086 cmap = compute_canonical_members_order(arg, elements);
1087 if(cmap) {
Wim Lewisfb6344e2014-07-28 12:16:01 -07001088 OUT("static const int asn_MAP_%s_cmap_%d[] = {",
Lev Walkina00d6b32006-03-21 03:40:38 +00001089 MKID(expr),
Lev Walkin59b176e2005-11-26 11:25:14 +00001090 expr->_type_unique_index);
1091 for(i = 0; i < elements; i++) {
1092 if(i) OUT(",");
1093 OUT(" %d", cmap[i]);
1094 }
1095 OUT(" };\n");
1096 free(cmap);
1097 }
1098 }
Lev Walkin64399722004-08-11 07:17:22 +00001099
Lev Walkinf15320b2004-06-03 03:38:44 +00001100 if(arg->embed) {
1101 /*
1102 * Our parent structure has already taken this into account.
1103 */
Lev Walkin188ed2c2004-09-13 08:31:01 +00001104 tv_mode = _TVM_SAME;
1105 tags_count = all_tags_count = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +00001106 } else {
Lev Walkin188ed2c2004-09-13 08:31:01 +00001107 tv_mode = emit_tags_vectors(arg, expr,
1108 &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +00001109 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001110
1111 /*
1112 * Tags to elements map.
1113 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001114 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +00001115
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001116 if(!(expr->_type_referenced)) OUT("static ");
1117 OUT("asn_CHOICE_specifics_t asn_SPC_%s_specs_%d = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00001118 MKID(expr), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +00001119 INDENTED(
Lev Walkin21d00002005-03-04 08:48:53 +00001120 OUT("sizeof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +00001121 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +00001122 OUT("),\n");
1123 OUT("offsetof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +00001124 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +00001125 OUT(", _asn_ctx),\n");
1126 OUT("offsetof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +00001127 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +00001128 OUT(", present),\n");
1129 OUT("sizeof(((struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +00001130 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +00001131 OUT(" *)0)->present),\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00001132 OUT("asn_MAP_%s_tag2el_%d,\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00001133 MKID(expr), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +00001134 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
Lev Walkin59b176e2005-11-26 11:25:14 +00001135 if(C99_MODE) OUT(".canonical_order = ");
1136 if(cmap) OUT("asn_MAP_%s_cmap_%d,\t/* Canonically sorted */\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00001137 MKID(expr), expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00001138 else OUT("0,\n");
1139 if(C99_MODE) OUT(".ext_start = ");
1140 OUT("%d\t/* Extensions start */\n",
1141 compute_extensions_start(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +00001142 );
1143 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +00001144
1145 /*
Lev Walkin05363a72004-09-29 13:16:40 +00001146 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +00001147 */
Lev Walkin188ed2c2004-09-13 08:31:01 +00001148 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
Lev Walkin8de2ab22004-09-26 13:11:31 +00001149 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +00001150
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001151 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +00001152
Bi-Ruei, Chiu12021b52016-11-04 11:59:45 +08001153 if (tag2el) free(tag2el);
1154
Lev Walkinf15320b2004-06-03 03:38:44 +00001155 return 0;
Lev Walkinb0b33412005-01-17 11:57:48 +00001156} /* _CHOICE_def() */
Lev Walkinf15320b2004-06-03 03:38:44 +00001157
1158int
1159asn1c_lang_C_type_REFERENCE(arg_t *arg) {
1160 asn1p_ref_t *ref;
1161
1162 ref = arg->expr->reference;
1163 if(ref->components[ref->comp_count-1].name[0] == '&') {
Lev Walkinf15320b2004-06-03 03:38:44 +00001164 asn1p_expr_t *extract;
1165 arg_t tmp;
1166 int ret;
1167
Lev Walkina9cc46e2004-09-22 16:06:28 +00001168 extract = asn1f_class_access_ex(arg->asn, arg->expr->module,
Lev Walkina00d6b32006-03-21 03:40:38 +00001169 arg->expr, arg->expr->rhs_pspecs, ref);
Lev Walkinf15320b2004-06-03 03:38:44 +00001170 if(extract == NULL)
1171 return -1;
1172
Lev Walkin08079b02004-08-22 03:25:24 +00001173 extract = asn1p_expr_clone(extract, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +00001174 if(extract) {
Lev Walkind8b83642016-03-14 02:00:27 -07001175 free(extract->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +00001176 extract->Identifier = strdup(arg->expr->Identifier);
1177 if(extract->Identifier == NULL) {
1178 asn1p_expr_free(extract);
1179 return -1;
1180 }
1181 } else {
1182 return -1;
1183 }
1184
1185 tmp = *arg;
1186 tmp.asn = arg->asn;
Lev Walkinf15320b2004-06-03 03:38:44 +00001187 tmp.expr = extract;
1188
Lev Walkin9de6cd82017-08-10 05:47:46 -07001189 ret = arg->default_cb(&tmp, NULL);
Lev Walkinf15320b2004-06-03 03:38:44 +00001190
1191 asn1p_expr_free(extract);
1192
1193 return ret;
1194 }
1195
1196
1197 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
1198}
1199
1200int
1201asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
1202 asn1p_expr_t *expr = arg->expr;
Lev Walkin64399722004-08-11 07:17:22 +00001203 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +00001204 int all_tags_count;
1205 enum tvm_compat tv_mode;
Lev Walkine0b56e02005-02-25 12:10:27 +00001206 enum etd_spec etd_spec;
Lev Walkinf15320b2004-06-03 03:38:44 +00001207 char *p;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001208 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +00001209
1210 if(arg->embed) {
Lev Walkin05363a72004-09-29 13:16:40 +00001211 enum tnfmt tnfmt = TNF_CTYPE;
1212
1213 /*
1214 * If this is an optional compound type,
1215 * refer it using "struct X" convention,
1216 * as it may recursively include the current structure.
1217 */
Lev Walkinc8285712005-03-04 22:18:20 +00001218 if(expr->marker.flags & (EM_INDIRECT | EM_UNRECURSE)) {
Lev Walkinb85a8132005-08-18 13:38:19 +00001219 if(terminal_structable(arg, expr)) {
Lev Walkinc8285712005-03-04 22:18:20 +00001220 tnfmt = TNF_RSAFE;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001221 if(saved_target != OT_FWD_DECLS) {
1222 REDIR(OT_FWD_DECLS);
1223 OUT("%s;\n",
1224 asn1c_type_name(arg, arg->expr, tnfmt));
1225 }
1226 REDIR(saved_target);
Lev Walkin05363a72004-09-29 13:16:40 +00001227 }
1228 }
1229
Lev Walkinf15320b2004-06-03 03:38:44 +00001230
Lev Walkinc8285712005-03-04 22:18:20 +00001231 OUT("%s", asn1c_type_name(arg, arg->expr, tnfmt));
Lev Walkine0b56e02005-02-25 12:10:27 +00001232 if(!expr->_anonymous_type) {
Lev Walkinc8285712005-03-04 22:18:20 +00001233 OUT("%s", (expr->marker.flags&EM_INDIRECT)?"\t*":"\t ");
Lev Walkina00d6b32006-03-21 03:40:38 +00001234 OUT("%s", MKID_safe(expr));
Lev Walkin59b176e2005-11-26 11:25:14 +00001235 if((expr->marker.flags & (EM_DEFAULT & ~EM_INDIRECT))
1236 == (EM_DEFAULT & ~EM_INDIRECT))
Lev Walkine0b56e02005-02-25 12:10:27 +00001237 OUT("\t/* DEFAULT %s */",
1238 asn1f_printable_value(
1239 expr->marker.default_value));
Lev Walkin59b176e2005-11-26 11:25:14 +00001240 else if((expr->marker.flags & EM_OPTIONAL)
1241 == EM_OPTIONAL)
Lev Walkine0b56e02005-02-25 12:10:27 +00001242 OUT("\t/* OPTIONAL */");
1243 }
1244
1245 } else {
1246 GEN_INCLUDE(asn1c_type_name(arg, expr, TNF_INCLUDE));
Lev Walkin59004fa2004-08-20 13:37:01 +00001247
1248 REDIR(OT_TYPE_DECLS);
Lev Walkine0b56e02005-02-25 12:10:27 +00001249
1250 OUT("typedef %s\t",
Lev Walkinc8285712005-03-04 22:18:20 +00001251 asn1c_type_name(arg, arg->expr, TNF_CTYPE));
Lev Walkine0b56e02005-02-25 12:10:27 +00001252 OUT("%s%s_t",
Lev Walkinc8285712005-03-04 22:18:20 +00001253 (expr->marker.flags & EM_INDIRECT)?"*":" ",
Lev Walkina00d6b32006-03-21 03:40:38 +00001254 MKID(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +00001255 }
1256
Lev Walkine0b56e02005-02-25 12:10:27 +00001257 if((expr->expr_type == ASN_BASIC_ENUMERATED)
Lev Walkin8ecf9db2005-03-03 21:28:12 +00001258 || (0 /* -- prohibited by X.693:8.3.4 */
1259 && expr->expr_type == ASN_BASIC_INTEGER
Lev Walkin8bb57a22007-12-03 13:41:36 +00001260 && expr_elements_count(arg, expr))
1261 || (expr->expr_type == ASN_BASIC_INTEGER
1262 && asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN)
1263 )
Lev Walkine0b56e02005-02-25 12:10:27 +00001264 etd_spec = ETD_HAS_SPECIFICS;
1265 else
1266 etd_spec = ETD_NO_SPECIFICS;
Lev Walkinf15320b2004-06-03 03:38:44 +00001267
Lev Walkin8de2ab22004-09-26 13:11:31 +00001268 /*
1269 * If this type just blindly refers the other type, alias it.
1270 * Type1 ::= Type2
1271 */
Lev Walkine0b56e02005-02-25 12:10:27 +00001272 if(arg->embed && etd_spec == ETD_NO_SPECIFICS) {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001273 REDIR(saved_target);
Lev Walkine0b56e02005-02-25 12:10:27 +00001274 return 0;
1275 }
Lev Walkin8de2ab22004-09-26 13:11:31 +00001276 if((!expr->constraints || (arg->flags & A1C_NO_CONSTRAINTS))
Lev Walkine0b56e02005-02-25 12:10:27 +00001277 && (arg->embed || expr->tag.tag_class == TC_NOCLASS)
Lev Walkin6938d042005-03-04 23:23:50 +00001278 && etd_spec == ETD_NO_SPECIFICS
1279 && 0 /* This shortcut is incompatible with XER */
1280 ) {
Lev Walkin8de2ab22004-09-26 13:11:31 +00001281 char *type_name;
1282 REDIR(OT_FUNC_DECLS);
1283 type_name = asn1c_type_name(arg, expr, TNF_SAFE);
1284 OUT("/* This type is equivalent to %s */\n", type_name);
Lev Walkin8de2ab22004-09-26 13:11:31 +00001285 if(HIDE_INNER_DEFS) OUT("/* ");
Lev Walkina00d6b32006-03-21 03:40:38 +00001286 OUT("#define\tasn_DEF_%s\t", MKID(expr));
Lev Walkin8de2ab22004-09-26 13:11:31 +00001287 type_name = asn1c_type_name(arg, expr, TNF_SAFE);
Lev Walkine0b56e02005-02-25 12:10:27 +00001288 OUT("asn_DEF_%s", type_name);
Lev Walkin8de2ab22004-09-26 13:11:31 +00001289 if(HIDE_INNER_DEFS)
Lev Walkine0b56e02005-02-25 12:10:27 +00001290 OUT("\t// (Use -fall-defs-global to expose) */");
1291 OUT("\n");
Lev Walkin8de2ab22004-09-26 13:11:31 +00001292 REDIR(OT_CODE);
1293 OUT("/* This type is equivalent to %s */\n", type_name);
1294 OUT("\n");
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001295 REDIR(saved_target);
Lev Walkin8de2ab22004-09-26 13:11:31 +00001296 return 0;
1297 }
1298
Lev Walkin59004fa2004-08-20 13:37:01 +00001299 REDIR(OT_CODE);
1300
Lev Walkinf15320b2004-06-03 03:38:44 +00001301 /*
1302 * Constraint checking.
1303 */
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001304 if(!(arg->flags & A1C_NO_CONSTRAINTS) && expr->combined_constraints) {
Lev Walkina00d6b32006-03-21 03:40:38 +00001305 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001306 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkin8de2ab22004-09-26 13:11:31 +00001307 OUT("int\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001308 OUT("%s", p);
1309 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1310 OUT("_constraint(asn_TYPE_descriptor_t *td, const void *sptr,\n");
Lev Walkin8de2ab22004-09-26 13:11:31 +00001311 INDENT(+1);
Lev Walkin1eded352006-07-13 11:19:01 +00001312 OUT("\t\tasn_app_constraint_failed_f *ctfailcb, void *app_key) {");
Lev Walkin8de2ab22004-09-26 13:11:31 +00001313 OUT("\n");
Lev Walkin725883b2006-10-09 12:07:58 +00001314 DEBUG("expr constraint checking code for %s", p);
Lev Walkin8de2ab22004-09-26 13:11:31 +00001315 if(asn1c_emit_constraint_checking_code(arg) == 1) {
1316 OUT("/* Replace with underlying type checker */\n");
1317 OUT("td->check_constraints "
Lev Walkin05363a72004-09-29 13:16:40 +00001318 "= asn_DEF_%s.check_constraints;\n",
Lev Walkin8de2ab22004-09-26 13:11:31 +00001319 asn1c_type_name(arg, expr, TNF_SAFE));
1320 OUT("return td->check_constraints"
Lev Walkin1eded352006-07-13 11:19:01 +00001321 "(td, sptr, ctfailcb, app_key);\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +00001322 }
Lev Walkin8de2ab22004-09-26 13:11:31 +00001323 INDENT(-1);
1324 OUT("}\n");
1325 OUT("\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001326 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001327
Lev Walkin725883b2006-10-09 12:07:58 +00001328 REDIR(OT_STAT_DEFS);
1329
1330 /*
1331 * Print out asn_DEF_<type>_[all_]tags[] vectors.
1332 */
1333 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
1334 DEBUG("emit tag vectors for %s %d, %d, %d", expr->Identifier,
1335 tv_mode, tags_count, all_tags_count);
1336
1337 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count,
1338 0, etd_spec);
1339
1340 REDIR(OT_CODE);
1341
Lev Walkinf15320b2004-06-03 03:38:44 +00001342 /*
1343 * Emit suicidal functions.
1344 */
1345
Lev Walkinf15320b2004-06-03 03:38:44 +00001346 /*
1347 * This function replaces certain fields from the definition
1348 * of a type with the corresponding fields from the basic type
1349 * (from which the current type is inherited).
1350 */
Lev Walkinf15320b2004-06-03 03:38:44 +00001351 OUT("/*\n");
Lev Walkin59004fa2004-08-20 13:37:01 +00001352 OUT(" * This type is implemented using %s,\n",
1353 asn1c_type_name(arg, expr, TNF_SAFE));
Lev Walkinb65b3002004-09-23 22:20:47 +00001354 OUT(" * so here we adjust the DEF accordingly.\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001355 OUT(" */\n");
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001356
1357#if 0 /* remove unnecessary functions */
Lev Walkinf15320b2004-06-03 03:38:44 +00001358 OUT("static void\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001359 OUT("%s_%d_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00001360 MKID(expr), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +00001361 INDENT(+1);
Lev Walkine0b56e02005-02-25 12:10:27 +00001362 {
Lev Walkina9cc46e2004-09-22 16:06:28 +00001363 asn1p_expr_t *terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
Lev Walkin59004fa2004-08-20 13:37:01 +00001364 char *type_name = asn1c_type_name(arg, expr, TNF_SAFE);
Lev Walkin05363a72004-09-29 13:16:40 +00001365 OUT("td->free_struct = asn_DEF_%s.free_struct;\n", type_name);
1366 OUT("td->print_struct = asn_DEF_%s.print_struct;\n", type_name);
Lev Walkin6169b8d2013-12-07 11:02:44 -08001367 OUT("td->check_constraints = asn_DEF_%s.check_constraints;\n", type_name);
Lev Walkin05363a72004-09-29 13:16:40 +00001368 OUT("td->ber_decoder = asn_DEF_%s.ber_decoder;\n", type_name);
1369 OUT("td->der_encoder = asn_DEF_%s.der_encoder;\n", type_name);
1370 OUT("td->xer_decoder = asn_DEF_%s.xer_decoder;\n", type_name);
1371 OUT("td->xer_encoder = asn_DEF_%s.xer_encoder;\n", type_name);
Lev Walkin59b176e2005-11-26 11:25:14 +00001372 OUT("td->uper_decoder = asn_DEF_%s.uper_decoder;\n", type_name);
Lev Walkin1dc85292006-08-18 01:32:26 +00001373 OUT("td->uper_encoder = asn_DEF_%s.uper_encoder;\n", type_name);
Lev Walkinba68c912017-07-06 07:52:39 -07001374 OUT("td->oer_decoder = asn_DEF_%s.oer_decoder;\n", type_name);
1375 OUT("td->oer_encoder = asn_DEF_%s.oer_encoder;\n", type_name);
Lev Walkin906654e2004-09-10 15:49:15 +00001376 if(!terminal && !tags_count) {
Lev Walkin188ed2c2004-09-13 08:31:01 +00001377 OUT("/* The next four lines are here because of -fknown-extern-type */\n");
Lev Walkin05363a72004-09-29 13:16:40 +00001378 OUT("td->tags = asn_DEF_%s.tags;\n", type_name);
1379 OUT("td->tags_count = asn_DEF_%s.tags_count;\n", type_name);
1380 OUT("td->all_tags = asn_DEF_%s.all_tags;\n", type_name);
1381 OUT("td->all_tags_count = asn_DEF_%s.all_tags_count;\n",type_name);
Lev Walkin906654e2004-09-10 15:49:15 +00001382 OUT("/* End of these lines */\n");
1383 }
Lev Walkinb33425f2017-07-14 14:59:52 +04001384 OUT("if(!td->oer_constraints)\n");
1385 OUT("\ttd->oer_constraints = asn_DEF_%s.oer_constraints;\n",
1386 type_name);
Lev Walkin59b176e2005-11-26 11:25:14 +00001387 OUT("if(!td->per_constraints)\n");
1388 OUT("\ttd->per_constraints = asn_DEF_%s.per_constraints;\n",
1389 type_name);
Lev Walkin05363a72004-09-29 13:16:40 +00001390 OUT("td->elements = asn_DEF_%s.elements;\n", type_name);
1391 OUT("td->elements_count = asn_DEF_%s.elements_count;\n", type_name);
Lev Walkine0b56e02005-02-25 12:10:27 +00001392 if(etd_spec != ETD_NO_SPECIFICS) {
1393 INDENT(-1);
Lev Walkin7ef83a42005-03-29 19:04:24 +00001394 OUT(" /* ");
Lev Walkin59004fa2004-08-20 13:37:01 +00001395 }
Lev Walkine0b56e02005-02-25 12:10:27 +00001396 OUT("td->specifics = asn_DEF_%s.specifics;", type_name);
1397 if(etd_spec == ETD_NO_SPECIFICS) {
1398 INDENT(-1);
1399 OUT("\n");
1400 } else {
1401 OUT("\t// Defined explicitly */\n");
1402 }
1403 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001404 OUT("}\n");
1405 OUT("\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001406
Lev Walkina00d6b32006-03-21 03:40:38 +00001407 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001408 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001409 OUT("void\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001410 OUT("%s", p);
1411 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1412 OUT("_free(asn_TYPE_descriptor_t *td,\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001413 INDENTED(
Lev Walkina9cc46e2004-09-22 16:06:28 +00001414 OUT("\tvoid *struct_ptr, int contents_only) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001415 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1416 p, expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +00001417 OUT("td->free_struct(td, struct_ptr, contents_only);\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001418 );
1419 OUT("}\n");
1420 OUT("\n");
1421
Lev Walkina00d6b32006-03-21 03:40:38 +00001422 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001423 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkinf15320b2004-06-03 03:38:44 +00001424 OUT("int\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001425 OUT("%s", p);
1426 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1427 OUT("_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001428 INDENTED(
1429 OUT("\tint ilevel, asn_app_consume_bytes_f *cb, void *app_key) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001430 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1431 p, expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +00001432 OUT("return td->print_struct(td, struct_ptr, ilevel, cb, app_key);\n");
1433 );
1434 OUT("}\n");
1435 OUT("\n");
1436
Lev Walkina00d6b32006-03-21 03:40:38 +00001437 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001438 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkindc06f6b2004-10-20 15:50:55 +00001439 OUT("asn_dec_rval_t\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001440 OUT("%s", p);
1441 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1442 OUT("_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001443 INDENTED(
Lev Walkindd1512e2005-03-17 21:56:00 +00001444 OUT("\tvoid **structure, const void *bufptr, size_t size, int tag_mode) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001445 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1446 p, expr->_type_unique_index);
Lev Walkin05363a72004-09-29 13:16:40 +00001447 OUT("return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);\n");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001448 );
1449 OUT("}\n");
1450 OUT("\n");
1451
Lev Walkina00d6b32006-03-21 03:40:38 +00001452 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001453 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001454 OUT("asn_enc_rval_t\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001455 OUT("%s", p);
1456 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1457 OUT("_encode_der(asn_TYPE_descriptor_t *td,\n");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001458 INDENTED(
1459 OUT("\tvoid *structure, int tag_mode, ber_tlv_tag_t tag,\n");
1460 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001461 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1462 p, expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +00001463 OUT("return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);\n");
1464 );
1465 OUT("}\n");
1466 OUT("\n");
1467
Lev Walkina00d6b32006-03-21 03:40:38 +00001468 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001469 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkinca47c292004-10-23 13:34:00 +00001470 OUT("asn_dec_rval_t\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001471 OUT("%s", p);
1472 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1473 OUT("_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n");
Lev Walkinca47c292004-10-23 13:34:00 +00001474 INDENTED(
Lev Walkindd1512e2005-03-17 21:56:00 +00001475 OUT("\tvoid **structure, const char *opt_mname, const void *bufptr, size_t size) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001476 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1477 p, expr->_type_unique_index);
Lev Walkinca47c292004-10-23 13:34:00 +00001478 OUT("return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size);\n");
1479 );
1480 OUT("}\n");
1481 OUT("\n");
1482
Lev Walkina00d6b32006-03-21 03:40:38 +00001483 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001484 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001485 OUT("asn_enc_rval_t\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001486 OUT("%s", p);
1487 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1488 OUT("_encode_xer(asn_TYPE_descriptor_t *td, void *structure,\n");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001489 INDENTED(
1490 OUT("\tint ilevel, enum xer_encoder_flags_e flags,\n");
1491 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001492 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1493 p, expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +00001494 OUT("return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001495 );
1496 OUT("}\n");
1497 OUT("\n");
1498
Lev Walkinb33425f2017-07-14 14:59:52 +04001499 if(arg->flags & A1C_GEN_OER) {
1500 p = MKID(expr);
1501
1502 if(HIDE_INNER_DEFS) OUT("static ");
1503 OUT("asn_dec_rval_t\n");
1504 OUT("%s", p);
1505 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1506 OUT("_decode_oer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n");
1507 INDENTED(
1508 OUT("\tasn_oer_constraints_t *constraints, void **structure, const void *buffer, size_t size) {\n");
1509 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1510 p, expr->_type_unique_index);
1511 OUT("return td->oer_decoder(opt_codec_ctx, td, constraints, structure, buffer, size);\n");
1512 );
1513 OUT("}\n");
1514 OUT("\n");
1515
1516 p = MKID(expr);
1517 if(HIDE_INNER_DEFS) OUT("static ");
1518 OUT("asn_enc_rval_t\n");
1519 OUT("%s", p);
1520 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1521 OUT("_encode_oer(asn_TYPE_descriptor_t *td,\n");
1522 INDENTED(
1523 OUT("\tasn_oer_constraints_t *constraints,\n");
1524 OUT("\tvoid *structure, asn_app_consume_bytes_f *cb, void *app_key) {\n");
1525 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1526 p, expr->_type_unique_index);
1527 OUT("return td->uper_encoder(td, constraints, structure, cb, app_key);\n");
1528 );
1529 OUT("}\n");
1530 OUT("\n");
1531 }
1532
Lev Walkin59b176e2005-11-26 11:25:14 +00001533 if(arg->flags & A1C_GEN_PER) {
Lev Walkina00d6b32006-03-21 03:40:38 +00001534 p = MKID(expr);
Lev Walkin1dc85292006-08-18 01:32:26 +00001535
Lev Walkin59b176e2005-11-26 11:25:14 +00001536 if(HIDE_INNER_DEFS) OUT("static ");
1537 OUT("asn_dec_rval_t\n");
1538 OUT("%s", p);
1539 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1540 OUT("_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n");
1541 INDENTED(
1542 OUT("\tasn_per_constraints_t *constraints, void **structure, asn_per_data_t *per_data) {\n");
1543 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1544 p, expr->_type_unique_index);
1545 OUT("return td->uper_decoder(opt_codec_ctx, td, constraints, structure, per_data);\n");
1546 );
1547 OUT("}\n");
1548 OUT("\n");
Lev Walkin1dc85292006-08-18 01:32:26 +00001549
1550 p = MKID(expr);
1551 if(HIDE_INNER_DEFS) OUT("static ");
1552 OUT("asn_enc_rval_t\n");
1553 OUT("%s", p);
1554 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1555 OUT("_encode_uper(asn_TYPE_descriptor_t *td,\n");
1556 INDENTED(
1557 OUT("\tasn_per_constraints_t *constraints,\n");
1558 OUT("\tvoid *structure, asn_per_outp_t *per_out) {\n");
1559 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1560 p, expr->_type_unique_index);
1561 OUT("return td->uper_encoder(td, constraints, structure, per_out);\n");
1562 );
1563 OUT("}\n");
1564 OUT("\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00001565 }
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001566#endif
Lev Walkinf15320b2004-06-03 03:38:44 +00001567 REDIR(OT_FUNC_DECLS);
1568
Lev Walkina00d6b32006-03-21 03:40:38 +00001569 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001570 if(HIDE_INNER_DEFS) {
Lev Walkin21d00002005-03-04 08:48:53 +00001571 OUT("/* extern asn_TYPE_descriptor_t asn_DEF_%s_%d;"
1572 "\t// (Use -fall-defs-global to expose) */\n",
1573 p, expr->_type_unique_index);
Lev Walkine0b56e02005-02-25 12:10:27 +00001574 } else {
1575 OUT("extern asn_TYPE_descriptor_t asn_DEF_%s;\n", p);
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001576 if (etd_spec == ETD_HAS_SPECIFICS) {
1577 if((expr->expr_type == ASN_BASIC_ENUMERATED) ||
1578 (expr->expr_type == ASN_BASIC_INTEGER)) {
1579 if(expr->_type_referenced) {
1580 OUT("extern asn_INTEGER_specifics_t "
1581 "asn_SPC_%s_specs_%d;\n", p, expr->_type_unique_index);
1582 }
1583 } else {
1584 asn1p_expr_t *terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
1585
1586 OUT("extern asn_%s_specifics_t ", asn1c_type_name(arg, terminal, TNF_SAFE));
1587 OUT("asn_SPC_%s_specs_%d;\n", MKID(expr), expr->_type_unique_index);
1588 }
1589 }
Lev Walkine0b56e02005-02-25 12:10:27 +00001590 OUT("asn_struct_free_f %s_free;\n", p);
1591 OUT("asn_struct_print_f %s_print;\n", p);
1592 OUT("asn_constr_check_f %s_constraint;\n", p);
1593 OUT("ber_type_decoder_f %s_decode_ber;\n", p);
1594 OUT("der_type_encoder_f %s_encode_der;\n", p);
1595 OUT("xer_type_decoder_f %s_decode_xer;\n", p);
1596 OUT("xer_type_encoder_f %s_encode_xer;\n", p);
Lev Walkinb33425f2017-07-14 14:59:52 +04001597 if(arg->flags & A1C_GEN_OER) {
1598 OUT("oer_type_decoder_f %s_decode_oer;\n", p);
1599 OUT("oer_type_encoder_f %s_encode_oer;\n", p);
1600 }
Lev Walkin1dc85292006-08-18 01:32:26 +00001601 if(arg->flags & A1C_GEN_PER) {
Lev Walkin59b176e2005-11-26 11:25:14 +00001602 OUT("per_type_decoder_f %s_decode_uper;\n", p);
Lev Walkin1dc85292006-08-18 01:32:26 +00001603 OUT("per_type_encoder_f %s_encode_uper;\n", p);
1604 }
Lev Walkine0b56e02005-02-25 12:10:27 +00001605 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001606
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001607 REDIR(saved_target);
Lev Walkin3dcaafa2004-08-11 05:21:32 +00001608
Lev Walkinf15320b2004-06-03 03:38:44 +00001609 return 0;
1610}
1611
1612int
1613asn1c_lang_C_type_EXTENSIBLE(arg_t *arg) {
1614
1615 OUT("/*\n");
1616 OUT(" * This type is extensible,\n");
1617 OUT(" * possible extensions are below.\n");
1618 OUT(" */\n");
1619
1620 return 0;
1621}
1622
Lev Walkin59b176e2005-11-26 11:25:14 +00001623static int
1624compute_extensions_start(asn1p_expr_t *expr) {
Lev Walkin35631482004-07-01 00:52:50 +00001625 asn1p_expr_t *v;
Lev Walkin59b176e2005-11-26 11:25:14 +00001626 int eidx = 0;
Lev Walkin35631482004-07-01 00:52:50 +00001627 TQ_FOR(v, &(expr->members), next) {
Lev Walkin59b176e2005-11-26 11:25:14 +00001628 if(v->expr_type == A1TC_EXTENSIBLE)
1629 return eidx;
1630 eidx++;
Lev Walkin35631482004-07-01 00:52:50 +00001631 }
Lev Walkin59b176e2005-11-26 11:25:14 +00001632 return -1;
Lev Walkin35631482004-07-01 00:52:50 +00001633}
1634
Lev Walkinf15320b2004-06-03 03:38:44 +00001635static int
Lev Walkinc3e29402004-09-10 06:07:18 +00001636_print_tag(arg_t *arg, struct asn1p_type_tag_s *tag) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001637
1638 OUT("(");
Lev Walkinc3e29402004-09-10 06:07:18 +00001639 switch(tag->tag_class) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001640 case TC_UNIVERSAL: OUT("ASN_TAG_CLASS_UNIVERSAL"); break;
1641 case TC_APPLICATION: OUT("ASN_TAG_CLASS_APPLICATION"); break;
1642 case TC_CONTEXT_SPECIFIC: OUT("ASN_TAG_CLASS_CONTEXT"); break;
1643 case TC_PRIVATE: OUT("ASN_TAG_CLASS_PRIVATE"); break;
1644 case TC_NOCLASS:
1645 break;
1646 }
Lev Walkinda997b12017-08-04 01:38:41 -07001647 OUT(" | (%s << 2))", asn1p_itoa(tag->tag_value));
Lev Walkinf15320b2004-06-03 03:38:44 +00001648
1649 return 0;
1650}
1651
Lev Walkinfd171ef2004-06-06 07:20:17 +00001652
1653static int
1654_tag2el_cmp(const void *ap, const void *bp) {
1655 const tag2el_t *a = ap;
1656 const tag2el_t *b = bp;
1657 const struct asn1p_type_tag_s *ta = &a->el_tag;
1658 const struct asn1p_type_tag_s *tb = &b->el_tag;
1659
1660 if(ta->tag_class == tb->tag_class) {
1661 if(ta->tag_value == tb->tag_value) {
1662 /*
1663 * Sort by their respective positions.
1664 */
1665 if(a->el_no < b->el_no)
1666 return -1;
1667 else if(a->el_no > b->el_no)
1668 return 1;
1669 return 0;
1670 } else if(ta->tag_value < tb->tag_value)
1671 return -1;
1672 else
1673 return 1;
1674 } else if(ta->tag_class < tb->tag_class) {
1675 return -1;
1676 } else {
1677 return 1;
1678 }
1679}
1680
Lev Walkinf15320b2004-06-03 03:38:44 +00001681/*
1682 * For constructed types, number of external tags may be greater than
1683 * number of elements in the type because of CHOICE type.
1684 * T ::= SET { -- Three possible tags:
1685 * a INTEGER, -- One tag is here...
1686 * b Choice1 -- ... and two more tags are there.
1687 * }
1688 * Choice1 ::= CHOICE {
1689 * s1 IA5String,
1690 * s2 ObjectDescriptor
1691 * }
1692 */
1693static int
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001694_fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001695 asn1p_expr_t *expr = arg->expr;
1696 arg_t tmparg = *arg;
1697 asn1p_expr_t *v;
1698 int element = 0;
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001699 int original_count = *count;
1700 int sort_until = -1;
Lev Walkinf15320b2004-06-03 03:38:44 +00001701
1702 TQ_FOR(v, &(expr->members), next) {
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001703 if(v->expr_type == A1TC_EXTENSIBLE) {
1704 /*
Lev Walkine0b56e02005-02-25 12:10:27 +00001705 * CXER mandates sorting
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001706 * only for the root part.
1707 */
1708 if(flags == FTE_CANONICAL_XER
1709 && sort_until == -1)
1710 sort_until = *count;
Lev Walkinf15320b2004-06-03 03:38:44 +00001711 continue;
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001712 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001713
1714 tmparg.expr = v;
1715
1716 if(_add_tag2el_member(&tmparg, tag2el, count,
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001717 (el_no==-1)?element:el_no, flags)) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001718 return -1;
1719 }
1720
1721 element++;
1722 }
1723
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001724
1725 if(flags == FTE_CANONICAL_XER) {
1726 if(sort_until == -1) sort_until = *count;
1727 qsort((*tag2el) + original_count,
1728 sort_until - original_count,
1729 sizeof(**tag2el), _tag2el_cmp);
1730 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1731 && (sort_until - original_count) >= 1) {
1732 /* Only take in account the root component */
1733 *count = original_count + 1;
1734 }
1735 } else {
1736 /*
1737 * Sort the map according to canonical order of their
1738 * tags and element numbers.
1739 */
1740 qsort(*tag2el, *count, sizeof(**tag2el), _tag2el_cmp);
1741 }
Lev Walkinfd171ef2004-06-06 07:20:17 +00001742
Lev Walkin38abe792004-06-14 13:09:45 +00001743 /*
1744 * Initialize .toff_{first|last} members.
1745 */
1746 if(*count) {
1747 struct asn1p_type_tag_s *cur_tag = 0;
1748 tag2el_t *cur = *tag2el;
1749 tag2el_t *end = cur + *count;
1750 int occur, i;
1751 for(occur = 0; cur < end; cur++) {
1752 if(cur_tag == 0
1753 || cur_tag->tag_value != cur->el_tag.tag_value
1754 || cur_tag->tag_class != cur->el_tag.tag_class) {
1755 cur_tag = &cur->el_tag;
1756 occur = 0;
1757 } else {
1758 occur++;
1759 }
1760 cur->toff_first = -occur;
1761 for(i = 0; i >= -occur; i--)
1762 cur[i].toff_last = -i;
1763 }
1764 }
1765
Lev Walkinf15320b2004-06-03 03:38:44 +00001766 return 0;
1767}
1768
1769static int
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001770_add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001771 struct asn1p_type_tag_s tag;
1772 int ret;
1773
1774 assert(el_no >= 0);
1775
Lev Walkina9cc46e2004-09-22 16:06:28 +00001776 ret = asn1f_fetch_outmost_tag(arg->asn, arg->expr->module,
Lev Walkin59b176e2005-11-26 11:25:14 +00001777 arg->expr, &tag, AFT_IMAGINARY_ANY);
Lev Walkinf15320b2004-06-03 03:38:44 +00001778 if(ret == 0) {
Lev Walkin201943e2004-09-04 04:42:29 +00001779 tag2el_t *te;
1780 int new_count = (*count) + 1;
Lev Walkinf15320b2004-06-03 03:38:44 +00001781 void *p;
Lev Walkin201943e2004-09-04 04:42:29 +00001782
Lev Walkinac7e2292004-09-05 10:42:33 +00001783 if(tag.tag_value == -1) {
1784 /*
1785 * This is an untagged ANY type,
1786 * proceed without adding a tag
1787 */
1788 return 0;
1789 }
1790
Lev Walkin201943e2004-09-04 04:42:29 +00001791 p = realloc(*tag2el, new_count * sizeof(tag2el_t));
Lev Walkinf15320b2004-06-03 03:38:44 +00001792 if(p) *tag2el = p;
1793 else return -1;
1794
Lev Walkin725883b2006-10-09 12:07:58 +00001795 if(0) DEBUG("Found tag for %s: %ld",
Lev Walkinf15320b2004-06-03 03:38:44 +00001796 arg->expr->Identifier,
1797 (long)tag.tag_value);
1798
Lev Walkin201943e2004-09-04 04:42:29 +00001799 te = &((*tag2el)[*count]);
1800 te->el_tag = tag;
1801 te->el_no = el_no;
1802 te->from_expr = arg->expr;
1803 *count = new_count;
Lev Walkinf15320b2004-06-03 03:38:44 +00001804 return 0;
1805 }
1806
1807 DEBUG("Searching tag in complex expression %s:%x at line %d",
1808 arg->expr->Identifier,
1809 arg->expr->expr_type,
1810 arg->expr->_lineno);
1811
1812 /*
1813 * Iterate over members of CHOICE type.
1814 */
1815 if(arg->expr->expr_type == ASN_CONSTR_CHOICE) {
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001816 return _fill_tag2el_map(arg, tag2el, count, el_no, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +00001817 }
1818
1819 if(arg->expr->expr_type == A1TC_REFERENCE) {
1820 arg_t tmp = *arg;
1821 asn1p_expr_t *expr;
Lev Walkinb85a8132005-08-18 13:38:19 +00001822 expr = asn1f_lookup_symbol_ex(tmp.asn, tmp.expr,
Lev Walkinf15320b2004-06-03 03:38:44 +00001823 arg->expr->reference);
1824 if(expr) {
1825 tmp.expr = expr;
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001826 return _add_tag2el_member(&tmp, tag2el, count, el_no, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +00001827 } else {
1828 FATAL("Cannot dereference %s at line %d",
1829 arg->expr->Identifier,
1830 arg->expr->_lineno);
1831 return -1;
1832 }
1833 }
1834
1835 DEBUG("No tag for %s at line %d",
1836 arg->expr->Identifier,
1837 arg->expr->_lineno);
1838
1839 return -1;
1840}
1841
1842static int
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001843emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier) {
Lev Walkinfd171ef2004-06-06 07:20:17 +00001844 asn1p_expr_t *expr = arg->expr;
Lev Walkinf3b29b12005-06-02 05:21:37 +00001845 int i;
1846
1847 if(!tag2el_count) return 0; /* No top level tags */
Lev Walkinfd171ef2004-06-06 07:20:17 +00001848
Wim Lewisfb6344e2014-07-28 12:16:01 -07001849 OUT("static const asn_TYPE_tag2member_t asn_MAP_%s_tag2el%s_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00001850 MKID(expr), opt_modifier?opt_modifier:"",
Lev Walkin59b176e2005-11-26 11:25:14 +00001851 expr->_type_unique_index);
Lev Walkinf3b29b12005-06-02 05:21:37 +00001852 for(i = 0; i < tag2el_count; i++) {
1853 OUT(" { ");
1854 _print_tag(arg, &tag2el[i].el_tag);
1855 OUT(", ");
1856 OUT("%d, ", tag2el[i].el_no);
1857 OUT("%d, ", tag2el[i].toff_first);
1858 OUT("%d ", tag2el[i].toff_last);
Lev Walkin4062b012013-10-11 14:29:38 -07001859 OUT("}%s /* %s",
Lev Walkinf3b29b12005-06-02 05:21:37 +00001860 (i + 1 < tag2el_count) ? "," : "",
Lev Walkin4062b012013-10-11 14:29:38 -07001861 tag2el[i].from_expr->Identifier);
1862 if(arg->flags & A1C_LINE_REFS)
1863 OUT("at %d", tag2el[i].from_expr->_lineno);
1864 OUT(" */\n");
Lev Walkinfd171ef2004-06-06 07:20:17 +00001865 }
1866 OUT("};\n");
1867
Lev Walkinf3b29b12005-06-02 05:21:37 +00001868 return 0;
Lev Walkinfd171ef2004-06-06 07:20:17 +00001869}
1870
Lev Walkin188ed2c2004-09-13 08:31:01 +00001871static enum tvm_compat
1872emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tags_count_r, int *all_tags_count_r) {
1873 struct asn1p_type_tag_s *tags = 0; /* Effective tags */
1874 struct asn1p_type_tag_s *all_tags = 0; /* The full array */
Lev Walkin64399722004-08-11 07:17:22 +00001875 int tags_count = 0;
Lev Walkin188ed2c2004-09-13 08:31:01 +00001876 int all_tags_count = 0;
1877 enum tvm_compat tv_mode = _TVM_SAME;
Lev Walkin906654e2004-09-10 15:49:15 +00001878 int i;
Lev Walkin27ea3802004-06-28 21:13:46 +00001879
Lev Walkin6d1220a2004-09-14 14:10:10 +00001880 /* Cleanup before proceeding. */
1881 *tags_count_r = 0;
1882 *all_tags_count_r = 0;
1883
Lev Walkin906654e2004-09-10 15:49:15 +00001884 /* Fetch a chain of tags */
Lev Walkina9cc46e2004-09-22 16:06:28 +00001885 tags_count = asn1f_fetch_tags(arg->asn, expr->module, expr, &tags, 0);
Lev Walkin725883b2006-10-09 12:07:58 +00001886 if(tags_count < 0) {
1887 DEBUG("fail to fetch tags for %s", expr->Identifier);
Lev Walkin6d1220a2004-09-14 14:10:10 +00001888 return -1;
Lev Walkin725883b2006-10-09 12:07:58 +00001889 }
Lev Walkin64399722004-08-11 07:17:22 +00001890
Lev Walkin188ed2c2004-09-13 08:31:01 +00001891 /* Fetch a chain of tags */
Lev Walkina9cc46e2004-09-22 16:06:28 +00001892 all_tags_count = asn1f_fetch_tags(arg->asn, expr->module, expr,
Lev Walkin188ed2c2004-09-13 08:31:01 +00001893 &all_tags, AFT_FULL_COLLECT);
1894 if(all_tags_count < 0) {
Lev Walkind8b83642016-03-14 02:00:27 -07001895 free(tags);
Lev Walkin725883b2006-10-09 12:07:58 +00001896 DEBUG("fail to fetch tags chain for %s", expr->Identifier);
Lev Walkin188ed2c2004-09-13 08:31:01 +00001897 return -1;
Lev Walkin5a8219a2004-09-08 00:28:57 +00001898 }
Lev Walkin906654e2004-09-10 15:49:15 +00001899
Lev Walkin188ed2c2004-09-13 08:31:01 +00001900 assert(tags_count <= all_tags_count);
1901 assert((tags_count?0:1) == (all_tags_count?0:1));
Lev Walkin27ea3802004-06-28 21:13:46 +00001902
Lev Walkin188ed2c2004-09-13 08:31:01 +00001903 if(tags_count <= all_tags_count) {
1904 for(i = 0; i < tags_count; i++) {
1905 if(tags[i].tag_value != all_tags[i].tag_value
1906 || tags[i].tag_class != all_tags[i].tag_class) {
1907 tv_mode = _TVM_DIFFERENT;
1908 break;
1909 }
1910 }
1911 if(i == tags_count && tags_count < all_tags_count)
1912 tv_mode = _TVM_SUBSET;
1913 } else {
1914 tv_mode = _TVM_DIFFERENT;
1915 }
1916
1917#define EMIT_TAGS_TABLE(name, tags, tags_count) do { \
Wim Lewisfb6344e2014-07-28 12:16:01 -07001918 OUT("static const ber_tlv_tag_t asn_DEF_%s%s_tags_%d[] = {\n",\
Lev Walkina00d6b32006-03-21 03:40:38 +00001919 MKID(expr), name, \
Lev Walkin59b176e2005-11-26 11:25:14 +00001920 expr->_type_unique_index); \
Lev Walkin188ed2c2004-09-13 08:31:01 +00001921 INDENT(+1); \
1922 /* Print the array of collected tags */ \
1923 for(i = 0; i < tags_count; i++) { \
1924 if(i) OUT(",\n"); \
1925 _print_tag(arg, &tags[i]); \
1926 } \
1927 OUT("\n"); \
1928 INDENT(-1); \
1929 OUT("};\n"); \
1930 } while(0)
1931
1932 if(tags_count) {
1933 if(tv_mode == _TVM_SUBSET)
1934 EMIT_TAGS_TABLE("", all_tags, all_tags_count);
1935 else
1936 EMIT_TAGS_TABLE("", tags, tags_count);
1937 }
1938
1939 if(all_tags_count) {
1940 if(tv_mode == _TVM_DIFFERENT)
1941 EMIT_TAGS_TABLE("_all", all_tags, all_tags_count);
1942 }
1943
Lev Walkind8b83642016-03-14 02:00:27 -07001944 free(tags);
1945 free(all_tags);
Lev Walkin188ed2c2004-09-13 08:31:01 +00001946
1947 *tags_count_r = tags_count;
1948 *all_tags_count_r = all_tags_count;
1949
1950 return tv_mode;
Lev Walkin27ea3802004-06-28 21:13:46 +00001951}
Lev Walkin59004fa2004-08-20 13:37:01 +00001952
1953static int
Lev Walkin59964be2004-08-25 02:03:12 +00001954expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin59004fa2004-08-20 13:37:01 +00001955 asn1p_expr_t *topmost_parent;
1956 asn1p_expr_t *v;
1957 int elements = 0;
1958
Lev Walkina9cc46e2004-09-22 16:06:28 +00001959 topmost_parent = asn1f_find_terminal_type_ex(arg->asn, expr);
Lev Walkin59004fa2004-08-20 13:37:01 +00001960 if(!topmost_parent) return 0;
1961
Lev Walkine0b56e02005-02-25 12:10:27 +00001962 if(!(topmost_parent->expr_type & ASN_CONSTR_MASK)
Lev Walkin1b3a1352016-01-10 13:15:02 -08001963 && !(topmost_parent->expr_type == ASN_BASIC_INTEGER)
Lev Walkin0f262452016-01-10 13:33:08 -08001964 && !(topmost_parent->expr_type == ASN_BASIC_ENUMERATED)
1965 && !(topmost_parent->expr_type == ASN_BASIC_BIT_STRING))
Lev Walkin59004fa2004-08-20 13:37:01 +00001966 return 0;
1967
1968 TQ_FOR(v, &(topmost_parent->members), next) {
1969 if(v->expr_type != A1TC_EXTENSIBLE)
1970 elements++;
1971 }
1972
1973 return elements;
1974}
1975
Lev Walkin59b176e2005-11-26 11:25:14 +00001976static asn1p_expr_type_e
1977expr_get_type(arg_t *arg, asn1p_expr_t *expr) {
1978 asn1p_expr_t *terminal;
1979 terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
1980 if(terminal) return terminal->expr_type;
1981 return A1TC_INVALID;
1982}
1983
Lev Walkin725883b2006-10-09 12:07:58 +00001984static asn1c_integer_t
1985PER_FROM_alphabet_characters(asn1cnst_range_t *range) {
1986 asn1c_integer_t numchars = 0;
1987 if(range->el_count) {
1988 int i;
1989 for(i = 0; i < range->el_count; i++)
1990 numchars
1991 += PER_FROM_alphabet_characters(range->elements[i]);
1992 } else {
1993 assert(range->left.type == ARE_VALUE);
1994 assert(range->right.type == ARE_VALUE);
1995 numchars = 1 + (range->right.value - range->left.value);
1996 }
1997 return numchars;
1998}
1999
Lev Walkin4118ccf2017-08-02 10:37:31 -07002000static void
2001emit_single_member_OER_constraint_comment(arg_t *arg, asn1cnst_range_t *range, char *type) {
2002
2003 /*
2004 * Print some courtesy debug information.
2005 */
2006 if(range
2007 && (range->left.type == ARE_VALUE || range->right.type == ARE_VALUE)) {
2008 OUT("\t/* ");
2009 if(type) OUT("(%s", type);
2010 OUT("(");
2011 if(range->left.type == ARE_VALUE)
Lev Walkinda997b12017-08-04 01:38:41 -07002012 OUT("%s", asn1p_itoa(range->left.value));
Lev Walkin4118ccf2017-08-02 10:37:31 -07002013 else
2014 OUT("MIN");
2015 OUT("..");
2016 if(range->right.type == ARE_VALUE)
Lev Walkinda997b12017-08-04 01:38:41 -07002017 OUT("%s", asn1p_itoa(range->right.value));
Lev Walkin4118ccf2017-08-02 10:37:31 -07002018 else
2019 OUT("MAX");
2020 if(range->extensible) OUT(",...");
2021 if(type) OUT(")");
2022 OUT(") */");
2023 }
2024}
2025
2026static int
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002027emit_single_member_OER_constraint_value(arg_t *arg, asn1cnst_range_t *range) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07002028 if(!range) {
2029 /* oer_support.h: asn_oer_constraint_s */
2030 OUT("{ 0, 0 }");
2031 return 0;
2032 }
2033
2034 if(range->incompatible || range->not_OER_visible) {
2035 OUT("{ 0, 0 }");
2036 } else if(range->left.type == ARE_VALUE &&
2037 range->right.type == ARE_VALUE) {
2038 asn1c_integer_t lb = range->left.value;
2039 asn1c_integer_t ub = range->right.value;
2040 unsigned width = 0;
2041 unsigned positive = 0;
2042
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002043
Lev Walkin4118ccf2017-08-02 10:37:31 -07002044 if(lb >= 0) {
2045 /* X.969 08/2015 10.2(a) */
2046 if(ub <= 255) {
2047 width = 1;
2048 } else if(ub <= 65535) {
2049 width = 2;
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002050 } else if((unsigned long long)ub <= 4294967295UL) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07002051 width = 4;
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002052 } else if((unsigned long long)ub <= 18446744073709551615ULL) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07002053 width = 8;
2054 }
2055 positive = 1;
2056 } else {
2057 positive = 0;
2058 /* X.969 08/2015 10.2(b) - no lower bound or negative lower bound */
2059 if(lb >= -128 && ub <= 127) {
2060 width = 1;
2061 } else if(lb >= -32768 && ub <= 32767) {
2062 width = 2;
2063 } else if(lb >= -2147483648L && ub <= 2147483647L) {
2064 width = 4;
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002065 } else if(lb >= (-9223372036854775807LL-1)
Lev Walkin4118ccf2017-08-02 10:37:31 -07002066 && ub <= 9223372036854775807LL) {
2067 width = 8;
2068 }
2069 }
2070 OUT("{ %u, %u }", width, positive);
2071 } else {
2072 OUT("{ 0, 0 }");
2073 }
2074
2075 return 0;
2076}
2077
2078static int
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002079emit_single_member_OER_constraint_size(arg_t *arg, asn1cnst_range_t *range) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07002080 if(!range) {
2081 /* oer_support.h: asn_oer_constraint_s */
2082 OUT("-1");
2083 return 0;
2084 }
2085
2086 if(range->incompatible || range->not_OER_visible) {
2087 OUT("-1");
2088 } else {
2089 if(range->left.type == ARE_VALUE && range->right.type == ARE_VALUE
2090 && range->left.value == range->right.value
2091 && range->left.value >= 0) {
Lev Walkinda997b12017-08-04 01:38:41 -07002092 OUT("%s", asn1p_itoa(range->left.value));
Lev Walkin4118ccf2017-08-02 10:37:31 -07002093 } else {
2094 OUT("-1");
2095 }
2096 }
2097
2098 return 0;
2099}
2100
Lev Walkin59b176e2005-11-26 11:25:14 +00002101static int
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002102emit_single_member_PER_constraint(arg_t *arg, asn1cnst_range_t *range, int alphabetsize, const char *type) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07002103 if(!range || range->incompatible || range->not_PER_visible) {
2104 OUT("{ APC_UNCONSTRAINED,\t-1, -1, 0, 0 }");
Lev Walkin59b176e2005-11-26 11:25:14 +00002105 return 0;
Lev Walkin4118ccf2017-08-02 10:37:31 -07002106 }
Lev Walkin59b176e2005-11-26 11:25:14 +00002107
Lev Walkin4118ccf2017-08-02 10:37:31 -07002108 if(range->left.type == ARE_VALUE) {
Lev Walkin59b176e2005-11-26 11:25:14 +00002109 if(range->right.type == ARE_VALUE) {
2110 asn1c_integer_t cover = 1;
2111 asn1c_integer_t r = 1 + range->right.value
2112 - range->left.value;
Lev Walkinc46b7cb2006-08-18 02:27:55 +00002113 size_t rbits; /* Value range bits */
2114 ssize_t ebits; /* Value effective range bits */
Lev Walkin59b176e2005-11-26 11:25:14 +00002115
2116 if(range->empty_constraint)
2117 r = 0;
2118
Lev Walkin725883b2006-10-09 12:07:58 +00002119 if(alphabetsize) {
2120 /* X.691: 27.5.2 */
2121 r = PER_FROM_alphabet_characters(range);
2122 }
2123
Lev Walkin59b176e2005-11-26 11:25:14 +00002124 /* Compute real constraint */
2125 for(rbits = 0; rbits < (8 * sizeof(r)); rbits++) {
2126 if(r <= cover)
2127 break;
2128 cover *= 2; /* Can't do shifting */
2129 if(cover < 0) {
2130 FATAL("Constraint at line %d too wide "
2131 "for %d-bits integer type",
2132 arg->expr->_lineno,
2133 sizeof(r) * 8);
2134 rbits = sizeof(r);
2135 break;
2136 }
2137 }
2138
Lev Walkin3a4689a2006-11-24 11:20:27 +00002139 if(alphabetsize) {
2140 ebits = rbits;
2141 } else {
Lev Walkin59b176e2005-11-26 11:25:14 +00002142 /* X.691, #10.9.4.1 */
2143 for(ebits = 0; ebits <= 16; ebits++)
2144 if(r <= 1 << ebits) break;
2145 if(ebits == 17
2146 || range->right.value >= 65536)
2147 ebits = -1;
Lev Walkin3a4689a2006-11-24 11:20:27 +00002148 if(0) {
Lev Walkin59b176e2005-11-26 11:25:14 +00002149 /* X.691, #10.5.7.1 */
2150 for(ebits = 0; ebits <= 8; ebits++)
2151 if(r <= 1 << ebits) break;
2152 if(ebits == 9) {
2153 if(r <= 65536)
2154 ebits = 16;
2155 else
2156 ebits = -1;
2157 }
2158 }
Lev Walkin3a4689a2006-11-24 11:20:27 +00002159 }
Lev Walkin725883b2006-10-09 12:07:58 +00002160
Lev Walkin59b176e2005-11-26 11:25:14 +00002161 OUT("{ APC_CONSTRAINED%s,%s% d, % d, ",
2162 range->extensible
2163 ? " | APC_EXTENSIBLE" : "",
2164 range->extensible ? " " : "\t", rbits, ebits);
Lev Walkin3a4689a2006-11-24 11:20:27 +00002165
2166 if(alphabetsize) {
2167 asn1c_integer_t lv = range->left.value;
2168 asn1c_integer_t rv = range->right.value;
2169 int gcmt = 0;
2170 if(lv > 0x7fffffff) { lv = 0x7fffffff; gcmt++; }
2171 if(rv > 0x7fffffff) { rv = 0x7fffffff; gcmt++; }
2172 if(gcmt) {
Lev Walkin63b41262007-11-06 01:48:46 +00002173 OINTS(lv); OUT(", "); OINTS(rv); OUT(" }");
Lev Walkin3a4689a2006-11-24 11:20:27 +00002174 goto pcmt;
2175 }
2176 }
Lev Walkin59b176e2005-11-26 11:25:14 +00002177 } else {
2178 if(range->extensible) {
2179 OUT("{ APC_SEMI_CONSTRAINED | APC_EXTENSIBLE, "
2180 "-1, ");
2181 } else {
2182 OUT("{ APC_SEMI_CONSTRAINED,\t-1, -1, ");
2183 }
2184 }
Lev Walkin63b41262007-11-06 01:48:46 +00002185 OINTS(range->left.value); OUT(", ");
2186 OINTS(range->right.value); OUT(" }");
Lev Walkin59b176e2005-11-26 11:25:14 +00002187 } else {
2188 OUT("{ APC_UNCONSTRAINED,\t-1, -1, 0, 0 }");
2189 }
2190
Lev Walkin3a4689a2006-11-24 11:20:27 +00002191 pcmt:
2192
Lev Walkin59b176e2005-11-26 11:25:14 +00002193 /*
2194 * Print some courtesy debug information.
2195 */
2196 if(range->left.type == ARE_VALUE
2197 || range->right.type == ARE_VALUE) {
2198 OUT("\t/* ");
2199 if(type) OUT("(%s", type);
2200 OUT("(");
2201 if(range->left.type == ARE_VALUE)
Lev Walkinda997b12017-08-04 01:38:41 -07002202 OUT("%s", asn1p_itoa(range->left.value));
Lev Walkin59b176e2005-11-26 11:25:14 +00002203 else
2204 OUT("MIN");
2205 OUT("..");
2206 if(range->right.type == ARE_VALUE)
Lev Walkinda997b12017-08-04 01:38:41 -07002207 OUT("%s", asn1p_itoa(range->right.value));
Lev Walkin59b176e2005-11-26 11:25:14 +00002208 else
2209 OUT("MAX");
2210 if(range->extensible) OUT(",...");
2211 if(type) OUT(")");
2212 OUT(") */");
2213 }
2214
2215 return 0;
2216}
2217
2218static int
Lev Walkin98eabc12017-07-19 08:51:11 +04002219emit_member_OER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx) {
2220 int save_target = arg->target->target;
2221 asn1cnst_range_t *range;
2222 asn1p_expr_type_e etype;
2223
2224 etype = expr_get_type(arg, expr);
2225
2226 if((arg->flags & A1C_GEN_OER)
2227 && (expr->constraints || etype == ASN_BASIC_ENUMERATED
2228 || etype == ASN_CONSTR_CHOICE)) {
2229 /* Fall through */
2230 } else {
2231 return 0;
2232 }
2233
2234 REDIR(OT_CTDEFS);
2235
2236 OUT("static asn_oer_constraints_t "
2237 "asn_OER_%s_%s_constr_%d GCC_NOTUSED = {\n",
2238 pfx, MKID(expr), expr->_type_unique_index);
2239
2240 INDENT(+1);
2241
Lev Walkin4118ccf2017-08-02 10:37:31 -07002242 /* .value{.width,.positive} */
Lev Walkina28cbb92017-07-31 20:20:17 -07002243 range = asn1constraint_compute_OER_range(expr->Identifier, etype,
2244 expr->combined_constraints,
Lev Walkin98eabc12017-07-19 08:51:11 +04002245 ACT_EL_RANGE, 0, 0, 0);
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002246 if(emit_single_member_OER_constraint_value(arg, range)) {
Lev Walkin98eabc12017-07-19 08:51:11 +04002247 return -1;
2248 }
Lev Walkin4118ccf2017-08-02 10:37:31 -07002249 emit_single_member_OER_constraint_comment(arg, range, 0);
Lev Walkin98eabc12017-07-19 08:51:11 +04002250 asn1constraint_range_free(range);
2251
2252 OUT(",\n");
2253
Lev Walkin4118ccf2017-08-02 10:37:31 -07002254 /* .size */
Lev Walkina28cbb92017-07-31 20:20:17 -07002255 range = asn1constraint_compute_OER_range(expr->Identifier, etype,
2256 expr->combined_constraints,
Lev Walkin98eabc12017-07-19 08:51:11 +04002257 ACT_CT_SIZE, 0, 0, 0);
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002258 if(emit_single_member_OER_constraint_size(arg, range)) {
Lev Walkin98eabc12017-07-19 08:51:11 +04002259 return -1;
2260 }
Lev Walkin4118ccf2017-08-02 10:37:31 -07002261 emit_single_member_OER_constraint_comment(arg, range, "SIZE");
Lev Walkin98eabc12017-07-19 08:51:11 +04002262 asn1constraint_range_free(range);
2263
2264 INDENT(-1);
2265
2266 OUT("};\n");
2267
2268 REDIR(save_target);
2269
2270 return 0;
2271}
2272
2273static int
Lev Walkin4b5dae32006-10-09 12:27:44 +00002274emit_member_PER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx) {
Lev Walkin725883b2006-10-09 12:07:58 +00002275 int save_target = arg->target->target;
Lev Walkin59b176e2005-11-26 11:25:14 +00002276 asn1cnst_range_t *range;
2277 asn1p_expr_type_e etype;
2278
Lev Walkin07aaa342006-10-09 12:52:15 +00002279 etype = expr_get_type(arg, expr);
2280
Lev Walkin725883b2006-10-09 12:07:58 +00002281 if((arg->flags & A1C_GEN_PER)
2282 && (expr->constraints
Lev Walkin07aaa342006-10-09 12:52:15 +00002283 || etype == ASN_BASIC_ENUMERATED
2284 || etype == ASN_CONSTR_CHOICE)
Lev Walkin725883b2006-10-09 12:07:58 +00002285 ) {
2286 /* Fall through */
2287 } else {
2288 return 0;
2289 }
2290
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002291 if(expr->_type_referenced) {
2292 REDIR(OT_FUNC_DECLS);
2293
2294 OUT("extern asn_per_constraints_t "
2295 "asn_PER_%s_%s_constr_%d;\n",
2296 pfx, MKID(expr), expr->_type_unique_index);
2297 }
2298
Lev Walkin725883b2006-10-09 12:07:58 +00002299 REDIR(OT_CTDEFS);
2300
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002301 if(!(expr->_type_referenced)) OUT("static ");
2302 OUT("asn_per_constraints_t "
Lev Walkin1715b322013-03-28 04:02:13 -07002303 "asn_PER_%s_%s_constr_%d GCC_NOTUSED = {\n",
Lev Walkin4b5dae32006-10-09 12:27:44 +00002304 pfx, MKID(expr), expr->_type_unique_index);
Lev Walkin725883b2006-10-09 12:07:58 +00002305
Lev Walkin59b176e2005-11-26 11:25:14 +00002306 INDENT(+1);
2307
2308 /*
2309 * ENUMERATED and CHOICE are special.
2310 */
2311 if(etype == ASN_BASIC_ENUMERATED
2312 || etype == ASN_CONSTR_CHOICE) {
2313 asn1cnst_range_t tmprng;
2314 asn1p_expr_t *v;
2315 int extensible = 0;
2316 int eidx = -1;
2317
2318 expr = asn1f_find_terminal_type_ex(arg->asn, expr);
2319 assert(expr);
2320
2321 TQ_FOR(v, &(expr->members), next) {
2322 if(v->expr_type == A1TC_EXTENSIBLE) {
2323 extensible++;
2324 break;
2325 }
2326 eidx++;
2327 }
2328
2329 memset(&tmprng, 0, sizeof (tmprng));
2330 tmprng.extensible = extensible;
2331 if(eidx < 0) tmprng.empty_constraint = 1;
2332 tmprng.left.type = ARE_VALUE;
2333 tmprng.left.value = 0;
2334 tmprng.right.type = ARE_VALUE;
2335 tmprng.right.value = eidx < 0 ? 0 : eidx;
Lev Walkin725883b2006-10-09 12:07:58 +00002336 if(emit_single_member_PER_constraint(arg, &tmprng, 0, 0))
Lev Walkin59b176e2005-11-26 11:25:14 +00002337 return -1;
Lev Walkin729eb862006-09-21 01:50:13 +00002338 } else if(etype & ASN_STRING_KM_MASK) {
Lev Walkina28cbb92017-07-31 20:20:17 -07002339 range = asn1constraint_compute_PER_range(expr->Identifier, etype,
Lev Walkin729eb862006-09-21 01:50:13 +00002340 expr->combined_constraints, ACT_CT_FROM,
2341 0, 0, 0);
Lev Walkin725883b2006-10-09 12:07:58 +00002342 DEBUG("Emitting FROM constraint for %s", expr->Identifier);
Lev Walkin3a4689a2006-11-24 11:20:27 +00002343
2344 if((range->left.type == ARE_MIN && range->right.type == ARE_MAX)
2345 || range->not_PER_visible) {
2346 switch(etype) {
2347 case ASN_STRING_BMPString:
2348 range->left.type = ARE_VALUE;
2349 range->left.value = 0;
2350 range->right.type = ARE_VALUE;
2351 range->right.value = 65535;
2352 range->not_PER_visible = 0;
2353 range->extensible = 0;
2354 break;
2355 case ASN_STRING_UniversalString:
2356 OUT("{ APC_CONSTRAINED,\t32, 32,"
2357 " 0, 2147483647 }"
2358 " /* special case 1 */\n");
2359 goto avoid;
2360 default:
2361 break;
2362 }
2363 }
Lev Walkin725883b2006-10-09 12:07:58 +00002364 if(emit_single_member_PER_constraint(arg, range, 1, 0))
Lev Walkin729eb862006-09-21 01:50:13 +00002365 return -1;
Lev Walkin3a4689a2006-11-24 11:20:27 +00002366 avoid:
Lev Walkin729eb862006-09-21 01:50:13 +00002367 asn1constraint_range_free(range);
Lev Walkin59b176e2005-11-26 11:25:14 +00002368 } else {
Lev Walkina28cbb92017-07-31 20:20:17 -07002369 range = asn1constraint_compute_PER_range(expr->Identifier, etype,
Lev Walkin59b176e2005-11-26 11:25:14 +00002370 expr->combined_constraints, ACT_EL_RANGE,
2371 0, 0, 0);
Lev Walkin725883b2006-10-09 12:07:58 +00002372 if(emit_single_member_PER_constraint(arg, range, 0, 0))
Lev Walkin59b176e2005-11-26 11:25:14 +00002373 return -1;
2374 asn1constraint_range_free(range);
2375 }
2376 OUT(",\n");
2377
Lev Walkina28cbb92017-07-31 20:20:17 -07002378 range = asn1constraint_compute_PER_range(expr->Identifier, etype,
Lev Walkin59b176e2005-11-26 11:25:14 +00002379 expr->combined_constraints, ACT_CT_SIZE, 0, 0, 0);
Lev Walkin725883b2006-10-09 12:07:58 +00002380 if(emit_single_member_PER_constraint(arg, range, 0, "SIZE"))
Lev Walkin59b176e2005-11-26 11:25:14 +00002381 return -1;
2382 asn1constraint_range_free(range);
Lev Walkin725883b2006-10-09 12:07:58 +00002383 OUT(",\n");
2384
2385 if((etype & ASN_STRING_KM_MASK) && (expr->_mark & TM_PERFROMCT)) {
2386 int old_target = arg->target->target;
2387 REDIR(OT_CODE);
2388
2389 OUT("static int asn_PER_MAP_%s_%d_v2c(unsigned int value) {\n",
2390 MKID(expr), expr->_type_unique_index);
2391 OUT("\tif(value >= sizeof(permitted_alphabet_table_%d)/"
2392 "sizeof(permitted_alphabet_table_%d[0]))\n",
2393 expr->_type_unique_index,
2394 expr->_type_unique_index);
2395 OUT("\t\treturn -1;\n");
2396 OUT("\treturn permitted_alphabet_table_%d[value] - 1;\n",
2397 expr->_type_unique_index);
2398 OUT("}\n");
2399
2400 OUT("static int asn_PER_MAP_%s_%d_c2v(unsigned int code) {\n",
2401 MKID(expr), expr->_type_unique_index);
2402 OUT("\tif(code >= sizeof(permitted_alphabet_code2value_%d)/"
2403 "sizeof(permitted_alphabet_code2value_%d[0]))\n",
2404 expr->_type_unique_index,
2405 expr->_type_unique_index);
2406 OUT("\t\treturn -1;\n");
2407 OUT("\treturn permitted_alphabet_code2value_%d[code];\n",
2408 expr->_type_unique_index);
2409 OUT("}\n");
2410
2411 REDIR(old_target);
2412
2413 OUT("asn_PER_MAP_%s_%d_v2c,\t/* Value to PER code map */\n",
2414 MKID(expr), expr->_type_unique_index);
2415 OUT("asn_PER_MAP_%s_%d_c2v\t/* PER code to value map */\n",
2416 MKID(expr), expr->_type_unique_index);
2417 } else if(etype & ASN_STRING_KM_MASK) {
2418 DEBUG("No PER value map necessary for %s", MKID(expr));
2419 OUT("0, 0\t/* No PER character map necessary */\n");
2420 } else {
2421 OUT("0, 0\t/* No PER value map */\n");
2422 }
Lev Walkin59b176e2005-11-26 11:25:14 +00002423
2424 INDENT(-1);
2425
Lev Walkin725883b2006-10-09 12:07:58 +00002426 OUT("};\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002427
Lev Walkin725883b2006-10-09 12:07:58 +00002428 REDIR(save_target);
Lev Walkin59b176e2005-11-26 11:25:14 +00002429
2430 return 0;
2431}
2432
2433static int
Lev Walkin8032f7a2007-06-27 01:54:57 +00002434safe_string(const uint8_t *buf, int size) {
2435 const uint8_t *end = buf + size;
2436 for(; buf < end; buf++) {
2437 int ch = *buf;
2438 if((ch < 0x20 || ch > 0x7e) || ch == '"')
2439 return 0;
2440 }
2441 return 1;
2442}
2443
2444static void
2445emit_default_value(arg_t *arg, asn1p_value_t *v) {
2446
2447 OUT("static uint8_t defv[] = ");
2448 assert(v->type == ATV_STRING);
2449
2450 if(safe_string(v->value.string.buf, v->value.string.size)) {
2451 OUT("\"%s\";\n", v->value.string.buf);
2452 } else {
2453 uint8_t *b = v->value.string.buf;
2454 uint8_t *e = v->value.string.size + b;
2455 OUT("{ ");
2456 for(;b < e; b++)
2457 OUT("0x%02x, ", *b);
2458 OUT("0 };\n");
2459 }
2460}
2461
2462static int
Lev Walkin59b176e2005-11-26 11:25:14 +00002463try_inline_default(arg_t *arg, asn1p_expr_t *expr, int out) {
2464 int save_target = arg->target->target;
2465 asn1p_expr_type_e etype = expr_get_type(arg, expr);
2466 int fits_long = 0;
2467
2468 switch(etype) {
2469 case ASN_BASIC_BOOLEAN:
2470 fits_long = 1;
2471 case ASN_BASIC_INTEGER:
2472 case ASN_BASIC_ENUMERATED:
2473 if(expr->marker.default_value == NULL
2474 || expr->marker.default_value->type != ATV_INTEGER)
2475 break;
2476 if(!fits_long)
2477 fits_long = asn1c_type_fits_long(arg, expr)!=FL_NOTFIT;
2478 if(fits_long && !expr->marker.default_value->value.v_integer)
2479 expr->marker.flags &= ~EM_INDIRECT;
Lev Walkin8032f7a2007-06-27 01:54:57 +00002480 if(!out) {
Lev Walkinda997b12017-08-04 01:38:41 -07002481 OUT("asn_DFL_%d_set_%s,",
Lev Walkin8032f7a2007-06-27 01:54:57 +00002482 expr->_type_unique_index,
Lev Walkinda997b12017-08-04 01:38:41 -07002483 asn1p_itoa(expr->marker.default_value->value.v_integer));
2484 OUT("\t/* DEFAULT %s */\n",
2485 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin8032f7a2007-06-27 01:54:57 +00002486 return 1;
2487 }
Lev Walkin59b176e2005-11-26 11:25:14 +00002488 REDIR(OT_STAT_DEFS);
Lev Walkinda997b12017-08-04 01:38:41 -07002489 OUT("static int asn_DFL_%d_set_%s(int set_value, void **sptr) {\n",
Lev Walkin59b176e2005-11-26 11:25:14 +00002490 expr->_type_unique_index,
Lev Walkinda997b12017-08-04 01:38:41 -07002491 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin59b176e2005-11-26 11:25:14 +00002492 INDENT(+1);
2493 OUT("%s *st = *sptr;\n", asn1c_type_name(arg, expr, TNF_CTYPE));
2494 OUT("\n");
2495 OUT("if(!st) {\n");
Lev Walkin1dc85292006-08-18 01:32:26 +00002496 OUT("\tif(!set_value) return -1;\t/* Not a default value */\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002497 OUT("\tst = (*sptr = CALLOC(1, sizeof(*st)));\n");
2498 OUT("\tif(!st) return -1;\n");
2499 OUT("}\n");
2500 OUT("\n");
Lev Walkin1dc85292006-08-18 01:32:26 +00002501 OUT("if(set_value) {\n");
2502 INDENT(+1);
Lev Walkinda997b12017-08-04 01:38:41 -07002503 OUT("/* Install default value %s */\n",
2504 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin59b176e2005-11-26 11:25:14 +00002505 if(fits_long) {
Lev Walkin63b41262007-11-06 01:48:46 +00002506 OUT("*st = ");
2507 OINT(expr->marker.default_value->value.v_integer);
2508 OUT(";\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002509 OUT("return 0;\n");
2510 } else {
Lev Walkin63b41262007-11-06 01:48:46 +00002511 OUT("return asn_long2INTEGER(st, ");
2512 OINT(expr->marker.default_value->value.v_integer);
2513 OUT(");\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002514 }
2515 INDENT(-1);
Lev Walkin1dc85292006-08-18 01:32:26 +00002516 OUT("} else {\n");
2517 INDENT(+1);
Lev Walkinda997b12017-08-04 01:38:41 -07002518 OUT("/* Test default value %s */\n",
2519 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin1dc85292006-08-18 01:32:26 +00002520 if(fits_long) {
Lev Walkinda997b12017-08-04 01:38:41 -07002521 OUT("return (*st == %s);\n",
2522 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin1dc85292006-08-18 01:32:26 +00002523 } else {
2524 OUT("long value;\n");
2525 OUT("if(asn_INTEGER2long(st, &value))\n");
2526 OUT("\treturn -1;\n");
Lev Walkinda997b12017-08-04 01:38:41 -07002527 OUT("return (value == %s);\n",
2528 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin1dc85292006-08-18 01:32:26 +00002529 }
2530 INDENT(-1);
2531 OUT("}\n");
2532 INDENT(-1);
Lev Walkin59b176e2005-11-26 11:25:14 +00002533 OUT("}\n");
2534 REDIR(save_target);
2535 return 1;
2536 case ASN_BASIC_NULL:
2537 //expr->marker.flags &= ~EM_INDIRECT;
2538 return 0;
2539 default:
Lev Walkin8032f7a2007-06-27 01:54:57 +00002540 if(etype & ASN_STRING_KM_MASK) {
2541 if(expr->marker.default_value == NULL
2542 || expr->marker.default_value->type != ATV_STRING)
2543 break;
2544 if(!out) {
2545 OUT("asn_DFL_%d_set,\t/* DEFAULT \"%s\" */\n",
2546 expr->_type_unique_index,
2547 expr->marker.default_value->value.string.buf);
2548 return 1;
2549 }
2550 REDIR(OT_STAT_DEFS);
2551 OUT("static int asn_DFL_%d_set(int set_value, void **sptr) {\n", expr->_type_unique_index);
2552 INDENT(+1);
2553 emit_default_value(arg, expr->marker.default_value);
2554 OUT("%s *st = *sptr;\n", asn1c_type_name(arg, expr, TNF_CTYPE));
2555 OUT("\n");
2556 OUT("if(!st) {\n");
2557 OUT("\tif(!set_value) return -1;\t/* Not a default value */\n");
2558 OUT("\tst = (*sptr = CALLOC(1, sizeof(*st)));\n");
2559 OUT("\tif(!st) return -1;\n");
2560 OUT("}\n");
2561 OUT("\n");
2562 OUT("if(set_value) {\n");
2563 INDENT(+1);
2564 OUT("uint8_t *ptr = MALLOC(sizeof(defv));\n");
2565 OUT("if(!ptr) return -1;\n");
2566 OUT("memcpy(ptr, &defv, sizeof(defv));\n");
2567 OUT("FREEMEM(st->buf);\n");
2568 OUT("st->buf = ptr;\n");
2569 OUT("st->size = sizeof(defv) - 1;\n");
2570 OUT("return 0;\n");
2571 INDENT(-1);
2572 OUT("} else {\n");
2573 INDENT(+1);
2574 OUT("if(st->size != (sizeof(defv) - 1)\n");
2575 OUT("|| memcmp(st->buf, &defv, sizeof(defv) - 1))\n");
2576 OUT("\treturn 0;\n");
2577 OUT("return 1;\n");
2578 INDENT(-1);
2579 OUT("}\n"); OUT("\n");
2580 INDENT(-1);
2581 OUT("}\n");
2582 REDIR(save_target);
2583 return 1;
2584 }
2585 break;
Lev Walkin59b176e2005-11-26 11:25:14 +00002586 }
2587 return 0;
2588}
2589
Lev Walkin59004fa2004-08-20 13:37:01 +00002590static int
Lev Walkin9de6cd82017-08-10 05:47:46 -07002591emit_member_type_selector(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_objset_t *opt_ioc) {
2592 int save_target = arg->target->target;
2593 asn1p_expr_t *parent_expr = arg->expr;
2594
2595 const asn1p_constraint_t *crc =
2596 asn1p_get_component_relation_constraint(expr->combined_constraints);
2597 if(!crc || crc->el_count <= 1) {
2598 /* Not an Open Type, it seems. */
2599 OUT("0");
2600 return 0;
2601 }
2602
2603 if(crc->el_count <= 1 || crc->elements[0]->type != ACT_EL_VALUE
2604 || crc->elements[0]->value->type != ATV_REFERENCED
2605 || crc->elements[0]->value->value.reference->comp_count != 1) {
2606 FATAL(
2607 "Reference does not look like an object set");
2608 return -1;
2609 }
2610
2611 const char *objset_name =
2612 crc->elements[0]->value->value.reference->components[0].name;
2613 if(strcmp(objset_name, opt_ioc->objset->Identifier) != 0) {
2614 FATAL("Object Set references do not match: %s != %s", objset_name,
2615 opt_ioc->objset->Identifier);
2616 return -1;
2617 }
2618
2619 if(crc->el_count != 2 || crc->elements[1]->type != ACT_EL_VALUE
2620 || crc->elements[1]->value->type != ATV_REFERENCED
2621 || crc->elements[1]->value->value.reference->comp_count != 1) {
2622 FATAL(
2623 "Do not know how to handle complex IoS constraints (%d components "
2624 "of constraint, %d components of reference %s) for %s at line "
2625 "%d",
2626 crc->el_count,
2627 crc->el_count >= 2 && crc->elements[1]->type == ACT_EL_VALUE
2628 && crc->elements[1]->value->type == ATV_REFERENCED
2629 ? crc->elements[1]->value->value.reference->comp_count
2630 : -1,
2631 crc->el_count >= 2 && crc->elements[1]->type == ACT_EL_VALUE
2632 && crc->elements[1]->value->type == ATV_REFERENCED
2633 ? asn1p_ref_string(crc->elements[1]->value->value.reference)
2634 : "?",
2635 MKID(parent_expr), parent_expr->_lineno);
2636 OUT("0");
2637 return -1;
2638 }
2639
2640 const asn1p_ref_t *cref = crc->elements[1]->value->value.reference;
2641 const char *cname = cref->components[0].name;
2642 if(cname[0] == '@' && cname[1] != '.') {
2643 cname += 1;
2644 } else if(cname[0] == '@' && cname[1] == '.' && cname[2] != '.') {
2645 cname += 2;
2646 } else {
2647 FATAL("Complex IoS reference %s can not be processed",
2648 asn1p_ref_string(cref));
2649 OUT("0");
2650 return -1;
2651 }
2652
2653 assert(opt_ioc != NULL);
2654
2655 asn1p_expr_t *constraining_memb = NULL;
2656 TQ_FOR(constraining_memb, &(parent_expr->members), next) {
2657 if(strcmp(constraining_memb->Identifier, cname) == 0)
2658 break;
2659 }
2660 if(!constraining_memb) {
2661 FATAL("Can not find \"%s\" in %s at line %d", cname, MKID(parent_expr),
2662 parent_expr->_lineno);
2663 return -1;
2664 }
2665
2666 if(constraining_memb->meta_type != AMT_TYPEREF
2667 || constraining_memb->expr_type != A1TC_REFERENCE
2668 || constraining_memb->reference->comp_count != 2
2669 || constraining_memb->reference->components[1].lex_type
2670 != RLT_Amplowercase) {
2671 FATAL(
2672 "Does not look like %s is a CLASS field reference (%s) on line "
2673 "%d",
2674 MKID(constraining_memb),
2675 constraining_memb->reference
2676 ? asn1p_ref_string(constraining_memb->reference)
2677 : "<no reference>",
2678 constraining_memb->_lineno);
2679 return -1;
2680 }
2681 const char *cfield = constraining_memb->reference->components[1].name;
2682
2683 ssize_t constraining_column = -1;
2684 for(size_t cn = 0; cn < opt_ioc->ioct->rows ? opt_ioc->ioct->row[0]->columns : 0;
2685 cn++) {
2686 if(strcmp(cfield, opt_ioc->ioct->row[0]->column[cn].field->Identifier)
2687 == 0) {
2688 constraining_column = cn;
2689 break;
2690 }
2691 }
2692 if(constraining_column < 0) {
2693 FATAL("Can not find referenced object class column %s\n", cfield);
2694 return -1;
2695 }
2696
2697 if(expr->meta_type != AMT_TYPEREF
2698 || expr->expr_type != A1TC_REFERENCE
2699 || expr->reference->comp_count != 2
2700 || expr->reference->components[1].lex_type
2701 != RLT_AmpUppercase) {
2702 FATAL(
2703 "Does not look like %s is a CLASS field reference (%s) denoting a type on line "
2704 "%d",
2705 MKID(expr),
2706 expr->reference
2707 ? asn1p_ref_string(expr->reference)
2708 : "<no reference>",
2709 expr->_lineno);
2710 return -1;
2711 }
2712 const char *for_field = expr->reference->components[1].name;
2713
2714 ssize_t for_column = -1;
2715 for(size_t cn = 0; cn < opt_ioc->ioct->rows ? opt_ioc->ioct->row[0]->columns : 0;
2716 cn++) {
2717 if(strcmp(for_field,
2718 opt_ioc->ioct->row[0]->column[cn].field->Identifier)
2719 == 0) {
2720 for_column = cn;
2721 break;
2722 }
2723 }
2724 if(for_column < 0) {
2725 FATAL("Can not find referenced object class column %s\n", for_field);
2726 return -1;
2727 }
2728
2729
2730 REDIR(OT_CODE);
2731 OUT("static asn_TYPE_descriptor_t *\n");
2732 OUT("select_%s_type(const asn_TYPE_descriptor_t *parent_type, const void *parent_sptr) {\n", MKID_safe(expr));
2733 INDENT(+1);
2734
2735 OUT("asn_ioc_set_t *itable = asn_IOS_%s_%d;\n", MKID(opt_ioc->objset),
2736 opt_ioc->objset->_type_unique_index);
2737 OUT("size_t constraining_column = %zu; /* %s */\n", constraining_column, cfield);
2738 OUT("size_t for_column = %zu; /* %s */\n", for_column, for_field);
2739 OUT("size_t row;\n");
2740
2741 const char *tname = asn1c_type_name(arg, constraining_memb, TNF_SAFE);
2742 if(constraining_memb->marker.flags & EM_INDIRECT) {
2743 OUT("void *memb_ptr = *(const void **)");
2744 OUT("((const char *)parent_sptr + offsetof(struct ");
2745 out_name_chain(arg, ONC_avoid_keywords);
2746 OUT(", %s));", MKID_safe(constraining_memb));
2747 OUT("if(!memb_ptr) return NULL;\n");
2748 OUT("\n");
2749 }
2750
2751 switch(asn1c_type_fits_long(arg, constraining_memb)) {
2752 case FL_NOTFIT:
2753 OUT("const %s_t *constraining_value = (const %s_t *)", tname, tname);
2754 break;
2755 case FL_PRESUMED:
2756 case FL_FITS_SIGNED:
2757 OUT("const long *constraining_value = (const long *)");
2758 break;
2759 case FL_FITS_UNSIGN:
2760 OUT("const unsigned long *constraining_value = (const unsigned long *)");
2761 break;
2762 }
2763 if(constraining_memb->marker.flags & EM_INDIRECT) {
2764 OUT("memb_ptr;\n");
2765 } else {
2766 OUT("((const char *)parent_sptr + offsetof(struct ");
2767 out_name_chain(arg, ONC_avoid_keywords);
2768 OUT(", %s));\n", MKID_safe(constraining_memb));
2769 }
2770 OUT("\n");
2771
2772 OUT("for(row=0; row < itable->rows_count; row++) {\n");
2773 OUT(" asn_ioc_cell_s *constraining_cell = itable->rows[row * itable->columns_count + constraining_column];\n");
2774 OUT(" asn_ioc_cell_s *type_cell = itable->rows[row * itable->columns_count + for_column];\n");
2775 OUT(" if(constraining_cell->type_descriptor->struct_compare(constraining_cell->type_descriptor, constraining_value, constraining_cell->value_sptr) == 0) {\n");
2776 OUT(" return type_cell->type_descriptor;\n");
2777 OUT(" }\n");
2778 OUT("}\n");
2779
2780
2781 OUT("\n");
2782 OUT("return NULL;\n");
2783 INDENT(-1);
2784 OUT("}\n");
2785 OUT("\n");
2786
2787 REDIR(save_target);
2788 OUT("select_%s_type", MKID_safe(expr));
2789
2790 return 0;
2791}
2792
2793static int
2794emit_member_table(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_objset_t *opt_ioc) {
Lev Walkin59004fa2004-08-20 13:37:01 +00002795 int save_target;
2796 arg_t tmp_arg;
Lev Walkinb9189732004-09-10 09:37:12 +00002797 struct asn1p_type_tag_s outmost_tag_s;
2798 struct asn1p_type_tag_s *outmost_tag;
Lev Walkine0b56e02005-02-25 12:10:27 +00002799 int complex_contents;
Lev Walkin59004fa2004-08-20 13:37:01 +00002800 char *p;
2801
Lev Walkinb9189732004-09-10 09:37:12 +00002802 if(asn1f_fetch_outmost_tag(arg->asn,
Lev Walkin59b176e2005-11-26 11:25:14 +00002803 expr->module, expr, &outmost_tag_s,
2804 AFT_IMAGINARY_ANY)) {
Lev Walkinb9189732004-09-10 09:37:12 +00002805 outmost_tag = 0;
2806 } else {
2807 outmost_tag = &outmost_tag_s;
2808 }
2809
Lev Walkin59004fa2004-08-20 13:37:01 +00002810 OUT("{ ");
Lev Walkinb9189732004-09-10 09:37:12 +00002811
2812 if(outmost_tag && outmost_tag->tag_value == -1)
2813 OUT("ATF_OPEN_TYPE | ");
Lev Walkinc8285712005-03-04 22:18:20 +00002814 OUT("%s, ",
2815 (expr->marker.flags & EM_INDIRECT)?"ATF_POINTER":"ATF_NOFLAGS");
Lev Walkinb85a8132005-08-18 13:38:19 +00002816 if((expr->marker.flags & EM_OMITABLE) == EM_OMITABLE) {
Lev Walkin59004fa2004-08-20 13:37:01 +00002817 asn1p_expr_t *tv;
2818 int opts = 0;
Lev Walkinb85a8132005-08-18 13:38:19 +00002819 for(tv = expr;
2820 tv && (tv->marker.flags & EM_OMITABLE) == EM_OMITABLE;
Lev Walkin59004fa2004-08-20 13:37:01 +00002821 tv = TQ_NEXT(tv, next), opts++) {
2822 if(tv->expr_type == A1TC_EXTENSIBLE)
2823 opts--;
2824 }
2825 OUT("%d, ", opts);
2826 } else {
2827 OUT("0, ");
2828 }
Lev Walkina9cc46e2004-09-22 16:06:28 +00002829 if(expr->_anonymous_type) {
2830 assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
2831 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
2832 OUT("0,\n");
2833 } else {
Lev Walkin21d00002005-03-04 08:48:53 +00002834 OUT("offsetof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +00002835 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +00002836 OUT(", ");
Lev Walkin59004fa2004-08-20 13:37:01 +00002837 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
2838 && (!UNNAMED_UNIONS)) OUT("choice.");
Lev Walkina00d6b32006-03-21 03:40:38 +00002839 OUT("%s),\n", MKID_safe(expr));
Lev Walkin59004fa2004-08-20 13:37:01 +00002840 }
2841 INDENT(+1);
2842 if(C99_MODE) OUT(".tag = ");
Lev Walkinb9189732004-09-10 09:37:12 +00002843 if(outmost_tag) {
2844 if(outmost_tag->tag_value == -1)
2845 OUT("-1 /* Ambiguous tag (ANY?) */");
2846 else
2847 _print_tag(arg, outmost_tag);
Lev Walkinc3e29402004-09-10 06:07:18 +00002848 } else {
Lev Walkinb9189732004-09-10 09:37:12 +00002849 OUT("-1 /* Ambiguous tag (CHOICE?) */");
Lev Walkinc3e29402004-09-10 06:07:18 +00002850 }
Lev Walkinb9189732004-09-10 09:37:12 +00002851
Lev Walkin59004fa2004-08-20 13:37:01 +00002852 OUT(",\n");
2853 if(C99_MODE) OUT(".tag_mode = ");
Lev Walkin9ab21b82006-10-19 02:46:01 +00002854 if((!(expr->expr_type & ASN_CONSTR_MASK)
2855 || expr->expr_type == ASN_CONSTR_CHOICE)
2856 && expr->tag.tag_class) {
Lev Walkin59004fa2004-08-20 13:37:01 +00002857 if(expr->tag.tag_mode == TM_IMPLICIT)
2858 OUT("-1,\t/* IMPLICIT tag at current level */\n");
2859 else
2860 OUT("+1,\t/* EXPLICIT tag at current level */\n");
2861 } else {
2862 OUT("0,\n");
2863 }
Lev Walkine0b56e02005-02-25 12:10:27 +00002864
2865 complex_contents =
2866 (expr->expr_type & ASN_CONSTR_MASK)
2867 || expr->expr_type == ASN_BASIC_ENUMERATED
Lev Walkin8ecf9db2005-03-03 21:28:12 +00002868 || (0 /* -- prohibited by X.693:8.3.4 */
2869 && expr->expr_type == ASN_BASIC_INTEGER
Lev Walkin8bb57a22007-12-03 13:41:36 +00002870 && expr_elements_count(arg, expr))
2871 || (expr->expr_type == ASN_BASIC_INTEGER
2872 && asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN);
Lev Walkin59004fa2004-08-20 13:37:01 +00002873 if(C99_MODE) OUT(".type = ");
Lev Walkinae7bf3f2005-08-29 10:31:14 +00002874 OUT("&asn_DEF_");
Lev Walkin21d00002005-03-04 08:48:53 +00002875 if(complex_contents) {
Lev Walkina00d6b32006-03-21 03:40:38 +00002876 OUT("%s", MKID(expr));
Lev Walkin21d00002005-03-04 08:48:53 +00002877 if(!(arg->flags & A1C_ALL_DEFS_GLOBAL))
2878 OUT("_%d", expr->_type_unique_index);
Lev Walkin08079b02004-08-22 03:25:24 +00002879 } else {
Lev Walkin21d00002005-03-04 08:48:53 +00002880 OUT("%s", asn1c_type_name(arg, expr, TNF_SAFE));
Lev Walkin08079b02004-08-22 03:25:24 +00002881 }
Lev Walkin21d00002005-03-04 08:48:53 +00002882 OUT(",\n");
Lev Walkin9de6cd82017-08-10 05:47:46 -07002883
2884
2885 if(C99_MODE) OUT(".type_selector = ");
2886 if(opt_ioc) {
2887 emit_member_type_selector(arg, expr, opt_ioc);
2888 } else {
2889 OUT("0");
2890 }
2891 OUT(",\n");
2892
Lev Walkin59004fa2004-08-20 13:37:01 +00002893 if(C99_MODE) OUT(".memb_constraints = ");
2894 if(expr->constraints) {
Lev Walkin8de2ab22004-09-26 13:11:31 +00002895 if(arg->flags & A1C_NO_CONSTRAINTS) {
2896 OUT("0,\t/* No check because of -fno-constraints */\n");
2897 } else {
Lev Walkina00d6b32006-03-21 03:40:38 +00002898 char *id = MKID(expr);
Lev Walkin8de2ab22004-09-26 13:11:31 +00002899 if(expr->_anonymous_type
Lev Walkin152a91e2005-02-14 20:41:29 +00002900 && !strcmp(expr->Identifier, "Member"))
Lev Walkin8de2ab22004-09-26 13:11:31 +00002901 id = asn1c_type_name(arg, expr, TNF_SAFE);
Lev Walkin59b176e2005-11-26 11:25:14 +00002902 OUT("memb_%s_constraint_%d,\n", id,
Lev Walkin21d00002005-03-04 08:48:53 +00002903 arg->expr->_type_unique_index);
Lev Walkin8de2ab22004-09-26 13:11:31 +00002904 }
Lev Walkin59004fa2004-08-20 13:37:01 +00002905 } else {
Lev Walkinb7bfd1a2005-01-17 12:16:58 +00002906 OUT("0,\t/* Defer constraints checking to the member type */\n");
Lev Walkin59004fa2004-08-20 13:37:01 +00002907 }
Lev Walkinb33425f2017-07-14 14:59:52 +04002908 if(C99_MODE) OUT(".oer_constraints = ");
2909 if(arg->flags & A1C_GEN_OER) {
2910 if(expr->constraints) {
2911 OUT("&asn_OER_memb_%s_constr_%d,\n",
2912 MKID(expr),
2913 expr->_type_unique_index);
2914 } else {
2915 OUT("0,\t/* No OER visible constraints */\n");
2916 }
2917 } else {
2918 OUT("0,\t/* OER is not compiled, use -gen-OER */\n");
2919 }
Lev Walkin59b176e2005-11-26 11:25:14 +00002920 if(C99_MODE) OUT(".per_constraints = ");
2921 if(arg->flags & A1C_GEN_PER) {
Lev Walkin07aaa342006-10-09 12:52:15 +00002922 if(expr->constraints) {
Lev Walkin4b5dae32006-10-09 12:27:44 +00002923 OUT("&asn_PER_memb_%s_constr_%d,\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00002924 MKID(expr),
Lev Walkin59b176e2005-11-26 11:25:14 +00002925 expr->_type_unique_index);
2926 } else {
2927 OUT("0,\t/* No PER visible constraints */\n");
2928 }
Lev Walkin152a91e2005-02-14 20:41:29 +00002929 } else {
Lev Walkin59b176e2005-11-26 11:25:14 +00002930 OUT("0,\t/* PER is not compiled, use -gen-PER */\n");
2931 }
2932 if(C99_MODE) OUT(".default_value = ");
2933 if(try_inline_default(arg, expr, 0)) {
Lev Walkin59b176e2005-11-26 11:25:14 +00002934 } else {
2935 OUT("0,\n");
2936 }
2937 if(C99_MODE) OUT(".name = ");
2938 if(expr->_anonymous_type && !strcmp(expr->Identifier, "Member")) {
2939 OUT("\"\"\n");
2940 } else {
2941 OUT("\"%s\"\n", expr->Identifier);
Lev Walkin152a91e2005-02-14 20:41:29 +00002942 }
Lev Walkin59004fa2004-08-20 13:37:01 +00002943 OUT("},\n");
2944 INDENT(-1);
2945
Lev Walkin8de2ab22004-09-26 13:11:31 +00002946 if(!expr->constraints || (arg->flags & A1C_NO_CONSTRAINTS))
Lev Walkin59004fa2004-08-20 13:37:01 +00002947 return 0;
2948
2949 save_target = arg->target->target;
2950 REDIR(OT_CODE);
2951
Lev Walkin152a91e2005-02-14 20:41:29 +00002952 if(expr->_anonymous_type && !strcmp(expr->Identifier, "Member"))
Lev Walkin59004fa2004-08-20 13:37:01 +00002953 p = asn1c_type_name(arg, expr, TNF_SAFE);
Lev Walkina9cc46e2004-09-22 16:06:28 +00002954 else
Lev Walkina00d6b32006-03-21 03:40:38 +00002955 p = MKID(expr);
Lev Walkin59004fa2004-08-20 13:37:01 +00002956 OUT("static int\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002957 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 +00002958 INDENT(+1);
Lev Walkin1eded352006-07-13 11:19:01 +00002959 OUT("\t\tasn_app_constraint_failed_f *ctfailcb, void *app_key) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +00002960 tmp_arg = *arg;
2961 tmp_arg.expr = expr;
Lev Walkin725883b2006-10-09 12:07:58 +00002962 DEBUG("member constraint checking code for %s", p);
Lev Walkin59004fa2004-08-20 13:37:01 +00002963 if(asn1c_emit_constraint_checking_code(&tmp_arg) == 1) {
Lev Walkin8de2ab22004-09-26 13:11:31 +00002964 OUT("return td->check_constraints"
Lev Walkin1eded352006-07-13 11:19:01 +00002965 "(td, sptr, ctfailcb, app_key);\n");
Lev Walkin59004fa2004-08-20 13:37:01 +00002966 }
2967 INDENT(-1);
2968 OUT("}\n");
2969 OUT("\n");
2970
Lev Walkin98eabc12017-07-19 08:51:11 +04002971 if(emit_member_OER_constraints(arg, expr, "memb"))
2972 return -1;
2973
Lev Walkin4b5dae32006-10-09 12:27:44 +00002974 if(emit_member_PER_constraints(arg, expr, "memb"))
Lev Walkin725883b2006-10-09 12:07:58 +00002975 return -1;
2976
Lev Walkin59004fa2004-08-20 13:37:01 +00002977 REDIR(save_target);
2978
2979 return 0;
2980}
Lev Walkin59964be2004-08-25 02:03:12 +00002981
Lev Walkindc06f6b2004-10-20 15:50:55 +00002982/*
2983 * Generate "asn_DEF_XXX" type definition.
2984 */
Lev Walkin59964be2004-08-25 02:03:12 +00002985static int
Lev Walkin8de2ab22004-09-26 13:11:31 +00002986emit_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 +00002987 asn1p_expr_t *terminal;
Lev Walkin21d00002005-03-04 08:48:53 +00002988 int using_type_name = 0;
Lev Walkina00d6b32006-03-21 03:40:38 +00002989 char *p = MKID(expr);
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002990 char *p2 = (char *)0;
Lev Walkin59b176e2005-11-26 11:25:14 +00002991
Lev Walkin8c2ca0b2006-09-17 06:31:08 +00002992 terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
2993
Lev Walkin01582a72017-07-26 18:47:08 -07002994 if(emit_member_OER_constraints(arg, expr, "type"))
2995 return -1;
2996
Lev Walkin4b5dae32006-10-09 12:27:44 +00002997 if(emit_member_PER_constraints(arg, expr, "type"))
Lev Walkin725883b2006-10-09 12:07:58 +00002998 return -1;
Lev Walkin59964be2004-08-25 02:03:12 +00002999
Lev Walkindd32b592004-09-06 08:07:29 +00003000 if(HIDE_INNER_DEFS)
3001 OUT("static /* Use -fall-defs-global to expose */\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00003002 OUT("asn_TYPE_descriptor_t asn_DEF_%s", p);
Lev Walkin21d00002005-03-04 08:48:53 +00003003 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
3004 OUT(" = {\n");
Lev Walkin188ed2c2004-09-13 08:31:01 +00003005 INDENT(+1);
Lev Walkin59b176e2005-11-26 11:25:14 +00003006
3007 if(expr->_anonymous_type) {
3008 p = ASN_EXPR_TYPE2STR(expr->expr_type);
3009 OUT("\"%s\",\n", p?p:"");
Lev Walkina00d6b32006-03-21 03:40:38 +00003010 OUT("\"%s\",\n",
3011 p ? asn1c_make_identifier(AMI_CHECK_RESERVED,
3012 0, p, 0) : "");
Lev Walkin59b176e2005-11-26 11:25:14 +00003013 } else {
3014 OUT("\"%s\",\n", expr->Identifier);
3015 OUT("\"%s\",\n", expr->Identifier);
3016 }
Lev Walkin59964be2004-08-25 02:03:12 +00003017
3018 if(expr->expr_type & ASN_CONSTR_MASK) {
Lev Walkin21d00002005-03-04 08:48:53 +00003019 using_type_name = 1;
Lev Walkin59964be2004-08-25 02:03:12 +00003020 p = asn1c_type_name(arg, arg->expr, TNF_SAFE);
Lev Walkin59b176e2005-11-26 11:25:14 +00003021 } else {
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003022 if (expr->expr_type == A1TC_REFERENCE) {
3023 p2 = strdup(asn1c_type_name(arg, terminal, TNF_SAFE));
3024 } else {
3025 p2 = strdup(asn1c_type_name(arg, expr, TNF_SAFE));
3026 }
Lev Walkina00d6b32006-03-21 03:40:38 +00003027 p = MKID(expr);
Lev Walkin59964be2004-08-25 02:03:12 +00003028 }
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003029 if (!p2)
3030 p2 = strdup(p);
Lev Walkin59964be2004-08-25 02:03:12 +00003031
Lev Walkin21d00002005-03-04 08:48:53 +00003032#define FUNCREF(foo) do { \
3033 OUT("%s", p); \
3034 if(HIDE_INNER_DEFS && !using_type_name) \
3035 OUT("_%d", expr->_type_unique_index); \
3036 OUT("_" #foo ",\n"); \
3037} while(0)
3038
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003039#define FUNCREF2(foo) \
3040do { \
3041 OUT("%s", p2); \
3042 OUT("_" #foo ",\n"); \
3043} while(0)
3044
3045 FUNCREF2(free);
3046 FUNCREF2(print);
Lev Walkincd2f48e2017-08-10 02:14:59 -07003047 FUNCREF2(compare);
mattipeee0b99ab2017-08-04 11:44:04 +01003048 if (arg->flags & A1C_NO_CONSTRAINTS)
3049 OUT("0,\t/* No check because of -fno-constraints */\n");
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003050 else
mattipeee0b99ab2017-08-04 11:44:04 +01003051 {
3052 if (!expr->combined_constraints)
3053 FUNCREF2(constraint);
3054 else
3055 FUNCREF(constraint);
3056 }
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003057 FUNCREF2(decode_ber);
3058 FUNCREF2(encode_der);
3059 FUNCREF2(decode_xer);
3060 FUNCREF2(encode_xer);
Lev Walkinb33425f2017-07-14 14:59:52 +04003061
3062 if(arg->flags & A1C_GEN_OER) {
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003063 FUNCREF2(decode_oer);
3064 FUNCREF2(encode_oer);
Lev Walkinb33425f2017-07-14 14:59:52 +04003065 } else {
3066 OUT("0, 0,\t/* No OER support, "
3067 "use \"-gen-OER\" to enable */\n");
3068 }
Lev Walkin1dc85292006-08-18 01:32:26 +00003069 if(arg->flags & A1C_GEN_PER) {
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003070 FUNCREF2(decode_uper);
3071 FUNCREF2(encode_uper);
Lev Walkin1dc85292006-08-18 01:32:26 +00003072 } else {
3073 OUT("0, 0,\t/* No PER support, "
3074 "use \"-gen-PER\" to enable */\n");
3075 }
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003076 if (p2) free(p2);
Lev Walkin59964be2004-08-25 02:03:12 +00003077
Lev Walkin8c2ca0b2006-09-17 06:31:08 +00003078 if(!terminal || terminal->expr_type == ASN_CONSTR_CHOICE) {
3079 //if(expr->expr_type == ASN_CONSTR_CHOICE) {
Lev Walkin59964be2004-08-25 02:03:12 +00003080 OUT("CHOICE_outmost_tag,\n");
3081 } else {
3082 OUT("0,\t/* Use generic outmost tag fetcher */\n");
3083 }
3084
Lev Walkina00d6b32006-03-21 03:40:38 +00003085 p = MKID(expr);
Lev Walkin59964be2004-08-25 02:03:12 +00003086 if(tags_count) {
Lev Walkin59b176e2005-11-26 11:25:14 +00003087 OUT("asn_DEF_%s_tags_%d,\n",
Lev Walkin21d00002005-03-04 08:48:53 +00003088 p, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00003089 OUT("sizeof(asn_DEF_%s_tags_%d)\n",
Lev Walkin21d00002005-03-04 08:48:53 +00003090 p, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00003091 OUT("\t/sizeof(asn_DEF_%s_tags_%d[0])",
Lev Walkin21d00002005-03-04 08:48:53 +00003092 p, expr->_type_unique_index);
Lev Walkin188ed2c2004-09-13 08:31:01 +00003093 if(tv_mode == _TVM_SUBSET
3094 && tags_count != all_tags_count)
3095 OUT(" - %d", all_tags_count - tags_count);
3096 OUT(", /* %d */\n", tags_count);
Lev Walkin59964be2004-08-25 02:03:12 +00003097 } else {
Lev Walkin188ed2c2004-09-13 08:31:01 +00003098 OUT("0,\t/* No effective tags (pointer) */\n");
3099 OUT("0,\t/* No effective tags (count) */\n");
3100 }
3101
3102 if(all_tags_count && tv_mode == _TVM_DIFFERENT) {
Lev Walkin59b176e2005-11-26 11:25:14 +00003103 OUT("asn_DEF_%s_all_tags_%d,\n",
Lev Walkin21d00002005-03-04 08:48:53 +00003104 p, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00003105 OUT("sizeof(asn_DEF_%s_all_tags_%d)\n",
Lev Walkin21d00002005-03-04 08:48:53 +00003106 p, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00003107 OUT("\t/sizeof(asn_DEF_%s_all_tags_%d[0]), /* %d */\n",
Lev Walkin21d00002005-03-04 08:48:53 +00003108 p, expr->_type_unique_index, all_tags_count);
Lev Walkin188ed2c2004-09-13 08:31:01 +00003109 } else if(all_tags_count) {
Lev Walkin59b176e2005-11-26 11:25:14 +00003110 OUT("asn_DEF_%s_tags_%d,\t/* Same as above */\n",
Lev Walkin21d00002005-03-04 08:48:53 +00003111 p, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00003112 OUT("sizeof(asn_DEF_%s_tags_%d)\n",
Lev Walkin21d00002005-03-04 08:48:53 +00003113 p, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00003114 OUT("\t/sizeof(asn_DEF_%s_tags_%d[0]), /* %d */\n",
Lev Walkin21d00002005-03-04 08:48:53 +00003115 p, expr->_type_unique_index, all_tags_count);
Lev Walkin188ed2c2004-09-13 08:31:01 +00003116 } else {
3117 OUT("0,\t/* No tags (pointer) */\n");
3118 OUT("0,\t/* No tags (count) */\n");
Lev Walkin59964be2004-08-25 02:03:12 +00003119 }
3120
Lev Walkinb33425f2017-07-14 14:59:52 +04003121 if(arg->flags & A1C_GEN_OER) {
3122 if(expr->constraints
3123 || expr->expr_type == ASN_BASIC_ENUMERATED
3124 || expr->expr_type == ASN_CONSTR_CHOICE) {
3125 OUT("&asn_OER_type_%s_constr_%d,\n",
3126 p, expr->_type_unique_index);
3127 } else {
3128 OUT("0,\t/* No OER visible constraints */\n");
3129 }
3130 } else {
3131 OUT("0,\t/* No OER visible constraints */\n");
3132 }
3133
Lev Walkin59b176e2005-11-26 11:25:14 +00003134 if(arg->flags & A1C_GEN_PER) {
3135 if(expr->constraints
3136 || expr->expr_type == ASN_BASIC_ENUMERATED
3137 || expr->expr_type == ASN_CONSTR_CHOICE) {
Lev Walkin4b5dae32006-10-09 12:27:44 +00003138 OUT("&asn_PER_type_%s_constr_%d,\n",
Lev Walkin59b176e2005-11-26 11:25:14 +00003139 p, expr->_type_unique_index);
3140 } else {
3141 OUT("0,\t/* No PER visible constraints */\n");
3142 }
3143 } else {
3144 OUT("0,\t/* No PER visible constraints */\n");
3145 }
3146
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003147 if(elements_count ||
3148 ((expr->expr_type == A1TC_REFERENCE) &&
3149 (terminal->expr_type & ASN_CONSTR_MASK) &&
3150 expr_elements_count(arg, terminal))) {
3151
3152 if (expr->expr_type == A1TC_REFERENCE) {
3153 OUT("asn_MBR_%s_%d,\n", MKID(terminal), terminal->_type_unique_index);
3154
3155 if(terminal->expr_type == ASN_CONSTR_SEQUENCE_OF
3156 || terminal->expr_type == ASN_CONSTR_SET_OF) {
3157 OUT("%d,\t/* Single element */\n",
3158 expr_elements_count(arg, terminal));
3159 assert(expr_elements_count(arg, terminal) == 1);
3160 } else {
3161 OUT("%d,\t/* Elements count */\n",
3162 expr_elements_count(arg, terminal));
3163 }
Lev Walkin59964be2004-08-25 02:03:12 +00003164 } else {
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003165 OUT("asn_MBR_%s_%d,\n", p, expr->_type_unique_index);
3166
3167 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF
3168 || expr->expr_type == ASN_CONSTR_SET_OF) {
3169 OUT("%d,\t/* Single element */\n",
3170 elements_count);
3171 assert(elements_count == 1);
3172 } else {
3173 OUT("%d,\t/* Elements count */\n",
3174 elements_count);
3175 }
Lev Walkin59964be2004-08-25 02:03:12 +00003176 }
3177 } else {
Lev Walkin59964be2004-08-25 02:03:12 +00003178 if(expr_elements_count(arg, expr))
3179 OUT("0, 0,\t/* Defined elsewhere */\n");
3180 else
3181 OUT("0, 0,\t/* No members */\n");
3182 }
3183
3184 switch(spec) {
3185 case ETD_NO_SPECIFICS:
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003186 if ((expr->expr_type == A1TC_REFERENCE) &&
3187 ((terminal->expr_type & ASN_CONSTR_MASK) ||
3188 (terminal->expr_type == ASN_BASIC_ENUMERATED) ||
3189 ((terminal->expr_type == ASN_BASIC_INTEGER) &&
3190 (asn1c_type_fits_long(arg, terminal) == FL_FITS_UNSIGN)))) {
3191 OUT("&asn_SPC_%s_specs_%d\t/* Additional specs */\n", MKID(terminal), terminal->_type_unique_index);
3192 } else if ((expr->expr_type == ASN_TYPE_ANY) ||
3193 (expr->expr_type == ASN_BASIC_BIT_STRING) ||
3194 (expr->expr_type == ASN_STRING_BMPString) ||
3195 (expr->expr_type == ASN_BASIC_OCTET_STRING) ||
3196 (expr->expr_type == ASN_STRING_UniversalString)) {
3197 OUT("&asn_SPC_%s_specs\t/* Additional specs */\n", asn1c_type_name(arg, expr, TNF_SAFE));
3198 } else if ((expr->expr_type == A1TC_REFERENCE) &&
3199 ((terminal->expr_type == ASN_TYPE_ANY) ||
3200 (terminal->expr_type == ASN_BASIC_BIT_STRING) ||
3201 (terminal->expr_type == ASN_STRING_BMPString) ||
3202 (terminal->expr_type == ASN_BASIC_OCTET_STRING) ||
3203 (terminal->expr_type == ASN_STRING_UniversalString))) {
3204 OUT("&asn_SPC_%s_specs\t/* Additional specs */\n", asn1c_type_name(arg, terminal, TNF_SAFE));
3205 } else {
3206 OUT("0\t/* No specifics */\n");
3207 }
Lev Walkin59964be2004-08-25 02:03:12 +00003208 break;
3209 case ETD_HAS_SPECIFICS:
Lev Walkin59b176e2005-11-26 11:25:14 +00003210 OUT("&asn_SPC_%s_specs_%d\t/* Additional specs */\n",
Lev Walkin21d00002005-03-04 08:48:53 +00003211 p, expr->_type_unique_index);
Lev Walkin59964be2004-08-25 02:03:12 +00003212 }
Lev Walkin188ed2c2004-09-13 08:31:01 +00003213 INDENT(-1);
Lev Walkin59964be2004-08-25 02:03:12 +00003214 OUT("};\n");
3215 OUT("\n");
Lev Walkin97298782004-08-26 06:20:34 +00003216
3217 return 0;
Lev Walkin59964be2004-08-25 02:03:12 +00003218}
Lev Walkincc93b0f2004-09-10 09:18:20 +00003219
Lev Walkina9cc46e2004-09-22 16:06:28 +00003220static int
3221expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkind1bfea62005-11-08 03:06:16 +00003222 /*
3223 * X.680, 25.5, Table 5
3224 */
Lev Walkin59b176e2005-11-26 11:25:14 +00003225 switch(expr_get_type(arg, expr)) {
Lev Walkina9cc46e2004-09-22 16:06:28 +00003226 case ASN_BASIC_BOOLEAN:
3227 case ASN_BASIC_ENUMERATED:
3228 case ASN_BASIC_NULL:
3229 return 1;
Lev Walkind1bfea62005-11-08 03:06:16 +00003230 case ASN_CONSTR_CHOICE:
3231 return 2;
Lev Walkina9cc46e2004-09-22 16:06:28 +00003232 default:
3233 return 0;
3234 }
3235}
Lev Walkin801fabc2005-01-28 12:18:50 +00003236
3237static int
Lev Walkin0f5d74c2005-08-14 15:03:31 +00003238out_name_chain(arg_t *arg, enum onc_flags onc_flags) {
Lev Walkin801fabc2005-01-28 12:18:50 +00003239 asn1p_expr_t *expr = arg->expr;
3240 char *id;
3241
Lev Walkin0f5d74c2005-08-14 15:03:31 +00003242 if((arg->flags & A1C_COMPOUND_NAMES
3243 || onc_flags & ONC_force_compound_name)
Lev Walkin21d00002005-03-04 08:48:53 +00003244 && ((expr->expr_type & ASN_CONSTR_MASK)
3245 || expr->expr_type == ASN_BASIC_ENUMERATED
Lev Walkinb02a8832005-08-13 23:51:47 +00003246 || ((expr->expr_type == ASN_BASIC_INTEGER
3247 || expr->expr_type == ASN_BASIC_BIT_STRING)
Lev Walkin21d00002005-03-04 08:48:53 +00003248 && expr_elements_count(arg, expr))
3249 )
Bi-Ruei, Chiu94f0b642017-06-29 01:34:23 +08003250 && expr->parent_expr) {
3251
Lev Walkin801fabc2005-01-28 12:18:50 +00003252 arg_t tmparg = *arg;
3253
3254 tmparg.expr = expr->parent_expr;
Lev Walkin21d00002005-03-04 08:48:53 +00003255 if(0) tmparg.flags &= ~A1C_COMPOUND_NAMES;
3256
Lev Walkin0f5d74c2005-08-14 15:03:31 +00003257 out_name_chain(&tmparg, onc_flags);
Lev Walkin801fabc2005-01-28 12:18:50 +00003258
Bi-Ruei, Chiu94f0b642017-06-29 01:34:23 +08003259 if(expr->parent_expr->Identifier) OUT("__"); /* a separator between id components */
Lev Walkin21d00002005-03-04 08:48:53 +00003260
Lev Walkin801fabc2005-01-28 12:18:50 +00003261 /* Fall through */
3262 }
3263
Lev Walkin0f5d74c2005-08-14 15:03:31 +00003264 if(onc_flags & ONC_avoid_keywords)
Lev Walkina00d6b32006-03-21 03:40:38 +00003265 id = MKID_safe(expr);
Lev Walkin801fabc2005-01-28 12:18:50 +00003266 else
Lev Walkina00d6b32006-03-21 03:40:38 +00003267 id = MKID(expr);
Lev Walkin801fabc2005-01-28 12:18:50 +00003268 OUT("%s", id);
3269
3270 return 0;
3271}
Lev Walkinb85a8132005-08-18 13:38:19 +00003272
3273static int
3274emit_include_dependencies(arg_t *arg) {
3275 asn1p_expr_t *expr = arg->expr;
3276 asn1p_expr_t *memb;
3277
3278 /* Avoid recursive definitions. */
3279 TQ_FOR(memb, &(expr->members), next) {
3280 expr_break_recursion(arg, memb);
3281 }
3282
3283 TQ_FOR(memb, &(expr->members), next) {
3284
3285 if(memb->marker.flags & (EM_INDIRECT | EM_UNRECURSE)) {
3286 if(terminal_structable(arg, memb)) {
3287 int saved_target = arg->target->target;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08003288 if(saved_target != OT_FWD_DECLS) {
3289 REDIR(OT_FWD_DECLS);
3290 OUT("%s;\n",
3291 asn1c_type_name(arg, memb, TNF_RSAFE));
3292 }
Lev Walkinb85a8132005-08-18 13:38:19 +00003293 REDIR(saved_target);
3294 }
3295 }
3296
3297 if((!(memb->expr_type & ASN_CONSTR_MASK)
3298 && memb->expr_type > ASN_CONSTR_MASK)
3299 || memb->meta_type == AMT_TYPEREF) {
3300 if(memb->marker.flags & EM_UNRECURSE) {
3301 GEN_POSTINCLUDE(asn1c_type_name(arg,
3302 memb, TNF_INCLUDE));
3303 } else {
3304 GEN_INCLUDE(asn1c_type_name(arg,
3305 memb, TNF_INCLUDE));
3306 }
3307 }
3308 }
3309
3310 return 0;
3311}
3312
3313/*
3314 * Check if it is better to make this type indirectly accessed via
3315 * a pointer.
3316 * This may be the case for the following recursive definition:
3317 * Type ::= CHOICE { member Type };
3318 */
3319static int
3320expr_break_recursion(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkinb85a8132005-08-18 13:38:19 +00003321 int ret;
3322
3323 if(expr->marker.flags & EM_UNRECURSE)
3324 return 1; /* Already broken */
3325
Lev Walkinb85a8132005-08-18 13:38:19 +00003326 /* -findirect-choice compiles members of CHOICE as indirect pointers */
3327 if((arg->flags & A1C_INDIRECT_CHOICE)
3328 && arg->expr->expr_type == ASN_CONSTR_CHOICE
Lev Walkin59b176e2005-11-26 11:25:14 +00003329 && (expr_get_type(arg, expr) & ASN_CONSTR_MASK)
Lev Walkinb85a8132005-08-18 13:38:19 +00003330 ) {
3331 /* Break cross-reference */
3332 expr->marker.flags |= EM_INDIRECT | EM_UNRECURSE;
3333 return 1;
3334 }
3335
3336 if((expr->marker.flags & EM_INDIRECT)
3337 || arg->expr->expr_type == ASN_CONSTR_SET_OF
3338 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF) {
3339 if(terminal_structable(arg, expr)) {
3340 expr->marker.flags |= EM_UNRECURSE;
3341
3342 if(arg->expr->expr_type == ASN_CONSTR_SET_OF
3343 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF) {
3344 /* Don't put EM_INDIRECT even if recursion */
3345 return 1;
3346 }
3347
3348 /* Fall through */
3349 }
3350 }
3351
3352 /* Look for recursive back-references */
3353 ret = expr_defined_recursively(arg, expr);
3354 switch(ret) {
3355 case 2: /* Explicitly break the recursion */
3356 case 1: /* Use safer typing */
3357 expr->marker.flags |= EM_INDIRECT;
3358 expr->marker.flags |= EM_UNRECURSE;
3359 break;
3360 }
3361
3362 return 0;
3363}
3364
3365/*
3366 * Check if the type can be represented using simple `struct TYPE`.
3367 */
3368static asn1p_expr_t *
3369terminal_structable(arg_t *arg, asn1p_expr_t *expr) {
3370 asn1p_expr_t *terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
3371 if(terminal
3372 && !terminal->parent_expr
3373 && (terminal->expr_type & ASN_CONSTR_MASK)) {
3374 return terminal;
3375 }
3376 return 0;
3377}
3378
3379static int
3380asn1c_recurse(arg_t *arg, asn1p_expr_t *expr, int (*callback)(arg_t *arg, void *key), void *key) {
3381 arg_t tmp = *arg;
3382 int maxret = 0;
3383 int ret;
3384
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +08003385 if(expr->_mark & TM_RECURSION) return 0;
Lev Walkinb85a8132005-08-18 13:38:19 +00003386 expr->_mark |= TM_RECURSION;
3387
3388 /* Invoke callback for every type going into recursion */
3389 tmp.expr = expr;
3390 maxret = callback(&tmp, key);
3391 if(maxret <= 1) {
3392 /*
3393 * Recursively invoke myself and the callbacks.
3394 */
3395 TQ_FOR(tmp.expr, &(expr->members), next) {
3396 ret = asn1c_recurse(&tmp, tmp.expr, callback, key);
3397 if(ret > maxret)
3398 maxret = ret;
3399 if(maxret > 1) break;
3400 }
3401 }
3402
3403 expr->_mark &= ~TM_RECURSION;
3404 return maxret;
3405}
3406
3407static int
3408check_is_refer_to(arg_t *arg, void *key) {
3409 asn1p_expr_t *terminal = terminal_structable(arg, arg->expr);
3410 if(terminal == key) {
3411 if(arg->expr->marker.flags & EM_INDIRECT)
3412 return 1; /* This is almost safe indirection */
3413 return 2;
3414 } else if(terminal) {
3415 /* This might be N-step circular loop. Dive into it. */
3416 return asn1c_recurse(arg, terminal, check_is_refer_to, key);
3417 }
3418 return 0;
3419}
3420
3421/*
3422 * Check if the possibly inner expression defined recursively.
3423 */
3424static int
3425expr_defined_recursively(arg_t *arg, asn1p_expr_t *expr) {
3426 asn1p_expr_t *terminal;
3427 asn1p_expr_t *topmost;
3428
3429 /* If expression is top-level, there's no way it can be recursive. */
3430 if(expr->parent_expr == 0) return 0;
3431 if(expr->expr_type != A1TC_REFERENCE)
3432 return 0; /* Basic types are never recursive */
3433
3434 terminal = terminal_structable(arg, expr);
3435 if(!terminal) return 0; /* Terminal cannot be indirected */
3436
3437 /* Search for the parent container for the given expression */
3438 topmost = expr;
3439 while(topmost->parent_expr)
3440 topmost = topmost->parent_expr;
3441
3442 /* Look inside the terminal type if it mentions the parent expression */
3443 return asn1c_recurse(arg, terminal, check_is_refer_to, topmost);
3444}
Lev Walkin59b176e2005-11-26 11:25:14 +00003445
3446struct canonical_map_element {
3447 int eidx;
3448 asn1p_expr_t *expr;
3449};
3450static int compar_cameo(const void *ap, const void *bp);
3451static arg_t *cameo_arg;
3452static int *
3453compute_canonical_members_order(arg_t *arg, int el_count) {
3454 struct canonical_map_element *cmap;
3455 int *rmap;
3456 asn1p_expr_t *v;
3457 int eidx = 0;
3458 int ext_start = -1;
3459 int nextmax = -1;
3460 int already_sorted = 1;
3461
3462 cmap = calloc(el_count, sizeof *cmap);
3463 assert(cmap);
3464
3465 TQ_FOR(v, &(arg->expr->members), next) {
3466 if(v->expr_type != A1TC_EXTENSIBLE) {
3467 cmap[eidx].eidx = eidx;
3468 cmap[eidx].expr = v;
3469 eidx++;
3470 } else if(ext_start == -1)
3471 ext_start = eidx;
3472 }
3473
3474 cameo_arg = arg;
3475 if(ext_start == -1) {
3476 /* Sort the whole thing */
3477 qsort(cmap, el_count, sizeof(*cmap), compar_cameo);
3478 } else {
3479 /* Sort root and extensions independently */
3480 qsort(cmap, ext_start, sizeof(*cmap), compar_cameo);
3481 qsort(cmap + ext_start, el_count - ext_start,
3482 sizeof(*cmap), compar_cameo);
3483 }
3484
3485 /* move data back to a simpler map */
3486 rmap = calloc(el_count, sizeof *rmap);
3487 assert(rmap);
3488 for(eidx = 0; eidx < el_count; eidx++) {
3489 rmap[eidx] = cmap[eidx].eidx;
3490 if(rmap[eidx] <= nextmax)
3491 already_sorted = 0;
3492 else
3493 nextmax = rmap[eidx];
3494 }
3495 free(cmap);
3496
3497 if(already_sorted) { free(rmap); rmap = 0; }
3498 return rmap;
3499}
3500static int compar_cameo(const void *ap, const void *bp) {
3501 const struct canonical_map_element *a = (const void *)ap;
3502 const struct canonical_map_element *b = (const void *)bp;
3503 struct asn1p_type_tag_s atag, btag;
3504 arg_t *arg = cameo_arg;
3505
3506 if(asn1f_fetch_outmost_tag(arg->asn, a->expr->module, a->expr,
3507 &atag, AFT_IMAGINARY_ANY | AFT_CANON_CHOICE))
3508 return 1;
3509
3510 if(asn1f_fetch_outmost_tag(arg->asn, b->expr->module, b->expr,
3511 &btag, AFT_IMAGINARY_ANY | AFT_CANON_CHOICE))
3512 return -1;
3513
3514 if(atag.tag_class < btag.tag_class)
3515 return -1;
3516 if(atag.tag_class > btag.tag_class)
3517 return 1;
3518 if(atag.tag_value < btag.tag_value)
3519 return -1;
3520 if(atag.tag_value > btag.tag_value)
3521 return 1;
3522 return 0;
3523
3524}