blob: c91a50ba41ac63a5fdbc03fa1124e4dc068f13a0 [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 Walkinf15320b2004-06-03 03:38:44 +000027static int asn1c_lang_C_type_SEQUENCE_def(arg_t *arg);
28static int asn1c_lang_C_type_SET_def(arg_t *arg);
29static int asn1c_lang_C_type_CHOICE_def(arg_t *arg);
30static int asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of);
Lev Walkinc3e29402004-09-10 06:07:18 +000031static int _print_tag(arg_t *arg, struct asn1p_type_tag_s *tag_p);
Lev Walkin35631482004-07-01 00:52:50 +000032static int check_if_extensible(asn1p_expr_t *expr);
Lev Walkincc93b0f2004-09-10 09:18:20 +000033static int expr_better_indirect(arg_t *arg, asn1p_expr_t *expr);
Lev Walkina9cc46e2004-09-22 16:06:28 +000034static int expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr);
Lev Walkin59964be2004-08-25 02:03:12 +000035static int expr_elements_count(arg_t *arg, asn1p_expr_t *expr);
36static int emit_member_table(arg_t *arg, asn1p_expr_t *expr);
Lev Walkin33d5d3c2004-10-03 09:13:30 +000037static int emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier);
Lev Walkinf15320b2004-06-03 03:38:44 +000038
Lev Walkin188ed2c2004-09-13 08:31:01 +000039enum tvm_compat {
40 _TVM_SAME = 0, /* tags and all_tags are same */
41 _TVM_SUBSET = 1, /* tags are subset of all_tags */
42 _TVM_DIFFERENT = 2, /* tags and all_tags are different */
43};
44static enum tvm_compat emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tc, int *atc);
45
Lev Walkin59964be2004-08-25 02:03:12 +000046enum etd_spec {
47 ETD_NO_SPECIFICS,
48 ETD_HAS_SPECIFICS
49};
Lev Walkin8de2ab22004-09-26 13:11:31 +000050static 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 +000051
Lev Walkin59004fa2004-08-20 13:37:01 +000052#define C99_MODE (!(arg->flags & A1C_NO_C99))
Lev Walkinf15320b2004-06-03 03:38:44 +000053#define UNNAMED_UNIONS (arg->flags & A1C_UNNAMED_UNIONS)
Lev Walkindd32b592004-09-06 08:07:29 +000054#define HIDE_INNER_DEFS (arg->embed && !(arg->flags & A1C_ALL_DEFS_GLOBAL))
Lev Walkinf15320b2004-06-03 03:38:44 +000055
56#define PCTX_DEF INDENTED( \
57 OUT("\n"); \
58 OUT("/* Context for parsing across buffer boundaries */\n"); \
Lev Walkin05363a72004-09-29 13:16:40 +000059 OUT("asn_struct_ctx_t _asn_ctx;\n"));
Lev Walkinf15320b2004-06-03 03:38:44 +000060
Lev Walkin3dcaafa2004-08-11 05:21:32 +000061#define DEPENDENCIES do { \
Lev Walkin08079b02004-08-22 03:25:24 +000062 asn1p_expr_t *__m; \
63 TQ_FOR(__m, &(expr->members), next) { \
64 if((!(__m->expr_type & ASN_CONSTR_MASK) \
65 && __m->expr_type > ASN_CONSTR_MASK) \
66 || __m->meta_type == AMT_TYPEREF) { \
67 GEN_INCLUDE(asn1c_type_name(arg, \
68 __m, TNF_INCLUDE)); \
Lev Walkin3dcaafa2004-08-11 05:21:32 +000069 } \
70 } \
71 if(expr->expr_type == ASN_CONSTR_SET_OF) \
72 GEN_INCLUDE("asn_SET_OF"); \
73 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF) \
74 GEN_INCLUDE("asn_SEQUENCE_OF"); \
75} while(0)
Lev Walkinf15320b2004-06-03 03:38:44 +000076
77#define MKID(id) asn1c_make_identifier(0, (id), 0)
78
79int
Lev Walkinc78cbfb2004-09-14 12:47:45 +000080asn1c_lang_C_type_REAL(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +000081 REDIR(OT_DEPS);
Lev Walkinf15320b2004-06-03 03:38:44 +000082 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
83}
84
Lev Walkinf15320b2004-06-03 03:38:44 +000085int
Lev Walkinc78cbfb2004-09-14 12:47:45 +000086asn1c_lang_C_type_common_INTEGER(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +000087 asn1p_expr_t *expr = arg->expr;
88 asn1p_expr_t *v;
89
90 REDIR(OT_DEPS);
91
Lev Walkinc78cbfb2004-09-14 12:47:45 +000092 if(expr->expr_type == ASN_BASIC_ENUMERATED
93 || TQ_FIRST(&(expr->members))
94 ) {
Lev Walkinf15320b2004-06-03 03:38:44 +000095 OUT("typedef enum %s {\n", MKID(expr->Identifier));
96 TQ_FOR(v, &(expr->members), next) {
97 switch(v->expr_type) {
98 case A1TC_UNIVERVAL:
Lev Walkin33c16ba2004-09-24 21:01:43 +000099 OUT("\t%s\t= %" PRIdASN ",\n",
Lev Walkinf15320b2004-06-03 03:38:44 +0000100 asn1c_make_identifier(0,
101 expr->Identifier,
102 v->Identifier, 0),
103 v->value->value.v_integer);
104 break;
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000105 case A1TC_EXTENSIBLE:
106 OUT("\t/*\n");
107 OUT("\t * Enumeration is extensible\n");
108 OUT("\t */\n");
109 break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000110 default:
111 return -1;
112 }
113 }
114 OUT("} %s_e;\n", MKID(expr->Identifier));
115 }
116
117 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
118}
119
120int
121asn1c_lang_C_type_SEQUENCE(arg_t *arg) {
122 asn1p_expr_t *expr = arg->expr;
123 asn1p_expr_t *v;
124 int comp_mode = 0; /* {root,ext=1,root,root,...} */
125
126 DEPENDENCIES;
127
128 if(arg->embed) {
Lev Walkin08079b02004-08-22 03:25:24 +0000129 OUT("struct %s {\n", MKID(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +0000130 } else {
131 OUT("typedef struct %s {\n",
132 MKID(expr->Identifier));
133 }
134
135 TQ_FOR(v, &(expr->members), next) {
136 if(v->expr_type == A1TC_EXTENSIBLE) {
137 if(comp_mode < 3) comp_mode++;
138 }
Lev Walkincc93b0f2004-09-10 09:18:20 +0000139 if(comp_mode == 1
140 || expr_better_indirect(arg, v))
Lev Walkin0204fa62004-09-15 11:54:38 +0000141 v->marker.flags |= EM_INDIRECT;
Lev Walkinf15320b2004-06-03 03:38:44 +0000142 EMBED(v);
143 }
144
145 PCTX_DEF;
Lev Walkin0204fa62004-09-15 11:54:38 +0000146 OUT("} %s%s%s", expr->marker.flags?"*":"",
Lev Walkin08079b02004-08-22 03:25:24 +0000147 expr->_anonymous_type ? "" : MKID(expr->Identifier),
148 arg->embed ? "" : "_t");
Lev Walkinf15320b2004-06-03 03:38:44 +0000149
150 return asn1c_lang_C_type_SEQUENCE_def(arg);
151}
152
153static int
154asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
155 asn1p_expr_t *expr = arg->expr;
156 asn1p_expr_t *v;
157 int elements; /* Number of elements */
Lev Walkinf15320b2004-06-03 03:38:44 +0000158 int ext_start = -1;
159 int ext_stop = -1;
Lev Walkinfd171ef2004-06-06 07:20:17 +0000160 tag2el_t *tag2el = NULL;
161 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000162 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000163 int all_tags_count;
164 enum tvm_compat tv_mode;
Lev Walkinf15320b2004-06-03 03:38:44 +0000165 char *p;
166
Lev Walkinfd171ef2004-06-06 07:20:17 +0000167 /*
168 * Fetch every inner tag from the tag to elements map.
169 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000170 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
Lev Walkinfd171ef2004-06-06 07:20:17 +0000171 if(tag2el) free(tag2el);
172 return -1;
173 }
174
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000175 GEN_INCLUDE("constr_SEQUENCE");
176 if(!arg->embed)
Lev Walkin05363a72004-09-29 13:16:40 +0000177 GEN_DECLARE(expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000178
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000179 REDIR(OT_STAT_DEFS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000180
181 /*
182 * Print out the table according to which the parsing is performed.
183 */
Lev Walkina9cc46e2004-09-22 16:06:28 +0000184 if(expr_elements_count(arg, expr)) {
185 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Lev Walkinf15320b2004-06-03 03:38:44 +0000186
Lev Walkina9cc46e2004-09-22 16:06:28 +0000187 p = MKID(expr->Identifier);
Lev Walkin05363a72004-09-29 13:16:40 +0000188 OUT("static asn_TYPE_member_t asn_MBR_%s[] = {\n", p);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000189
190 elements = 0;
191 INDENTED(TQ_FOR(v, &(expr->members), next) {
192 if(v->expr_type == A1TC_EXTENSIBLE) {
193 if((++comp_mode) == 1)
194 ext_start = elements - 1;
195 else
196 ext_stop = elements - 1;
197 continue;
198 }
199 elements++;
200 emit_member_table(arg, v);
201 });
202 OUT("};\n");
203 } else {
204 elements = 0;
205 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000206
Lev Walkin27ea3802004-06-28 21:13:46 +0000207 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000208 * Print out asn_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +0000209 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000210 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000211
Lev Walkinfd171ef2004-06-06 07:20:17 +0000212 /*
213 * Tags to elements map.
214 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000215 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
Lev Walkinfd171ef2004-06-06 07:20:17 +0000216
Lev Walkin27ea3802004-06-28 21:13:46 +0000217 p = MKID(expr->Identifier);
Lev Walkin05363a72004-09-29 13:16:40 +0000218 OUT("static asn_SEQUENCE_specifics_t asn_DEF_%s_specs = {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000219 INDENTED(
220 OUT("sizeof(struct %s),\n", p);
Lev Walkin05363a72004-09-29 13:16:40 +0000221 OUT("offsetof(struct %s, _asn_ctx),\n", p);
222 OUT("asn_DEF_%s_tag2el,\n", p);
Lev Walkinfd171ef2004-06-06 07:20:17 +0000223 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000224 OUT("%d,\t/* Start extensions */\n",
225 ext_start);
226 OUT("%d\t/* Stop extensions */\n",
227 (ext_stop<ext_start)?elements+1:ext_stop, ext_stop);
228 );
229 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000230
231 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000232 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +0000233 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000234 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
Lev Walkin8de2ab22004-09-26 13:11:31 +0000235 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000236
Lev Walkinf15320b2004-06-03 03:38:44 +0000237 REDIR(OT_TYPE_DECLS);
238
239 return 0;
240}
241
242int
Lev Walkinf15320b2004-06-03 03:38:44 +0000243asn1c_lang_C_type_SET(arg_t *arg) {
244 asn1p_expr_t *expr = arg->expr;
245 asn1p_expr_t *v;
246 long mcount;
247 char *id;
248 int comp_mode = 0; /* {root,ext=1,root,root,...} */
249
250 DEPENDENCIES;
251
252 REDIR(OT_DEPS);
253
254 OUT("\n");
255 OUT("/*\n");
256 OUT(" * Method of determining the components presence\n");
257 OUT(" */\n");
258 mcount = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000259 OUT("typedef enum %s_PR {\n", MKID(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +0000260 TQ_FOR(v, &(expr->members), next) {
261 if(v->expr_type == A1TC_EXTENSIBLE) continue;
262 INDENTED(
263 id = MKID(expr->Identifier);
264 OUT("%s_PR_", id);
265 id = MKID(v->Identifier);
266 OUT("%s,\t/* Member %s is present */\n",
267 id, id)
268 );
269 mcount++;
270 }
Lev Walkin64399722004-08-11 07:17:22 +0000271 id = MKID(expr->Identifier);
272 OUT("} %s_PR;\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000273
274 REDIR(OT_TYPE_DECLS);
275
276 if(arg->embed) {
Lev Walkin64399722004-08-11 07:17:22 +0000277 OUT("struct %s {\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000278 } else {
Lev Walkin64399722004-08-11 07:17:22 +0000279 OUT("typedef struct %s {\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000280 }
281
282 TQ_FOR(v, &(expr->members), next) {
283 if(v->expr_type == A1TC_EXTENSIBLE) {
284 if(comp_mode < 3) comp_mode++;
285 }
Lev Walkincc93b0f2004-09-10 09:18:20 +0000286 if(comp_mode == 1
287 || expr_better_indirect(arg, v))
Lev Walkin0204fa62004-09-15 11:54:38 +0000288 v->marker.flags |= EM_INDIRECT;
Lev Walkinf15320b2004-06-03 03:38:44 +0000289 EMBED(v);
290 }
291
292 INDENTED(
293 id = MKID(expr->Identifier);
294 OUT("\n");
295 OUT("/* Presence bitmask: ASN_SET_ISPRESENT(p%s, %s_PR_x) */\n",
296 id, id);
297 OUT("unsigned int _presence_map\n");
298 OUT("\t[((%ld+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))];\n", mcount);
299 );
300
301 PCTX_DEF;
Lev Walkin0204fa62004-09-15 11:54:38 +0000302 OUT("} %s%s%s", expr->marker.flags?"*":"",
Lev Walkin08079b02004-08-22 03:25:24 +0000303 expr->_anonymous_type ? "" : MKID(expr->Identifier),
304 arg->embed ? "" : "_t");
Lev Walkinf15320b2004-06-03 03:38:44 +0000305
306 return asn1c_lang_C_type_SET_def(arg);
307}
308
Lev Walkinf15320b2004-06-03 03:38:44 +0000309static int
310asn1c_lang_C_type_SET_def(arg_t *arg) {
311 asn1p_expr_t *expr = arg->expr;
312 asn1p_expr_t *v;
313 int elements;
Lev Walkinf15320b2004-06-03 03:38:44 +0000314 tag2el_t *tag2el = NULL;
315 int tag2el_count = 0;
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000316 tag2el_t *tag2el_cxer = NULL;
317 int tag2el_cxer_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000318 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000319 int all_tags_count;
320 enum tvm_compat tv_mode;
Lev Walkinf15320b2004-06-03 03:38:44 +0000321 char *p;
322
323 /*
324 * Fetch every inner tag from the tag to elements map.
325 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000326 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000327 if(tag2el) free(tag2el);
328 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000329 }
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000330 if(_fill_tag2el_map(arg, &tag2el_cxer, &tag2el_cxer_count, -1, FTE_CANONICAL_XER)) {
331 if(tag2el) free(tag2el);
332 if(tag2el_cxer) free(tag2el_cxer);
333 return -1;
334 }
335 if(tag2el_cxer_count == tag2el_count
336 && memcmp(tag2el, tag2el_cxer, tag2el_count) == 0) {
337 free(tag2el_cxer);
338 tag2el_cxer = 0;
339 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000340
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000341 GEN_INCLUDE("constr_SET");
342 if(!arg->embed)
Lev Walkin05363a72004-09-29 13:16:40 +0000343 GEN_DECLARE(expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000344
345 REDIR(OT_STAT_DEFS);
346
Lev Walkinf15320b2004-06-03 03:38:44 +0000347 /*
348 * Print out the table according to which the parsing is performed.
349 */
Lev Walkina9cc46e2004-09-22 16:06:28 +0000350 if(expr_elements_count(arg, expr)) {
351 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Lev Walkinf15320b2004-06-03 03:38:44 +0000352
Lev Walkina9cc46e2004-09-22 16:06:28 +0000353 p = MKID(expr->Identifier);
Lev Walkin05363a72004-09-29 13:16:40 +0000354 OUT("static asn_TYPE_member_t asn_MBR_%s[] = {\n", p);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000355
356 elements = 0;
357 INDENTED(TQ_FOR(v, &(expr->members), next) {
358 if(v->expr_type == A1TC_EXTENSIBLE) {
359 if(comp_mode < 3) comp_mode++;
360 } else {
361 if(comp_mode == 1
362 || expr_better_indirect(arg, v))
363 v->marker.flags |= EM_INDIRECT;
364 elements++;
365 emit_member_table(arg, v);
366 }
367 });
368 OUT("};\n");
369 } else {
370 elements = 0;
371 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000372
Lev Walkin27ea3802004-06-28 21:13:46 +0000373 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000374 * Print out asn_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +0000375 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000376 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000377
378 /*
379 * Tags to elements map.
380 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000381 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
382 if(tag2el_cxer)
383 emit_tag2member_map(arg, tag2el_cxer, tag2el_cxer_count, "_cxer");
Lev Walkinf15320b2004-06-03 03:38:44 +0000384
385 /*
386 * Emit a map of mandatory elements.
387 */
Lev Walkin27ea3802004-06-28 21:13:46 +0000388 p = MKID(expr->Identifier);
Lev Walkin05363a72004-09-29 13:16:40 +0000389 OUT("static uint8_t asn_DEF_%s_mmap", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000390 OUT("[(%d + (8 * sizeof(unsigned int)) - 1) / 8]", elements);
391 OUT(" = {\n", p);
392 INDENTED(
393 if(elements) {
394 int delimit = 0;
395 int el = 0;
396 TQ_FOR(v, &(expr->members), next) {
397 if(v->expr_type == A1TC_EXTENSIBLE) continue;
398 if(delimit) {
399 OUT(",\n");
400 delimit = 0;
401 } else if(el) {
402 OUT(" | ");
403 }
Lev Walkincc93b0f2004-09-10 09:18:20 +0000404 OUT("(%d << %d)",
Lev Walkin0204fa62004-09-15 11:54:38 +0000405 v->marker.flags?0:1,
Lev Walkincc93b0f2004-09-10 09:18:20 +0000406 7 - (el % 8));
Lev Walkinf15320b2004-06-03 03:38:44 +0000407 if(el && (el % 8) == 0)
408 delimit = 1;
409 el++;
410 }
411 } else {
412 OUT("0");
413 }
414 );
415 OUT("\n");
416 OUT("};\n");
417
Lev Walkin05363a72004-09-29 13:16:40 +0000418 OUT("static asn_SET_specifics_t asn_DEF_%s_specs = {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000419 INDENTED(
420 OUT("sizeof(struct %s),\n", p);
Lev Walkin05363a72004-09-29 13:16:40 +0000421 OUT("offsetof(struct %s, _asn_ctx),\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000422 OUT("offsetof(struct %s, _presence_map),\n", p);
Lev Walkin05363a72004-09-29 13:16:40 +0000423 OUT("asn_DEF_%s_tag2el,\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000424 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000425 if(tag2el_cxer)
426 OUT("asn_DEF_%s_tag2el_cxer,\n", p);
427 else
428 OUT("asn_DEF_%s_tag2el,\t/* Same as above */\n", p);
429 OUT("%d,\t/* Count of tags in the CANONICAL-XER map */\n", tag2el_cxer_count);
Lev Walkin35631482004-07-01 00:52:50 +0000430 OUT("%d,\t/* Whether extensible */\n",
431 check_if_extensible(expr));
Lev Walkin05363a72004-09-29 13:16:40 +0000432 OUT("(unsigned int *)asn_DEF_%s_mmap\t/* Mandatory elements map */\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000433 );
434 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000435
436 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000437 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +0000438 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000439 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
Lev Walkin8de2ab22004-09-26 13:11:31 +0000440 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000441
Lev Walkinf15320b2004-06-03 03:38:44 +0000442 REDIR(OT_TYPE_DECLS);
443
444 return 0;
445}
446
447int
Lev Walkin08079b02004-08-22 03:25:24 +0000448asn1c_lang_C_type_SEx_OF(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000449 asn1p_expr_t *expr = arg->expr;
Lev Walkin08079b02004-08-22 03:25:24 +0000450 asn1p_expr_t *memb;
Lev Walkinf15320b2004-06-03 03:38:44 +0000451
452 DEPENDENCIES;
453
454 if(arg->embed) {
455 OUT("struct %s {\n", MKID(expr->Identifier));
456 } else {
Lev Walkin08079b02004-08-22 03:25:24 +0000457 OUT("typedef struct %s {\n", MKID(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +0000458 }
459
Lev Walkin08079b02004-08-22 03:25:24 +0000460 memb = TQ_FIRST(&expr->members);
461
462 INDENT(+1);
463 OUT("A_%s_OF(",
464 (arg->expr->expr_type == ASN_CONSTR_SET_OF)
465 ? "SET" : "SEQUENCE");
466 if(memb->expr_type & ASN_CONSTR_MASK) {
467 arg_t tmp;
468 asn1p_expr_t tmp_memb;
469 arg->embed++;
470 tmp = *arg;
471 tmp.expr = &tmp_memb;
472 tmp_memb = *memb;
473 tmp_memb._anonymous_type = 1;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000474 if(tmp_memb.Identifier == 0) {
475 tmp_memb.Identifier = strdup(
476 asn1c_make_identifier(0,
477 expr->Identifier, "member", 0));
478 assert(tmp_memb.Identifier);
479 }
Lev Walkin08079b02004-08-22 03:25:24 +0000480 tmp.default_cb(&tmp);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000481 if(tmp_memb.Identifier != memb->Identifier)
482 free(tmp_memb.Identifier);
Lev Walkin08079b02004-08-22 03:25:24 +0000483 arg->embed--;
484 assert(arg->target->target == OT_TYPE_DECLS);
485 } else {
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000486 OUT("%s", asn1c_type_name(arg, memb, TNF_CTYPE));
Lev Walkinf15320b2004-06-03 03:38:44 +0000487 }
Lev Walkin08079b02004-08-22 03:25:24 +0000488 OUT(") list;\n");
489 INDENT(-1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000490
491 PCTX_DEF;
Lev Walkin0204fa62004-09-15 11:54:38 +0000492 OUT("} %s%s%s", expr->marker.flags?"*":"",
Lev Walkin08079b02004-08-22 03:25:24 +0000493 expr->_anonymous_type ? "" : MKID(expr->Identifier),
494 arg->embed ? "" : "_t");
Lev Walkinf15320b2004-06-03 03:38:44 +0000495
496 /*
Lev Walkin08079b02004-08-22 03:25:24 +0000497 * SET OF/SEQUENCE OF definition
Lev Walkinf15320b2004-06-03 03:38:44 +0000498 */
Lev Walkin08079b02004-08-22 03:25:24 +0000499 return asn1c_lang_C_type_SEx_OF_def(arg,
500 (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF));
Lev Walkinf15320b2004-06-03 03:38:44 +0000501}
502
503static int
504asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
505 asn1p_expr_t *expr = arg->expr;
506 asn1p_expr_t *v;
Lev Walkin64399722004-08-11 07:17:22 +0000507 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000508 int all_tags_count;
509 enum tvm_compat tv_mode;
Lev Walkinf15320b2004-06-03 03:38:44 +0000510 char *p;
511
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000512 /*
513 * Print out the table according to which the parsing is performed.
514 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000515 if(seq_of) {
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000516 GEN_INCLUDE("constr_SEQUENCE_OF");
Lev Walkinf15320b2004-06-03 03:38:44 +0000517 } else {
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000518 GEN_INCLUDE("constr_SET_OF");
Lev Walkinf15320b2004-06-03 03:38:44 +0000519 }
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000520 if(!arg->embed)
Lev Walkin05363a72004-09-29 13:16:40 +0000521 GEN_DECLARE(expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000522
523 REDIR(OT_STAT_DEFS);
524
525 /*
526 * Print out the table according to which the parsing is performed.
527 */
528 p = MKID(expr->Identifier);
Lev Walkin05363a72004-09-29 13:16:40 +0000529 OUT("static asn_TYPE_member_t asn_MBR_%s[] = {\n", p);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000530 INDENT(+1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000531 v = TQ_FIRST(&(expr->members));
Lev Walkina9cc46e2004-09-22 16:06:28 +0000532 if(!v->Identifier) {
533 v->Identifier = strdup("member");
534 assert(v->Identifier);
535 }
536 v->_anonymous_type = 1;
537 arg->embed++;
Lev Walkin59964be2004-08-25 02:03:12 +0000538 emit_member_table(arg, v);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000539 arg->embed--;
540 INDENT(-1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000541 OUT("};\n");
542
Lev Walkin27ea3802004-06-28 21:13:46 +0000543 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000544 * Print out asn_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +0000545 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000546 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000547
Lev Walkin27ea3802004-06-28 21:13:46 +0000548 p = MKID(expr->Identifier);
Lev Walkin05363a72004-09-29 13:16:40 +0000549 OUT("static asn_SET_OF_specifics_t asn_DEF_%s_specs = {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000550 INDENTED(
551 OUT("sizeof(struct %s),\n", p);
Lev Walkin05363a72004-09-29 13:16:40 +0000552 OUT("offsetof(struct %s, _asn_ctx),\n", p);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000553 if(expr_as_xmlvaluelist(arg, v))
554 OUT("1,\t/* XER encoding is XMLValueList */\n");
555 else
556 OUT("0,\t/* XER encoding is XMLDelimitedItemList */\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000557 );
558 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000559
560 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000561 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +0000562 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000563 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, 1,
Lev Walkin8de2ab22004-09-26 13:11:31 +0000564 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000565
Lev Walkinf15320b2004-06-03 03:38:44 +0000566 REDIR(OT_TYPE_DECLS);
567
568 return 0;
569}
570
571int
572asn1c_lang_C_type_CHOICE(arg_t *arg) {
573 asn1p_expr_t *expr = arg->expr;
574 asn1p_expr_t *v;
Lev Walkin08079b02004-08-22 03:25:24 +0000575 char *id;
Lev Walkinf15320b2004-06-03 03:38:44 +0000576
577 DEPENDENCIES;
578
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000579 REDIR(OT_DEPS);
580
Lev Walkin08079b02004-08-22 03:25:24 +0000581 id = MKID(expr->Identifier);
582 OUT("typedef enum %s_PR {\n", id);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000583 INDENTED(
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000584 OUT("%s_PR_NOTHING,\t"
Lev Walkin08079b02004-08-22 03:25:24 +0000585 "/* No components present */\n", id);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000586 TQ_FOR(v, &(expr->members), next) {
587 if(v->expr_type == A1TC_EXTENSIBLE) {
588 OUT("/* Extensions may appear below */\n");
589 continue;
590 }
Lev Walkin08079b02004-08-22 03:25:24 +0000591 id = MKID(expr->Identifier);
592 OUT("%s_PR_", id);
593 id = MKID(v->Identifier);
594 OUT("%s,\n", id, id);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000595 }
596 );
Lev Walkin08079b02004-08-22 03:25:24 +0000597 id = MKID(expr->Identifier);
598 OUT("} %s_PR;\n", id);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000599
600 REDIR(OT_TYPE_DECLS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000601
602 if(arg->embed) {
Lev Walkin08079b02004-08-22 03:25:24 +0000603 OUT("struct %s {\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000604 } else {
Lev Walkin08079b02004-08-22 03:25:24 +0000605 OUT("typedef struct %s {\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000606 }
607
608 INDENTED(
Lev Walkin08079b02004-08-22 03:25:24 +0000609 OUT("%s_PR present;\n", id);
610 OUT("union {\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000611 TQ_FOR(v, &(expr->members), next) {
Lev Walkincc93b0f2004-09-10 09:18:20 +0000612 if(expr_better_indirect(arg, v))
Lev Walkin0204fa62004-09-15 11:54:38 +0000613 v->marker.flags |= EM_INDIRECT;
Lev Walkinf15320b2004-06-03 03:38:44 +0000614 EMBED(v);
615 }
616 if(UNNAMED_UNIONS) OUT("};\n");
617 else OUT("} choice;\n");
618 );
619
620 PCTX_DEF;
Lev Walkin0204fa62004-09-15 11:54:38 +0000621 OUT("} %s%s%s", expr->marker.flags?"*":"",
Lev Walkin08079b02004-08-22 03:25:24 +0000622 expr->_anonymous_type ? "" : MKID(expr->Identifier),
623 arg->embed ? "" : "_t");
Lev Walkinf15320b2004-06-03 03:38:44 +0000624
625 return asn1c_lang_C_type_CHOICE_def(arg);
626}
627
628static int
629asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
630 asn1p_expr_t *expr = arg->expr;
631 asn1p_expr_t *v;
632 int elements; /* Number of elements */
Lev Walkinf15320b2004-06-03 03:38:44 +0000633 tag2el_t *tag2el = NULL;
634 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000635 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000636 int all_tags_count;
637 enum tvm_compat tv_mode;
Lev Walkinf15320b2004-06-03 03:38:44 +0000638 char *p;
639
640 /*
641 * Fetch every inner tag from the tag to elements map.
642 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000643 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000644 if(tag2el) free(tag2el);
645 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000646 }
647
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000648 GEN_INCLUDE("constr_CHOICE");
649 if(!arg->embed)
Lev Walkin05363a72004-09-29 13:16:40 +0000650 GEN_DECLARE(expr); /* asn_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000651
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000652 REDIR(OT_STAT_DEFS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000653
654 /*
655 * Print out the table according to which the parsing is performed.
656 */
Lev Walkina9cc46e2004-09-22 16:06:28 +0000657 if(expr_elements_count(arg, expr)) {
658 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Lev Walkinf15320b2004-06-03 03:38:44 +0000659
Lev Walkina9cc46e2004-09-22 16:06:28 +0000660 p = MKID(expr->Identifier);
Lev Walkin05363a72004-09-29 13:16:40 +0000661 OUT("static asn_TYPE_member_t asn_MBR_%s[] = {\n", p);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000662
663 elements = 0;
664 INDENTED(TQ_FOR(v, &(expr->members), next) {
665 if(v->expr_type == A1TC_EXTENSIBLE) {
666 if(comp_mode < 3) comp_mode++;
667 } else {
668 if(comp_mode == 1
669 || expr_better_indirect(arg, v))
670 v->marker.flags |= EM_INDIRECT;
671 elements++;
672 emit_member_table(arg, v);
673 }
674 });
675 OUT("};\n");
676 } else {
677 elements = 0;
678 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000679
Lev Walkin64399722004-08-11 07:17:22 +0000680
Lev Walkinf15320b2004-06-03 03:38:44 +0000681 if(arg->embed) {
682 /*
683 * Our parent structure has already taken this into account.
684 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000685 tv_mode = _TVM_SAME;
686 tags_count = all_tags_count = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000687 } else {
Lev Walkin188ed2c2004-09-13 08:31:01 +0000688 tv_mode = emit_tags_vectors(arg, expr,
689 &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000690 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000691
692 /*
693 * Tags to elements map.
694 */
Lev Walkin33d5d3c2004-10-03 09:13:30 +0000695 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000696
Lev Walkin64399722004-08-11 07:17:22 +0000697 p = MKID(expr->Identifier);
Lev Walkin05363a72004-09-29 13:16:40 +0000698 OUT("static asn_CHOICE_specifics_t asn_DEF_%s_specs = {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000699 INDENTED(
700 OUT("sizeof(struct %s),\n", p);
Lev Walkin05363a72004-09-29 13:16:40 +0000701 OUT("offsetof(struct %s, _asn_ctx),\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000702 OUT("offsetof(struct %s, present),\n", p);
703 OUT("sizeof(((struct %s *)0)->present),\n", p);
Lev Walkin05363a72004-09-29 13:16:40 +0000704 OUT("asn_DEF_%s_tag2el,\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000705 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
Lev Walkin35631482004-07-01 00:52:50 +0000706 OUT("%d\t/* Whether extensible */\n",
707 check_if_extensible(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +0000708 );
709 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000710
711 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000712 * Emit asn_DEF_xxx table.
Lev Walkin59964be2004-08-25 02:03:12 +0000713 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000714 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
Lev Walkin8de2ab22004-09-26 13:11:31 +0000715 ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000716
Lev Walkinf15320b2004-06-03 03:38:44 +0000717 REDIR(OT_TYPE_DECLS);
718
719 return 0;
720}
721
722int
723asn1c_lang_C_type_REFERENCE(arg_t *arg) {
724 asn1p_ref_t *ref;
725
726 ref = arg->expr->reference;
727 if(ref->components[ref->comp_count-1].name[0] == '&') {
Lev Walkinf15320b2004-06-03 03:38:44 +0000728 asn1p_expr_t *extract;
729 arg_t tmp;
730 int ret;
731
Lev Walkina9cc46e2004-09-22 16:06:28 +0000732 extract = asn1f_class_access_ex(arg->asn, arg->expr->module,
Lev Walkin08079b02004-08-22 03:25:24 +0000733 arg->expr, ref);
Lev Walkinf15320b2004-06-03 03:38:44 +0000734 if(extract == NULL)
735 return -1;
736
Lev Walkin08079b02004-08-22 03:25:24 +0000737 extract = asn1p_expr_clone(extract, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000738 if(extract) {
739 if(extract->Identifier)
740 free(extract->Identifier);
741 extract->Identifier = strdup(arg->expr->Identifier);
742 if(extract->Identifier == NULL) {
743 asn1p_expr_free(extract);
744 return -1;
745 }
746 } else {
747 return -1;
748 }
749
750 tmp = *arg;
751 tmp.asn = arg->asn;
Lev Walkin08079b02004-08-22 03:25:24 +0000752 tmp.mod = extract->module;
Lev Walkinf15320b2004-06-03 03:38:44 +0000753 tmp.expr = extract;
754
755 ret = arg->default_cb(&tmp);
756
757 asn1p_expr_free(extract);
758
759 return ret;
760 }
761
762
763 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
764}
765
766int
767asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
768 asn1p_expr_t *expr = arg->expr;
Lev Walkin64399722004-08-11 07:17:22 +0000769 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000770 int all_tags_count;
771 enum tvm_compat tv_mode;
Lev Walkinf15320b2004-06-03 03:38:44 +0000772 char *p;
773
774 if(arg->embed) {
Lev Walkin05363a72004-09-29 13:16:40 +0000775 enum tnfmt tnfmt = TNF_CTYPE;
776
777 /*
778 * If this is an optional compound type,
779 * refer it using "struct X" convention,
780 * as it may recursively include the current structure.
781 */
782 if(expr->marker.flags) {
783 asn1p_expr_t *terminal;
784 terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
785 if(terminal
786 && (terminal->expr_type & ASN_CONSTR_MASK)) {
787 REDIR(OT_DEPS);
788 tnfmt = TNF_RSAFE;
789 OUT("\n");
790 OUT("%s;\t/* Forward declaration */\n",
791 asn1c_type_name(arg, arg->expr, tnfmt));
792 }
793 }
794
Lev Walkinf15320b2004-06-03 03:38:44 +0000795 REDIR(OT_TYPE_DECLS);
796
Lev Walkin05363a72004-09-29 13:16:40 +0000797 OUT("%s\t", asn1c_type_name(arg, arg->expr, tnfmt));
Lev Walkin0204fa62004-09-15 11:54:38 +0000798 OUT("%s", expr->marker.flags?"*":" ");
Lev Walkin08079b02004-08-22 03:25:24 +0000799 OUT("%s", MKID(expr->Identifier));
Lev Walkin0204fa62004-09-15 11:54:38 +0000800 if((expr->marker.flags & EM_DEFAULT) == EM_DEFAULT)
801 OUT("\t/* DEFAULT %s */",
802 asn1f_printable_value(expr->marker.default_value));
803 else if((expr->marker.flags & EM_OPTIONAL) == EM_OPTIONAL)
Lev Walkincc93b0f2004-09-10 09:18:20 +0000804 OUT("\t/* OPTIONAL */");
Lev Walkin59004fa2004-08-20 13:37:01 +0000805
806 REDIR(OT_TYPE_DECLS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000807 return 0;
808 }
809
Lev Walkinf15320b2004-06-03 03:38:44 +0000810
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000811 GEN_INCLUDE(asn1c_type_name(arg, expr, TNF_INCLUDE));
Lev Walkinf15320b2004-06-03 03:38:44 +0000812
813 REDIR(OT_TYPE_DECLS);
814
815 OUT("typedef %s\t", asn1c_type_name(arg, arg->expr, TNF_CTYPE));
Lev Walkin0204fa62004-09-15 11:54:38 +0000816 OUT("%s", expr->marker.flags?"*":" ");
Lev Walkin08079b02004-08-22 03:25:24 +0000817 OUT("%s_t", MKID(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +0000818
Lev Walkin8de2ab22004-09-26 13:11:31 +0000819 /*
820 * If this type just blindly refers the other type, alias it.
821 * Type1 ::= Type2
822 */
823 if((!expr->constraints || (arg->flags & A1C_NO_CONSTRAINTS))
824 && expr->tag.tag_class == TC_NOCLASS
825 && !TQ_FIRST(&(expr->members))
826 ) {
827 char *type_name;
828 REDIR(OT_FUNC_DECLS);
829 type_name = asn1c_type_name(arg, expr, TNF_SAFE);
830 OUT("/* This type is equivalent to %s */\n", type_name);
831 p = MKID(expr->Identifier);
832 if(HIDE_INNER_DEFS) OUT("/* ");
Lev Walkin05363a72004-09-29 13:16:40 +0000833 OUT("#define\tasn_DEF_%s\t", p);
Lev Walkin8de2ab22004-09-26 13:11:31 +0000834 type_name = asn1c_type_name(arg, expr, TNF_SAFE);
Lev Walkin05363a72004-09-29 13:16:40 +0000835 OUT("asn_DEF_%s\n", type_name);
Lev Walkin8de2ab22004-09-26 13:11:31 +0000836 if(HIDE_INNER_DEFS)
837 OUT(" // (Use -fall-defs-global to expose) */");
838 REDIR(OT_CODE);
839 OUT("/* This type is equivalent to %s */\n", type_name);
840 OUT("\n");
841 REDIR(OT_TYPE_DECLS);
842 return 0;
843 }
844
Lev Walkinf15320b2004-06-03 03:38:44 +0000845 REDIR(OT_STAT_DEFS);
846
Lev Walkin27ea3802004-06-28 21:13:46 +0000847 /*
Lev Walkin05363a72004-09-29 13:16:40 +0000848 * Print out asn_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +0000849 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000850 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000851
Lev Walkin188ed2c2004-09-13 08:31:01 +0000852 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, 0,
Lev Walkin8de2ab22004-09-26 13:11:31 +0000853 ETD_NO_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000854
Lev Walkin59004fa2004-08-20 13:37:01 +0000855 REDIR(OT_CODE);
856
Lev Walkinf15320b2004-06-03 03:38:44 +0000857 /*
858 * Constraint checking.
859 */
Lev Walkin8de2ab22004-09-26 13:11:31 +0000860 if(!(arg->flags & A1C_NO_CONSTRAINTS)) {
861 p = MKID(expr->Identifier);
862 OUT("int\n");
863 OUT("%s_constraint("
Lev Walkin05363a72004-09-29 13:16:40 +0000864 "asn_TYPE_descriptor_t *td, const void *sptr,\n", p);
Lev Walkin8de2ab22004-09-26 13:11:31 +0000865 INDENT(+1);
866 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {");
867 OUT("\n");
868 if(asn1c_emit_constraint_checking_code(arg) == 1) {
869 OUT("/* Replace with underlying type checker */\n");
870 OUT("td->check_constraints "
Lev Walkin05363a72004-09-29 13:16:40 +0000871 "= asn_DEF_%s.check_constraints;\n",
Lev Walkin8de2ab22004-09-26 13:11:31 +0000872 asn1c_type_name(arg, expr, TNF_SAFE));
873 OUT("return td->check_constraints"
874 "(td, sptr, app_errlog, app_key);\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000875 }
Lev Walkin8de2ab22004-09-26 13:11:31 +0000876 INDENT(-1);
877 OUT("}\n");
878 OUT("\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000879 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000880
881 /*
882 * Emit suicidal functions.
883 */
884
Lev Walkinf15320b2004-06-03 03:38:44 +0000885 /*
886 * This function replaces certain fields from the definition
887 * of a type with the corresponding fields from the basic type
888 * (from which the current type is inherited).
889 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000890 OUT("/*\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000891 OUT(" * This type is implemented using %s,\n",
892 asn1c_type_name(arg, expr, TNF_SAFE));
Lev Walkinb65b3002004-09-23 22:20:47 +0000893 OUT(" * so here we adjust the DEF accordingly.\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000894 OUT(" */\n");
895 OUT("static void\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000896 p = MKID(expr->Identifier);
Lev Walkin05363a72004-09-29 13:16:40 +0000897 OUT("%s_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000898 INDENT(+1);
Lev Walkin59004fa2004-08-20 13:37:01 +0000899 {
Lev Walkina9cc46e2004-09-22 16:06:28 +0000900 asn1p_expr_t *terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
Lev Walkin59004fa2004-08-20 13:37:01 +0000901 char *type_name = asn1c_type_name(arg, expr, TNF_SAFE);
Lev Walkin05363a72004-09-29 13:16:40 +0000902 OUT("td->free_struct = asn_DEF_%s.free_struct;\n", type_name);
903 OUT("td->print_struct = asn_DEF_%s.print_struct;\n", type_name);
904 OUT("td->ber_decoder = asn_DEF_%s.ber_decoder;\n", type_name);
905 OUT("td->der_encoder = asn_DEF_%s.der_encoder;\n", type_name);
906 OUT("td->xer_decoder = asn_DEF_%s.xer_decoder;\n", type_name);
907 OUT("td->xer_encoder = asn_DEF_%s.xer_encoder;\n", type_name);
Lev Walkin906654e2004-09-10 15:49:15 +0000908 if(!terminal && !tags_count) {
Lev Walkin188ed2c2004-09-13 08:31:01 +0000909 OUT("/* The next four lines are here because of -fknown-extern-type */\n");
Lev Walkin05363a72004-09-29 13:16:40 +0000910 OUT("td->tags = asn_DEF_%s.tags;\n", type_name);
911 OUT("td->tags_count = asn_DEF_%s.tags_count;\n", type_name);
912 OUT("td->all_tags = asn_DEF_%s.all_tags;\n", type_name);
913 OUT("td->all_tags_count = asn_DEF_%s.all_tags_count;\n",type_name);
Lev Walkin906654e2004-09-10 15:49:15 +0000914 OUT("/* End of these lines */\n");
915 }
Lev Walkin05363a72004-09-29 13:16:40 +0000916 OUT("td->elements = asn_DEF_%s.elements;\n", type_name);
917 OUT("td->elements_count = asn_DEF_%s.elements_count;\n", type_name);
918 OUT("td->specifics = asn_DEF_%s.specifics;\n", type_name);
Lev Walkin59004fa2004-08-20 13:37:01 +0000919 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000920 INDENT(-1);
921 OUT("}\n");
922 OUT("\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000923
924 p = MKID(expr->Identifier);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000925 OUT("void\n");
Lev Walkin05363a72004-09-29 13:16:40 +0000926 OUT("%s_free(asn_TYPE_descriptor_t *td,\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000927 INDENTED(
Lev Walkina9cc46e2004-09-22 16:06:28 +0000928 OUT("\tvoid *struct_ptr, int contents_only) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000929 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000930 OUT("td->free_struct(td, struct_ptr, contents_only);\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000931 );
932 OUT("}\n");
933 OUT("\n");
934
935 p = MKID(expr->Identifier);
936 OUT("int\n");
Lev Walkin05363a72004-09-29 13:16:40 +0000937 OUT("%s_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000938 INDENTED(
939 OUT("\tint ilevel, asn_app_consume_bytes_f *cb, void *app_key) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000940 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000941 OUT("return td->print_struct(td, struct_ptr, ilevel, cb, app_key);\n");
942 );
943 OUT("}\n");
944 OUT("\n");
945
946 p = MKID(expr->Identifier);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000947 OUT("ber_dec_rval_t\n");
Lev Walkin05363a72004-09-29 13:16:40 +0000948 OUT("%s_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000949 INDENTED(
Lev Walkina9cc46e2004-09-22 16:06:28 +0000950 OUT("\tvoid **structure, void *bufptr, size_t size, int tag_mode) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000951 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
Lev Walkin05363a72004-09-29 13:16:40 +0000952 OUT("return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);\n");
Lev Walkina9cc46e2004-09-22 16:06:28 +0000953 );
954 OUT("}\n");
955 OUT("\n");
956
957 p = MKID(expr->Identifier);
958 OUT("asn_enc_rval_t\n");
Lev Walkin05363a72004-09-29 13:16:40 +0000959 OUT("%s_encode_der(asn_TYPE_descriptor_t *td,\n", p);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000960 INDENTED(
961 OUT("\tvoid *structure, int tag_mode, ber_tlv_tag_t tag,\n");
962 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
963 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
964 OUT("return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);\n");
965 );
966 OUT("}\n");
967 OUT("\n");
968
969 p = MKID(expr->Identifier);
970 OUT("asn_enc_rval_t\n");
Lev Walkin05363a72004-09-29 13:16:40 +0000971 OUT("%s_encode_xer(asn_TYPE_descriptor_t *td, void *structure,\n", p);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000972 INDENTED(
973 OUT("\tint ilevel, enum xer_encoder_flags_e flags,\n");
974 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
975 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
976 OUT("return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000977 );
978 OUT("}\n");
979 OUT("\n");
980
981 REDIR(OT_FUNC_DECLS);
982
983 p = MKID(expr->Identifier);
Lev Walkindd32b592004-09-06 08:07:29 +0000984 if(HIDE_INNER_DEFS) OUT("/* ");
Lev Walkin05363a72004-09-29 13:16:40 +0000985 OUT("extern asn_TYPE_descriptor_t asn_DEF_%s;", p);
Lev Walkindd32b592004-09-06 08:07:29 +0000986 if(HIDE_INNER_DEFS) OUT(" // (Use -fall-defs-global to expose) */");
987 OUT("\n");
Lev Walkina9cc46e2004-09-22 16:06:28 +0000988 OUT("asn_struct_free_f %s_free;\n", p);
989 OUT("asn_struct_print_f %s_print;\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000990 OUT("asn_constr_check_f %s_constraint;\n", p);
991 OUT("ber_type_decoder_f %s_decode_ber;\n", p);
992 OUT("der_type_encoder_f %s_encode_der;\n", p);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000993 OUT("xer_type_encoder_f %s_encode_xer;\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000994
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000995 REDIR(OT_TYPE_DECLS);
996
Lev Walkinf15320b2004-06-03 03:38:44 +0000997 return 0;
998}
999
1000int
1001asn1c_lang_C_type_EXTENSIBLE(arg_t *arg) {
1002
1003 OUT("/*\n");
1004 OUT(" * This type is extensible,\n");
1005 OUT(" * possible extensions are below.\n");
1006 OUT(" */\n");
1007
1008 return 0;
1009}
1010
Lev Walkin35631482004-07-01 00:52:50 +00001011static int check_if_extensible(asn1p_expr_t *expr) {
1012 asn1p_expr_t *v;
1013 TQ_FOR(v, &(expr->members), next) {
1014 if(v->expr_type == A1TC_EXTENSIBLE) return 1;
1015 }
1016 return 0;
1017}
1018
Lev Walkinf15320b2004-06-03 03:38:44 +00001019static int
Lev Walkinc3e29402004-09-10 06:07:18 +00001020_print_tag(arg_t *arg, struct asn1p_type_tag_s *tag) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001021
1022 OUT("(");
Lev Walkinc3e29402004-09-10 06:07:18 +00001023 switch(tag->tag_class) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001024 case TC_UNIVERSAL: OUT("ASN_TAG_CLASS_UNIVERSAL"); break;
1025 case TC_APPLICATION: OUT("ASN_TAG_CLASS_APPLICATION"); break;
1026 case TC_CONTEXT_SPECIFIC: OUT("ASN_TAG_CLASS_CONTEXT"); break;
1027 case TC_PRIVATE: OUT("ASN_TAG_CLASS_PRIVATE"); break;
1028 case TC_NOCLASS:
1029 break;
1030 }
Lev Walkin33c16ba2004-09-24 21:01:43 +00001031 OUT(" | (%" PRIdASN " << 2))", tag->tag_value);
Lev Walkinf15320b2004-06-03 03:38:44 +00001032
1033 return 0;
1034}
1035
Lev Walkinfd171ef2004-06-06 07:20:17 +00001036
1037static int
1038_tag2el_cmp(const void *ap, const void *bp) {
1039 const tag2el_t *a = ap;
1040 const tag2el_t *b = bp;
1041 const struct asn1p_type_tag_s *ta = &a->el_tag;
1042 const struct asn1p_type_tag_s *tb = &b->el_tag;
1043
1044 if(ta->tag_class == tb->tag_class) {
1045 if(ta->tag_value == tb->tag_value) {
1046 /*
1047 * Sort by their respective positions.
1048 */
1049 if(a->el_no < b->el_no)
1050 return -1;
1051 else if(a->el_no > b->el_no)
1052 return 1;
1053 return 0;
1054 } else if(ta->tag_value < tb->tag_value)
1055 return -1;
1056 else
1057 return 1;
1058 } else if(ta->tag_class < tb->tag_class) {
1059 return -1;
1060 } else {
1061 return 1;
1062 }
1063}
1064
Lev Walkinf15320b2004-06-03 03:38:44 +00001065/*
1066 * For constructed types, number of external tags may be greater than
1067 * number of elements in the type because of CHOICE type.
1068 * T ::= SET { -- Three possible tags:
1069 * a INTEGER, -- One tag is here...
1070 * b Choice1 -- ... and two more tags are there.
1071 * }
1072 * Choice1 ::= CHOICE {
1073 * s1 IA5String,
1074 * s2 ObjectDescriptor
1075 * }
1076 */
1077static int
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001078_fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001079 asn1p_expr_t *expr = arg->expr;
1080 arg_t tmparg = *arg;
1081 asn1p_expr_t *v;
1082 int element = 0;
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001083 int original_count = *count;
1084 int sort_until = -1;
Lev Walkinf15320b2004-06-03 03:38:44 +00001085
1086 TQ_FOR(v, &(expr->members), next) {
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001087 if(v->expr_type == A1TC_EXTENSIBLE) {
1088 /*
1089 * CANONICAL-XER mandates sorting
1090 * only for the root part.
1091 */
1092 if(flags == FTE_CANONICAL_XER
1093 && sort_until == -1)
1094 sort_until = *count;
Lev Walkinf15320b2004-06-03 03:38:44 +00001095 continue;
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001096 }
Lev Walkinf15320b2004-06-03 03:38:44 +00001097
1098 tmparg.expr = v;
1099
1100 if(_add_tag2el_member(&tmparg, tag2el, count,
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001101 (el_no==-1)?element:el_no, flags)) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001102 return -1;
1103 }
1104
1105 element++;
1106 }
1107
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001108
1109 if(flags == FTE_CANONICAL_XER) {
1110 if(sort_until == -1) sort_until = *count;
1111 qsort((*tag2el) + original_count,
1112 sort_until - original_count,
1113 sizeof(**tag2el), _tag2el_cmp);
1114 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1115 && (sort_until - original_count) >= 1) {
1116 /* Only take in account the root component */
1117 *count = original_count + 1;
1118 }
1119 } else {
1120 /*
1121 * Sort the map according to canonical order of their
1122 * tags and element numbers.
1123 */
1124 qsort(*tag2el, *count, sizeof(**tag2el), _tag2el_cmp);
1125 }
Lev Walkinfd171ef2004-06-06 07:20:17 +00001126
Lev Walkin38abe792004-06-14 13:09:45 +00001127 /*
1128 * Initialize .toff_{first|last} members.
1129 */
1130 if(*count) {
1131 struct asn1p_type_tag_s *cur_tag = 0;
1132 tag2el_t *cur = *tag2el;
1133 tag2el_t *end = cur + *count;
1134 int occur, i;
1135 for(occur = 0; cur < end; cur++) {
1136 if(cur_tag == 0
1137 || cur_tag->tag_value != cur->el_tag.tag_value
1138 || cur_tag->tag_class != cur->el_tag.tag_class) {
1139 cur_tag = &cur->el_tag;
1140 occur = 0;
1141 } else {
1142 occur++;
1143 }
1144 cur->toff_first = -occur;
1145 for(i = 0; i >= -occur; i--)
1146 cur[i].toff_last = -i;
1147 }
1148 }
1149
Lev Walkinf15320b2004-06-03 03:38:44 +00001150 return 0;
1151}
1152
1153static int
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001154_add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +00001155 struct asn1p_type_tag_s tag;
1156 int ret;
1157
1158 assert(el_no >= 0);
1159
Lev Walkina9cc46e2004-09-22 16:06:28 +00001160 ret = asn1f_fetch_outmost_tag(arg->asn, arg->expr->module,
1161 arg->expr, &tag, 1);
Lev Walkinf15320b2004-06-03 03:38:44 +00001162 if(ret == 0) {
Lev Walkin201943e2004-09-04 04:42:29 +00001163 tag2el_t *te;
1164 int new_count = (*count) + 1;
Lev Walkinf15320b2004-06-03 03:38:44 +00001165 void *p;
Lev Walkin201943e2004-09-04 04:42:29 +00001166
Lev Walkinac7e2292004-09-05 10:42:33 +00001167 if(tag.tag_value == -1) {
1168 /*
1169 * This is an untagged ANY type,
1170 * proceed without adding a tag
1171 */
1172 return 0;
1173 }
1174
Lev Walkin201943e2004-09-04 04:42:29 +00001175 p = realloc(*tag2el, new_count * sizeof(tag2el_t));
Lev Walkinf15320b2004-06-03 03:38:44 +00001176 if(p) *tag2el = p;
1177 else return -1;
1178
1179 DEBUG("Found tag for %s: %ld",
1180 arg->expr->Identifier,
1181 (long)tag.tag_value);
1182
Lev Walkin201943e2004-09-04 04:42:29 +00001183 te = &((*tag2el)[*count]);
1184 te->el_tag = tag;
1185 te->el_no = el_no;
1186 te->from_expr = arg->expr;
1187 *count = new_count;
Lev Walkinf15320b2004-06-03 03:38:44 +00001188 return 0;
1189 }
1190
1191 DEBUG("Searching tag in complex expression %s:%x at line %d",
1192 arg->expr->Identifier,
1193 arg->expr->expr_type,
1194 arg->expr->_lineno);
1195
1196 /*
1197 * Iterate over members of CHOICE type.
1198 */
1199 if(arg->expr->expr_type == ASN_CONSTR_CHOICE) {
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001200 return _fill_tag2el_map(arg, tag2el, count, el_no, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +00001201 }
1202
1203 if(arg->expr->expr_type == A1TC_REFERENCE) {
1204 arg_t tmp = *arg;
1205 asn1p_expr_t *expr;
Lev Walkin08079b02004-08-22 03:25:24 +00001206 expr = asn1f_lookup_symbol_ex(tmp.asn, tmp.mod, tmp.expr,
Lev Walkinf15320b2004-06-03 03:38:44 +00001207 arg->expr->reference);
1208 if(expr) {
Lev Walkin08079b02004-08-22 03:25:24 +00001209 tmp.mod = expr->module;
Lev Walkinf15320b2004-06-03 03:38:44 +00001210 tmp.expr = expr;
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001211 return _add_tag2el_member(&tmp, tag2el, count, el_no, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +00001212 } else {
1213 FATAL("Cannot dereference %s at line %d",
1214 arg->expr->Identifier,
1215 arg->expr->_lineno);
1216 return -1;
1217 }
1218 }
1219
1220 DEBUG("No tag for %s at line %d",
1221 arg->expr->Identifier,
1222 arg->expr->_lineno);
1223
1224 return -1;
1225}
1226
1227static int
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001228emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier) {
Lev Walkinfd171ef2004-06-06 07:20:17 +00001229 asn1p_expr_t *expr = arg->expr;
1230
Lev Walkin33d5d3c2004-10-03 09:13:30 +00001231 OUT("static asn_TYPE_tag2member_t asn_DEF_%s_tag2el%s[] = {\n",
1232 MKID(expr->Identifier), opt_modifier?opt_modifier:"");
Lev Walkinfd171ef2004-06-06 07:20:17 +00001233 if(tag2el_count) {
1234 int i;
1235 for(i = 0; i < tag2el_count; i++) {
1236 OUT(" { ");
Lev Walkinc3e29402004-09-10 06:07:18 +00001237 _print_tag(arg, &tag2el[i].el_tag);
Lev Walkinfd171ef2004-06-06 07:20:17 +00001238 OUT(", ");
Lev Walkin38abe792004-06-14 13:09:45 +00001239 OUT("%d, ", tag2el[i].el_no);
1240 OUT("%d, ", tag2el[i].toff_first);
1241 OUT("%d ", tag2el[i].toff_last);
Lev Walkinfd171ef2004-06-06 07:20:17 +00001242 OUT("}, /* %s at %d */\n",
1243 tag2el[i].from_expr->Identifier,
1244 tag2el[i].from_expr->_lineno
1245 );
1246 }
1247 }
1248 OUT("};\n");
1249
1250 return 0;;
1251}
1252
Lev Walkin188ed2c2004-09-13 08:31:01 +00001253static enum tvm_compat
1254emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tags_count_r, int *all_tags_count_r) {
1255 struct asn1p_type_tag_s *tags = 0; /* Effective tags */
1256 struct asn1p_type_tag_s *all_tags = 0; /* The full array */
Lev Walkin64399722004-08-11 07:17:22 +00001257 int tags_count = 0;
Lev Walkin188ed2c2004-09-13 08:31:01 +00001258 int all_tags_count = 0;
1259 enum tvm_compat tv_mode = _TVM_SAME;
Lev Walkin906654e2004-09-10 15:49:15 +00001260 int i;
Lev Walkin27ea3802004-06-28 21:13:46 +00001261
Lev Walkin6d1220a2004-09-14 14:10:10 +00001262 /* Cleanup before proceeding. */
1263 *tags_count_r = 0;
1264 *all_tags_count_r = 0;
1265
Lev Walkin906654e2004-09-10 15:49:15 +00001266 /* Fetch a chain of tags */
Lev Walkina9cc46e2004-09-22 16:06:28 +00001267 tags_count = asn1f_fetch_tags(arg->asn, expr->module, expr, &tags, 0);
Lev Walkin6d1220a2004-09-14 14:10:10 +00001268 if(tags_count < 0)
1269 return -1;
Lev Walkin64399722004-08-11 07:17:22 +00001270
Lev Walkin188ed2c2004-09-13 08:31:01 +00001271 /* Fetch a chain of tags */
Lev Walkina9cc46e2004-09-22 16:06:28 +00001272 all_tags_count = asn1f_fetch_tags(arg->asn, expr->module, expr,
Lev Walkin188ed2c2004-09-13 08:31:01 +00001273 &all_tags, AFT_FULL_COLLECT);
1274 if(all_tags_count < 0) {
1275 if(tags) free(tags);
1276 return -1;
Lev Walkin5a8219a2004-09-08 00:28:57 +00001277 }
Lev Walkin906654e2004-09-10 15:49:15 +00001278
Lev Walkin188ed2c2004-09-13 08:31:01 +00001279 assert(tags_count <= all_tags_count);
1280 assert((tags_count?0:1) == (all_tags_count?0:1));
Lev Walkin27ea3802004-06-28 21:13:46 +00001281
Lev Walkin188ed2c2004-09-13 08:31:01 +00001282 if(tags_count <= all_tags_count) {
1283 for(i = 0; i < tags_count; i++) {
1284 if(tags[i].tag_value != all_tags[i].tag_value
1285 || tags[i].tag_class != all_tags[i].tag_class) {
1286 tv_mode = _TVM_DIFFERENT;
1287 break;
1288 }
1289 }
1290 if(i == tags_count && tags_count < all_tags_count)
1291 tv_mode = _TVM_SUBSET;
1292 } else {
1293 tv_mode = _TVM_DIFFERENT;
1294 }
1295
1296#define EMIT_TAGS_TABLE(name, tags, tags_count) do { \
Lev Walkin05363a72004-09-29 13:16:40 +00001297 OUT("static ber_tlv_tag_t asn_DEF_%s%s_tags[] = {\n", \
Lev Walkin188ed2c2004-09-13 08:31:01 +00001298 MKID(expr->Identifier), name); \
1299 INDENT(+1); \
1300 /* Print the array of collected tags */ \
1301 for(i = 0; i < tags_count; i++) { \
1302 if(i) OUT(",\n"); \
1303 _print_tag(arg, &tags[i]); \
1304 } \
1305 OUT("\n"); \
1306 INDENT(-1); \
1307 OUT("};\n"); \
1308 } while(0)
1309
1310 if(tags_count) {
1311 if(tv_mode == _TVM_SUBSET)
1312 EMIT_TAGS_TABLE("", all_tags, all_tags_count);
1313 else
1314 EMIT_TAGS_TABLE("", tags, tags_count);
1315 }
1316
1317 if(all_tags_count) {
1318 if(tv_mode == _TVM_DIFFERENT)
1319 EMIT_TAGS_TABLE("_all", all_tags, all_tags_count);
1320 }
1321
1322 if(tags) free(tags);
1323 if(all_tags) free(all_tags);
1324
1325 *tags_count_r = tags_count;
1326 *all_tags_count_r = all_tags_count;
1327
1328 return tv_mode;
Lev Walkin27ea3802004-06-28 21:13:46 +00001329}
Lev Walkin59004fa2004-08-20 13:37:01 +00001330
1331static int
Lev Walkin59964be2004-08-25 02:03:12 +00001332expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin59004fa2004-08-20 13:37:01 +00001333 asn1p_expr_t *topmost_parent;
1334 asn1p_expr_t *v;
1335 int elements = 0;
1336
Lev Walkina9cc46e2004-09-22 16:06:28 +00001337 topmost_parent = asn1f_find_terminal_type_ex(arg->asn, expr);
Lev Walkin59004fa2004-08-20 13:37:01 +00001338 if(!topmost_parent) return 0;
1339
1340 if(!(topmost_parent->expr_type & ASN_CONSTR_MASK))
1341 return 0;
1342
1343 TQ_FOR(v, &(topmost_parent->members), next) {
1344 if(v->expr_type != A1TC_EXTENSIBLE)
1345 elements++;
1346 }
1347
1348 return elements;
1349}
1350
1351static int
Lev Walkin59964be2004-08-25 02:03:12 +00001352emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin08079b02004-08-22 03:25:24 +00001353 static int global_memb_unique;
Lev Walkin59004fa2004-08-20 13:37:01 +00001354 int save_target;
1355 arg_t tmp_arg;
Lev Walkinb9189732004-09-10 09:37:12 +00001356 struct asn1p_type_tag_s outmost_tag_s;
1357 struct asn1p_type_tag_s *outmost_tag;
Lev Walkin59004fa2004-08-20 13:37:01 +00001358 char *p;
1359
Lev Walkinb9189732004-09-10 09:37:12 +00001360 if(asn1f_fetch_outmost_tag(arg->asn,
1361 expr->module, expr, &outmost_tag_s, 1)) {
1362 outmost_tag = 0;
1363 } else {
1364 outmost_tag = &outmost_tag_s;
1365 }
1366
Lev Walkin59004fa2004-08-20 13:37:01 +00001367 OUT("{ ");
Lev Walkinb9189732004-09-10 09:37:12 +00001368
1369 if(outmost_tag && outmost_tag->tag_value == -1)
1370 OUT("ATF_OPEN_TYPE | ");
Lev Walkin0204fa62004-09-15 11:54:38 +00001371 OUT("%s, ", expr->marker.flags?"ATF_POINTER":"ATF_NOFLAGS");
1372 if((expr->marker.flags & EM_OPTIONAL) == EM_OPTIONAL) {
Lev Walkin59004fa2004-08-20 13:37:01 +00001373 asn1p_expr_t *tv;
1374 int opts = 0;
Lev Walkin0204fa62004-09-15 11:54:38 +00001375 for(tv = expr; tv && tv->marker.flags;
Lev Walkin59004fa2004-08-20 13:37:01 +00001376 tv = TQ_NEXT(tv, next), opts++) {
1377 if(tv->expr_type == A1TC_EXTENSIBLE)
1378 opts--;
1379 }
1380 OUT("%d, ", opts);
1381 } else {
1382 OUT("0, ");
1383 }
Lev Walkina9cc46e2004-09-22 16:06:28 +00001384 if(expr->_anonymous_type) {
1385 assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
1386 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
1387 OUT("0,\n");
1388 } else {
Lev Walkin59004fa2004-08-20 13:37:01 +00001389 OUT("offsetof(struct %s, ", MKID(arg->expr->Identifier));
1390 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1391 && (!UNNAMED_UNIONS)) OUT("choice.");
1392 OUT("%s),\n", MKID(expr->Identifier));
Lev Walkin59004fa2004-08-20 13:37:01 +00001393 }
1394 INDENT(+1);
1395 if(C99_MODE) OUT(".tag = ");
Lev Walkinb9189732004-09-10 09:37:12 +00001396 if(outmost_tag) {
1397 if(outmost_tag->tag_value == -1)
1398 OUT("-1 /* Ambiguous tag (ANY?) */");
1399 else
1400 _print_tag(arg, outmost_tag);
Lev Walkinc3e29402004-09-10 06:07:18 +00001401 } else {
Lev Walkinb9189732004-09-10 09:37:12 +00001402 OUT("-1 /* Ambiguous tag (CHOICE?) */");
Lev Walkinc3e29402004-09-10 06:07:18 +00001403 }
Lev Walkinb9189732004-09-10 09:37:12 +00001404
Lev Walkin59004fa2004-08-20 13:37:01 +00001405 OUT(",\n");
1406 if(C99_MODE) OUT(".tag_mode = ");
1407 if(expr->tag.tag_class) {
1408 if(expr->tag.tag_mode == TM_IMPLICIT)
1409 OUT("-1,\t/* IMPLICIT tag at current level */\n");
1410 else
1411 OUT("+1,\t/* EXPLICIT tag at current level */\n");
1412 } else {
1413 OUT("0,\n");
1414 }
1415 if(C99_MODE) OUT(".type = ");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001416 if(expr->_anonymous_type && (expr->expr_type & ASN_CONSTR_MASK)) {
Lev Walkin05363a72004-09-29 13:16:40 +00001417 OUT("(void *)&asn_DEF_%s_member,\n",
Lev Walkin08079b02004-08-22 03:25:24 +00001418 MKID(arg->expr->Identifier));
Lev Walkin59964be2004-08-25 02:03:12 +00001419 } else if(expr->expr_type & ASN_CONSTR_MASK) {
Lev Walkin05363a72004-09-29 13:16:40 +00001420 OUT("(void *)&asn_DEF_%s,\n",
Lev Walkin59964be2004-08-25 02:03:12 +00001421 MKID(expr->Identifier));
Lev Walkin08079b02004-08-22 03:25:24 +00001422 } else {
Lev Walkin05363a72004-09-29 13:16:40 +00001423 OUT("(void *)&asn_DEF_%s,\n",
Lev Walkin08079b02004-08-22 03:25:24 +00001424 asn1c_type_name(arg, expr, TNF_SAFE));
1425 }
Lev Walkin59004fa2004-08-20 13:37:01 +00001426 if(C99_MODE) OUT(".memb_constraints = ");
1427 if(expr->constraints) {
Lev Walkin8de2ab22004-09-26 13:11:31 +00001428 if(arg->flags & A1C_NO_CONSTRAINTS) {
1429 OUT("0,\t/* No check because of -fno-constraints */\n");
1430 } else {
1431 char *id = MKID(expr->Identifier);
1432 if(expr->_anonymous_type
1433 && !strcmp(expr->Identifier, "member"))
1434 id = asn1c_type_name(arg, expr, TNF_SAFE);
1435 OUT("memb_%s_%d_constraint,\n", id,
1436 ++global_memb_unique);
1437 }
Lev Walkin59004fa2004-08-20 13:37:01 +00001438 } else {
1439 OUT("0,\t/* Defer to actual type */\n");
1440 }
1441 if(C99_MODE) OUT(".name = ");
Lev Walkina9cc46e2004-09-22 16:06:28 +00001442 OUT("\"%s\"\n", expr->_anonymous_type ? "" : expr->Identifier);
Lev Walkin59004fa2004-08-20 13:37:01 +00001443 OUT("},\n");
1444 INDENT(-1);
1445
Lev Walkin8de2ab22004-09-26 13:11:31 +00001446 if(!expr->constraints || (arg->flags & A1C_NO_CONSTRAINTS))
Lev Walkin59004fa2004-08-20 13:37:01 +00001447 return 0;
1448
1449 save_target = arg->target->target;
1450 REDIR(OT_CODE);
1451
Lev Walkina9cc46e2004-09-22 16:06:28 +00001452 if(expr->_anonymous_type && !strcmp(expr->Identifier, "member"))
Lev Walkin59004fa2004-08-20 13:37:01 +00001453 p = asn1c_type_name(arg, expr, TNF_SAFE);
Lev Walkina9cc46e2004-09-22 16:06:28 +00001454 else
1455 p = MKID(expr->Identifier);
Lev Walkin59004fa2004-08-20 13:37:01 +00001456 OUT("static int\n");
Lev Walkin05363a72004-09-29 13:16:40 +00001457 OUT("memb_%s_%d_constraint(asn_TYPE_descriptor_t *td, const void *sptr,\n", p, global_memb_unique);
Lev Walkin59004fa2004-08-20 13:37:01 +00001458 INDENT(+1);
1459 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
1460 tmp_arg = *arg;
1461 tmp_arg.expr = expr;
1462 if(asn1c_emit_constraint_checking_code(&tmp_arg) == 1) {
Lev Walkin8de2ab22004-09-26 13:11:31 +00001463 OUT("return td->check_constraints"
1464 "(td, sptr, app_errlog, app_key);\n");
Lev Walkin59004fa2004-08-20 13:37:01 +00001465 }
1466 INDENT(-1);
1467 OUT("}\n");
1468 OUT("\n");
1469
1470 REDIR(save_target);
1471
1472 return 0;
1473}
Lev Walkin59964be2004-08-25 02:03:12 +00001474
1475static int
Lev Walkin8de2ab22004-09-26 13:11:31 +00001476emit_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 Walkin59964be2004-08-25 02:03:12 +00001477 char *p;
1478
1479 p = MKID(expr->Identifier);
Lev Walkindd32b592004-09-06 08:07:29 +00001480 if(HIDE_INNER_DEFS)
1481 OUT("static /* Use -fall-defs-global to expose */\n");
Lev Walkin05363a72004-09-29 13:16:40 +00001482 OUT("asn_TYPE_descriptor_t asn_DEF_%s = {\n", p);
Lev Walkin188ed2c2004-09-13 08:31:01 +00001483 INDENT(+1);
Lev Walkin59964be2004-08-25 02:03:12 +00001484 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
1485
1486 if(expr->expr_type & ASN_CONSTR_MASK) {
1487 p = asn1c_type_name(arg, arg->expr, TNF_SAFE);
1488 }
1489
Lev Walkina9cc46e2004-09-22 16:06:28 +00001490 OUT("%s_free,\n", p);
1491 OUT("%s_print,\n", p);
Lev Walkin59964be2004-08-25 02:03:12 +00001492 OUT("%s_constraint,\n", p);
1493 OUT("%s_decode_ber,\n", p);
1494 OUT("%s_encode_der,\n", p);
Lev Walkina9cc46e2004-09-22 16:06:28 +00001495 OUT("0, /* Not implemented yet */\n");
1496 OUT("%s_encode_xer,\n", p);
Lev Walkin59964be2004-08-25 02:03:12 +00001497
1498 p = MKID(expr->Identifier);
1499
1500 if(expr->expr_type == ASN_CONSTR_CHOICE) {
1501 OUT("CHOICE_outmost_tag,\n");
1502 } else {
1503 OUT("0,\t/* Use generic outmost tag fetcher */\n");
1504 }
1505
1506 if(tags_count) {
Lev Walkin05363a72004-09-29 13:16:40 +00001507 OUT("asn_DEF_%s_tags,\n", p);
1508 OUT("sizeof(asn_DEF_%s_tags)\n", p);
1509 OUT("\t/sizeof(asn_DEF_%s_tags[0])", p);
Lev Walkin188ed2c2004-09-13 08:31:01 +00001510 if(tv_mode == _TVM_SUBSET
1511 && tags_count != all_tags_count)
1512 OUT(" - %d", all_tags_count - tags_count);
1513 OUT(", /* %d */\n", tags_count);
Lev Walkin59964be2004-08-25 02:03:12 +00001514 } else {
Lev Walkin188ed2c2004-09-13 08:31:01 +00001515 OUT("0,\t/* No effective tags (pointer) */\n");
1516 OUT("0,\t/* No effective tags (count) */\n");
1517 }
1518
1519 if(all_tags_count && tv_mode == _TVM_DIFFERENT) {
Lev Walkin05363a72004-09-29 13:16:40 +00001520 OUT("asn_DEF_%s_all_tags,\n", p);
1521 OUT("sizeof(asn_DEF_%s_all_tags)\n", p);
1522 OUT("\t/sizeof(asn_DEF_%s_all_tags[0]), /* %d */\n",
Lev Walkin188ed2c2004-09-13 08:31:01 +00001523 p, all_tags_count);
1524 } else if(all_tags_count) {
Lev Walkin05363a72004-09-29 13:16:40 +00001525 OUT("asn_DEF_%s_tags,\t/* Same as above */\n", p);
1526 OUT("sizeof(asn_DEF_%s_tags)\n", p);
1527 OUT("\t/sizeof(asn_DEF_%s_tags[0]), /* %d */\n",
Lev Walkin188ed2c2004-09-13 08:31:01 +00001528 p, all_tags_count);
1529 } else {
1530 OUT("0,\t/* No tags (pointer) */\n");
1531 OUT("0,\t/* No tags (count) */\n");
Lev Walkin59964be2004-08-25 02:03:12 +00001532 }
1533
Lev Walkin59964be2004-08-25 02:03:12 +00001534 if(elements_count) {
Lev Walkin05363a72004-09-29 13:16:40 +00001535 OUT("asn_MBR_%s,\n", p);
Lev Walkin59964be2004-08-25 02:03:12 +00001536 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF
1537 || expr->expr_type == ASN_CONSTR_SET_OF) {
1538 OUT("%d,\t/* Single element */\n",
1539 elements_count);
1540 assert(elements_count == 1);
1541 } else {
1542 OUT("%d,\t/* Elements count */\n",
1543 elements_count);
1544 }
1545 } else {
1546 //if(expr->meta_type == AMT_TYPEREF)
1547 if(expr_elements_count(arg, expr))
1548 OUT("0, 0,\t/* Defined elsewhere */\n");
1549 else
1550 OUT("0, 0,\t/* No members */\n");
1551 }
1552
1553 switch(spec) {
1554 case ETD_NO_SPECIFICS:
1555 OUT("0\t/* No specifics */\n");
1556 break;
1557 case ETD_HAS_SPECIFICS:
Lev Walkin05363a72004-09-29 13:16:40 +00001558 OUT("&asn_DEF_%s_specs\t/* Additional specs */\n", p);
Lev Walkin59964be2004-08-25 02:03:12 +00001559 }
Lev Walkin188ed2c2004-09-13 08:31:01 +00001560 INDENT(-1);
Lev Walkin59964be2004-08-25 02:03:12 +00001561 OUT("};\n");
1562 OUT("\n");
Lev Walkin97298782004-08-26 06:20:34 +00001563
1564 return 0;
Lev Walkin59964be2004-08-25 02:03:12 +00001565}
Lev Walkincc93b0f2004-09-10 09:18:20 +00001566
1567/*
1568 * Check if it is better to make this type indirectly accessed via
1569 * a pointer.
1570 * This may be the case for the following recursive definition:
1571 * Type ::= CHOICE { member Type };
1572 */
1573static int
1574expr_better_indirect(arg_t *arg, asn1p_expr_t *expr) {
1575 asn1p_expr_t *top_parent;
1576 asn1p_expr_t *terminal;
1577
1578 if(expr->expr_type != A1TC_REFERENCE)
1579 return 0;
1580
1581 /* Rewind to the topmost parent expression */
1582 if((top_parent = expr->parent_expr)) {
1583 while(top_parent->parent_expr)
1584 top_parent = top_parent->parent_expr;
1585 } else {
1586 return 0;
1587 }
1588
Lev Walkina9cc46e2004-09-22 16:06:28 +00001589 terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
Lev Walkincc93b0f2004-09-10 09:18:20 +00001590
1591 return (terminal == top_parent);
1592}
Lev Walkina9cc46e2004-09-22 16:06:28 +00001593
1594static int
1595expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr) {
1596 expr = asn1f_find_terminal_type_ex(arg->asn, expr);
1597 if(!expr) return 0;
1598
1599 /* X.680, 25.5, Table 5 */
1600 switch(expr->expr_type) {
1601 case ASN_CONSTR_CHOICE:
1602 case ASN_BASIC_BOOLEAN:
1603 case ASN_BASIC_ENUMERATED:
1604 case ASN_BASIC_NULL:
1605 return 1;
1606 default:
1607 return 0;
1608 }
1609}