blob: 546b88924c8f7c20f3d6b9bac769be7e066aa792 [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;
Bi-Ruei, Chiudcc822a2017-10-19 01:06:57 +08001068 open_type_choice->parent_expr = arg->expr->parent_expr;
Lev Walkinf6853ce2017-08-11 00:50:27 -07001069
1070 for(size_t row = 0; row < opt_ioc->ioct->rows; row++) {
1071 struct asn1p_ioc_cell_s *cell =
1072 &opt_ioc->ioct->row[row]->column[column_index];
1073
Bi-Ruei, Chiu069c0762017-09-11 14:09:34 +08001074 if(!cell->value) continue;
1075
Lev Walkinf6853ce2017-08-11 00:50:27 -07001076 asn1p_expr_t *m = asn1p_expr_clone(cell->value, 0);
Bi-Ruei, Chiudcc822a2017-10-19 01:06:57 +08001077 if (asn1p_lookup_child(open_type_choice, m->Identifier))
1078 m->_mark |= TM_SKIPinUNION;
Lev Walkinf6853ce2017-08-11 00:50:27 -07001079 asn1p_expr_add(open_type_choice, m);
1080 }
1081
1082 tmp_arg.expr = open_type_choice;
1083 GEN_INCLUDE_STD("OPEN_TYPE");
1084 asn1c_lang_C_type_CHOICE(&tmp_arg);
1085 asn1p_expr_free(tmp_arg.expr);
1086 return 0;
1087}
1088
Lev Walkinf15320b2004-06-03 03:38:44 +00001089static int
1090asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
1091 asn1p_expr_t *expr = arg->expr;
1092 asn1p_expr_t *v;
1093 int elements; /* Number of elements */
Lev Walkinf15320b2004-06-03 03:38:44 +00001094 tag2el_t *tag2el = NULL;
1095 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +00001096 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +00001097 int all_tags_count;
1098 enum tvm_compat tv_mode;
Lev Walkin59b176e2005-11-26 11:25:14 +00001099 int *cmap = 0;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001100 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +00001101
1102 /*
1103 * Fetch every inner tag from the tag to elements map.
1104 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001105 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001106 if(tag2el) free(tag2el);
1107 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +00001108 }
1109
Lev Walkin22b5ed42006-09-13 02:51:20 +00001110 GEN_INCLUDE_STD("constr_CHOICE");
Lev Walkin3dcaafa2004-08-11 05:21:32 +00001111 if(!arg->embed)
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001112 GEN_DECLARE("CHOICE", expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +00001113
Lev Walkin3dcaafa2004-08-11 05:21:32 +00001114 REDIR(OT_STAT_DEFS);
Lev Walkinf15320b2004-06-03 03:38:44 +00001115
1116 /*
Lev Walkin59b176e2005-11-26 11:25:14 +00001117 * Print out the table according to which parsing is performed.
Lev Walkinf15320b2004-06-03 03:38:44 +00001118 */
Lev Walkina9cc46e2004-09-22 16:06:28 +00001119 if(expr_elements_count(arg, expr)) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001120
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001121 if(!(expr->_type_referenced)) OUT("static ");
1122 OUT("asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -07001123 c_name(arg).part_name, expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +00001124
1125 elements = 0;
1126 INDENTED(TQ_FOR(v, &(expr->members), next) {
Lev Walkin659c63b2005-01-17 11:40:49 +00001127 if(v->expr_type == A1TC_EXTENSIBLE)
1128 continue;
Lev Walkin9de6cd82017-08-10 05:47:46 -07001129 emit_member_table(arg, v, NULL);
Lev Walkinda9a3b82005-08-16 17:00:21 +00001130 elements++;
Lev Walkina9cc46e2004-09-22 16:06:28 +00001131 });
1132 OUT("};\n");
1133 } else {
1134 elements = 0;
1135 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001136
Lev Walkin37231fb2017-10-17 21:24:34 -07001137 /* Create a canonical elements map */
1138 if(elements && (arg->flags & A1C_GEN_PER)) {
1139 cmap = compute_canonical_members_order(arg, elements);
1140 if(cmap) {
1141 OUT("static const unsigned asn_MAP_%s_to_canonical_%d[] = {",
1142 MKID(expr), expr->_type_unique_index);
1143 for(int i = 0; i < elements; i++) {
1144 if(i) OUT(",");
1145 OUT(" %d", cmap[i]);
1146 }
1147 OUT(" };\n");
1148 OUT("static const unsigned asn_MAP_%s_from_canonical_%d[] = {",
1149 MKID(expr), expr->_type_unique_index);
1150 for(int i = 0; i < elements; i++) {
1151 if(i) OUT(",");
1152 int j;
1153 for(j = 0; j < elements; j++) {
1154 if(cmap[j] == i) {
1155 OUT(" %d", j);
1156 break;
1157 }
1158 }
1159 assert(j < elements);
1160 }
1161 OUT(" };\n");
1162 free(cmap);
1163 }
1164 }
Lev Walkin64399722004-08-11 07:17:22 +00001165
Lev Walkinf15320b2004-06-03 03:38:44 +00001166 if(arg->embed) {
1167 /*
1168 * Our parent structure has already taken this into account.
1169 */
Lev Walkin188ed2c2004-09-13 08:31:01 +00001170 tv_mode = _TVM_SAME;
1171 tags_count = all_tags_count = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +00001172 } else {
Lev Walkin188ed2c2004-09-13 08:31:01 +00001173 tv_mode = emit_tags_vectors(arg, expr,
1174 &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +00001175 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001176
1177 /*
1178 * Tags to elements map.
1179 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001180 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +00001181
Lev Walkin37231fb2017-10-17 21:24:34 -07001182 if(!(expr->_type_referenced)) OUT("static ");
1183 OUT("asn_CHOICE_specifics_t asn_SPC_%s_specs_%d = {\n", MKID(expr),
1184 expr->_type_unique_index);
1185 INDENTED(
1186 OUT("sizeof(%s),\n", c_name(arg).full_name);
1187 OUT("offsetof(%s, _asn_ctx),\n", c_name(arg).full_name);
1188 OUT("offsetof(%s, present),\n", c_name(arg).full_name);
1189 OUT("sizeof(((%s *)0)->present),\n", c_name(arg).full_name);
1190 emit_tag2member_reference(arg, expr, tag2el_count);
1191 if(cmap) {
1192 if(C99_MODE) OUT(".to_canonical_order = ");
1193 OUT("asn_MAP_%s_to_canonical_%d,\n", MKID(expr),
1194 expr->_type_unique_index);
1195 if(C99_MODE) OUT(".from_canonical_order = ");
1196 OUT("asn_MAP_%s_from_canonical_%d,\n", MKID(expr),
1197 expr->_type_unique_index);
1198 } else { OUT("0, 0,\n"); }
1199 if(C99_MODE) OUT(".ext_start = ");
1200 OUT("%d\t/* Extensions start */\n", compute_extensions_start(expr));
1201 );
1202 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +00001203
1204 /*
Lev Walkin05363a72004-09-29 13:16:40 +00001205 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +00001206 */
Lev Walkin188ed2c2004-09-13 08:31:01 +00001207 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
Lev Walkin8de2ab22004-09-26 13:11:31 +00001208 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +00001209
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001210 REDIR(saved_target);
Lev Walkinf15320b2004-06-03 03:38:44 +00001211
Bi-Ruei, Chiu12021b52016-11-04 11:59:45 +08001212 if (tag2el) free(tag2el);
1213
Lev Walkinf15320b2004-06-03 03:38:44 +00001214 return 0;
Lev Walkinb0b33412005-01-17 11:57:48 +00001215} /* _CHOICE_def() */
Lev Walkinf15320b2004-06-03 03:38:44 +00001216
1217int
1218asn1c_lang_C_type_REFERENCE(arg_t *arg) {
1219 asn1p_ref_t *ref;
1220
1221 ref = arg->expr->reference;
1222 if(ref->components[ref->comp_count-1].name[0] == '&') {
Lev Walkinf15320b2004-06-03 03:38:44 +00001223 asn1p_expr_t *extract;
1224 arg_t tmp;
1225 int ret;
1226
Lev Walkinc0e03b92017-08-22 01:48:23 -07001227 extract = WITH_MODULE_NAMESPACE(
1228 arg->expr->module, expr_ns,
1229 asn1f_class_access_ex(arg->asn, arg->expr->module, expr_ns,
1230 arg->expr, arg->expr->rhs_pspecs, ref));
1231 if(extract == NULL)
Lev Walkinf15320b2004-06-03 03:38:44 +00001232 return -1;
1233
Lev Walkin08079b02004-08-22 03:25:24 +00001234 extract = asn1p_expr_clone(extract, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +00001235 if(extract) {
Lev Walkind8b83642016-03-14 02:00:27 -07001236 free(extract->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +00001237 extract->Identifier = strdup(arg->expr->Identifier);
1238 if(extract->Identifier == NULL) {
1239 asn1p_expr_free(extract);
1240 return -1;
1241 }
1242 } else {
1243 return -1;
1244 }
1245
1246 tmp = *arg;
1247 tmp.asn = arg->asn;
Lev Walkinf15320b2004-06-03 03:38:44 +00001248 tmp.expr = extract;
1249
Lev Walkin9de6cd82017-08-10 05:47:46 -07001250 ret = arg->default_cb(&tmp, NULL);
Lev Walkinf15320b2004-06-03 03:38:44 +00001251
1252 asn1p_expr_free(extract);
1253
1254 return ret;
1255 }
1256
1257
1258 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
1259}
1260
1261int
1262asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
1263 asn1p_expr_t *expr = arg->expr;
Lev Walkin64399722004-08-11 07:17:22 +00001264 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +00001265 int all_tags_count;
1266 enum tvm_compat tv_mode;
Lev Walkine0b56e02005-02-25 12:10:27 +00001267 enum etd_spec etd_spec;
Lev Walkinb46156d2017-09-05 02:53:05 -07001268 const char *p;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001269 int saved_target = arg->target->target;
Lev Walkinf15320b2004-06-03 03:38:44 +00001270
1271 if(arg->embed) {
Lev Walkin05363a72004-09-29 13:16:40 +00001272 enum tnfmt tnfmt = TNF_CTYPE;
1273
1274 /*
1275 * If this is an optional compound type,
1276 * refer it using "struct X" convention,
1277 * as it may recursively include the current structure.
1278 */
Lev Walkinc8285712005-03-04 22:18:20 +00001279 if(expr->marker.flags & (EM_INDIRECT | EM_UNRECURSE)) {
Lev Walkinb85a8132005-08-18 13:38:19 +00001280 if(terminal_structable(arg, expr)) {
Lev Walkinc8285712005-03-04 22:18:20 +00001281 tnfmt = TNF_RSAFE;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001282 if(saved_target != OT_FWD_DECLS) {
1283 REDIR(OT_FWD_DECLS);
1284 OUT("%s;\n",
1285 asn1c_type_name(arg, arg->expr, tnfmt));
1286 }
1287 REDIR(saved_target);
Lev Walkin05363a72004-09-29 13:16:40 +00001288 }
1289 }
1290
Bi-Ruei, Chiudcc822a2017-10-19 01:06:57 +08001291 if(!(expr->_mark & TM_SKIPinUNION))
1292 OUT("%s", asn1c_type_name(arg, arg->expr, tnfmt));
Lev Walkinf15320b2004-06-03 03:38:44 +00001293
Lev Walkine0b56e02005-02-25 12:10:27 +00001294 if(!expr->_anonymous_type) {
Bi-Ruei, Chiudcc822a2017-10-19 01:06:57 +08001295 if(!(expr->_mark & TM_SKIPinUNION)) {
1296 OUT("%s", (expr->marker.flags&EM_INDIRECT)?"\t*":"\t ");
1297 OUT("%s", MKID_safe(expr));
1298 }
Lev Walkin59b176e2005-11-26 11:25:14 +00001299 if((expr->marker.flags & (EM_DEFAULT & ~EM_INDIRECT))
1300 == (EM_DEFAULT & ~EM_INDIRECT))
Lev Walkine0b56e02005-02-25 12:10:27 +00001301 OUT("\t/* DEFAULT %s */",
1302 asn1f_printable_value(
1303 expr->marker.default_value));
Lev Walkin59b176e2005-11-26 11:25:14 +00001304 else if((expr->marker.flags & EM_OPTIONAL)
1305 == EM_OPTIONAL)
Lev Walkine0b56e02005-02-25 12:10:27 +00001306 OUT("\t/* OPTIONAL */");
1307 }
1308
1309 } else {
1310 GEN_INCLUDE(asn1c_type_name(arg, expr, TNF_INCLUDE));
Lev Walkin59004fa2004-08-20 13:37:01 +00001311
1312 REDIR(OT_TYPE_DECLS);
Lev Walkine0b56e02005-02-25 12:10:27 +00001313
1314 OUT("typedef %s\t",
Lev Walkinc8285712005-03-04 22:18:20 +00001315 asn1c_type_name(arg, arg->expr, TNF_CTYPE));
Lev Walkine0b56e02005-02-25 12:10:27 +00001316 OUT("%s%s_t",
Lev Walkinc8285712005-03-04 22:18:20 +00001317 (expr->marker.flags & EM_INDIRECT)?"*":" ",
Lev Walkina00d6b32006-03-21 03:40:38 +00001318 MKID(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +00001319 }
1320
Lev Walkine0b56e02005-02-25 12:10:27 +00001321 if((expr->expr_type == ASN_BASIC_ENUMERATED)
Lev Walkin8ecf9db2005-03-03 21:28:12 +00001322 || (0 /* -- prohibited by X.693:8.3.4 */
1323 && expr->expr_type == ASN_BASIC_INTEGER
Lev Walkin8bb57a22007-12-03 13:41:36 +00001324 && expr_elements_count(arg, expr))
1325 || (expr->expr_type == ASN_BASIC_INTEGER
1326 && asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN)
Lev Walkin43292722017-10-05 00:33:32 -07001327 || asn1c_REAL_fits(arg, expr) == RL_FITS_FLOAT32
Lev Walkin8bb57a22007-12-03 13:41:36 +00001328 )
Lev Walkine0b56e02005-02-25 12:10:27 +00001329 etd_spec = ETD_HAS_SPECIFICS;
1330 else
1331 etd_spec = ETD_NO_SPECIFICS;
Lev Walkinf15320b2004-06-03 03:38:44 +00001332
Lev Walkin8de2ab22004-09-26 13:11:31 +00001333 /*
1334 * If this type just blindly refers the other type, alias it.
1335 * Type1 ::= Type2
1336 */
Lev Walkine0b56e02005-02-25 12:10:27 +00001337 if(arg->embed && etd_spec == ETD_NO_SPECIFICS) {
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001338 REDIR(saved_target);
Lev Walkine0b56e02005-02-25 12:10:27 +00001339 return 0;
1340 }
Lev Walkin8de2ab22004-09-26 13:11:31 +00001341
Lev Walkin59004fa2004-08-20 13:37:01 +00001342 REDIR(OT_CODE);
1343
Lev Walkinf15320b2004-06-03 03:38:44 +00001344 /*
1345 * Constraint checking.
1346 */
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001347 if(!(arg->flags & A1C_NO_CONSTRAINTS) && expr->combined_constraints) {
Lev Walkina00d6b32006-03-21 03:40:38 +00001348 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001349 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkin8de2ab22004-09-26 13:11:31 +00001350 OUT("int\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001351 OUT("%s", p);
1352 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
Lev Walkin37231fb2017-10-17 21:24:34 -07001353 OUT("_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,\n");
Lev Walkin8de2ab22004-09-26 13:11:31 +00001354 INDENT(+1);
Lev Walkin1eded352006-07-13 11:19:01 +00001355 OUT("\t\tasn_app_constraint_failed_f *ctfailcb, void *app_key) {");
Lev Walkin8de2ab22004-09-26 13:11:31 +00001356 OUT("\n");
Lev Walkin725883b2006-10-09 12:07:58 +00001357 DEBUG("expr constraint checking code for %s", p);
Lev Walkin8de2ab22004-09-26 13:11:31 +00001358 if(asn1c_emit_constraint_checking_code(arg) == 1) {
Lev Walkin14e75ed2017-09-29 23:15:02 -07001359 OUT("return td->encoding_constraints.general_constraints"
Lev Walkin1eded352006-07-13 11:19:01 +00001360 "(td, sptr, ctfailcb, app_key);\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +00001361 }
Lev Walkin8de2ab22004-09-26 13:11:31 +00001362 INDENT(-1);
1363 OUT("}\n");
1364 OUT("\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001365 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001366
Lev Walkin725883b2006-10-09 12:07:58 +00001367 REDIR(OT_STAT_DEFS);
1368
Lev Walkin43292722017-10-05 00:33:32 -07001369 /*
1370 * By default, NativeReal is double. We only override this if
1371 * (OER) constraints suggested that we may use float.
1372 */
1373 if(asn1c_REAL_fits(arg, expr) == RL_FITS_FLOAT32) {
Lev Walkinb5450702017-10-04 02:52:57 -07001374 if(!(expr->_type_referenced)) OUT("static ");
1375 OUT("const asn_NativeReal_specifics_t asn_SPC_%s_specs_%d = {\n",
1376 MKID(expr), expr->_type_unique_index);
1377 INDENT(+1);
1378 OUT("4\t/* Use 'float' type. */\n");
1379 INDENT(-1);
1380 OUT("};\n");
1381 }
1382
Lev Walkin725883b2006-10-09 12:07:58 +00001383 /*
1384 * Print out asn_DEF_<type>_[all_]tags[] vectors.
1385 */
1386 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
1387 DEBUG("emit tag vectors for %s %d, %d, %d", expr->Identifier,
1388 tv_mode, tags_count, all_tags_count);
1389
1390 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count,
1391 0, etd_spec);
1392
1393 REDIR(OT_CODE);
1394
Lev Walkinf15320b2004-06-03 03:38:44 +00001395 /*
1396 * Emit suicidal functions.
1397 */
1398
Lev Walkinf15320b2004-06-03 03:38:44 +00001399 /*
1400 * This function replaces certain fields from the definition
1401 * of a type with the corresponding fields from the basic type
1402 * (from which the current type is inherited).
1403 */
Lev Walkinf15320b2004-06-03 03:38:44 +00001404 OUT("/*\n");
Lev Walkin026e21a2017-10-04 00:49:01 -07001405 OUT(" * This type is implemented using %s,\n", c_name(arg).type.base_name);
Lev Walkinb65b3002004-09-23 22:20:47 +00001406 OUT(" * so here we adjust the DEF accordingly.\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001407 OUT(" */\n");
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08001408
Lev Walkinf15320b2004-06-03 03:38:44 +00001409 REDIR(OT_FUNC_DECLS);
1410
Lev Walkina00d6b32006-03-21 03:40:38 +00001411 p = MKID(expr);
Lev Walkine0b56e02005-02-25 12:10:27 +00001412 if(HIDE_INNER_DEFS) {
Lev Walkin21d00002005-03-04 08:48:53 +00001413 OUT("/* extern asn_TYPE_descriptor_t asn_DEF_%s_%d;"
1414 "\t// (Use -fall-defs-global to expose) */\n",
1415 p, expr->_type_unique_index);
Lev Walkine0b56e02005-02-25 12:10:27 +00001416 } else {
1417 OUT("extern asn_TYPE_descriptor_t asn_DEF_%s;\n", p);
Lev Walkinb5450702017-10-04 02:52:57 -07001418 if(etd_spec == ETD_HAS_SPECIFICS && expr->_type_referenced) {
1419 if((expr->expr_type == ASN_BASIC_ENUMERATED)
1420 || (expr->expr_type == ASN_BASIC_INTEGER)) {
1421 OUT("extern const asn_INTEGER_specifics_t "
1422 "asn_SPC_%s_specs_%d;\n",
1423 c_name(arg).base_name, expr->_type_unique_index);
1424 } else {
Lev Walkinc0e03b92017-08-22 01:48:23 -07001425 asn1p_expr_t *terminal = WITH_MODULE_NAMESPACE(
1426 expr->module, expr_ns,
1427 asn1f_find_terminal_type_ex(arg->asn, expr_ns, expr));
Lev Walkinb5450702017-10-04 02:52:57 -07001428 OUT("extern const asn_%s_specifics_t ",
1429 asn1c_type_name(arg, terminal, TNF_SAFE));
1430 OUT("asn_SPC_%s_specs_%d;\n", MKID(expr),
1431 expr->_type_unique_index);
1432 }
1433 }
Lev Walkine0b56e02005-02-25 12:10:27 +00001434 OUT("asn_struct_free_f %s_free;\n", p);
1435 OUT("asn_struct_print_f %s_print;\n", p);
1436 OUT("asn_constr_check_f %s_constraint;\n", p);
1437 OUT("ber_type_decoder_f %s_decode_ber;\n", p);
1438 OUT("der_type_encoder_f %s_encode_der;\n", p);
1439 OUT("xer_type_decoder_f %s_decode_xer;\n", p);
1440 OUT("xer_type_encoder_f %s_encode_xer;\n", p);
Lev Walkinb33425f2017-07-14 14:59:52 +04001441 if(arg->flags & A1C_GEN_OER) {
1442 OUT("oer_type_decoder_f %s_decode_oer;\n", p);
1443 OUT("oer_type_encoder_f %s_encode_oer;\n", p);
1444 }
Lev Walkin1dc85292006-08-18 01:32:26 +00001445 if(arg->flags & A1C_GEN_PER) {
Lev Walkin59b176e2005-11-26 11:25:14 +00001446 OUT("per_type_decoder_f %s_decode_uper;\n", p);
Lev Walkin1dc85292006-08-18 01:32:26 +00001447 OUT("per_type_encoder_f %s_encode_uper;\n", p);
1448 }
Lev Walkine0b56e02005-02-25 12:10:27 +00001449 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001450
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08001451 REDIR(saved_target);
Lev Walkin3dcaafa2004-08-11 05:21:32 +00001452
Lev Walkinf15320b2004-06-03 03:38:44 +00001453 return 0;
1454}
1455
1456int
1457asn1c_lang_C_type_EXTENSIBLE(arg_t *arg) {
1458
1459 OUT("/*\n");
1460 OUT(" * This type is extensible,\n");
1461 OUT(" * possible extensions are below.\n");
1462 OUT(" */\n");
1463
1464 return 0;
1465}
1466
Lev Walkin59b176e2005-11-26 11:25:14 +00001467static int
1468compute_extensions_start(asn1p_expr_t *expr) {
Lev Walkin35631482004-07-01 00:52:50 +00001469 asn1p_expr_t *v;
Lev Walkin59b176e2005-11-26 11:25:14 +00001470 int eidx = 0;
Lev Walkin35631482004-07-01 00:52:50 +00001471 TQ_FOR(v, &(expr->members), next) {
Lev Walkin59b176e2005-11-26 11:25:14 +00001472 if(v->expr_type == A1TC_EXTENSIBLE)
1473 return eidx;
1474 eidx++;
Lev Walkin35631482004-07-01 00:52:50 +00001475 }
Lev Walkin59b176e2005-11-26 11:25:14 +00001476 return -1;
Lev Walkin35631482004-07-01 00:52:50 +00001477}
1478
Lev Walkinf15320b2004-06-03 03:38:44 +00001479static int
Lev Walkinc3e29402004-09-10 06:07:18 +00001480_print_tag(arg_t *arg, struct asn1p_type_tag_s *tag) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001481
1482 OUT("(");
Lev Walkinc3e29402004-09-10 06:07:18 +00001483 switch(tag->tag_class) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001484 case TC_UNIVERSAL: OUT("ASN_TAG_CLASS_UNIVERSAL"); break;
1485 case TC_APPLICATION: OUT("ASN_TAG_CLASS_APPLICATION"); break;
1486 case TC_CONTEXT_SPECIFIC: OUT("ASN_TAG_CLASS_CONTEXT"); break;
1487 case TC_PRIVATE: OUT("ASN_TAG_CLASS_PRIVATE"); break;
1488 case TC_NOCLASS:
1489 break;
1490 }
Lev Walkinda997b12017-08-04 01:38:41 -07001491 OUT(" | (%s << 2))", asn1p_itoa(tag->tag_value));
Lev Walkinf15320b2004-06-03 03:38:44 +00001492
1493 return 0;
1494}
1495
Lev Walkinfd171ef2004-06-06 07:20:17 +00001496
1497static int
1498_tag2el_cmp(const void *ap, const void *bp) {
1499 const tag2el_t *a = ap;
1500 const tag2el_t *b = bp;
1501 const struct asn1p_type_tag_s *ta = &a->el_tag;
1502 const struct asn1p_type_tag_s *tb = &b->el_tag;
1503
1504 if(ta->tag_class == tb->tag_class) {
1505 if(ta->tag_value == tb->tag_value) {
1506 /*
1507 * Sort by their respective positions.
1508 */
1509 if(a->el_no < b->el_no)
1510 return -1;
1511 else if(a->el_no > b->el_no)
1512 return 1;
1513 return 0;
1514 } else if(ta->tag_value < tb->tag_value)
1515 return -1;
1516 else
1517 return 1;
1518 } else if(ta->tag_class < tb->tag_class) {
1519 return -1;
1520 } else {
1521 return 1;
1522 }
1523}
1524
Lev Walkinf15320b2004-06-03 03:38:44 +00001525/*
1526 * For constructed types, number of external tags may be greater than
1527 * number of elements in the type because of CHOICE type.
1528 * T ::= SET { -- Three possible tags:
1529 * a INTEGER, -- One tag is here...
1530 * b Choice1 -- ... and two more tags are there.
1531 * }
1532 * Choice1 ::= CHOICE {
1533 * s1 IA5String,
1534 * s2 ObjectDescriptor
1535 * }
1536 */
1537static int
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001538_fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001539 asn1p_expr_t *expr = arg->expr;
1540 arg_t tmparg = *arg;
1541 asn1p_expr_t *v;
1542 int element = 0;
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001543 int original_count = *count;
1544 int sort_until = -1;
Lev Walkinf15320b2004-06-03 03:38:44 +00001545
1546 TQ_FOR(v, &(expr->members), next) {
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001547 if(v->expr_type == A1TC_EXTENSIBLE) {
1548 /*
Lev Walkine0b56e02005-02-25 12:10:27 +00001549 * CXER mandates sorting
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001550 * only for the root part.
1551 */
1552 if(flags == FTE_CANONICAL_XER
1553 && sort_until == -1)
1554 sort_until = *count;
Lev Walkinf15320b2004-06-03 03:38:44 +00001555 continue;
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001556 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001557
1558 tmparg.expr = v;
1559
1560 if(_add_tag2el_member(&tmparg, tag2el, count,
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001561 (el_no==-1)?element:el_no, flags)) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001562 return -1;
1563 }
1564
1565 element++;
1566 }
1567
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001568
1569 if(flags == FTE_CANONICAL_XER) {
1570 if(sort_until == -1) sort_until = *count;
1571 qsort((*tag2el) + original_count,
1572 sort_until - original_count,
1573 sizeof(**tag2el), _tag2el_cmp);
1574 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1575 && (sort_until - original_count) >= 1) {
1576 /* Only take in account the root component */
1577 *count = original_count + 1;
1578 }
1579 } else {
1580 /*
1581 * Sort the map according to canonical order of their
1582 * tags and element numbers.
1583 */
1584 qsort(*tag2el, *count, sizeof(**tag2el), _tag2el_cmp);
1585 }
Lev Walkinfd171ef2004-06-06 07:20:17 +00001586
Lev Walkin38abe792004-06-14 13:09:45 +00001587 /*
1588 * Initialize .toff_{first|last} members.
1589 */
1590 if(*count) {
1591 struct asn1p_type_tag_s *cur_tag = 0;
1592 tag2el_t *cur = *tag2el;
1593 tag2el_t *end = cur + *count;
1594 int occur, i;
1595 for(occur = 0; cur < end; cur++) {
1596 if(cur_tag == 0
1597 || cur_tag->tag_value != cur->el_tag.tag_value
1598 || cur_tag->tag_class != cur->el_tag.tag_class) {
1599 cur_tag = &cur->el_tag;
1600 occur = 0;
1601 } else {
1602 occur++;
1603 }
1604 cur->toff_first = -occur;
1605 for(i = 0; i >= -occur; i--)
1606 cur[i].toff_last = -i;
1607 }
1608 }
1609
Lev Walkinf15320b2004-06-03 03:38:44 +00001610 return 0;
1611}
1612
1613static int
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001614_add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001615 struct asn1p_type_tag_s tag;
1616 int ret;
1617
1618 assert(el_no >= 0);
1619
Lev Walkinc0e03b92017-08-22 01:48:23 -07001620 ret = WITH_MODULE_NAMESPACE(
1621 arg->expr->module, expr_ns,
1622 asn1f_fetch_outmost_tag(arg->asn, expr_ns, arg->expr->module, arg->expr,
1623 &tag, AFT_IMAGINARY_ANY));
1624 if(ret == 0) {
Lev Walkin201943e2004-09-04 04:42:29 +00001625 tag2el_t *te;
1626 int new_count = (*count) + 1;
Lev Walkinf15320b2004-06-03 03:38:44 +00001627 void *p;
Lev Walkin201943e2004-09-04 04:42:29 +00001628
Lev Walkinac7e2292004-09-05 10:42:33 +00001629 if(tag.tag_value == -1) {
1630 /*
1631 * This is an untagged ANY type,
1632 * proceed without adding a tag
1633 */
1634 return 0;
1635 }
1636
Lev Walkin201943e2004-09-04 04:42:29 +00001637 p = realloc(*tag2el, new_count * sizeof(tag2el_t));
Lev Walkinf15320b2004-06-03 03:38:44 +00001638 if(p) *tag2el = p;
1639 else return -1;
1640
Lev Walkin725883b2006-10-09 12:07:58 +00001641 if(0) DEBUG("Found tag for %s: %ld",
Lev Walkinf15320b2004-06-03 03:38:44 +00001642 arg->expr->Identifier,
1643 (long)tag.tag_value);
1644
Lev Walkin201943e2004-09-04 04:42:29 +00001645 te = &((*tag2el)[*count]);
1646 te->el_tag = tag;
1647 te->el_no = el_no;
1648 te->from_expr = arg->expr;
1649 *count = new_count;
Lev Walkinf15320b2004-06-03 03:38:44 +00001650 return 0;
1651 }
1652
1653 DEBUG("Searching tag in complex expression %s:%x at line %d",
1654 arg->expr->Identifier,
1655 arg->expr->expr_type,
1656 arg->expr->_lineno);
1657
1658 /*
1659 * Iterate over members of CHOICE type.
1660 */
1661 if(arg->expr->expr_type == ASN_CONSTR_CHOICE) {
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001662 return _fill_tag2el_map(arg, tag2el, count, el_no, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +00001663 }
1664
1665 if(arg->expr->expr_type == A1TC_REFERENCE) {
1666 arg_t tmp = *arg;
1667 asn1p_expr_t *expr;
Lev Walkinc0e03b92017-08-22 01:48:23 -07001668 expr = WITH_MODULE_NAMESPACE(
1669 tmp.expr->module, expr_ns,
1670 asn1f_lookup_symbol_ex(tmp.asn, expr_ns, tmp.expr,
1671 arg->expr->reference));
1672 if(expr) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001673 tmp.expr = expr;
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001674 return _add_tag2el_member(&tmp, tag2el, count, el_no, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +00001675 } else {
1676 FATAL("Cannot dereference %s at line %d",
1677 arg->expr->Identifier,
1678 arg->expr->_lineno);
1679 return -1;
1680 }
1681 }
1682
1683 DEBUG("No tag for %s at line %d",
1684 arg->expr->Identifier,
1685 arg->expr->_lineno);
1686
1687 return -1;
1688}
1689
1690static int
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001691emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier) {
Lev Walkinfd171ef2004-06-06 07:20:17 +00001692 asn1p_expr_t *expr = arg->expr;
Lev Walkinf3b29b12005-06-02 05:21:37 +00001693 int i;
1694
1695 if(!tag2el_count) return 0; /* No top level tags */
Lev Walkinfd171ef2004-06-06 07:20:17 +00001696
Wim Lewisfb6344e2014-07-28 12:16:01 -07001697 OUT("static const asn_TYPE_tag2member_t asn_MAP_%s_tag2el%s_%d[] = {\n",
Lev Walkina00d6b32006-03-21 03:40:38 +00001698 MKID(expr), opt_modifier?opt_modifier:"",
Lev Walkin59b176e2005-11-26 11:25:14 +00001699 expr->_type_unique_index);
Lev Walkinf3b29b12005-06-02 05:21:37 +00001700 for(i = 0; i < tag2el_count; i++) {
1701 OUT(" { ");
1702 _print_tag(arg, &tag2el[i].el_tag);
1703 OUT(", ");
1704 OUT("%d, ", tag2el[i].el_no);
1705 OUT("%d, ", tag2el[i].toff_first);
1706 OUT("%d ", tag2el[i].toff_last);
Lev Walkin4062b012013-10-11 14:29:38 -07001707 OUT("}%s /* %s",
Lev Walkinf3b29b12005-06-02 05:21:37 +00001708 (i + 1 < tag2el_count) ? "," : "",
Lev Walkin4062b012013-10-11 14:29:38 -07001709 tag2el[i].from_expr->Identifier);
1710 if(arg->flags & A1C_LINE_REFS)
1711 OUT("at %d", tag2el[i].from_expr->_lineno);
1712 OUT(" */\n");
Lev Walkinfd171ef2004-06-06 07:20:17 +00001713 }
1714 OUT("};\n");
1715
Lev Walkinf3b29b12005-06-02 05:21:37 +00001716 return 0;
Lev Walkinfd171ef2004-06-06 07:20:17 +00001717}
1718
Lev Walkin188ed2c2004-09-13 08:31:01 +00001719static enum tvm_compat
1720emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tags_count_r, int *all_tags_count_r) {
1721 struct asn1p_type_tag_s *tags = 0; /* Effective tags */
1722 struct asn1p_type_tag_s *all_tags = 0; /* The full array */
Lev Walkin64399722004-08-11 07:17:22 +00001723 int tags_count = 0;
Lev Walkin188ed2c2004-09-13 08:31:01 +00001724 int all_tags_count = 0;
1725 enum tvm_compat tv_mode = _TVM_SAME;
Lev Walkin906654e2004-09-10 15:49:15 +00001726 int i;
Lev Walkin27ea3802004-06-28 21:13:46 +00001727
Lev Walkin6d1220a2004-09-14 14:10:10 +00001728 /* Cleanup before proceeding. */
1729 *tags_count_r = 0;
1730 *all_tags_count_r = 0;
1731
Lev Walkin906654e2004-09-10 15:49:15 +00001732 /* Fetch a chain of tags */
Lev Walkinc0e03b92017-08-22 01:48:23 -07001733 tags_count = WITH_MODULE_NAMESPACE(
1734 expr->module, expr_ns,
1735 asn1f_fetch_tags(arg->asn, expr_ns, expr->module, expr, &tags, 0));
1736 if(tags_count < 0) {
Lev Walkin725883b2006-10-09 12:07:58 +00001737 DEBUG("fail to fetch tags for %s", expr->Identifier);
Lev Walkin6d1220a2004-09-14 14:10:10 +00001738 return -1;
Lev Walkin725883b2006-10-09 12:07:58 +00001739 }
Lev Walkin64399722004-08-11 07:17:22 +00001740
Lev Walkin188ed2c2004-09-13 08:31:01 +00001741 /* Fetch a chain of tags */
Lev Walkinc0e03b92017-08-22 01:48:23 -07001742 all_tags_count = WITH_MODULE_NAMESPACE(
1743 expr->module, expr_ns,
1744 asn1f_fetch_tags(arg->asn, expr_ns, expr->module, expr, &all_tags,
1745 AFT_FULL_COLLECT));
1746 if(all_tags_count < 0) {
Lev Walkind8b83642016-03-14 02:00:27 -07001747 free(tags);
Lev Walkin725883b2006-10-09 12:07:58 +00001748 DEBUG("fail to fetch tags chain for %s", expr->Identifier);
Lev Walkin188ed2c2004-09-13 08:31:01 +00001749 return -1;
Lev Walkin5a8219a2004-09-08 00:28:57 +00001750 }
Lev Walkin906654e2004-09-10 15:49:15 +00001751
Lev Walkin188ed2c2004-09-13 08:31:01 +00001752 assert(tags_count <= all_tags_count);
1753 assert((tags_count?0:1) == (all_tags_count?0:1));
Lev Walkin27ea3802004-06-28 21:13:46 +00001754
Lev Walkin188ed2c2004-09-13 08:31:01 +00001755 if(tags_count <= all_tags_count) {
1756 for(i = 0; i < tags_count; i++) {
1757 if(tags[i].tag_value != all_tags[i].tag_value
1758 || tags[i].tag_class != all_tags[i].tag_class) {
1759 tv_mode = _TVM_DIFFERENT;
1760 break;
1761 }
1762 }
1763 if(i == tags_count && tags_count < all_tags_count)
1764 tv_mode = _TVM_SUBSET;
1765 } else {
1766 tv_mode = _TVM_DIFFERENT;
1767 }
1768
1769#define EMIT_TAGS_TABLE(name, tags, tags_count) do { \
Wim Lewisfb6344e2014-07-28 12:16:01 -07001770 OUT("static const ber_tlv_tag_t asn_DEF_%s%s_tags_%d[] = {\n",\
Lev Walkina00d6b32006-03-21 03:40:38 +00001771 MKID(expr), name, \
Lev Walkin59b176e2005-11-26 11:25:14 +00001772 expr->_type_unique_index); \
Lev Walkin188ed2c2004-09-13 08:31:01 +00001773 INDENT(+1); \
1774 /* Print the array of collected tags */ \
1775 for(i = 0; i < tags_count; i++) { \
1776 if(i) OUT(",\n"); \
1777 _print_tag(arg, &tags[i]); \
1778 } \
1779 OUT("\n"); \
1780 INDENT(-1); \
1781 OUT("};\n"); \
1782 } while(0)
1783
1784 if(tags_count) {
1785 if(tv_mode == _TVM_SUBSET)
1786 EMIT_TAGS_TABLE("", all_tags, all_tags_count);
1787 else
1788 EMIT_TAGS_TABLE("", tags, tags_count);
1789 }
1790
1791 if(all_tags_count) {
1792 if(tv_mode == _TVM_DIFFERENT)
1793 EMIT_TAGS_TABLE("_all", all_tags, all_tags_count);
1794 }
1795
Lev Walkind8b83642016-03-14 02:00:27 -07001796 free(tags);
1797 free(all_tags);
Lev Walkin188ed2c2004-09-13 08:31:01 +00001798
1799 *tags_count_r = tags_count;
1800 *all_tags_count_r = all_tags_count;
1801
1802 return tv_mode;
Lev Walkin27ea3802004-06-28 21:13:46 +00001803}
Lev Walkin59004fa2004-08-20 13:37:01 +00001804
1805static int
Lev Walkin59964be2004-08-25 02:03:12 +00001806expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin59004fa2004-08-20 13:37:01 +00001807 asn1p_expr_t *topmost_parent;
1808 asn1p_expr_t *v;
1809 int elements = 0;
1810
Lev Walkinc0e03b92017-08-22 01:48:23 -07001811 topmost_parent = WITH_MODULE_NAMESPACE(
1812 expr->module, expr_ns,
1813 asn1f_find_terminal_type_ex(arg->asn, expr_ns, expr));
1814 if(!topmost_parent) return 0;
Lev Walkin59004fa2004-08-20 13:37:01 +00001815
Lev Walkine0b56e02005-02-25 12:10:27 +00001816 if(!(topmost_parent->expr_type & ASN_CONSTR_MASK)
Lev Walkin1b3a1352016-01-10 13:15:02 -08001817 && !(topmost_parent->expr_type == ASN_BASIC_INTEGER)
Lev Walkin0f262452016-01-10 13:33:08 -08001818 && !(topmost_parent->expr_type == ASN_BASIC_ENUMERATED)
1819 && !(topmost_parent->expr_type == ASN_BASIC_BIT_STRING))
Lev Walkin59004fa2004-08-20 13:37:01 +00001820 return 0;
1821
1822 TQ_FOR(v, &(topmost_parent->members), next) {
1823 if(v->expr_type != A1TC_EXTENSIBLE)
1824 elements++;
1825 }
1826
1827 return elements;
1828}
1829
Lev Walkin59b176e2005-11-26 11:25:14 +00001830static asn1p_expr_type_e
1831expr_get_type(arg_t *arg, asn1p_expr_t *expr) {
1832 asn1p_expr_t *terminal;
Lev Walkinc0e03b92017-08-22 01:48:23 -07001833 terminal = asn1f_find_terminal_type_ex(arg->asn, arg->ns, expr);
Lev Walkin59b176e2005-11-26 11:25:14 +00001834 if(terminal) return terminal->expr_type;
1835 return A1TC_INVALID;
1836}
1837
Lev Walkin725883b2006-10-09 12:07:58 +00001838static asn1c_integer_t
1839PER_FROM_alphabet_characters(asn1cnst_range_t *range) {
1840 asn1c_integer_t numchars = 0;
1841 if(range->el_count) {
1842 int i;
1843 for(i = 0; i < range->el_count; i++)
1844 numchars
1845 += PER_FROM_alphabet_characters(range->elements[i]);
1846 } else {
1847 assert(range->left.type == ARE_VALUE);
1848 assert(range->right.type == ARE_VALUE);
1849 numchars = 1 + (range->right.value - range->left.value);
1850 }
1851 return numchars;
1852}
1853
Lev Walkin4118ccf2017-08-02 10:37:31 -07001854static void
1855emit_single_member_OER_constraint_comment(arg_t *arg, asn1cnst_range_t *range, char *type) {
1856
1857 /*
1858 * Print some courtesy debug information.
1859 */
1860 if(range
1861 && (range->left.type == ARE_VALUE || range->right.type == ARE_VALUE)) {
1862 OUT("\t/* ");
1863 if(type) OUT("(%s", type);
1864 OUT("(");
1865 if(range->left.type == ARE_VALUE)
Lev Walkinda997b12017-08-04 01:38:41 -07001866 OUT("%s", asn1p_itoa(range->left.value));
Lev Walkin4118ccf2017-08-02 10:37:31 -07001867 else
1868 OUT("MIN");
1869 OUT("..");
1870 if(range->right.type == ARE_VALUE)
Lev Walkinda997b12017-08-04 01:38:41 -07001871 OUT("%s", asn1p_itoa(range->right.value));
Lev Walkin4118ccf2017-08-02 10:37:31 -07001872 else
1873 OUT("MAX");
1874 if(range->extensible) OUT(",...");
1875 if(type) OUT(")");
1876 OUT(") */");
1877 }
1878}
1879
1880static int
Lev Walkinb9e98cb2017-08-02 12:53:44 -07001881emit_single_member_OER_constraint_value(arg_t *arg, asn1cnst_range_t *range) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07001882 if(!range) {
1883 /* oer_support.h: asn_oer_constraint_s */
1884 OUT("{ 0, 0 }");
1885 return 0;
1886 }
1887
1888 if(range->incompatible || range->not_OER_visible) {
1889 OUT("{ 0, 0 }");
Lev Walkinafcc8912017-10-04 23:48:35 -07001890 } else if(expr_get_type(arg, arg->expr) == ASN_BASIC_REAL) {
1891 if(range->narrowing == NARROW_FLOAT32) {
1892 OUT("{ sizeof(float), 0 }");
Lev Walkin43292722017-10-05 00:33:32 -07001893 } else if(range->narrowing == NARROW_DOUBLE64) {
Lev Walkinafcc8912017-10-04 23:48:35 -07001894 OUT("{ sizeof(double), 0 }");
1895 } else {
1896 OUT("{ 0, 0 }");
1897 }
Lev Walkin6713bcb2017-08-30 19:41:03 -07001898 } else if(range->left.type == ARE_VALUE && range->left.value >= 0
1899 && range->right.type == ARE_MAX) {
1900 OUT("{ 0, 1 }");
Lev Walkin4118ccf2017-08-02 10:37:31 -07001901 } else if(range->left.type == ARE_VALUE &&
1902 range->right.type == ARE_VALUE) {
1903 asn1c_integer_t lb = range->left.value;
1904 asn1c_integer_t ub = range->right.value;
1905 unsigned width = 0;
1906 unsigned positive = 0;
1907
Lev Walkinb9e98cb2017-08-02 12:53:44 -07001908
Lev Walkin4118ccf2017-08-02 10:37:31 -07001909 if(lb >= 0) {
1910 /* X.969 08/2015 10.2(a) */
1911 if(ub <= 255) {
1912 width = 1;
1913 } else if(ub <= 65535) {
1914 width = 2;
Lev Walkinb9e98cb2017-08-02 12:53:44 -07001915 } else if((unsigned long long)ub <= 4294967295UL) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07001916 width = 4;
Lev Walkinb9e98cb2017-08-02 12:53:44 -07001917 } else if((unsigned long long)ub <= 18446744073709551615ULL) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07001918 width = 8;
1919 }
1920 positive = 1;
1921 } else {
1922 positive = 0;
1923 /* X.969 08/2015 10.2(b) - no lower bound or negative lower bound */
1924 if(lb >= -128 && ub <= 127) {
1925 width = 1;
1926 } else if(lb >= -32768 && ub <= 32767) {
1927 width = 2;
1928 } else if(lb >= -2147483648L && ub <= 2147483647L) {
1929 width = 4;
Lev Walkinb9e98cb2017-08-02 12:53:44 -07001930 } else if(lb >= (-9223372036854775807LL-1)
Lev Walkin4118ccf2017-08-02 10:37:31 -07001931 && ub <= 9223372036854775807LL) {
1932 width = 8;
1933 }
1934 }
1935 OUT("{ %u, %u }", width, positive);
1936 } else {
1937 OUT("{ 0, 0 }");
1938 }
1939
1940 return 0;
1941}
1942
1943static int
Lev Walkinb9e98cb2017-08-02 12:53:44 -07001944emit_single_member_OER_constraint_size(arg_t *arg, asn1cnst_range_t *range) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07001945 if(!range) {
1946 /* oer_support.h: asn_oer_constraint_s */
1947 OUT("-1");
1948 return 0;
1949 }
1950
1951 if(range->incompatible || range->not_OER_visible) {
1952 OUT("-1");
1953 } else {
1954 if(range->left.type == ARE_VALUE && range->right.type == ARE_VALUE
1955 && range->left.value == range->right.value
1956 && range->left.value >= 0) {
Lev Walkinda997b12017-08-04 01:38:41 -07001957 OUT("%s", asn1p_itoa(range->left.value));
Lev Walkin4118ccf2017-08-02 10:37:31 -07001958 } else {
1959 OUT("-1");
1960 }
1961 }
1962
1963 return 0;
1964}
1965
Lev Walkin59b176e2005-11-26 11:25:14 +00001966static int
Lev Walkinb9e98cb2017-08-02 12:53:44 -07001967emit_single_member_PER_constraint(arg_t *arg, asn1cnst_range_t *range, int alphabetsize, const char *type) {
Lev Walkin4118ccf2017-08-02 10:37:31 -07001968 if(!range || range->incompatible || range->not_PER_visible) {
1969 OUT("{ APC_UNCONSTRAINED,\t-1, -1, 0, 0 }");
Lev Walkin59b176e2005-11-26 11:25:14 +00001970 return 0;
Lev Walkin4118ccf2017-08-02 10:37:31 -07001971 }
Lev Walkin59b176e2005-11-26 11:25:14 +00001972
Lev Walkin026e21a2017-10-04 00:49:01 -07001973 if(expr_get_type(arg, arg->expr) == ASN_BASIC_REAL) {
1974 /* Unsupported */
1975 OUT("{ APC_UNCONSTRAINED,\t-1, -1, 0, 0 }");
1976 return 0;
1977 }
1978
Lev Walkin4118ccf2017-08-02 10:37:31 -07001979 if(range->left.type == ARE_VALUE) {
Lev Walkin59b176e2005-11-26 11:25:14 +00001980 if(range->right.type == ARE_VALUE) {
1981 asn1c_integer_t cover = 1;
1982 asn1c_integer_t r = 1 + range->right.value
1983 - range->left.value;
Lev Walkinc46b7cb2006-08-18 02:27:55 +00001984 size_t rbits; /* Value range bits */
1985 ssize_t ebits; /* Value effective range bits */
Lev Walkin59b176e2005-11-26 11:25:14 +00001986
1987 if(range->empty_constraint)
1988 r = 0;
1989
Lev Walkin725883b2006-10-09 12:07:58 +00001990 if(alphabetsize) {
1991 /* X.691: 27.5.2 */
1992 r = PER_FROM_alphabet_characters(range);
1993 }
1994
Lev Walkin59b176e2005-11-26 11:25:14 +00001995 /* Compute real constraint */
1996 for(rbits = 0; rbits < (8 * sizeof(r)); rbits++) {
1997 if(r <= cover)
1998 break;
1999 cover *= 2; /* Can't do shifting */
2000 if(cover < 0) {
2001 FATAL("Constraint at line %d too wide "
2002 "for %d-bits integer type",
2003 arg->expr->_lineno,
2004 sizeof(r) * 8);
2005 rbits = sizeof(r);
2006 break;
2007 }
2008 }
2009
Lev Walkin3a4689a2006-11-24 11:20:27 +00002010 if(alphabetsize) {
2011 ebits = rbits;
2012 } else {
Lev Walkin59b176e2005-11-26 11:25:14 +00002013 /* X.691, #10.9.4.1 */
2014 for(ebits = 0; ebits <= 16; ebits++)
2015 if(r <= 1 << ebits) break;
2016 if(ebits == 17
2017 || range->right.value >= 65536)
2018 ebits = -1;
Lev Walkin3a4689a2006-11-24 11:20:27 +00002019 if(0) {
Lev Walkin59b176e2005-11-26 11:25:14 +00002020 /* X.691, #10.5.7.1 */
2021 for(ebits = 0; ebits <= 8; ebits++)
2022 if(r <= 1 << ebits) break;
2023 if(ebits == 9) {
2024 if(r <= 65536)
2025 ebits = 16;
2026 else
2027 ebits = -1;
2028 }
2029 }
Lev Walkin3a4689a2006-11-24 11:20:27 +00002030 }
Lev Walkin725883b2006-10-09 12:07:58 +00002031
Lev Walkin59b176e2005-11-26 11:25:14 +00002032 OUT("{ APC_CONSTRAINED%s,%s% d, % d, ",
2033 range->extensible
2034 ? " | APC_EXTENSIBLE" : "",
2035 range->extensible ? " " : "\t", rbits, ebits);
Lev Walkin3a4689a2006-11-24 11:20:27 +00002036
2037 if(alphabetsize) {
2038 asn1c_integer_t lv = range->left.value;
2039 asn1c_integer_t rv = range->right.value;
2040 int gcmt = 0;
2041 if(lv > 0x7fffffff) { lv = 0x7fffffff; gcmt++; }
2042 if(rv > 0x7fffffff) { rv = 0x7fffffff; gcmt++; }
2043 if(gcmt) {
Lev Walkin63b41262007-11-06 01:48:46 +00002044 OINTS(lv); OUT(", "); OINTS(rv); OUT(" }");
Lev Walkin3a4689a2006-11-24 11:20:27 +00002045 goto pcmt;
2046 }
2047 }
Lev Walkin59b176e2005-11-26 11:25:14 +00002048 } else {
2049 if(range->extensible) {
2050 OUT("{ APC_SEMI_CONSTRAINED | APC_EXTENSIBLE, "
2051 "-1, ");
2052 } else {
2053 OUT("{ APC_SEMI_CONSTRAINED,\t-1, -1, ");
2054 }
2055 }
Lev Walkin63b41262007-11-06 01:48:46 +00002056 OINTS(range->left.value); OUT(", ");
2057 OINTS(range->right.value); OUT(" }");
Lev Walkin59b176e2005-11-26 11:25:14 +00002058 } else {
2059 OUT("{ APC_UNCONSTRAINED,\t-1, -1, 0, 0 }");
2060 }
2061
Lev Walkin3a4689a2006-11-24 11:20:27 +00002062 pcmt:
2063
Lev Walkin59b176e2005-11-26 11:25:14 +00002064 /*
2065 * Print some courtesy debug information.
2066 */
2067 if(range->left.type == ARE_VALUE
2068 || range->right.type == ARE_VALUE) {
2069 OUT("\t/* ");
2070 if(type) OUT("(%s", type);
2071 OUT("(");
2072 if(range->left.type == ARE_VALUE)
Lev Walkinda997b12017-08-04 01:38:41 -07002073 OUT("%s", asn1p_itoa(range->left.value));
Lev Walkin59b176e2005-11-26 11:25:14 +00002074 else
2075 OUT("MIN");
2076 OUT("..");
2077 if(range->right.type == ARE_VALUE)
Lev Walkinda997b12017-08-04 01:38:41 -07002078 OUT("%s", asn1p_itoa(range->right.value));
Lev Walkin59b176e2005-11-26 11:25:14 +00002079 else
2080 OUT("MAX");
2081 if(range->extensible) OUT(",...");
2082 if(type) OUT(")");
2083 OUT(") */");
2084 }
2085
2086 return 0;
2087}
2088
2089static int
Lev Walkin98eabc12017-07-19 08:51:11 +04002090emit_member_OER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx) {
2091 int save_target = arg->target->target;
2092 asn1cnst_range_t *range;
2093 asn1p_expr_type_e etype;
2094
2095 etype = expr_get_type(arg, expr);
2096
2097 if((arg->flags & A1C_GEN_OER)
Lev Walkin135d7dd2017-08-28 00:21:38 -07002098 && (expr->combined_constraints || etype == ASN_BASIC_ENUMERATED
Lev Walkin98eabc12017-07-19 08:51:11 +04002099 || etype == ASN_CONSTR_CHOICE)) {
2100 /* Fall through */
2101 } else {
2102 return 0;
2103 }
2104
2105 REDIR(OT_CTDEFS);
2106
2107 OUT("static asn_oer_constraints_t "
Lev Walkin2e93c222017-09-26 18:29:15 -07002108 "asn_OER_%s_%s_constr_%d CC_NOTUSED = {\n",
Lev Walkin98eabc12017-07-19 08:51:11 +04002109 pfx, MKID(expr), expr->_type_unique_index);
2110
2111 INDENT(+1);
2112
Lev Walkin4118ccf2017-08-02 10:37:31 -07002113 /* .value{.width,.positive} */
Lev Walkina28cbb92017-07-31 20:20:17 -07002114 range = asn1constraint_compute_OER_range(expr->Identifier, etype,
2115 expr->combined_constraints,
Lev Walkin98eabc12017-07-19 08:51:11 +04002116 ACT_EL_RANGE, 0, 0, 0);
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002117 if(emit_single_member_OER_constraint_value(arg, range)) {
Lev Walkin98eabc12017-07-19 08:51:11 +04002118 return -1;
2119 }
Lev Walkin4118ccf2017-08-02 10:37:31 -07002120 emit_single_member_OER_constraint_comment(arg, range, 0);
Lev Walkin98eabc12017-07-19 08:51:11 +04002121 asn1constraint_range_free(range);
2122
2123 OUT(",\n");
2124
Lev Walkin4118ccf2017-08-02 10:37:31 -07002125 /* .size */
Lev Walkina28cbb92017-07-31 20:20:17 -07002126 range = asn1constraint_compute_OER_range(expr->Identifier, etype,
2127 expr->combined_constraints,
Lev Walkin98eabc12017-07-19 08:51:11 +04002128 ACT_CT_SIZE, 0, 0, 0);
Lev Walkinb9e98cb2017-08-02 12:53:44 -07002129 if(emit_single_member_OER_constraint_size(arg, range)) {
Lev Walkin98eabc12017-07-19 08:51:11 +04002130 return -1;
2131 }
Lev Walkin4118ccf2017-08-02 10:37:31 -07002132 emit_single_member_OER_constraint_comment(arg, range, "SIZE");
Lev Walkin98eabc12017-07-19 08:51:11 +04002133 asn1constraint_range_free(range);
2134
2135 INDENT(-1);
2136
2137 OUT("};\n");
2138
2139 REDIR(save_target);
2140
2141 return 0;
2142}
2143
2144static int
Lev Walkin4b5dae32006-10-09 12:27:44 +00002145emit_member_PER_constraints(arg_t *arg, asn1p_expr_t *expr, const char *pfx) {
Lev Walkin725883b2006-10-09 12:07:58 +00002146 int save_target = arg->target->target;
Lev Walkin59b176e2005-11-26 11:25:14 +00002147 asn1cnst_range_t *range;
2148 asn1p_expr_type_e etype;
2149
Lev Walkin07aaa342006-10-09 12:52:15 +00002150 etype = expr_get_type(arg, expr);
2151
Lev Walkin725883b2006-10-09 12:07:58 +00002152 if((arg->flags & A1C_GEN_PER)
Lev Walkin135d7dd2017-08-28 00:21:38 -07002153 && (expr->combined_constraints
Lev Walkin07aaa342006-10-09 12:52:15 +00002154 || etype == ASN_BASIC_ENUMERATED
Lev Walkin22cef6c2017-10-16 20:33:07 -07002155 || etype == ASN_CONSTR_CHOICE
2156 || (etype & ASN_STRING_KM_MASK)
2157 )
Lev Walkin725883b2006-10-09 12:07:58 +00002158 ) {
2159 /* Fall through */
2160 } else {
2161 return 0;
2162 }
2163
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002164 if(expr->_type_referenced) {
2165 REDIR(OT_FUNC_DECLS);
2166
2167 OUT("extern asn_per_constraints_t "
2168 "asn_PER_%s_%s_constr_%d;\n",
2169 pfx, MKID(expr), expr->_type_unique_index);
2170 }
2171
Lev Walkin725883b2006-10-09 12:07:58 +00002172 REDIR(OT_CTDEFS);
2173
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002174 if(!(expr->_type_referenced)) OUT("static ");
2175 OUT("asn_per_constraints_t "
Lev Walkin2e93c222017-09-26 18:29:15 -07002176 "asn_PER_%s_%s_constr_%d CC_NOTUSED = {\n",
Lev Walkin4b5dae32006-10-09 12:27:44 +00002177 pfx, MKID(expr), expr->_type_unique_index);
Lev Walkin725883b2006-10-09 12:07:58 +00002178
Lev Walkin59b176e2005-11-26 11:25:14 +00002179 INDENT(+1);
2180
2181 /*
2182 * ENUMERATED and CHOICE are special.
2183 */
2184 if(etype == ASN_BASIC_ENUMERATED
2185 || etype == ASN_CONSTR_CHOICE) {
2186 asn1cnst_range_t tmprng;
2187 asn1p_expr_t *v;
2188 int extensible = 0;
2189 int eidx = -1;
2190
Lev Walkinc0e03b92017-08-22 01:48:23 -07002191 expr = asn1f_find_terminal_type_ex(arg->asn, arg->ns, expr);
Lev Walkin59b176e2005-11-26 11:25:14 +00002192 assert(expr);
2193
2194 TQ_FOR(v, &(expr->members), next) {
2195 if(v->expr_type == A1TC_EXTENSIBLE) {
2196 extensible++;
2197 break;
2198 }
2199 eidx++;
2200 }
2201
2202 memset(&tmprng, 0, sizeof (tmprng));
2203 tmprng.extensible = extensible;
2204 if(eidx < 0) tmprng.empty_constraint = 1;
2205 tmprng.left.type = ARE_VALUE;
2206 tmprng.left.value = 0;
2207 tmprng.right.type = ARE_VALUE;
2208 tmprng.right.value = eidx < 0 ? 0 : eidx;
Lev Walkin725883b2006-10-09 12:07:58 +00002209 if(emit_single_member_PER_constraint(arg, &tmprng, 0, 0))
Lev Walkin59b176e2005-11-26 11:25:14 +00002210 return -1;
Lev Walkin729eb862006-09-21 01:50:13 +00002211 } else if(etype & ASN_STRING_KM_MASK) {
Lev Walkina28cbb92017-07-31 20:20:17 -07002212 range = asn1constraint_compute_PER_range(expr->Identifier, etype,
Lev Walkin729eb862006-09-21 01:50:13 +00002213 expr->combined_constraints, ACT_CT_FROM,
2214 0, 0, 0);
Lev Walkin725883b2006-10-09 12:07:58 +00002215 DEBUG("Emitting FROM constraint for %s", expr->Identifier);
Lev Walkin3a4689a2006-11-24 11:20:27 +00002216
2217 if((range->left.type == ARE_MIN && range->right.type == ARE_MAX)
2218 || range->not_PER_visible) {
2219 switch(etype) {
2220 case ASN_STRING_BMPString:
2221 range->left.type = ARE_VALUE;
2222 range->left.value = 0;
2223 range->right.type = ARE_VALUE;
2224 range->right.value = 65535;
2225 range->not_PER_visible = 0;
2226 range->extensible = 0;
2227 break;
2228 case ASN_STRING_UniversalString:
2229 OUT("{ APC_CONSTRAINED,\t32, 32,"
2230 " 0, 2147483647 }"
2231 " /* special case 1 */\n");
2232 goto avoid;
2233 default:
2234 break;
2235 }
2236 }
Lev Walkin725883b2006-10-09 12:07:58 +00002237 if(emit_single_member_PER_constraint(arg, range, 1, 0))
Lev Walkin729eb862006-09-21 01:50:13 +00002238 return -1;
Lev Walkin3a4689a2006-11-24 11:20:27 +00002239 avoid:
Lev Walkin729eb862006-09-21 01:50:13 +00002240 asn1constraint_range_free(range);
Lev Walkin59b176e2005-11-26 11:25:14 +00002241 } else {
Lev Walkina28cbb92017-07-31 20:20:17 -07002242 range = asn1constraint_compute_PER_range(expr->Identifier, etype,
Lev Walkin59b176e2005-11-26 11:25:14 +00002243 expr->combined_constraints, ACT_EL_RANGE,
2244 0, 0, 0);
Lev Walkin725883b2006-10-09 12:07:58 +00002245 if(emit_single_member_PER_constraint(arg, range, 0, 0))
Lev Walkin59b176e2005-11-26 11:25:14 +00002246 return -1;
2247 asn1constraint_range_free(range);
2248 }
2249 OUT(",\n");
2250
Lev Walkina28cbb92017-07-31 20:20:17 -07002251 range = asn1constraint_compute_PER_range(expr->Identifier, etype,
Lev Walkin59b176e2005-11-26 11:25:14 +00002252 expr->combined_constraints, ACT_CT_SIZE, 0, 0, 0);
Lev Walkin725883b2006-10-09 12:07:58 +00002253 if(emit_single_member_PER_constraint(arg, range, 0, "SIZE"))
Lev Walkin59b176e2005-11-26 11:25:14 +00002254 return -1;
2255 asn1constraint_range_free(range);
Lev Walkin725883b2006-10-09 12:07:58 +00002256 OUT(",\n");
2257
2258 if((etype & ASN_STRING_KM_MASK) && (expr->_mark & TM_PERFROMCT)) {
2259 int old_target = arg->target->target;
2260 REDIR(OT_CODE);
2261
2262 OUT("static int asn_PER_MAP_%s_%d_v2c(unsigned int value) {\n",
2263 MKID(expr), expr->_type_unique_index);
2264 OUT("\tif(value >= sizeof(permitted_alphabet_table_%d)/"
2265 "sizeof(permitted_alphabet_table_%d[0]))\n",
2266 expr->_type_unique_index,
2267 expr->_type_unique_index);
2268 OUT("\t\treturn -1;\n");
2269 OUT("\treturn permitted_alphabet_table_%d[value] - 1;\n",
2270 expr->_type_unique_index);
2271 OUT("}\n");
2272
2273 OUT("static int asn_PER_MAP_%s_%d_c2v(unsigned int code) {\n",
2274 MKID(expr), expr->_type_unique_index);
2275 OUT("\tif(code >= sizeof(permitted_alphabet_code2value_%d)/"
2276 "sizeof(permitted_alphabet_code2value_%d[0]))\n",
2277 expr->_type_unique_index,
2278 expr->_type_unique_index);
2279 OUT("\t\treturn -1;\n");
2280 OUT("\treturn permitted_alphabet_code2value_%d[code];\n",
2281 expr->_type_unique_index);
2282 OUT("}\n");
2283
2284 REDIR(old_target);
2285
2286 OUT("asn_PER_MAP_%s_%d_v2c,\t/* Value to PER code map */\n",
2287 MKID(expr), expr->_type_unique_index);
2288 OUT("asn_PER_MAP_%s_%d_c2v\t/* PER code to value map */\n",
2289 MKID(expr), expr->_type_unique_index);
2290 } else if(etype & ASN_STRING_KM_MASK) {
2291 DEBUG("No PER value map necessary for %s", MKID(expr));
2292 OUT("0, 0\t/* No PER character map necessary */\n");
2293 } else {
2294 OUT("0, 0\t/* No PER value map */\n");
2295 }
Lev Walkin59b176e2005-11-26 11:25:14 +00002296
2297 INDENT(-1);
2298
Lev Walkin725883b2006-10-09 12:07:58 +00002299 OUT("};\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002300
Lev Walkin725883b2006-10-09 12:07:58 +00002301 REDIR(save_target);
Lev Walkin59b176e2005-11-26 11:25:14 +00002302
2303 return 0;
2304}
2305
2306static int
Lev Walkin8032f7a2007-06-27 01:54:57 +00002307safe_string(const uint8_t *buf, int size) {
2308 const uint8_t *end = buf + size;
2309 for(; buf < end; buf++) {
2310 int ch = *buf;
2311 if((ch < 0x20 || ch > 0x7e) || ch == '"')
2312 return 0;
2313 }
2314 return 1;
2315}
2316
2317static void
Lev Walkin37231fb2017-10-17 21:24:34 -07002318emit_default_string_value(arg_t *arg, asn1p_value_t *v) {
Lev Walkin8032f7a2007-06-27 01:54:57 +00002319
Lev Walkin0b56b222017-10-18 00:40:32 -07002320 OUT("static const uint8_t defv[] = ");
Lev Walkin8032f7a2007-06-27 01:54:57 +00002321 assert(v->type == ATV_STRING);
2322
2323 if(safe_string(v->value.string.buf, v->value.string.size)) {
2324 OUT("\"%s\";\n", v->value.string.buf);
2325 } else {
2326 uint8_t *b = v->value.string.buf;
2327 uint8_t *e = v->value.string.size + b;
2328 OUT("{ ");
2329 for(;b < e; b++)
2330 OUT("0x%02x, ", *b);
2331 OUT("0 };\n");
2332 }
2333}
2334
2335static int
Lev Walkin59b176e2005-11-26 11:25:14 +00002336try_inline_default(arg_t *arg, asn1p_expr_t *expr, int out) {
2337 int save_target = arg->target->target;
2338 asn1p_expr_type_e etype = expr_get_type(arg, expr);
2339 int fits_long = 0;
2340
2341 switch(etype) {
2342 case ASN_BASIC_BOOLEAN:
2343 fits_long = 1;
Lev Walkin48e82d12017-10-19 03:06:35 -07002344 /* Fall through */
Lev Walkin59b176e2005-11-26 11:25:14 +00002345 case ASN_BASIC_INTEGER:
2346 case ASN_BASIC_ENUMERATED:
2347 if(expr->marker.default_value == NULL
Ryan Sleevia93d9972017-08-16 18:27:46 -04002348 || (expr->marker.default_value->type != ATV_INTEGER &&
2349 expr->marker.default_value->type != ATV_TRUE &&
2350 expr->marker.default_value->type != ATV_FALSE))
Lev Walkin59b176e2005-11-26 11:25:14 +00002351 break;
2352 if(!fits_long)
2353 fits_long = asn1c_type_fits_long(arg, expr)!=FL_NOTFIT;
2354 if(fits_long && !expr->marker.default_value->value.v_integer)
2355 expr->marker.flags &= ~EM_INDIRECT;
Lev Walkin8032f7a2007-06-27 01:54:57 +00002356 if(!out) {
Lev Walkin37231fb2017-10-17 21:24:34 -07002357 if(C99_MODE) OUT(".default_value_cmp = ");
Lev Walkin0b56b222017-10-18 00:40:32 -07002358 OUT("&asn_DFL_%d_cmp_%s,",
Lev Walkin37231fb2017-10-17 21:24:34 -07002359 expr->_type_unique_index,
2360 asn1p_itoa(expr->marker.default_value->value.v_integer));
2361 OUT("\t/* Compare DEFAULT %s */\n",
2362 asn1p_itoa(expr->marker.default_value->value.v_integer));
2363 if(C99_MODE) OUT(".default_value_set = ");
Lev Walkin0b56b222017-10-18 00:40:32 -07002364 OUT("&asn_DFL_%d_set_%s,",
Lev Walkin8032f7a2007-06-27 01:54:57 +00002365 expr->_type_unique_index,
Lev Walkinda997b12017-08-04 01:38:41 -07002366 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin37231fb2017-10-17 21:24:34 -07002367 OUT("\t/* Set DEFAULT %s */\n",
Lev Walkinda997b12017-08-04 01:38:41 -07002368 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin8032f7a2007-06-27 01:54:57 +00002369 return 1;
2370 }
Lev Walkin59b176e2005-11-26 11:25:14 +00002371 REDIR(OT_STAT_DEFS);
Lev Walkin37231fb2017-10-17 21:24:34 -07002372
2373 OUT("static int asn_DFL_%d_cmp_%s(const void *sptr) {\n",
2374 expr->_type_unique_index,
2375 asn1p_itoa(expr->marker.default_value->value.v_integer));
2376 INDENT(+1);
2377 OUT("const %s *st = sptr;\n", asn1c_type_name(arg, expr, TNF_CTYPE));
2378 OUT("\n");
2379 OUT("if(!st) {\n");
2380 OUT("\treturn -1; /* No value is not a default value */\n");
2381 OUT("}\n");
2382 OUT("\n");
2383 OUT("/* Test default value %s */\n",
2384 asn1p_itoa(expr->marker.default_value->value.v_integer));
2385 if(fits_long) {
2386 OUT("return (*st != %s);\n",
2387 asn1p_itoa(expr->marker.default_value->value.v_integer));
2388 } else {
2389 OUT("long value;\n");
2390 OUT("if(asn_INTEGER2long(st, &value))\n");
2391 OUT("\treturn -1;\n");
2392 OUT("return (value != %s);\n",
2393 asn1p_itoa(expr->marker.default_value->value.v_integer));
2394 }
2395 INDENT(-1);
2396 OUT("}\n");
2397
2398 OUT("static int asn_DFL_%d_set_%s(void **sptr) {\n",
Lev Walkin59b176e2005-11-26 11:25:14 +00002399 expr->_type_unique_index,
Lev Walkinda997b12017-08-04 01:38:41 -07002400 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin59b176e2005-11-26 11:25:14 +00002401 INDENT(+1);
2402 OUT("%s *st = *sptr;\n", asn1c_type_name(arg, expr, TNF_CTYPE));
2403 OUT("\n");
2404 OUT("if(!st) {\n");
2405 OUT("\tst = (*sptr = CALLOC(1, sizeof(*st)));\n");
2406 OUT("\tif(!st) return -1;\n");
2407 OUT("}\n");
2408 OUT("\n");
Lev Walkinda997b12017-08-04 01:38:41 -07002409 OUT("/* Install default value %s */\n",
2410 asn1p_itoa(expr->marker.default_value->value.v_integer));
Lev Walkin59b176e2005-11-26 11:25:14 +00002411 if(fits_long) {
Lev Walkin63b41262007-11-06 01:48:46 +00002412 OUT("*st = ");
2413 OINT(expr->marker.default_value->value.v_integer);
2414 OUT(";\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002415 OUT("return 0;\n");
2416 } else {
Lev Walkin63b41262007-11-06 01:48:46 +00002417 OUT("return asn_long2INTEGER(st, ");
2418 OINT(expr->marker.default_value->value.v_integer);
2419 OUT(");\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002420 }
2421 INDENT(-1);
Lev Walkin1dc85292006-08-18 01:32:26 +00002422 OUT("}\n");
Lev Walkin37231fb2017-10-17 21:24:34 -07002423
Lev Walkin59b176e2005-11-26 11:25:14 +00002424 REDIR(save_target);
2425 return 1;
2426 case ASN_BASIC_NULL:
2427 //expr->marker.flags &= ~EM_INDIRECT;
2428 return 0;
2429 default:
Lev Walkin8032f7a2007-06-27 01:54:57 +00002430 if(etype & ASN_STRING_KM_MASK) {
2431 if(expr->marker.default_value == NULL
2432 || expr->marker.default_value->type != ATV_STRING)
2433 break;
2434 if(!out) {
Lev Walkin37231fb2017-10-17 21:24:34 -07002435 if(C99_MODE) OUT(".default_value_cmp = ");
Lev Walkin0b56b222017-10-18 00:40:32 -07002436 OUT("&asn_DFL_%d_cmp,\t/* Compare DEFAULT \"%s\" */\n",
Lev Walkin37231fb2017-10-17 21:24:34 -07002437 expr->_type_unique_index,
2438 expr->marker.default_value->value.string.buf);
2439 if(C99_MODE) OUT(".default_value_set = ");
Lev Walkin0b56b222017-10-18 00:40:32 -07002440 OUT("&asn_DFL_%d_set,\t/* Set DEFAULT \"%s\" */\n",
Lev Walkin8032f7a2007-06-27 01:54:57 +00002441 expr->_type_unique_index,
2442 expr->marker.default_value->value.string.buf);
2443 return 1;
2444 }
2445 REDIR(OT_STAT_DEFS);
Lev Walkin37231fb2017-10-17 21:24:34 -07002446
2447 OUT("static int asn_DFL_%d_cmp(const void *sptr) {\n",
2448 expr->_type_unique_index);
2449 INDENT(+1);
2450 emit_default_string_value(arg, expr->marker.default_value);
2451 OUT("const %s *st = sptr;\n", asn1c_type_name(arg, expr, TNF_CTYPE));
2452 OUT("\n");
2453 OUT("if(!st) {\n");
2454 OUT("\treturn -1; /* No value is not a default value */\n");
2455 OUT("}\n");
2456 OUT("\n");
2457 OUT("if(st->size == (sizeof(defv) - 1)\n");
2458 OUT("&& memcmp(st->buf, &defv, sizeof(defv) - 1) == 0)\n");
2459 OUT("\treturn 0;\n");
2460 OUT("return 1;\n");
2461 INDENT(-1);
2462 OUT("}\n");
2463
2464 OUT("static int asn_DFL_%d_set(void **sptr) {\n",
2465 expr->_type_unique_index);
2466 INDENT(+1);
2467 emit_default_string_value(arg, expr->marker.default_value);
Lev Walkin8032f7a2007-06-27 01:54:57 +00002468 OUT("%s *st = *sptr;\n", asn1c_type_name(arg, expr, TNF_CTYPE));
Lev Walkin37231fb2017-10-17 21:24:34 -07002469 OUT("uint8_t *nstr = MALLOC(sizeof(defv));\n");
Lev Walkin8032f7a2007-06-27 01:54:57 +00002470 OUT("\n");
Lev Walkin37231fb2017-10-17 21:24:34 -07002471 OUT("if(!nstr) return -1;\n");
2472 OUT("memcpy(nstr, defv, sizeof(defv));\n");
2473 OUT("\n");
Lev Walkin0b56b222017-10-18 00:40:32 -07002474 OUT("if(st) {\n");
Lev Walkin37231fb2017-10-17 21:24:34 -07002475 OUT("\tFREEMEM(st->buf);\n");
Lev Walkin8032f7a2007-06-27 01:54:57 +00002476 OUT("} else {\n");
Lev Walkin37231fb2017-10-17 21:24:34 -07002477 OUT("\tst = (*sptr = CALLOC(1, sizeof(*st)));\n");
Lev Walkin04ca1b52017-10-18 00:27:35 -07002478 OUT("\tif(!st) { FREEMEM(nstr); return -1; }\n");
Lev Walkin37231fb2017-10-17 21:24:34 -07002479 OUT("}\n");
2480 OUT("st->buf = nstr;\n");
2481 OUT("st->size = sizeof(defv) - 1;\n");
2482 OUT("\n");
2483 OUT("return 0;\n");
Lev Walkin8032f7a2007-06-27 01:54:57 +00002484 INDENT(-1);
2485 OUT("}\n");
Lev Walkin37231fb2017-10-17 21:24:34 -07002486
Lev Walkin8032f7a2007-06-27 01:54:57 +00002487 REDIR(save_target);
2488 return 1;
2489 }
2490 break;
Lev Walkin59b176e2005-11-26 11:25:14 +00002491 }
2492 return 0;
2493}
2494
Lev Walkin59004fa2004-08-20 13:37:01 +00002495static int
Lev Walkin9de6cd82017-08-10 05:47:46 -07002496emit_member_type_selector(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_objset_t *opt_ioc) {
2497 int save_target = arg->target->target;
2498 asn1p_expr_t *parent_expr = arg->expr;
2499
2500 const asn1p_constraint_t *crc =
2501 asn1p_get_component_relation_constraint(expr->combined_constraints);
2502 if(!crc || crc->el_count <= 1) {
2503 /* Not an Open Type, it seems. */
2504 OUT("0");
2505 return 0;
2506 }
2507
Lev Walkind8e07c52017-08-23 07:38:30 -07002508 const asn1p_ref_t *objset_ref =
2509 asn1c_get_information_object_set_reference_from_constraint(arg, crc);
2510
Lev Walkinade508c2017-08-23 10:19:30 -07002511 if(!objset_ref) {
2512 FATAL("Constraint %s does not look like it referst to a set type %s",
2513 asn1p_constraint_string(crc),
2514 opt_ioc->objset->Identifier);
Lev Walkin9de6cd82017-08-10 05:47:46 -07002515 return -1;
2516 }
2517
Lev Walkinade508c2017-08-23 10:19:30 -07002518 const char *objset_name;
2519 if(objset_ref->comp_count == 1) {
2520 objset_name = objset_ref->components[0].name;
2521 } else if(objset_ref->comp_count == 2) {
2522 if(strcmp(objset_ref->components[0].name,
2523 opt_ioc->objset->module->ModuleName)
2524 != 0) {
2525 FATAL(
2526 "Composite reference %s (from %s) does not look like it refers "
2527 "to the same module as %s from an object set type %s",
2528 asn1p_ref_string(objset_ref), asn1p_constraint_string(crc),
2529 opt_ioc->objset->module->ModuleName,
2530 opt_ioc->objset->Identifier);
2531 return -1;
2532 }
2533 objset_name = objset_ref->components[1].name;
2534 } else {
2535 FATAL("Reference %s (from %s) does not look like an object set type %s",
2536 asn1p_ref_string(objset_ref), asn1p_constraint_string(crc),
2537 opt_ioc->objset->Identifier);
2538 return -1;
2539 }
Lev Walkin9de6cd82017-08-10 05:47:46 -07002540 if(strcmp(objset_name, opt_ioc->objset->Identifier) != 0) {
2541 FATAL("Object Set references do not match: %s != %s", objset_name,
2542 opt_ioc->objset->Identifier);
2543 return -1;
2544 }
2545
2546 if(crc->el_count != 2 || crc->elements[1]->type != ACT_EL_VALUE
2547 || crc->elements[1]->value->type != ATV_REFERENCED
2548 || crc->elements[1]->value->value.reference->comp_count != 1) {
2549 FATAL(
2550 "Do not know how to handle complex IoS constraints (%d components "
2551 "of constraint, %d components of reference %s) for %s at line "
2552 "%d",
2553 crc->el_count,
2554 crc->el_count >= 2 && crc->elements[1]->type == ACT_EL_VALUE
2555 && crc->elements[1]->value->type == ATV_REFERENCED
Lev Walkin5d929d82017-08-10 15:17:44 -07002556 ? (signed)crc->elements[1]->value->value.reference->comp_count
Lev Walkin9de6cd82017-08-10 05:47:46 -07002557 : -1,
2558 crc->el_count >= 2 && crc->elements[1]->type == ACT_EL_VALUE
2559 && crc->elements[1]->value->type == ATV_REFERENCED
2560 ? asn1p_ref_string(crc->elements[1]->value->value.reference)
2561 : "?",
2562 MKID(parent_expr), parent_expr->_lineno);
2563 OUT("0");
2564 return -1;
2565 }
2566
2567 const asn1p_ref_t *cref = crc->elements[1]->value->value.reference;
2568 const char *cname = cref->components[0].name;
2569 if(cname[0] == '@' && cname[1] != '.') {
2570 cname += 1;
2571 } else if(cname[0] == '@' && cname[1] == '.' && cname[2] != '.') {
2572 cname += 2;
2573 } else {
2574 FATAL("Complex IoS reference %s can not be processed",
2575 asn1p_ref_string(cref));
2576 OUT("0");
2577 return -1;
2578 }
2579
2580 assert(opt_ioc != NULL);
2581
Lev Walkinf6853ce2017-08-11 00:50:27 -07002582 asn1p_expr_t *constraining_memb = NULL;
2583 TQ_FOR(constraining_memb, &(parent_expr->members), next) {
2584 if(strcmp(constraining_memb->Identifier, cname) == 0) {
Lev Walkin9de6cd82017-08-10 05:47:46 -07002585 break;
Lev Walkinf6853ce2017-08-11 00:50:27 -07002586 }
Lev Walkin9de6cd82017-08-10 05:47:46 -07002587 }
2588 if(!constraining_memb) {
2589 FATAL("Can not find \"%s\" in %s at line %d", cname, MKID(parent_expr),
2590 parent_expr->_lineno);
2591 return -1;
2592 }
2593
2594 if(constraining_memb->meta_type != AMT_TYPEREF
2595 || constraining_memb->expr_type != A1TC_REFERENCE
2596 || constraining_memb->reference->comp_count != 2
2597 || constraining_memb->reference->components[1].lex_type
2598 != RLT_Amplowercase) {
2599 FATAL(
2600 "Does not look like %s is a CLASS field reference (%s) on line "
2601 "%d",
2602 MKID(constraining_memb),
2603 constraining_memb->reference
2604 ? asn1p_ref_string(constraining_memb->reference)
2605 : "<no reference>",
2606 constraining_memb->_lineno);
2607 return -1;
2608 }
2609 const char *cfield = constraining_memb->reference->components[1].name;
2610
2611 ssize_t constraining_column = -1;
2612 for(size_t cn = 0; cn < opt_ioc->ioct->rows ? opt_ioc->ioct->row[0]->columns : 0;
2613 cn++) {
2614 if(strcmp(cfield, opt_ioc->ioct->row[0]->column[cn].field->Identifier)
2615 == 0) {
2616 constraining_column = cn;
2617 break;
2618 }
2619 }
2620 if(constraining_column < 0) {
Lev Walkin53a28a22017-08-23 09:56:53 -07002621 if(opt_ioc->ioct->rows == 0) {
2622 OUT("0");
2623 return 0;
2624 } else {
2625 FATAL("Can not find referenced object class %s column %s\n",
2626 asn1p_ref_string(objset_ref), cfield);
2627 return -1;
2628 }
Lev Walkin9de6cd82017-08-10 05:47:46 -07002629 }
2630
2631 if(expr->meta_type != AMT_TYPEREF
2632 || expr->expr_type != A1TC_REFERENCE
2633 || expr->reference->comp_count != 2
Bi-Ruei, Chiu742a1962017-09-11 14:14:44 +08002634 || ((expr->reference->components[1].lex_type
2635 != RLT_AmpUppercase)
2636 && (expr->reference->components[1].lex_type
2637 != RLT_Amplowercase))) {
Lev Walkin9de6cd82017-08-10 05:47:46 -07002638 FATAL(
2639 "Does not look like %s is a CLASS field reference (%s) denoting a type on line "
2640 "%d",
2641 MKID(expr),
2642 expr->reference
2643 ? asn1p_ref_string(expr->reference)
2644 : "<no reference>",
2645 expr->_lineno);
2646 return -1;
2647 }
2648 const char *for_field = expr->reference->components[1].name;
2649
2650 ssize_t for_column = -1;
Bi-Ruei, Chiub6bd8d72017-09-18 23:35:40 +08002651 for(size_t cn = 0; cn < (opt_ioc->ioct->rows ? opt_ioc->ioct->row[0]->columns : 0);
Lev Walkin9de6cd82017-08-10 05:47:46 -07002652 cn++) {
2653 if(strcmp(for_field,
2654 opt_ioc->ioct->row[0]->column[cn].field->Identifier)
2655 == 0) {
2656 for_column = cn;
2657 break;
2658 }
2659 }
2660 if(for_column < 0) {
2661 FATAL("Can not find referenced object class column %s\n", for_field);
2662 return -1;
2663 }
2664
Lev Walkin9de6cd82017-08-10 05:47:46 -07002665 REDIR(OT_CODE);
Lev Walkinf6853ce2017-08-11 00:50:27 -07002666 OUT("static asn_type_selector_result_t\n");
Bi-Ruei, Chiu156b0fe2017-10-19 14:30:06 +08002667 OUT("select_%s_", c_name(arg).compound_name);
2668 OUT("%s_type(const asn_TYPE_descriptor_t *parent_type, const void *parent_sptr) {\n", MKID(expr));
Lev Walkin9de6cd82017-08-10 05:47:46 -07002669 INDENT(+1);
2670
Lev Walkinf6853ce2017-08-11 00:50:27 -07002671 OUT("asn_type_selector_result_t result = {0, 0};\n");
Lev Walkin6aae7c62017-08-10 17:58:48 -07002672 OUT("const asn_ioc_set_t *itable = asn_IOS_%s_%d;\n", MKID(opt_ioc->objset),
Lev Walkin9de6cd82017-08-10 05:47:46 -07002673 opt_ioc->objset->_type_unique_index);
2674 OUT("size_t constraining_column = %zu; /* %s */\n", constraining_column, cfield);
2675 OUT("size_t for_column = %zu; /* %s */\n", for_column, for_field);
2676 OUT("size_t row;\n");
2677
2678 const char *tname = asn1c_type_name(arg, constraining_memb, TNF_SAFE);
2679 if(constraining_memb->marker.flags & EM_INDIRECT) {
Lev Walkin6aae7c62017-08-10 17:58:48 -07002680 OUT("const void *memb_ptr = *(const void **)");
Lev Walkinb46156d2017-09-05 02:53:05 -07002681 OUT("((const char *)parent_sptr + offsetof(%s", c_name(arg).full_name);
Lev Walkin9de6cd82017-08-10 05:47:46 -07002682 OUT(", %s));", MKID_safe(constraining_memb));
Lev Walkinf6853ce2017-08-11 00:50:27 -07002683 OUT("if(!memb_ptr) return result;\n");
Lev Walkin9de6cd82017-08-10 05:47:46 -07002684 OUT("\n");
2685 }
2686
2687 switch(asn1c_type_fits_long(arg, constraining_memb)) {
2688 case FL_NOTFIT:
2689 OUT("const %s_t *constraining_value = (const %s_t *)", tname, tname);
2690 break;
2691 case FL_PRESUMED:
2692 case FL_FITS_SIGNED:
2693 OUT("const long *constraining_value = (const long *)");
2694 break;
2695 case FL_FITS_UNSIGN:
2696 OUT("const unsigned long *constraining_value = (const unsigned long *)");
2697 break;
2698 }
2699 if(constraining_memb->marker.flags & EM_INDIRECT) {
2700 OUT("memb_ptr;\n");
2701 } else {
Lev Walkinb46156d2017-09-05 02:53:05 -07002702 OUT("((const char *)parent_sptr + offsetof(%s", c_name(arg).full_name);
Lev Walkin9de6cd82017-08-10 05:47:46 -07002703 OUT(", %s));\n", MKID_safe(constraining_memb));
2704 }
2705 OUT("\n");
2706
2707 OUT("for(row=0; row < itable->rows_count; row++) {\n");
Lev Walkin6aae7c62017-08-10 17:58:48 -07002708 OUT(" const asn_ioc_cell_t *constraining_cell = &itable->rows[row * itable->columns_count + constraining_column];\n");
2709 OUT(" const asn_ioc_cell_t *type_cell = &itable->rows[row * itable->columns_count + for_column];\n");
2710 OUT("\n");
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +08002711 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 -07002712 OUT(" result.type_descriptor = type_cell->type_descriptor;\n");
2713 OUT(" result.presence_index = row + 1;\n");
2714 OUT(" break;\n");
Lev Walkin9de6cd82017-08-10 05:47:46 -07002715 OUT(" }\n");
2716 OUT("}\n");
2717
2718
2719 OUT("\n");
Lev Walkinf6853ce2017-08-11 00:50:27 -07002720 OUT("return result;\n");
Lev Walkin9de6cd82017-08-10 05:47:46 -07002721 INDENT(-1);
2722 OUT("}\n");
2723 OUT("\n");
2724
2725 REDIR(save_target);
Bi-Ruei, Chiu156b0fe2017-10-19 14:30:06 +08002726 OUT("select_%s_", c_name(arg).compound_name);
2727 OUT("%s_type", MKID(expr));
Lev Walkin9de6cd82017-08-10 05:47:46 -07002728
2729 return 0;
2730}
2731
2732static int
2733emit_member_table(arg_t *arg, asn1p_expr_t *expr, asn1c_ioc_table_and_objset_t *opt_ioc) {
Lev Walkin59004fa2004-08-20 13:37:01 +00002734 int save_target;
2735 arg_t tmp_arg;
Lev Walkinb9189732004-09-10 09:37:12 +00002736 struct asn1p_type_tag_s outmost_tag_s;
2737 struct asn1p_type_tag_s *outmost_tag;
Lev Walkine0b56e02005-02-25 12:10:27 +00002738 int complex_contents;
Lev Walkincf3f6eb2017-08-23 04:34:15 -07002739 const char *p;
Lev Walkin59004fa2004-08-20 13:37:01 +00002740
Lev Walkinc0e03b92017-08-22 01:48:23 -07002741 if(WITH_MODULE_NAMESPACE(
2742 expr->module, expr_ns,
2743 asn1f_fetch_outmost_tag(arg->asn, expr_ns, expr->module, expr,
2744 &outmost_tag_s, AFT_IMAGINARY_ANY))) {
2745 outmost_tag = 0;
Lev Walkinb9189732004-09-10 09:37:12 +00002746 } else {
2747 outmost_tag = &outmost_tag_s;
2748 }
2749
Lev Walkin59004fa2004-08-20 13:37:01 +00002750 OUT("{ ");
Lev Walkinb9189732004-09-10 09:37:12 +00002751
Lev Walkin14fd3e52017-08-27 01:38:45 -07002752 if(is_open_type(arg, expr, opt_ioc)) {
Lev Walkinf6853ce2017-08-11 00:50:27 -07002753 OUT("ATF_OPEN_TYPE | ");
Lev Walkin14fd3e52017-08-27 01:38:45 -07002754 } else if(outmost_tag && outmost_tag->tag_value == -1) {
2755 OUT("ATF_ANY_TYPE | ");
Lev Walkinf6853ce2017-08-11 00:50:27 -07002756 }
2757 OUT("%s, ",
Lev Walkinc8285712005-03-04 22:18:20 +00002758 (expr->marker.flags & EM_INDIRECT)?"ATF_POINTER":"ATF_NOFLAGS");
Lev Walkinb85a8132005-08-18 13:38:19 +00002759 if((expr->marker.flags & EM_OMITABLE) == EM_OMITABLE) {
Lev Walkin59004fa2004-08-20 13:37:01 +00002760 asn1p_expr_t *tv;
2761 int opts = 0;
Lev Walkinb85a8132005-08-18 13:38:19 +00002762 for(tv = expr;
2763 tv && (tv->marker.flags & EM_OMITABLE) == EM_OMITABLE;
Lev Walkin59004fa2004-08-20 13:37:01 +00002764 tv = TQ_NEXT(tv, next), opts++) {
2765 if(tv->expr_type == A1TC_EXTENSIBLE)
2766 opts--;
2767 }
2768 OUT("%d, ", opts);
2769 } else {
2770 OUT("0, ");
2771 }
Lev Walkinf6853ce2017-08-11 00:50:27 -07002772 if(expr->_anonymous_type) {
2773 assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
2774 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
2775 OUT("0,\n");
2776 } else {
Lev Walkinb46156d2017-09-05 02:53:05 -07002777 OUT("offsetof(%s, ", c_name(arg).full_name);
Lev Walkinf6853ce2017-08-11 00:50:27 -07002778 if((arg->expr->expr_type == ASN_CONSTR_CHOICE
2779 || arg->expr->expr_type == ASN_CONSTR_OPEN_TYPE)
2780 && (!UNNAMED_UNIONS))
2781 OUT("choice.");
2782 OUT("%s),\n", MKID_safe(expr));
2783 }
2784
2785 INDENT(+1);
Lev Walkin59004fa2004-08-20 13:37:01 +00002786 if(C99_MODE) OUT(".tag = ");
Lev Walkinb9189732004-09-10 09:37:12 +00002787 if(outmost_tag) {
2788 if(outmost_tag->tag_value == -1)
2789 OUT("-1 /* Ambiguous tag (ANY?) */");
2790 else
2791 _print_tag(arg, outmost_tag);
Lev Walkinc3e29402004-09-10 06:07:18 +00002792 } else {
Lev Walkinb9189732004-09-10 09:37:12 +00002793 OUT("-1 /* Ambiguous tag (CHOICE?) */");
Lev Walkinc3e29402004-09-10 06:07:18 +00002794 }
Lev Walkinb9189732004-09-10 09:37:12 +00002795
Lev Walkin59004fa2004-08-20 13:37:01 +00002796 OUT(",\n");
2797 if(C99_MODE) OUT(".tag_mode = ");
Lev Walkin9ab21b82006-10-19 02:46:01 +00002798 if((!(expr->expr_type & ASN_CONSTR_MASK)
2799 || expr->expr_type == ASN_CONSTR_CHOICE)
2800 && expr->tag.tag_class) {
Lev Walkin59004fa2004-08-20 13:37:01 +00002801 if(expr->tag.tag_mode == TM_IMPLICIT)
2802 OUT("-1,\t/* IMPLICIT tag at current level */\n");
2803 else
2804 OUT("+1,\t/* EXPLICIT tag at current level */\n");
2805 } else {
2806 OUT("0,\n");
2807 }
Lev Walkine0b56e02005-02-25 12:10:27 +00002808
2809 complex_contents =
Lev Walkinf6853ce2017-08-11 00:50:27 -07002810 is_open_type(arg, expr, opt_ioc)
2811 || (expr->expr_type & ASN_CONSTR_MASK)
Lev Walkine0b56e02005-02-25 12:10:27 +00002812 || expr->expr_type == ASN_BASIC_ENUMERATED
Lev Walkin8ecf9db2005-03-03 21:28:12 +00002813 || (0 /* -- prohibited by X.693:8.3.4 */
2814 && expr->expr_type == ASN_BASIC_INTEGER
Lev Walkin8bb57a22007-12-03 13:41:36 +00002815 && expr_elements_count(arg, expr))
2816 || (expr->expr_type == ASN_BASIC_INTEGER
2817 && asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN);
Lev Walkin59004fa2004-08-20 13:37:01 +00002818 if(C99_MODE) OUT(".type = ");
Lev Walkinf6853ce2017-08-11 00:50:27 -07002819
2820 OUT("&asn_DEF_");
2821 if(complex_contents) {
2822 OUT("%s", MKID(expr));
2823 if(!(arg->flags & A1C_ALL_DEFS_GLOBAL))
2824 OUT("_%d", expr->_type_unique_index);
2825 } else {
2826 OUT("%s", asn1c_type_name(arg, expr, TNF_SAFE));
2827 }
2828 OUT(",\n");
Lev Walkin9de6cd82017-08-10 05:47:46 -07002829
2830
2831 if(C99_MODE) OUT(".type_selector = ");
2832 if(opt_ioc) {
Lev Walkind8e07c52017-08-23 07:38:30 -07002833 if(emit_member_type_selector(arg, expr, opt_ioc) < 0)
2834 return -1;
Lev Walkin9de6cd82017-08-10 05:47:46 -07002835 } else {
2836 OUT("0");
2837 }
2838 OUT(",\n");
2839
Lev Walkin14e75ed2017-09-29 23:15:02 -07002840 OUT("{ ");
2841 if(C99_MODE) OUT(".oer_constraints = ");
2842 if(arg->flags & A1C_GEN_OER) {
2843 if(expr->constraints) {
2844 OUT("&asn_OER_memb_%s_constr_%d",
2845 MKID(expr),
2846 expr->_type_unique_index);
2847 } else {
2848 OUT("0");
2849 }
2850 } else {
2851 OUT("0");
2852 }
2853 OUT(", ");
2854 if(C99_MODE) OUT(".per_constraints = ");
2855 if(arg->flags & A1C_GEN_PER) {
2856 if(expr->constraints) {
2857 OUT("&asn_PER_memb_%s_constr_%d",
2858 MKID(expr),
2859 expr->_type_unique_index);
2860 } else {
2861 OUT("0");
2862 }
2863 } else {
2864 OUT("0");
2865 }
2866 OUT(", ");
2867 if(C99_MODE) OUT(".general_constraints = ");
Lev Walkin59004fa2004-08-20 13:37:01 +00002868 if(expr->constraints) {
Lev Walkin8de2ab22004-09-26 13:11:31 +00002869 if(arg->flags & A1C_NO_CONSTRAINTS) {
Lev Walkin14e75ed2017-09-29 23:15:02 -07002870 OUT("0");
Lev Walkin8de2ab22004-09-26 13:11:31 +00002871 } else {
Lev Walkincf3f6eb2017-08-23 04:34:15 -07002872 const char *id = MKID(expr);
Lev Walkin8de2ab22004-09-26 13:11:31 +00002873 if(expr->_anonymous_type
Lev Walkin152a91e2005-02-14 20:41:29 +00002874 && !strcmp(expr->Identifier, "Member"))
Lev Walkin8de2ab22004-09-26 13:11:31 +00002875 id = asn1c_type_name(arg, expr, TNF_SAFE);
Lev Walkin14e75ed2017-09-29 23:15:02 -07002876 OUT(" memb_%s_constraint_%d", id,
Lev Walkin21d00002005-03-04 08:48:53 +00002877 arg->expr->_type_unique_index);
Lev Walkin8de2ab22004-09-26 13:11:31 +00002878 }
Lev Walkin59004fa2004-08-20 13:37:01 +00002879 } else {
Lev Walkin14e75ed2017-09-29 23:15:02 -07002880 OUT("0");
Lev Walkin59004fa2004-08-20 13:37:01 +00002881 }
Lev Walkin14e75ed2017-09-29 23:15:02 -07002882 OUT(" },\n");
2883
Lev Walkin59b176e2005-11-26 11:25:14 +00002884 if(try_inline_default(arg, expr, 0)) {
Lev Walkin59b176e2005-11-26 11:25:14 +00002885 } else {
Lev Walkin37231fb2017-10-17 21:24:34 -07002886 OUT("0, 0, /* No default value */\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002887 }
2888 if(C99_MODE) OUT(".name = ");
2889 if(expr->_anonymous_type && !strcmp(expr->Identifier, "Member")) {
2890 OUT("\"\"\n");
2891 } else {
2892 OUT("\"%s\"\n", expr->Identifier);
Lev Walkin152a91e2005-02-14 20:41:29 +00002893 }
Lev Walkin59004fa2004-08-20 13:37:01 +00002894 OUT("},\n");
2895 INDENT(-1);
2896
Lev Walkin8de2ab22004-09-26 13:11:31 +00002897 if(!expr->constraints || (arg->flags & A1C_NO_CONSTRAINTS))
Lev Walkin59004fa2004-08-20 13:37:01 +00002898 return 0;
2899
2900 save_target = arg->target->target;
2901 REDIR(OT_CODE);
2902
Lev Walkin152a91e2005-02-14 20:41:29 +00002903 if(expr->_anonymous_type && !strcmp(expr->Identifier, "Member"))
Lev Walkin59004fa2004-08-20 13:37:01 +00002904 p = asn1c_type_name(arg, expr, TNF_SAFE);
Lev Walkina9cc46e2004-09-22 16:06:28 +00002905 else
Lev Walkina00d6b32006-03-21 03:40:38 +00002906 p = MKID(expr);
Lev Walkin59004fa2004-08-20 13:37:01 +00002907 OUT("static int\n");
Lev Walkin37231fb2017-10-17 21:24:34 -07002908 OUT("memb_%s_constraint_%d(const asn_TYPE_descriptor_t *td, const void *sptr,\n", p, arg->expr->_type_unique_index);
Lev Walkin59004fa2004-08-20 13:37:01 +00002909 INDENT(+1);
Lev Walkin1eded352006-07-13 11:19:01 +00002910 OUT("\t\tasn_app_constraint_failed_f *ctfailcb, void *app_key) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +00002911 tmp_arg = *arg;
2912 tmp_arg.expr = expr;
Lev Walkin725883b2006-10-09 12:07:58 +00002913 DEBUG("member constraint checking code for %s", p);
Lev Walkin59004fa2004-08-20 13:37:01 +00002914 if(asn1c_emit_constraint_checking_code(&tmp_arg) == 1) {
Lev Walkin14e75ed2017-09-29 23:15:02 -07002915 OUT("return td->encoding_constraints.general_constraints"
Lev Walkin1eded352006-07-13 11:19:01 +00002916 "(td, sptr, ctfailcb, app_key);\n");
Lev Walkin59004fa2004-08-20 13:37:01 +00002917 }
2918 INDENT(-1);
2919 OUT("}\n");
2920 OUT("\n");
2921
Lev Walkin98eabc12017-07-19 08:51:11 +04002922 if(emit_member_OER_constraints(arg, expr, "memb"))
2923 return -1;
2924
Lev Walkin4b5dae32006-10-09 12:27:44 +00002925 if(emit_member_PER_constraints(arg, expr, "memb"))
Lev Walkin725883b2006-10-09 12:07:58 +00002926 return -1;
2927
Lev Walkin59004fa2004-08-20 13:37:01 +00002928 REDIR(save_target);
2929
2930 return 0;
2931}
Lev Walkin59964be2004-08-25 02:03:12 +00002932
Lev Walkindc06f6b2004-10-20 15:50:55 +00002933/*
2934 * Generate "asn_DEF_XXX" type definition.
2935 */
Lev Walkin59964be2004-08-25 02:03:12 +00002936static int
Lev Walkin8de2ab22004-09-26 13:11:31 +00002937emit_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 +00002938 asn1p_expr_t *terminal;
Lev Walkin21d00002005-03-04 08:48:53 +00002939 int using_type_name = 0;
Lev Walkin14e75ed2017-09-29 23:15:02 -07002940 char *expr_id = strdup(MKID(expr));
2941 char *p = expr_id;
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002942 char *p2 = (char *)0;
Lev Walkin59b176e2005-11-26 11:25:14 +00002943
Lev Walkinc0e03b92017-08-22 01:48:23 -07002944 terminal = asn1f_find_terminal_type_ex(arg->asn, arg->ns, expr);
Lev Walkin8c2ca0b2006-09-17 06:31:08 +00002945
Lev Walkin01582a72017-07-26 18:47:08 -07002946 if(emit_member_OER_constraints(arg, expr, "type"))
2947 return -1;
2948
Lev Walkin4b5dae32006-10-09 12:27:44 +00002949 if(emit_member_PER_constraints(arg, expr, "type"))
Lev Walkin725883b2006-10-09 12:07:58 +00002950 return -1;
Lev Walkin59964be2004-08-25 02:03:12 +00002951
Lev Walkindd32b592004-09-06 08:07:29 +00002952 if(HIDE_INNER_DEFS)
2953 OUT("static /* Use -fall-defs-global to expose */\n");
Lev Walkin59b176e2005-11-26 11:25:14 +00002954 OUT("asn_TYPE_descriptor_t asn_DEF_%s", p);
Lev Walkinf6853ce2017-08-11 00:50:27 -07002955 if(HIDE_INNER_DEFS || (arg->flags & A1C_ALL_DEFS_GLOBAL))
2956 OUT("_%d", expr->_type_unique_index);
2957 OUT(" = {\n");
Lev Walkin188ed2c2004-09-13 08:31:01 +00002958 INDENT(+1);
Lev Walkin59b176e2005-11-26 11:25:14 +00002959
2960 if(expr->_anonymous_type) {
Lev Walkin14e75ed2017-09-29 23:15:02 -07002961 p = strdup(ASN_EXPR_TYPE2STR(expr->expr_type));
Lev Walkin59b176e2005-11-26 11:25:14 +00002962 OUT("\"%s\",\n", p?p:"");
Lev Walkina00d6b32006-03-21 03:40:38 +00002963 OUT("\"%s\",\n",
2964 p ? asn1c_make_identifier(AMI_CHECK_RESERVED,
2965 0, p, 0) : "");
Lev Walkin59b176e2005-11-26 11:25:14 +00002966 } else {
2967 OUT("\"%s\",\n", expr->Identifier);
2968 OUT("\"%s\",\n", expr->Identifier);
2969 }
Lev Walkin59964be2004-08-25 02:03:12 +00002970
2971 if(expr->expr_type & ASN_CONSTR_MASK) {
Lev Walkin21d00002005-03-04 08:48:53 +00002972 using_type_name = 1;
Lev Walkin14e75ed2017-09-29 23:15:02 -07002973 p = strdup(asn1c_type_name(arg, arg->expr, TNF_SAFE));
Lev Walkin59b176e2005-11-26 11:25:14 +00002974 } else {
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002975 if (expr->expr_type == A1TC_REFERENCE) {
2976 p2 = strdup(asn1c_type_name(arg, terminal, TNF_SAFE));
2977 } else {
2978 p2 = strdup(asn1c_type_name(arg, expr, TNF_SAFE));
2979 }
Lev Walkin14e75ed2017-09-29 23:15:02 -07002980 p = strdup(expr_id);
Lev Walkin59964be2004-08-25 02:03:12 +00002981 }
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08002982 if (!p2)
2983 p2 = strdup(p);
Lev Walkin59964be2004-08-25 02:03:12 +00002984
Lev Walkin14e75ed2017-09-29 23:15:02 -07002985 OUT("&asn_OP_%s,\n", p2);
Lev Walkin21d00002005-03-04 08:48:53 +00002986
Lev Walkin59964be2004-08-25 02:03:12 +00002987 if(tags_count) {
Lev Walkin59b176e2005-11-26 11:25:14 +00002988 OUT("asn_DEF_%s_tags_%d,\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -07002989 expr_id, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00002990 OUT("sizeof(asn_DEF_%s_tags_%d)\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -07002991 expr_id, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00002992 OUT("\t/sizeof(asn_DEF_%s_tags_%d[0])",
Lev Walkin14e75ed2017-09-29 23:15:02 -07002993 expr_id, expr->_type_unique_index);
Lev Walkin188ed2c2004-09-13 08:31:01 +00002994 if(tv_mode == _TVM_SUBSET
2995 && tags_count != all_tags_count)
2996 OUT(" - %d", all_tags_count - tags_count);
2997 OUT(", /* %d */\n", tags_count);
Lev Walkin59964be2004-08-25 02:03:12 +00002998 } else {
Lev Walkin188ed2c2004-09-13 08:31:01 +00002999 OUT("0,\t/* No effective tags (pointer) */\n");
3000 OUT("0,\t/* No effective tags (count) */\n");
3001 }
3002
3003 if(all_tags_count && tv_mode == _TVM_DIFFERENT) {
Lev Walkin59b176e2005-11-26 11:25:14 +00003004 OUT("asn_DEF_%s_all_tags_%d,\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -07003005 expr_id, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00003006 OUT("sizeof(asn_DEF_%s_all_tags_%d)\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -07003007 expr_id, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00003008 OUT("\t/sizeof(asn_DEF_%s_all_tags_%d[0]), /* %d */\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -07003009 expr_id, expr->_type_unique_index, all_tags_count);
Lev Walkin188ed2c2004-09-13 08:31:01 +00003010 } else if(all_tags_count) {
Lev Walkin59b176e2005-11-26 11:25:14 +00003011 OUT("asn_DEF_%s_tags_%d,\t/* Same as above */\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -07003012 expr_id, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00003013 OUT("sizeof(asn_DEF_%s_tags_%d)\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -07003014 expr_id, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00003015 OUT("\t/sizeof(asn_DEF_%s_tags_%d[0]), /* %d */\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -07003016 expr_id, expr->_type_unique_index, all_tags_count);
Lev Walkin188ed2c2004-09-13 08:31:01 +00003017 } else {
3018 OUT("0,\t/* No tags (pointer) */\n");
3019 OUT("0,\t/* No tags (count) */\n");
Lev Walkin59964be2004-08-25 02:03:12 +00003020 }
3021
Lev Walkin14e75ed2017-09-29 23:15:02 -07003022 OUT("{ ");
Lev Walkinb33425f2017-07-14 14:59:52 +04003023 if(arg->flags & A1C_GEN_OER) {
Lev Walkin135d7dd2017-08-28 00:21:38 -07003024 if(expr->combined_constraints
Lev Walkinb33425f2017-07-14 14:59:52 +04003025 || expr->expr_type == ASN_BASIC_ENUMERATED
3026 || expr->expr_type == ASN_CONSTR_CHOICE) {
Lev Walkin14e75ed2017-09-29 23:15:02 -07003027 OUT("&asn_OER_type_%s_constr_%d",
3028 expr_id, expr->_type_unique_index);
Lev Walkinb33425f2017-07-14 14:59:52 +04003029 } else {
Lev Walkin14e75ed2017-09-29 23:15:02 -07003030 OUT("0");
Lev Walkinb33425f2017-07-14 14:59:52 +04003031 }
3032 } else {
Lev Walkin14e75ed2017-09-29 23:15:02 -07003033 OUT("0");
Lev Walkinb33425f2017-07-14 14:59:52 +04003034 }
Lev Walkin14e75ed2017-09-29 23:15:02 -07003035 OUT(", ");
Lev Walkinb33425f2017-07-14 14:59:52 +04003036
Lev Walkin59b176e2005-11-26 11:25:14 +00003037 if(arg->flags & A1C_GEN_PER) {
Lev Walkin22cef6c2017-10-16 20:33:07 -07003038 if(expr->combined_constraints
3039 || expr->expr_type == ASN_BASIC_ENUMERATED
3040 || expr->expr_type == ASN_CONSTR_CHOICE
3041 || (expr->expr_type & ASN_STRING_KM_MASK)) {
3042 OUT("&asn_PER_type_%s_constr_%d",
Lev Walkin14e75ed2017-09-29 23:15:02 -07003043 expr_id, expr->_type_unique_index);
Lev Walkin59b176e2005-11-26 11:25:14 +00003044 } else {
Lev Walkin14e75ed2017-09-29 23:15:02 -07003045 OUT("0");
Lev Walkin59b176e2005-11-26 11:25:14 +00003046 }
3047 } else {
Lev Walkin14e75ed2017-09-29 23:15:02 -07003048 OUT("0");
Lev Walkin59b176e2005-11-26 11:25:14 +00003049 }
Lev Walkin14e75ed2017-09-29 23:15:02 -07003050 OUT(", ");
3051#define FUNCREF(foo) \
3052 do { \
3053 OUT("%s", p); \
3054 if(HIDE_INNER_DEFS && !using_type_name) \
3055 OUT("_%d", expr->_type_unique_index); \
3056 OUT("_" #foo ""); \
3057 } while(0)
3058
3059#define FUNCREF2(foo) \
3060 do { \
3061 OUT("%s", p2); \
3062 OUT("_" #foo); \
3063 } while(0)
3064
3065 if (arg->flags & A1C_NO_CONSTRAINTS) {
3066 OUT("0");
3067 } else {
3068 if (!expr->combined_constraints)
3069 FUNCREF2(constraint);
3070 else
3071 FUNCREF(constraint);
3072 }
3073 OUT(" },\n");
3074
3075 free(p);
3076 p = NULL;
3077 free(p2);
3078 p2 = NULL;
3079 free(expr_id);
3080 expr_id = NULL;
Lev Walkin59b176e2005-11-26 11:25:14 +00003081
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003082 if(elements_count ||
3083 ((expr->expr_type == A1TC_REFERENCE) &&
3084 (terminal->expr_type & ASN_CONSTR_MASK) &&
3085 expr_elements_count(arg, terminal))) {
3086
3087 if (expr->expr_type == A1TC_REFERENCE) {
3088 OUT("asn_MBR_%s_%d,\n", MKID(terminal), terminal->_type_unique_index);
3089
3090 if(terminal->expr_type == ASN_CONSTR_SEQUENCE_OF
3091 || terminal->expr_type == ASN_CONSTR_SET_OF) {
3092 OUT("%d,\t/* Single element */\n",
3093 expr_elements_count(arg, terminal));
3094 assert(expr_elements_count(arg, terminal) == 1);
3095 } else {
3096 OUT("%d,\t/* Elements count */\n",
3097 expr_elements_count(arg, terminal));
3098 }
Lev Walkin59964be2004-08-25 02:03:12 +00003099 } else {
Lev Walkin14e75ed2017-09-29 23:15:02 -07003100 OUT("asn_MBR_%s_%d,\n", c_name(arg).part_name,
3101 expr->_type_unique_index);
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003102
Lev Walkin14e75ed2017-09-29 23:15:02 -07003103 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003104 || expr->expr_type == ASN_CONSTR_SET_OF) {
3105 OUT("%d,\t/* Single element */\n",
3106 elements_count);
3107 assert(elements_count == 1);
3108 } else {
3109 OUT("%d,\t/* Elements count */\n",
3110 elements_count);
3111 }
Lev Walkin59964be2004-08-25 02:03:12 +00003112 }
3113 } else {
Lev Walkin59964be2004-08-25 02:03:12 +00003114 if(expr_elements_count(arg, expr))
3115 OUT("0, 0,\t/* Defined elsewhere */\n");
3116 else
3117 OUT("0, 0,\t/* No members */\n");
3118 }
3119
3120 switch(spec) {
3121 case ETD_NO_SPECIFICS:
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003122 if ((expr->expr_type == A1TC_REFERENCE) &&
3123 ((terminal->expr_type & ASN_CONSTR_MASK) ||
3124 (terminal->expr_type == ASN_BASIC_ENUMERATED) ||
3125 ((terminal->expr_type == ASN_BASIC_INTEGER) &&
3126 (asn1c_type_fits_long(arg, terminal) == FL_FITS_UNSIGN)))) {
Lev Walkin14e75ed2017-09-29 23:15:02 -07003127 OUT("&asn_SPC_%s_specs_%d\t/* Additional specs */\n",
3128 c_expr_name(arg, terminal).part_name,
3129 terminal->_type_unique_index);
3130 } else if ((expr->expr_type == ASN_TYPE_ANY) ||
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003131 (expr->expr_type == ASN_BASIC_BIT_STRING) ||
3132 (expr->expr_type == ASN_STRING_BMPString) ||
3133 (expr->expr_type == ASN_BASIC_OCTET_STRING) ||
3134 (expr->expr_type == ASN_STRING_UniversalString)) {
Lev Walkin14e75ed2017-09-29 23:15:02 -07003135 OUT("&asn_SPC_%s_specs\t/* Additional specs */\n",
3136 c_name(arg).type.part_name);
3137 } else if ((expr->expr_type == A1TC_REFERENCE) &&
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003138 ((terminal->expr_type == ASN_TYPE_ANY) ||
3139 (terminal->expr_type == ASN_BASIC_BIT_STRING) ||
3140 (terminal->expr_type == ASN_STRING_BMPString) ||
3141 (terminal->expr_type == ASN_BASIC_OCTET_STRING) ||
3142 (terminal->expr_type == ASN_STRING_UniversalString))) {
Lev Walkin14e75ed2017-09-29 23:15:02 -07003143 OUT("&asn_SPC_%s_specs\t/* Additional specs */\n",
3144 c_expr_name(arg, terminal).type.part_name);
3145 } else {
Bi-Ruei, Chiu1fa31c92016-05-16 13:50:09 +08003146 OUT("0\t/* No specifics */\n");
3147 }
Lev Walkin59964be2004-08-25 02:03:12 +00003148 break;
3149 case ETD_HAS_SPECIFICS:
Lev Walkin59b176e2005-11-26 11:25:14 +00003150 OUT("&asn_SPC_%s_specs_%d\t/* Additional specs */\n",
Lev Walkin14e75ed2017-09-29 23:15:02 -07003151 c_name(arg).part_name, expr->_type_unique_index);
Lev Walkin59964be2004-08-25 02:03:12 +00003152 }
Lev Walkin188ed2c2004-09-13 08:31:01 +00003153 INDENT(-1);
Lev Walkin59964be2004-08-25 02:03:12 +00003154 OUT("};\n");
3155 OUT("\n");
Lev Walkin97298782004-08-26 06:20:34 +00003156
3157 return 0;
Lev Walkin59964be2004-08-25 02:03:12 +00003158}
Lev Walkincc93b0f2004-09-10 09:18:20 +00003159
Lev Walkina9cc46e2004-09-22 16:06:28 +00003160static int
3161expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkind1bfea62005-11-08 03:06:16 +00003162 /*
3163 * X.680, 25.5, Table 5
3164 */
Lev Walkin59b176e2005-11-26 11:25:14 +00003165 switch(expr_get_type(arg, expr)) {
Lev Walkina9cc46e2004-09-22 16:06:28 +00003166 case ASN_BASIC_BOOLEAN:
3167 case ASN_BASIC_ENUMERATED:
3168 case ASN_BASIC_NULL:
3169 return 1;
Lev Walkind1bfea62005-11-08 03:06:16 +00003170 case ASN_CONSTR_CHOICE:
3171 return 2;
Lev Walkina9cc46e2004-09-22 16:06:28 +00003172 default:
3173 return 0;
3174 }
3175}
Lev Walkin801fabc2005-01-28 12:18:50 +00003176
3177static int
Lev Walkin0f5d74c2005-08-14 15:03:31 +00003178out_name_chain(arg_t *arg, enum onc_flags onc_flags) {
Lev Walkin801fabc2005-01-28 12:18:50 +00003179 asn1p_expr_t *expr = arg->expr;
Lev Walkinb46156d2017-09-05 02:53:05 -07003180 const char *id;
Lev Walkin801fabc2005-01-28 12:18:50 +00003181
Lev Walkin0f5d74c2005-08-14 15:03:31 +00003182 if((arg->flags & A1C_COMPOUND_NAMES
Denis Filatovdbb89902017-06-28 14:39:39 +02003183 || onc_flags & ONC_force_compound_name
Lev Walkinacdca412017-08-12 20:59:16 -07003184 || (0 && arg->embed /* Not yet */))
Lev Walkin21d00002005-03-04 08:48:53 +00003185 && ((expr->expr_type & ASN_CONSTR_MASK)
3186 || expr->expr_type == ASN_BASIC_ENUMERATED
Lev Walkinb02a8832005-08-13 23:51:47 +00003187 || ((expr->expr_type == ASN_BASIC_INTEGER
3188 || expr->expr_type == ASN_BASIC_BIT_STRING)
Lev Walkin21d00002005-03-04 08:48:53 +00003189 && expr_elements_count(arg, expr))
3190 )
Bi-Ruei, Chiu94f0b642017-06-29 01:34:23 +08003191 && expr->parent_expr) {
3192
Lev Walkin801fabc2005-01-28 12:18:50 +00003193 arg_t tmparg = *arg;
3194
3195 tmparg.expr = expr->parent_expr;
Lev Walkin21d00002005-03-04 08:48:53 +00003196 if(0) tmparg.flags &= ~A1C_COMPOUND_NAMES;
3197
Lev Walkin0f5d74c2005-08-14 15:03:31 +00003198 out_name_chain(&tmparg, onc_flags);
Lev Walkin801fabc2005-01-28 12:18:50 +00003199
Bi-Ruei, Chiu94f0b642017-06-29 01:34:23 +08003200 if(expr->parent_expr->Identifier) OUT("__"); /* a separator between id components */
Lev Walkin21d00002005-03-04 08:48:53 +00003201
Lev Walkin801fabc2005-01-28 12:18:50 +00003202 /* Fall through */
3203 }
3204
Lev Walkin0f5d74c2005-08-14 15:03:31 +00003205 if(onc_flags & ONC_avoid_keywords)
Lev Walkina00d6b32006-03-21 03:40:38 +00003206 id = MKID_safe(expr);
Lev Walkin801fabc2005-01-28 12:18:50 +00003207 else
Lev Walkina00d6b32006-03-21 03:40:38 +00003208 id = MKID(expr);
Lev Walkin801fabc2005-01-28 12:18:50 +00003209 OUT("%s", id);
3210
3211 return 0;
3212}
Lev Walkinb85a8132005-08-18 13:38:19 +00003213
3214static int
3215emit_include_dependencies(arg_t *arg) {
3216 asn1p_expr_t *expr = arg->expr;
3217 asn1p_expr_t *memb;
3218
3219 /* Avoid recursive definitions. */
3220 TQ_FOR(memb, &(expr->members), next) {
3221 expr_break_recursion(arg, memb);
3222 }
3223
3224 TQ_FOR(memb, &(expr->members), next) {
3225
3226 if(memb->marker.flags & (EM_INDIRECT | EM_UNRECURSE)) {
3227 if(terminal_structable(arg, memb)) {
3228 int saved_target = arg->target->target;
Bi-Ruei, Chiu9b87e5b2016-06-06 00:23:16 +08003229 if(saved_target != OT_FWD_DECLS) {
3230 REDIR(OT_FWD_DECLS);
3231 OUT("%s;\n",
3232 asn1c_type_name(arg, memb, TNF_RSAFE));
3233 }
Lev Walkinb85a8132005-08-18 13:38:19 +00003234 REDIR(saved_target);
3235 }
3236 }
3237
3238 if((!(memb->expr_type & ASN_CONSTR_MASK)
3239 && memb->expr_type > ASN_CONSTR_MASK)
3240 || memb->meta_type == AMT_TYPEREF) {
3241 if(memb->marker.flags & EM_UNRECURSE) {
3242 GEN_POSTINCLUDE(asn1c_type_name(arg,
3243 memb, TNF_INCLUDE));
3244 } else {
3245 GEN_INCLUDE(asn1c_type_name(arg,
3246 memb, TNF_INCLUDE));
3247 }
3248 }
3249 }
3250
3251 return 0;
3252}
3253
3254/*
3255 * Check if it is better to make this type indirectly accessed via
3256 * a pointer.
3257 * This may be the case for the following recursive definition:
3258 * Type ::= CHOICE { member Type };
3259 */
3260static int
3261expr_break_recursion(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkinb85a8132005-08-18 13:38:19 +00003262 int ret;
3263
3264 if(expr->marker.flags & EM_UNRECURSE)
3265 return 1; /* Already broken */
3266
Lev Walkinb85a8132005-08-18 13:38:19 +00003267 /* -findirect-choice compiles members of CHOICE as indirect pointers */
3268 if((arg->flags & A1C_INDIRECT_CHOICE)
3269 && arg->expr->expr_type == ASN_CONSTR_CHOICE
Lev Walkin59b176e2005-11-26 11:25:14 +00003270 && (expr_get_type(arg, expr) & ASN_CONSTR_MASK)
Lev Walkinb85a8132005-08-18 13:38:19 +00003271 ) {
3272 /* Break cross-reference */
3273 expr->marker.flags |= EM_INDIRECT | EM_UNRECURSE;
3274 return 1;
3275 }
3276
3277 if((expr->marker.flags & EM_INDIRECT)
3278 || arg->expr->expr_type == ASN_CONSTR_SET_OF
3279 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF) {
3280 if(terminal_structable(arg, expr)) {
3281 expr->marker.flags |= EM_UNRECURSE;
3282
3283 if(arg->expr->expr_type == ASN_CONSTR_SET_OF
3284 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF) {
3285 /* Don't put EM_INDIRECT even if recursion */
3286 return 1;
3287 }
3288
3289 /* Fall through */
3290 }
3291 }
3292
3293 /* Look for recursive back-references */
3294 ret = expr_defined_recursively(arg, expr);
3295 switch(ret) {
3296 case 2: /* Explicitly break the recursion */
3297 case 1: /* Use safer typing */
3298 expr->marker.flags |= EM_INDIRECT;
3299 expr->marker.flags |= EM_UNRECURSE;
3300 break;
3301 }
3302
3303 return 0;
3304}
3305
3306/*
3307 * Check if the type can be represented using simple `struct TYPE`.
3308 */
3309static asn1p_expr_t *
3310terminal_structable(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkinc0e03b92017-08-22 01:48:23 -07003311 asn1p_expr_t *terminal =
3312 asn1f_find_terminal_type_ex(arg->asn, arg->ns, expr);
3313 if(terminal
Lev Walkinb85a8132005-08-18 13:38:19 +00003314 && !terminal->parent_expr
3315 && (terminal->expr_type & ASN_CONSTR_MASK)) {
3316 return terminal;
3317 }
3318 return 0;
3319}
3320
3321static int
3322asn1c_recurse(arg_t *arg, asn1p_expr_t *expr, int (*callback)(arg_t *arg, void *key), void *key) {
3323 arg_t tmp = *arg;
3324 int maxret = 0;
3325 int ret;
3326
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +08003327 if(expr->_mark & TM_RECURSION) return 0;
Lev Walkinb85a8132005-08-18 13:38:19 +00003328 expr->_mark |= TM_RECURSION;
3329
3330 /* Invoke callback for every type going into recursion */
3331 tmp.expr = expr;
3332 maxret = callback(&tmp, key);
3333 if(maxret <= 1) {
3334 /*
3335 * Recursively invoke myself and the callbacks.
3336 */
3337 TQ_FOR(tmp.expr, &(expr->members), next) {
3338 ret = asn1c_recurse(&tmp, tmp.expr, callback, key);
3339 if(ret > maxret)
3340 maxret = ret;
3341 if(maxret > 1) break;
3342 }
3343 }
3344
3345 expr->_mark &= ~TM_RECURSION;
3346 return maxret;
3347}
3348
3349static int
3350check_is_refer_to(arg_t *arg, void *key) {
3351 asn1p_expr_t *terminal = terminal_structable(arg, arg->expr);
3352 if(terminal == key) {
3353 if(arg->expr->marker.flags & EM_INDIRECT)
3354 return 1; /* This is almost safe indirection */
3355 return 2;
3356 } else if(terminal) {
3357 /* This might be N-step circular loop. Dive into it. */
3358 return asn1c_recurse(arg, terminal, check_is_refer_to, key);
3359 }
3360 return 0;
3361}
3362
3363/*
3364 * Check if the possibly inner expression defined recursively.
3365 */
3366static int
3367expr_defined_recursively(arg_t *arg, asn1p_expr_t *expr) {
3368 asn1p_expr_t *terminal;
3369 asn1p_expr_t *topmost;
3370
3371 /* If expression is top-level, there's no way it can be recursive. */
3372 if(expr->parent_expr == 0) return 0;
3373 if(expr->expr_type != A1TC_REFERENCE)
3374 return 0; /* Basic types are never recursive */
3375
3376 terminal = terminal_structable(arg, expr);
3377 if(!terminal) return 0; /* Terminal cannot be indirected */
3378
3379 /* Search for the parent container for the given expression */
3380 topmost = expr;
3381 while(topmost->parent_expr)
3382 topmost = topmost->parent_expr;
3383
3384 /* Look inside the terminal type if it mentions the parent expression */
3385 return asn1c_recurse(arg, terminal, check_is_refer_to, topmost);
3386}
Lev Walkin59b176e2005-11-26 11:25:14 +00003387
3388struct canonical_map_element {
3389 int eidx;
3390 asn1p_expr_t *expr;
3391};
3392static int compar_cameo(const void *ap, const void *bp);
3393static arg_t *cameo_arg;
3394static int *
3395compute_canonical_members_order(arg_t *arg, int el_count) {
3396 struct canonical_map_element *cmap;
3397 int *rmap;
3398 asn1p_expr_t *v;
3399 int eidx = 0;
3400 int ext_start = -1;
3401 int nextmax = -1;
3402 int already_sorted = 1;
3403
3404 cmap = calloc(el_count, sizeof *cmap);
3405 assert(cmap);
3406
3407 TQ_FOR(v, &(arg->expr->members), next) {
3408 if(v->expr_type != A1TC_EXTENSIBLE) {
3409 cmap[eidx].eidx = eidx;
3410 cmap[eidx].expr = v;
3411 eidx++;
3412 } else if(ext_start == -1)
3413 ext_start = eidx;
3414 }
3415
3416 cameo_arg = arg;
3417 if(ext_start == -1) {
3418 /* Sort the whole thing */
3419 qsort(cmap, el_count, sizeof(*cmap), compar_cameo);
3420 } else {
3421 /* Sort root and extensions independently */
3422 qsort(cmap, ext_start, sizeof(*cmap), compar_cameo);
3423 qsort(cmap + ext_start, el_count - ext_start,
3424 sizeof(*cmap), compar_cameo);
3425 }
3426
3427 /* move data back to a simpler map */
3428 rmap = calloc(el_count, sizeof *rmap);
3429 assert(rmap);
3430 for(eidx = 0; eidx < el_count; eidx++) {
3431 rmap[eidx] = cmap[eidx].eidx;
3432 if(rmap[eidx] <= nextmax)
3433 already_sorted = 0;
3434 else
3435 nextmax = rmap[eidx];
3436 }
3437 free(cmap);
3438
3439 if(already_sorted) { free(rmap); rmap = 0; }
3440 return rmap;
3441}
3442static int compar_cameo(const void *ap, const void *bp) {
3443 const struct canonical_map_element *a = (const void *)ap;
3444 const struct canonical_map_element *b = (const void *)bp;
3445 struct asn1p_type_tag_s atag, btag;
3446 arg_t *arg = cameo_arg;
3447
Lev Walkinc0e03b92017-08-22 01:48:23 -07003448 if(WITH_MODULE_NAMESPACE(a->expr->module, expr_ns,
3449 asn1f_fetch_outmost_tag(
3450 arg->asn, expr_ns, a->expr->module, a->expr,
3451 &atag, AFT_IMAGINARY_ANY | AFT_CANON_CHOICE)))
3452 return 1;
Lev Walkin59b176e2005-11-26 11:25:14 +00003453
Lev Walkin48e82d12017-10-19 03:06:35 -07003454 if(WITH_MODULE_NAMESPACE(
3455 b->expr->module, expr_ns,
3456 asn1f_fetch_outmost_tag(arg->asn, expr_ns, b->expr->module, b->expr,
3457 &btag,
3458 AFT_IMAGINARY_ANY | AFT_CANON_CHOICE))) {
Lev Walkinc0e03b92017-08-22 01:48:23 -07003459 return -1;
Lev Walkin48e82d12017-10-19 03:06:35 -07003460 }
Lev Walkin59b176e2005-11-26 11:25:14 +00003461
Lev Walkin48e82d12017-10-19 03:06:35 -07003462 if(atag.tag_class < btag.tag_class)
Lev Walkin59b176e2005-11-26 11:25:14 +00003463 return -1;
3464 if(atag.tag_class > btag.tag_class)
3465 return 1;
3466 if(atag.tag_value < btag.tag_value)
3467 return -1;
3468 if(atag.tag_value > btag.tag_value)
3469 return 1;
3470 return 0;
3471
3472}