blob: 539f79202a5e0374b856ee3ef531fd1737439b33 [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001/*
2 * Don't look into this file. First, because it's a mess, and second, because
3 * it's a brain of the compiler, and you don't wanna mess with brains do you? ;)
4 */
5#include "asn1c_internal.h"
6#include "asn1c_C.h"
Lev Walkin84cd58e2004-08-19 13:29:46 +00007#include "asn1c_constraint.h"
Lev Walkin59004fa2004-08-20 13:37:01 +00008#include "asn1c_out.h"
9#include "asn1c_misc.h"
Lev Walkinad0d6372017-08-08 02:02:42 -070010#include "asn1c_ioc.h"
Lev Walkinb46156d2017-09-05 02:53:05 -070011#include "asn1c_naming.h"
Lev Walkind8e07c52017-08-23 07:38:30 -070012#include <asn1print.h>
Lev Walkin59b176e2005-11-26 11:25:14 +000013#include <asn1fix_crange.h> /* constraint groker from libasn1fix */
14#include <asn1fix_export.h> /* other exportables from libasn1fix */
Lev Walkinda997b12017-08-04 01:38:41 -070015#include <asn1parser.h>
Lev Walkinf15320b2004-06-03 03:38:44 +000016
Lev Walkinfd171ef2004-06-06 07:20:17 +000017typedef struct tag2el_s {
18 struct asn1p_type_tag_s el_tag;
19 int el_no;
Lev Walkin38abe792004-06-14 13:09:45 +000020 int toff_first;
21 int toff_last;
Lev Walkinfd171ef2004-06-06 07:20:17 +000022 asn1p_expr_t *from_expr;
23} tag2el_t;
24
Lev Walkin33d5d3c2004-10-03 09:13:30 +000025typedef enum fte {
26 FTE_ALLTAGS,
27 FTE_CANONICAL_XER,
28} fte_e;
29static int _fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags);
30static int _add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags);
Lev Walkinfd171ef2004-06-06 07:20:17 +000031
Lev Walkin0f5d74c2005-08-14 15:03:31 +000032enum onc_flags {
33 ONC_noflags = 0x00,
34 ONC_avoid_keywords = 0x01,
35 ONC_force_compound_name = 0x02,
36};
37static int out_name_chain(arg_t *arg, enum onc_flags);
Lev Walkin9de6cd82017-08-10 05:47:46 -070038static int asn1c_lang_C_type_SEQUENCE_def(
39 arg_t *arg, asn1c_ioc_table_and_objset_t *);
Lev Walkinf15320b2004-06-03 03:38:44 +000040static int asn1c_lang_C_type_SET_def(arg_t *arg);
41static int asn1c_lang_C_type_CHOICE_def(arg_t *arg);
42static int asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of);
Lev Walkinf6853ce2017-08-11 00:50:27 -070043static int asn1c_lang_C_OpenType(arg_t *arg, asn1c_ioc_table_and_objset_t *opt_ioc, const char *column_name);
Lev Walkinc3e29402004-09-10 06:07:18 +000044static int _print_tag(arg_t *arg, struct asn1p_type_tag_s *tag_p);
Lev Walkin59b176e2005-11-26 11:25:14 +000045static int compute_extensions_start(asn1p_expr_t *expr);
Lev Walkinda9a3b82005-08-16 17:00:21 +000046static int expr_break_recursion(arg_t *arg, asn1p_expr_t *expr);
Lev Walkina9cc46e2004-09-22 16:06:28 +000047static int expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr);
Lev Walkin59964be2004-08-25 02:03:12 +000048static int expr_elements_count(arg_t *arg, asn1p_expr_t *expr);
Lev Walkinb9e98cb2017-08-02 12:53:44 -070049static int emit_single_member_OER_constraint_value(arg_t *arg, asn1cnst_range_t *range);
50static int emit_single_member_OER_constraint_size(arg_t *arg, asn1cnst_range_t *range);
51static int emit_single_member_PER_constraint(arg_t *arg, asn1cnst_range_t *range, int juscountvalues, const char *type);
Lev Walkin98eabc12017-07-19 08:51:11 +040052static int emit_member_OER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx);
Lev Walkin4b5dae32006-10-09 12:27:44 +000053static int emit_member_PER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx);
Lev Walkin9de6cd82017-08-10 05:47:46 -070054static int emit_member_table(arg_t *arg, asn1p_expr_t *expr,
55 asn1c_ioc_table_and_objset_t *);
Lev Walkin33d5d3c2004-10-03 09:13:30 +000056static int emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier);
Lev Walkinc8285712005-03-04 22:18:20 +000057static int emit_include_dependencies(arg_t *arg);
Lev Walkinb85a8132005-08-18 13:38:19 +000058static asn1p_expr_t *terminal_structable(arg_t *arg, asn1p_expr_t *expr);
59static int expr_defined_recursively(arg_t *arg, asn1p_expr_t *expr);
60static int asn1c_recurse(arg_t *arg, asn1p_expr_t *expr, int (*callback)(arg_t *arg, void *key), void *key);
Lev Walkin59b176e2005-11-26 11:25:14 +000061static asn1p_expr_type_e expr_get_type(arg_t *arg, asn1p_expr_t *expr);
62static int try_inline_default(arg_t *arg, asn1p_expr_t *expr, int out);
63static int *compute_canonical_members_order(arg_t *arg, int el_count);
Lev Walkinf15320b2004-06-03 03:38:44 +000064
Lev Walkin188ed2c2004-09-13 08:31:01 +000065enum tvm_compat {
66 _TVM_SAME = 0, /* tags and all_tags are same */
67 _TVM_SUBSET = 1, /* tags are subset of all_tags */
68 _TVM_DIFFERENT = 2, /* tags and all_tags are different */
69};
70static enum tvm_compat emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tc, int *atc);
71
Lev Walkin59964be2004-08-25 02:03:12 +000072enum etd_spec {
73 ETD_NO_SPECIFICS,
74 ETD_HAS_SPECIFICS
75};
Lev Walkin8de2ab22004-09-26 13:11:31 +000076static int emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, enum tvm_compat tv_mode, int tags_count, int all_tags_count, int elements_count, enum etd_spec);
Lev Walkin59964be2004-08-25 02:03:12 +000077
Lev Walkin59004fa2004-08-20 13:37:01 +000078#define C99_MODE (!(arg->flags & A1C_NO_C99))
Lev Walkinf15320b2004-06-03 03:38:44 +000079#define UNNAMED_UNIONS (arg->flags & A1C_UNNAMED_UNIONS)
Lev Walkindd32b592004-09-06 08:07:29 +000080#define HIDE_INNER_DEFS (arg->embed && !(arg->flags & A1C_ALL_DEFS_GLOBAL))
Lev Walkinf15320b2004-06-03 03:38:44 +000081
82#define PCTX_DEF INDENTED( \
83 OUT("\n"); \
84 OUT("/* Context for parsing across buffer boundaries */\n"); \
Lev Walkin05363a72004-09-29 13:16:40 +000085 OUT("asn_struct_ctx_t _asn_ctx;\n"));
Lev Walkinf15320b2004-06-03 03:38:44 +000086
Lev Walkinc8285712005-03-04 22:18:20 +000087
Lev Walkin3dcaafa2004-08-11 05:21:32 +000088#define DEPENDENCIES do { \
Lev Walkinc8285712005-03-04 22:18:20 +000089 emit_include_dependencies(arg); \
Lev Walkin3dcaafa2004-08-11 05:21:32 +000090 if(expr->expr_type == ASN_CONSTR_SET_OF) \
Lev Walkin22b5ed42006-09-13 02:51:20 +000091 GEN_INCLUDE_STD("asn_SET_OF"); \
Lev Walkin3dcaafa2004-08-11 05:21:32 +000092 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF) \
Lev Walkin22b5ed42006-09-13 02:51:20 +000093 GEN_INCLUDE_STD("asn_SEQUENCE_OF"); \
Lev Walkin3dcaafa2004-08-11 05:21:32 +000094} while(0)
Lev Walkinf15320b2004-06-03 03:38:44 +000095
Lev Walkincaf0d5a2005-03-04 23:48:19 +000096/* MKID_safe() without checking for reserved keywords */
Lev Walkina00d6b32006-03-21 03:40:38 +000097#define MKID(expr) (asn1c_make_identifier(0, expr, 0))
98#define MKID_safe(expr) (asn1c_make_identifier(AMI_CHECK_RESERVED, expr, 0))
Lev Walkinf15320b2004-06-03 03:38:44 +000099
100int
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000101asn1c_lang_C_type_REAL(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000102 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
103}
104
Lev Walkine0b56e02005-02-25 12:10:27 +0000105struct value2enum {
106 asn1c_integer_t value;
107 const char *name;
108 int idx;
109};
110static int compar_enumMap_byName(const void *ap, const void *bp) {
111 const struct value2enum *a = (const struct value2enum *)ap;
112 const struct value2enum *b = (const struct value2enum *)bp;
113 return strcmp(a->name, b->name);
114}
115static int compar_enumMap_byValue(const void *ap, const void *bp) {
116 const struct value2enum *a = (const struct value2enum *)ap;
117 const struct value2enum *b = (const struct value2enum *)bp;
118 if(a->value < b->value)
119 return -1;
120 else if(a->value == b->value)
121 return 0;
122 return 1;
123}
124
Lev Walkinf15320b2004-06-03 03:38:44 +0000125int
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000126asn1c_lang_C_type_common_INTEGER(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000127 asn1p_expr_t *expr = arg->expr;
128 asn1p_expr_t *v;
Lev Walkine0b56e02005-02-25 12:10:27 +0000129 int el_count = expr_elements_count(arg, expr);
130 struct value2enum *v2e;
Lev Walkin59b176e2005-11-26 11:25:14 +0000131 int map_extensions = (expr->expr_type == ASN_BASIC_INTEGER);
Lev Walkin414b0782005-08-13 23:30:24 +0000132 int eidx;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800133 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000134
Lev Walkina4f8e942017-10-08 19:28:20 -0700135 v2e = calloc(el_count + 1, sizeof(*v2e));
136 assert(v2e);
Lev Walkinf15320b2004-06-03 03:38:44 +0000137
Lev Walkine0b56e02005-02-25 12:10:27 +0000138 /*
Lev Walkin414b0782005-08-13 23:30:24 +0000139 * For all ENUMERATED types and for those INTEGER types which
140 * have identifiers, print out an enumeration table.
Lev Walkine0b56e02005-02-25 12:10:27 +0000141 */
Lev Walkin414b0782005-08-13 23:30:24 +0000142 if(expr->expr_type == ASN_BASIC_ENUMERATED || el_count) {
143 eidx = 0;
Lev Walkine0b56e02005-02-25 12:10:27 +0000144 REDIR(OT_DEPS);
Lev Walkinb46156d2017-09-05 02:53:05 -0700145 OUT("typedef %s {\n", c_name(arg).members_enum);
Lev Walkinf15320b2004-06-03 03:38:44 +0000146 TQ_FOR(v, &(expr->members), next) {
147 switch(v->expr_type) {
148 case A1TC_UNIVERVAL:
Lev Walkin21d00002005-03-04 08:48:53 +0000149 OUT("\t");
Lev Walkinb46156d2017-09-05 02:53:05 -0700150 OUT("%s", c_member_name(arg, v));
Lev Walkinda997b12017-08-04 01:38:41 -0700151 OUT("\t= %s%s\n",
152 asn1p_itoa(v->value->value.v_integer),
Lev Walkin21d00002005-03-04 08:48:53 +0000153 (eidx+1 < el_count) ? "," : "");
Lev Walkine0b56e02005-02-25 12:10:27 +0000154 v2e[eidx].name = v->Identifier;
155 v2e[eidx].value = v->value->value.v_integer;
156 eidx++;
Lev Walkinf15320b2004-06-03 03:38:44 +0000157 break;
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000158 case A1TC_EXTENSIBLE:
159 OUT("\t/*\n");
160 OUT("\t * Enumeration is extensible\n");
161 OUT("\t */\n");
Lev Walkin59b176e2005-11-26 11:25:14 +0000162 if(!map_extensions)
163 map_extensions = eidx + 1;
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000164 break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000165 default:
Lev Walkina4f8e942017-10-08 19:28:20 -0700166 free(v2e);
Lev Walkinf15320b2004-06-03 03:38:44 +0000167 return -1;
168 }
169 }
Lev Walkinb46156d2017-09-05 02:53:05 -0700170 OUT("} %s;\n", c_name(arg).members_name);
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 Walkina4f8e942017-10-08 19:28:20 -0700263 free(v2e);
Lev Walkinf15320b2004-06-03 03:38:44 +0000264 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
265}
266
267int
Lev Walkinb02a8832005-08-13 23:51:47 +0000268asn1c_lang_C_type_BIT_STRING(arg_t *arg) {
269 asn1p_expr_t *expr = arg->expr;
270 asn1p_expr_t *v;
271 int el_count = expr_elements_count(arg, expr);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800272 int saved_target = arg->target->target;
Lev Walkinb02a8832005-08-13 23:51:47 +0000273
274 if(el_count) {
Lev Walkin082cadc2005-08-14 02:18:27 +0000275 int eidx = 0;
Lev Walkinb02a8832005-08-13 23:51:47 +0000276 REDIR(OT_DEPS);
Lev Walkinb46156d2017-09-05 02:53:05 -0700277 OUT("typedef %s {\n", c_name(arg).members_enum);
Lev Walkinb02a8832005-08-13 23:51:47 +0000278 TQ_FOR(v, &(expr->members), next) {
Lev Walkin082cadc2005-08-14 02:18:27 +0000279 if(v->expr_type != A1TC_UNIVERVAL) {
Lev Walkinb02a8832005-08-13 23:51:47 +0000280 OUT("/* Unexpected BIT STRING element: %s */\n",
281 v->Identifier);
Lev Walkin082cadc2005-08-14 02:18:27 +0000282 continue;
Lev Walkinb02a8832005-08-13 23:51:47 +0000283 }
Lev Walkin0f8d4a42006-08-26 03:29:15 +0000284 eidx++;
Lev Walkin082cadc2005-08-14 02:18:27 +0000285 OUT("\t");
Lev Walkinb46156d2017-09-05 02:53:05 -0700286 OUT("%s", c_member_name(arg, v));
Lev Walkinda997b12017-08-04 01:38:41 -0700287 OUT("\t= %s%s\n",
288 asn1p_itoa(v->value->value.v_integer),
Lev Walkin082cadc2005-08-14 02:18:27 +0000289 (eidx < el_count) ? "," : "");
Lev Walkinb02a8832005-08-13 23:51:47 +0000290 }
Lev Walkinb46156d2017-09-05 02:53:05 -0700291 OUT("} %s;\n", c_name(arg).members_name);
Lev Walkinb02a8832005-08-13 23:51:47 +0000292 assert(eidx == el_count);
293 }
294
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800295 REDIR(saved_target);
296
Lev Walkinb02a8832005-08-13 23:51:47 +0000297 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
298}
299
Lev Walkinf6853ce2017-08-11 00:50:27 -0700300/*
301 * Check if it is a true open type. That is, type is taken from
302 * the Information Object Set driven constraints.
303 */
304static int
305is_open_type(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_objset_t *opt_ioc) {
306
307 (void)arg;
308
309 if(!opt_ioc) {
310 return 0;
311 }
312
313 if(expr->meta_type == AMT_TYPEREF
314 && expr->expr_type == A1TC_REFERENCE
315 && expr->reference->comp_count == 2
316 && expr->reference->components[1].lex_type
317 == RLT_AmpUppercase) {
Lev Walkind8e07c52017-08-23 07:38:30 -0700318 DEBUG("%s is a true open type", MKID(expr));
Lev Walkinf6853ce2017-08-11 00:50:27 -0700319 return 1;
320 }
321
322 return 0;
323}
324
Lev Walkinb02a8832005-08-13 23:51:47 +0000325int
Lev Walkinf15320b2004-06-03 03:38:44 +0000326asn1c_lang_C_type_SEQUENCE(arg_t *arg) {
327 asn1p_expr_t *expr = arg->expr;
328 asn1p_expr_t *v;
329 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800330 int saved_target = arg->target->target;
Lev Walkinad0d6372017-08-08 02:02:42 -0700331 asn1c_ioc_table_and_objset_t ioc_tao;
Lev Walkinf15320b2004-06-03 03:38:44 +0000332
333 DEPENDENCIES;
334
Lev Walkinad0d6372017-08-08 02:02:42 -0700335 ioc_tao = asn1c_get_ioc_table(arg);
336 if(ioc_tao.ioct) {
337 if(emit_ioc_table(arg, expr, ioc_tao)) {
338 return -1;
339 }
340 } else if(ioc_tao.fatal_error) {
Lev Walkinea6635b2017-08-06 23:23:04 -0700341 return -1;
342 }
343
Lev Walkinf15320b2004-06-03 03:38:44 +0000344 if(arg->embed) {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800345
346 /* Use _anonymous_type field to indicate it's called from
347 * asn1c_lang_C_type_SEx_OF() */
348 if (expr->_anonymous_type) {
349 REDIR(OT_FWD_DEFS);
350 OUT("typedef ");
351 }
Lev Walkinb46156d2017-09-05 02:53:05 -0700352 OUT("%s {\n", c_name(arg).full_name);
Lev Walkinf15320b2004-06-03 03:38:44 +0000353 } else {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800354 REDIR(OT_TYPE_DECLS);
Lev Walkinb46156d2017-09-05 02:53:05 -0700355 OUT("typedef %s {\n", c_name(arg).full_name);
Lev Walkinf15320b2004-06-03 03:38:44 +0000356 }
357
358 TQ_FOR(v, &(expr->members), next) {
Lev Walkinda9a3b82005-08-16 17:00:21 +0000359 if(v->expr_type == A1TC_EXTENSIBLE)
Lev Walkinf15320b2004-06-03 03:38:44 +0000360 if(comp_mode < 3) comp_mode++;
Lev Walkinda9a3b82005-08-16 17:00:21 +0000361 if(comp_mode == 1)
Lev Walkin59b176e2005-11-26 11:25:14 +0000362 v->marker.flags |= EM_OMITABLE | EM_INDIRECT;
363 try_inline_default(arg, v, 1);
Lev Walkinf6853ce2017-08-11 00:50:27 -0700364 if(is_open_type(arg, v, ioc_tao.ioct ? &ioc_tao : 0)) {
365 arg_t tmp_arg = *arg;
366 tmp_arg.embed++;
367 INDENT(+1);
368 tmp_arg.expr = v;
369 const char *column_name = v->reference->components[1].name;
370 if(asn1c_lang_C_OpenType(&tmp_arg, &ioc_tao, column_name)) {
371 return -1;
372 }
373 INDENT(-1);
374 tmp_arg.embed--;
375 if(v->expr_type != A1TC_EXTENSIBLE) OUT(";\n");
376 } else {
377 EMBED_WITH_IOCT(v, ioc_tao);
378 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000379 }
380
381 PCTX_DEF;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800382
383 if (arg->embed && expr->_anonymous_type) {
Lev Walkinb46156d2017-09-05 02:53:05 -0700384 OUT("} %s%s;\n", (expr->marker.flags & EM_INDIRECT)?"*":"",
385 c_name(arg).base_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800386
387 REDIR(saved_target);
388
Lev Walkinb46156d2017-09-05 02:53:05 -0700389 OUT("%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
390 c_name(arg).base_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800391 } else {
Lev Walkinb46156d2017-09-05 02:53:05 -0700392 OUT("} %s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
393 c_name(arg).short_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800394 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000395
Lev Walkin9de6cd82017-08-10 05:47:46 -0700396 return asn1c_lang_C_type_SEQUENCE_def(arg, ioc_tao.ioct ? &ioc_tao : 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000397}
398
Lev Walkinade508c2017-08-23 10:19:30 -0700399static void
400emit_tag2member_reference(arg_t *arg, asn1p_expr_t *expr,
401 unsigned tag2el_count) {
402 if(tag2el_count) {
403 if(C99_MODE) OUT(".tag2el = ");
404 OUT("asn_MAP_%s_tag2el_%d,\n", MKID(expr), expr->_type_unique_index);
405 if(C99_MODE) OUT(".tag2el_count = ");
406 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
407 } else {
408 OUT("0,\t/* No top level tags */\n");
409 OUT("0,\t/* No tags in the map */\n");
410 }
411}
412
Lev Walkinf15320b2004-06-03 03:38:44 +0000413static int
Lev Walkin9de6cd82017-08-10 05:47:46 -0700414asn1c_lang_C_type_SEQUENCE_def(arg_t *arg, asn1c_ioc_table_and_objset_t *opt_ioc) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000415 asn1p_expr_t *expr = arg->expr;
416 asn1p_expr_t *v;
417 int elements; /* Number of elements */
Lev Walkin33af5c32007-06-23 20:05:49 +0000418 int ext_start = -2;
419 int ext_stop = -2;
Lev Walkinfd171ef2004-06-06 07:20:17 +0000420 tag2el_t *tag2el = NULL;
421 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000422 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000423 int all_tags_count;
424 enum tvm_compat tv_mode;
Lev Walkin59b176e2005-11-26 11:25:14 +0000425 int roms_count; /* Root optional members */
426 int aoms_count; /* Additions optional members */
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800427 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000428
Lev Walkinfd171ef2004-06-06 07:20:17 +0000429 /*
430 * Fetch every inner tag from the tag to elements map.
431 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000432 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
Lev Walkinfd171ef2004-06-06 07:20:17 +0000433 if(tag2el) free(tag2el);
434 return -1;
435 }
436
Lev Walkin22b5ed42006-09-13 02:51:20 +0000437 GEN_INCLUDE_STD("constr_SEQUENCE");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000438 if(!arg->embed)
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800439 GEN_DECLARE("SEQUENCE", expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000440
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000441 REDIR(OT_STAT_DEFS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000442
443 /*
Lev Walkin59b176e2005-11-26 11:25:14 +0000444 * Print out the table according to which parsing is performed.
Lev Walkinf15320b2004-06-03 03:38:44 +0000445 */
Lev Walkina9cc46e2004-09-22 16:06:28 +0000446 if(expr_elements_count(arg, expr)) {
447 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Lev Walkinf15320b2004-06-03 03:38:44 +0000448
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800449 if(!(expr->_type_referenced)) OUT("static ");
450 OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -0700451 c_name(arg).part_name, expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000452
453 elements = 0;
Lev Walkin59b176e2005-11-26 11:25:14 +0000454 roms_count = 0;
455 aoms_count = 0;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000456 INDENTED(TQ_FOR(v, &(expr->members), next) {
457 if(v->expr_type == A1TC_EXTENSIBLE) {
458 if((++comp_mode) == 1)
459 ext_start = elements - 1;
460 else
461 ext_stop = elements - 1;
462 continue;
463 }
Lev Walkin59b176e2005-11-26 11:25:14 +0000464 if(v->marker.flags & EM_OMITABLE)
465 comp_mode == 1 ? ++aoms_count : ++roms_count;
Lev Walkind8e07c52017-08-23 07:38:30 -0700466 if(emit_member_table(arg, v, opt_ioc) < 0)
467 return -1;
Lev Walkinda9a3b82005-08-16 17:00:21 +0000468 elements++;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000469 });
470 OUT("};\n");
Lev Walkin59b176e2005-11-26 11:25:14 +0000471
Lev Walkin3c5d9412017-07-24 01:49:24 +0400472 if((roms_count + aoms_count) && (arg->flags & (A1C_GEN_OER|A1C_GEN_PER))) {
Lev Walkin59b176e2005-11-26 11:25:14 +0000473 int elm = 0;
474 int comma = 0;
475 comp_mode = 0;
Wim Lewisfb6344e2014-07-28 12:16:01 -0700476 OUT("static const int asn_MAP_%s_oms_%d[] = {",
Lev Walkina00d6b32006-03-21 03:40:38 +0000477 MKID(expr),
Lev Walkin59b176e2005-11-26 11:25:14 +0000478 expr->_type_unique_index);
479 TQ_FOR(v, &(expr->members), next) {
480 if(v->expr_type == A1TC_EXTENSIBLE) {
481 ++comp_mode;
482 continue;
483 }
484 if((v->marker.flags & EM_OMITABLE)
485 && comp_mode != 1) {
486 if(!comma) comma++;
487 else OUT(",");
488 OUT(" %d", elm);
489 }
490 ++elm;
491 }
492 elm = 0;
493 comp_mode = 0;
494 TQ_FOR(v, &(expr->members), next) {
495 if(v->expr_type == A1TC_EXTENSIBLE) {
496 ++comp_mode;
497 continue;
498 }
499 if((v->marker.flags & EM_OMITABLE)
500 && comp_mode == 1) {
501 if(!comma) comma++;
502 else OUT(",");
503 OUT(" %d", elm);
504 }
505 ++elm;
506 }
507 OUT(" };\n");
Lev Walkinea6635b2017-08-06 23:23:04 -0700508 if(roms_count > 65536) {
Lev Walkin59b176e2005-11-26 11:25:14 +0000509 FATAL("Too many optional elements in %s "
510 "at line %d!",
511 arg->expr->Identifier,
512 arg->expr->_lineno);
Lev Walkinea6635b2017-08-06 23:23:04 -0700513 return -1;
514 }
Lev Walkin59b176e2005-11-26 11:25:14 +0000515 } else {
516 roms_count = 0;
517 aoms_count = 0;
518 }
Lev Walkina9cc46e2004-09-22 16:06:28 +0000519 } else {
520 elements = 0;
Lev Walkin59b176e2005-11-26 11:25:14 +0000521 roms_count = 0;
522 aoms_count = 0;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000523 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000524
Lev Walkin27ea3802004-06-28 21:13:46 +0000525 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000526 * Print out asn_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +0000527 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000528 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000529
Lev Walkinfd171ef2004-06-06 07:20:17 +0000530 /*
531 * Tags to elements map.
532 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000533 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
Lev Walkinfd171ef2004-06-06 07:20:17 +0000534
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800535 if(!(expr->_type_referenced)) OUT("static ");
536 OUT("asn_SEQUENCE_specifics_t asn_SPC_%s_specs_%d = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000537 MKID(expr), expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +0000538 INDENT(+1);
Lev Walkinb46156d2017-09-05 02:53:05 -0700539 OUT("sizeof(%s),\n", c_name(arg).full_name);
540 OUT("offsetof(%s, _asn_ctx),\n", c_name(arg).full_name);
Lev Walkinade508c2017-08-23 10:19:30 -0700541 emit_tag2member_reference(arg, expr, tag2el_count);
Lev Walkin59b176e2005-11-26 11:25:14 +0000542 if(roms_count + aoms_count) {
543 OUT("asn_MAP_%s_oms_%d,\t/* Optional members */\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000544 MKID(expr), expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +0000545 OUT("%d, %d,\t/* Root/Additions */\n", roms_count, aoms_count);
546 } else {
547 OUT("0, 0, 0,\t/* Optional elements (not needed) */\n");
548 }
549 OUT("%d,\t/* Start extensions */\n",
Lev Walkin33af5c32007-06-23 20:05:49 +0000550 ext_start<0 ? -1 : ext_start);
Lev Walkin59b176e2005-11-26 11:25:14 +0000551 OUT("%d\t/* Stop extensions */\n",
Lev Walkin33af5c32007-06-23 20:05:49 +0000552 (ext_stop<ext_start)?elements+1:(ext_stop<0?-1:ext_stop));
Lev Walkin59b176e2005-11-26 11:25:14 +0000553 INDENT(-1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000554 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000555
556 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000557 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +0000558 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000559 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
Lev Walkin8de2ab22004-09-26 13:11:31 +0000560 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000561
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800562 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +0000563
Bi-Ruei, Chiu12021b52016-11-04 11:59:45 +0800564 if(tag2el) free(tag2el);
565
Lev Walkinf15320b2004-06-03 03:38:44 +0000566 return 0;
Lev Walkinb0b33412005-01-17 11:57:48 +0000567} /* _SEQUENCE_def() */
Lev Walkinf15320b2004-06-03 03:38:44 +0000568
569int
Lev Walkinf15320b2004-06-03 03:38:44 +0000570asn1c_lang_C_type_SET(arg_t *arg) {
571 asn1p_expr_t *expr = arg->expr;
572 asn1p_expr_t *v;
573 long mcount;
Lev Walkinb46156d2017-09-05 02:53:05 -0700574 const char *id;
Lev Walkinf15320b2004-06-03 03:38:44 +0000575 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800576 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000577
578 DEPENDENCIES;
579
580 REDIR(OT_DEPS);
581
582 OUT("\n");
583 OUT("/*\n");
584 OUT(" * Method of determining the components presence\n");
585 OUT(" */\n");
586 mcount = 0;
Lev Walkinb46156d2017-09-05 02:53:05 -0700587 OUT("typedef %s {\n", c_name(arg).presence_enum);
Lev Walkinf15320b2004-06-03 03:38:44 +0000588 TQ_FOR(v, &(expr->members), next) {
589 if(v->expr_type == A1TC_EXTENSIBLE) continue;
590 INDENTED(
Lev Walkinb46156d2017-09-05 02:53:05 -0700591 OUT("%s,", c_presence_name(arg, v));
592 OUT("\t/* Member %s is present */\n", MKID(v));
Lev Walkinf15320b2004-06-03 03:38:44 +0000593 );
594 mcount++;
595 }
Lev Walkinb46156d2017-09-05 02:53:05 -0700596 OUT("} %s;\n", c_name(arg).presence_name);
Lev Walkinf15320b2004-06-03 03:38:44 +0000597
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800598 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +0000599
600 if(arg->embed) {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800601 if (expr->_anonymous_type) {
602 REDIR(OT_FWD_DEFS);
603 OUT("typedef ");
604 }
Lev Walkinb46156d2017-09-05 02:53:05 -0700605 OUT("%s {\n", c_name(arg).full_name);
Lev Walkinf15320b2004-06-03 03:38:44 +0000606 } else {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800607 REDIR(OT_TYPE_DECLS);
Lev Walkinb46156d2017-09-05 02:53:05 -0700608 OUT("typedef %s {\n", c_name(arg).full_name);
Lev Walkinf15320b2004-06-03 03:38:44 +0000609 }
610
611 TQ_FOR(v, &(expr->members), next) {
Lev Walkin59b176e2005-11-26 11:25:14 +0000612 if(v->expr_type == A1TC_EXTENSIBLE)
Lev Walkinf15320b2004-06-03 03:38:44 +0000613 if(comp_mode < 3) comp_mode++;
Lev Walkinda9a3b82005-08-16 17:00:21 +0000614 if(comp_mode == 1)
Lev Walkin59b176e2005-11-26 11:25:14 +0000615 v->marker.flags |= EM_OMITABLE | EM_INDIRECT;
616 try_inline_default(arg, v, 1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000617 EMBED(v);
618 }
619
620 INDENTED(
Lev Walkina00d6b32006-03-21 03:40:38 +0000621 id = MKID(expr);
Lev Walkinf15320b2004-06-03 03:38:44 +0000622 OUT("\n");
623 OUT("/* Presence bitmask: ASN_SET_ISPRESENT(p%s, %s_PR_x) */\n",
624 id, id);
625 OUT("unsigned int _presence_map\n");
626 OUT("\t[((%ld+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))];\n", mcount);
627 );
628
629 PCTX_DEF;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800630
631 if (arg->embed && expr->_anonymous_type) {
Lev Walkinb46156d2017-09-05 02:53:05 -0700632 OUT("} %s%s;\n", (expr->marker.flags & EM_INDIRECT)?"*":"",
633 c_name(arg).base_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800634
635 REDIR(saved_target);
636
Lev Walkinb46156d2017-09-05 02:53:05 -0700637 OUT("%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
638 c_name(arg).base_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800639 } else {
Lev Walkinb46156d2017-09-05 02:53:05 -0700640 OUT("} %s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
641 c_name(arg).short_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800642 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000643
644 return asn1c_lang_C_type_SET_def(arg);
645}
646
Lev Walkinf15320b2004-06-03 03:38:44 +0000647static int
648asn1c_lang_C_type_SET_def(arg_t *arg) {
649 asn1p_expr_t *expr = arg->expr;
650 asn1p_expr_t *v;
651 int elements;
Lev Walkinf15320b2004-06-03 03:38:44 +0000652 tag2el_t *tag2el = NULL;
653 int tag2el_count = 0;
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000654 tag2el_t *tag2el_cxer = NULL;
655 int tag2el_cxer_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000656 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000657 int all_tags_count;
658 enum tvm_compat tv_mode;
Lev Walkinb46156d2017-09-05 02:53:05 -0700659 const char *p;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800660 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000661
662 /*
663 * Fetch every inner tag from the tag to elements map.
664 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000665 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000666 if(tag2el) free(tag2el);
667 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000668 }
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000669 if(_fill_tag2el_map(arg, &tag2el_cxer, &tag2el_cxer_count, -1, FTE_CANONICAL_XER)) {
670 if(tag2el) free(tag2el);
671 if(tag2el_cxer) free(tag2el_cxer);
672 return -1;
673 }
674 if(tag2el_cxer_count == tag2el_count
675 && memcmp(tag2el, tag2el_cxer, tag2el_count) == 0) {
676 free(tag2el_cxer);
677 tag2el_cxer = 0;
678 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000679
Lev Walkin22b5ed42006-09-13 02:51:20 +0000680 GEN_INCLUDE_STD("constr_SET");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000681 if(!arg->embed)
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800682 GEN_DECLARE("SET", expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000683
684 REDIR(OT_STAT_DEFS);
685
Lev Walkinf15320b2004-06-03 03:38:44 +0000686 /*
Lev Walkin59b176e2005-11-26 11:25:14 +0000687 * Print out the table according to which parsing is performed.
Lev Walkinf15320b2004-06-03 03:38:44 +0000688 */
Lev Walkina9cc46e2004-09-22 16:06:28 +0000689 if(expr_elements_count(arg, expr)) {
690 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Lev Walkinf15320b2004-06-03 03:38:44 +0000691
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800692 if(!(expr->_type_referenced)) OUT("static ");
693 OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -0700694 c_name(arg).part_name, expr->_type_unique_index);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800695
Lev Walkina9cc46e2004-09-22 16:06:28 +0000696 elements = 0;
697 INDENTED(TQ_FOR(v, &(expr->members), next) {
698 if(v->expr_type == A1TC_EXTENSIBLE) {
699 if(comp_mode < 3) comp_mode++;
700 } else {
Lev Walkin9de6cd82017-08-10 05:47:46 -0700701 emit_member_table(arg, v, NULL);
Lev Walkinda9a3b82005-08-16 17:00:21 +0000702 elements++;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000703 }
704 });
705 OUT("};\n");
706 } else {
707 elements = 0;
708 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000709
Lev Walkin27ea3802004-06-28 21:13:46 +0000710 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000711 * Print out asn_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +0000712 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000713 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000714
715 /*
716 * Tags to elements map.
717 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000718 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
719 if(tag2el_cxer)
720 emit_tag2member_map(arg, tag2el_cxer, tag2el_cxer_count, "_cxer");
Lev Walkinf15320b2004-06-03 03:38:44 +0000721
722 /*
723 * Emit a map of mandatory elements.
724 */
Wim Lewisfb6344e2014-07-28 12:16:01 -0700725 OUT("static const uint8_t asn_MAP_%s_mmap_%d",
Lev Walkina00d6b32006-03-21 03:40:38 +0000726 MKID(expr), expr->_type_unique_index);
727 p = MKID_safe(expr);
Lev Walkinf15320b2004-06-03 03:38:44 +0000728 OUT("[(%d + (8 * sizeof(unsigned int)) - 1) / 8]", elements);
Lev Walkin21d00002005-03-04 08:48:53 +0000729 OUT(" = {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000730 INDENTED(
731 if(elements) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000732 int el = 0;
733 TQ_FOR(v, &(expr->members), next) {
734 if(v->expr_type == A1TC_EXTENSIBLE) continue;
Lev Walkinac760bf2005-10-05 08:59:03 +0000735 if(el) {
736 if((el % 8) == 0)
737 OUT(",\n");
738 else
739 OUT(" | ");
Lev Walkinf15320b2004-06-03 03:38:44 +0000740 }
Lev Walkincc93b0f2004-09-10 09:18:20 +0000741 OUT("(%d << %d)",
Lev Walkinb85a8132005-08-18 13:38:19 +0000742 (v->marker.flags & EM_OMITABLE) != EM_OMITABLE,
Lev Walkincc93b0f2004-09-10 09:18:20 +0000743 7 - (el % 8));
Lev Walkinf15320b2004-06-03 03:38:44 +0000744 el++;
745 }
746 } else {
747 OUT("0");
748 }
749 );
750 OUT("\n");
751 OUT("};\n");
752
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800753 if(!(expr->_type_referenced)) OUT("static \n");
754 OUT("asn_SET_specifics_t asn_SPC_%s_specs_%d = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000755 MKID(expr), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +0000756 INDENTED(
Lev Walkinb46156d2017-09-05 02:53:05 -0700757 OUT("sizeof(%s),\n", c_name(arg).full_name);
758 OUT("offsetof(%s, _asn_ctx),\n", c_name(arg).full_name);
759 OUT("offsetof(%s, _presence_map),\n", c_name(arg).full_name);
Lev Walkinade508c2017-08-23 10:19:30 -0700760 emit_tag2member_reference(arg, expr, tag2el_count);
Lev Walkina00d6b32006-03-21 03:40:38 +0000761 p = MKID(expr);
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000762 if(tag2el_cxer)
Lev Walkin59b176e2005-11-26 11:25:14 +0000763 OUT("asn_MAP_%s_tag2el_cxer_%d,\n",
Lev Walkin21d00002005-03-04 08:48:53 +0000764 p, expr->_type_unique_index);
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000765 else
Lev Walkin59b176e2005-11-26 11:25:14 +0000766 OUT("asn_MAP_%s_tag2el_%d,\t/* Same as above */\n",
Lev Walkin21d00002005-03-04 08:48:53 +0000767 p, expr->_type_unique_index);
768 OUT("%d,\t/* Count of tags in the CXER map */\n",
769 tag2el_cxer_count);
Lev Walkin35631482004-07-01 00:52:50 +0000770 OUT("%d,\t/* Whether extensible */\n",
Lev Walkin59b176e2005-11-26 11:25:14 +0000771 compute_extensions_start(expr) == -1 ? 0 : 1);
Lev Walkin46ef3f32017-07-06 08:47:53 -0700772 OUT("(const unsigned int *)asn_MAP_%s_mmap_%d\t/* Mandatory elements map */\n",
Lev Walkin21d00002005-03-04 08:48:53 +0000773 p, expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +0000774 );
775 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000776
777 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000778 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +0000779 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000780 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
Lev Walkin8de2ab22004-09-26 13:11:31 +0000781 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000782
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800783 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +0000784
Bi-Ruei, Chiu12021b52016-11-04 11:59:45 +0800785 if (tag2el) free(tag2el);
786 if (tag2el_cxer) free(tag2el_cxer);
787
Lev Walkinf15320b2004-06-03 03:38:44 +0000788 return 0;
Lev Walkinb0b33412005-01-17 11:57:48 +0000789} /* _SET_def() */
Lev Walkinf15320b2004-06-03 03:38:44 +0000790
791int
Lev Walkin08079b02004-08-22 03:25:24 +0000792asn1c_lang_C_type_SEx_OF(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000793 asn1p_expr_t *expr = arg->expr;
Lev Walkinc8285712005-03-04 22:18:20 +0000794 asn1p_expr_t *memb = TQ_FIRST(&expr->members);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800795 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000796
797 DEPENDENCIES;
798
799 if(arg->embed) {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800800 if (expr->_anonymous_type) {
801 REDIR(OT_FWD_DEFS);
802 OUT("typedef ");
803 }
Lev Walkinb46156d2017-09-05 02:53:05 -0700804 OUT("%s {\n", c_name(arg).full_name);
Lev Walkinf15320b2004-06-03 03:38:44 +0000805 } else {
Lev Walkinb46156d2017-09-05 02:53:05 -0700806 OUT("typedef %s {\n", c_name(arg).full_name);
Lev Walkinf15320b2004-06-03 03:38:44 +0000807 }
808
Lev Walkin08079b02004-08-22 03:25:24 +0000809 INDENT(+1);
810 OUT("A_%s_OF(",
811 (arg->expr->expr_type == ASN_CONSTR_SET_OF)
812 ? "SET" : "SEQUENCE");
Lev Walkinda9a3b82005-08-16 17:00:21 +0000813
814 /*
815 * README README
816 * The implementation of the A_SET_OF() macro is already indirect.
817 */
818 memb->marker.flags |= EM_INDIRECT;
819
Lev Walkine0b56e02005-02-25 12:10:27 +0000820 if(memb->expr_type & ASN_CONSTR_MASK
821 || ((memb->expr_type == ASN_BASIC_ENUMERATED
Lev Walkin8ecf9db2005-03-03 21:28:12 +0000822 || (0 /* -- prohibited by X.693:8.3.4 */
823 && memb->expr_type == ASN_BASIC_INTEGER))
824 && expr_elements_count(arg, memb))) {
Lev Walkin08079b02004-08-22 03:25:24 +0000825 arg_t tmp;
Bi-Ruei, Chiu59b1bc82017-09-19 16:30:05 +0800826 asn1p_expr_t *tmp_memb = memb;
827 enum asn1p_expr_marker_e flags = memb->marker.flags;
Lev Walkin08079b02004-08-22 03:25:24 +0000828 arg->embed++;
829 tmp = *arg;
Bi-Ruei, Chiu59b1bc82017-09-19 16:30:05 +0800830 tmp.expr = tmp_memb;
831 tmp_memb->marker.flags &= ~EM_INDIRECT;
832 tmp_memb->_anonymous_type = 1;
833 if(tmp_memb->Identifier == 0) {
834 tmp_memb->Identifier = strdup("Member");
Lev Walkin21d00002005-03-04 08:48:53 +0000835 if(0)
Bi-Ruei, Chiu59b1bc82017-09-19 16:30:05 +0800836 tmp_memb->Identifier = strdup(
Lev Walkina9cc46e2004-09-22 16:06:28 +0000837 asn1c_make_identifier(0,
Lev Walkina00d6b32006-03-21 03:40:38 +0000838 expr, "Member", 0));
Bi-Ruei, Chiu59b1bc82017-09-19 16:30:05 +0800839 assert(tmp_memb->Identifier);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000840 }
Lev Walkin9de6cd82017-08-10 05:47:46 -0700841 tmp.default_cb(&tmp, NULL);
Bi-Ruei, Chiu59b1bc82017-09-19 16:30:05 +0800842 tmp_memb->marker.flags = flags;
Lev Walkin08079b02004-08-22 03:25:24 +0000843 arg->embed--;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800844 assert(arg->target->target == OT_TYPE_DECLS ||
845 arg->target->target == OT_FWD_DEFS);
Lev Walkin08079b02004-08-22 03:25:24 +0000846 } else {
Lev Walkinfe7f6ec2005-03-04 22:38:22 +0000847 OUT("%s", asn1c_type_name(arg, memb,
848 (memb->marker.flags & EM_UNRECURSE)
849 ? TNF_RSAFE : TNF_CTYPE));
Lev Walkinf15320b2004-06-03 03:38:44 +0000850 }
Lev Walkinda9a3b82005-08-16 17:00:21 +0000851 /* README README (above) */
852 if(0 && (memb->marker.flags & EM_INDIRECT))
853 OUT(" *");
Lev Walkin08079b02004-08-22 03:25:24 +0000854 OUT(") list;\n");
855 INDENT(-1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000856
857 PCTX_DEF;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800858
859 if (arg->embed && expr->_anonymous_type) {
Lev Walkinb46156d2017-09-05 02:53:05 -0700860 OUT("} %s%s;\n", (expr->marker.flags & EM_INDIRECT)?"*":"",
861 c_name(arg).base_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800862
863 REDIR(saved_target);
864
Lev Walkinb46156d2017-09-05 02:53:05 -0700865 OUT("%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
866 c_name(arg).base_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800867 } else {
Lev Walkinb46156d2017-09-05 02:53:05 -0700868 OUT("} %s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
869 c_name(arg).short_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800870 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000871
872 /*
Lev Walkin08079b02004-08-22 03:25:24 +0000873 * SET OF/SEQUENCE OF definition
Lev Walkinf15320b2004-06-03 03:38:44 +0000874 */
Lev Walkin08079b02004-08-22 03:25:24 +0000875 return asn1c_lang_C_type_SEx_OF_def(arg,
876 (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF));
Lev Walkinf15320b2004-06-03 03:38:44 +0000877}
878
879static int
880asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
881 asn1p_expr_t *expr = arg->expr;
882 asn1p_expr_t *v;
Lev Walkin64399722004-08-11 07:17:22 +0000883 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000884 int all_tags_count;
885 enum tvm_compat tv_mode;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800886 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000887
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000888 /*
Lev Walkin59b176e2005-11-26 11:25:14 +0000889 * Print out the table according to which parsing is performed.
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000890 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000891 if(seq_of) {
Lev Walkin22b5ed42006-09-13 02:51:20 +0000892 GEN_INCLUDE_STD("constr_SEQUENCE_OF");
Lev Walkinf15320b2004-06-03 03:38:44 +0000893 } else {
Lev Walkin22b5ed42006-09-13 02:51:20 +0000894 GEN_INCLUDE_STD("constr_SET_OF");
Lev Walkinf15320b2004-06-03 03:38:44 +0000895 }
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000896 if(!arg->embed)
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800897 GEN_DECLARE("SET_OF", expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000898
899 REDIR(OT_STAT_DEFS);
900
901 /*
Lev Walkin59b176e2005-11-26 11:25:14 +0000902 * Print out the table according to which parsing is performed.
Lev Walkinf15320b2004-06-03 03:38:44 +0000903 */
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800904 if(!(expr->_type_referenced)) OUT("static ");
905 OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -0700906 c_name(arg).part_name, expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000907 INDENT(+1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000908 v = TQ_FIRST(&(expr->members));
Lev Walkina9cc46e2004-09-22 16:06:28 +0000909 if(!v->Identifier) {
Lev Walkin152a91e2005-02-14 20:41:29 +0000910 v->Identifier = strdup("Member");
Lev Walkina9cc46e2004-09-22 16:06:28 +0000911 assert(v->Identifier);
912 }
913 v->_anonymous_type = 1;
914 arg->embed++;
Lev Walkin9de6cd82017-08-10 05:47:46 -0700915 emit_member_table(arg, v, NULL);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000916 arg->embed--;
Bi-Ruei, Chiu9b780832016-11-07 22:19:10 +0800917 free(v->Identifier);
918 v->Identifier = (char *)NULL;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000919 INDENT(-1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000920 OUT("};\n");
921
Lev Walkin27ea3802004-06-28 21:13:46 +0000922 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000923 * Print out asn_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +0000924 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000925 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000926
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +0800927 if(!(expr->_type_referenced)) OUT("static ");
928 OUT("asn_SET_OF_specifics_t asn_SPC_%s_specs_%d = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000929 MKID(expr), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +0000930 INDENTED(
Lev Walkinb46156d2017-09-05 02:53:05 -0700931 OUT("sizeof(%s),\n", c_name(arg).full_name);
932 OUT("offsetof(%s, _asn_ctx),\n", c_name(arg).full_name);
Lev Walkind1bfea62005-11-08 03:06:16 +0000933 {
934 int as_xvl = expr_as_xmlvaluelist(arg, v);
935 OUT("%d,\t/* XER encoding is %s */\n",
936 as_xvl,
937 as_xvl ? "XMLValueList" : "XMLDelimitedItemList");
938 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000939 );
940 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000941
942 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000943 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +0000944 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000945 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, 1,
Lev Walkin8de2ab22004-09-26 13:11:31 +0000946 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000947
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800948 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +0000949
950 return 0;
Lev Walkinb0b33412005-01-17 11:57:48 +0000951} /* _SEx_OF_def() */
Lev Walkinf15320b2004-06-03 03:38:44 +0000952
953int
954asn1c_lang_C_type_CHOICE(arg_t *arg) {
955 asn1p_expr_t *expr = arg->expr;
956 asn1p_expr_t *v;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800957 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +0000958
959 DEPENDENCIES;
960
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000961 REDIR(OT_DEPS);
962
Lev Walkinb46156d2017-09-05 02:53:05 -0700963 OUT("typedef %s {\n", c_name(arg).presence_enum);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000964 INDENTED(
Lev Walkin11380fb2006-08-18 01:38:40 +0000965 int skipComma = 1;
Lev Walkinb46156d2017-09-05 02:53:05 -0700966 OUT("%s,\t/* No components present */\n", c_presence_name(arg, 0));
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000967 TQ_FOR(v, &(expr->members), next) {
Lev Walkin11380fb2006-08-18 01:38:40 +0000968 if(skipComma) skipComma = 0;
johvik792216e2017-04-11 10:42:21 +0200969 else if (v->expr_type == A1TC_EXTENSIBLE && !TQ_NEXT(v, next)) OUT("\n");
Lev Walkin1dc85292006-08-18 01:32:26 +0000970 else OUT(",\n");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000971 if(v->expr_type == A1TC_EXTENSIBLE) {
972 OUT("/* Extensions may appear below */\n");
Lev Walkin11380fb2006-08-18 01:38:40 +0000973 skipComma = 1;
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000974 continue;
975 }
Lev Walkinb46156d2017-09-05 02:53:05 -0700976 OUT("%s", c_presence_name(arg, v));
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000977 }
Lev Walkin1dc85292006-08-18 01:32:26 +0000978 OUT("\n");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000979 );
Lev Walkinb46156d2017-09-05 02:53:05 -0700980 OUT("} %s;\n", c_name(arg).presence_name);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000981
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800982 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +0000983
984 if(arg->embed) {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800985 if (expr->_anonymous_type) {
986 REDIR(OT_FWD_DEFS);
987 OUT("typedef ");
988 }
Lev Walkinb46156d2017-09-05 02:53:05 -0700989 OUT("%s {\n", c_name(arg).full_name);
Lev Walkinf15320b2004-06-03 03:38:44 +0000990 } else {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +0800991 REDIR(OT_TYPE_DECLS);
Lev Walkinb46156d2017-09-05 02:53:05 -0700992 OUT("typedef %s {\n", c_name(arg).full_name);
Lev Walkinf15320b2004-06-03 03:38:44 +0000993 }
994
995 INDENTED(
Lev Walkinb46156d2017-09-05 02:53:05 -0700996 OUT("%s present;\n", c_name(arg).presence_name);
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000997 OUT("union ");
998 if(UNNAMED_UNIONS == 0) {
999 out_name_chain(arg, ONC_force_compound_name);
1000 OUT("_u ");
1001 }
1002 OUT("{\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001003 TQ_FOR(v, &(expr->members), next) {
1004 EMBED(v);
1005 }
1006 if(UNNAMED_UNIONS) OUT("};\n");
1007 else OUT("} choice;\n");
1008 );
1009
1010 PCTX_DEF;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001011
1012 if (arg->embed && expr->_anonymous_type) {
Lev Walkinb46156d2017-09-05 02:53:05 -07001013 OUT("} %s%s;\n", (expr->marker.flags & EM_INDIRECT)?"*":"",
1014 c_name(arg).base_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001015
1016 REDIR(saved_target);
1017
Lev Walkinb46156d2017-09-05 02:53:05 -07001018 OUT("%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
1019 c_name(arg).base_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001020 } else {
Lev Walkinb46156d2017-09-05 02:53:05 -07001021 OUT("} %s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
1022 c_name(arg).short_name);
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001023 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001024
1025 return asn1c_lang_C_type_CHOICE_def(arg);
1026}
1027
Lev Walkinf6853ce2017-08-11 00:50:27 -07001028static ssize_t
1029find_column_index(arg_t *arg, asn1c_ioc_table_and_objset_t *opt_ioc, const char *column_name) {
1030 (void)arg;
1031
1032 if(!opt_ioc || !opt_ioc->ioct || !column_name) {
1033 return -1;
1034 }
1035
1036 if(opt_ioc->ioct->rows == 0) {
1037 return 0; /* No big deal. Just no data */
1038 } else {
1039 for(size_t clmn = 0; clmn < opt_ioc->ioct->row[0]->columns; clmn++) {
1040 if(strcmp(opt_ioc->ioct->row[0]->column[clmn].field->Identifier,
1041 column_name) == 0) {
1042 return clmn;
1043 }
1044 }
1045 return -1;
1046 }
1047
1048}
1049
1050static int
1051asn1c_lang_C_OpenType(arg_t *arg, asn1c_ioc_table_and_objset_t *opt_ioc,
1052 const char *column_name) {
1053 arg_t tmp_arg = *arg;
1054
1055 ssize_t column_index = find_column_index(arg, opt_ioc, column_name);
1056 if(column_index < 0) {
1057 FATAL("Open type generation attempted for %s, incomplete", column_name);
1058 return -1;
1059 }
1060
1061 asn1p_expr_t *open_type_choice =
1062 asn1p_expr_new(arg->expr->_lineno, arg->expr->module);
1063
1064 open_type_choice->Identifier = strdup(arg->expr->Identifier);
1065 open_type_choice->meta_type = AMT_TYPE;
1066 open_type_choice->expr_type = ASN_CONSTR_OPEN_TYPE;
1067 open_type_choice->_type_unique_index = arg->expr->_type_unique_index;
1068
1069 for(size_t row = 0; row < opt_ioc->ioct->rows; row++) {
1070 struct asn1p_ioc_cell_s *cell =
1071 &opt_ioc->ioct->row[row]->column[column_index];
1072
1073 asn1p_expr_t *m = asn1p_expr_clone(cell->value, 0);
1074 asn1p_expr_add(open_type_choice, m);
1075 }
1076
1077 tmp_arg.expr = open_type_choice;
1078 GEN_INCLUDE_STD("OPEN_TYPE");
1079 asn1c_lang_C_type_CHOICE(&tmp_arg);
1080 asn1p_expr_free(tmp_arg.expr);
1081 return 0;
1082}
1083
Lev Walkinf15320b2004-06-03 03:38:44 +00001084static int
1085asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
1086 asn1p_expr_t *expr = arg->expr;
1087 asn1p_expr_t *v;
1088 int elements; /* Number of elements */
Lev Walkinf15320b2004-06-03 03:38:44 +00001089 tag2el_t *tag2el = NULL;
1090 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +00001091 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +00001092 int all_tags_count;
1093 enum tvm_compat tv_mode;
Lev Walkin59b176e2005-11-26 11:25:14 +00001094 int *cmap = 0;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001095 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +00001096
1097 /*
1098 * Fetch every inner tag from the tag to elements map.
1099 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001100 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001101 if(tag2el) free(tag2el);
1102 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +00001103 }
1104
Lev Walkin22b5ed42006-09-13 02:51:20 +00001105 GEN_INCLUDE_STD("constr_CHOICE");
Lev Walkin3dcaafa2004-08-11 05:21:32 +00001106 if(!arg->embed)
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001107 GEN_DECLARE("CHOICE", expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +00001108
Lev Walkin3dcaafa2004-08-11 05:21:32 +00001109 REDIR(OT_STAT_DEFS);
Lev Walkinf15320b2004-06-03 03:38:44 +00001110
1111 /*
Lev Walkin59b176e2005-11-26 11:25:14 +00001112 * Print out the table according to which parsing is performed.
Lev Walkinf15320b2004-06-03 03:38:44 +00001113 */
Lev Walkina9cc46e2004-09-22 16:06:28 +00001114 if(expr_elements_count(arg, expr)) {
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_TYPE_member_t asn_MBR_%s_%d[] = {\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -07001118 c_name(arg).part_name, expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +00001119
1120 elements = 0;
1121 INDENTED(TQ_FOR(v, &(expr->members), next) {
Lev Walkin659c63b2005-01-17 11:40:49 +00001122 if(v->expr_type == A1TC_EXTENSIBLE)
1123 continue;
Lev Walkin9de6cd82017-08-10 05:47:46 -07001124 emit_member_table(arg, v, NULL);
Lev Walkinda9a3b82005-08-16 17:00:21 +00001125 elements++;
Lev Walkina9cc46e2004-09-22 16:06:28 +00001126 });
1127 OUT("};\n");
1128 } else {
1129 elements = 0;
1130 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001131
Lev Walkin59b176e2005-11-26 11:25:14 +00001132 /* Create a canonical elements map */
1133 if(elements && (arg->flags & A1C_GEN_PER)) {
1134 int i;
1135 cmap = compute_canonical_members_order(arg, elements);
1136 if(cmap) {
Lev Walkinf6853ce2017-08-11 00:50:27 -07001137 OUT("static const unsigned asn_MAP_%s_cmap_%d[] = {",
Lev Walkina00d6b32006-03-21 03:40:38 +00001138 MKID(expr),
Lev Walkin59b176e2005-11-26 11:25:14 +00001139 expr->_type_unique_index);
1140 for(i = 0; i < elements; i++) {
1141 if(i) OUT(",");
1142 OUT(" %d", cmap[i]);
1143 }
1144 OUT(" };\n");
1145 free(cmap);
1146 }
1147 }
Lev Walkin64399722004-08-11 07:17:22 +00001148
Lev Walkinf15320b2004-06-03 03:38:44 +00001149 if(arg->embed) {
1150 /*
1151 * Our parent structure has already taken this into account.
1152 */
Lev Walkin188ed2c2004-09-13 08:31:01 +00001153 tv_mode = _TVM_SAME;
1154 tags_count = all_tags_count = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +00001155 } else {
Lev Walkin188ed2c2004-09-13 08:31:01 +00001156 tv_mode = emit_tags_vectors(arg, expr,
1157 &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +00001158 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001159
1160 /*
1161 * Tags to elements map.
1162 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001163 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +00001164
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001165 if(!(expr->_type_referenced)) OUT("static ");
1166 OUT("asn_CHOICE_specifics_t asn_SPC_%s_specs_%d = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00001167 MKID(expr), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +00001168 INDENTED(
Lev Walkinb46156d2017-09-05 02:53:05 -07001169 OUT("sizeof(%s),\n", c_name(arg).full_name);
1170 OUT("offsetof(%s, _asn_ctx),\n", c_name(arg).full_name);
1171 OUT("offsetof(%s, present),\n", c_name(arg).full_name);
1172 OUT("sizeof(((%s *)0)->present),\n", c_name(arg).full_name);
Lev Walkinade508c2017-08-23 10:19:30 -07001173 emit_tag2member_reference(arg, expr, tag2el_count);
Lev Walkin59b176e2005-11-26 11:25:14 +00001174 if(C99_MODE) OUT(".canonical_order = ");
1175 if(cmap) OUT("asn_MAP_%s_cmap_%d,\t/* Canonically sorted */\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00001176 MKID(expr), expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00001177 else OUT("0,\n");
1178 if(C99_MODE) OUT(".ext_start = ");
1179 OUT("%d\t/* Extensions start */\n",
1180 compute_extensions_start(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +00001181 );
1182 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +00001183
1184 /*
Lev Walkin05363a72004-09-29 13:16:40 +00001185 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +00001186 */
Lev Walkin188ed2c2004-09-13 08:31:01 +00001187 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
Lev Walkin8de2ab22004-09-26 13:11:31 +00001188 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +00001189
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001190 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +00001191
Bi-Ruei, Chiu12021b52016-11-04 11:59:45 +08001192 if (tag2el) free(tag2el);
1193
Lev Walkinf15320b2004-06-03 03:38:44 +00001194 return 0;
Lev Walkinb0b33412005-01-17 11:57:48 +00001195} /* _CHOICE_def() */
Lev Walkinf15320b2004-06-03 03:38:44 +00001196
1197int
1198asn1c_lang_C_type_REFERENCE(arg_t *arg) {
1199 asn1p_ref_t *ref;
1200
1201 ref = arg->expr->reference;
1202 if(ref->components[ref->comp_count-1].name[0] == '&') {
Lev Walkinf15320b2004-06-03 03:38:44 +00001203 asn1p_expr_t *extract;
1204 arg_t tmp;
1205 int ret;
1206
Lev Walkinc0e03b92017-08-22 01:48:23 -07001207 extract = WITH_MODULE_NAMESPACE(
1208 arg->expr->module, expr_ns,
1209 asn1f_class_access_ex(arg->asn, arg->expr->module, expr_ns,
1210 arg->expr, arg->expr->rhs_pspecs, ref));
1211 if(extract == NULL)
Lev Walkinf15320b2004-06-03 03:38:44 +00001212 return -1;
1213
Lev Walkin08079b02004-08-22 03:25:24 +00001214 extract = asn1p_expr_clone(extract, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +00001215 if(extract) {
Lev Walkind8b83642016-03-14 02:00:27 -07001216 free(extract->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +00001217 extract->Identifier = strdup(arg->expr->Identifier);
1218 if(extract->Identifier == NULL) {
1219 asn1p_expr_free(extract);
1220 return -1;
1221 }
1222 } else {
1223 return -1;
1224 }
1225
1226 tmp = *arg;
1227 tmp.asn = arg->asn;
Lev Walkinf15320b2004-06-03 03:38:44 +00001228 tmp.expr = extract;
1229
Lev Walkin9de6cd82017-08-10 05:47:46 -07001230 ret = arg->default_cb(&tmp, NULL);
Lev Walkinf15320b2004-06-03 03:38:44 +00001231
1232 asn1p_expr_free(extract);
1233
1234 return ret;
1235 }
1236
1237
1238 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
1239}
1240
1241int
1242asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
1243 asn1p_expr_t *expr = arg->expr;
Lev Walkin64399722004-08-11 07:17:22 +00001244 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +00001245 int all_tags_count;
1246 enum tvm_compat tv_mode;
Lev Walkine0b56e02005-02-25 12:10:27 +00001247 enum etd_spec etd_spec;
Lev Walkinb46156d2017-09-05 02:53:05 -07001248 const char *p;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001249 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +00001250
1251 if(arg->embed) {
Lev Walkin05363a72004-09-29 13:16:40 +00001252 enum tnfmt tnfmt = TNF_CTYPE;
1253
1254 /*
1255 * If this is an optional compound type,
1256 * refer it using "struct X" convention,
1257 * as it may recursively include the current structure.
1258 */
Lev Walkinc8285712005-03-04 22:18:20 +00001259 if(expr->marker.flags & (EM_INDIRECT | EM_UNRECURSE)) {
Lev Walkinb85a8132005-08-18 13:38:19 +00001260 if(terminal_structable(arg, expr)) {
Lev Walkinc8285712005-03-04 22:18:20 +00001261 tnfmt = TNF_RSAFE;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001262 if(saved_target != OT_FWD_DECLS) {
1263 REDIR(OT_FWD_DECLS);
1264 OUT("%s;\n",
1265 asn1c_type_name(arg, arg->expr, tnfmt));
1266 }
1267 REDIR(saved_target);
Lev Walkin05363a72004-09-29 13:16:40 +00001268 }
1269 }
1270
Lev Walkinf15320b2004-06-03 03:38:44 +00001271
Lev Walkinc8285712005-03-04 22:18:20 +00001272 OUT("%s", asn1c_type_name(arg, arg->expr, tnfmt));
Lev Walkine0b56e02005-02-25 12:10:27 +00001273 if(!expr->_anonymous_type) {
Lev Walkinc8285712005-03-04 22:18:20 +00001274 OUT("%s", (expr->marker.flags&EM_INDIRECT)?"\t*":"\t ");
Lev Walkina00d6b32006-03-21 03:40:38 +00001275 OUT("%s", MKID_safe(expr));
Lev Walkin59b176e2005-11-26 11:25:14 +00001276 if((expr->marker.flags & (EM_DEFAULT & ~EM_INDIRECT))
1277 == (EM_DEFAULT & ~EM_INDIRECT))
Lev Walkine0b56e02005-02-25 12:10:27 +00001278 OUT("\t/* DEFAULT %s */",
1279 asn1f_printable_value(
1280 expr->marker.default_value));
Lev Walkin59b176e2005-11-26 11:25:14 +00001281 else if((expr->marker.flags & EM_OPTIONAL)
1282 == EM_OPTIONAL)
Lev Walkine0b56e02005-02-25 12:10:27 +00001283 OUT("\t/* OPTIONAL */");
1284 }
1285
1286 } else {
1287 GEN_INCLUDE(asn1c_type_name(arg, expr, TNF_INCLUDE));
Lev Walkin59004fa2004-08-20 13:37:01 +00001288
1289 REDIR(OT_TYPE_DECLS);
Lev Walkine0b56e02005-02-25 12:10:27 +00001290
1291 OUT("typedef %s\t",
Lev Walkinc8285712005-03-04 22:18:20 +00001292 asn1c_type_name(arg, arg->expr, TNF_CTYPE));
Lev Walkine0b56e02005-02-25 12:10:27 +00001293 OUT("%s%s_t",
Lev Walkinc8285712005-03-04 22:18:20 +00001294 (expr->marker.flags & EM_INDIRECT)?"*":" ",
Lev Walkina00d6b32006-03-21 03:40:38 +00001295 MKID(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +00001296 }
1297
Lev Walkine0b56e02005-02-25 12:10:27 +00001298 if((expr->expr_type == ASN_BASIC_ENUMERATED)
Lev Walkin8ecf9db2005-03-03 21:28:12 +00001299 || (0 /* -- prohibited by X.693:8.3.4 */
1300 && expr->expr_type == ASN_BASIC_INTEGER
Lev Walkin8bb57a22007-12-03 13:41:36 +00001301 && expr_elements_count(arg, expr))
1302 || (expr->expr_type == ASN_BASIC_INTEGER
1303 && asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN)
Lev Walkin43292722017-10-05 00:33:32 -07001304 || asn1c_REAL_fits(arg, expr) == RL_FITS_FLOAT32
Lev Walkin8bb57a22007-12-03 13:41:36 +00001305 )
Lev Walkine0b56e02005-02-25 12:10:27 +00001306 etd_spec = ETD_HAS_SPECIFICS;
1307 else
1308 etd_spec = ETD_NO_SPECIFICS;
Lev Walkinf15320b2004-06-03 03:38:44 +00001309
Lev Walkin8de2ab22004-09-26 13:11:31 +00001310 /*
1311 * If this type just blindly refers the other type, alias it.
1312 * Type1 ::= Type2
1313 */
Lev Walkine0b56e02005-02-25 12:10:27 +00001314 if(arg->embed && etd_spec == ETD_NO_SPECIFICS) {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001315 REDIR(saved_target);
Lev Walkine0b56e02005-02-25 12:10:27 +00001316 return 0;
1317 }
Lev Walkin8de2ab22004-09-26 13:11:31 +00001318
Lev Walkin59004fa2004-08-20 13:37:01 +00001319 REDIR(OT_CODE);
1320
Lev Walkinf15320b2004-06-03 03:38:44 +00001321 /*
1322 * Constraint checking.
1323 */
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001324 if(!(arg->flags & A1C_NO_CONSTRAINTS) && expr->combined_constraints) {
Lev Walkina00d6b32006-03-21 03:40:38 +00001325 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001326 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkin8de2ab22004-09-26 13:11:31 +00001327 OUT("int\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001328 OUT("%s", p);
1329 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1330 OUT("_constraint(asn_TYPE_descriptor_t *td, const void *sptr,\n");
Lev Walkin8de2ab22004-09-26 13:11:31 +00001331 INDENT(+1);
Lev Walkin1eded352006-07-13 11:19:01 +00001332 OUT("\t\tasn_app_constraint_failed_f *ctfailcb, void *app_key) {");
Lev Walkin8de2ab22004-09-26 13:11:31 +00001333 OUT("\n");
Lev Walkin725883b2006-10-09 12:07:58 +00001334 DEBUG("expr constraint checking code for %s", p);
Lev Walkin8de2ab22004-09-26 13:11:31 +00001335 if(asn1c_emit_constraint_checking_code(arg) == 1) {
Lev Walkin14e75ed2017-09-29 23:15:02 -07001336 OUT("return td->encoding_constraints.general_constraints"
Lev Walkin1eded352006-07-13 11:19:01 +00001337 "(td, sptr, ctfailcb, app_key);\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +00001338 }
Lev Walkin8de2ab22004-09-26 13:11:31 +00001339 INDENT(-1);
1340 OUT("}\n");
1341 OUT("\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001342 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001343
Lev Walkin725883b2006-10-09 12:07:58 +00001344 REDIR(OT_STAT_DEFS);
1345
Lev Walkin43292722017-10-05 00:33:32 -07001346 /*
1347 * By default, NativeReal is double. We only override this if
1348 * (OER) constraints suggested that we may use float.
1349 */
1350 if(asn1c_REAL_fits(arg, expr) == RL_FITS_FLOAT32) {
Lev Walkinb5450702017-10-04 02:52:57 -07001351 if(!(expr->_type_referenced)) OUT("static ");
1352 OUT("const asn_NativeReal_specifics_t asn_SPC_%s_specs_%d = {\n",
1353 MKID(expr), expr->_type_unique_index);
1354 INDENT(+1);
1355 OUT("4\t/* Use 'float' type. */\n");
1356 INDENT(-1);
1357 OUT("};\n");
1358 }
1359
Lev Walkin725883b2006-10-09 12:07:58 +00001360 /*
1361 * Print out asn_DEF_<type>_[all_]tags[] vectors.
1362 */
1363 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
1364 DEBUG("emit tag vectors for %s %d, %d, %d", expr->Identifier,
1365 tv_mode, tags_count, all_tags_count);
1366
1367 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count,
1368 0, etd_spec);
1369
1370 REDIR(OT_CODE);
1371
Lev Walkinf15320b2004-06-03 03:38:44 +00001372 /*
1373 * Emit suicidal functions.
1374 */
1375
Lev Walkinf15320b2004-06-03 03:38:44 +00001376 /*
1377 * This function replaces certain fields from the definition
1378 * of a type with the corresponding fields from the basic type
1379 * (from which the current type is inherited).
1380 */
Lev Walkinf15320b2004-06-03 03:38:44 +00001381 OUT("/*\n");
Lev Walkin026e21a2017-10-04 00:49:01 -07001382 OUT(" * This type is implemented using %s,\n", c_name(arg).type.base_name);
Lev Walkinb65b3002004-09-23 22:20:47 +00001383 OUT(" * so here we adjust the DEF accordingly.\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001384 OUT(" */\n");
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001385
Lev Walkinf15320b2004-06-03 03:38:44 +00001386 REDIR(OT_FUNC_DECLS);
1387
Lev Walkina00d6b32006-03-21 03:40:38 +00001388 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001389 if(HIDE_INNER_DEFS) {
Lev Walkin21d00002005-03-04 08:48:53 +00001390 OUT("/* extern asn_TYPE_descriptor_t asn_DEF_%s_%d;"
1391 "\t// (Use -fall-defs-global to expose) */\n",
1392 p, expr->_type_unique_index);
Lev Walkine0b56e02005-02-25 12:10:27 +00001393 } else {
1394 OUT("extern asn_TYPE_descriptor_t asn_DEF_%s;\n", p);
Lev Walkinb5450702017-10-04 02:52:57 -07001395 if(etd_spec == ETD_HAS_SPECIFICS && expr->_type_referenced) {
1396 if((expr->expr_type == ASN_BASIC_ENUMERATED)
1397 || (expr->expr_type == ASN_BASIC_INTEGER)) {
1398 OUT("extern const asn_INTEGER_specifics_t "
1399 "asn_SPC_%s_specs_%d;\n",
1400 c_name(arg).base_name, expr->_type_unique_index);
1401 } else {
Lev Walkinc0e03b92017-08-22 01:48:23 -07001402 asn1p_expr_t *terminal = WITH_MODULE_NAMESPACE(
1403 expr->module, expr_ns,
1404 asn1f_find_terminal_type_ex(arg->asn, expr_ns, expr));
Lev Walkinb5450702017-10-04 02:52:57 -07001405 OUT("extern const asn_%s_specifics_t ",
1406 asn1c_type_name(arg, terminal, TNF_SAFE));
1407 OUT("asn_SPC_%s_specs_%d;\n", MKID(expr),
1408 expr->_type_unique_index);
1409 }
1410 }
Lev Walkine0b56e02005-02-25 12:10:27 +00001411 OUT("asn_struct_free_f %s_free;\n", p);
1412 OUT("asn_struct_print_f %s_print;\n", p);
1413 OUT("asn_constr_check_f %s_constraint;\n", p);
1414 OUT("ber_type_decoder_f %s_decode_ber;\n", p);
1415 OUT("der_type_encoder_f %s_encode_der;\n", p);
1416 OUT("xer_type_decoder_f %s_decode_xer;\n", p);
1417 OUT("xer_type_encoder_f %s_encode_xer;\n", p);
Lev Walkinb33425f2017-07-14 14:59:52 +04001418 if(arg->flags & A1C_GEN_OER) {
1419 OUT("oer_type_decoder_f %s_decode_oer;\n", p);
1420 OUT("oer_type_encoder_f %s_encode_oer;\n", p);
1421 }
Lev Walkin1dc85292006-08-18 01:32:26 +00001422 if(arg->flags & A1C_GEN_PER) {
Lev Walkin59b176e2005-11-26 11:25:14 +00001423 OUT("per_type_decoder_f %s_decode_uper;\n", p);
Lev Walkin1dc85292006-08-18 01:32:26 +00001424 OUT("per_type_encoder_f %s_encode_uper;\n", p);
1425 }
Lev Walkine0b56e02005-02-25 12:10:27 +00001426 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001427
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001428 REDIR(saved_target);
Lev Walkin3dcaafa2004-08-11 05:21:32 +00001429
Lev Walkinf15320b2004-06-03 03:38:44 +00001430 return 0;
1431}
1432
1433int
1434asn1c_lang_C_type_EXTENSIBLE(arg_t *arg) {
1435
1436 OUT("/*\n");
1437 OUT(" * This type is extensible,\n");
1438 OUT(" * possible extensions are below.\n");
1439 OUT(" */\n");
1440
1441 return 0;
1442}
1443
Lev Walkin59b176e2005-11-26 11:25:14 +00001444static int
1445compute_extensions_start(asn1p_expr_t *expr) {
Lev Walkin35631482004-07-01 00:52:50 +00001446 asn1p_expr_t *v;
Lev Walkin59b176e2005-11-26 11:25:14 +00001447 int eidx = 0;
Lev Walkin35631482004-07-01 00:52:50 +00001448 TQ_FOR(v, &(expr->members), next) {
Lev Walkin59b176e2005-11-26 11:25:14 +00001449 if(v->expr_type == A1TC_EXTENSIBLE)
1450 return eidx;
1451 eidx++;
Lev Walkin35631482004-07-01 00:52:50 +00001452 }
Lev Walkin59b176e2005-11-26 11:25:14 +00001453 return -1;
Lev Walkin35631482004-07-01 00:52:50 +00001454}
1455
Lev Walkinf15320b2004-06-03 03:38:44 +00001456static int
Lev Walkinc3e29402004-09-10 06:07:18 +00001457_print_tag(arg_t *arg, struct asn1p_type_tag_s *tag) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001458
1459 OUT("(");
Lev Walkinc3e29402004-09-10 06:07:18 +00001460 switch(tag->tag_class) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001461 case TC_UNIVERSAL: OUT("ASN_TAG_CLASS_UNIVERSAL"); break;
1462 case TC_APPLICATION: OUT("ASN_TAG_CLASS_APPLICATION"); break;
1463 case TC_CONTEXT_SPECIFIC: OUT("ASN_TAG_CLASS_CONTEXT"); break;
1464 case TC_PRIVATE: OUT("ASN_TAG_CLASS_PRIVATE"); break;
1465 case TC_NOCLASS:
1466 break;
1467 }
Lev Walkinda997b12017-08-04 01:38:41 -07001468 OUT(" | (%s << 2))", asn1p_itoa(tag->tag_value));
Lev Walkinf15320b2004-06-03 03:38:44 +00001469
1470 return 0;
1471}
1472
Lev Walkinfd171ef2004-06-06 07:20:17 +00001473
1474static int
1475_tag2el_cmp(const void *ap, const void *bp) {
1476 const tag2el_t *a = ap;
1477 const tag2el_t *b = bp;
1478 const struct asn1p_type_tag_s *ta = &a->el_tag;
1479 const struct asn1p_type_tag_s *tb = &b->el_tag;
1480
1481 if(ta->tag_class == tb->tag_class) {
1482 if(ta->tag_value == tb->tag_value) {
1483 /*
1484 * Sort by their respective positions.
1485 */
1486 if(a->el_no < b->el_no)
1487 return -1;
1488 else if(a->el_no > b->el_no)
1489 return 1;
1490 return 0;
1491 } else if(ta->tag_value < tb->tag_value)
1492 return -1;
1493 else
1494 return 1;
1495 } else if(ta->tag_class < tb->tag_class) {
1496 return -1;
1497 } else {
1498 return 1;
1499 }
1500}
1501
Lev Walkinf15320b2004-06-03 03:38:44 +00001502/*
1503 * For constructed types, number of external tags may be greater than
1504 * number of elements in the type because of CHOICE type.
1505 * T ::= SET { -- Three possible tags:
1506 * a INTEGER, -- One tag is here...
1507 * b Choice1 -- ... and two more tags are there.
1508 * }
1509 * Choice1 ::= CHOICE {
1510 * s1 IA5String,
1511 * s2 ObjectDescriptor
1512 * }
1513 */
1514static int
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001515_fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001516 asn1p_expr_t *expr = arg->expr;
1517 arg_t tmparg = *arg;
1518 asn1p_expr_t *v;
1519 int element = 0;
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001520 int original_count = *count;
1521 int sort_until = -1;
Lev Walkinf15320b2004-06-03 03:38:44 +00001522
1523 TQ_FOR(v, &(expr->members), next) {
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001524 if(v->expr_type == A1TC_EXTENSIBLE) {
1525 /*
Lev Walkine0b56e02005-02-25 12:10:27 +00001526 * CXER mandates sorting
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001527 * only for the root part.
1528 */
1529 if(flags == FTE_CANONICAL_XER
1530 && sort_until == -1)
1531 sort_until = *count;
Lev Walkinf15320b2004-06-03 03:38:44 +00001532 continue;
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001533 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001534
1535 tmparg.expr = v;
1536
1537 if(_add_tag2el_member(&tmparg, tag2el, count,
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001538 (el_no==-1)?element:el_no, flags)) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001539 return -1;
1540 }
1541
1542 element++;
1543 }
1544
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001545
1546 if(flags == FTE_CANONICAL_XER) {
1547 if(sort_until == -1) sort_until = *count;
1548 qsort((*tag2el) + original_count,
1549 sort_until - original_count,
1550 sizeof(**tag2el), _tag2el_cmp);
1551 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1552 && (sort_until - original_count) >= 1) {
1553 /* Only take in account the root component */
1554 *count = original_count + 1;
1555 }
1556 } else {
1557 /*
1558 * Sort the map according to canonical order of their
1559 * tags and element numbers.
1560 */
1561 qsort(*tag2el, *count, sizeof(**tag2el), _tag2el_cmp);
1562 }
Lev Walkinfd171ef2004-06-06 07:20:17 +00001563
Lev Walkin38abe792004-06-14 13:09:45 +00001564 /*
1565 * Initialize .toff_{first|last} members.
1566 */
1567 if(*count) {
1568 struct asn1p_type_tag_s *cur_tag = 0;
1569 tag2el_t *cur = *tag2el;
1570 tag2el_t *end = cur + *count;
1571 int occur, i;
1572 for(occur = 0; cur < end; cur++) {
1573 if(cur_tag == 0
1574 || cur_tag->tag_value != cur->el_tag.tag_value
1575 || cur_tag->tag_class != cur->el_tag.tag_class) {
1576 cur_tag = &cur->el_tag;
1577 occur = 0;
1578 } else {
1579 occur++;
1580 }
1581 cur->toff_first = -occur;
1582 for(i = 0; i >= -occur; i--)
1583 cur[i].toff_last = -i;
1584 }
1585 }
1586
Lev Walkinf15320b2004-06-03 03:38:44 +00001587 return 0;
1588}
1589
1590static int
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001591_add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001592 struct asn1p_type_tag_s tag;
1593 int ret;
1594
1595 assert(el_no >= 0);
1596
Lev Walkinc0e03b92017-08-22 01:48:23 -07001597 ret = WITH_MODULE_NAMESPACE(
1598 arg->expr->module, expr_ns,
1599 asn1f_fetch_outmost_tag(arg->asn, expr_ns, arg->expr->module, arg->expr,
1600 &tag, AFT_IMAGINARY_ANY));
1601 if(ret == 0) {
Lev Walkin201943e2004-09-04 04:42:29 +00001602 tag2el_t *te;
1603 int new_count = (*count) + 1;
Lev Walkinf15320b2004-06-03 03:38:44 +00001604 void *p;
Lev Walkin201943e2004-09-04 04:42:29 +00001605
Lev Walkinac7e2292004-09-05 10:42:33 +00001606 if(tag.tag_value == -1) {
1607 /*
1608 * This is an untagged ANY type,
1609 * proceed without adding a tag
1610 */
1611 return 0;
1612 }
1613
Lev Walkin201943e2004-09-04 04:42:29 +00001614 p = realloc(*tag2el, new_count * sizeof(tag2el_t));
Lev Walkinf15320b2004-06-03 03:38:44 +00001615 if(p) *tag2el = p;
1616 else return -1;
1617
Lev Walkin725883b2006-10-09 12:07:58 +00001618 if(0) DEBUG("Found tag for %s: %ld",
Lev Walkinf15320b2004-06-03 03:38:44 +00001619 arg->expr->Identifier,
1620 (long)tag.tag_value);
1621
Lev Walkin201943e2004-09-04 04:42:29 +00001622 te = &((*tag2el)[*count]);
1623 te->el_tag = tag;
1624 te->el_no = el_no;
1625 te->from_expr = arg->expr;
1626 *count = new_count;
Lev Walkinf15320b2004-06-03 03:38:44 +00001627 return 0;
1628 }
1629
1630 DEBUG("Searching tag in complex expression %s:%x at line %d",
1631 arg->expr->Identifier,
1632 arg->expr->expr_type,
1633 arg->expr->_lineno);
1634
1635 /*
1636 * Iterate over members of CHOICE type.
1637 */
1638 if(arg->expr->expr_type == ASN_CONSTR_CHOICE) {
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001639 return _fill_tag2el_map(arg, tag2el, count, el_no, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +00001640 }
1641
1642 if(arg->expr->expr_type == A1TC_REFERENCE) {
1643 arg_t tmp = *arg;
1644 asn1p_expr_t *expr;
Lev Walkinc0e03b92017-08-22 01:48:23 -07001645 expr = WITH_MODULE_NAMESPACE(
1646 tmp.expr->module, expr_ns,
1647 asn1f_lookup_symbol_ex(tmp.asn, expr_ns, tmp.expr,
1648 arg->expr->reference));
1649 if(expr) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001650 tmp.expr = expr;
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001651 return _add_tag2el_member(&tmp, tag2el, count, el_no, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +00001652 } else {
1653 FATAL("Cannot dereference %s at line %d",
1654 arg->expr->Identifier,
1655 arg->expr->_lineno);
1656 return -1;
1657 }
1658 }
1659
1660 DEBUG("No tag for %s at line %d",
1661 arg->expr->Identifier,
1662 arg->expr->_lineno);
1663
1664 return -1;
1665}
1666
1667static int
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001668emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier) {
Lev Walkinfd171ef2004-06-06 07:20:17 +00001669 asn1p_expr_t *expr = arg->expr;
Lev Walkinf3b29b12005-06-02 05:21:37 +00001670 int i;
1671
1672 if(!tag2el_count) return 0; /* No top level tags */
Lev Walkinfd171ef2004-06-06 07:20:17 +00001673
Wim Lewisfb6344e2014-07-28 12:16:01 -07001674 OUT("static const asn_TYPE_tag2member_t asn_MAP_%s_tag2el%s_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00001675 MKID(expr), opt_modifier?opt_modifier:"",
Lev Walkin59b176e2005-11-26 11:25:14 +00001676 expr->_type_unique_index);
Lev Walkinf3b29b12005-06-02 05:21:37 +00001677 for(i = 0; i < tag2el_count; i++) {
1678 OUT(" { ");
1679 _print_tag(arg, &tag2el[i].el_tag);
1680 OUT(", ");
1681 OUT("%d, ", tag2el[i].el_no);
1682 OUT("%d, ", tag2el[i].toff_first);
1683 OUT("%d ", tag2el[i].toff_last);
Lev Walkin4062b012013-10-11 14:29:38 -07001684 OUT("}%s /* %s",
Lev Walkinf3b29b12005-06-02 05:21:37 +00001685 (i + 1 < tag2el_count) ? "," : "",
Lev Walkin4062b012013-10-11 14:29:38 -07001686 tag2el[i].from_expr->Identifier);
1687 if(arg->flags & A1C_LINE_REFS)
1688 OUT("at %d", tag2el[i].from_expr->_lineno);
1689 OUT(" */\n");
Lev Walkinfd171ef2004-06-06 07:20:17 +00001690 }
1691 OUT("};\n");
1692
Lev Walkinf3b29b12005-06-02 05:21:37 +00001693 return 0;
Lev Walkinfd171ef2004-06-06 07:20:17 +00001694}
1695
Lev Walkin188ed2c2004-09-13 08:31:01 +00001696static enum tvm_compat
1697emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tags_count_r, int *all_tags_count_r) {
1698 struct asn1p_type_tag_s *tags = 0; /* Effective tags */
1699 struct asn1p_type_tag_s *all_tags = 0; /* The full array */
Lev Walkin64399722004-08-11 07:17:22 +00001700 int tags_count = 0;
Lev Walkin188ed2c2004-09-13 08:31:01 +00001701 int all_tags_count = 0;
1702 enum tvm_compat tv_mode = _TVM_SAME;
Lev Walkin906654e2004-09-10 15:49:15 +00001703 int i;
Lev Walkin27ea3802004-06-28 21:13:46 +00001704
Lev Walkin6d1220a2004-09-14 14:10:10 +00001705 /* Cleanup before proceeding. */
1706 *tags_count_r = 0;
1707 *all_tags_count_r = 0;
1708
Lev Walkin906654e2004-09-10 15:49:15 +00001709 /* Fetch a chain of tags */
Lev Walkinc0e03b92017-08-22 01:48:23 -07001710 tags_count = WITH_MODULE_NAMESPACE(
1711 expr->module, expr_ns,
1712 asn1f_fetch_tags(arg->asn, expr_ns, expr->module, expr, &tags, 0));
1713 if(tags_count < 0) {
Lev Walkin725883b2006-10-09 12:07:58 +00001714 DEBUG("fail to fetch tags for %s", expr->Identifier);
Lev Walkin6d1220a2004-09-14 14:10:10 +00001715 return -1;
Lev Walkin725883b2006-10-09 12:07:58 +00001716 }
Lev Walkin64399722004-08-11 07:17:22 +00001717
Lev Walkin188ed2c2004-09-13 08:31:01 +00001718 /* Fetch a chain of tags */
Lev Walkinc0e03b92017-08-22 01:48:23 -07001719 all_tags_count = WITH_MODULE_NAMESPACE(
1720 expr->module, expr_ns,
1721 asn1f_fetch_tags(arg->asn, expr_ns, expr->module, expr, &all_tags,
1722 AFT_FULL_COLLECT));
1723 if(all_tags_count < 0) {
Lev Walkind8b83642016-03-14 02:00:27 -07001724 free(tags);
Lev Walkin725883b2006-10-09 12:07:58 +00001725 DEBUG("fail to fetch tags chain for %s", expr->Identifier);
Lev Walkin188ed2c2004-09-13 08:31:01 +00001726 return -1;
Lev Walkin5a8219a2004-09-08 00:28:57 +00001727 }
Lev Walkin906654e2004-09-10 15:49:15 +00001728
Lev Walkin188ed2c2004-09-13 08:31:01 +00001729 assert(tags_count <= all_tags_count);
1730 assert((tags_count?0:1) == (all_tags_count?0:1));
Lev Walkin27ea3802004-06-28 21:13:46 +00001731
Lev Walkin188ed2c2004-09-13 08:31:01 +00001732 if(tags_count <= all_tags_count) {
1733 for(i = 0; i < tags_count; i++) {
1734 if(tags[i].tag_value != all_tags[i].tag_value
1735 || tags[i].tag_class != all_tags[i].tag_class) {
1736 tv_mode = _TVM_DIFFERENT;
1737 break;
1738 }
1739 }
1740 if(i == tags_count && tags_count < all_tags_count)
1741 tv_mode = _TVM_SUBSET;
1742 } else {
1743 tv_mode = _TVM_DIFFERENT;
1744 }
1745
1746#define EMIT_TAGS_TABLE(name, tags, tags_count) do { \
Wim Lewisfb6344e2014-07-28 12:16:01 -07001747 OUT("static const ber_tlv_tag_t asn_DEF_%s%s_tags_%d[] = {\n",\
Lev Walkina00d6b32006-03-21 03:40:38 +00001748 MKID(expr), name, \
Lev Walkin59b176e2005-11-26 11:25:14 +00001749 expr->_type_unique_index); \
Lev Walkin188ed2c2004-09-13 08:31:01 +00001750 INDENT(+1); \
1751 /* Print the array of collected tags */ \
1752 for(i = 0; i < tags_count; i++) { \
1753 if(i) OUT(",\n"); \
1754 _print_tag(arg, &tags[i]); \
1755 } \
1756 OUT("\n"); \
1757 INDENT(-1); \
1758 OUT("};\n"); \
1759 } while(0)
1760
1761 if(tags_count) {
1762 if(tv_mode == _TVM_SUBSET)
1763 EMIT_TAGS_TABLE("", all_tags, all_tags_count);
1764 else
1765 EMIT_TAGS_TABLE("", tags, tags_count);
1766 }
1767
1768 if(all_tags_count) {
1769 if(tv_mode == _TVM_DIFFERENT)
1770 EMIT_TAGS_TABLE("_all", all_tags, all_tags_count);
1771 }
1772
Lev Walkind8b83642016-03-14 02:00:27 -07001773 free(tags);
1774 free(all_tags);
Lev Walkin188ed2c2004-09-13 08:31:01 +00001775
1776 *tags_count_r = tags_count;
1777 *all_tags_count_r = all_tags_count;
1778
1779 return tv_mode;
Lev Walkin27ea3802004-06-28 21:13:46 +00001780}
Lev Walkin59004fa2004-08-20 13:37:01 +00001781
1782static int
Lev Walkin59964be2004-08-25 02:03:12 +00001783expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin59004fa2004-08-20 13:37:01 +00001784 asn1p_expr_t *topmost_parent;
1785 asn1p_expr_t *v;
1786 int elements = 0;
1787
Lev Walkinc0e03b92017-08-22 01:48:23 -07001788 topmost_parent = WITH_MODULE_NAMESPACE(
1789 expr->module, expr_ns,
1790 asn1f_find_terminal_type_ex(arg->asn, expr_ns, expr));
1791 if(!topmost_parent) return 0;
Lev Walkin59004fa2004-08-20 13:37:01 +00001792
Lev Walkine0b56e02005-02-25 12:10:27 +00001793 if(!(topmost_parent->expr_type & ASN_CONSTR_MASK)
Lev Walkin1b3a1352016-01-10 13:15:02 -08001794 && !(topmost_parent->expr_type == ASN_BASIC_INTEGER)
Lev Walkin0f262452016-01-10 13:33:08 -08001795 && !(topmost_parent->expr_type == ASN_BASIC_ENUMERATED)
1796 && !(topmost_parent->expr_type == ASN_BASIC_BIT_STRING))
Lev Walkin59004fa2004-08-20 13:37:01 +00001797 return 0;
1798
1799 TQ_FOR(v, &(topmost_parent->members), next) {
1800 if(v->expr_type != A1TC_EXTENSIBLE)
1801 elements++;
1802 }
1803
1804 return elements;
1805}
1806
Lev Walkin59b176e2005-11-26 11:25:14 +00001807static asn1p_expr_type_e
1808expr_get_type(arg_t *arg, asn1p_expr_t *expr) {
1809 asn1p_expr_t *terminal;
Lev Walkinc0e03b92017-08-22 01:48:23 -07001810 terminal = asn1f_find_terminal_type_ex(arg->asn, arg->ns, expr);
Lev Walkin59b176e2005-11-26 11:25:14 +00001811 if(terminal) return terminal->expr_type;
1812 return A1TC_INVALID;
1813}
1814
Lev Walkin725883b2006-10-09 12:07:58 +00001815static asn1c_integer_t
1816PER_FROM_alphabet_characters(asn1cnst_range_t *range) {
1817 asn1c_integer_t numchars = 0;
1818 if(range->el_count) {
1819 int i;
1820 for(i = 0; i < range->el_count; i++)
1821 numchars
1822 += PER_FROM_alphabet_characters(range->elements[i]);
1823 } else {
1824 assert(range->left.type == ARE_VALUE);
1825 assert(range->right.type == ARE_VALUE);
1826 numchars = 1 + (range->right.value - range->left.value);
1827 }
1828 return numchars;
1829}
1830
Lev Walkin4118ccf2017-08-02 10:37:31 -07001831static void
1832emit_single_member_OER_constraint_comment(arg_t *arg, asn1cnst_range_t *range, char *type) {
1833
1834 /*
1835 * Print some courtesy debug information.
1836 */
1837 if(range
1838 && (range->left.type == ARE_VALUE || range->right.type == ARE_VALUE)) {
1839 OUT("\t/* ");
1840 if(type) OUT("(%s", type);
1841 OUT("(");
1842 if(range->left.type == ARE_VALUE)
Lev Walkinda997b12017-08-04 01:38:41 -07001843 OUT("%s", asn1p_itoa(range->left.value));
Lev Walkin4118ccf2017-08-02 10:37:31 -07001844 else
1845 OUT("MIN");
1846 OUT("..");
1847 if(range->right.type == ARE_VALUE)
Lev Walkinda997b12017-08-04 01:38:41 -07001848 OUT("%s", asn1p_itoa(range->right.value));
Lev Walkin4118ccf2017-08-02 10:37:31 -07001849 else
1850 OUT("MAX");
1851 if(range->extensible) OUT(",...");
1852 if(type) OUT(")");
1853 OUT(") */");
1854 }
1855}
1856
1857static int
Lev Walkinb9e98cb2017-08-02 12:53:44 -07001858emit_single_member_OER_constraint_value(arg_t *arg, asn1cnst_range_t *range) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07001859 if(!range) {
1860 /* oer_support.h: asn_oer_constraint_s */
1861 OUT("{ 0, 0 }");
1862 return 0;
1863 }
1864
1865 if(range->incompatible || range->not_OER_visible) {
1866 OUT("{ 0, 0 }");
Lev Walkinafcc8912017-10-04 23:48:35 -07001867 } else if(expr_get_type(arg, arg->expr) == ASN_BASIC_REAL) {
1868 if(range->narrowing == NARROW_FLOAT32) {
1869 OUT("{ sizeof(float), 0 }");
Lev Walkin43292722017-10-05 00:33:32 -07001870 } else if(range->narrowing == NARROW_DOUBLE64) {
Lev Walkinafcc8912017-10-04 23:48:35 -07001871 OUT("{ sizeof(double), 0 }");
1872 } else {
1873 OUT("{ 0, 0 }");
1874 }
Lev Walkin6713bcb2017-08-30 19:41:03 -07001875 } else if(range->left.type == ARE_VALUE && range->left.value >= 0
1876 && range->right.type == ARE_MAX) {
1877 OUT("{ 0, 1 }");
Lev Walkin4118ccf2017-08-02 10:37:31 -07001878 } else if(range->left.type == ARE_VALUE &&
1879 range->right.type == ARE_VALUE) {
1880 asn1c_integer_t lb = range->left.value;
1881 asn1c_integer_t ub = range->right.value;
1882 unsigned width = 0;
1883 unsigned positive = 0;
1884
Lev Walkinb9e98cb2017-08-02 12:53:44 -07001885
Lev Walkin4118ccf2017-08-02 10:37:31 -07001886 if(lb >= 0) {
1887 /* X.969 08/2015 10.2(a) */
1888 if(ub <= 255) {
1889 width = 1;
1890 } else if(ub <= 65535) {
1891 width = 2;
Lev Walkinb9e98cb2017-08-02 12:53:44 -07001892 } else if((unsigned long long)ub <= 4294967295UL) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07001893 width = 4;
Lev Walkinb9e98cb2017-08-02 12:53:44 -07001894 } else if((unsigned long long)ub <= 18446744073709551615ULL) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07001895 width = 8;
1896 }
1897 positive = 1;
1898 } else {
1899 positive = 0;
1900 /* X.969 08/2015 10.2(b) - no lower bound or negative lower bound */
1901 if(lb >= -128 && ub <= 127) {
1902 width = 1;
1903 } else if(lb >= -32768 && ub <= 32767) {
1904 width = 2;
1905 } else if(lb >= -2147483648L && ub <= 2147483647L) {
1906 width = 4;
Lev Walkinb9e98cb2017-08-02 12:53:44 -07001907 } else if(lb >= (-9223372036854775807LL-1)
Lev Walkin4118ccf2017-08-02 10:37:31 -07001908 && ub <= 9223372036854775807LL) {
1909 width = 8;
1910 }
1911 }
1912 OUT("{ %u, %u }", width, positive);
1913 } else {
1914 OUT("{ 0, 0 }");
1915 }
1916
1917 return 0;
1918}
1919
1920static int
Lev Walkinb9e98cb2017-08-02 12:53:44 -07001921emit_single_member_OER_constraint_size(arg_t *arg, asn1cnst_range_t *range) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07001922 if(!range) {
1923 /* oer_support.h: asn_oer_constraint_s */
1924 OUT("-1");
1925 return 0;
1926 }
1927
1928 if(range->incompatible || range->not_OER_visible) {
1929 OUT("-1");
1930 } else {
1931 if(range->left.type == ARE_VALUE && range->right.type == ARE_VALUE
1932 && range->left.value == range->right.value
1933 && range->left.value >= 0) {
Lev Walkinda997b12017-08-04 01:38:41 -07001934 OUT("%s", asn1p_itoa(range->left.value));
Lev Walkin4118ccf2017-08-02 10:37:31 -07001935 } else {
1936 OUT("-1");
1937 }
1938 }
1939
1940 return 0;
1941}
1942
Lev Walkin59b176e2005-11-26 11:25:14 +00001943static int
Lev Walkinb9e98cb2017-08-02 12:53:44 -07001944emit_single_member_PER_constraint(arg_t *arg, asn1cnst_range_t *range, int alphabetsize, const char *type) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07001945 if(!range || range->incompatible || range->not_PER_visible) {
1946 OUT("{ APC_UNCONSTRAINED,\t-1, -1, 0, 0 }");
Lev Walkin59b176e2005-11-26 11:25:14 +00001947 return 0;
Lev Walkin4118ccf2017-08-02 10:37:31 -07001948 }
Lev Walkin59b176e2005-11-26 11:25:14 +00001949
Lev Walkin026e21a2017-10-04 00:49:01 -07001950 if(expr_get_type(arg, arg->expr) == ASN_BASIC_REAL) {
1951 /* Unsupported */
1952 OUT("{ APC_UNCONSTRAINED,\t-1, -1, 0, 0 }");
1953 return 0;
1954 }
1955
Lev Walkin4118ccf2017-08-02 10:37:31 -07001956 if(range->left.type == ARE_VALUE) {
Lev Walkin59b176e2005-11-26 11:25:14 +00001957 if(range->right.type == ARE_VALUE) {
1958 asn1c_integer_t cover = 1;
1959 asn1c_integer_t r = 1 + range->right.value
1960 - range->left.value;
Lev Walkinc46b7cb2006-08-18 02:27:55 +00001961 size_t rbits; /* Value range bits */
1962 ssize_t ebits; /* Value effective range bits */
Lev Walkin59b176e2005-11-26 11:25:14 +00001963
1964 if(range->empty_constraint)
1965 r = 0;
1966
Lev Walkin725883b2006-10-09 12:07:58 +00001967 if(alphabetsize) {
1968 /* X.691: 27.5.2 */
1969 r = PER_FROM_alphabet_characters(range);
1970 }
1971
Lev Walkin59b176e2005-11-26 11:25:14 +00001972 /* Compute real constraint */
1973 for(rbits = 0; rbits < (8 * sizeof(r)); rbits++) {
1974 if(r <= cover)
1975 break;
1976 cover *= 2; /* Can't do shifting */
1977 if(cover < 0) {
1978 FATAL("Constraint at line %d too wide "
1979 "for %d-bits integer type",
1980 arg->expr->_lineno,
1981 sizeof(r) * 8);
1982 rbits = sizeof(r);
1983 break;
1984 }
1985 }
1986
Lev Walkin3a4689a2006-11-24 11:20:27 +00001987 if(alphabetsize) {
1988 ebits = rbits;
1989 } else {
Lev Walkin59b176e2005-11-26 11:25:14 +00001990 /* X.691, #10.9.4.1 */
1991 for(ebits = 0; ebits <= 16; ebits++)
1992 if(r <= 1 << ebits) break;
1993 if(ebits == 17
1994 || range->right.value >= 65536)
1995 ebits = -1;
Lev Walkin3a4689a2006-11-24 11:20:27 +00001996 if(0) {
Lev Walkin59b176e2005-11-26 11:25:14 +00001997 /* X.691, #10.5.7.1 */
1998 for(ebits = 0; ebits <= 8; ebits++)
1999 if(r <= 1 << ebits) break;
2000 if(ebits == 9) {
2001 if(r <= 65536)
2002 ebits = 16;
2003 else
2004 ebits = -1;
2005 }
2006 }
Lev Walkin3a4689a2006-11-24 11:20:27 +00002007 }
Lev Walkin725883b2006-10-09 12:07:58 +00002008
Lev Walkin59b176e2005-11-26 11:25:14 +00002009 OUT("{ APC_CONSTRAINED%s,%s% d, % d, ",
2010 range->extensible
2011 ? " | APC_EXTENSIBLE" : "",
2012 range->extensible ? " " : "\t", rbits, ebits);
Lev Walkin3a4689a2006-11-24 11:20:27 +00002013
2014 if(alphabetsize) {
2015 asn1c_integer_t lv = range->left.value;
2016 asn1c_integer_t rv = range->right.value;
2017 int gcmt = 0;
2018 if(lv > 0x7fffffff) { lv = 0x7fffffff; gcmt++; }
2019 if(rv > 0x7fffffff) { rv = 0x7fffffff; gcmt++; }
2020 if(gcmt) {
Lev Walkin63b41262007-11-06 01:48:46 +00002021 OINTS(lv); OUT(", "); OINTS(rv); OUT(" }");
Lev Walkin3a4689a2006-11-24 11:20:27 +00002022 goto pcmt;
2023 }
2024 }
Lev Walkin59b176e2005-11-26 11:25:14 +00002025 } else {
2026 if(range->extensible) {
2027 OUT("{ APC_SEMI_CONSTRAINED | APC_EXTENSIBLE, "
2028 "-1, ");
2029 } else {
2030 OUT("{ APC_SEMI_CONSTRAINED,\t-1, -1, ");
2031 }
2032 }
Lev Walkin63b41262007-11-06 01:48:46 +00002033 OINTS(range->left.value); OUT(", ");
2034 OINTS(range->right.value); OUT(" }");
Lev Walkin59b176e2005-11-26 11:25:14 +00002035 } else {
2036 OUT("{ APC_UNCONSTRAINED,\t-1, -1, 0, 0 }");
2037 }
2038
Lev Walkin3a4689a2006-11-24 11:20:27 +00002039 pcmt:
2040
Lev Walkin59b176e2005-11-26 11:25:14 +00002041 /*
2042 * Print some courtesy debug information.
2043 */
2044 if(range->left.type == ARE_VALUE
2045 || range->right.type == ARE_VALUE) {
2046 OUT("\t/* ");
2047 if(type) OUT("(%s", type);
2048 OUT("(");
2049 if(range->left.type == ARE_VALUE)
Lev Walkinda997b12017-08-04 01:38:41 -07002050 OUT("%s", asn1p_itoa(range->left.value));
Lev Walkin59b176e2005-11-26 11:25:14 +00002051 else
2052 OUT("MIN");
2053 OUT("..");
2054 if(range->right.type == ARE_VALUE)
Lev Walkinda997b12017-08-04 01:38:41 -07002055 OUT("%s", asn1p_itoa(range->right.value));
Lev Walkin59b176e2005-11-26 11:25:14 +00002056 else
2057 OUT("MAX");
2058 if(range->extensible) OUT(",...");
2059 if(type) OUT(")");
2060 OUT(") */");
2061 }
2062
2063 return 0;
2064}
2065
2066static int
Lev Walkin98eabc12017-07-19 08:51:11 +04002067emit_member_OER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx) {
2068 int save_target = arg->target->target;
2069 asn1cnst_range_t *range;
2070 asn1p_expr_type_e etype;
2071
2072 etype = expr_get_type(arg, expr);
2073
2074 if((arg->flags & A1C_GEN_OER)
Lev Walkin135d7dd2017-08-28 00:21:38 -07002075 && (expr->combined_constraints || etype == ASN_BASIC_ENUMERATED
Lev Walkin98eabc12017-07-19 08:51:11 +04002076 || etype == ASN_CONSTR_CHOICE)) {
2077 /* Fall through */
2078 } else {
2079 return 0;
2080 }
2081
2082 REDIR(OT_CTDEFS);
2083
2084 OUT("static asn_oer_constraints_t "
Lev Walkin2e93c222017-09-26 18:29:15 -07002085 "asn_OER_%s_%s_constr_%d CC_NOTUSED = {\n",
Lev Walkin98eabc12017-07-19 08:51:11 +04002086 pfx, MKID(expr), expr->_type_unique_index);
2087
2088 INDENT(+1);
2089
Lev Walkin4118ccf2017-08-02 10:37:31 -07002090 /* .value{.width,.positive} */
Lev Walkina28cbb92017-07-31 20:20:17 -07002091 range = asn1constraint_compute_OER_range(expr->Identifier, etype,
2092 expr->combined_constraints,
Lev Walkin98eabc12017-07-19 08:51:11 +04002093 ACT_EL_RANGE, 0, 0, 0);
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002094 if(emit_single_member_OER_constraint_value(arg, range)) {
Lev Walkin98eabc12017-07-19 08:51:11 +04002095 return -1;
2096 }
Lev Walkin4118ccf2017-08-02 10:37:31 -07002097 emit_single_member_OER_constraint_comment(arg, range, 0);
Lev Walkin98eabc12017-07-19 08:51:11 +04002098 asn1constraint_range_free(range);
2099
2100 OUT(",\n");
2101
Lev Walkin4118ccf2017-08-02 10:37:31 -07002102 /* .size */
Lev Walkina28cbb92017-07-31 20:20:17 -07002103 range = asn1constraint_compute_OER_range(expr->Identifier, etype,
2104 expr->combined_constraints,
Lev Walkin98eabc12017-07-19 08:51:11 +04002105 ACT_CT_SIZE, 0, 0, 0);
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002106 if(emit_single_member_OER_constraint_size(arg, range)) {
Lev Walkin98eabc12017-07-19 08:51:11 +04002107 return -1;
2108 }
Lev Walkin4118ccf2017-08-02 10:37:31 -07002109 emit_single_member_OER_constraint_comment(arg, range, "SIZE");
Lev Walkin98eabc12017-07-19 08:51:11 +04002110 asn1constraint_range_free(range);
2111
2112 INDENT(-1);
2113
2114 OUT("};\n");
2115
2116 REDIR(save_target);
2117
2118 return 0;
2119}
2120
2121static int
Lev Walkin4b5dae32006-10-09 12:27:44 +00002122emit_member_PER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx) {
Lev Walkin725883b2006-10-09 12:07:58 +00002123 int save_target = arg->target->target;
Lev Walkin59b176e2005-11-26 11:25:14 +00002124 asn1cnst_range_t *range;
2125 asn1p_expr_type_e etype;
2126
Lev Walkin07aaa342006-10-09 12:52:15 +00002127 etype = expr_get_type(arg, expr);
2128
Lev Walkin725883b2006-10-09 12:07:58 +00002129 if((arg->flags & A1C_GEN_PER)
Lev Walkin135d7dd2017-08-28 00:21:38 -07002130 && (expr->combined_constraints
Lev Walkin07aaa342006-10-09 12:52:15 +00002131 || etype == ASN_BASIC_ENUMERATED
2132 || etype == ASN_CONSTR_CHOICE)
Lev Walkin725883b2006-10-09 12:07:58 +00002133 ) {
2134 /* Fall through */
2135 } else {
2136 return 0;
2137 }
2138
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002139 if(expr->_type_referenced) {
2140 REDIR(OT_FUNC_DECLS);
2141
2142 OUT("extern asn_per_constraints_t "
2143 "asn_PER_%s_%s_constr_%d;\n",
2144 pfx, MKID(expr), expr->_type_unique_index);
2145 }
2146
Lev Walkin725883b2006-10-09 12:07:58 +00002147 REDIR(OT_CTDEFS);
2148
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002149 if(!(expr->_type_referenced)) OUT("static ");
2150 OUT("asn_per_constraints_t "
Lev Walkin2e93c222017-09-26 18:29:15 -07002151 "asn_PER_%s_%s_constr_%d CC_NOTUSED = {\n",
Lev Walkin4b5dae32006-10-09 12:27:44 +00002152 pfx, MKID(expr), expr->_type_unique_index);
Lev Walkin725883b2006-10-09 12:07:58 +00002153
Lev Walkin59b176e2005-11-26 11:25:14 +00002154 INDENT(+1);
2155
2156 /*
2157 * ENUMERATED and CHOICE are special.
2158 */
2159 if(etype == ASN_BASIC_ENUMERATED
2160 || etype == ASN_CONSTR_CHOICE) {
2161 asn1cnst_range_t tmprng;
2162 asn1p_expr_t *v;
2163 int extensible = 0;
2164 int eidx = -1;
2165
Lev Walkinc0e03b92017-08-22 01:48:23 -07002166 expr = asn1f_find_terminal_type_ex(arg->asn, arg->ns, expr);
Lev Walkin59b176e2005-11-26 11:25:14 +00002167 assert(expr);
2168
2169 TQ_FOR(v, &(expr->members), next) {
2170 if(v->expr_type == A1TC_EXTENSIBLE) {
2171 extensible++;
2172 break;
2173 }
2174 eidx++;
2175 }
2176
2177 memset(&tmprng, 0, sizeof (tmprng));
2178 tmprng.extensible = extensible;
2179 if(eidx < 0) tmprng.empty_constraint = 1;
2180 tmprng.left.type = ARE_VALUE;
2181 tmprng.left.value = 0;
2182 tmprng.right.type = ARE_VALUE;
2183 tmprng.right.value = eidx < 0 ? 0 : eidx;
Lev Walkin725883b2006-10-09 12:07:58 +00002184 if(emit_single_member_PER_constraint(arg, &tmprng, 0, 0))
Lev Walkin59b176e2005-11-26 11:25:14 +00002185 return -1;
Lev Walkin729eb862006-09-21 01:50:13 +00002186 } else if(etype & ASN_STRING_KM_MASK) {
Lev Walkina28cbb92017-07-31 20:20:17 -07002187 range = asn1constraint_compute_PER_range(expr->Identifier, etype,
Lev Walkin729eb862006-09-21 01:50:13 +00002188 expr->combined_constraints, ACT_CT_FROM,
2189 0, 0, 0);
Lev Walkin725883b2006-10-09 12:07:58 +00002190 DEBUG("Emitting FROM constraint for %s", expr->Identifier);
Lev Walkin3a4689a2006-11-24 11:20:27 +00002191
2192 if((range->left.type == ARE_MIN && range->right.type == ARE_MAX)
2193 || range->not_PER_visible) {
2194 switch(etype) {
2195 case ASN_STRING_BMPString:
2196 range->left.type = ARE_VALUE;
2197 range->left.value = 0;
2198 range->right.type = ARE_VALUE;
2199 range->right.value = 65535;
2200 range->not_PER_visible = 0;
2201 range->extensible = 0;
2202 break;
2203 case ASN_STRING_UniversalString:
2204 OUT("{ APC_CONSTRAINED,\t32, 32,"
2205 " 0, 2147483647 }"
2206 " /* special case 1 */\n");
2207 goto avoid;
2208 default:
2209 break;
2210 }
2211 }
Lev Walkin725883b2006-10-09 12:07:58 +00002212 if(emit_single_member_PER_constraint(arg, range, 1, 0))
Lev Walkin729eb862006-09-21 01:50:13 +00002213 return -1;
Lev Walkin3a4689a2006-11-24 11:20:27 +00002214 avoid:
Lev Walkin729eb862006-09-21 01:50:13 +00002215 asn1constraint_range_free(range);
Lev Walkin59b176e2005-11-26 11:25:14 +00002216 } else {
Lev Walkina28cbb92017-07-31 20:20:17 -07002217 range = asn1constraint_compute_PER_range(expr->Identifier, etype,
Lev Walkin59b176e2005-11-26 11:25:14 +00002218 expr->combined_constraints, ACT_EL_RANGE,
2219 0, 0, 0);
Lev Walkin725883b2006-10-09 12:07:58 +00002220 if(emit_single_member_PER_constraint(arg, range, 0, 0))
Lev Walkin59b176e2005-11-26 11:25:14 +00002221 return -1;
2222 asn1constraint_range_free(range);
2223 }
2224 OUT(",\n");
2225
Lev Walkina28cbb92017-07-31 20:20:17 -07002226 range = asn1constraint_compute_PER_range(expr->Identifier, etype,
Lev Walkin59b176e2005-11-26 11:25:14 +00002227 expr->combined_constraints, ACT_CT_SIZE, 0, 0, 0);
Lev Walkin725883b2006-10-09 12:07:58 +00002228 if(emit_single_member_PER_constraint(arg, range, 0, "SIZE"))
Lev Walkin59b176e2005-11-26 11:25:14 +00002229 return -1;
2230 asn1constraint_range_free(range);
Lev Walkin725883b2006-10-09 12:07:58 +00002231 OUT(",\n");
2232
2233 if((etype & ASN_STRING_KM_MASK) && (expr->_mark & TM_PERFROMCT)) {
2234 int old_target = arg->target->target;
2235 REDIR(OT_CODE);
2236
2237 OUT("static int asn_PER_MAP_%s_%d_v2c(unsigned int value) {\n",
2238 MKID(expr), expr->_type_unique_index);
2239 OUT("\tif(value >= sizeof(permitted_alphabet_table_%d)/"
2240 "sizeof(permitted_alphabet_table_%d[0]))\n",
2241 expr->_type_unique_index,
2242 expr->_type_unique_index);
2243 OUT("\t\treturn -1;\n");
2244 OUT("\treturn permitted_alphabet_table_%d[value] - 1;\n",
2245 expr->_type_unique_index);
2246 OUT("}\n");
2247
2248 OUT("static int asn_PER_MAP_%s_%d_c2v(unsigned int code) {\n",
2249 MKID(expr), expr->_type_unique_index);
2250 OUT("\tif(code >= sizeof(permitted_alphabet_code2value_%d)/"
2251 "sizeof(permitted_alphabet_code2value_%d[0]))\n",
2252 expr->_type_unique_index,
2253 expr->_type_unique_index);
2254 OUT("\t\treturn -1;\n");
2255 OUT("\treturn permitted_alphabet_code2value_%d[code];\n",
2256 expr->_type_unique_index);
2257 OUT("}\n");
2258
2259 REDIR(old_target);
2260
2261 OUT("asn_PER_MAP_%s_%d_v2c,\t/* Value to PER code map */\n",
2262 MKID(expr), expr->_type_unique_index);
2263 OUT("asn_PER_MAP_%s_%d_c2v\t/* PER code to value map */\n",
2264 MKID(expr), expr->_type_unique_index);
2265 } else if(etype & ASN_STRING_KM_MASK) {
2266 DEBUG("No PER value map necessary for %s", MKID(expr));
2267 OUT("0, 0\t/* No PER character map necessary */\n");
2268 } else {
2269 OUT("0, 0\t/* No PER value map */\n");
2270 }
Lev Walkin59b176e2005-11-26 11:25:14 +00002271
2272 INDENT(-1);
2273
Lev Walkin725883b2006-10-09 12:07:58 +00002274 OUT("};\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002275
Lev Walkin725883b2006-10-09 12:07:58 +00002276 REDIR(save_target);
Lev Walkin59b176e2005-11-26 11:25:14 +00002277
2278 return 0;
2279}
2280
2281static int
Lev Walkin8032f7a2007-06-27 01:54:57 +00002282safe_string(const uint8_t *buf, int size) {
2283 const uint8_t *end = buf + size;
2284 for(; buf < end; buf++) {
2285 int ch = *buf;
2286 if((ch < 0x20 || ch > 0x7e) || ch == '"')
2287 return 0;
2288 }
2289 return 1;
2290}
2291
2292static void
2293emit_default_value(arg_t *arg, asn1p_value_t *v) {
2294
2295 OUT("static uint8_t defv[] = ");
2296 assert(v->type == ATV_STRING);
2297
2298 if(safe_string(v->value.string.buf, v->value.string.size)) {
2299 OUT("\"%s\";\n", v->value.string.buf);
2300 } else {
2301 uint8_t *b = v->value.string.buf;
2302 uint8_t *e = v->value.string.size + b;
2303 OUT("{ ");
2304 for(;b < e; b++)
2305 OUT("0x%02x, ", *b);
2306 OUT("0 };\n");
2307 }
2308}
2309
2310static int
Lev Walkin59b176e2005-11-26 11:25:14 +00002311try_inline_default(arg_t *arg, asn1p_expr_t *expr, int out) {
2312 int save_target = arg->target->target;
2313 asn1p_expr_type_e etype = expr_get_type(arg, expr);
2314 int fits_long = 0;
2315
2316 switch(etype) {
2317 case ASN_BASIC_BOOLEAN:
2318 fits_long = 1;
2319 case ASN_BASIC_INTEGER:
2320 case ASN_BASIC_ENUMERATED:
2321 if(expr->marker.default_value == NULL
Ryan Sleevia93d9972017-08-16 18:27:46 -04002322 || (expr->marker.default_value->type != ATV_INTEGER &&
2323 expr->marker.default_value->type != ATV_TRUE &&
2324 expr->marker.default_value->type != ATV_FALSE))
Lev Walkin59b176e2005-11-26 11:25:14 +00002325 break;
2326 if(!fits_long)
2327 fits_long = asn1c_type_fits_long(arg, expr)!=FL_NOTFIT;
2328 if(fits_long && !expr->marker.default_value->value.v_integer)
2329 expr->marker.flags &= ~EM_INDIRECT;
Lev Walkin8032f7a2007-06-27 01:54:57 +00002330 if(!out) {
Lev Walkinda997b12017-08-04 01:38:41 -07002331 OUT("asn_DFL_%d_set_%s,",
Lev Walkin8032f7a2007-06-27 01:54:57 +00002332 expr->_type_unique_index,
Lev Walkinda997b12017-08-04 01:38:41 -07002333 asn1p_itoa(expr->marker.default_value->value.v_integer));
2334 OUT("\t/* DEFAULT %s */\n",
2335 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin8032f7a2007-06-27 01:54:57 +00002336 return 1;
2337 }
Lev Walkin59b176e2005-11-26 11:25:14 +00002338 REDIR(OT_STAT_DEFS);
Lev Walkinda997b12017-08-04 01:38:41 -07002339 OUT("static int asn_DFL_%d_set_%s(int set_value, void **sptr) {\n",
Lev Walkin59b176e2005-11-26 11:25:14 +00002340 expr->_type_unique_index,
Lev Walkinda997b12017-08-04 01:38:41 -07002341 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin59b176e2005-11-26 11:25:14 +00002342 INDENT(+1);
2343 OUT("%s *st = *sptr;\n", asn1c_type_name(arg, expr, TNF_CTYPE));
2344 OUT("\n");
2345 OUT("if(!st) {\n");
Lev Walkin1dc85292006-08-18 01:32:26 +00002346 OUT("\tif(!set_value) return -1;\t/* Not a default value */\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002347 OUT("\tst = (*sptr = CALLOC(1, sizeof(*st)));\n");
2348 OUT("\tif(!st) return -1;\n");
2349 OUT("}\n");
2350 OUT("\n");
Lev Walkin1dc85292006-08-18 01:32:26 +00002351 OUT("if(set_value) {\n");
2352 INDENT(+1);
Lev Walkinda997b12017-08-04 01:38:41 -07002353 OUT("/* Install default value %s */\n",
2354 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin59b176e2005-11-26 11:25:14 +00002355 if(fits_long) {
Lev Walkin63b41262007-11-06 01:48:46 +00002356 OUT("*st = ");
2357 OINT(expr->marker.default_value->value.v_integer);
2358 OUT(";\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002359 OUT("return 0;\n");
2360 } else {
Lev Walkin63b41262007-11-06 01:48:46 +00002361 OUT("return asn_long2INTEGER(st, ");
2362 OINT(expr->marker.default_value->value.v_integer);
2363 OUT(");\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002364 }
2365 INDENT(-1);
Lev Walkin1dc85292006-08-18 01:32:26 +00002366 OUT("} else {\n");
2367 INDENT(+1);
Lev Walkinda997b12017-08-04 01:38:41 -07002368 OUT("/* Test default value %s */\n",
2369 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin1dc85292006-08-18 01:32:26 +00002370 if(fits_long) {
Lev Walkinda997b12017-08-04 01:38:41 -07002371 OUT("return (*st == %s);\n",
2372 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin1dc85292006-08-18 01:32:26 +00002373 } else {
2374 OUT("long value;\n");
2375 OUT("if(asn_INTEGER2long(st, &value))\n");
2376 OUT("\treturn -1;\n");
Lev Walkinda997b12017-08-04 01:38:41 -07002377 OUT("return (value == %s);\n",
2378 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin1dc85292006-08-18 01:32:26 +00002379 }
2380 INDENT(-1);
2381 OUT("}\n");
2382 INDENT(-1);
Lev Walkin59b176e2005-11-26 11:25:14 +00002383 OUT("}\n");
2384 REDIR(save_target);
2385 return 1;
2386 case ASN_BASIC_NULL:
2387 //expr->marker.flags &= ~EM_INDIRECT;
2388 return 0;
2389 default:
Lev Walkin8032f7a2007-06-27 01:54:57 +00002390 if(etype & ASN_STRING_KM_MASK) {
2391 if(expr->marker.default_value == NULL
2392 || expr->marker.default_value->type != ATV_STRING)
2393 break;
2394 if(!out) {
2395 OUT("asn_DFL_%d_set,\t/* DEFAULT \"%s\" */\n",
2396 expr->_type_unique_index,
2397 expr->marker.default_value->value.string.buf);
2398 return 1;
2399 }
2400 REDIR(OT_STAT_DEFS);
2401 OUT("static int asn_DFL_%d_set(int set_value, void **sptr) {\n", expr->_type_unique_index);
2402 INDENT(+1);
2403 emit_default_value(arg, expr->marker.default_value);
2404 OUT("%s *st = *sptr;\n", asn1c_type_name(arg, expr, TNF_CTYPE));
2405 OUT("\n");
2406 OUT("if(!st) {\n");
2407 OUT("\tif(!set_value) return -1;\t/* Not a default value */\n");
2408 OUT("\tst = (*sptr = CALLOC(1, sizeof(*st)));\n");
2409 OUT("\tif(!st) return -1;\n");
2410 OUT("}\n");
2411 OUT("\n");
2412 OUT("if(set_value) {\n");
2413 INDENT(+1);
2414 OUT("uint8_t *ptr = MALLOC(sizeof(defv));\n");
2415 OUT("if(!ptr) return -1;\n");
2416 OUT("memcpy(ptr, &defv, sizeof(defv));\n");
2417 OUT("FREEMEM(st->buf);\n");
2418 OUT("st->buf = ptr;\n");
2419 OUT("st->size = sizeof(defv) - 1;\n");
2420 OUT("return 0;\n");
2421 INDENT(-1);
2422 OUT("} else {\n");
2423 INDENT(+1);
2424 OUT("if(st->size != (sizeof(defv) - 1)\n");
2425 OUT("|| memcmp(st->buf, &defv, sizeof(defv) - 1))\n");
2426 OUT("\treturn 0;\n");
2427 OUT("return 1;\n");
2428 INDENT(-1);
2429 OUT("}\n"); OUT("\n");
2430 INDENT(-1);
2431 OUT("}\n");
2432 REDIR(save_target);
2433 return 1;
2434 }
2435 break;
Lev Walkin59b176e2005-11-26 11:25:14 +00002436 }
2437 return 0;
2438}
2439
Lev Walkin59004fa2004-08-20 13:37:01 +00002440static int
Lev Walkin9de6cd82017-08-10 05:47:46 -07002441emit_member_type_selector(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_objset_t *opt_ioc) {
2442 int save_target = arg->target->target;
2443 asn1p_expr_t *parent_expr = arg->expr;
2444
2445 const asn1p_constraint_t *crc =
2446 asn1p_get_component_relation_constraint(expr->combined_constraints);
2447 if(!crc || crc->el_count <= 1) {
2448 /* Not an Open Type, it seems. */
2449 OUT("0");
2450 return 0;
2451 }
2452
Lev Walkind8e07c52017-08-23 07:38:30 -07002453 const asn1p_ref_t *objset_ref =
2454 asn1c_get_information_object_set_reference_from_constraint(arg, crc);
2455
Lev Walkinade508c2017-08-23 10:19:30 -07002456 if(!objset_ref) {
2457 FATAL("Constraint %s does not look like it referst to a set type %s",
2458 asn1p_constraint_string(crc),
2459 opt_ioc->objset->Identifier);
Lev Walkin9de6cd82017-08-10 05:47:46 -07002460 return -1;
2461 }
2462
Lev Walkinade508c2017-08-23 10:19:30 -07002463 const char *objset_name;
2464 if(objset_ref->comp_count == 1) {
2465 objset_name = objset_ref->components[0].name;
2466 } else if(objset_ref->comp_count == 2) {
2467 if(strcmp(objset_ref->components[0].name,
2468 opt_ioc->objset->module->ModuleName)
2469 != 0) {
2470 FATAL(
2471 "Composite reference %s (from %s) does not look like it refers "
2472 "to the same module as %s from an object set type %s",
2473 asn1p_ref_string(objset_ref), asn1p_constraint_string(crc),
2474 opt_ioc->objset->module->ModuleName,
2475 opt_ioc->objset->Identifier);
2476 return -1;
2477 }
2478 objset_name = objset_ref->components[1].name;
2479 } else {
2480 FATAL("Reference %s (from %s) does not look like an object set type %s",
2481 asn1p_ref_string(objset_ref), asn1p_constraint_string(crc),
2482 opt_ioc->objset->Identifier);
2483 return -1;
2484 }
Lev Walkin9de6cd82017-08-10 05:47:46 -07002485 if(strcmp(objset_name, opt_ioc->objset->Identifier) != 0) {
2486 FATAL("Object Set references do not match: %s != %s", objset_name,
2487 opt_ioc->objset->Identifier);
2488 return -1;
2489 }
2490
2491 if(crc->el_count != 2 || crc->elements[1]->type != ACT_EL_VALUE
2492 || crc->elements[1]->value->type != ATV_REFERENCED
2493 || crc->elements[1]->value->value.reference->comp_count != 1) {
2494 FATAL(
2495 "Do not know how to handle complex IoS constraints (%d components "
2496 "of constraint, %d components of reference %s) for %s at line "
2497 "%d",
2498 crc->el_count,
2499 crc->el_count >= 2 && crc->elements[1]->type == ACT_EL_VALUE
2500 && crc->elements[1]->value->type == ATV_REFERENCED
Lev Walkin5d929d82017-08-10 15:17:44 -07002501 ? (signed)crc->elements[1]->value->value.reference->comp_count
Lev Walkin9de6cd82017-08-10 05:47:46 -07002502 : -1,
2503 crc->el_count >= 2 && crc->elements[1]->type == ACT_EL_VALUE
2504 && crc->elements[1]->value->type == ATV_REFERENCED
2505 ? asn1p_ref_string(crc->elements[1]->value->value.reference)
2506 : "?",
2507 MKID(parent_expr), parent_expr->_lineno);
2508 OUT("0");
2509 return -1;
2510 }
2511
2512 const asn1p_ref_t *cref = crc->elements[1]->value->value.reference;
2513 const char *cname = cref->components[0].name;
2514 if(cname[0] == '@' && cname[1] != '.') {
2515 cname += 1;
2516 } else if(cname[0] == '@' && cname[1] == '.' && cname[2] != '.') {
2517 cname += 2;
2518 } else {
2519 FATAL("Complex IoS reference %s can not be processed",
2520 asn1p_ref_string(cref));
2521 OUT("0");
2522 return -1;
2523 }
2524
2525 assert(opt_ioc != NULL);
2526
Lev Walkinf6853ce2017-08-11 00:50:27 -07002527 asn1p_expr_t *constraining_memb = NULL;
2528 TQ_FOR(constraining_memb, &(parent_expr->members), next) {
2529 if(strcmp(constraining_memb->Identifier, cname) == 0) {
Lev Walkin9de6cd82017-08-10 05:47:46 -07002530 break;
Lev Walkinf6853ce2017-08-11 00:50:27 -07002531 }
Lev Walkin9de6cd82017-08-10 05:47:46 -07002532 }
2533 if(!constraining_memb) {
2534 FATAL("Can not find \"%s\" in %s at line %d", cname, MKID(parent_expr),
2535 parent_expr->_lineno);
2536 return -1;
2537 }
2538
2539 if(constraining_memb->meta_type != AMT_TYPEREF
2540 || constraining_memb->expr_type != A1TC_REFERENCE
2541 || constraining_memb->reference->comp_count != 2
2542 || constraining_memb->reference->components[1].lex_type
2543 != RLT_Amplowercase) {
2544 FATAL(
2545 "Does not look like %s is a CLASS field reference (%s) on line "
2546 "%d",
2547 MKID(constraining_memb),
2548 constraining_memb->reference
2549 ? asn1p_ref_string(constraining_memb->reference)
2550 : "<no reference>",
2551 constraining_memb->_lineno);
2552 return -1;
2553 }
2554 const char *cfield = constraining_memb->reference->components[1].name;
2555
2556 ssize_t constraining_column = -1;
2557 for(size_t cn = 0; cn < opt_ioc->ioct->rows ? opt_ioc->ioct->row[0]->columns : 0;
2558 cn++) {
2559 if(strcmp(cfield, opt_ioc->ioct->row[0]->column[cn].field->Identifier)
2560 == 0) {
2561 constraining_column = cn;
2562 break;
2563 }
2564 }
2565 if(constraining_column < 0) {
Lev Walkin53a28a22017-08-23 09:56:53 -07002566 if(opt_ioc->ioct->rows == 0) {
2567 OUT("0");
2568 return 0;
2569 } else {
2570 FATAL("Can not find referenced object class %s column %s\n",
2571 asn1p_ref_string(objset_ref), cfield);
2572 return -1;
2573 }
Lev Walkin9de6cd82017-08-10 05:47:46 -07002574 }
2575
2576 if(expr->meta_type != AMT_TYPEREF
2577 || expr->expr_type != A1TC_REFERENCE
2578 || expr->reference->comp_count != 2
2579 || expr->reference->components[1].lex_type
2580 != RLT_AmpUppercase) {
2581 FATAL(
2582 "Does not look like %s is a CLASS field reference (%s) denoting a type on line "
2583 "%d",
2584 MKID(expr),
2585 expr->reference
2586 ? asn1p_ref_string(expr->reference)
2587 : "<no reference>",
2588 expr->_lineno);
2589 return -1;
2590 }
2591 const char *for_field = expr->reference->components[1].name;
2592
2593 ssize_t for_column = -1;
2594 for(size_t cn = 0; cn < opt_ioc->ioct->rows ? opt_ioc->ioct->row[0]->columns : 0;
2595 cn++) {
2596 if(strcmp(for_field,
2597 opt_ioc->ioct->row[0]->column[cn].field->Identifier)
2598 == 0) {
2599 for_column = cn;
2600 break;
2601 }
2602 }
2603 if(for_column < 0) {
2604 FATAL("Can not find referenced object class column %s\n", for_field);
2605 return -1;
2606 }
2607
2608
2609 REDIR(OT_CODE);
Lev Walkinf6853ce2017-08-11 00:50:27 -07002610 OUT("static asn_type_selector_result_t\n");
Lev Walkin9de6cd82017-08-10 05:47:46 -07002611 OUT("select_%s_type(const asn_TYPE_descriptor_t *parent_type, const void *parent_sptr) {\n", MKID_safe(expr));
2612 INDENT(+1);
2613
Lev Walkinf6853ce2017-08-11 00:50:27 -07002614 OUT("asn_type_selector_result_t result = {0, 0};\n");
Lev Walkin6aae7c62017-08-10 17:58:48 -07002615 OUT("const asn_ioc_set_t *itable = asn_IOS_%s_%d;\n", MKID(opt_ioc->objset),
Lev Walkin9de6cd82017-08-10 05:47:46 -07002616 opt_ioc->objset->_type_unique_index);
2617 OUT("size_t constraining_column = %zu; /* %s */\n", constraining_column, cfield);
2618 OUT("size_t for_column = %zu; /* %s */\n", for_column, for_field);
2619 OUT("size_t row;\n");
2620
2621 const char *tname = asn1c_type_name(arg, constraining_memb, TNF_SAFE);
2622 if(constraining_memb->marker.flags & EM_INDIRECT) {
Lev Walkin6aae7c62017-08-10 17:58:48 -07002623 OUT("const void *memb_ptr = *(const void **)");
Lev Walkinb46156d2017-09-05 02:53:05 -07002624 OUT("((const char *)parent_sptr + offsetof(%s", c_name(arg).full_name);
Lev Walkin9de6cd82017-08-10 05:47:46 -07002625 OUT(", %s));", MKID_safe(constraining_memb));
Lev Walkinf6853ce2017-08-11 00:50:27 -07002626 OUT("if(!memb_ptr) return result;\n");
Lev Walkin9de6cd82017-08-10 05:47:46 -07002627 OUT("\n");
2628 }
2629
2630 switch(asn1c_type_fits_long(arg, constraining_memb)) {
2631 case FL_NOTFIT:
2632 OUT("const %s_t *constraining_value = (const %s_t *)", tname, tname);
2633 break;
2634 case FL_PRESUMED:
2635 case FL_FITS_SIGNED:
2636 OUT("const long *constraining_value = (const long *)");
2637 break;
2638 case FL_FITS_UNSIGN:
2639 OUT("const unsigned long *constraining_value = (const unsigned long *)");
2640 break;
2641 }
2642 if(constraining_memb->marker.flags & EM_INDIRECT) {
2643 OUT("memb_ptr;\n");
2644 } else {
Lev Walkinb46156d2017-09-05 02:53:05 -07002645 OUT("((const char *)parent_sptr + offsetof(%s", c_name(arg).full_name);
Lev Walkin9de6cd82017-08-10 05:47:46 -07002646 OUT(", %s));\n", MKID_safe(constraining_memb));
2647 }
2648 OUT("\n");
2649
2650 OUT("for(row=0; row < itable->rows_count; row++) {\n");
Lev Walkin6aae7c62017-08-10 17:58:48 -07002651 OUT(" const asn_ioc_cell_t *constraining_cell = &itable->rows[row * itable->columns_count + constraining_column];\n");
2652 OUT(" const asn_ioc_cell_t *type_cell = &itable->rows[row * itable->columns_count + for_column];\n");
2653 OUT("\n");
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +08002654 OUT(" if(constraining_cell->type_descriptor->op->compare_struct(constraining_cell->type_descriptor, constraining_value, constraining_cell->value_sptr) == 0) {\n");
Lev Walkinf6853ce2017-08-11 00:50:27 -07002655 OUT(" result.type_descriptor = type_cell->type_descriptor;\n");
2656 OUT(" result.presence_index = row + 1;\n");
2657 OUT(" break;\n");
Lev Walkin9de6cd82017-08-10 05:47:46 -07002658 OUT(" }\n");
2659 OUT("}\n");
2660
2661
2662 OUT("\n");
Lev Walkinf6853ce2017-08-11 00:50:27 -07002663 OUT("return result;\n");
Lev Walkin9de6cd82017-08-10 05:47:46 -07002664 INDENT(-1);
2665 OUT("}\n");
2666 OUT("\n");
2667
2668 REDIR(save_target);
2669 OUT("select_%s_type", MKID_safe(expr));
2670
2671 return 0;
2672}
2673
2674static int
2675emit_member_table(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_objset_t *opt_ioc) {
Lev Walkin59004fa2004-08-20 13:37:01 +00002676 int save_target;
2677 arg_t tmp_arg;
Lev Walkinb9189732004-09-10 09:37:12 +00002678 struct asn1p_type_tag_s outmost_tag_s;
2679 struct asn1p_type_tag_s *outmost_tag;
Lev Walkine0b56e02005-02-25 12:10:27 +00002680 int complex_contents;
Lev Walkincf3f6eb2017-08-23 04:34:15 -07002681 const char *p;
Lev Walkin59004fa2004-08-20 13:37:01 +00002682
Lev Walkinc0e03b92017-08-22 01:48:23 -07002683 if(WITH_MODULE_NAMESPACE(
2684 expr->module, expr_ns,
2685 asn1f_fetch_outmost_tag(arg->asn, expr_ns, expr->module, expr,
2686 &outmost_tag_s, AFT_IMAGINARY_ANY))) {
2687 outmost_tag = 0;
Lev Walkinb9189732004-09-10 09:37:12 +00002688 } else {
2689 outmost_tag = &outmost_tag_s;
2690 }
2691
Lev Walkin59004fa2004-08-20 13:37:01 +00002692 OUT("{ ");
Lev Walkinb9189732004-09-10 09:37:12 +00002693
Lev Walkin14fd3e52017-08-27 01:38:45 -07002694 if(is_open_type(arg, expr, opt_ioc)) {
Lev Walkinf6853ce2017-08-11 00:50:27 -07002695 OUT("ATF_OPEN_TYPE | ");
Lev Walkin14fd3e52017-08-27 01:38:45 -07002696 } else if(outmost_tag && outmost_tag->tag_value == -1) {
2697 OUT("ATF_ANY_TYPE | ");
Lev Walkinf6853ce2017-08-11 00:50:27 -07002698 }
2699 OUT("%s, ",
Lev Walkinc8285712005-03-04 22:18:20 +00002700 (expr->marker.flags & EM_INDIRECT)?"ATF_POINTER":"ATF_NOFLAGS");
Lev Walkinb85a8132005-08-18 13:38:19 +00002701 if((expr->marker.flags & EM_OMITABLE) == EM_OMITABLE) {
Lev Walkin59004fa2004-08-20 13:37:01 +00002702 asn1p_expr_t *tv;
2703 int opts = 0;
Lev Walkinb85a8132005-08-18 13:38:19 +00002704 for(tv = expr;
2705 tv && (tv->marker.flags & EM_OMITABLE) == EM_OMITABLE;
Lev Walkin59004fa2004-08-20 13:37:01 +00002706 tv = TQ_NEXT(tv, next), opts++) {
2707 if(tv->expr_type == A1TC_EXTENSIBLE)
2708 opts--;
2709 }
2710 OUT("%d, ", opts);
2711 } else {
2712 OUT("0, ");
2713 }
Lev Walkinf6853ce2017-08-11 00:50:27 -07002714 if(expr->_anonymous_type) {
2715 assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
2716 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
2717 OUT("0,\n");
2718 } else {
Lev Walkinb46156d2017-09-05 02:53:05 -07002719 OUT("offsetof(%s, ", c_name(arg).full_name);
Lev Walkinf6853ce2017-08-11 00:50:27 -07002720 if((arg->expr->expr_type == ASN_CONSTR_CHOICE
2721 || arg->expr->expr_type == ASN_CONSTR_OPEN_TYPE)
2722 && (!UNNAMED_UNIONS))
2723 OUT("choice.");
2724 OUT("%s),\n", MKID_safe(expr));
2725 }
2726
2727 INDENT(+1);
Lev Walkin59004fa2004-08-20 13:37:01 +00002728 if(C99_MODE) OUT(".tag = ");
Lev Walkinb9189732004-09-10 09:37:12 +00002729 if(outmost_tag) {
2730 if(outmost_tag->tag_value == -1)
2731 OUT("-1 /* Ambiguous tag (ANY?) */");
2732 else
2733 _print_tag(arg, outmost_tag);
Lev Walkinc3e29402004-09-10 06:07:18 +00002734 } else {
Lev Walkinb9189732004-09-10 09:37:12 +00002735 OUT("-1 /* Ambiguous tag (CHOICE?) */");
Lev Walkinc3e29402004-09-10 06:07:18 +00002736 }
Lev Walkinb9189732004-09-10 09:37:12 +00002737
Lev Walkin59004fa2004-08-20 13:37:01 +00002738 OUT(",\n");
2739 if(C99_MODE) OUT(".tag_mode = ");
Lev Walkin9ab21b82006-10-19 02:46:01 +00002740 if((!(expr->expr_type & ASN_CONSTR_MASK)
2741 || expr->expr_type == ASN_CONSTR_CHOICE)
2742 && expr->tag.tag_class) {
Lev Walkin59004fa2004-08-20 13:37:01 +00002743 if(expr->tag.tag_mode == TM_IMPLICIT)
2744 OUT("-1,\t/* IMPLICIT tag at current level */\n");
2745 else
2746 OUT("+1,\t/* EXPLICIT tag at current level */\n");
2747 } else {
2748 OUT("0,\n");
2749 }
Lev Walkine0b56e02005-02-25 12:10:27 +00002750
2751 complex_contents =
Lev Walkinf6853ce2017-08-11 00:50:27 -07002752 is_open_type(arg, expr, opt_ioc)
2753 || (expr->expr_type & ASN_CONSTR_MASK)
Lev Walkine0b56e02005-02-25 12:10:27 +00002754 || expr->expr_type == ASN_BASIC_ENUMERATED
Lev Walkin8ecf9db2005-03-03 21:28:12 +00002755 || (0 /* -- prohibited by X.693:8.3.4 */
2756 && expr->expr_type == ASN_BASIC_INTEGER
Lev Walkin8bb57a22007-12-03 13:41:36 +00002757 && expr_elements_count(arg, expr))
2758 || (expr->expr_type == ASN_BASIC_INTEGER
2759 && asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN);
Lev Walkin59004fa2004-08-20 13:37:01 +00002760 if(C99_MODE) OUT(".type = ");
Lev Walkinf6853ce2017-08-11 00:50:27 -07002761
2762 OUT("&asn_DEF_");
2763 if(complex_contents) {
2764 OUT("%s", MKID(expr));
2765 if(!(arg->flags & A1C_ALL_DEFS_GLOBAL))
2766 OUT("_%d", expr->_type_unique_index);
2767 } else {
2768 OUT("%s", asn1c_type_name(arg, expr, TNF_SAFE));
2769 }
2770 OUT(",\n");
Lev Walkin9de6cd82017-08-10 05:47:46 -07002771
2772
2773 if(C99_MODE) OUT(".type_selector = ");
2774 if(opt_ioc) {
Lev Walkind8e07c52017-08-23 07:38:30 -07002775 if(emit_member_type_selector(arg, expr, opt_ioc) < 0)
2776 return -1;
Lev Walkin9de6cd82017-08-10 05:47:46 -07002777 } else {
2778 OUT("0");
2779 }
2780 OUT(",\n");
2781
Lev Walkin14e75ed2017-09-29 23:15:02 -07002782 OUT("{ ");
2783 if(C99_MODE) OUT(".oer_constraints = ");
2784 if(arg->flags & A1C_GEN_OER) {
2785 if(expr->constraints) {
2786 OUT("&asn_OER_memb_%s_constr_%d",
2787 MKID(expr),
2788 expr->_type_unique_index);
2789 } else {
2790 OUT("0");
2791 }
2792 } else {
2793 OUT("0");
2794 }
2795 OUT(", ");
2796 if(C99_MODE) OUT(".per_constraints = ");
2797 if(arg->flags & A1C_GEN_PER) {
2798 if(expr->constraints) {
2799 OUT("&asn_PER_memb_%s_constr_%d",
2800 MKID(expr),
2801 expr->_type_unique_index);
2802 } else {
2803 OUT("0");
2804 }
2805 } else {
2806 OUT("0");
2807 }
2808 OUT(", ");
2809 if(C99_MODE) OUT(".general_constraints = ");
Lev Walkin59004fa2004-08-20 13:37:01 +00002810 if(expr->constraints) {
Lev Walkin8de2ab22004-09-26 13:11:31 +00002811 if(arg->flags & A1C_NO_CONSTRAINTS) {
Lev Walkin14e75ed2017-09-29 23:15:02 -07002812 OUT("0");
Lev Walkin8de2ab22004-09-26 13:11:31 +00002813 } else {
Lev Walkincf3f6eb2017-08-23 04:34:15 -07002814 const char *id = MKID(expr);
Lev Walkin8de2ab22004-09-26 13:11:31 +00002815 if(expr->_anonymous_type
Lev Walkin152a91e2005-02-14 20:41:29 +00002816 && !strcmp(expr->Identifier, "Member"))
Lev Walkin8de2ab22004-09-26 13:11:31 +00002817 id = asn1c_type_name(arg, expr, TNF_SAFE);
Lev Walkin14e75ed2017-09-29 23:15:02 -07002818 OUT(" memb_%s_constraint_%d", id,
Lev Walkin21d00002005-03-04 08:48:53 +00002819 arg->expr->_type_unique_index);
Lev Walkin8de2ab22004-09-26 13:11:31 +00002820 }
Lev Walkin59004fa2004-08-20 13:37:01 +00002821 } else {
Lev Walkin14e75ed2017-09-29 23:15:02 -07002822 OUT("0");
Lev Walkin59004fa2004-08-20 13:37:01 +00002823 }
Lev Walkin14e75ed2017-09-29 23:15:02 -07002824 OUT(" },\n");
2825
Lev Walkin59b176e2005-11-26 11:25:14 +00002826 if(C99_MODE) OUT(".default_value = ");
2827 if(try_inline_default(arg, expr, 0)) {
Lev Walkin59b176e2005-11-26 11:25:14 +00002828 } else {
2829 OUT("0,\n");
2830 }
2831 if(C99_MODE) OUT(".name = ");
2832 if(expr->_anonymous_type && !strcmp(expr->Identifier, "Member")) {
2833 OUT("\"\"\n");
2834 } else {
2835 OUT("\"%s\"\n", expr->Identifier);
Lev Walkin152a91e2005-02-14 20:41:29 +00002836 }
Lev Walkin59004fa2004-08-20 13:37:01 +00002837 OUT("},\n");
2838 INDENT(-1);
2839
Lev Walkin8de2ab22004-09-26 13:11:31 +00002840 if(!expr->constraints || (arg->flags & A1C_NO_CONSTRAINTS))
Lev Walkin59004fa2004-08-20 13:37:01 +00002841 return 0;
2842
2843 save_target = arg->target->target;
2844 REDIR(OT_CODE);
2845
Lev Walkin152a91e2005-02-14 20:41:29 +00002846 if(expr->_anonymous_type && !strcmp(expr->Identifier, "Member"))
Lev Walkin59004fa2004-08-20 13:37:01 +00002847 p = asn1c_type_name(arg, expr, TNF_SAFE);
Lev Walkina9cc46e2004-09-22 16:06:28 +00002848 else
Lev Walkina00d6b32006-03-21 03:40:38 +00002849 p = MKID(expr);
Lev Walkin59004fa2004-08-20 13:37:01 +00002850 OUT("static int\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002851 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 +00002852 INDENT(+1);
Lev Walkin1eded352006-07-13 11:19:01 +00002853 OUT("\t\tasn_app_constraint_failed_f *ctfailcb, void *app_key) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +00002854 tmp_arg = *arg;
2855 tmp_arg.expr = expr;
Lev Walkin725883b2006-10-09 12:07:58 +00002856 DEBUG("member constraint checking code for %s", p);
Lev Walkin59004fa2004-08-20 13:37:01 +00002857 if(asn1c_emit_constraint_checking_code(&tmp_arg) == 1) {
Lev Walkin14e75ed2017-09-29 23:15:02 -07002858 OUT("return td->encoding_constraints.general_constraints"
Lev Walkin1eded352006-07-13 11:19:01 +00002859 "(td, sptr, ctfailcb, app_key);\n");
Lev Walkin59004fa2004-08-20 13:37:01 +00002860 }
2861 INDENT(-1);
2862 OUT("}\n");
2863 OUT("\n");
2864
Lev Walkin98eabc12017-07-19 08:51:11 +04002865 if(emit_member_OER_constraints(arg, expr, "memb"))
2866 return -1;
2867
Lev Walkin4b5dae32006-10-09 12:27:44 +00002868 if(emit_member_PER_constraints(arg, expr, "memb"))
Lev Walkin725883b2006-10-09 12:07:58 +00002869 return -1;
2870
Lev Walkin59004fa2004-08-20 13:37:01 +00002871 REDIR(save_target);
2872
2873 return 0;
2874}
Lev Walkin59964be2004-08-25 02:03:12 +00002875
Lev Walkindc06f6b2004-10-20 15:50:55 +00002876/*
2877 * Generate "asn_DEF_XXX" type definition.
2878 */
Lev Walkin59964be2004-08-25 02:03:12 +00002879static int
Lev Walkin8de2ab22004-09-26 13:11:31 +00002880emit_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 +00002881 asn1p_expr_t *terminal;
Lev Walkin21d00002005-03-04 08:48:53 +00002882 int using_type_name = 0;
Lev Walkin14e75ed2017-09-29 23:15:02 -07002883 char *expr_id = strdup(MKID(expr));
2884 char *p = expr_id;
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002885 char *p2 = (char *)0;
Lev Walkin59b176e2005-11-26 11:25:14 +00002886
Lev Walkinc0e03b92017-08-22 01:48:23 -07002887 terminal = asn1f_find_terminal_type_ex(arg->asn, arg->ns, expr);
Lev Walkin8c2ca0b2006-09-17 06:31:08 +00002888
Lev Walkin01582a72017-07-26 18:47:08 -07002889 if(emit_member_OER_constraints(arg, expr, "type"))
2890 return -1;
2891
Lev Walkin4b5dae32006-10-09 12:27:44 +00002892 if(emit_member_PER_constraints(arg, expr, "type"))
Lev Walkin725883b2006-10-09 12:07:58 +00002893 return -1;
Lev Walkin59964be2004-08-25 02:03:12 +00002894
Lev Walkindd32b592004-09-06 08:07:29 +00002895 if(HIDE_INNER_DEFS)
2896 OUT("static /* Use -fall-defs-global to expose */\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002897 OUT("asn_TYPE_descriptor_t asn_DEF_%s", p);
Lev Walkinf6853ce2017-08-11 00:50:27 -07002898 if(HIDE_INNER_DEFS || (arg->flags & A1C_ALL_DEFS_GLOBAL))
2899 OUT("_%d", expr->_type_unique_index);
2900 OUT(" = {\n");
Lev Walkin188ed2c2004-09-13 08:31:01 +00002901 INDENT(+1);
Lev Walkin59b176e2005-11-26 11:25:14 +00002902
2903 if(expr->_anonymous_type) {
Lev Walkin14e75ed2017-09-29 23:15:02 -07002904 p = strdup(ASN_EXPR_TYPE2STR(expr->expr_type));
Lev Walkin59b176e2005-11-26 11:25:14 +00002905 OUT("\"%s\",\n", p?p:"");
Lev Walkina00d6b32006-03-21 03:40:38 +00002906 OUT("\"%s\",\n",
2907 p ? asn1c_make_identifier(AMI_CHECK_RESERVED,
2908 0, p, 0) : "");
Lev Walkin59b176e2005-11-26 11:25:14 +00002909 } else {
2910 OUT("\"%s\",\n", expr->Identifier);
2911 OUT("\"%s\",\n", expr->Identifier);
2912 }
Lev Walkin59964be2004-08-25 02:03:12 +00002913
2914 if(expr->expr_type & ASN_CONSTR_MASK) {
Lev Walkin21d00002005-03-04 08:48:53 +00002915 using_type_name = 1;
Lev Walkin14e75ed2017-09-29 23:15:02 -07002916 p = strdup(asn1c_type_name(arg, arg->expr, TNF_SAFE));
Lev Walkin59b176e2005-11-26 11:25:14 +00002917 } else {
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002918 if (expr->expr_type == A1TC_REFERENCE) {
2919 p2 = strdup(asn1c_type_name(arg, terminal, TNF_SAFE));
2920 } else {
2921 p2 = strdup(asn1c_type_name(arg, expr, TNF_SAFE));
2922 }
Lev Walkin14e75ed2017-09-29 23:15:02 -07002923 p = strdup(expr_id);
Lev Walkin59964be2004-08-25 02:03:12 +00002924 }
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002925 if (!p2)
2926 p2 = strdup(p);
Lev Walkin59964be2004-08-25 02:03:12 +00002927
Lev Walkin14e75ed2017-09-29 23:15:02 -07002928 OUT("&asn_OP_%s,\n", p2);
Lev Walkin21d00002005-03-04 08:48:53 +00002929
Lev Walkin59964be2004-08-25 02:03:12 +00002930 if(tags_count) {
Lev Walkin59b176e2005-11-26 11:25:14 +00002931 OUT("asn_DEF_%s_tags_%d,\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -07002932 expr_id, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00002933 OUT("sizeof(asn_DEF_%s_tags_%d)\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -07002934 expr_id, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00002935 OUT("\t/sizeof(asn_DEF_%s_tags_%d[0])",
Lev Walkin14e75ed2017-09-29 23:15:02 -07002936 expr_id, expr->_type_unique_index);
Lev Walkin188ed2c2004-09-13 08:31:01 +00002937 if(tv_mode == _TVM_SUBSET
2938 && tags_count != all_tags_count)
2939 OUT(" - %d", all_tags_count - tags_count);
2940 OUT(", /* %d */\n", tags_count);
Lev Walkin59964be2004-08-25 02:03:12 +00002941 } else {
Lev Walkin188ed2c2004-09-13 08:31:01 +00002942 OUT("0,\t/* No effective tags (pointer) */\n");
2943 OUT("0,\t/* No effective tags (count) */\n");
2944 }
2945
2946 if(all_tags_count && tv_mode == _TVM_DIFFERENT) {
Lev Walkin59b176e2005-11-26 11:25:14 +00002947 OUT("asn_DEF_%s_all_tags_%d,\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -07002948 expr_id, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00002949 OUT("sizeof(asn_DEF_%s_all_tags_%d)\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -07002950 expr_id, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00002951 OUT("\t/sizeof(asn_DEF_%s_all_tags_%d[0]), /* %d */\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -07002952 expr_id, expr->_type_unique_index, all_tags_count);
Lev Walkin188ed2c2004-09-13 08:31:01 +00002953 } else if(all_tags_count) {
Lev Walkin59b176e2005-11-26 11:25:14 +00002954 OUT("asn_DEF_%s_tags_%d,\t/* Same as above */\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -07002955 expr_id, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00002956 OUT("sizeof(asn_DEF_%s_tags_%d)\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -07002957 expr_id, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00002958 OUT("\t/sizeof(asn_DEF_%s_tags_%d[0]), /* %d */\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -07002959 expr_id, expr->_type_unique_index, all_tags_count);
Lev Walkin188ed2c2004-09-13 08:31:01 +00002960 } else {
2961 OUT("0,\t/* No tags (pointer) */\n");
2962 OUT("0,\t/* No tags (count) */\n");
Lev Walkin59964be2004-08-25 02:03:12 +00002963 }
2964
Lev Walkin14e75ed2017-09-29 23:15:02 -07002965 OUT("{ ");
Lev Walkinb33425f2017-07-14 14:59:52 +04002966 if(arg->flags & A1C_GEN_OER) {
Lev Walkin135d7dd2017-08-28 00:21:38 -07002967 if(expr->combined_constraints
Lev Walkinb33425f2017-07-14 14:59:52 +04002968 || expr->expr_type == ASN_BASIC_ENUMERATED
2969 || expr->expr_type == ASN_CONSTR_CHOICE) {
Lev Walkin14e75ed2017-09-29 23:15:02 -07002970 OUT("&asn_OER_type_%s_constr_%d",
2971 expr_id, expr->_type_unique_index);
Lev Walkinb33425f2017-07-14 14:59:52 +04002972 } else {
Lev Walkin14e75ed2017-09-29 23:15:02 -07002973 OUT("0");
Lev Walkinb33425f2017-07-14 14:59:52 +04002974 }
2975 } else {
Lev Walkin14e75ed2017-09-29 23:15:02 -07002976 OUT("0");
Lev Walkinb33425f2017-07-14 14:59:52 +04002977 }
Lev Walkin14e75ed2017-09-29 23:15:02 -07002978 OUT(", ");
Lev Walkinb33425f2017-07-14 14:59:52 +04002979
Lev Walkin59b176e2005-11-26 11:25:14 +00002980 if(arg->flags & A1C_GEN_PER) {
Lev Walkin135d7dd2017-08-28 00:21:38 -07002981 if(expr->combined_constraints
Lev Walkin59b176e2005-11-26 11:25:14 +00002982 || expr->expr_type == ASN_BASIC_ENUMERATED
2983 || expr->expr_type == ASN_CONSTR_CHOICE) {
Lev Walkin14e75ed2017-09-29 23:15:02 -07002984 OUT("&asn_PER_type_%s_constr_%d",
2985 expr_id, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00002986 } else {
Lev Walkin14e75ed2017-09-29 23:15:02 -07002987 OUT("0");
Lev Walkin59b176e2005-11-26 11:25:14 +00002988 }
2989 } else {
Lev Walkin14e75ed2017-09-29 23:15:02 -07002990 OUT("0");
Lev Walkin59b176e2005-11-26 11:25:14 +00002991 }
Lev Walkin14e75ed2017-09-29 23:15:02 -07002992 OUT(", ");
2993#define FUNCREF(foo) \
2994 do { \
2995 OUT("%s", p); \
2996 if(HIDE_INNER_DEFS && !using_type_name) \
2997 OUT("_%d", expr->_type_unique_index); \
2998 OUT("_" #foo ""); \
2999 } while(0)
3000
3001#define FUNCREF2(foo) \
3002 do { \
3003 OUT("%s", p2); \
3004 OUT("_" #foo); \
3005 } while(0)
3006
3007 if (arg->flags & A1C_NO_CONSTRAINTS) {
3008 OUT("0");
3009 } else {
3010 if (!expr->combined_constraints)
3011 FUNCREF2(constraint);
3012 else
3013 FUNCREF(constraint);
3014 }
3015 OUT(" },\n");
3016
3017 free(p);
3018 p = NULL;
3019 free(p2);
3020 p2 = NULL;
3021 free(expr_id);
3022 expr_id = NULL;
Lev Walkin59b176e2005-11-26 11:25:14 +00003023
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003024 if(elements_count ||
3025 ((expr->expr_type == A1TC_REFERENCE) &&
3026 (terminal->expr_type & ASN_CONSTR_MASK) &&
3027 expr_elements_count(arg, terminal))) {
3028
3029 if (expr->expr_type == A1TC_REFERENCE) {
3030 OUT("asn_MBR_%s_%d,\n", MKID(terminal), terminal->_type_unique_index);
3031
3032 if(terminal->expr_type == ASN_CONSTR_SEQUENCE_OF
3033 || terminal->expr_type == ASN_CONSTR_SET_OF) {
3034 OUT("%d,\t/* Single element */\n",
3035 expr_elements_count(arg, terminal));
3036 assert(expr_elements_count(arg, terminal) == 1);
3037 } else {
3038 OUT("%d,\t/* Elements count */\n",
3039 expr_elements_count(arg, terminal));
3040 }
Lev Walkin59964be2004-08-25 02:03:12 +00003041 } else {
Lev Walkin14e75ed2017-09-29 23:15:02 -07003042 OUT("asn_MBR_%s_%d,\n", c_name(arg).part_name,
3043 expr->_type_unique_index);
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003044
Lev Walkin14e75ed2017-09-29 23:15:02 -07003045 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003046 || expr->expr_type == ASN_CONSTR_SET_OF) {
3047 OUT("%d,\t/* Single element */\n",
3048 elements_count);
3049 assert(elements_count == 1);
3050 } else {
3051 OUT("%d,\t/* Elements count */\n",
3052 elements_count);
3053 }
Lev Walkin59964be2004-08-25 02:03:12 +00003054 }
3055 } else {
Lev Walkin59964be2004-08-25 02:03:12 +00003056 if(expr_elements_count(arg, expr))
3057 OUT("0, 0,\t/* Defined elsewhere */\n");
3058 else
3059 OUT("0, 0,\t/* No members */\n");
3060 }
3061
3062 switch(spec) {
3063 case ETD_NO_SPECIFICS:
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003064 if ((expr->expr_type == A1TC_REFERENCE) &&
3065 ((terminal->expr_type & ASN_CONSTR_MASK) ||
3066 (terminal->expr_type == ASN_BASIC_ENUMERATED) ||
3067 ((terminal->expr_type == ASN_BASIC_INTEGER) &&
3068 (asn1c_type_fits_long(arg, terminal) == FL_FITS_UNSIGN)))) {
Lev Walkin14e75ed2017-09-29 23:15:02 -07003069 OUT("&asn_SPC_%s_specs_%d\t/* Additional specs */\n",
3070 c_expr_name(arg, terminal).part_name,
3071 terminal->_type_unique_index);
3072 } else if ((expr->expr_type == ASN_TYPE_ANY) ||
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003073 (expr->expr_type == ASN_BASIC_BIT_STRING) ||
3074 (expr->expr_type == ASN_STRING_BMPString) ||
3075 (expr->expr_type == ASN_BASIC_OCTET_STRING) ||
3076 (expr->expr_type == ASN_STRING_UniversalString)) {
Lev Walkin14e75ed2017-09-29 23:15:02 -07003077 OUT("&asn_SPC_%s_specs\t/* Additional specs */\n",
3078 c_name(arg).type.part_name);
3079 } else if ((expr->expr_type == A1TC_REFERENCE) &&
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003080 ((terminal->expr_type == ASN_TYPE_ANY) ||
3081 (terminal->expr_type == ASN_BASIC_BIT_STRING) ||
3082 (terminal->expr_type == ASN_STRING_BMPString) ||
3083 (terminal->expr_type == ASN_BASIC_OCTET_STRING) ||
3084 (terminal->expr_type == ASN_STRING_UniversalString))) {
Lev Walkin14e75ed2017-09-29 23:15:02 -07003085 OUT("&asn_SPC_%s_specs\t/* Additional specs */\n",
3086 c_expr_name(arg, terminal).type.part_name);
3087 } else {
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003088 OUT("0\t/* No specifics */\n");
3089 }
Lev Walkin59964be2004-08-25 02:03:12 +00003090 break;
3091 case ETD_HAS_SPECIFICS:
Lev Walkin59b176e2005-11-26 11:25:14 +00003092 OUT("&asn_SPC_%s_specs_%d\t/* Additional specs */\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -07003093 c_name(arg).part_name, expr->_type_unique_index);
Lev Walkin59964be2004-08-25 02:03:12 +00003094 }
Lev Walkin188ed2c2004-09-13 08:31:01 +00003095 INDENT(-1);
Lev Walkin59964be2004-08-25 02:03:12 +00003096 OUT("};\n");
3097 OUT("\n");
Lev Walkin97298782004-08-26 06:20:34 +00003098
3099 return 0;
Lev Walkin59964be2004-08-25 02:03:12 +00003100}
Lev Walkincc93b0f2004-09-10 09:18:20 +00003101
Lev Walkina9cc46e2004-09-22 16:06:28 +00003102static int
3103expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkind1bfea62005-11-08 03:06:16 +00003104 /*
3105 * X.680, 25.5, Table 5
3106 */
Lev Walkin59b176e2005-11-26 11:25:14 +00003107 switch(expr_get_type(arg, expr)) {
Lev Walkina9cc46e2004-09-22 16:06:28 +00003108 case ASN_BASIC_BOOLEAN:
3109 case ASN_BASIC_ENUMERATED:
3110 case ASN_BASIC_NULL:
3111 return 1;
Lev Walkind1bfea62005-11-08 03:06:16 +00003112 case ASN_CONSTR_CHOICE:
3113 return 2;
Lev Walkina9cc46e2004-09-22 16:06:28 +00003114 default:
3115 return 0;
3116 }
3117}
Lev Walkin801fabc2005-01-28 12:18:50 +00003118
3119static int
Lev Walkin0f5d74c2005-08-14 15:03:31 +00003120out_name_chain(arg_t *arg, enum onc_flags onc_flags) {
Lev Walkin801fabc2005-01-28 12:18:50 +00003121 asn1p_expr_t *expr = arg->expr;
Lev Walkinb46156d2017-09-05 02:53:05 -07003122 const char *id;
Lev Walkin801fabc2005-01-28 12:18:50 +00003123
Lev Walkin0f5d74c2005-08-14 15:03:31 +00003124 if((arg->flags & A1C_COMPOUND_NAMES
Denis Filatovdbb89902017-06-28 14:39:39 +02003125 || onc_flags & ONC_force_compound_name
Lev Walkinacdca412017-08-12 20:59:16 -07003126 || (0 && arg->embed /* Not yet */))
Lev Walkin21d00002005-03-04 08:48:53 +00003127 && ((expr->expr_type & ASN_CONSTR_MASK)
3128 || expr->expr_type == ASN_BASIC_ENUMERATED
Lev Walkinb02a8832005-08-13 23:51:47 +00003129 || ((expr->expr_type == ASN_BASIC_INTEGER
3130 || expr->expr_type == ASN_BASIC_BIT_STRING)
Lev Walkin21d00002005-03-04 08:48:53 +00003131 && expr_elements_count(arg, expr))
3132 )
Bi-Ruei, Chiu94f0b642017-06-29 01:34:23 +08003133 && expr->parent_expr) {
3134
Lev Walkin801fabc2005-01-28 12:18:50 +00003135 arg_t tmparg = *arg;
3136
3137 tmparg.expr = expr->parent_expr;
Lev Walkin21d00002005-03-04 08:48:53 +00003138 if(0) tmparg.flags &= ~A1C_COMPOUND_NAMES;
3139
Lev Walkin0f5d74c2005-08-14 15:03:31 +00003140 out_name_chain(&tmparg, onc_flags);
Lev Walkin801fabc2005-01-28 12:18:50 +00003141
Bi-Ruei, Chiu94f0b642017-06-29 01:34:23 +08003142 if(expr->parent_expr->Identifier) OUT("__"); /* a separator between id components */
Lev Walkin21d00002005-03-04 08:48:53 +00003143
Lev Walkin801fabc2005-01-28 12:18:50 +00003144 /* Fall through */
3145 }
3146
Lev Walkin0f5d74c2005-08-14 15:03:31 +00003147 if(onc_flags & ONC_avoid_keywords)
Lev Walkina00d6b32006-03-21 03:40:38 +00003148 id = MKID_safe(expr);
Lev Walkin801fabc2005-01-28 12:18:50 +00003149 else
Lev Walkina00d6b32006-03-21 03:40:38 +00003150 id = MKID(expr);
Lev Walkin801fabc2005-01-28 12:18:50 +00003151 OUT("%s", id);
3152
3153 return 0;
3154}
Lev Walkinb85a8132005-08-18 13:38:19 +00003155
3156static int
3157emit_include_dependencies(arg_t *arg) {
3158 asn1p_expr_t *expr = arg->expr;
3159 asn1p_expr_t *memb;
3160
3161 /* Avoid recursive definitions. */
3162 TQ_FOR(memb, &(expr->members), next) {
3163 expr_break_recursion(arg, memb);
3164 }
3165
3166 TQ_FOR(memb, &(expr->members), next) {
3167
3168 if(memb->marker.flags & (EM_INDIRECT | EM_UNRECURSE)) {
3169 if(terminal_structable(arg, memb)) {
3170 int saved_target = arg->target->target;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08003171 if(saved_target != OT_FWD_DECLS) {
3172 REDIR(OT_FWD_DECLS);
3173 OUT("%s;\n",
3174 asn1c_type_name(arg, memb, TNF_RSAFE));
3175 }
Lev Walkinb85a8132005-08-18 13:38:19 +00003176 REDIR(saved_target);
3177 }
3178 }
3179
3180 if((!(memb->expr_type & ASN_CONSTR_MASK)
3181 && memb->expr_type > ASN_CONSTR_MASK)
3182 || memb->meta_type == AMT_TYPEREF) {
3183 if(memb->marker.flags & EM_UNRECURSE) {
3184 GEN_POSTINCLUDE(asn1c_type_name(arg,
3185 memb, TNF_INCLUDE));
3186 } else {
3187 GEN_INCLUDE(asn1c_type_name(arg,
3188 memb, TNF_INCLUDE));
3189 }
3190 }
3191 }
3192
3193 return 0;
3194}
3195
3196/*
3197 * Check if it is better to make this type indirectly accessed via
3198 * a pointer.
3199 * This may be the case for the following recursive definition:
3200 * Type ::= CHOICE { member Type };
3201 */
3202static int
3203expr_break_recursion(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkinb85a8132005-08-18 13:38:19 +00003204 int ret;
3205
3206 if(expr->marker.flags & EM_UNRECURSE)
3207 return 1; /* Already broken */
3208
Lev Walkinb85a8132005-08-18 13:38:19 +00003209 /* -findirect-choice compiles members of CHOICE as indirect pointers */
3210 if((arg->flags & A1C_INDIRECT_CHOICE)
3211 && arg->expr->expr_type == ASN_CONSTR_CHOICE
Lev Walkin59b176e2005-11-26 11:25:14 +00003212 && (expr_get_type(arg, expr) & ASN_CONSTR_MASK)
Lev Walkinb85a8132005-08-18 13:38:19 +00003213 ) {
3214 /* Break cross-reference */
3215 expr->marker.flags |= EM_INDIRECT | EM_UNRECURSE;
3216 return 1;
3217 }
3218
3219 if((expr->marker.flags & EM_INDIRECT)
3220 || arg->expr->expr_type == ASN_CONSTR_SET_OF
3221 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF) {
3222 if(terminal_structable(arg, expr)) {
3223 expr->marker.flags |= EM_UNRECURSE;
3224
3225 if(arg->expr->expr_type == ASN_CONSTR_SET_OF
3226 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF) {
3227 /* Don't put EM_INDIRECT even if recursion */
3228 return 1;
3229 }
3230
3231 /* Fall through */
3232 }
3233 }
3234
3235 /* Look for recursive back-references */
3236 ret = expr_defined_recursively(arg, expr);
3237 switch(ret) {
3238 case 2: /* Explicitly break the recursion */
3239 case 1: /* Use safer typing */
3240 expr->marker.flags |= EM_INDIRECT;
3241 expr->marker.flags |= EM_UNRECURSE;
3242 break;
3243 }
3244
3245 return 0;
3246}
3247
3248/*
3249 * Check if the type can be represented using simple `struct TYPE`.
3250 */
3251static asn1p_expr_t *
3252terminal_structable(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkinc0e03b92017-08-22 01:48:23 -07003253 asn1p_expr_t *terminal =
3254 asn1f_find_terminal_type_ex(arg->asn, arg->ns, expr);
3255 if(terminal
Lev Walkinb85a8132005-08-18 13:38:19 +00003256 && !terminal->parent_expr
3257 && (terminal->expr_type & ASN_CONSTR_MASK)) {
3258 return terminal;
3259 }
3260 return 0;
3261}
3262
3263static int
3264asn1c_recurse(arg_t *arg, asn1p_expr_t *expr, int (*callback)(arg_t *arg, void *key), void *key) {
3265 arg_t tmp = *arg;
3266 int maxret = 0;
3267 int ret;
3268
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +08003269 if(expr->_mark & TM_RECURSION) return 0;
Lev Walkinb85a8132005-08-18 13:38:19 +00003270 expr->_mark |= TM_RECURSION;
3271
3272 /* Invoke callback for every type going into recursion */
3273 tmp.expr = expr;
3274 maxret = callback(&tmp, key);
3275 if(maxret <= 1) {
3276 /*
3277 * Recursively invoke myself and the callbacks.
3278 */
3279 TQ_FOR(tmp.expr, &(expr->members), next) {
3280 ret = asn1c_recurse(&tmp, tmp.expr, callback, key);
3281 if(ret > maxret)
3282 maxret = ret;
3283 if(maxret > 1) break;
3284 }
3285 }
3286
3287 expr->_mark &= ~TM_RECURSION;
3288 return maxret;
3289}
3290
3291static int
3292check_is_refer_to(arg_t *arg, void *key) {
3293 asn1p_expr_t *terminal = terminal_structable(arg, arg->expr);
3294 if(terminal == key) {
3295 if(arg->expr->marker.flags & EM_INDIRECT)
3296 return 1; /* This is almost safe indirection */
3297 return 2;
3298 } else if(terminal) {
3299 /* This might be N-step circular loop. Dive into it. */
3300 return asn1c_recurse(arg, terminal, check_is_refer_to, key);
3301 }
3302 return 0;
3303}
3304
3305/*
3306 * Check if the possibly inner expression defined recursively.
3307 */
3308static int
3309expr_defined_recursively(arg_t *arg, asn1p_expr_t *expr) {
3310 asn1p_expr_t *terminal;
3311 asn1p_expr_t *topmost;
3312
3313 /* If expression is top-level, there's no way it can be recursive. */
3314 if(expr->parent_expr == 0) return 0;
3315 if(expr->expr_type != A1TC_REFERENCE)
3316 return 0; /* Basic types are never recursive */
3317
3318 terminal = terminal_structable(arg, expr);
3319 if(!terminal) return 0; /* Terminal cannot be indirected */
3320
3321 /* Search for the parent container for the given expression */
3322 topmost = expr;
3323 while(topmost->parent_expr)
3324 topmost = topmost->parent_expr;
3325
3326 /* Look inside the terminal type if it mentions the parent expression */
3327 return asn1c_recurse(arg, terminal, check_is_refer_to, topmost);
3328}
Lev Walkin59b176e2005-11-26 11:25:14 +00003329
3330struct canonical_map_element {
3331 int eidx;
3332 asn1p_expr_t *expr;
3333};
3334static int compar_cameo(const void *ap, const void *bp);
3335static arg_t *cameo_arg;
3336static int *
3337compute_canonical_members_order(arg_t *arg, int el_count) {
3338 struct canonical_map_element *cmap;
3339 int *rmap;
3340 asn1p_expr_t *v;
3341 int eidx = 0;
3342 int ext_start = -1;
3343 int nextmax = -1;
3344 int already_sorted = 1;
3345
3346 cmap = calloc(el_count, sizeof *cmap);
3347 assert(cmap);
3348
3349 TQ_FOR(v, &(arg->expr->members), next) {
3350 if(v->expr_type != A1TC_EXTENSIBLE) {
3351 cmap[eidx].eidx = eidx;
3352 cmap[eidx].expr = v;
3353 eidx++;
3354 } else if(ext_start == -1)
3355 ext_start = eidx;
3356 }
3357
3358 cameo_arg = arg;
3359 if(ext_start == -1) {
3360 /* Sort the whole thing */
3361 qsort(cmap, el_count, sizeof(*cmap), compar_cameo);
3362 } else {
3363 /* Sort root and extensions independently */
3364 qsort(cmap, ext_start, sizeof(*cmap), compar_cameo);
3365 qsort(cmap + ext_start, el_count - ext_start,
3366 sizeof(*cmap), compar_cameo);
3367 }
3368
3369 /* move data back to a simpler map */
3370 rmap = calloc(el_count, sizeof *rmap);
3371 assert(rmap);
3372 for(eidx = 0; eidx < el_count; eidx++) {
3373 rmap[eidx] = cmap[eidx].eidx;
3374 if(rmap[eidx] <= nextmax)
3375 already_sorted = 0;
3376 else
3377 nextmax = rmap[eidx];
3378 }
3379 free(cmap);
3380
3381 if(already_sorted) { free(rmap); rmap = 0; }
3382 return rmap;
3383}
3384static int compar_cameo(const void *ap, const void *bp) {
3385 const struct canonical_map_element *a = (const void *)ap;
3386 const struct canonical_map_element *b = (const void *)bp;
3387 struct asn1p_type_tag_s atag, btag;
3388 arg_t *arg = cameo_arg;
3389
Lev Walkinc0e03b92017-08-22 01:48:23 -07003390 if(WITH_MODULE_NAMESPACE(a->expr->module, expr_ns,
3391 asn1f_fetch_outmost_tag(
3392 arg->asn, expr_ns, a->expr->module, a->expr,
3393 &atag, AFT_IMAGINARY_ANY | AFT_CANON_CHOICE)))
3394 return 1;
Lev Walkin59b176e2005-11-26 11:25:14 +00003395
Lev Walkinc0e03b92017-08-22 01:48:23 -07003396 if(WITH_MODULE_NAMESPACE(b->expr->module, expr_ns,
3397 asn1f_fetch_outmost_tag(
3398 arg->asn, expr_ns, b->expr->module, b->expr,
3399 &btag, AFT_IMAGINARY_ANY | AFT_CANON_CHOICE)))
3400 return -1;
Lev Walkin59b176e2005-11-26 11:25:14 +00003401
3402 if(atag.tag_class < btag.tag_class)
3403 return -1;
3404 if(atag.tag_class > btag.tag_class)
3405 return 1;
3406 if(atag.tag_value < btag.tag_value)
3407 return -1;
3408 if(atag.tag_value > btag.tag_value)
3409 return 1;
3410 return 0;
3411
3412}