blob: 7b1536b99af15a096f73a7dd147d430d299f952d [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 Walkin84cd58e2004-08-19 13:29:46 +000010#include <asn1fix_export.h> /* Stuff exported by libasn1fix */
Lev Walkinf15320b2004-06-03 03:38:44 +000011
Lev Walkinfd171ef2004-06-06 07:20:17 +000012typedef struct tag2el_s {
13 struct asn1p_type_tag_s el_tag;
14 int el_no;
Lev Walkin38abe792004-06-14 13:09:45 +000015 int toff_first;
16 int toff_last;
Lev Walkinfd171ef2004-06-06 07:20:17 +000017 asn1p_expr_t *from_expr;
18} tag2el_t;
19
Lev Walkin33d5d3c2004-10-03 09:13:30 +000020typedef enum fte {
21 FTE_ALLTAGS,
22 FTE_CANONICAL_XER,
23} fte_e;
24static int _fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags);
25static 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 +000026
Lev Walkin0f5d74c2005-08-14 15:03:31 +000027enum onc_flags {
28 ONC_noflags = 0x00,
29 ONC_avoid_keywords = 0x01,
30 ONC_force_compound_name = 0x02,
31};
32static int out_name_chain(arg_t *arg, enum onc_flags);
Lev Walkinf15320b2004-06-03 03:38:44 +000033static int asn1c_lang_C_type_SEQUENCE_def(arg_t *arg);
34static int asn1c_lang_C_type_SET_def(arg_t *arg);
35static int asn1c_lang_C_type_CHOICE_def(arg_t *arg);
36static int asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of);
Lev Walkinc3e29402004-09-10 06:07:18 +000037static int _print_tag(arg_t *arg, struct asn1p_type_tag_s *tag_p);
Lev Walkin35631482004-07-01 00:52:50 +000038static int check_if_extensible(asn1p_expr_t *expr);
Lev Walkinda9a3b82005-08-16 17:00:21 +000039static int expr_break_recursion(arg_t *arg, asn1p_expr_t *expr);
Lev Walkina9cc46e2004-09-22 16:06:28 +000040static int expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr);
Lev Walkin59964be2004-08-25 02:03:12 +000041static int expr_elements_count(arg_t *arg, asn1p_expr_t *expr);
42static int emit_member_table(arg_t *arg, asn1p_expr_t *expr);
Lev Walkin33d5d3c2004-10-03 09:13:30 +000043static int emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier);
Lev Walkinc8285712005-03-04 22:18:20 +000044static int emit_include_dependencies(arg_t *arg);
Lev Walkinb85a8132005-08-18 13:38:19 +000045static asn1p_expr_t *terminal_structable(arg_t *arg, asn1p_expr_t *expr);
46static int expr_defined_recursively(arg_t *arg, asn1p_expr_t *expr);
47static int asn1c_recurse(arg_t *arg, asn1p_expr_t *expr, int (*callback)(arg_t *arg, void *key), void *key);
Lev Walkinf15320b2004-06-03 03:38:44 +000048
Lev Walkin188ed2c2004-09-13 08:31:01 +000049enum tvm_compat {
50 _TVM_SAME = 0, /* tags and all_tags are same */
51 _TVM_SUBSET = 1, /* tags are subset of all_tags */
52 _TVM_DIFFERENT = 2, /* tags and all_tags are different */
53};
54static enum tvm_compat emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tc, int *atc);
55
Lev Walkin59964be2004-08-25 02:03:12 +000056enum etd_spec {
57 ETD_NO_SPECIFICS,
58 ETD_HAS_SPECIFICS
59};
Lev Walkin8de2ab22004-09-26 13:11:31 +000060static 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 +000061
Lev Walkin59004fa2004-08-20 13:37:01 +000062#define C99_MODE (!(arg->flags & A1C_NO_C99))
Lev Walkinf15320b2004-06-03 03:38:44 +000063#define UNNAMED_UNIONS (arg->flags & A1C_UNNAMED_UNIONS)
Lev Walkindd32b592004-09-06 08:07:29 +000064#define HIDE_INNER_DEFS (arg->embed && !(arg->flags & A1C_ALL_DEFS_GLOBAL))
Lev Walkinf15320b2004-06-03 03:38:44 +000065
66#define PCTX_DEF INDENTED( \
67 OUT("\n"); \
68 OUT("/* Context for parsing across buffer boundaries */\n"); \
Lev Walkin05363a72004-09-29 13:16:40 +000069 OUT("asn_struct_ctx_t _asn_ctx;\n"));
Lev Walkinf15320b2004-06-03 03:38:44 +000070
Lev Walkinc8285712005-03-04 22:18:20 +000071
Lev Walkin3dcaafa2004-08-11 05:21:32 +000072#define DEPENDENCIES do { \
Lev Walkinc8285712005-03-04 22:18:20 +000073 emit_include_dependencies(arg); \
Lev Walkin3dcaafa2004-08-11 05:21:32 +000074 if(expr->expr_type == ASN_CONSTR_SET_OF) \
75 GEN_INCLUDE("asn_SET_OF"); \
76 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF) \
77 GEN_INCLUDE("asn_SEQUENCE_OF"); \
78} while(0)
Lev Walkinf15320b2004-06-03 03:38:44 +000079
Lev Walkincaf0d5a2005-03-04 23:48:19 +000080/* MKID_safe() without checking for reserved keywords */
81#define MKID(id) asn1c_make_identifier(0, (id), 0)
82#define MKID_safe(id) asn1c_make_identifier(AMI_CHECK_RESERVED, (id), 0)
Lev Walkinf15320b2004-06-03 03:38:44 +000083
84int
Lev Walkinc78cbfb2004-09-14 12:47:45 +000085asn1c_lang_C_type_REAL(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +000086 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
87}
88
Lev Walkine0b56e02005-02-25 12:10:27 +000089struct value2enum {
90 asn1c_integer_t value;
91 const char *name;
92 int idx;
93};
94static int compar_enumMap_byName(const void *ap, const void *bp) {
95 const struct value2enum *a = (const struct value2enum *)ap;
96 const struct value2enum *b = (const struct value2enum *)bp;
97 return strcmp(a->name, b->name);
98}
99static int compar_enumMap_byValue(const void *ap, const void *bp) {
100 const struct value2enum *a = (const struct value2enum *)ap;
101 const struct value2enum *b = (const struct value2enum *)bp;
102 if(a->value < b->value)
103 return -1;
104 else if(a->value == b->value)
105 return 0;
106 return 1;
107}
108
Lev Walkinf15320b2004-06-03 03:38:44 +0000109int
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000110asn1c_lang_C_type_common_INTEGER(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000111 asn1p_expr_t *expr = arg->expr;
112 asn1p_expr_t *v;
Lev Walkine0b56e02005-02-25 12:10:27 +0000113 int el_count = expr_elements_count(arg, expr);
114 struct value2enum *v2e;
115 int map_is_extensible = (expr->expr_type == ASN_BASIC_INTEGER);
Lev Walkin414b0782005-08-13 23:30:24 +0000116 int eidx;
Lev Walkinf15320b2004-06-03 03:38:44 +0000117
Lev Walkine0b56e02005-02-25 12:10:27 +0000118 v2e = alloca((el_count + 1) * sizeof(*v2e));
Lev Walkinf15320b2004-06-03 03:38:44 +0000119
Lev Walkine0b56e02005-02-25 12:10:27 +0000120 /*
Lev Walkin414b0782005-08-13 23:30:24 +0000121 * For all ENUMERATED types and for those INTEGER types which
122 * have identifiers, print out an enumeration table.
Lev Walkine0b56e02005-02-25 12:10:27 +0000123 */
Lev Walkin414b0782005-08-13 23:30:24 +0000124 if(expr->expr_type == ASN_BASIC_ENUMERATED || el_count) {
125 eidx = 0;
Lev Walkine0b56e02005-02-25 12:10:27 +0000126 REDIR(OT_DEPS);
Lev Walkin21d00002005-03-04 08:48:53 +0000127 OUT("typedef enum ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000128 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000129 OUT(" {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000130 TQ_FOR(v, &(expr->members), next) {
131 switch(v->expr_type) {
132 case A1TC_UNIVERVAL:
Lev Walkin21d00002005-03-04 08:48:53 +0000133 OUT("\t");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000134 out_name_chain(arg, ONC_noflags);
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000135 OUT("_%s", MKID(v->Identifier));
Lev Walkin21d00002005-03-04 08:48:53 +0000136 OUT("\t= %" PRIdASN "%s\n",
Lev Walkine0b56e02005-02-25 12:10:27 +0000137 v->value->value.v_integer,
Lev Walkin21d00002005-03-04 08:48:53 +0000138 (eidx+1 < el_count) ? "," : "");
Lev Walkine0b56e02005-02-25 12:10:27 +0000139 v2e[eidx].name = v->Identifier;
140 v2e[eidx].value = v->value->value.v_integer;
141 eidx++;
Lev Walkinf15320b2004-06-03 03:38:44 +0000142 break;
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000143 case A1TC_EXTENSIBLE:
144 OUT("\t/*\n");
145 OUT("\t * Enumeration is extensible\n");
146 OUT("\t */\n");
Lev Walkine0b56e02005-02-25 12:10:27 +0000147 map_is_extensible = 1;
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000148 break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000149 default:
150 return -1;
151 }
152 }
Lev Walkin21d00002005-03-04 08:48:53 +0000153 OUT("} ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000154 out_name_chain(arg, ONC_noflags);
Lev Walkin21d00002005-03-04 08:48:53 +0000155 OUT("_e;\n");
Lev Walkine0b56e02005-02-25 12:10:27 +0000156 assert(eidx == el_count);
Lev Walkin414b0782005-08-13 23:30:24 +0000157 }
158
159 /*
160 * For all ENUMERATED types print out a mapping table
161 * between identifiers and associated values.
162 * This is prohibited for INTEGER types by by X.693:8.3.4.
163 */
164 if(expr->expr_type == ASN_BASIC_ENUMERATED) {
Lev Walkine0b56e02005-02-25 12:10:27 +0000165
166 /*
167 * Generate a enumerationName<->value map for XER codec.
168 */
169 REDIR(OT_STAT_DEFS);
170
Lev Walkin21d00002005-03-04 08:48:53 +0000171 OUT("static asn_INTEGER_enum_map_t asn_MAP_%s_%d_value2enum[] = {\n",
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000172 MKID(expr->Identifier), expr->_type_unique_index);
Lev Walkine0b56e02005-02-25 12:10:27 +0000173 qsort(v2e, el_count, sizeof(v2e[0]), compar_enumMap_byValue);
174 for(eidx = 0; eidx < el_count; eidx++) {
175 v2e[eidx].idx = eidx;
176 OUT("\t{ %" PRIdASN ",\t%ld,\t\"%s\" }%s\n",
177 v2e[eidx].value,
178 (long)strlen(v2e[eidx].name), v2e[eidx].name,
179 (eidx + 1 < el_count) ? "," : "");
180 }
181 if(map_is_extensible)
182 OUT("\t/* This list is extensible */\n");
183 OUT("};\n");
184
Lev Walkin21d00002005-03-04 08:48:53 +0000185 OUT("static unsigned int asn_MAP_%s_%d_enum2value[] = {\n",
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000186 MKID(expr->Identifier), expr->_type_unique_index);
Lev Walkine0b56e02005-02-25 12:10:27 +0000187 qsort(v2e, el_count, sizeof(v2e[0]), compar_enumMap_byName);
188 for(eidx = 0; eidx < el_count; eidx++) {
189 OUT("\t%d%s\t/* %s(%" PRIdASN ") */\n",
190 v2e[eidx].idx,
191 (eidx + 1 < el_count) ? "," : "",
192 v2e[eidx].name, v2e[eidx].value);
193 }
194 if(map_is_extensible)
195 OUT("\t/* This list is extensible */\n");
196 OUT("};\n");
197
Lev Walkin21d00002005-03-04 08:48:53 +0000198 OUT("static asn_INTEGER_specifics_t asn_SPC_%s_%d_specs = {\n",
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000199 MKID(expr->Identifier), expr->_type_unique_index);
Lev Walkine0b56e02005-02-25 12:10:27 +0000200 INDENT(+1);
Lev Walkin21d00002005-03-04 08:48:53 +0000201 OUT("asn_MAP_%s_%d_value2enum,\t"
Lev Walkine0b56e02005-02-25 12:10:27 +0000202 "/* \"tag\" => N; sorted by tag */\n",
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000203 MKID(expr->Identifier),
Lev Walkin21d00002005-03-04 08:48:53 +0000204 expr->_type_unique_index);
205 OUT("asn_MAP_%s_%d_enum2value,\t"
Lev Walkine0b56e02005-02-25 12:10:27 +0000206 "/* N => \"tag\"; sorted by N */\n",
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000207 MKID(expr->Identifier),
Lev Walkin21d00002005-03-04 08:48:53 +0000208 expr->_type_unique_index);
Lev Walkine0b56e02005-02-25 12:10:27 +0000209 OUT("%d,\t/* Number of elements in the maps */\n",
210 el_count);
211 OUT("%d,\t/* Enumeration is %sextensible */\n",
212 map_is_extensible, map_is_extensible ? "": "not ");
213 if(expr->expr_type == ASN_BASIC_ENUMERATED)
214 OUT("1\t/* Strict enumeration */\n");
215 else
216 OUT("0\n");
217 INDENT(-1);
218 OUT("};\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000219 }
220
221 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
222}
223
224int
Lev Walkinb02a8832005-08-13 23:51:47 +0000225asn1c_lang_C_type_BIT_STRING(arg_t *arg) {
226 asn1p_expr_t *expr = arg->expr;
227 asn1p_expr_t *v;
228 int el_count = expr_elements_count(arg, expr);
Lev Walkinb02a8832005-08-13 23:51:47 +0000229
230 if(el_count) {
Lev Walkin082cadc2005-08-14 02:18:27 +0000231 int eidx = 0;
Lev Walkinb02a8832005-08-13 23:51:47 +0000232 REDIR(OT_DEPS);
233 OUT("typedef enum ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000234 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkinb02a8832005-08-13 23:51:47 +0000235 OUT(" {\n");
236 TQ_FOR(v, &(expr->members), next) {
Lev Walkin082cadc2005-08-14 02:18:27 +0000237 eidx++;
238 if(v->expr_type != A1TC_UNIVERVAL) {
Lev Walkinb02a8832005-08-13 23:51:47 +0000239 OUT("/* Unexpected BIT STRING element: %s */\n",
240 v->Identifier);
Lev Walkin082cadc2005-08-14 02:18:27 +0000241 continue;
Lev Walkinb02a8832005-08-13 23:51:47 +0000242 }
Lev Walkin082cadc2005-08-14 02:18:27 +0000243 OUT("\t");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000244 out_name_chain(arg, ONC_noflags);
Lev Walkin082cadc2005-08-14 02:18:27 +0000245 OUT("_%s", MKID(v->Identifier));
246 OUT("\t= %" PRIdASN "%s\n",
247 v->value->value.v_integer,
248 (eidx < el_count) ? "," : "");
Lev Walkinb02a8832005-08-13 23:51:47 +0000249 }
250 OUT("} ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000251 out_name_chain(arg, ONC_noflags);
Lev Walkinb02a8832005-08-13 23:51:47 +0000252 OUT("_e;\n");
253 assert(eidx == el_count);
254 }
255
256 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
257}
258
259int
Lev Walkinf15320b2004-06-03 03:38:44 +0000260asn1c_lang_C_type_SEQUENCE(arg_t *arg) {
261 asn1p_expr_t *expr = arg->expr;
262 asn1p_expr_t *v;
263 int comp_mode = 0; /* {root,ext=1,root,root,...} */
264
265 DEPENDENCIES;
266
267 if(arg->embed) {
Lev Walkin21d00002005-03-04 08:48:53 +0000268 OUT("struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000269 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000270 OUT(" {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000271 } else {
272 OUT("typedef struct %s {\n",
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000273 MKID_safe(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +0000274 }
275
276 TQ_FOR(v, &(expr->members), next) {
Lev Walkinda9a3b82005-08-16 17:00:21 +0000277 if(v->expr_type == A1TC_EXTENSIBLE)
Lev Walkinf15320b2004-06-03 03:38:44 +0000278 if(comp_mode < 3) comp_mode++;
Lev Walkinda9a3b82005-08-16 17:00:21 +0000279 if(comp_mode == 1)
Lev Walkinb85a8132005-08-18 13:38:19 +0000280 v->marker.flags |= EM_OMITABLE;
Lev Walkinf15320b2004-06-03 03:38:44 +0000281 EMBED(v);
282 }
283
284 PCTX_DEF;
Lev Walkinc8285712005-03-04 22:18:20 +0000285 OUT("} %s%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000286 expr->_anonymous_type ? "" :
287 arg->embed
288 ? MKID_safe(expr->Identifier)
289 : MKID(expr->Identifier),
Lev Walkin08079b02004-08-22 03:25:24 +0000290 arg->embed ? "" : "_t");
Lev Walkinf15320b2004-06-03 03:38:44 +0000291
292 return asn1c_lang_C_type_SEQUENCE_def(arg);
293}
294
295static int
296asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
297 asn1p_expr_t *expr = arg->expr;
298 asn1p_expr_t *v;
299 int elements; /* Number of elements */
Lev Walkinf15320b2004-06-03 03:38:44 +0000300 int ext_start = -1;
301 int ext_stop = -1;
Lev Walkinfd171ef2004-06-06 07:20:17 +0000302 tag2el_t *tag2el = NULL;
303 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000304 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000305 int all_tags_count;
306 enum tvm_compat tv_mode;
Lev Walkinf15320b2004-06-03 03:38:44 +0000307
Lev Walkinfd171ef2004-06-06 07:20:17 +0000308 /*
309 * Fetch every inner tag from the tag to elements map.
310 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000311 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
Lev Walkinfd171ef2004-06-06 07:20:17 +0000312 if(tag2el) free(tag2el);
313 return -1;
314 }
315
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000316 GEN_INCLUDE("constr_SEQUENCE");
317 if(!arg->embed)
Lev Walkin05363a72004-09-29 13:16:40 +0000318 GEN_DECLARE(expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000319
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000320 REDIR(OT_STAT_DEFS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000321
322 /*
323 * Print out the table according to which the parsing is performed.
324 */
Lev Walkina9cc46e2004-09-22 16:06:28 +0000325 if(expr_elements_count(arg, expr)) {
326 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Lev Walkinf15320b2004-06-03 03:38:44 +0000327
Lev Walkin21d00002005-03-04 08:48:53 +0000328 OUT("static asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000329 MKID(expr->Identifier), expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000330
331 elements = 0;
332 INDENTED(TQ_FOR(v, &(expr->members), next) {
333 if(v->expr_type == A1TC_EXTENSIBLE) {
334 if((++comp_mode) == 1)
335 ext_start = elements - 1;
336 else
337 ext_stop = elements - 1;
338 continue;
339 }
Lev Walkinda9a3b82005-08-16 17:00:21 +0000340 if(comp_mode == 1)
Lev Walkinb85a8132005-08-18 13:38:19 +0000341 v->marker.flags |= EM_OMITABLE;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000342 emit_member_table(arg, v);
Lev Walkinda9a3b82005-08-16 17:00:21 +0000343 elements++;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000344 });
345 OUT("};\n");
346 } else {
347 elements = 0;
348 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000349
Lev Walkin27ea3802004-06-28 21:13:46 +0000350 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000351 * Print out asn_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +0000352 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000353 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000354
Lev Walkinfd171ef2004-06-06 07:20:17 +0000355 /*
356 * Tags to elements map.
357 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000358 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
Lev Walkinfd171ef2004-06-06 07:20:17 +0000359
Lev Walkin21d00002005-03-04 08:48:53 +0000360 OUT("static asn_SEQUENCE_specifics_t asn_SPC_%s_%d_specs = {\n",
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000361 MKID(expr->Identifier), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +0000362 INDENTED(
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000363 OUT("sizeof(struct "); out_name_chain(arg, ONC_avoid_keywords); OUT("),\n");
364 OUT("offsetof(struct "); out_name_chain(arg, ONC_avoid_keywords); OUT(", _asn_ctx),\n");
Lev Walkin21d00002005-03-04 08:48:53 +0000365
Lev Walkinf3b29b12005-06-02 05:21:37 +0000366 if(tag2el_count) {
367 OUT("asn_MAP_%s_%d_tag2el,\n",
368 MKID(expr->Identifier),
369 expr->_type_unique_index);
370 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
371 } else {
372 OUT("0,\t/* No top level tags */\n");
373 OUT("0,\t/* No tags in the map */\n");
374 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000375 OUT("%d,\t/* Start extensions */\n",
376 ext_start);
377 OUT("%d\t/* Stop extensions */\n",
378 (ext_stop<ext_start)?elements+1:ext_stop, ext_stop);
379 );
380 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000381
382 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000383 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +0000384 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000385 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
Lev Walkin8de2ab22004-09-26 13:11:31 +0000386 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000387
Lev Walkinf15320b2004-06-03 03:38:44 +0000388 REDIR(OT_TYPE_DECLS);
389
390 return 0;
Lev Walkinb0b33412005-01-17 11:57:48 +0000391} /* _SEQUENCE_def() */
Lev Walkinf15320b2004-06-03 03:38:44 +0000392
393int
Lev Walkinf15320b2004-06-03 03:38:44 +0000394asn1c_lang_C_type_SET(arg_t *arg) {
395 asn1p_expr_t *expr = arg->expr;
396 asn1p_expr_t *v;
397 long mcount;
398 char *id;
399 int comp_mode = 0; /* {root,ext=1,root,root,...} */
400
401 DEPENDENCIES;
402
403 REDIR(OT_DEPS);
404
405 OUT("\n");
406 OUT("/*\n");
407 OUT(" * Method of determining the components presence\n");
408 OUT(" */\n");
409 mcount = 0;
Lev Walkin21d00002005-03-04 08:48:53 +0000410 OUT("typedef enum ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000411 out_name_chain(arg, ONC_noflags);
Lev Walkin21d00002005-03-04 08:48:53 +0000412 OUT("_PR {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000413 TQ_FOR(v, &(expr->members), next) {
414 if(v->expr_type == A1TC_EXTENSIBLE) continue;
415 INDENTED(
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000416 out_name_chain(arg, ONC_noflags);
Lev Walkin801fabc2005-01-28 12:18:50 +0000417 OUT("_PR_");
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000418 id = MKID(v->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000419 OUT("%s,\t/* Member %s is present */\n",
420 id, id)
421 );
422 mcount++;
423 }
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000424 OUT("} "); out_name_chain(arg, ONC_noflags); OUT("_PR;\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000425
426 REDIR(OT_TYPE_DECLS);
427
428 if(arg->embed) {
Lev Walkin21d00002005-03-04 08:48:53 +0000429 OUT("struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000430 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000431 OUT(" {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000432 } else {
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000433 OUT("typedef struct %s {\n", MKID_safe(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +0000434 }
435
436 TQ_FOR(v, &(expr->members), next) {
437 if(v->expr_type == A1TC_EXTENSIBLE) {
438 if(comp_mode < 3) comp_mode++;
439 }
Lev Walkinda9a3b82005-08-16 17:00:21 +0000440 if(comp_mode == 1)
Lev Walkinb85a8132005-08-18 13:38:19 +0000441 v->marker.flags |= EM_OMITABLE;
Lev Walkinf15320b2004-06-03 03:38:44 +0000442 EMBED(v);
443 }
444
445 INDENTED(
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000446 id = MKID(expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000447 OUT("\n");
448 OUT("/* Presence bitmask: ASN_SET_ISPRESENT(p%s, %s_PR_x) */\n",
449 id, id);
450 OUT("unsigned int _presence_map\n");
451 OUT("\t[((%ld+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))];\n", mcount);
452 );
453
454 PCTX_DEF;
Lev Walkinc8285712005-03-04 22:18:20 +0000455 OUT("} %s%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000456 expr->_anonymous_type ? "" : MKID_safe(expr->Identifier),
Lev Walkin08079b02004-08-22 03:25:24 +0000457 arg->embed ? "" : "_t");
Lev Walkinf15320b2004-06-03 03:38:44 +0000458
459 return asn1c_lang_C_type_SET_def(arg);
460}
461
Lev Walkinf15320b2004-06-03 03:38:44 +0000462static int
463asn1c_lang_C_type_SET_def(arg_t *arg) {
464 asn1p_expr_t *expr = arg->expr;
465 asn1p_expr_t *v;
466 int elements;
Lev Walkinf15320b2004-06-03 03:38:44 +0000467 tag2el_t *tag2el = NULL;
468 int tag2el_count = 0;
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000469 tag2el_t *tag2el_cxer = NULL;
470 int tag2el_cxer_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000471 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000472 int all_tags_count;
473 enum tvm_compat tv_mode;
Lev Walkinf15320b2004-06-03 03:38:44 +0000474 char *p;
475
476 /*
477 * Fetch every inner tag from the tag to elements map.
478 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000479 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000480 if(tag2el) free(tag2el);
481 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000482 }
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000483 if(_fill_tag2el_map(arg, &tag2el_cxer, &tag2el_cxer_count, -1, FTE_CANONICAL_XER)) {
484 if(tag2el) free(tag2el);
485 if(tag2el_cxer) free(tag2el_cxer);
486 return -1;
487 }
488 if(tag2el_cxer_count == tag2el_count
489 && memcmp(tag2el, tag2el_cxer, tag2el_count) == 0) {
490 free(tag2el_cxer);
491 tag2el_cxer = 0;
492 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000493
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000494 GEN_INCLUDE("constr_SET");
495 if(!arg->embed)
Lev Walkin05363a72004-09-29 13:16:40 +0000496 GEN_DECLARE(expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000497
498 REDIR(OT_STAT_DEFS);
499
Lev Walkinf15320b2004-06-03 03:38:44 +0000500 /*
501 * Print out the table according to which the parsing is performed.
502 */
Lev Walkina9cc46e2004-09-22 16:06:28 +0000503 if(expr_elements_count(arg, expr)) {
504 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Lev Walkinf15320b2004-06-03 03:38:44 +0000505
Lev Walkin21d00002005-03-04 08:48:53 +0000506 OUT("static asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000507 MKID(expr->Identifier), expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000508
509 elements = 0;
510 INDENTED(TQ_FOR(v, &(expr->members), next) {
511 if(v->expr_type == A1TC_EXTENSIBLE) {
512 if(comp_mode < 3) comp_mode++;
513 } else {
Lev Walkinda9a3b82005-08-16 17:00:21 +0000514 if(comp_mode == 1)
Lev Walkinb85a8132005-08-18 13:38:19 +0000515 v->marker.flags |= EM_OMITABLE;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000516 emit_member_table(arg, v);
Lev Walkinda9a3b82005-08-16 17:00:21 +0000517 elements++;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000518 }
519 });
520 OUT("};\n");
521 } else {
522 elements = 0;
523 }
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
530 /*
531 * Tags to elements map.
532 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000533 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
534 if(tag2el_cxer)
535 emit_tag2member_map(arg, tag2el_cxer, tag2el_cxer_count, "_cxer");
Lev Walkinf15320b2004-06-03 03:38:44 +0000536
537 /*
538 * Emit a map of mandatory elements.
539 */
Lev Walkin21d00002005-03-04 08:48:53 +0000540 OUT("static uint8_t asn_MAP_%s_%d_mmap",
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000541 MKID(expr->Identifier), expr->_type_unique_index);
542 p = MKID_safe(expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000543 OUT("[(%d + (8 * sizeof(unsigned int)) - 1) / 8]", elements);
Lev Walkin21d00002005-03-04 08:48:53 +0000544 OUT(" = {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000545 INDENTED(
546 if(elements) {
547 int delimit = 0;
548 int el = 0;
549 TQ_FOR(v, &(expr->members), next) {
550 if(v->expr_type == A1TC_EXTENSIBLE) continue;
551 if(delimit) {
552 OUT(",\n");
553 delimit = 0;
554 } else if(el) {
555 OUT(" | ");
556 }
Lev Walkincc93b0f2004-09-10 09:18:20 +0000557 OUT("(%d << %d)",
Lev Walkinb85a8132005-08-18 13:38:19 +0000558 (v->marker.flags & EM_OMITABLE) != EM_OMITABLE,
Lev Walkincc93b0f2004-09-10 09:18:20 +0000559 7 - (el % 8));
Lev Walkinf15320b2004-06-03 03:38:44 +0000560 if(el && (el % 8) == 0)
561 delimit = 1;
562 el++;
563 }
564 } else {
565 OUT("0");
566 }
567 );
568 OUT("\n");
569 OUT("};\n");
570
Lev Walkin21d00002005-03-04 08:48:53 +0000571 OUT("static asn_SET_specifics_t asn_SPC_%s_%d_specs = {\n",
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000572 MKID(expr->Identifier), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +0000573 INDENTED(
Lev Walkin21d00002005-03-04 08:48:53 +0000574 OUT("sizeof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000575 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000576 OUT("),\n");
577 OUT("offsetof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000578 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000579 OUT(", _asn_ctx),\n");
580 OUT("offsetof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000581 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000582 OUT(", _presence_map),\n");
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000583 p = MKID(expr->Identifier);
Lev Walkin21d00002005-03-04 08:48:53 +0000584 OUT("asn_MAP_%s_%d_tag2el,\n", p, expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +0000585 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000586 if(tag2el_cxer)
Lev Walkin21d00002005-03-04 08:48:53 +0000587 OUT("asn_MAP_%s_%d_tag2el_cxer,\n",
588 p, expr->_type_unique_index);
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000589 else
Lev Walkin21d00002005-03-04 08:48:53 +0000590 OUT("asn_MAP_%s_%d_tag2el,\t/* Same as above */\n",
591 p, expr->_type_unique_index);
592 OUT("%d,\t/* Count of tags in the CXER map */\n",
593 tag2el_cxer_count);
Lev Walkin35631482004-07-01 00:52:50 +0000594 OUT("%d,\t/* Whether extensible */\n",
595 check_if_extensible(expr));
Lev Walkin21d00002005-03-04 08:48:53 +0000596 OUT("(unsigned int *)asn_MAP_%s_%d_mmap\t/* Mandatory elements map */\n",
597 p, expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +0000598 );
599 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000600
601 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000602 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +0000603 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000604 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
Lev Walkin8de2ab22004-09-26 13:11:31 +0000605 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000606
Lev Walkinf15320b2004-06-03 03:38:44 +0000607 REDIR(OT_TYPE_DECLS);
608
609 return 0;
Lev Walkinb0b33412005-01-17 11:57:48 +0000610} /* _SET_def() */
Lev Walkinf15320b2004-06-03 03:38:44 +0000611
612int
Lev Walkin08079b02004-08-22 03:25:24 +0000613asn1c_lang_C_type_SEx_OF(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000614 asn1p_expr_t *expr = arg->expr;
Lev Walkinc8285712005-03-04 22:18:20 +0000615 asn1p_expr_t *memb = TQ_FIRST(&expr->members);
Lev Walkinf15320b2004-06-03 03:38:44 +0000616
617 DEPENDENCIES;
618
619 if(arg->embed) {
Lev Walkin21d00002005-03-04 08:48:53 +0000620 OUT("struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000621 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000622 OUT(" {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000623 } else {
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000624 OUT("typedef struct %s {\n", MKID_safe(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +0000625 }
626
Lev Walkin08079b02004-08-22 03:25:24 +0000627 INDENT(+1);
628 OUT("A_%s_OF(",
629 (arg->expr->expr_type == ASN_CONSTR_SET_OF)
630 ? "SET" : "SEQUENCE");
Lev Walkinda9a3b82005-08-16 17:00:21 +0000631
632 /*
633 * README README
634 * The implementation of the A_SET_OF() macro is already indirect.
635 */
636 memb->marker.flags |= EM_INDIRECT;
637
Lev Walkine0b56e02005-02-25 12:10:27 +0000638 if(memb->expr_type & ASN_CONSTR_MASK
639 || ((memb->expr_type == ASN_BASIC_ENUMERATED
Lev Walkin8ecf9db2005-03-03 21:28:12 +0000640 || (0 /* -- prohibited by X.693:8.3.4 */
641 && memb->expr_type == ASN_BASIC_INTEGER))
642 && expr_elements_count(arg, memb))) {
Lev Walkin08079b02004-08-22 03:25:24 +0000643 arg_t tmp;
644 asn1p_expr_t tmp_memb;
645 arg->embed++;
646 tmp = *arg;
647 tmp.expr = &tmp_memb;
648 tmp_memb = *memb;
Lev Walkinda9a3b82005-08-16 17:00:21 +0000649 tmp_memb.marker.flags &= ~EM_INDIRECT;
Lev Walkin08079b02004-08-22 03:25:24 +0000650 tmp_memb._anonymous_type = 1;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000651 if(tmp_memb.Identifier == 0) {
Lev Walkin21d00002005-03-04 08:48:53 +0000652 tmp_memb.Identifier = "Member";
653 if(0)
Lev Walkina9cc46e2004-09-22 16:06:28 +0000654 tmp_memb.Identifier = strdup(
655 asn1c_make_identifier(0,
Lev Walkin152a91e2005-02-14 20:41:29 +0000656 expr->Identifier, "Member", 0));
Lev Walkina9cc46e2004-09-22 16:06:28 +0000657 assert(tmp_memb.Identifier);
658 }
Lev Walkin08079b02004-08-22 03:25:24 +0000659 tmp.default_cb(&tmp);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000660 if(tmp_memb.Identifier != memb->Identifier)
Lev Walkin21d00002005-03-04 08:48:53 +0000661 if(0) free(tmp_memb.Identifier);
Lev Walkin08079b02004-08-22 03:25:24 +0000662 arg->embed--;
663 assert(arg->target->target == OT_TYPE_DECLS);
664 } else {
Lev Walkinfe7f6ec2005-03-04 22:38:22 +0000665 OUT("%s", asn1c_type_name(arg, memb,
666 (memb->marker.flags & EM_UNRECURSE)
667 ? TNF_RSAFE : TNF_CTYPE));
Lev Walkinf15320b2004-06-03 03:38:44 +0000668 }
Lev Walkinda9a3b82005-08-16 17:00:21 +0000669 /* README README (above) */
670 if(0 && (memb->marker.flags & EM_INDIRECT))
671 OUT(" *");
Lev Walkin08079b02004-08-22 03:25:24 +0000672 OUT(") list;\n");
673 INDENT(-1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000674
675 PCTX_DEF;
Lev Walkinc8285712005-03-04 22:18:20 +0000676 OUT("} %s%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000677 expr->_anonymous_type ? "" : MKID_safe(expr->Identifier),
Lev Walkin08079b02004-08-22 03:25:24 +0000678 arg->embed ? "" : "_t");
Lev Walkinf15320b2004-06-03 03:38:44 +0000679
680 /*
Lev Walkin08079b02004-08-22 03:25:24 +0000681 * SET OF/SEQUENCE OF definition
Lev Walkinf15320b2004-06-03 03:38:44 +0000682 */
Lev Walkin08079b02004-08-22 03:25:24 +0000683 return asn1c_lang_C_type_SEx_OF_def(arg,
684 (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF));
Lev Walkinf15320b2004-06-03 03:38:44 +0000685}
686
687static int
688asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
689 asn1p_expr_t *expr = arg->expr;
690 asn1p_expr_t *v;
Lev Walkin64399722004-08-11 07:17:22 +0000691 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000692 int all_tags_count;
693 enum tvm_compat tv_mode;
Lev Walkinf15320b2004-06-03 03:38:44 +0000694
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000695 /*
696 * Print out the table according to which the parsing is performed.
697 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000698 if(seq_of) {
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000699 GEN_INCLUDE("constr_SEQUENCE_OF");
Lev Walkinf15320b2004-06-03 03:38:44 +0000700 } else {
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000701 GEN_INCLUDE("constr_SET_OF");
Lev Walkinf15320b2004-06-03 03:38:44 +0000702 }
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000703 if(!arg->embed)
Lev Walkin05363a72004-09-29 13:16:40 +0000704 GEN_DECLARE(expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000705
706 REDIR(OT_STAT_DEFS);
707
708 /*
709 * Print out the table according to which the parsing is performed.
710 */
Lev Walkin21d00002005-03-04 08:48:53 +0000711 OUT("static asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
712 MKID(expr->Identifier), expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000713 INDENT(+1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000714 v = TQ_FIRST(&(expr->members));
Lev Walkina9cc46e2004-09-22 16:06:28 +0000715 if(!v->Identifier) {
Lev Walkin152a91e2005-02-14 20:41:29 +0000716 v->Identifier = strdup("Member");
Lev Walkina9cc46e2004-09-22 16:06:28 +0000717 assert(v->Identifier);
718 }
719 v->_anonymous_type = 1;
720 arg->embed++;
Lev Walkin59964be2004-08-25 02:03:12 +0000721 emit_member_table(arg, v);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000722 arg->embed--;
723 INDENT(-1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000724 OUT("};\n");
725
Lev Walkin27ea3802004-06-28 21:13:46 +0000726 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000727 * Print out asn_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +0000728 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000729 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000730
Lev Walkin21d00002005-03-04 08:48:53 +0000731 OUT("static asn_SET_OF_specifics_t asn_SPC_%s_%d_specs = {\n",
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000732 MKID(expr->Identifier), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +0000733 INDENTED(
Lev Walkin21d00002005-03-04 08:48:53 +0000734 OUT("sizeof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000735 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000736 OUT("),\n");
737 OUT("offsetof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000738 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000739 OUT(", _asn_ctx),\n");
740
Lev Walkina9cc46e2004-09-22 16:06:28 +0000741 if(expr_as_xmlvaluelist(arg, v))
742 OUT("1,\t/* XER encoding is XMLValueList */\n");
743 else
744 OUT("0,\t/* XER encoding is XMLDelimitedItemList */\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000745 );
746 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000747
748 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000749 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +0000750 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000751 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, 1,
Lev Walkin8de2ab22004-09-26 13:11:31 +0000752 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000753
Lev Walkinf15320b2004-06-03 03:38:44 +0000754 REDIR(OT_TYPE_DECLS);
755
756 return 0;
Lev Walkinb0b33412005-01-17 11:57:48 +0000757} /* _SEx_OF_def() */
Lev Walkinf15320b2004-06-03 03:38:44 +0000758
759int
760asn1c_lang_C_type_CHOICE(arg_t *arg) {
761 asn1p_expr_t *expr = arg->expr;
762 asn1p_expr_t *v;
Lev Walkin08079b02004-08-22 03:25:24 +0000763 char *id;
Lev Walkinf15320b2004-06-03 03:38:44 +0000764
765 DEPENDENCIES;
766
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000767 REDIR(OT_DEPS);
768
Lev Walkin21d00002005-03-04 08:48:53 +0000769 OUT("typedef enum ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000770 out_name_chain(arg, ONC_noflags);
Lev Walkin21d00002005-03-04 08:48:53 +0000771 OUT("_PR {\n");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000772 INDENTED(
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000773 out_name_chain(arg, ONC_noflags);
Lev Walkin801fabc2005-01-28 12:18:50 +0000774 OUT("_PR_NOTHING,\t/* No components present */\n");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000775 TQ_FOR(v, &(expr->members), next) {
776 if(v->expr_type == A1TC_EXTENSIBLE) {
777 OUT("/* Extensions may appear below */\n");
778 continue;
779 }
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000780 out_name_chain(arg, ONC_noflags);
Lev Walkin801fabc2005-01-28 12:18:50 +0000781 OUT("_PR_");
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000782 id = MKID(v->Identifier);
Lev Walkin08079b02004-08-22 03:25:24 +0000783 OUT("%s,\n", id, id);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000784 }
785 );
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000786 OUT("} "); out_name_chain(arg, ONC_noflags); OUT("_PR;\n");
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000787
788 REDIR(OT_TYPE_DECLS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000789
790 if(arg->embed) {
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000791 OUT("struct "); out_name_chain(arg, ONC_avoid_keywords); OUT(" {\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000792 } else {
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000793 OUT("typedef struct %s {\n", MKID_safe(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +0000794 }
795
796 INDENTED(
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000797 out_name_chain(arg, ONC_noflags);
Lev Walkin801fabc2005-01-28 12:18:50 +0000798 OUT("_PR present;\n");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000799 OUT("union ");
800 if(UNNAMED_UNIONS == 0) {
801 out_name_chain(arg, ONC_force_compound_name);
802 OUT("_u ");
803 }
804 OUT("{\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000805 TQ_FOR(v, &(expr->members), next) {
806 EMBED(v);
807 }
808 if(UNNAMED_UNIONS) OUT("};\n");
809 else OUT("} choice;\n");
810 );
811
812 PCTX_DEF;
Lev Walkinc8285712005-03-04 22:18:20 +0000813 OUT("} %s%s%s", (expr->marker.flags & EM_INDIRECT)?"*":"",
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000814 expr->_anonymous_type ? "" :
815 arg->embed
816 ? MKID_safe(expr->Identifier)
817 : MKID(expr->Identifier),
Lev Walkin08079b02004-08-22 03:25:24 +0000818 arg->embed ? "" : "_t");
Lev Walkinf15320b2004-06-03 03:38:44 +0000819
820 return asn1c_lang_C_type_CHOICE_def(arg);
821}
822
823static int
824asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
825 asn1p_expr_t *expr = arg->expr;
826 asn1p_expr_t *v;
827 int elements; /* Number of elements */
Lev Walkinf15320b2004-06-03 03:38:44 +0000828 tag2el_t *tag2el = NULL;
829 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000830 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000831 int all_tags_count;
832 enum tvm_compat tv_mode;
Lev Walkinf15320b2004-06-03 03:38:44 +0000833
834 /*
835 * Fetch every inner tag from the tag to elements map.
836 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000837 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000838 if(tag2el) free(tag2el);
839 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000840 }
841
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000842 GEN_INCLUDE("constr_CHOICE");
843 if(!arg->embed)
Lev Walkin05363a72004-09-29 13:16:40 +0000844 GEN_DECLARE(expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000845
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000846 REDIR(OT_STAT_DEFS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000847
848 /*
849 * Print out the table according to which the parsing is performed.
850 */
Lev Walkina9cc46e2004-09-22 16:06:28 +0000851 if(expr_elements_count(arg, expr)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000852
Lev Walkin21d00002005-03-04 08:48:53 +0000853 OUT("static asn_TYPE_member_t asn_MBR_%s_%d[] = {\n",
854 MKID(expr->Identifier), expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000855
856 elements = 0;
857 INDENTED(TQ_FOR(v, &(expr->members), next) {
Lev Walkin659c63b2005-01-17 11:40:49 +0000858 if(v->expr_type == A1TC_EXTENSIBLE)
859 continue;
Lev Walkin659c63b2005-01-17 11:40:49 +0000860 emit_member_table(arg, v);
Lev Walkinda9a3b82005-08-16 17:00:21 +0000861 elements++;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000862 });
863 OUT("};\n");
864 } else {
865 elements = 0;
866 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000867
Lev Walkin64399722004-08-11 07:17:22 +0000868
Lev Walkinf15320b2004-06-03 03:38:44 +0000869 if(arg->embed) {
870 /*
871 * Our parent structure has already taken this into account.
872 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000873 tv_mode = _TVM_SAME;
874 tags_count = all_tags_count = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000875 } else {
Lev Walkin188ed2c2004-09-13 08:31:01 +0000876 tv_mode = emit_tags_vectors(arg, expr,
877 &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000878 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000879
880 /*
881 * Tags to elements map.
882 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000883 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000884
Lev Walkin21d00002005-03-04 08:48:53 +0000885 OUT("static asn_CHOICE_specifics_t asn_SPC_%s_%d_specs = {\n",
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000886 MKID(expr->Identifier), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +0000887 INDENTED(
Lev Walkin21d00002005-03-04 08:48:53 +0000888 OUT("sizeof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000889 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000890 OUT("),\n");
891 OUT("offsetof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000892 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000893 OUT(", _asn_ctx),\n");
894 OUT("offsetof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000895 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000896 OUT(", present),\n");
897 OUT("sizeof(((struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +0000898 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +0000899 OUT(" *)0)->present),\n");
900 OUT("asn_MAP_%s_%d_tag2el,\n",
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000901 MKID(expr->Identifier), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +0000902 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
Lev Walkin35631482004-07-01 00:52:50 +0000903 OUT("%d\t/* Whether extensible */\n",
904 check_if_extensible(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +0000905 );
906 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000907
908 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000909 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +0000910 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000911 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
Lev Walkin8de2ab22004-09-26 13:11:31 +0000912 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000913
Lev Walkinf15320b2004-06-03 03:38:44 +0000914 REDIR(OT_TYPE_DECLS);
915
916 return 0;
Lev Walkinb0b33412005-01-17 11:57:48 +0000917} /* _CHOICE_def() */
Lev Walkinf15320b2004-06-03 03:38:44 +0000918
919int
920asn1c_lang_C_type_REFERENCE(arg_t *arg) {
921 asn1p_ref_t *ref;
922
923 ref = arg->expr->reference;
924 if(ref->components[ref->comp_count-1].name[0] == '&') {
Lev Walkinf15320b2004-06-03 03:38:44 +0000925 asn1p_expr_t *extract;
926 arg_t tmp;
927 int ret;
928
Lev Walkina9cc46e2004-09-22 16:06:28 +0000929 extract = asn1f_class_access_ex(arg->asn, arg->expr->module,
Lev Walkin08079b02004-08-22 03:25:24 +0000930 arg->expr, ref);
Lev Walkinf15320b2004-06-03 03:38:44 +0000931 if(extract == NULL)
932 return -1;
933
Lev Walkin08079b02004-08-22 03:25:24 +0000934 extract = asn1p_expr_clone(extract, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000935 if(extract) {
936 if(extract->Identifier)
937 free(extract->Identifier);
938 extract->Identifier = strdup(arg->expr->Identifier);
939 if(extract->Identifier == NULL) {
940 asn1p_expr_free(extract);
941 return -1;
942 }
943 } else {
944 return -1;
945 }
946
947 tmp = *arg;
948 tmp.asn = arg->asn;
Lev Walkinf15320b2004-06-03 03:38:44 +0000949 tmp.expr = extract;
950
951 ret = arg->default_cb(&tmp);
952
953 asn1p_expr_free(extract);
954
955 return ret;
956 }
957
958
959 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
960}
961
962int
963asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
964 asn1p_expr_t *expr = arg->expr;
Lev Walkin64399722004-08-11 07:17:22 +0000965 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000966 int all_tags_count;
967 enum tvm_compat tv_mode;
Lev Walkine0b56e02005-02-25 12:10:27 +0000968 enum etd_spec etd_spec;
Lev Walkinf15320b2004-06-03 03:38:44 +0000969 char *p;
970
971 if(arg->embed) {
Lev Walkin05363a72004-09-29 13:16:40 +0000972 enum tnfmt tnfmt = TNF_CTYPE;
973
974 /*
975 * If this is an optional compound type,
976 * refer it using "struct X" convention,
977 * as it may recursively include the current structure.
978 */
Lev Walkinc8285712005-03-04 22:18:20 +0000979 if(expr->marker.flags & (EM_INDIRECT | EM_UNRECURSE)) {
Lev Walkinb85a8132005-08-18 13:38:19 +0000980 if(terminal_structable(arg, expr)) {
Lev Walkinc8285712005-03-04 22:18:20 +0000981 tnfmt = TNF_RSAFE;
982 REDIR(OT_FWD_DECLS);
Lev Walkinbf56d542005-03-04 23:50:56 +0000983 OUT("%s;\n",
Lev Walkinc8285712005-03-04 22:18:20 +0000984 asn1c_type_name(arg, arg->expr, tnfmt));
Lev Walkin05363a72004-09-29 13:16:40 +0000985 }
986 }
987
Lev Walkinf15320b2004-06-03 03:38:44 +0000988 REDIR(OT_TYPE_DECLS);
989
Lev Walkinc8285712005-03-04 22:18:20 +0000990 OUT("%s", asn1c_type_name(arg, arg->expr, tnfmt));
Lev Walkine0b56e02005-02-25 12:10:27 +0000991 if(!expr->_anonymous_type) {
Lev Walkinc8285712005-03-04 22:18:20 +0000992 OUT("%s", (expr->marker.flags&EM_INDIRECT)?"\t*":"\t ");
Lev Walkincaf0d5a2005-03-04 23:48:19 +0000993 OUT("%s", MKID_safe(expr->Identifier));
Lev Walkine0b56e02005-02-25 12:10:27 +0000994 if((expr->marker.flags & EM_DEFAULT) == EM_DEFAULT)
995 OUT("\t/* DEFAULT %s */",
996 asn1f_printable_value(
997 expr->marker.default_value));
998 else if((expr->marker.flags & EM_OPTIONAL) == EM_OPTIONAL)
999 OUT("\t/* OPTIONAL */");
1000 }
1001
1002 } else {
1003 GEN_INCLUDE(asn1c_type_name(arg, expr, TNF_INCLUDE));
Lev Walkin59004fa2004-08-20 13:37:01 +00001004
1005 REDIR(OT_TYPE_DECLS);
Lev Walkine0b56e02005-02-25 12:10:27 +00001006
1007 OUT("typedef %s\t",
Lev Walkinc8285712005-03-04 22:18:20 +00001008 asn1c_type_name(arg, arg->expr, TNF_CTYPE));
Lev Walkine0b56e02005-02-25 12:10:27 +00001009 OUT("%s%s_t",
Lev Walkinc8285712005-03-04 22:18:20 +00001010 (expr->marker.flags & EM_INDIRECT)?"*":" ",
Lev Walkincaf0d5a2005-03-04 23:48:19 +00001011 MKID(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +00001012 }
1013
Lev Walkine0b56e02005-02-25 12:10:27 +00001014 if((expr->expr_type == ASN_BASIC_ENUMERATED)
Lev Walkin8ecf9db2005-03-03 21:28:12 +00001015 || (0 /* -- prohibited by X.693:8.3.4 */
1016 && expr->expr_type == ASN_BASIC_INTEGER
Lev Walkine0b56e02005-02-25 12:10:27 +00001017 && expr_elements_count(arg, expr)))
1018 etd_spec = ETD_HAS_SPECIFICS;
1019 else
1020 etd_spec = ETD_NO_SPECIFICS;
Lev Walkinf15320b2004-06-03 03:38:44 +00001021
Lev Walkin8de2ab22004-09-26 13:11:31 +00001022 /*
1023 * If this type just blindly refers the other type, alias it.
1024 * Type1 ::= Type2
1025 */
Lev Walkine0b56e02005-02-25 12:10:27 +00001026 if(arg->embed && etd_spec == ETD_NO_SPECIFICS) {
1027 REDIR(OT_TYPE_DECLS);
1028 return 0;
1029 }
Lev Walkin8de2ab22004-09-26 13:11:31 +00001030 if((!expr->constraints || (arg->flags & A1C_NO_CONSTRAINTS))
Lev Walkine0b56e02005-02-25 12:10:27 +00001031 && (arg->embed || expr->tag.tag_class == TC_NOCLASS)
Lev Walkin6938d042005-03-04 23:23:50 +00001032 && etd_spec == ETD_NO_SPECIFICS
1033 && 0 /* This shortcut is incompatible with XER */
1034 ) {
Lev Walkin8de2ab22004-09-26 13:11:31 +00001035 char *type_name;
1036 REDIR(OT_FUNC_DECLS);
1037 type_name = asn1c_type_name(arg, expr, TNF_SAFE);
1038 OUT("/* This type is equivalent to %s */\n", type_name);
Lev Walkin8de2ab22004-09-26 13:11:31 +00001039 if(HIDE_INNER_DEFS) OUT("/* ");
Lev Walkincaf0d5a2005-03-04 23:48:19 +00001040 OUT("#define\tasn_DEF_%s\t", MKID(expr->Identifier));
Lev Walkin8de2ab22004-09-26 13:11:31 +00001041 type_name = asn1c_type_name(arg, expr, TNF_SAFE);
Lev Walkine0b56e02005-02-25 12:10:27 +00001042 OUT("asn_DEF_%s", type_name);
Lev Walkin8de2ab22004-09-26 13:11:31 +00001043 if(HIDE_INNER_DEFS)
Lev Walkine0b56e02005-02-25 12:10:27 +00001044 OUT("\t// (Use -fall-defs-global to expose) */");
1045 OUT("\n");
Lev Walkin8de2ab22004-09-26 13:11:31 +00001046 REDIR(OT_CODE);
1047 OUT("/* This type is equivalent to %s */\n", type_name);
1048 OUT("\n");
1049 REDIR(OT_TYPE_DECLS);
1050 return 0;
1051 }
1052
Lev Walkinf15320b2004-06-03 03:38:44 +00001053 REDIR(OT_STAT_DEFS);
1054
Lev Walkin27ea3802004-06-28 21:13:46 +00001055 /*
Lev Walkin05363a72004-09-29 13:16:40 +00001056 * Print out asn_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +00001057 */
Lev Walkin188ed2c2004-09-13 08:31:01 +00001058 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +00001059
Lev Walkine0b56e02005-02-25 12:10:27 +00001060 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count,
1061 0, etd_spec);
Lev Walkinf15320b2004-06-03 03:38:44 +00001062
Lev Walkin59004fa2004-08-20 13:37:01 +00001063 REDIR(OT_CODE);
1064
Lev Walkinf15320b2004-06-03 03:38:44 +00001065 /*
1066 * Constraint checking.
1067 */
Lev Walkin8de2ab22004-09-26 13:11:31 +00001068 if(!(arg->flags & A1C_NO_CONSTRAINTS)) {
1069 p = MKID(expr->Identifier);
Lev Walkine0b56e02005-02-25 12:10:27 +00001070 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkin8de2ab22004-09-26 13:11:31 +00001071 OUT("int\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001072 OUT("%s", p);
1073 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1074 OUT("_constraint(asn_TYPE_descriptor_t *td, const void *sptr,\n");
Lev Walkin8de2ab22004-09-26 13:11:31 +00001075 INDENT(+1);
1076 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {");
1077 OUT("\n");
1078 if(asn1c_emit_constraint_checking_code(arg) == 1) {
1079 OUT("/* Replace with underlying type checker */\n");
1080 OUT("td->check_constraints "
Lev Walkin05363a72004-09-29 13:16:40 +00001081 "= asn_DEF_%s.check_constraints;\n",
Lev Walkin8de2ab22004-09-26 13:11:31 +00001082 asn1c_type_name(arg, expr, TNF_SAFE));
1083 OUT("return td->check_constraints"
1084 "(td, sptr, app_errlog, app_key);\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +00001085 }
Lev Walkin8de2ab22004-09-26 13:11:31 +00001086 INDENT(-1);
1087 OUT("}\n");
1088 OUT("\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001089 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001090
1091 /*
1092 * Emit suicidal functions.
1093 */
1094
Lev Walkinf15320b2004-06-03 03:38:44 +00001095 /*
1096 * This function replaces certain fields from the definition
1097 * of a type with the corresponding fields from the basic type
1098 * (from which the current type is inherited).
1099 */
Lev Walkinf15320b2004-06-03 03:38:44 +00001100 OUT("/*\n");
Lev Walkin59004fa2004-08-20 13:37:01 +00001101 OUT(" * This type is implemented using %s,\n",
1102 asn1c_type_name(arg, expr, TNF_SAFE));
Lev Walkinb65b3002004-09-23 22:20:47 +00001103 OUT(" * so here we adjust the DEF accordingly.\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001104 OUT(" */\n");
1105 OUT("static void\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001106 OUT("%s_%d_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {\n",
Lev Walkincaf0d5a2005-03-04 23:48:19 +00001107 MKID(expr->Identifier), expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +00001108 INDENT(+1);
Lev Walkine0b56e02005-02-25 12:10:27 +00001109 {
Lev Walkina9cc46e2004-09-22 16:06:28 +00001110 asn1p_expr_t *terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
Lev Walkin59004fa2004-08-20 13:37:01 +00001111 char *type_name = asn1c_type_name(arg, expr, TNF_SAFE);
Lev Walkin05363a72004-09-29 13:16:40 +00001112 OUT("td->free_struct = asn_DEF_%s.free_struct;\n", type_name);
1113 OUT("td->print_struct = asn_DEF_%s.print_struct;\n", type_name);
1114 OUT("td->ber_decoder = asn_DEF_%s.ber_decoder;\n", type_name);
1115 OUT("td->der_encoder = asn_DEF_%s.der_encoder;\n", type_name);
1116 OUT("td->xer_decoder = asn_DEF_%s.xer_decoder;\n", type_name);
1117 OUT("td->xer_encoder = asn_DEF_%s.xer_encoder;\n", type_name);
Lev Walkin906654e2004-09-10 15:49:15 +00001118 if(!terminal && !tags_count) {
Lev Walkin188ed2c2004-09-13 08:31:01 +00001119 OUT("/* The next four lines are here because of -fknown-extern-type */\n");
Lev Walkin05363a72004-09-29 13:16:40 +00001120 OUT("td->tags = asn_DEF_%s.tags;\n", type_name);
1121 OUT("td->tags_count = asn_DEF_%s.tags_count;\n", type_name);
1122 OUT("td->all_tags = asn_DEF_%s.all_tags;\n", type_name);
1123 OUT("td->all_tags_count = asn_DEF_%s.all_tags_count;\n",type_name);
Lev Walkin906654e2004-09-10 15:49:15 +00001124 OUT("/* End of these lines */\n");
1125 }
Lev Walkin05363a72004-09-29 13:16:40 +00001126 OUT("td->elements = asn_DEF_%s.elements;\n", type_name);
1127 OUT("td->elements_count = asn_DEF_%s.elements_count;\n", type_name);
Lev Walkine0b56e02005-02-25 12:10:27 +00001128 if(etd_spec != ETD_NO_SPECIFICS) {
1129 INDENT(-1);
Lev Walkin7ef83a42005-03-29 19:04:24 +00001130 OUT(" /* ");
Lev Walkin59004fa2004-08-20 13:37:01 +00001131 }
Lev Walkine0b56e02005-02-25 12:10:27 +00001132 OUT("td->specifics = asn_DEF_%s.specifics;", type_name);
1133 if(etd_spec == ETD_NO_SPECIFICS) {
1134 INDENT(-1);
1135 OUT("\n");
1136 } else {
1137 OUT("\t// Defined explicitly */\n");
1138 }
1139 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001140 OUT("}\n");
1141 OUT("\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001142
1143 p = MKID(expr->Identifier);
Lev Walkine0b56e02005-02-25 12:10:27 +00001144 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001145 OUT("void\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001146 OUT("%s", p);
1147 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1148 OUT("_free(asn_TYPE_descriptor_t *td,\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001149 INDENTED(
Lev Walkina9cc46e2004-09-22 16:06:28 +00001150 OUT("\tvoid *struct_ptr, int contents_only) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001151 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1152 p, expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +00001153 OUT("td->free_struct(td, struct_ptr, contents_only);\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001154 );
1155 OUT("}\n");
1156 OUT("\n");
1157
1158 p = MKID(expr->Identifier);
Lev Walkine0b56e02005-02-25 12:10:27 +00001159 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkinf15320b2004-06-03 03:38:44 +00001160 OUT("int\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001161 OUT("%s", p);
1162 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1163 OUT("_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001164 INDENTED(
1165 OUT("\tint ilevel, asn_app_consume_bytes_f *cb, void *app_key) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001166 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1167 p, expr->_type_unique_index);
Lev Walkinf15320b2004-06-03 03:38:44 +00001168 OUT("return td->print_struct(td, struct_ptr, ilevel, cb, app_key);\n");
1169 );
1170 OUT("}\n");
1171 OUT("\n");
1172
1173 p = MKID(expr->Identifier);
Lev Walkine0b56e02005-02-25 12:10:27 +00001174 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkindc06f6b2004-10-20 15:50:55 +00001175 OUT("asn_dec_rval_t\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001176 OUT("%s", p);
1177 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1178 OUT("_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001179 INDENTED(
Lev Walkindd1512e2005-03-17 21:56:00 +00001180 OUT("\tvoid **structure, const void *bufptr, size_t size, int tag_mode) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001181 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1182 p, expr->_type_unique_index);
Lev Walkin05363a72004-09-29 13:16:40 +00001183 OUT("return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);\n");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001184 );
1185 OUT("}\n");
1186 OUT("\n");
1187
1188 p = MKID(expr->Identifier);
Lev Walkine0b56e02005-02-25 12:10:27 +00001189 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001190 OUT("asn_enc_rval_t\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001191 OUT("%s", p);
1192 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1193 OUT("_encode_der(asn_TYPE_descriptor_t *td,\n");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001194 INDENTED(
1195 OUT("\tvoid *structure, int tag_mode, ber_tlv_tag_t tag,\n");
1196 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001197 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1198 p, expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +00001199 OUT("return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);\n");
1200 );
1201 OUT("}\n");
1202 OUT("\n");
1203
1204 p = MKID(expr->Identifier);
Lev Walkine0b56e02005-02-25 12:10:27 +00001205 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkinca47c292004-10-23 13:34:00 +00001206 OUT("asn_dec_rval_t\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001207 OUT("%s", p);
1208 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1209 OUT("_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n");
Lev Walkinca47c292004-10-23 13:34:00 +00001210 INDENTED(
Lev Walkindd1512e2005-03-17 21:56:00 +00001211 OUT("\tvoid **structure, const char *opt_mname, const void *bufptr, size_t size) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001212 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1213 p, expr->_type_unique_index);
Lev Walkinca47c292004-10-23 13:34:00 +00001214 OUT("return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size);\n");
1215 );
1216 OUT("}\n");
1217 OUT("\n");
1218
1219 p = MKID(expr->Identifier);
Lev Walkine0b56e02005-02-25 12:10:27 +00001220 if(HIDE_INNER_DEFS) OUT("static ");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001221 OUT("asn_enc_rval_t\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001222 OUT("%s", p);
1223 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1224 OUT("_encode_xer(asn_TYPE_descriptor_t *td, void *structure,\n");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001225 INDENTED(
1226 OUT("\tint ilevel, enum xer_encoder_flags_e flags,\n");
1227 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001228 OUT("%s_%d_inherit_TYPE_descriptor(td);\n",
1229 p, expr->_type_unique_index);
Lev Walkina9cc46e2004-09-22 16:06:28 +00001230 OUT("return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);\n");
Lev Walkinf15320b2004-06-03 03:38:44 +00001231 );
1232 OUT("}\n");
1233 OUT("\n");
1234
1235 REDIR(OT_FUNC_DECLS);
1236
Lev Walkincaf0d5a2005-03-04 23:48:19 +00001237 p = MKID(expr->Identifier);
Lev Walkine0b56e02005-02-25 12:10:27 +00001238 if(HIDE_INNER_DEFS) {
Lev Walkin21d00002005-03-04 08:48:53 +00001239 OUT("/* extern asn_TYPE_descriptor_t asn_DEF_%s_%d;"
1240 "\t// (Use -fall-defs-global to expose) */\n",
1241 p, expr->_type_unique_index);
Lev Walkine0b56e02005-02-25 12:10:27 +00001242 } else {
1243 OUT("extern asn_TYPE_descriptor_t asn_DEF_%s;\n", p);
1244 OUT("asn_struct_free_f %s_free;\n", p);
1245 OUT("asn_struct_print_f %s_print;\n", p);
1246 OUT("asn_constr_check_f %s_constraint;\n", p);
1247 OUT("ber_type_decoder_f %s_decode_ber;\n", p);
1248 OUT("der_type_encoder_f %s_encode_der;\n", p);
1249 OUT("xer_type_decoder_f %s_decode_xer;\n", p);
1250 OUT("xer_type_encoder_f %s_encode_xer;\n", p);
1251 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001252
Lev Walkin3dcaafa2004-08-11 05:21:32 +00001253 REDIR(OT_TYPE_DECLS);
1254
Lev Walkinf15320b2004-06-03 03:38:44 +00001255 return 0;
1256}
1257
1258int
1259asn1c_lang_C_type_EXTENSIBLE(arg_t *arg) {
1260
1261 OUT("/*\n");
1262 OUT(" * This type is extensible,\n");
1263 OUT(" * possible extensions are below.\n");
1264 OUT(" */\n");
1265
1266 return 0;
1267}
1268
Lev Walkin35631482004-07-01 00:52:50 +00001269static int check_if_extensible(asn1p_expr_t *expr) {
1270 asn1p_expr_t *v;
1271 TQ_FOR(v, &(expr->members), next) {
1272 if(v->expr_type == A1TC_EXTENSIBLE) return 1;
1273 }
1274 return 0;
1275}
1276
Lev Walkinf15320b2004-06-03 03:38:44 +00001277static int
Lev Walkinc3e29402004-09-10 06:07:18 +00001278_print_tag(arg_t *arg, struct asn1p_type_tag_s *tag) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001279
1280 OUT("(");
Lev Walkinc3e29402004-09-10 06:07:18 +00001281 switch(tag->tag_class) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001282 case TC_UNIVERSAL: OUT("ASN_TAG_CLASS_UNIVERSAL"); break;
1283 case TC_APPLICATION: OUT("ASN_TAG_CLASS_APPLICATION"); break;
1284 case TC_CONTEXT_SPECIFIC: OUT("ASN_TAG_CLASS_CONTEXT"); break;
1285 case TC_PRIVATE: OUT("ASN_TAG_CLASS_PRIVATE"); break;
1286 case TC_NOCLASS:
1287 break;
1288 }
Lev Walkin33c16ba2004-09-24 21:01:43 +00001289 OUT(" | (%" PRIdASN " << 2))", tag->tag_value);
Lev Walkinf15320b2004-06-03 03:38:44 +00001290
1291 return 0;
1292}
1293
Lev Walkinfd171ef2004-06-06 07:20:17 +00001294
1295static int
1296_tag2el_cmp(const void *ap, const void *bp) {
1297 const tag2el_t *a = ap;
1298 const tag2el_t *b = bp;
1299 const struct asn1p_type_tag_s *ta = &a->el_tag;
1300 const struct asn1p_type_tag_s *tb = &b->el_tag;
1301
1302 if(ta->tag_class == tb->tag_class) {
1303 if(ta->tag_value == tb->tag_value) {
1304 /*
1305 * Sort by their respective positions.
1306 */
1307 if(a->el_no < b->el_no)
1308 return -1;
1309 else if(a->el_no > b->el_no)
1310 return 1;
1311 return 0;
1312 } else if(ta->tag_value < tb->tag_value)
1313 return -1;
1314 else
1315 return 1;
1316 } else if(ta->tag_class < tb->tag_class) {
1317 return -1;
1318 } else {
1319 return 1;
1320 }
1321}
1322
Lev Walkinf15320b2004-06-03 03:38:44 +00001323/*
1324 * For constructed types, number of external tags may be greater than
1325 * number of elements in the type because of CHOICE type.
1326 * T ::= SET { -- Three possible tags:
1327 * a INTEGER, -- One tag is here...
1328 * b Choice1 -- ... and two more tags are there.
1329 * }
1330 * Choice1 ::= CHOICE {
1331 * s1 IA5String,
1332 * s2 ObjectDescriptor
1333 * }
1334 */
1335static int
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001336_fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001337 asn1p_expr_t *expr = arg->expr;
1338 arg_t tmparg = *arg;
1339 asn1p_expr_t *v;
1340 int element = 0;
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001341 int original_count = *count;
1342 int sort_until = -1;
Lev Walkinf15320b2004-06-03 03:38:44 +00001343
1344 TQ_FOR(v, &(expr->members), next) {
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001345 if(v->expr_type == A1TC_EXTENSIBLE) {
1346 /*
Lev Walkine0b56e02005-02-25 12:10:27 +00001347 * CXER mandates sorting
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001348 * only for the root part.
1349 */
1350 if(flags == FTE_CANONICAL_XER
1351 && sort_until == -1)
1352 sort_until = *count;
Lev Walkinf15320b2004-06-03 03:38:44 +00001353 continue;
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001354 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001355
1356 tmparg.expr = v;
1357
1358 if(_add_tag2el_member(&tmparg, tag2el, count,
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001359 (el_no==-1)?element:el_no, flags)) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001360 return -1;
1361 }
1362
1363 element++;
1364 }
1365
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001366
1367 if(flags == FTE_CANONICAL_XER) {
1368 if(sort_until == -1) sort_until = *count;
1369 qsort((*tag2el) + original_count,
1370 sort_until - original_count,
1371 sizeof(**tag2el), _tag2el_cmp);
1372 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1373 && (sort_until - original_count) >= 1) {
1374 /* Only take in account the root component */
1375 *count = original_count + 1;
1376 }
1377 } else {
1378 /*
1379 * Sort the map according to canonical order of their
1380 * tags and element numbers.
1381 */
1382 qsort(*tag2el, *count, sizeof(**tag2el), _tag2el_cmp);
1383 }
Lev Walkinfd171ef2004-06-06 07:20:17 +00001384
Lev Walkin38abe792004-06-14 13:09:45 +00001385 /*
1386 * Initialize .toff_{first|last} members.
1387 */
1388 if(*count) {
1389 struct asn1p_type_tag_s *cur_tag = 0;
1390 tag2el_t *cur = *tag2el;
1391 tag2el_t *end = cur + *count;
1392 int occur, i;
1393 for(occur = 0; cur < end; cur++) {
1394 if(cur_tag == 0
1395 || cur_tag->tag_value != cur->el_tag.tag_value
1396 || cur_tag->tag_class != cur->el_tag.tag_class) {
1397 cur_tag = &cur->el_tag;
1398 occur = 0;
1399 } else {
1400 occur++;
1401 }
1402 cur->toff_first = -occur;
1403 for(i = 0; i >= -occur; i--)
1404 cur[i].toff_last = -i;
1405 }
1406 }
1407
Lev Walkinf15320b2004-06-03 03:38:44 +00001408 return 0;
1409}
1410
1411static int
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001412_add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001413 struct asn1p_type_tag_s tag;
1414 int ret;
1415
1416 assert(el_no >= 0);
1417
Lev Walkina9cc46e2004-09-22 16:06:28 +00001418 ret = asn1f_fetch_outmost_tag(arg->asn, arg->expr->module,
1419 arg->expr, &tag, 1);
Lev Walkinf15320b2004-06-03 03:38:44 +00001420 if(ret == 0) {
Lev Walkin201943e2004-09-04 04:42:29 +00001421 tag2el_t *te;
1422 int new_count = (*count) + 1;
Lev Walkinf15320b2004-06-03 03:38:44 +00001423 void *p;
Lev Walkin201943e2004-09-04 04:42:29 +00001424
Lev Walkinac7e2292004-09-05 10:42:33 +00001425 if(tag.tag_value == -1) {
1426 /*
1427 * This is an untagged ANY type,
1428 * proceed without adding a tag
1429 */
1430 return 0;
1431 }
1432
Lev Walkin201943e2004-09-04 04:42:29 +00001433 p = realloc(*tag2el, new_count * sizeof(tag2el_t));
Lev Walkinf15320b2004-06-03 03:38:44 +00001434 if(p) *tag2el = p;
1435 else return -1;
1436
1437 DEBUG("Found tag for %s: %ld",
1438 arg->expr->Identifier,
1439 (long)tag.tag_value);
1440
Lev Walkin201943e2004-09-04 04:42:29 +00001441 te = &((*tag2el)[*count]);
1442 te->el_tag = tag;
1443 te->el_no = el_no;
1444 te->from_expr = arg->expr;
1445 *count = new_count;
Lev Walkinf15320b2004-06-03 03:38:44 +00001446 return 0;
1447 }
1448
1449 DEBUG("Searching tag in complex expression %s:%x at line %d",
1450 arg->expr->Identifier,
1451 arg->expr->expr_type,
1452 arg->expr->_lineno);
1453
1454 /*
1455 * Iterate over members of CHOICE type.
1456 */
1457 if(arg->expr->expr_type == ASN_CONSTR_CHOICE) {
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001458 return _fill_tag2el_map(arg, tag2el, count, el_no, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +00001459 }
1460
1461 if(arg->expr->expr_type == A1TC_REFERENCE) {
1462 arg_t tmp = *arg;
1463 asn1p_expr_t *expr;
Lev Walkinb85a8132005-08-18 13:38:19 +00001464 expr = asn1f_lookup_symbol_ex(tmp.asn, tmp.expr,
Lev Walkinf15320b2004-06-03 03:38:44 +00001465 arg->expr->reference);
1466 if(expr) {
1467 tmp.expr = expr;
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001468 return _add_tag2el_member(&tmp, tag2el, count, el_no, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +00001469 } else {
1470 FATAL("Cannot dereference %s at line %d",
1471 arg->expr->Identifier,
1472 arg->expr->_lineno);
1473 return -1;
1474 }
1475 }
1476
1477 DEBUG("No tag for %s at line %d",
1478 arg->expr->Identifier,
1479 arg->expr->_lineno);
1480
1481 return -1;
1482}
1483
1484static int
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001485emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier) {
Lev Walkinfd171ef2004-06-06 07:20:17 +00001486 asn1p_expr_t *expr = arg->expr;
Lev Walkinf3b29b12005-06-02 05:21:37 +00001487 int i;
1488
1489 if(!tag2el_count) return 0; /* No top level tags */
Lev Walkinfd171ef2004-06-06 07:20:17 +00001490
Lev Walkin21d00002005-03-04 08:48:53 +00001491 OUT("static asn_TYPE_tag2member_t asn_MAP_%s_%d_tag2el%s[] = {\n",
Lev Walkincaf0d5a2005-03-04 23:48:19 +00001492 MKID(expr->Identifier), expr->_type_unique_index,
Lev Walkin21d00002005-03-04 08:48:53 +00001493 opt_modifier?opt_modifier:"");
Lev Walkinf3b29b12005-06-02 05:21:37 +00001494 for(i = 0; i < tag2el_count; i++) {
1495 OUT(" { ");
1496 _print_tag(arg, &tag2el[i].el_tag);
1497 OUT(", ");
1498 OUT("%d, ", tag2el[i].el_no);
1499 OUT("%d, ", tag2el[i].toff_first);
1500 OUT("%d ", tag2el[i].toff_last);
1501 OUT("}%s /* %s at %d */\n",
1502 (i + 1 < tag2el_count) ? "," : "",
1503 tag2el[i].from_expr->Identifier,
1504 tag2el[i].from_expr->_lineno
1505 );
Lev Walkinfd171ef2004-06-06 07:20:17 +00001506 }
1507 OUT("};\n");
1508
Lev Walkinf3b29b12005-06-02 05:21:37 +00001509 return 0;
Lev Walkinfd171ef2004-06-06 07:20:17 +00001510}
1511
Lev Walkin188ed2c2004-09-13 08:31:01 +00001512static enum tvm_compat
1513emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tags_count_r, int *all_tags_count_r) {
1514 struct asn1p_type_tag_s *tags = 0; /* Effective tags */
1515 struct asn1p_type_tag_s *all_tags = 0; /* The full array */
Lev Walkin64399722004-08-11 07:17:22 +00001516 int tags_count = 0;
Lev Walkin188ed2c2004-09-13 08:31:01 +00001517 int all_tags_count = 0;
1518 enum tvm_compat tv_mode = _TVM_SAME;
Lev Walkin906654e2004-09-10 15:49:15 +00001519 int i;
Lev Walkin27ea3802004-06-28 21:13:46 +00001520
Lev Walkin6d1220a2004-09-14 14:10:10 +00001521 /* Cleanup before proceeding. */
1522 *tags_count_r = 0;
1523 *all_tags_count_r = 0;
1524
Lev Walkin906654e2004-09-10 15:49:15 +00001525 /* Fetch a chain of tags */
Lev Walkina9cc46e2004-09-22 16:06:28 +00001526 tags_count = asn1f_fetch_tags(arg->asn, expr->module, expr, &tags, 0);
Lev Walkin6d1220a2004-09-14 14:10:10 +00001527 if(tags_count < 0)
1528 return -1;
Lev Walkin64399722004-08-11 07:17:22 +00001529
Lev Walkin188ed2c2004-09-13 08:31:01 +00001530 /* Fetch a chain of tags */
Lev Walkina9cc46e2004-09-22 16:06:28 +00001531 all_tags_count = asn1f_fetch_tags(arg->asn, expr->module, expr,
Lev Walkin188ed2c2004-09-13 08:31:01 +00001532 &all_tags, AFT_FULL_COLLECT);
1533 if(all_tags_count < 0) {
1534 if(tags) free(tags);
1535 return -1;
Lev Walkin5a8219a2004-09-08 00:28:57 +00001536 }
Lev Walkin906654e2004-09-10 15:49:15 +00001537
Lev Walkin188ed2c2004-09-13 08:31:01 +00001538 assert(tags_count <= all_tags_count);
1539 assert((tags_count?0:1) == (all_tags_count?0:1));
Lev Walkin27ea3802004-06-28 21:13:46 +00001540
Lev Walkin188ed2c2004-09-13 08:31:01 +00001541 if(tags_count <= all_tags_count) {
1542 for(i = 0; i < tags_count; i++) {
1543 if(tags[i].tag_value != all_tags[i].tag_value
1544 || tags[i].tag_class != all_tags[i].tag_class) {
1545 tv_mode = _TVM_DIFFERENT;
1546 break;
1547 }
1548 }
1549 if(i == tags_count && tags_count < all_tags_count)
1550 tv_mode = _TVM_SUBSET;
1551 } else {
1552 tv_mode = _TVM_DIFFERENT;
1553 }
1554
1555#define EMIT_TAGS_TABLE(name, tags, tags_count) do { \
Lev Walkin21d00002005-03-04 08:48:53 +00001556 OUT("static ber_tlv_tag_t asn_DEF_%s_%d%s_tags[] = {\n",\
Lev Walkincaf0d5a2005-03-04 23:48:19 +00001557 MKID(expr->Identifier), \
Lev Walkin21d00002005-03-04 08:48:53 +00001558 expr->_type_unique_index, name); \
Lev Walkin188ed2c2004-09-13 08:31:01 +00001559 INDENT(+1); \
1560 /* Print the array of collected tags */ \
1561 for(i = 0; i < tags_count; i++) { \
1562 if(i) OUT(",\n"); \
1563 _print_tag(arg, &tags[i]); \
1564 } \
1565 OUT("\n"); \
1566 INDENT(-1); \
1567 OUT("};\n"); \
1568 } while(0)
1569
1570 if(tags_count) {
1571 if(tv_mode == _TVM_SUBSET)
1572 EMIT_TAGS_TABLE("", all_tags, all_tags_count);
1573 else
1574 EMIT_TAGS_TABLE("", tags, tags_count);
1575 }
1576
1577 if(all_tags_count) {
1578 if(tv_mode == _TVM_DIFFERENT)
1579 EMIT_TAGS_TABLE("_all", all_tags, all_tags_count);
1580 }
1581
1582 if(tags) free(tags);
1583 if(all_tags) free(all_tags);
1584
1585 *tags_count_r = tags_count;
1586 *all_tags_count_r = all_tags_count;
1587
1588 return tv_mode;
Lev Walkin27ea3802004-06-28 21:13:46 +00001589}
Lev Walkin59004fa2004-08-20 13:37:01 +00001590
1591static int
Lev Walkin59964be2004-08-25 02:03:12 +00001592expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin59004fa2004-08-20 13:37:01 +00001593 asn1p_expr_t *topmost_parent;
1594 asn1p_expr_t *v;
1595 int elements = 0;
1596
Lev Walkina9cc46e2004-09-22 16:06:28 +00001597 topmost_parent = asn1f_find_terminal_type_ex(arg->asn, expr);
Lev Walkin59004fa2004-08-20 13:37:01 +00001598 if(!topmost_parent) return 0;
1599
Lev Walkine0b56e02005-02-25 12:10:27 +00001600 if(!(topmost_parent->expr_type & ASN_CONSTR_MASK)
1601 && !topmost_parent->expr_type == ASN_BASIC_INTEGER
1602 && !topmost_parent->expr_type == ASN_BASIC_ENUMERATED)
Lev Walkin59004fa2004-08-20 13:37:01 +00001603 return 0;
1604
1605 TQ_FOR(v, &(topmost_parent->members), next) {
1606 if(v->expr_type != A1TC_EXTENSIBLE)
1607 elements++;
1608 }
1609
1610 return elements;
1611}
1612
1613static int
Lev Walkin59964be2004-08-25 02:03:12 +00001614emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin59004fa2004-08-20 13:37:01 +00001615 int save_target;
1616 arg_t tmp_arg;
Lev Walkinb9189732004-09-10 09:37:12 +00001617 struct asn1p_type_tag_s outmost_tag_s;
1618 struct asn1p_type_tag_s *outmost_tag;
Lev Walkine0b56e02005-02-25 12:10:27 +00001619 int complex_contents;
Lev Walkin59004fa2004-08-20 13:37:01 +00001620 char *p;
1621
Lev Walkinb9189732004-09-10 09:37:12 +00001622 if(asn1f_fetch_outmost_tag(arg->asn,
1623 expr->module, expr, &outmost_tag_s, 1)) {
1624 outmost_tag = 0;
1625 } else {
1626 outmost_tag = &outmost_tag_s;
1627 }
1628
Lev Walkin59004fa2004-08-20 13:37:01 +00001629 OUT("{ ");
Lev Walkinb9189732004-09-10 09:37:12 +00001630
1631 if(outmost_tag && outmost_tag->tag_value == -1)
1632 OUT("ATF_OPEN_TYPE | ");
Lev Walkinc8285712005-03-04 22:18:20 +00001633 OUT("%s, ",
1634 (expr->marker.flags & EM_INDIRECT)?"ATF_POINTER":"ATF_NOFLAGS");
Lev Walkinb85a8132005-08-18 13:38:19 +00001635 if((expr->marker.flags & EM_OMITABLE) == EM_OMITABLE) {
Lev Walkin59004fa2004-08-20 13:37:01 +00001636 asn1p_expr_t *tv;
1637 int opts = 0;
Lev Walkinb85a8132005-08-18 13:38:19 +00001638 for(tv = expr;
1639 tv && (tv->marker.flags & EM_OMITABLE) == EM_OMITABLE;
Lev Walkin59004fa2004-08-20 13:37:01 +00001640 tv = TQ_NEXT(tv, next), opts++) {
1641 if(tv->expr_type == A1TC_EXTENSIBLE)
1642 opts--;
1643 }
1644 OUT("%d, ", opts);
1645 } else {
1646 OUT("0, ");
1647 }
Lev Walkina9cc46e2004-09-22 16:06:28 +00001648 if(expr->_anonymous_type) {
1649 assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
1650 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
1651 OUT("0,\n");
1652 } else {
Lev Walkin21d00002005-03-04 08:48:53 +00001653 OUT("offsetof(struct ");
Lev Walkin0f5d74c2005-08-14 15:03:31 +00001654 out_name_chain(arg, ONC_avoid_keywords);
Lev Walkin21d00002005-03-04 08:48:53 +00001655 OUT(", ");
Lev Walkin59004fa2004-08-20 13:37:01 +00001656 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1657 && (!UNNAMED_UNIONS)) OUT("choice.");
Lev Walkincaf0d5a2005-03-04 23:48:19 +00001658 OUT("%s),\n", MKID_safe(expr->Identifier));
Lev Walkin59004fa2004-08-20 13:37:01 +00001659 }
1660 INDENT(+1);
1661 if(C99_MODE) OUT(".tag = ");
Lev Walkinb9189732004-09-10 09:37:12 +00001662 if(outmost_tag) {
1663 if(outmost_tag->tag_value == -1)
1664 OUT("-1 /* Ambiguous tag (ANY?) */");
1665 else
1666 _print_tag(arg, outmost_tag);
Lev Walkinc3e29402004-09-10 06:07:18 +00001667 } else {
Lev Walkinb9189732004-09-10 09:37:12 +00001668 OUT("-1 /* Ambiguous tag (CHOICE?) */");
Lev Walkinc3e29402004-09-10 06:07:18 +00001669 }
Lev Walkinb9189732004-09-10 09:37:12 +00001670
Lev Walkin59004fa2004-08-20 13:37:01 +00001671 OUT(",\n");
1672 if(C99_MODE) OUT(".tag_mode = ");
1673 if(expr->tag.tag_class) {
1674 if(expr->tag.tag_mode == TM_IMPLICIT)
1675 OUT("-1,\t/* IMPLICIT tag at current level */\n");
1676 else
1677 OUT("+1,\t/* EXPLICIT tag at current level */\n");
1678 } else {
1679 OUT("0,\n");
1680 }
Lev Walkine0b56e02005-02-25 12:10:27 +00001681
1682 complex_contents =
1683 (expr->expr_type & ASN_CONSTR_MASK)
1684 || expr->expr_type == ASN_BASIC_ENUMERATED
Lev Walkin8ecf9db2005-03-03 21:28:12 +00001685 || (0 /* -- prohibited by X.693:8.3.4 */
1686 && expr->expr_type == ASN_BASIC_INTEGER
Lev Walkine0b56e02005-02-25 12:10:27 +00001687 && expr_elements_count(arg, expr));
Lev Walkin59004fa2004-08-20 13:37:01 +00001688 if(C99_MODE) OUT(".type = ");
Lev Walkinae7bf3f2005-08-29 10:31:14 +00001689 OUT("&asn_DEF_");
Lev Walkin21d00002005-03-04 08:48:53 +00001690 if(complex_contents) {
Lev Walkincaf0d5a2005-03-04 23:48:19 +00001691 OUT("%s", MKID(expr->Identifier));
Lev Walkin21d00002005-03-04 08:48:53 +00001692 if(!(arg->flags & A1C_ALL_DEFS_GLOBAL))
1693 OUT("_%d", expr->_type_unique_index);
Lev Walkin08079b02004-08-22 03:25:24 +00001694 } else {
Lev Walkin21d00002005-03-04 08:48:53 +00001695 OUT("%s", asn1c_type_name(arg, expr, TNF_SAFE));
Lev Walkin08079b02004-08-22 03:25:24 +00001696 }
Lev Walkin21d00002005-03-04 08:48:53 +00001697 OUT(",\n");
Lev Walkin59004fa2004-08-20 13:37:01 +00001698 if(C99_MODE) OUT(".memb_constraints = ");
1699 if(expr->constraints) {
Lev Walkin8de2ab22004-09-26 13:11:31 +00001700 if(arg->flags & A1C_NO_CONSTRAINTS) {
1701 OUT("0,\t/* No check because of -fno-constraints */\n");
1702 } else {
Lev Walkincaf0d5a2005-03-04 23:48:19 +00001703 char *id = MKID(expr->Identifier);
Lev Walkin8de2ab22004-09-26 13:11:31 +00001704 if(expr->_anonymous_type
Lev Walkin152a91e2005-02-14 20:41:29 +00001705 && !strcmp(expr->Identifier, "Member"))
Lev Walkin8de2ab22004-09-26 13:11:31 +00001706 id = asn1c_type_name(arg, expr, TNF_SAFE);
1707 OUT("memb_%s_%d_constraint,\n", id,
Lev Walkin21d00002005-03-04 08:48:53 +00001708 arg->expr->_type_unique_index);
Lev Walkin8de2ab22004-09-26 13:11:31 +00001709 }
Lev Walkin59004fa2004-08-20 13:37:01 +00001710 } else {
Lev Walkinb7bfd1a2005-01-17 12:16:58 +00001711 OUT("0,\t/* Defer constraints checking to the member type */\n");
Lev Walkin59004fa2004-08-20 13:37:01 +00001712 }
1713 if(C99_MODE) OUT(".name = ");
Lev Walkin152a91e2005-02-14 20:41:29 +00001714 if(1) {
1715 if(expr->_anonymous_type && !strcmp(expr->Identifier, "Member"))
1716 OUT("\"\"\n");
1717 else
1718 OUT("\"%s\"\n", expr->Identifier);
1719 } else {
1720 OUT("\"%s\"\n", expr->_anonymous_type ? "" : expr->Identifier);
1721 }
Lev Walkin59004fa2004-08-20 13:37:01 +00001722 OUT("},\n");
1723 INDENT(-1);
1724
Lev Walkin8de2ab22004-09-26 13:11:31 +00001725 if(!expr->constraints || (arg->flags & A1C_NO_CONSTRAINTS))
Lev Walkin59004fa2004-08-20 13:37:01 +00001726 return 0;
1727
1728 save_target = arg->target->target;
1729 REDIR(OT_CODE);
1730
Lev Walkin152a91e2005-02-14 20:41:29 +00001731 if(expr->_anonymous_type && !strcmp(expr->Identifier, "Member"))
Lev Walkin59004fa2004-08-20 13:37:01 +00001732 p = asn1c_type_name(arg, expr, TNF_SAFE);
Lev Walkina9cc46e2004-09-22 16:06:28 +00001733 else
Lev Walkincaf0d5a2005-03-04 23:48:19 +00001734 p = MKID(expr->Identifier);
Lev Walkin59004fa2004-08-20 13:37:01 +00001735 OUT("static int\n");
Lev Walkin21d00002005-03-04 08:48:53 +00001736 OUT("memb_%s_%d_constraint(asn_TYPE_descriptor_t *td, const void *sptr,\n", p, arg->expr->_type_unique_index);
Lev Walkin59004fa2004-08-20 13:37:01 +00001737 INDENT(+1);
1738 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
1739 tmp_arg = *arg;
1740 tmp_arg.expr = expr;
1741 if(asn1c_emit_constraint_checking_code(&tmp_arg) == 1) {
Lev Walkin8de2ab22004-09-26 13:11:31 +00001742 OUT("return td->check_constraints"
1743 "(td, sptr, app_errlog, app_key);\n");
Lev Walkin59004fa2004-08-20 13:37:01 +00001744 }
1745 INDENT(-1);
1746 OUT("}\n");
1747 OUT("\n");
1748
1749 REDIR(save_target);
1750
1751 return 0;
1752}
Lev Walkin59964be2004-08-25 02:03:12 +00001753
Lev Walkindc06f6b2004-10-20 15:50:55 +00001754/*
1755 * Generate "asn_DEF_XXX" type definition.
1756 */
Lev Walkin59964be2004-08-25 02:03:12 +00001757static int
Lev Walkin8de2ab22004-09-26 13:11:31 +00001758emit_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 Walkin21d00002005-03-04 08:48:53 +00001759 int using_type_name = 0;
Lev Walkin59964be2004-08-25 02:03:12 +00001760 char *p;
1761
Lev Walkindd32b592004-09-06 08:07:29 +00001762 if(HIDE_INNER_DEFS)
1763 OUT("static /* Use -fall-defs-global to expose */\n");
Lev Walkincaf0d5a2005-03-04 23:48:19 +00001764 OUT("asn_TYPE_descriptor_t asn_DEF_%s", MKID(expr->Identifier));
Lev Walkin21d00002005-03-04 08:48:53 +00001765 if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index);
1766 OUT(" = {\n");
Lev Walkin801fabc2005-01-28 12:18:50 +00001767 p = MKID(expr->Identifier);
Lev Walkin188ed2c2004-09-13 08:31:01 +00001768 INDENT(+1);
Lev Walkin59964be2004-08-25 02:03:12 +00001769 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
Lev Walkindc06f6b2004-10-20 15:50:55 +00001770 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
Lev Walkin59964be2004-08-25 02:03:12 +00001771
1772 if(expr->expr_type & ASN_CONSTR_MASK) {
Lev Walkin21d00002005-03-04 08:48:53 +00001773 using_type_name = 1;
Lev Walkin59964be2004-08-25 02:03:12 +00001774 p = asn1c_type_name(arg, arg->expr, TNF_SAFE);
1775 }
1776
Lev Walkin21d00002005-03-04 08:48:53 +00001777#define FUNCREF(foo) do { \
1778 OUT("%s", p); \
1779 if(HIDE_INNER_DEFS && !using_type_name) \
1780 OUT("_%d", expr->_type_unique_index); \
1781 OUT("_" #foo ",\n"); \
1782} while(0)
1783
1784 FUNCREF(free);
1785 FUNCREF(print);
1786 FUNCREF(constraint);
1787 FUNCREF(decode_ber);
1788 FUNCREF(encode_der);
1789 FUNCREF(decode_xer);
1790 FUNCREF(encode_xer);
Lev Walkin59964be2004-08-25 02:03:12 +00001791
Lev Walkin59964be2004-08-25 02:03:12 +00001792 if(expr->expr_type == ASN_CONSTR_CHOICE) {
1793 OUT("CHOICE_outmost_tag,\n");
1794 } else {
1795 OUT("0,\t/* Use generic outmost tag fetcher */\n");
1796 }
1797
Lev Walkincaf0d5a2005-03-04 23:48:19 +00001798 p = MKID(expr->Identifier);
Lev Walkin59964be2004-08-25 02:03:12 +00001799 if(tags_count) {
Lev Walkin21d00002005-03-04 08:48:53 +00001800 OUT("asn_DEF_%s_%d_tags,\n",
1801 p, expr->_type_unique_index);
1802 OUT("sizeof(asn_DEF_%s_%d_tags)\n",
1803 p, expr->_type_unique_index);
1804 OUT("\t/sizeof(asn_DEF_%s_%d_tags[0])",
1805 p, expr->_type_unique_index);
Lev Walkin188ed2c2004-09-13 08:31:01 +00001806 if(tv_mode == _TVM_SUBSET
1807 && tags_count != all_tags_count)
1808 OUT(" - %d", all_tags_count - tags_count);
1809 OUT(", /* %d */\n", tags_count);
Lev Walkin59964be2004-08-25 02:03:12 +00001810 } else {
Lev Walkin188ed2c2004-09-13 08:31:01 +00001811 OUT("0,\t/* No effective tags (pointer) */\n");
1812 OUT("0,\t/* No effective tags (count) */\n");
1813 }
1814
1815 if(all_tags_count && tv_mode == _TVM_DIFFERENT) {
Lev Walkin21d00002005-03-04 08:48:53 +00001816 OUT("asn_DEF_%s_%d_all_tags,\n",
1817 p, expr->_type_unique_index);
1818 OUT("sizeof(asn_DEF_%s_%d_all_tags)\n",
1819 p, expr->_type_unique_index);
1820 OUT("\t/sizeof(asn_DEF_%s_%d_all_tags[0]), /* %d */\n",
1821 p, expr->_type_unique_index, all_tags_count);
Lev Walkin188ed2c2004-09-13 08:31:01 +00001822 } else if(all_tags_count) {
Lev Walkin21d00002005-03-04 08:48:53 +00001823 OUT("asn_DEF_%s_%d_tags,\t/* Same as above */\n",
1824 p, expr->_type_unique_index);
1825 OUT("sizeof(asn_DEF_%s_%d_tags)\n",
1826 p, expr->_type_unique_index);
1827 OUT("\t/sizeof(asn_DEF_%s_%d_tags[0]), /* %d */\n",
1828 p, expr->_type_unique_index, all_tags_count);
Lev Walkin188ed2c2004-09-13 08:31:01 +00001829 } else {
1830 OUT("0,\t/* No tags (pointer) */\n");
1831 OUT("0,\t/* No tags (count) */\n");
Lev Walkin59964be2004-08-25 02:03:12 +00001832 }
1833
Lev Walkin59964be2004-08-25 02:03:12 +00001834 if(elements_count) {
Lev Walkin21d00002005-03-04 08:48:53 +00001835 OUT("asn_MBR_%s_%d,\n", p, expr->_type_unique_index);
Lev Walkin59964be2004-08-25 02:03:12 +00001836 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF
1837 || expr->expr_type == ASN_CONSTR_SET_OF) {
1838 OUT("%d,\t/* Single element */\n",
1839 elements_count);
1840 assert(elements_count == 1);
1841 } else {
1842 OUT("%d,\t/* Elements count */\n",
1843 elements_count);
1844 }
1845 } else {
Lev Walkin59964be2004-08-25 02:03:12 +00001846 if(expr_elements_count(arg, expr))
1847 OUT("0, 0,\t/* Defined elsewhere */\n");
1848 else
1849 OUT("0, 0,\t/* No members */\n");
1850 }
1851
1852 switch(spec) {
1853 case ETD_NO_SPECIFICS:
1854 OUT("0\t/* No specifics */\n");
1855 break;
1856 case ETD_HAS_SPECIFICS:
Lev Walkin21d00002005-03-04 08:48:53 +00001857 OUT("&asn_SPC_%s_%d_specs\t/* Additional specs */\n",
1858 p, expr->_type_unique_index);
Lev Walkin59964be2004-08-25 02:03:12 +00001859 }
Lev Walkin188ed2c2004-09-13 08:31:01 +00001860 INDENT(-1);
Lev Walkin59964be2004-08-25 02:03:12 +00001861 OUT("};\n");
1862 OUT("\n");
Lev Walkin97298782004-08-26 06:20:34 +00001863
1864 return 0;
Lev Walkin59964be2004-08-25 02:03:12 +00001865}
Lev Walkincc93b0f2004-09-10 09:18:20 +00001866
Lev Walkina9cc46e2004-09-22 16:06:28 +00001867static int
1868expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr) {
1869 expr = asn1f_find_terminal_type_ex(arg->asn, expr);
1870 if(!expr) return 0;
1871
1872 /* X.680, 25.5, Table 5 */
1873 switch(expr->expr_type) {
Lev Walkina9cc46e2004-09-22 16:06:28 +00001874 case ASN_BASIC_BOOLEAN:
1875 case ASN_BASIC_ENUMERATED:
1876 case ASN_BASIC_NULL:
1877 return 1;
1878 default:
1879 return 0;
1880 }
1881}
Lev Walkin801fabc2005-01-28 12:18:50 +00001882
1883static int
Lev Walkin0f5d74c2005-08-14 15:03:31 +00001884out_name_chain(arg_t *arg, enum onc_flags onc_flags) {
Lev Walkin801fabc2005-01-28 12:18:50 +00001885 asn1p_expr_t *expr = arg->expr;
1886 char *id;
1887
1888 assert(expr->Identifier);
1889
Lev Walkin0f5d74c2005-08-14 15:03:31 +00001890 if((arg->flags & A1C_COMPOUND_NAMES
1891 || onc_flags & ONC_force_compound_name)
Lev Walkin21d00002005-03-04 08:48:53 +00001892 && ((expr->expr_type & ASN_CONSTR_MASK)
1893 || expr->expr_type == ASN_BASIC_ENUMERATED
Lev Walkinb02a8832005-08-13 23:51:47 +00001894 || ((expr->expr_type == ASN_BASIC_INTEGER
1895 || expr->expr_type == ASN_BASIC_BIT_STRING)
Lev Walkin21d00002005-03-04 08:48:53 +00001896 && expr_elements_count(arg, expr))
1897 )
Lev Walkin801fabc2005-01-28 12:18:50 +00001898 && expr->parent_expr
1899 && expr->parent_expr->Identifier) {
1900 arg_t tmparg = *arg;
1901
1902 tmparg.expr = expr->parent_expr;
Lev Walkin21d00002005-03-04 08:48:53 +00001903 if(0) tmparg.flags &= ~A1C_COMPOUND_NAMES;
1904
Lev Walkin0f5d74c2005-08-14 15:03:31 +00001905 out_name_chain(&tmparg, onc_flags);
Lev Walkin801fabc2005-01-28 12:18:50 +00001906
Lev Walkin01633092005-03-05 00:08:41 +00001907 OUT("__"); /* a separator between id components */
Lev Walkin21d00002005-03-04 08:48:53 +00001908
Lev Walkin801fabc2005-01-28 12:18:50 +00001909 /* Fall through */
1910 }
1911
Lev Walkin0f5d74c2005-08-14 15:03:31 +00001912 if(onc_flags & ONC_avoid_keywords)
Lev Walkincaf0d5a2005-03-04 23:48:19 +00001913 id = MKID_safe(expr->Identifier);
Lev Walkin801fabc2005-01-28 12:18:50 +00001914 else
Lev Walkincaf0d5a2005-03-04 23:48:19 +00001915 id = MKID(expr->Identifier);
Lev Walkin801fabc2005-01-28 12:18:50 +00001916 OUT("%s", id);
1917
1918 return 0;
1919}
Lev Walkinb85a8132005-08-18 13:38:19 +00001920
1921static int
1922emit_include_dependencies(arg_t *arg) {
1923 asn1p_expr_t *expr = arg->expr;
1924 asn1p_expr_t *memb;
1925
1926 /* Avoid recursive definitions. */
1927 TQ_FOR(memb, &(expr->members), next) {
1928 expr_break_recursion(arg, memb);
1929 }
1930
1931 TQ_FOR(memb, &(expr->members), next) {
1932
1933 if(memb->marker.flags & (EM_INDIRECT | EM_UNRECURSE)) {
1934 if(terminal_structable(arg, memb)) {
1935 int saved_target = arg->target->target;
1936 REDIR(OT_FWD_DECLS);
1937 OUT("%s;\n",
1938 asn1c_type_name(arg, memb, TNF_RSAFE));
1939 REDIR(saved_target);
1940 }
1941 }
1942
1943 if((!(memb->expr_type & ASN_CONSTR_MASK)
1944 && memb->expr_type > ASN_CONSTR_MASK)
1945 || memb->meta_type == AMT_TYPEREF) {
1946 if(memb->marker.flags & EM_UNRECURSE) {
1947 GEN_POSTINCLUDE(asn1c_type_name(arg,
1948 memb, TNF_INCLUDE));
1949 } else {
1950 GEN_INCLUDE(asn1c_type_name(arg,
1951 memb, TNF_INCLUDE));
1952 }
1953 }
1954 }
1955
1956 return 0;
1957}
1958
1959/*
1960 * Check if it is better to make this type indirectly accessed via
1961 * a pointer.
1962 * This may be the case for the following recursive definition:
1963 * Type ::= CHOICE { member Type };
1964 */
1965static int
1966expr_break_recursion(arg_t *arg, asn1p_expr_t *expr) {
1967 asn1p_expr_t *terminal;
1968 int ret;
1969
1970 if(expr->marker.flags & EM_UNRECURSE)
1971 return 1; /* Already broken */
1972
1973 terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
1974
1975 /* -findirect-choice compiles members of CHOICE as indirect pointers */
1976 if((arg->flags & A1C_INDIRECT_CHOICE)
1977 && arg->expr->expr_type == ASN_CONSTR_CHOICE
1978 && terminal
1979 && (terminal->expr_type & ASN_CONSTR_MASK)
1980 ) {
1981 /* Break cross-reference */
1982 expr->marker.flags |= EM_INDIRECT | EM_UNRECURSE;
1983 return 1;
1984 }
1985
1986 if((expr->marker.flags & EM_INDIRECT)
1987 || arg->expr->expr_type == ASN_CONSTR_SET_OF
1988 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF) {
1989 if(terminal_structable(arg, expr)) {
1990 expr->marker.flags |= EM_UNRECURSE;
1991
1992 if(arg->expr->expr_type == ASN_CONSTR_SET_OF
1993 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF) {
1994 /* Don't put EM_INDIRECT even if recursion */
1995 return 1;
1996 }
1997
1998 /* Fall through */
1999 }
2000 }
2001
2002 /* Look for recursive back-references */
2003 ret = expr_defined_recursively(arg, expr);
2004 switch(ret) {
2005 case 2: /* Explicitly break the recursion */
2006 case 1: /* Use safer typing */
2007 expr->marker.flags |= EM_INDIRECT;
2008 expr->marker.flags |= EM_UNRECURSE;
2009 break;
2010 }
2011
2012 return 0;
2013}
2014
2015/*
2016 * Check if the type can be represented using simple `struct TYPE`.
2017 */
2018static asn1p_expr_t *
2019terminal_structable(arg_t *arg, asn1p_expr_t *expr) {
2020 asn1p_expr_t *terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
2021 if(terminal
2022 && !terminal->parent_expr
2023 && (terminal->expr_type & ASN_CONSTR_MASK)) {
2024 return terminal;
2025 }
2026 return 0;
2027}
2028
2029static int
2030asn1c_recurse(arg_t *arg, asn1p_expr_t *expr, int (*callback)(arg_t *arg, void *key), void *key) {
2031 arg_t tmp = *arg;
2032 int maxret = 0;
2033 int ret;
2034
2035 if(expr->_mark) return 0;
2036 expr->_mark |= TM_RECURSION;
2037
2038 /* Invoke callback for every type going into recursion */
2039 tmp.expr = expr;
2040 maxret = callback(&tmp, key);
2041 if(maxret <= 1) {
2042 /*
2043 * Recursively invoke myself and the callbacks.
2044 */
2045 TQ_FOR(tmp.expr, &(expr->members), next) {
2046 ret = asn1c_recurse(&tmp, tmp.expr, callback, key);
2047 if(ret > maxret)
2048 maxret = ret;
2049 if(maxret > 1) break;
2050 }
2051 }
2052
2053 expr->_mark &= ~TM_RECURSION;
2054 return maxret;
2055}
2056
2057static int
2058check_is_refer_to(arg_t *arg, void *key) {
2059 asn1p_expr_t *terminal = terminal_structable(arg, arg->expr);
2060 if(terminal == key) {
2061 if(arg->expr->marker.flags & EM_INDIRECT)
2062 return 1; /* This is almost safe indirection */
2063 return 2;
2064 } else if(terminal) {
2065 /* This might be N-step circular loop. Dive into it. */
2066 return asn1c_recurse(arg, terminal, check_is_refer_to, key);
2067 }
2068 return 0;
2069}
2070
2071/*
2072 * Check if the possibly inner expression defined recursively.
2073 */
2074static int
2075expr_defined_recursively(arg_t *arg, asn1p_expr_t *expr) {
2076 asn1p_expr_t *terminal;
2077 asn1p_expr_t *topmost;
2078
2079 /* If expression is top-level, there's no way it can be recursive. */
2080 if(expr->parent_expr == 0) return 0;
2081 if(expr->expr_type != A1TC_REFERENCE)
2082 return 0; /* Basic types are never recursive */
2083
2084 terminal = terminal_structable(arg, expr);
2085 if(!terminal) return 0; /* Terminal cannot be indirected */
2086
2087 /* Search for the parent container for the given expression */
2088 topmost = expr;
2089 while(topmost->parent_expr)
2090 topmost = topmost->parent_expr;
2091
2092 /* Look inside the terminal type if it mentions the parent expression */
2093 return asn1c_recurse(arg, terminal, check_is_refer_to, topmost);
2094}