blob: 5b9eae69548349cba0ad850503790b879214f618 [file] [log] [blame]
vlmfa67ddc2004-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"
vlm1d036692004-08-19 13:29:46 +00007#include "asn1c_constraint.h"
vlmb2839012004-08-20 13:37:01 +00008#include "asn1c_out.h"
9#include "asn1c_misc.h"
vlm1d036692004-08-19 13:29:46 +000010#include <asn1fix_export.h> /* Stuff exported by libasn1fix */
vlmfa67ddc2004-06-03 03:38:44 +000011
vlm4e03ce22004-06-06 07:20:17 +000012typedef struct tag2el_s {
13 struct asn1p_type_tag_s el_tag;
14 int el_no;
vlmc8aeab42004-06-14 13:09:45 +000015 int toff_first;
16 int toff_last;
vlm4e03ce22004-06-06 07:20:17 +000017 asn1p_expr_t *from_expr;
18} tag2el_t;
19
vlm940bc6b2004-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);
vlm4e03ce22004-06-06 07:20:17 +000026
vlmfa67ddc2004-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);
vlma8a86cc2004-09-10 06:07:18 +000031static int _print_tag(arg_t *arg, struct asn1p_type_tag_s *tag_p);
vlm79b08d52004-07-01 00:52:50 +000032static int check_if_extensible(asn1p_expr_t *expr);
vlmddd5a7d2004-09-10 09:18:20 +000033static int expr_better_indirect(arg_t *arg, asn1p_expr_t *expr);
vlm39ba4c42004-09-22 16:06:28 +000034static int expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr);
vlm4e554992004-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);
vlm940bc6b2004-10-03 09:13:30 +000037static int emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier);
vlmfa67ddc2004-06-03 03:38:44 +000038
vlm72425de2004-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
vlm4e554992004-08-25 02:03:12 +000046enum etd_spec {
47 ETD_NO_SPECIFICS,
48 ETD_HAS_SPECIFICS
49};
vlm86f5ed22004-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);
vlm4e554992004-08-25 02:03:12 +000051
vlmb2839012004-08-20 13:37:01 +000052#define C99_MODE (!(arg->flags & A1C_NO_C99))
vlmfa67ddc2004-06-03 03:38:44 +000053#define UNNAMED_UNIONS (arg->flags & A1C_UNNAMED_UNIONS)
vlm12c8f692004-09-06 08:07:29 +000054#define HIDE_INNER_DEFS (arg->embed && !(arg->flags & A1C_ALL_DEFS_GLOBAL))
vlmfa67ddc2004-06-03 03:38:44 +000055
56#define PCTX_DEF INDENTED( \
57 OUT("\n"); \
58 OUT("/* Context for parsing across buffer boundaries */\n"); \
vlma5dcb912004-09-29 13:16:40 +000059 OUT("asn_struct_ctx_t _asn_ctx;\n"));
vlmfa67ddc2004-06-03 03:38:44 +000060
vlm33a4ff12004-08-11 05:21:32 +000061#define DEPENDENCIES do { \
vlmdae7f9d2004-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)); \
vlm33a4ff12004-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)
vlmfa67ddc2004-06-03 03:38:44 +000076
77#define MKID(id) asn1c_make_identifier(0, (id), 0)
78
79int
vlmf9d178d2004-09-14 12:47:45 +000080asn1c_lang_C_type_REAL(arg_t *arg) {
vlmfa67ddc2004-06-03 03:38:44 +000081 REDIR(OT_DEPS);
vlmfa67ddc2004-06-03 03:38:44 +000082 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
83}
84
vlmfa67ddc2004-06-03 03:38:44 +000085int
vlmf9d178d2004-09-14 12:47:45 +000086asn1c_lang_C_type_common_INTEGER(arg_t *arg) {
vlmfa67ddc2004-06-03 03:38:44 +000087 asn1p_expr_t *expr = arg->expr;
88 asn1p_expr_t *v;
89
90 REDIR(OT_DEPS);
91
vlmf9d178d2004-09-14 12:47:45 +000092 if(expr->expr_type == ASN_BASIC_ENUMERATED
93 || TQ_FIRST(&(expr->members))
94 ) {
vlmfa67ddc2004-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:
vlm47ae1582004-09-24 21:01:43 +000099 OUT("\t%s\t= %" PRIdASN ",\n",
vlmfa67ddc2004-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;
vlmf9d178d2004-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;
vlmfa67ddc2004-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) {
vlmdae7f9d2004-08-22 03:25:24 +0000129 OUT("struct %s {\n", MKID(expr->Identifier));
vlmfa67ddc2004-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 }
vlmddd5a7d2004-09-10 09:18:20 +0000139 if(comp_mode == 1
140 || expr_better_indirect(arg, v))
vlma02b74d2004-09-15 11:54:38 +0000141 v->marker.flags |= EM_INDIRECT;
vlmfa67ddc2004-06-03 03:38:44 +0000142 EMBED(v);
143 }
144
145 PCTX_DEF;
vlma02b74d2004-09-15 11:54:38 +0000146 OUT("} %s%s%s", expr->marker.flags?"*":"",
vlmdae7f9d2004-08-22 03:25:24 +0000147 expr->_anonymous_type ? "" : MKID(expr->Identifier),
148 arg->embed ? "" : "_t");
vlmfa67ddc2004-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 */
vlmfa67ddc2004-06-03 03:38:44 +0000158 int ext_start = -1;
159 int ext_stop = -1;
vlm4e03ce22004-06-06 07:20:17 +0000160 tag2el_t *tag2el = NULL;
161 int tag2el_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000162 int tags_count;
vlm72425de2004-09-13 08:31:01 +0000163 int all_tags_count;
164 enum tvm_compat tv_mode;
vlmfa67ddc2004-06-03 03:38:44 +0000165 char *p;
166
vlm4e03ce22004-06-06 07:20:17 +0000167 /*
168 * Fetch every inner tag from the tag to elements map.
169 */
vlm940bc6b2004-10-03 09:13:30 +0000170 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
vlm4e03ce22004-06-06 07:20:17 +0000171 if(tag2el) free(tag2el);
172 return -1;
173 }
174
vlm33a4ff12004-08-11 05:21:32 +0000175 GEN_INCLUDE("constr_SEQUENCE");
176 if(!arg->embed)
vlma5dcb912004-09-29 13:16:40 +0000177 GEN_DECLARE(expr); /* asn_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000178
vlm33a4ff12004-08-11 05:21:32 +0000179 REDIR(OT_STAT_DEFS);
vlmfa67ddc2004-06-03 03:38:44 +0000180
181 /*
182 * Print out the table according to which the parsing is performed.
183 */
vlm39ba4c42004-09-22 16:06:28 +0000184 if(expr_elements_count(arg, expr)) {
185 int comp_mode = 0; /* {root,ext=1,root,root,...} */
vlmfa67ddc2004-06-03 03:38:44 +0000186
vlm39ba4c42004-09-22 16:06:28 +0000187 p = MKID(expr->Identifier);
vlma5dcb912004-09-29 13:16:40 +0000188 OUT("static asn_TYPE_member_t asn_MBR_%s[] = {\n", p);
vlm39ba4c42004-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 }
vlmfa67ddc2004-06-03 03:38:44 +0000206
vlm4a3f5822004-06-28 21:13:46 +0000207 /*
vlma5dcb912004-09-29 13:16:40 +0000208 * Print out asn_DEF_<type>_[all_]tags[] vectors.
vlm4a3f5822004-06-28 21:13:46 +0000209 */
vlm72425de2004-09-13 08:31:01 +0000210 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
vlmfa67ddc2004-06-03 03:38:44 +0000211
vlm4e03ce22004-06-06 07:20:17 +0000212 /*
213 * Tags to elements map.
214 */
vlm940bc6b2004-10-03 09:13:30 +0000215 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
vlm4e03ce22004-06-06 07:20:17 +0000216
vlm4a3f5822004-06-28 21:13:46 +0000217 p = MKID(expr->Identifier);
vlma5dcb912004-09-29 13:16:40 +0000218 OUT("static asn_SEQUENCE_specifics_t asn_DEF_%s_specs = {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000219 INDENTED(
220 OUT("sizeof(struct %s),\n", p);
vlma5dcb912004-09-29 13:16:40 +0000221 OUT("offsetof(struct %s, _asn_ctx),\n", p);
222 OUT("asn_DEF_%s_tag2el,\n", p);
vlm4e03ce22004-06-06 07:20:17 +0000223 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
vlmfa67ddc2004-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");
vlm4e554992004-08-25 02:03:12 +0000230
231 /*
vlma5dcb912004-09-29 13:16:40 +0000232 * Emit asn_DEF_xxx table.
vlm4e554992004-08-25 02:03:12 +0000233 */
vlm72425de2004-09-13 08:31:01 +0000234 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
vlm86f5ed22004-09-26 13:11:31 +0000235 ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000236
vlmfa67ddc2004-06-03 03:38:44 +0000237 REDIR(OT_TYPE_DECLS);
238
239 return 0;
240}
241
242int
vlmfa67ddc2004-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;
vlm6e73a042004-08-11 07:17:22 +0000259 OUT("typedef enum %s_PR {\n", MKID(expr->Identifier));
vlmfa67ddc2004-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 }
vlm6e73a042004-08-11 07:17:22 +0000271 id = MKID(expr->Identifier);
272 OUT("} %s_PR;\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000273
274 REDIR(OT_TYPE_DECLS);
275
276 if(arg->embed) {
vlm6e73a042004-08-11 07:17:22 +0000277 OUT("struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000278 } else {
vlm6e73a042004-08-11 07:17:22 +0000279 OUT("typedef struct %s {\n", id);
vlmfa67ddc2004-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 }
vlmddd5a7d2004-09-10 09:18:20 +0000286 if(comp_mode == 1
287 || expr_better_indirect(arg, v))
vlma02b74d2004-09-15 11:54:38 +0000288 v->marker.flags |= EM_INDIRECT;
vlmfa67ddc2004-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;
vlma02b74d2004-09-15 11:54:38 +0000302 OUT("} %s%s%s", expr->marker.flags?"*":"",
vlmdae7f9d2004-08-22 03:25:24 +0000303 expr->_anonymous_type ? "" : MKID(expr->Identifier),
304 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000305
306 return asn1c_lang_C_type_SET_def(arg);
307}
308
vlmfa67ddc2004-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;
vlmfa67ddc2004-06-03 03:38:44 +0000314 tag2el_t *tag2el = NULL;
315 int tag2el_count = 0;
vlm940bc6b2004-10-03 09:13:30 +0000316 tag2el_t *tag2el_cxer = NULL;
317 int tag2el_cxer_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000318 int tags_count;
vlm72425de2004-09-13 08:31:01 +0000319 int all_tags_count;
320 enum tvm_compat tv_mode;
vlmfa67ddc2004-06-03 03:38:44 +0000321 char *p;
322
323 /*
324 * Fetch every inner tag from the tag to elements map.
325 */
vlm940bc6b2004-10-03 09:13:30 +0000326 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
vlmfa67ddc2004-06-03 03:38:44 +0000327 if(tag2el) free(tag2el);
328 return -1;
vlmfa67ddc2004-06-03 03:38:44 +0000329 }
vlm940bc6b2004-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 }
vlmfa67ddc2004-06-03 03:38:44 +0000340
vlm33a4ff12004-08-11 05:21:32 +0000341 GEN_INCLUDE("constr_SET");
342 if(!arg->embed)
vlma5dcb912004-09-29 13:16:40 +0000343 GEN_DECLARE(expr); /* asn_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000344
345 REDIR(OT_STAT_DEFS);
346
vlmfa67ddc2004-06-03 03:38:44 +0000347 /*
348 * Print out the table according to which the parsing is performed.
349 */
vlm39ba4c42004-09-22 16:06:28 +0000350 if(expr_elements_count(arg, expr)) {
351 int comp_mode = 0; /* {root,ext=1,root,root,...} */
vlmfa67ddc2004-06-03 03:38:44 +0000352
vlm39ba4c42004-09-22 16:06:28 +0000353 p = MKID(expr->Identifier);
vlma5dcb912004-09-29 13:16:40 +0000354 OUT("static asn_TYPE_member_t asn_MBR_%s[] = {\n", p);
vlm39ba4c42004-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 }
vlmfa67ddc2004-06-03 03:38:44 +0000372
vlm4a3f5822004-06-28 21:13:46 +0000373 /*
vlma5dcb912004-09-29 13:16:40 +0000374 * Print out asn_DEF_<type>_[all_]tags[] vectors.
vlm4a3f5822004-06-28 21:13:46 +0000375 */
vlm72425de2004-09-13 08:31:01 +0000376 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
vlmfa67ddc2004-06-03 03:38:44 +0000377
378 /*
379 * Tags to elements map.
380 */
vlm940bc6b2004-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");
vlmfa67ddc2004-06-03 03:38:44 +0000384
385 /*
386 * Emit a map of mandatory elements.
387 */
vlm4a3f5822004-06-28 21:13:46 +0000388 p = MKID(expr->Identifier);
vlma5dcb912004-09-29 13:16:40 +0000389 OUT("static uint8_t asn_DEF_%s_mmap", p);
vlmfa67ddc2004-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 }
vlmddd5a7d2004-09-10 09:18:20 +0000404 OUT("(%d << %d)",
vlma02b74d2004-09-15 11:54:38 +0000405 v->marker.flags?0:1,
vlmddd5a7d2004-09-10 09:18:20 +0000406 7 - (el % 8));
vlmfa67ddc2004-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
vlma5dcb912004-09-29 13:16:40 +0000418 OUT("static asn_SET_specifics_t asn_DEF_%s_specs = {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000419 INDENTED(
420 OUT("sizeof(struct %s),\n", p);
vlma5dcb912004-09-29 13:16:40 +0000421 OUT("offsetof(struct %s, _asn_ctx),\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000422 OUT("offsetof(struct %s, _presence_map),\n", p);
vlma5dcb912004-09-29 13:16:40 +0000423 OUT("asn_DEF_%s_tag2el,\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000424 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
vlm940bc6b2004-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);
vlm79b08d52004-07-01 00:52:50 +0000430 OUT("%d,\t/* Whether extensible */\n",
431 check_if_extensible(expr));
vlma5dcb912004-09-29 13:16:40 +0000432 OUT("(unsigned int *)asn_DEF_%s_mmap\t/* Mandatory elements map */\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000433 );
434 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000435
436 /*
vlma5dcb912004-09-29 13:16:40 +0000437 * Emit asn_DEF_xxx table.
vlm4e554992004-08-25 02:03:12 +0000438 */
vlm72425de2004-09-13 08:31:01 +0000439 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
vlm86f5ed22004-09-26 13:11:31 +0000440 ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000441
vlmfa67ddc2004-06-03 03:38:44 +0000442 REDIR(OT_TYPE_DECLS);
443
444 return 0;
445}
446
447int
vlmdae7f9d2004-08-22 03:25:24 +0000448asn1c_lang_C_type_SEx_OF(arg_t *arg) {
vlmfa67ddc2004-06-03 03:38:44 +0000449 asn1p_expr_t *expr = arg->expr;
vlmdae7f9d2004-08-22 03:25:24 +0000450 asn1p_expr_t *memb;
vlmfa67ddc2004-06-03 03:38:44 +0000451
452 DEPENDENCIES;
453
454 if(arg->embed) {
455 OUT("struct %s {\n", MKID(expr->Identifier));
456 } else {
vlmdae7f9d2004-08-22 03:25:24 +0000457 OUT("typedef struct %s {\n", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000458 }
459
vlmdae7f9d2004-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;
vlm39ba4c42004-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 }
vlmdae7f9d2004-08-22 03:25:24 +0000480 tmp.default_cb(&tmp);
vlm39ba4c42004-09-22 16:06:28 +0000481 if(tmp_memb.Identifier != memb->Identifier)
482 free(tmp_memb.Identifier);
vlmdae7f9d2004-08-22 03:25:24 +0000483 arg->embed--;
484 assert(arg->target->target == OT_TYPE_DECLS);
485 } else {
vlmb47f48e2004-09-17 06:32:12 +0000486 OUT("%s", asn1c_type_name(arg, memb, TNF_CTYPE));
vlmfa67ddc2004-06-03 03:38:44 +0000487 }
vlmdae7f9d2004-08-22 03:25:24 +0000488 OUT(") list;\n");
489 INDENT(-1);
vlmfa67ddc2004-06-03 03:38:44 +0000490
491 PCTX_DEF;
vlma02b74d2004-09-15 11:54:38 +0000492 OUT("} %s%s%s", expr->marker.flags?"*":"",
vlmdae7f9d2004-08-22 03:25:24 +0000493 expr->_anonymous_type ? "" : MKID(expr->Identifier),
494 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000495
496 /*
vlmdae7f9d2004-08-22 03:25:24 +0000497 * SET OF/SEQUENCE OF definition
vlmfa67ddc2004-06-03 03:38:44 +0000498 */
vlmdae7f9d2004-08-22 03:25:24 +0000499 return asn1c_lang_C_type_SEx_OF_def(arg,
500 (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF));
vlmfa67ddc2004-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;
vlm6e73a042004-08-11 07:17:22 +0000507 int tags_count;
vlm72425de2004-09-13 08:31:01 +0000508 int all_tags_count;
509 enum tvm_compat tv_mode;
vlmfa67ddc2004-06-03 03:38:44 +0000510 char *p;
511
vlm33a4ff12004-08-11 05:21:32 +0000512 /*
513 * Print out the table according to which the parsing is performed.
514 */
vlmfa67ddc2004-06-03 03:38:44 +0000515 if(seq_of) {
vlm33a4ff12004-08-11 05:21:32 +0000516 GEN_INCLUDE("constr_SEQUENCE_OF");
vlmfa67ddc2004-06-03 03:38:44 +0000517 } else {
vlm33a4ff12004-08-11 05:21:32 +0000518 GEN_INCLUDE("constr_SET_OF");
vlmfa67ddc2004-06-03 03:38:44 +0000519 }
vlm33a4ff12004-08-11 05:21:32 +0000520 if(!arg->embed)
vlma5dcb912004-09-29 13:16:40 +0000521 GEN_DECLARE(expr); /* asn_DEF_xxx */
vlmfa67ddc2004-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);
vlma5dcb912004-09-29 13:16:40 +0000529 OUT("static asn_TYPE_member_t asn_MBR_%s[] = {\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000530 INDENT(+1);
vlmfa67ddc2004-06-03 03:38:44 +0000531 v = TQ_FIRST(&(expr->members));
vlm39ba4c42004-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++;
vlm4e554992004-08-25 02:03:12 +0000538 emit_member_table(arg, v);
vlm39ba4c42004-09-22 16:06:28 +0000539 arg->embed--;
540 INDENT(-1);
vlmfa67ddc2004-06-03 03:38:44 +0000541 OUT("};\n");
542
vlm4a3f5822004-06-28 21:13:46 +0000543 /*
vlma5dcb912004-09-29 13:16:40 +0000544 * Print out asn_DEF_<type>_[all_]tags[] vectors.
vlm4a3f5822004-06-28 21:13:46 +0000545 */
vlm72425de2004-09-13 08:31:01 +0000546 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
vlmfa67ddc2004-06-03 03:38:44 +0000547
vlm4a3f5822004-06-28 21:13:46 +0000548 p = MKID(expr->Identifier);
vlma5dcb912004-09-29 13:16:40 +0000549 OUT("static asn_SET_OF_specifics_t asn_DEF_%s_specs = {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000550 INDENTED(
551 OUT("sizeof(struct %s),\n", p);
vlma5dcb912004-09-29 13:16:40 +0000552 OUT("offsetof(struct %s, _asn_ctx),\n", p);
vlm39ba4c42004-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");
vlmfa67ddc2004-06-03 03:38:44 +0000557 );
558 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000559
560 /*
vlma5dcb912004-09-29 13:16:40 +0000561 * Emit asn_DEF_xxx table.
vlm4e554992004-08-25 02:03:12 +0000562 */
vlm72425de2004-09-13 08:31:01 +0000563 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, 1,
vlm86f5ed22004-09-26 13:11:31 +0000564 ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000565
vlmfa67ddc2004-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;
vlmdae7f9d2004-08-22 03:25:24 +0000575 char *id;
vlmfa67ddc2004-06-03 03:38:44 +0000576
577 DEPENDENCIES;
578
vlm33a4ff12004-08-11 05:21:32 +0000579 REDIR(OT_DEPS);
580
vlmdae7f9d2004-08-22 03:25:24 +0000581 id = MKID(expr->Identifier);
582 OUT("typedef enum %s_PR {\n", id);
vlm33a4ff12004-08-11 05:21:32 +0000583 INDENTED(
vlm33a4ff12004-08-11 05:21:32 +0000584 OUT("%s_PR_NOTHING,\t"
vlmdae7f9d2004-08-22 03:25:24 +0000585 "/* No components present */\n", id);
vlm33a4ff12004-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 }
vlmdae7f9d2004-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);
vlm33a4ff12004-08-11 05:21:32 +0000595 }
596 );
vlmdae7f9d2004-08-22 03:25:24 +0000597 id = MKID(expr->Identifier);
598 OUT("} %s_PR;\n", id);
vlm33a4ff12004-08-11 05:21:32 +0000599
600 REDIR(OT_TYPE_DECLS);
vlmfa67ddc2004-06-03 03:38:44 +0000601
602 if(arg->embed) {
vlmdae7f9d2004-08-22 03:25:24 +0000603 OUT("struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000604 } else {
vlmdae7f9d2004-08-22 03:25:24 +0000605 OUT("typedef struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000606 }
607
608 INDENTED(
vlmdae7f9d2004-08-22 03:25:24 +0000609 OUT("%s_PR present;\n", id);
610 OUT("union {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000611 TQ_FOR(v, &(expr->members), next) {
vlmddd5a7d2004-09-10 09:18:20 +0000612 if(expr_better_indirect(arg, v))
vlma02b74d2004-09-15 11:54:38 +0000613 v->marker.flags |= EM_INDIRECT;
vlmfa67ddc2004-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;
vlma02b74d2004-09-15 11:54:38 +0000621 OUT("} %s%s%s", expr->marker.flags?"*":"",
vlmdae7f9d2004-08-22 03:25:24 +0000622 expr->_anonymous_type ? "" : MKID(expr->Identifier),
623 arg->embed ? "" : "_t");
vlmfa67ddc2004-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 */
vlmfa67ddc2004-06-03 03:38:44 +0000633 tag2el_t *tag2el = NULL;
634 int tag2el_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000635 int tags_count;
vlm72425de2004-09-13 08:31:01 +0000636 int all_tags_count;
637 enum tvm_compat tv_mode;
vlmfa67ddc2004-06-03 03:38:44 +0000638 char *p;
639
640 /*
641 * Fetch every inner tag from the tag to elements map.
642 */
vlm940bc6b2004-10-03 09:13:30 +0000643 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
vlmfa67ddc2004-06-03 03:38:44 +0000644 if(tag2el) free(tag2el);
645 return -1;
vlmfa67ddc2004-06-03 03:38:44 +0000646 }
647
vlm33a4ff12004-08-11 05:21:32 +0000648 GEN_INCLUDE("constr_CHOICE");
649 if(!arg->embed)
vlma5dcb912004-09-29 13:16:40 +0000650 GEN_DECLARE(expr); /* asn_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000651
vlm33a4ff12004-08-11 05:21:32 +0000652 REDIR(OT_STAT_DEFS);
vlmfa67ddc2004-06-03 03:38:44 +0000653
654 /*
655 * Print out the table according to which the parsing is performed.
656 */
vlm39ba4c42004-09-22 16:06:28 +0000657 if(expr_elements_count(arg, expr)) {
658 int comp_mode = 0; /* {root,ext=1,root,root,...} */
vlmfa67ddc2004-06-03 03:38:44 +0000659
vlm39ba4c42004-09-22 16:06:28 +0000660 p = MKID(expr->Identifier);
vlma5dcb912004-09-29 13:16:40 +0000661 OUT("static asn_TYPE_member_t asn_MBR_%s[] = {\n", p);
vlm39ba4c42004-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 }
vlmfa67ddc2004-06-03 03:38:44 +0000679
vlm6e73a042004-08-11 07:17:22 +0000680
vlmfa67ddc2004-06-03 03:38:44 +0000681 if(arg->embed) {
682 /*
683 * Our parent structure has already taken this into account.
684 */
vlm72425de2004-09-13 08:31:01 +0000685 tv_mode = _TVM_SAME;
686 tags_count = all_tags_count = 0;
vlmfa67ddc2004-06-03 03:38:44 +0000687 } else {
vlm72425de2004-09-13 08:31:01 +0000688 tv_mode = emit_tags_vectors(arg, expr,
689 &tags_count, &all_tags_count);
vlmfa67ddc2004-06-03 03:38:44 +0000690 }
vlmfa67ddc2004-06-03 03:38:44 +0000691
692 /*
693 * Tags to elements map.
694 */
vlm940bc6b2004-10-03 09:13:30 +0000695 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000696
vlm6e73a042004-08-11 07:17:22 +0000697 p = MKID(expr->Identifier);
vlma5dcb912004-09-29 13:16:40 +0000698 OUT("static asn_CHOICE_specifics_t asn_DEF_%s_specs = {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000699 INDENTED(
700 OUT("sizeof(struct %s),\n", p);
vlma5dcb912004-09-29 13:16:40 +0000701 OUT("offsetof(struct %s, _asn_ctx),\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000702 OUT("offsetof(struct %s, present),\n", p);
703 OUT("sizeof(((struct %s *)0)->present),\n", p);
vlma5dcb912004-09-29 13:16:40 +0000704 OUT("asn_DEF_%s_tag2el,\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000705 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
vlm79b08d52004-07-01 00:52:50 +0000706 OUT("%d\t/* Whether extensible */\n",
707 check_if_extensible(expr));
vlmfa67ddc2004-06-03 03:38:44 +0000708 );
709 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000710
711 /*
vlma5dcb912004-09-29 13:16:40 +0000712 * Emit asn_DEF_xxx table.
vlm4e554992004-08-25 02:03:12 +0000713 */
vlm72425de2004-09-13 08:31:01 +0000714 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
vlm86f5ed22004-09-26 13:11:31 +0000715 ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000716
vlmfa67ddc2004-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] == '&') {
vlmfa67ddc2004-06-03 03:38:44 +0000728 asn1p_expr_t *extract;
729 arg_t tmp;
730 int ret;
731
vlm39ba4c42004-09-22 16:06:28 +0000732 extract = asn1f_class_access_ex(arg->asn, arg->expr->module,
vlmdae7f9d2004-08-22 03:25:24 +0000733 arg->expr, ref);
vlmfa67ddc2004-06-03 03:38:44 +0000734 if(extract == NULL)
735 return -1;
736
vlmdae7f9d2004-08-22 03:25:24 +0000737 extract = asn1p_expr_clone(extract, 0);
vlmfa67ddc2004-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;
vlmdae7f9d2004-08-22 03:25:24 +0000752 tmp.mod = extract->module;
vlmfa67ddc2004-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;
vlm6e73a042004-08-11 07:17:22 +0000769 int tags_count;
vlm72425de2004-09-13 08:31:01 +0000770 int all_tags_count;
771 enum tvm_compat tv_mode;
vlmfa67ddc2004-06-03 03:38:44 +0000772 char *p;
773
774 if(arg->embed) {
vlma5dcb912004-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
vlmfa67ddc2004-06-03 03:38:44 +0000795 REDIR(OT_TYPE_DECLS);
796
vlma5dcb912004-09-29 13:16:40 +0000797 OUT("%s\t", asn1c_type_name(arg, arg->expr, tnfmt));
vlma02b74d2004-09-15 11:54:38 +0000798 OUT("%s", expr->marker.flags?"*":" ");
vlmdae7f9d2004-08-22 03:25:24 +0000799 OUT("%s", MKID(expr->Identifier));
vlma02b74d2004-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)
vlmddd5a7d2004-09-10 09:18:20 +0000804 OUT("\t/* OPTIONAL */");
vlmb2839012004-08-20 13:37:01 +0000805
806 REDIR(OT_TYPE_DECLS);
vlmfa67ddc2004-06-03 03:38:44 +0000807 return 0;
808 }
809
vlmfa67ddc2004-06-03 03:38:44 +0000810
vlm33a4ff12004-08-11 05:21:32 +0000811 GEN_INCLUDE(asn1c_type_name(arg, expr, TNF_INCLUDE));
vlmfa67ddc2004-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));
vlma02b74d2004-09-15 11:54:38 +0000816 OUT("%s", expr->marker.flags?"*":" ");
vlmdae7f9d2004-08-22 03:25:24 +0000817 OUT("%s_t", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000818
vlm86f5ed22004-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("/* ");
vlma5dcb912004-09-29 13:16:40 +0000833 OUT("#define\tasn_DEF_%s\t", p);
vlm86f5ed22004-09-26 13:11:31 +0000834 type_name = asn1c_type_name(arg, expr, TNF_SAFE);
vlma5dcb912004-09-29 13:16:40 +0000835 OUT("asn_DEF_%s\n", type_name);
vlm86f5ed22004-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
vlmfa67ddc2004-06-03 03:38:44 +0000845 REDIR(OT_STAT_DEFS);
846
vlm4a3f5822004-06-28 21:13:46 +0000847 /*
vlma5dcb912004-09-29 13:16:40 +0000848 * Print out asn_DEF_<type>_[all_]tags[] vectors.
vlm4a3f5822004-06-28 21:13:46 +0000849 */
vlm72425de2004-09-13 08:31:01 +0000850 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
vlmfa67ddc2004-06-03 03:38:44 +0000851
vlm72425de2004-09-13 08:31:01 +0000852 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, 0,
vlm86f5ed22004-09-26 13:11:31 +0000853 ETD_NO_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000854
vlmb2839012004-08-20 13:37:01 +0000855 REDIR(OT_CODE);
856
vlmfa67ddc2004-06-03 03:38:44 +0000857 /*
858 * Constraint checking.
859 */
vlm86f5ed22004-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("
vlma5dcb912004-09-29 13:16:40 +0000864 "asn_TYPE_descriptor_t *td, const void *sptr,\n", p);
vlm86f5ed22004-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 "
vlma5dcb912004-09-29 13:16:40 +0000871 "= asn_DEF_%s.check_constraints;\n",
vlm86f5ed22004-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");
vlm1d036692004-08-19 13:29:46 +0000875 }
vlm86f5ed22004-09-26 13:11:31 +0000876 INDENT(-1);
877 OUT("}\n");
878 OUT("\n");
vlmfa67ddc2004-06-03 03:38:44 +0000879 }
vlmfa67ddc2004-06-03 03:38:44 +0000880
881 /*
882 * Emit suicidal functions.
883 */
884
vlmfa67ddc2004-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 */
vlmfa67ddc2004-06-03 03:38:44 +0000890 OUT("/*\n");
vlmb2839012004-08-20 13:37:01 +0000891 OUT(" * This type is implemented using %s,\n",
892 asn1c_type_name(arg, expr, TNF_SAFE));
vlmdcd32fe2004-09-23 22:20:47 +0000893 OUT(" * so here we adjust the DEF accordingly.\n");
vlmfa67ddc2004-06-03 03:38:44 +0000894 OUT(" */\n");
895 OUT("static void\n");
vlmb2839012004-08-20 13:37:01 +0000896 p = MKID(expr->Identifier);
vlma5dcb912004-09-29 13:16:40 +0000897 OUT("%s_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000898 INDENT(+1);
vlmb2839012004-08-20 13:37:01 +0000899 {
vlm39ba4c42004-09-22 16:06:28 +0000900 asn1p_expr_t *terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
vlmb2839012004-08-20 13:37:01 +0000901 char *type_name = asn1c_type_name(arg, expr, TNF_SAFE);
vlma5dcb912004-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);
vlm1308d2b2004-09-10 15:49:15 +0000908 if(!terminal && !tags_count) {
vlm72425de2004-09-13 08:31:01 +0000909 OUT("/* The next four lines are here because of -fknown-extern-type */\n");
vlma5dcb912004-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);
vlm1308d2b2004-09-10 15:49:15 +0000914 OUT("/* End of these lines */\n");
915 }
vlma5dcb912004-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);
vlmb2839012004-08-20 13:37:01 +0000919 }
vlmfa67ddc2004-06-03 03:38:44 +0000920 INDENT(-1);
921 OUT("}\n");
922 OUT("\n");
vlmfa67ddc2004-06-03 03:38:44 +0000923
924 p = MKID(expr->Identifier);
vlm39ba4c42004-09-22 16:06:28 +0000925 OUT("void\n");
vlma5dcb912004-09-29 13:16:40 +0000926 OUT("%s_free(asn_TYPE_descriptor_t *td,\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000927 INDENTED(
vlm39ba4c42004-09-22 16:06:28 +0000928 OUT("\tvoid *struct_ptr, int contents_only) {\n");
vlmb2839012004-08-20 13:37:01 +0000929 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000930 OUT("td->free_struct(td, struct_ptr, contents_only);\n");
vlmfa67ddc2004-06-03 03:38:44 +0000931 );
932 OUT("}\n");
933 OUT("\n");
934
935 p = MKID(expr->Identifier);
936 OUT("int\n");
vlma5dcb912004-09-29 13:16:40 +0000937 OUT("%s_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000938 INDENTED(
939 OUT("\tint ilevel, asn_app_consume_bytes_f *cb, void *app_key) {\n");
vlmb2839012004-08-20 13:37:01 +0000940 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlmfa67ddc2004-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);
vlm9de248e2004-10-20 15:50:55 +0000947 OUT("asn_dec_rval_t\n");
vlma5dcb912004-09-29 13:16:40 +0000948 OUT("%s_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000949 INDENTED(
vlm39ba4c42004-09-22 16:06:28 +0000950 OUT("\tvoid **structure, void *bufptr, size_t size, int tag_mode) {\n");
vlmb2839012004-08-20 13:37:01 +0000951 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlma5dcb912004-09-29 13:16:40 +0000952 OUT("return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);\n");
vlm39ba4c42004-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");
vlma5dcb912004-09-29 13:16:40 +0000959 OUT("%s_encode_der(asn_TYPE_descriptor_t *td,\n", p);
vlm39ba4c42004-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);
vlme03646b2004-10-23 13:34:00 +0000970 OUT("asn_dec_rval_t\n");
971 OUT("%s_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n", p);
972 INDENTED(
973 OUT("\tvoid **structure, const char *opt_mname, void *bufptr, size_t size) {\n");
974 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
975 OUT("return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size);\n");
976 );
977 OUT("}\n");
978 OUT("\n");
979
980 p = MKID(expr->Identifier);
vlm39ba4c42004-09-22 16:06:28 +0000981 OUT("asn_enc_rval_t\n");
vlma5dcb912004-09-29 13:16:40 +0000982 OUT("%s_encode_xer(asn_TYPE_descriptor_t *td, void *structure,\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000983 INDENTED(
984 OUT("\tint ilevel, enum xer_encoder_flags_e flags,\n");
985 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
986 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
987 OUT("return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);\n");
vlmfa67ddc2004-06-03 03:38:44 +0000988 );
989 OUT("}\n");
990 OUT("\n");
991
992 REDIR(OT_FUNC_DECLS);
993
994 p = MKID(expr->Identifier);
vlm12c8f692004-09-06 08:07:29 +0000995 if(HIDE_INNER_DEFS) OUT("/* ");
vlma5dcb912004-09-29 13:16:40 +0000996 OUT("extern asn_TYPE_descriptor_t asn_DEF_%s;", p);
vlm12c8f692004-09-06 08:07:29 +0000997 if(HIDE_INNER_DEFS) OUT(" // (Use -fall-defs-global to expose) */");
998 OUT("\n");
vlm39ba4c42004-09-22 16:06:28 +0000999 OUT("asn_struct_free_f %s_free;\n", p);
1000 OUT("asn_struct_print_f %s_print;\n", p);
vlmfa67ddc2004-06-03 03:38:44 +00001001 OUT("asn_constr_check_f %s_constraint;\n", p);
1002 OUT("ber_type_decoder_f %s_decode_ber;\n", p);
1003 OUT("der_type_encoder_f %s_encode_der;\n", p);
vlme03646b2004-10-23 13:34:00 +00001004 OUT("xer_type_decoder_f %s_decode_xer;\n", p);
vlm39ba4c42004-09-22 16:06:28 +00001005 OUT("xer_type_encoder_f %s_encode_xer;\n", p);
vlmfa67ddc2004-06-03 03:38:44 +00001006
vlm33a4ff12004-08-11 05:21:32 +00001007 REDIR(OT_TYPE_DECLS);
1008
vlmfa67ddc2004-06-03 03:38:44 +00001009 return 0;
1010}
1011
1012int
1013asn1c_lang_C_type_EXTENSIBLE(arg_t *arg) {
1014
1015 OUT("/*\n");
1016 OUT(" * This type is extensible,\n");
1017 OUT(" * possible extensions are below.\n");
1018 OUT(" */\n");
1019
1020 return 0;
1021}
1022
vlm79b08d52004-07-01 00:52:50 +00001023static int check_if_extensible(asn1p_expr_t *expr) {
1024 asn1p_expr_t *v;
1025 TQ_FOR(v, &(expr->members), next) {
1026 if(v->expr_type == A1TC_EXTENSIBLE) return 1;
1027 }
1028 return 0;
1029}
1030
vlmfa67ddc2004-06-03 03:38:44 +00001031static int
vlma8a86cc2004-09-10 06:07:18 +00001032_print_tag(arg_t *arg, struct asn1p_type_tag_s *tag) {
vlmfa67ddc2004-06-03 03:38:44 +00001033
1034 OUT("(");
vlma8a86cc2004-09-10 06:07:18 +00001035 switch(tag->tag_class) {
vlmfa67ddc2004-06-03 03:38:44 +00001036 case TC_UNIVERSAL: OUT("ASN_TAG_CLASS_UNIVERSAL"); break;
1037 case TC_APPLICATION: OUT("ASN_TAG_CLASS_APPLICATION"); break;
1038 case TC_CONTEXT_SPECIFIC: OUT("ASN_TAG_CLASS_CONTEXT"); break;
1039 case TC_PRIVATE: OUT("ASN_TAG_CLASS_PRIVATE"); break;
1040 case TC_NOCLASS:
1041 break;
1042 }
vlm47ae1582004-09-24 21:01:43 +00001043 OUT(" | (%" PRIdASN " << 2))", tag->tag_value);
vlmfa67ddc2004-06-03 03:38:44 +00001044
1045 return 0;
1046}
1047
vlm4e03ce22004-06-06 07:20:17 +00001048
1049static int
1050_tag2el_cmp(const void *ap, const void *bp) {
1051 const tag2el_t *a = ap;
1052 const tag2el_t *b = bp;
1053 const struct asn1p_type_tag_s *ta = &a->el_tag;
1054 const struct asn1p_type_tag_s *tb = &b->el_tag;
1055
1056 if(ta->tag_class == tb->tag_class) {
1057 if(ta->tag_value == tb->tag_value) {
1058 /*
1059 * Sort by their respective positions.
1060 */
1061 if(a->el_no < b->el_no)
1062 return -1;
1063 else if(a->el_no > b->el_no)
1064 return 1;
1065 return 0;
1066 } else if(ta->tag_value < tb->tag_value)
1067 return -1;
1068 else
1069 return 1;
1070 } else if(ta->tag_class < tb->tag_class) {
1071 return -1;
1072 } else {
1073 return 1;
1074 }
1075}
1076
vlmfa67ddc2004-06-03 03:38:44 +00001077/*
1078 * For constructed types, number of external tags may be greater than
1079 * number of elements in the type because of CHOICE type.
1080 * T ::= SET { -- Three possible tags:
1081 * a INTEGER, -- One tag is here...
1082 * b Choice1 -- ... and two more tags are there.
1083 * }
1084 * Choice1 ::= CHOICE {
1085 * s1 IA5String,
1086 * s2 ObjectDescriptor
1087 * }
1088 */
1089static int
vlm940bc6b2004-10-03 09:13:30 +00001090_fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
vlmfa67ddc2004-06-03 03:38:44 +00001091 asn1p_expr_t *expr = arg->expr;
1092 arg_t tmparg = *arg;
1093 asn1p_expr_t *v;
1094 int element = 0;
vlm940bc6b2004-10-03 09:13:30 +00001095 int original_count = *count;
1096 int sort_until = -1;
vlmfa67ddc2004-06-03 03:38:44 +00001097
1098 TQ_FOR(v, &(expr->members), next) {
vlm940bc6b2004-10-03 09:13:30 +00001099 if(v->expr_type == A1TC_EXTENSIBLE) {
1100 /*
1101 * CANONICAL-XER mandates sorting
1102 * only for the root part.
1103 */
1104 if(flags == FTE_CANONICAL_XER
1105 && sort_until == -1)
1106 sort_until = *count;
vlmfa67ddc2004-06-03 03:38:44 +00001107 continue;
vlm940bc6b2004-10-03 09:13:30 +00001108 }
vlmfa67ddc2004-06-03 03:38:44 +00001109
1110 tmparg.expr = v;
1111
1112 if(_add_tag2el_member(&tmparg, tag2el, count,
vlm940bc6b2004-10-03 09:13:30 +00001113 (el_no==-1)?element:el_no, flags)) {
vlmfa67ddc2004-06-03 03:38:44 +00001114 return -1;
1115 }
1116
1117 element++;
1118 }
1119
vlm940bc6b2004-10-03 09:13:30 +00001120
1121 if(flags == FTE_CANONICAL_XER) {
1122 if(sort_until == -1) sort_until = *count;
1123 qsort((*tag2el) + original_count,
1124 sort_until - original_count,
1125 sizeof(**tag2el), _tag2el_cmp);
1126 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1127 && (sort_until - original_count) >= 1) {
1128 /* Only take in account the root component */
1129 *count = original_count + 1;
1130 }
1131 } else {
1132 /*
1133 * Sort the map according to canonical order of their
1134 * tags and element numbers.
1135 */
1136 qsort(*tag2el, *count, sizeof(**tag2el), _tag2el_cmp);
1137 }
vlm4e03ce22004-06-06 07:20:17 +00001138
vlmc8aeab42004-06-14 13:09:45 +00001139 /*
1140 * Initialize .toff_{first|last} members.
1141 */
1142 if(*count) {
1143 struct asn1p_type_tag_s *cur_tag = 0;
1144 tag2el_t *cur = *tag2el;
1145 tag2el_t *end = cur + *count;
1146 int occur, i;
1147 for(occur = 0; cur < end; cur++) {
1148 if(cur_tag == 0
1149 || cur_tag->tag_value != cur->el_tag.tag_value
1150 || cur_tag->tag_class != cur->el_tag.tag_class) {
1151 cur_tag = &cur->el_tag;
1152 occur = 0;
1153 } else {
1154 occur++;
1155 }
1156 cur->toff_first = -occur;
1157 for(i = 0; i >= -occur; i--)
1158 cur[i].toff_last = -i;
1159 }
1160 }
1161
vlmfa67ddc2004-06-03 03:38:44 +00001162 return 0;
1163}
1164
1165static int
vlm940bc6b2004-10-03 09:13:30 +00001166_add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
vlmfa67ddc2004-06-03 03:38:44 +00001167 struct asn1p_type_tag_s tag;
1168 int ret;
1169
1170 assert(el_no >= 0);
1171
vlm39ba4c42004-09-22 16:06:28 +00001172 ret = asn1f_fetch_outmost_tag(arg->asn, arg->expr->module,
1173 arg->expr, &tag, 1);
vlmfa67ddc2004-06-03 03:38:44 +00001174 if(ret == 0) {
vlme2070ea2004-09-04 04:42:29 +00001175 tag2el_t *te;
1176 int new_count = (*count) + 1;
vlmfa67ddc2004-06-03 03:38:44 +00001177 void *p;
vlme2070ea2004-09-04 04:42:29 +00001178
vlm2de0e792004-09-05 10:42:33 +00001179 if(tag.tag_value == -1) {
1180 /*
1181 * This is an untagged ANY type,
1182 * proceed without adding a tag
1183 */
1184 return 0;
1185 }
1186
vlme2070ea2004-09-04 04:42:29 +00001187 p = realloc(*tag2el, new_count * sizeof(tag2el_t));
vlmfa67ddc2004-06-03 03:38:44 +00001188 if(p) *tag2el = p;
1189 else return -1;
1190
1191 DEBUG("Found tag for %s: %ld",
1192 arg->expr->Identifier,
1193 (long)tag.tag_value);
1194
vlme2070ea2004-09-04 04:42:29 +00001195 te = &((*tag2el)[*count]);
1196 te->el_tag = tag;
1197 te->el_no = el_no;
1198 te->from_expr = arg->expr;
1199 *count = new_count;
vlmfa67ddc2004-06-03 03:38:44 +00001200 return 0;
1201 }
1202
1203 DEBUG("Searching tag in complex expression %s:%x at line %d",
1204 arg->expr->Identifier,
1205 arg->expr->expr_type,
1206 arg->expr->_lineno);
1207
1208 /*
1209 * Iterate over members of CHOICE type.
1210 */
1211 if(arg->expr->expr_type == ASN_CONSTR_CHOICE) {
vlm940bc6b2004-10-03 09:13:30 +00001212 return _fill_tag2el_map(arg, tag2el, count, el_no, flags);
vlmfa67ddc2004-06-03 03:38:44 +00001213 }
1214
1215 if(arg->expr->expr_type == A1TC_REFERENCE) {
1216 arg_t tmp = *arg;
1217 asn1p_expr_t *expr;
vlmdae7f9d2004-08-22 03:25:24 +00001218 expr = asn1f_lookup_symbol_ex(tmp.asn, tmp.mod, tmp.expr,
vlmfa67ddc2004-06-03 03:38:44 +00001219 arg->expr->reference);
1220 if(expr) {
vlmdae7f9d2004-08-22 03:25:24 +00001221 tmp.mod = expr->module;
vlmfa67ddc2004-06-03 03:38:44 +00001222 tmp.expr = expr;
vlm940bc6b2004-10-03 09:13:30 +00001223 return _add_tag2el_member(&tmp, tag2el, count, el_no, flags);
vlmfa67ddc2004-06-03 03:38:44 +00001224 } else {
1225 FATAL("Cannot dereference %s at line %d",
1226 arg->expr->Identifier,
1227 arg->expr->_lineno);
1228 return -1;
1229 }
1230 }
1231
1232 DEBUG("No tag for %s at line %d",
1233 arg->expr->Identifier,
1234 arg->expr->_lineno);
1235
1236 return -1;
1237}
1238
1239static int
vlm940bc6b2004-10-03 09:13:30 +00001240emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier) {
vlm4e03ce22004-06-06 07:20:17 +00001241 asn1p_expr_t *expr = arg->expr;
1242
vlm940bc6b2004-10-03 09:13:30 +00001243 OUT("static asn_TYPE_tag2member_t asn_DEF_%s_tag2el%s[] = {\n",
1244 MKID(expr->Identifier), opt_modifier?opt_modifier:"");
vlm4e03ce22004-06-06 07:20:17 +00001245 if(tag2el_count) {
1246 int i;
1247 for(i = 0; i < tag2el_count; i++) {
1248 OUT(" { ");
vlma8a86cc2004-09-10 06:07:18 +00001249 _print_tag(arg, &tag2el[i].el_tag);
vlm4e03ce22004-06-06 07:20:17 +00001250 OUT(", ");
vlmc8aeab42004-06-14 13:09:45 +00001251 OUT("%d, ", tag2el[i].el_no);
1252 OUT("%d, ", tag2el[i].toff_first);
1253 OUT("%d ", tag2el[i].toff_last);
vlm4e03ce22004-06-06 07:20:17 +00001254 OUT("}, /* %s at %d */\n",
1255 tag2el[i].from_expr->Identifier,
1256 tag2el[i].from_expr->_lineno
1257 );
1258 }
1259 }
1260 OUT("};\n");
1261
1262 return 0;;
1263}
1264
vlm72425de2004-09-13 08:31:01 +00001265static enum tvm_compat
1266emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tags_count_r, int *all_tags_count_r) {
1267 struct asn1p_type_tag_s *tags = 0; /* Effective tags */
1268 struct asn1p_type_tag_s *all_tags = 0; /* The full array */
vlm6e73a042004-08-11 07:17:22 +00001269 int tags_count = 0;
vlm72425de2004-09-13 08:31:01 +00001270 int all_tags_count = 0;
1271 enum tvm_compat tv_mode = _TVM_SAME;
vlm1308d2b2004-09-10 15:49:15 +00001272 int i;
vlm4a3f5822004-06-28 21:13:46 +00001273
vlmc6de2c42004-09-14 14:10:10 +00001274 /* Cleanup before proceeding. */
1275 *tags_count_r = 0;
1276 *all_tags_count_r = 0;
1277
vlm1308d2b2004-09-10 15:49:15 +00001278 /* Fetch a chain of tags */
vlm39ba4c42004-09-22 16:06:28 +00001279 tags_count = asn1f_fetch_tags(arg->asn, expr->module, expr, &tags, 0);
vlmc6de2c42004-09-14 14:10:10 +00001280 if(tags_count < 0)
1281 return -1;
vlm6e73a042004-08-11 07:17:22 +00001282
vlm72425de2004-09-13 08:31:01 +00001283 /* Fetch a chain of tags */
vlm39ba4c42004-09-22 16:06:28 +00001284 all_tags_count = asn1f_fetch_tags(arg->asn, expr->module, expr,
vlm72425de2004-09-13 08:31:01 +00001285 &all_tags, AFT_FULL_COLLECT);
1286 if(all_tags_count < 0) {
1287 if(tags) free(tags);
1288 return -1;
vlmfb41dbb2004-09-08 00:28:57 +00001289 }
vlm1308d2b2004-09-10 15:49:15 +00001290
vlm72425de2004-09-13 08:31:01 +00001291 assert(tags_count <= all_tags_count);
1292 assert((tags_count?0:1) == (all_tags_count?0:1));
vlm4a3f5822004-06-28 21:13:46 +00001293
vlm72425de2004-09-13 08:31:01 +00001294 if(tags_count <= all_tags_count) {
1295 for(i = 0; i < tags_count; i++) {
1296 if(tags[i].tag_value != all_tags[i].tag_value
1297 || tags[i].tag_class != all_tags[i].tag_class) {
1298 tv_mode = _TVM_DIFFERENT;
1299 break;
1300 }
1301 }
1302 if(i == tags_count && tags_count < all_tags_count)
1303 tv_mode = _TVM_SUBSET;
1304 } else {
1305 tv_mode = _TVM_DIFFERENT;
1306 }
1307
1308#define EMIT_TAGS_TABLE(name, tags, tags_count) do { \
vlma5dcb912004-09-29 13:16:40 +00001309 OUT("static ber_tlv_tag_t asn_DEF_%s%s_tags[] = {\n", \
vlm72425de2004-09-13 08:31:01 +00001310 MKID(expr->Identifier), name); \
1311 INDENT(+1); \
1312 /* Print the array of collected tags */ \
1313 for(i = 0; i < tags_count; i++) { \
1314 if(i) OUT(",\n"); \
1315 _print_tag(arg, &tags[i]); \
1316 } \
1317 OUT("\n"); \
1318 INDENT(-1); \
1319 OUT("};\n"); \
1320 } while(0)
1321
1322 if(tags_count) {
1323 if(tv_mode == _TVM_SUBSET)
1324 EMIT_TAGS_TABLE("", all_tags, all_tags_count);
1325 else
1326 EMIT_TAGS_TABLE("", tags, tags_count);
1327 }
1328
1329 if(all_tags_count) {
1330 if(tv_mode == _TVM_DIFFERENT)
1331 EMIT_TAGS_TABLE("_all", all_tags, all_tags_count);
1332 }
1333
1334 if(tags) free(tags);
1335 if(all_tags) free(all_tags);
1336
1337 *tags_count_r = tags_count;
1338 *all_tags_count_r = all_tags_count;
1339
1340 return tv_mode;
vlm4a3f5822004-06-28 21:13:46 +00001341}
vlmb2839012004-08-20 13:37:01 +00001342
1343static int
vlm4e554992004-08-25 02:03:12 +00001344expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
vlmb2839012004-08-20 13:37:01 +00001345 asn1p_expr_t *topmost_parent;
1346 asn1p_expr_t *v;
1347 int elements = 0;
1348
vlm39ba4c42004-09-22 16:06:28 +00001349 topmost_parent = asn1f_find_terminal_type_ex(arg->asn, expr);
vlmb2839012004-08-20 13:37:01 +00001350 if(!topmost_parent) return 0;
1351
1352 if(!(topmost_parent->expr_type & ASN_CONSTR_MASK))
1353 return 0;
1354
1355 TQ_FOR(v, &(topmost_parent->members), next) {
1356 if(v->expr_type != A1TC_EXTENSIBLE)
1357 elements++;
1358 }
1359
1360 return elements;
1361}
1362
1363static int
vlm4e554992004-08-25 02:03:12 +00001364emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
vlmdae7f9d2004-08-22 03:25:24 +00001365 static int global_memb_unique;
vlmb2839012004-08-20 13:37:01 +00001366 int save_target;
1367 arg_t tmp_arg;
vlm060fe2a2004-09-10 09:37:12 +00001368 struct asn1p_type_tag_s outmost_tag_s;
1369 struct asn1p_type_tag_s *outmost_tag;
vlmb2839012004-08-20 13:37:01 +00001370 char *p;
1371
vlm060fe2a2004-09-10 09:37:12 +00001372 if(asn1f_fetch_outmost_tag(arg->asn,
1373 expr->module, expr, &outmost_tag_s, 1)) {
1374 outmost_tag = 0;
1375 } else {
1376 outmost_tag = &outmost_tag_s;
1377 }
1378
vlmb2839012004-08-20 13:37:01 +00001379 OUT("{ ");
vlm060fe2a2004-09-10 09:37:12 +00001380
1381 if(outmost_tag && outmost_tag->tag_value == -1)
1382 OUT("ATF_OPEN_TYPE | ");
vlma02b74d2004-09-15 11:54:38 +00001383 OUT("%s, ", expr->marker.flags?"ATF_POINTER":"ATF_NOFLAGS");
1384 if((expr->marker.flags & EM_OPTIONAL) == EM_OPTIONAL) {
vlmb2839012004-08-20 13:37:01 +00001385 asn1p_expr_t *tv;
1386 int opts = 0;
vlma02b74d2004-09-15 11:54:38 +00001387 for(tv = expr; tv && tv->marker.flags;
vlmb2839012004-08-20 13:37:01 +00001388 tv = TQ_NEXT(tv, next), opts++) {
1389 if(tv->expr_type == A1TC_EXTENSIBLE)
1390 opts--;
1391 }
1392 OUT("%d, ", opts);
1393 } else {
1394 OUT("0, ");
1395 }
vlm39ba4c42004-09-22 16:06:28 +00001396 if(expr->_anonymous_type) {
1397 assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
1398 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
1399 OUT("0,\n");
1400 } else {
vlmb2839012004-08-20 13:37:01 +00001401 OUT("offsetof(struct %s, ", MKID(arg->expr->Identifier));
1402 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1403 && (!UNNAMED_UNIONS)) OUT("choice.");
1404 OUT("%s),\n", MKID(expr->Identifier));
vlmb2839012004-08-20 13:37:01 +00001405 }
1406 INDENT(+1);
1407 if(C99_MODE) OUT(".tag = ");
vlm060fe2a2004-09-10 09:37:12 +00001408 if(outmost_tag) {
1409 if(outmost_tag->tag_value == -1)
1410 OUT("-1 /* Ambiguous tag (ANY?) */");
1411 else
1412 _print_tag(arg, outmost_tag);
vlma8a86cc2004-09-10 06:07:18 +00001413 } else {
vlm060fe2a2004-09-10 09:37:12 +00001414 OUT("-1 /* Ambiguous tag (CHOICE?) */");
vlma8a86cc2004-09-10 06:07:18 +00001415 }
vlm060fe2a2004-09-10 09:37:12 +00001416
vlmb2839012004-08-20 13:37:01 +00001417 OUT(",\n");
1418 if(C99_MODE) OUT(".tag_mode = ");
1419 if(expr->tag.tag_class) {
1420 if(expr->tag.tag_mode == TM_IMPLICIT)
1421 OUT("-1,\t/* IMPLICIT tag at current level */\n");
1422 else
1423 OUT("+1,\t/* EXPLICIT tag at current level */\n");
1424 } else {
1425 OUT("0,\n");
1426 }
1427 if(C99_MODE) OUT(".type = ");
vlm39ba4c42004-09-22 16:06:28 +00001428 if(expr->_anonymous_type && (expr->expr_type & ASN_CONSTR_MASK)) {
vlma5dcb912004-09-29 13:16:40 +00001429 OUT("(void *)&asn_DEF_%s_member,\n",
vlmdae7f9d2004-08-22 03:25:24 +00001430 MKID(arg->expr->Identifier));
vlm4e554992004-08-25 02:03:12 +00001431 } else if(expr->expr_type & ASN_CONSTR_MASK) {
vlma5dcb912004-09-29 13:16:40 +00001432 OUT("(void *)&asn_DEF_%s,\n",
vlm4e554992004-08-25 02:03:12 +00001433 MKID(expr->Identifier));
vlmdae7f9d2004-08-22 03:25:24 +00001434 } else {
vlma5dcb912004-09-29 13:16:40 +00001435 OUT("(void *)&asn_DEF_%s,\n",
vlmdae7f9d2004-08-22 03:25:24 +00001436 asn1c_type_name(arg, expr, TNF_SAFE));
1437 }
vlmb2839012004-08-20 13:37:01 +00001438 if(C99_MODE) OUT(".memb_constraints = ");
1439 if(expr->constraints) {
vlm86f5ed22004-09-26 13:11:31 +00001440 if(arg->flags & A1C_NO_CONSTRAINTS) {
1441 OUT("0,\t/* No check because of -fno-constraints */\n");
1442 } else {
1443 char *id = MKID(expr->Identifier);
1444 if(expr->_anonymous_type
1445 && !strcmp(expr->Identifier, "member"))
1446 id = asn1c_type_name(arg, expr, TNF_SAFE);
1447 OUT("memb_%s_%d_constraint,\n", id,
1448 ++global_memb_unique);
1449 }
vlmb2839012004-08-20 13:37:01 +00001450 } else {
1451 OUT("0,\t/* Defer to actual type */\n");
1452 }
1453 if(C99_MODE) OUT(".name = ");
vlm39ba4c42004-09-22 16:06:28 +00001454 OUT("\"%s\"\n", expr->_anonymous_type ? "" : expr->Identifier);
vlmb2839012004-08-20 13:37:01 +00001455 OUT("},\n");
1456 INDENT(-1);
1457
vlm86f5ed22004-09-26 13:11:31 +00001458 if(!expr->constraints || (arg->flags & A1C_NO_CONSTRAINTS))
vlmb2839012004-08-20 13:37:01 +00001459 return 0;
1460
1461 save_target = arg->target->target;
1462 REDIR(OT_CODE);
1463
vlm39ba4c42004-09-22 16:06:28 +00001464 if(expr->_anonymous_type && !strcmp(expr->Identifier, "member"))
vlmb2839012004-08-20 13:37:01 +00001465 p = asn1c_type_name(arg, expr, TNF_SAFE);
vlm39ba4c42004-09-22 16:06:28 +00001466 else
1467 p = MKID(expr->Identifier);
vlmb2839012004-08-20 13:37:01 +00001468 OUT("static int\n");
vlma5dcb912004-09-29 13:16:40 +00001469 OUT("memb_%s_%d_constraint(asn_TYPE_descriptor_t *td, const void *sptr,\n", p, global_memb_unique);
vlmb2839012004-08-20 13:37:01 +00001470 INDENT(+1);
1471 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
1472 tmp_arg = *arg;
1473 tmp_arg.expr = expr;
1474 if(asn1c_emit_constraint_checking_code(&tmp_arg) == 1) {
vlm86f5ed22004-09-26 13:11:31 +00001475 OUT("return td->check_constraints"
1476 "(td, sptr, app_errlog, app_key);\n");
vlmb2839012004-08-20 13:37:01 +00001477 }
1478 INDENT(-1);
1479 OUT("}\n");
1480 OUT("\n");
1481
1482 REDIR(save_target);
1483
1484 return 0;
1485}
vlm4e554992004-08-25 02:03:12 +00001486
vlm9de248e2004-10-20 15:50:55 +00001487/*
1488 * Generate "asn_DEF_XXX" type definition.
1489 */
vlm4e554992004-08-25 02:03:12 +00001490static int
vlm86f5ed22004-09-26 13:11:31 +00001491emit_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) {
vlm4e554992004-08-25 02:03:12 +00001492 char *p;
1493
1494 p = MKID(expr->Identifier);
vlm12c8f692004-09-06 08:07:29 +00001495 if(HIDE_INNER_DEFS)
1496 OUT("static /* Use -fall-defs-global to expose */\n");
vlma5dcb912004-09-29 13:16:40 +00001497 OUT("asn_TYPE_descriptor_t asn_DEF_%s = {\n", p);
vlm72425de2004-09-13 08:31:01 +00001498 INDENT(+1);
vlm4e554992004-08-25 02:03:12 +00001499 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
vlm9de248e2004-10-20 15:50:55 +00001500 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
vlm4e554992004-08-25 02:03:12 +00001501
1502 if(expr->expr_type & ASN_CONSTR_MASK) {
1503 p = asn1c_type_name(arg, arg->expr, TNF_SAFE);
1504 }
1505
vlm39ba4c42004-09-22 16:06:28 +00001506 OUT("%s_free,\n", p);
1507 OUT("%s_print,\n", p);
vlm4e554992004-08-25 02:03:12 +00001508 OUT("%s_constraint,\n", p);
1509 OUT("%s_decode_ber,\n", p);
1510 OUT("%s_encode_der,\n", p);
vlme03646b2004-10-23 13:34:00 +00001511 if(!(expr->expr_type & ASN_CONSTR_MASK)
1512 && (expr->expr_type != ASN_CONSTR_SEQUENCE))
1513 OUT("%s_decode_xer,\n", p);
1514 else
1515 OUT("0,\t\t\t\t/* Not implemented yet */\n");
vlm39ba4c42004-09-22 16:06:28 +00001516 OUT("%s_encode_xer,\n", p);
vlm4e554992004-08-25 02:03:12 +00001517
1518 p = MKID(expr->Identifier);
1519
1520 if(expr->expr_type == ASN_CONSTR_CHOICE) {
1521 OUT("CHOICE_outmost_tag,\n");
1522 } else {
1523 OUT("0,\t/* Use generic outmost tag fetcher */\n");
1524 }
1525
1526 if(tags_count) {
vlma5dcb912004-09-29 13:16:40 +00001527 OUT("asn_DEF_%s_tags,\n", p);
1528 OUT("sizeof(asn_DEF_%s_tags)\n", p);
1529 OUT("\t/sizeof(asn_DEF_%s_tags[0])", p);
vlm72425de2004-09-13 08:31:01 +00001530 if(tv_mode == _TVM_SUBSET
1531 && tags_count != all_tags_count)
1532 OUT(" - %d", all_tags_count - tags_count);
1533 OUT(", /* %d */\n", tags_count);
vlm4e554992004-08-25 02:03:12 +00001534 } else {
vlm72425de2004-09-13 08:31:01 +00001535 OUT("0,\t/* No effective tags (pointer) */\n");
1536 OUT("0,\t/* No effective tags (count) */\n");
1537 }
1538
1539 if(all_tags_count && tv_mode == _TVM_DIFFERENT) {
vlma5dcb912004-09-29 13:16:40 +00001540 OUT("asn_DEF_%s_all_tags,\n", p);
1541 OUT("sizeof(asn_DEF_%s_all_tags)\n", p);
1542 OUT("\t/sizeof(asn_DEF_%s_all_tags[0]), /* %d */\n",
vlm72425de2004-09-13 08:31:01 +00001543 p, all_tags_count);
1544 } else if(all_tags_count) {
vlma5dcb912004-09-29 13:16:40 +00001545 OUT("asn_DEF_%s_tags,\t/* Same as above */\n", p);
1546 OUT("sizeof(asn_DEF_%s_tags)\n", p);
1547 OUT("\t/sizeof(asn_DEF_%s_tags[0]), /* %d */\n",
vlm72425de2004-09-13 08:31:01 +00001548 p, all_tags_count);
1549 } else {
1550 OUT("0,\t/* No tags (pointer) */\n");
1551 OUT("0,\t/* No tags (count) */\n");
vlm4e554992004-08-25 02:03:12 +00001552 }
1553
vlm4e554992004-08-25 02:03:12 +00001554 if(elements_count) {
vlma5dcb912004-09-29 13:16:40 +00001555 OUT("asn_MBR_%s,\n", p);
vlm4e554992004-08-25 02:03:12 +00001556 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF
1557 || expr->expr_type == ASN_CONSTR_SET_OF) {
1558 OUT("%d,\t/* Single element */\n",
1559 elements_count);
1560 assert(elements_count == 1);
1561 } else {
1562 OUT("%d,\t/* Elements count */\n",
1563 elements_count);
1564 }
1565 } else {
1566 //if(expr->meta_type == AMT_TYPEREF)
1567 if(expr_elements_count(arg, expr))
1568 OUT("0, 0,\t/* Defined elsewhere */\n");
1569 else
1570 OUT("0, 0,\t/* No members */\n");
1571 }
1572
1573 switch(spec) {
1574 case ETD_NO_SPECIFICS:
1575 OUT("0\t/* No specifics */\n");
1576 break;
1577 case ETD_HAS_SPECIFICS:
vlma5dcb912004-09-29 13:16:40 +00001578 OUT("&asn_DEF_%s_specs\t/* Additional specs */\n", p);
vlm4e554992004-08-25 02:03:12 +00001579 }
vlm72425de2004-09-13 08:31:01 +00001580 INDENT(-1);
vlm4e554992004-08-25 02:03:12 +00001581 OUT("};\n");
1582 OUT("\n");
vlme2bb4432004-08-26 06:20:34 +00001583
1584 return 0;
vlm4e554992004-08-25 02:03:12 +00001585}
vlmddd5a7d2004-09-10 09:18:20 +00001586
1587/*
1588 * Check if it is better to make this type indirectly accessed via
1589 * a pointer.
1590 * This may be the case for the following recursive definition:
1591 * Type ::= CHOICE { member Type };
1592 */
1593static int
1594expr_better_indirect(arg_t *arg, asn1p_expr_t *expr) {
1595 asn1p_expr_t *top_parent;
1596 asn1p_expr_t *terminal;
1597
1598 if(expr->expr_type != A1TC_REFERENCE)
1599 return 0;
1600
1601 /* Rewind to the topmost parent expression */
1602 if((top_parent = expr->parent_expr)) {
1603 while(top_parent->parent_expr)
1604 top_parent = top_parent->parent_expr;
1605 } else {
1606 return 0;
1607 }
1608
vlm39ba4c42004-09-22 16:06:28 +00001609 terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
vlmddd5a7d2004-09-10 09:18:20 +00001610
1611 return (terminal == top_parent);
1612}
vlm39ba4c42004-09-22 16:06:28 +00001613
1614static int
1615expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr) {
1616 expr = asn1f_find_terminal_type_ex(arg->asn, expr);
1617 if(!expr) return 0;
1618
1619 /* X.680, 25.5, Table 5 */
1620 switch(expr->expr_type) {
1621 case ASN_CONSTR_CHOICE:
1622 case ASN_BASIC_BOOLEAN:
1623 case ASN_BASIC_ENUMERATED:
1624 case ASN_BASIC_NULL:
1625 return 1;
1626 default:
1627 return 0;
1628 }
1629}