blob: 6b6b87d79c21e2742a12e036b1a16268374c63b8 [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;
vlmedf203f2005-01-17 11:57:48 +0000240} /* _SEQUENCE_def() */
vlmfa67ddc2004-06-03 03:38:44 +0000241
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;
vlmedf203f2005-01-17 11:57:48 +0000445} /* _SET_def() */
vlmfa67ddc2004-06-03 03:38:44 +0000446
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;
vlmedf203f2005-01-17 11:57:48 +0000569} /* _SEx_OF_def() */
vlmfa67ddc2004-06-03 03:38:44 +0000570
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)) {
vlmfa67ddc2004-06-03 03:38:44 +0000658
vlm39ba4c42004-09-22 16:06:28 +0000659 p = MKID(expr->Identifier);
vlma5dcb912004-09-29 13:16:40 +0000660 OUT("static asn_TYPE_member_t asn_MBR_%s[] = {\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000661
662 elements = 0;
663 INDENTED(TQ_FOR(v, &(expr->members), next) {
vlm34dcd572005-01-17 11:40:49 +0000664 if(v->expr_type == A1TC_EXTENSIBLE)
665 continue;
666 if(expr_better_indirect(arg, v))
667 v->marker.flags |= EM_INDIRECT;
668 elements++;
669 emit_member_table(arg, v);
vlm39ba4c42004-09-22 16:06:28 +0000670 });
671 OUT("};\n");
672 } else {
673 elements = 0;
674 }
vlmfa67ddc2004-06-03 03:38:44 +0000675
vlm6e73a042004-08-11 07:17:22 +0000676
vlmfa67ddc2004-06-03 03:38:44 +0000677 if(arg->embed) {
678 /*
679 * Our parent structure has already taken this into account.
680 */
vlm72425de2004-09-13 08:31:01 +0000681 tv_mode = _TVM_SAME;
682 tags_count = all_tags_count = 0;
vlmfa67ddc2004-06-03 03:38:44 +0000683 } else {
vlm72425de2004-09-13 08:31:01 +0000684 tv_mode = emit_tags_vectors(arg, expr,
685 &tags_count, &all_tags_count);
vlmfa67ddc2004-06-03 03:38:44 +0000686 }
vlmfa67ddc2004-06-03 03:38:44 +0000687
688 /*
689 * Tags to elements map.
690 */
vlm940bc6b2004-10-03 09:13:30 +0000691 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000692
vlm6e73a042004-08-11 07:17:22 +0000693 p = MKID(expr->Identifier);
vlma5dcb912004-09-29 13:16:40 +0000694 OUT("static asn_CHOICE_specifics_t asn_DEF_%s_specs = {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000695 INDENTED(
696 OUT("sizeof(struct %s),\n", p);
vlma5dcb912004-09-29 13:16:40 +0000697 OUT("offsetof(struct %s, _asn_ctx),\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000698 OUT("offsetof(struct %s, present),\n", p);
699 OUT("sizeof(((struct %s *)0)->present),\n", p);
vlma5dcb912004-09-29 13:16:40 +0000700 OUT("asn_DEF_%s_tag2el,\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000701 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
vlm79b08d52004-07-01 00:52:50 +0000702 OUT("%d\t/* Whether extensible */\n",
703 check_if_extensible(expr));
vlmfa67ddc2004-06-03 03:38:44 +0000704 );
705 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000706
707 /*
vlma5dcb912004-09-29 13:16:40 +0000708 * Emit asn_DEF_xxx table.
vlm4e554992004-08-25 02:03:12 +0000709 */
vlm72425de2004-09-13 08:31:01 +0000710 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
vlm86f5ed22004-09-26 13:11:31 +0000711 ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000712
vlmfa67ddc2004-06-03 03:38:44 +0000713 REDIR(OT_TYPE_DECLS);
714
715 return 0;
vlmedf203f2005-01-17 11:57:48 +0000716} /* _CHOICE_def() */
vlmfa67ddc2004-06-03 03:38:44 +0000717
718int
719asn1c_lang_C_type_REFERENCE(arg_t *arg) {
720 asn1p_ref_t *ref;
721
722 ref = arg->expr->reference;
723 if(ref->components[ref->comp_count-1].name[0] == '&') {
vlmfa67ddc2004-06-03 03:38:44 +0000724 asn1p_expr_t *extract;
725 arg_t tmp;
726 int ret;
727
vlm39ba4c42004-09-22 16:06:28 +0000728 extract = asn1f_class_access_ex(arg->asn, arg->expr->module,
vlmdae7f9d2004-08-22 03:25:24 +0000729 arg->expr, ref);
vlmfa67ddc2004-06-03 03:38:44 +0000730 if(extract == NULL)
731 return -1;
732
vlmdae7f9d2004-08-22 03:25:24 +0000733 extract = asn1p_expr_clone(extract, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000734 if(extract) {
735 if(extract->Identifier)
736 free(extract->Identifier);
737 extract->Identifier = strdup(arg->expr->Identifier);
738 if(extract->Identifier == NULL) {
739 asn1p_expr_free(extract);
740 return -1;
741 }
742 } else {
743 return -1;
744 }
745
746 tmp = *arg;
747 tmp.asn = arg->asn;
vlmdae7f9d2004-08-22 03:25:24 +0000748 tmp.mod = extract->module;
vlmfa67ddc2004-06-03 03:38:44 +0000749 tmp.expr = extract;
750
751 ret = arg->default_cb(&tmp);
752
753 asn1p_expr_free(extract);
754
755 return ret;
756 }
757
758
759 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
760}
761
762int
763asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
764 asn1p_expr_t *expr = arg->expr;
vlm6e73a042004-08-11 07:17:22 +0000765 int tags_count;
vlm72425de2004-09-13 08:31:01 +0000766 int all_tags_count;
767 enum tvm_compat tv_mode;
vlmfa67ddc2004-06-03 03:38:44 +0000768 char *p;
769
770 if(arg->embed) {
vlma5dcb912004-09-29 13:16:40 +0000771 enum tnfmt tnfmt = TNF_CTYPE;
772
773 /*
774 * If this is an optional compound type,
775 * refer it using "struct X" convention,
776 * as it may recursively include the current structure.
777 */
778 if(expr->marker.flags) {
779 asn1p_expr_t *terminal;
780 terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
781 if(terminal
782 && (terminal->expr_type & ASN_CONSTR_MASK)) {
783 REDIR(OT_DEPS);
784 tnfmt = TNF_RSAFE;
785 OUT("\n");
786 OUT("%s;\t/* Forward declaration */\n",
787 asn1c_type_name(arg, arg->expr, tnfmt));
788 }
789 }
790
vlmfa67ddc2004-06-03 03:38:44 +0000791 REDIR(OT_TYPE_DECLS);
792
vlma5dcb912004-09-29 13:16:40 +0000793 OUT("%s\t", asn1c_type_name(arg, arg->expr, tnfmt));
vlma02b74d2004-09-15 11:54:38 +0000794 OUT("%s", expr->marker.flags?"*":" ");
vlmdae7f9d2004-08-22 03:25:24 +0000795 OUT("%s", MKID(expr->Identifier));
vlma02b74d2004-09-15 11:54:38 +0000796 if((expr->marker.flags & EM_DEFAULT) == EM_DEFAULT)
797 OUT("\t/* DEFAULT %s */",
798 asn1f_printable_value(expr->marker.default_value));
799 else if((expr->marker.flags & EM_OPTIONAL) == EM_OPTIONAL)
vlmddd5a7d2004-09-10 09:18:20 +0000800 OUT("\t/* OPTIONAL */");
vlmb2839012004-08-20 13:37:01 +0000801
802 REDIR(OT_TYPE_DECLS);
vlmfa67ddc2004-06-03 03:38:44 +0000803 return 0;
804 }
805
vlmfa67ddc2004-06-03 03:38:44 +0000806
vlm33a4ff12004-08-11 05:21:32 +0000807 GEN_INCLUDE(asn1c_type_name(arg, expr, TNF_INCLUDE));
vlmfa67ddc2004-06-03 03:38:44 +0000808
809 REDIR(OT_TYPE_DECLS);
810
811 OUT("typedef %s\t", asn1c_type_name(arg, arg->expr, TNF_CTYPE));
vlma02b74d2004-09-15 11:54:38 +0000812 OUT("%s", expr->marker.flags?"*":" ");
vlmdae7f9d2004-08-22 03:25:24 +0000813 OUT("%s_t", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000814
vlm86f5ed22004-09-26 13:11:31 +0000815 /*
816 * If this type just blindly refers the other type, alias it.
817 * Type1 ::= Type2
818 */
819 if((!expr->constraints || (arg->flags & A1C_NO_CONSTRAINTS))
820 && expr->tag.tag_class == TC_NOCLASS
821 && !TQ_FIRST(&(expr->members))
822 ) {
823 char *type_name;
824 REDIR(OT_FUNC_DECLS);
825 type_name = asn1c_type_name(arg, expr, TNF_SAFE);
826 OUT("/* This type is equivalent to %s */\n", type_name);
827 p = MKID(expr->Identifier);
828 if(HIDE_INNER_DEFS) OUT("/* ");
vlma5dcb912004-09-29 13:16:40 +0000829 OUT("#define\tasn_DEF_%s\t", p);
vlm86f5ed22004-09-26 13:11:31 +0000830 type_name = asn1c_type_name(arg, expr, TNF_SAFE);
vlma5dcb912004-09-29 13:16:40 +0000831 OUT("asn_DEF_%s\n", type_name);
vlm86f5ed22004-09-26 13:11:31 +0000832 if(HIDE_INNER_DEFS)
833 OUT(" // (Use -fall-defs-global to expose) */");
834 REDIR(OT_CODE);
835 OUT("/* This type is equivalent to %s */\n", type_name);
836 OUT("\n");
837 REDIR(OT_TYPE_DECLS);
838 return 0;
839 }
840
vlmfa67ddc2004-06-03 03:38:44 +0000841 REDIR(OT_STAT_DEFS);
842
vlm4a3f5822004-06-28 21:13:46 +0000843 /*
vlma5dcb912004-09-29 13:16:40 +0000844 * Print out asn_DEF_<type>_[all_]tags[] vectors.
vlm4a3f5822004-06-28 21:13:46 +0000845 */
vlm72425de2004-09-13 08:31:01 +0000846 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
vlmfa67ddc2004-06-03 03:38:44 +0000847
vlm72425de2004-09-13 08:31:01 +0000848 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, 0,
vlm86f5ed22004-09-26 13:11:31 +0000849 ETD_NO_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000850
vlmb2839012004-08-20 13:37:01 +0000851 REDIR(OT_CODE);
852
vlmfa67ddc2004-06-03 03:38:44 +0000853 /*
854 * Constraint checking.
855 */
vlm86f5ed22004-09-26 13:11:31 +0000856 if(!(arg->flags & A1C_NO_CONSTRAINTS)) {
857 p = MKID(expr->Identifier);
858 OUT("int\n");
859 OUT("%s_constraint("
vlma5dcb912004-09-29 13:16:40 +0000860 "asn_TYPE_descriptor_t *td, const void *sptr,\n", p);
vlm86f5ed22004-09-26 13:11:31 +0000861 INDENT(+1);
862 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {");
863 OUT("\n");
864 if(asn1c_emit_constraint_checking_code(arg) == 1) {
865 OUT("/* Replace with underlying type checker */\n");
866 OUT("td->check_constraints "
vlma5dcb912004-09-29 13:16:40 +0000867 "= asn_DEF_%s.check_constraints;\n",
vlm86f5ed22004-09-26 13:11:31 +0000868 asn1c_type_name(arg, expr, TNF_SAFE));
869 OUT("return td->check_constraints"
870 "(td, sptr, app_errlog, app_key);\n");
vlm1d036692004-08-19 13:29:46 +0000871 }
vlm86f5ed22004-09-26 13:11:31 +0000872 INDENT(-1);
873 OUT("}\n");
874 OUT("\n");
vlmfa67ddc2004-06-03 03:38:44 +0000875 }
vlmfa67ddc2004-06-03 03:38:44 +0000876
877 /*
878 * Emit suicidal functions.
879 */
880
vlmfa67ddc2004-06-03 03:38:44 +0000881 /*
882 * This function replaces certain fields from the definition
883 * of a type with the corresponding fields from the basic type
884 * (from which the current type is inherited).
885 */
vlmfa67ddc2004-06-03 03:38:44 +0000886 OUT("/*\n");
vlmb2839012004-08-20 13:37:01 +0000887 OUT(" * This type is implemented using %s,\n",
888 asn1c_type_name(arg, expr, TNF_SAFE));
vlmdcd32fe2004-09-23 22:20:47 +0000889 OUT(" * so here we adjust the DEF accordingly.\n");
vlmfa67ddc2004-06-03 03:38:44 +0000890 OUT(" */\n");
891 OUT("static void\n");
vlmb2839012004-08-20 13:37:01 +0000892 p = MKID(expr->Identifier);
vlma5dcb912004-09-29 13:16:40 +0000893 OUT("%s_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000894 INDENT(+1);
vlmb2839012004-08-20 13:37:01 +0000895 {
vlm39ba4c42004-09-22 16:06:28 +0000896 asn1p_expr_t *terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
vlmb2839012004-08-20 13:37:01 +0000897 char *type_name = asn1c_type_name(arg, expr, TNF_SAFE);
vlma5dcb912004-09-29 13:16:40 +0000898 OUT("td->free_struct = asn_DEF_%s.free_struct;\n", type_name);
899 OUT("td->print_struct = asn_DEF_%s.print_struct;\n", type_name);
900 OUT("td->ber_decoder = asn_DEF_%s.ber_decoder;\n", type_name);
901 OUT("td->der_encoder = asn_DEF_%s.der_encoder;\n", type_name);
902 OUT("td->xer_decoder = asn_DEF_%s.xer_decoder;\n", type_name);
903 OUT("td->xer_encoder = asn_DEF_%s.xer_encoder;\n", type_name);
vlm1308d2b2004-09-10 15:49:15 +0000904 if(!terminal && !tags_count) {
vlm72425de2004-09-13 08:31:01 +0000905 OUT("/* The next four lines are here because of -fknown-extern-type */\n");
vlma5dcb912004-09-29 13:16:40 +0000906 OUT("td->tags = asn_DEF_%s.tags;\n", type_name);
907 OUT("td->tags_count = asn_DEF_%s.tags_count;\n", type_name);
908 OUT("td->all_tags = asn_DEF_%s.all_tags;\n", type_name);
909 OUT("td->all_tags_count = asn_DEF_%s.all_tags_count;\n",type_name);
vlm1308d2b2004-09-10 15:49:15 +0000910 OUT("/* End of these lines */\n");
911 }
vlma5dcb912004-09-29 13:16:40 +0000912 OUT("td->elements = asn_DEF_%s.elements;\n", type_name);
913 OUT("td->elements_count = asn_DEF_%s.elements_count;\n", type_name);
914 OUT("td->specifics = asn_DEF_%s.specifics;\n", type_name);
vlmb2839012004-08-20 13:37:01 +0000915 }
vlmfa67ddc2004-06-03 03:38:44 +0000916 INDENT(-1);
917 OUT("}\n");
918 OUT("\n");
vlmfa67ddc2004-06-03 03:38:44 +0000919
920 p = MKID(expr->Identifier);
vlm39ba4c42004-09-22 16:06:28 +0000921 OUT("void\n");
vlma5dcb912004-09-29 13:16:40 +0000922 OUT("%s_free(asn_TYPE_descriptor_t *td,\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000923 INDENTED(
vlm39ba4c42004-09-22 16:06:28 +0000924 OUT("\tvoid *struct_ptr, int contents_only) {\n");
vlmb2839012004-08-20 13:37:01 +0000925 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000926 OUT("td->free_struct(td, struct_ptr, contents_only);\n");
vlmfa67ddc2004-06-03 03:38:44 +0000927 );
928 OUT("}\n");
929 OUT("\n");
930
931 p = MKID(expr->Identifier);
932 OUT("int\n");
vlma5dcb912004-09-29 13:16:40 +0000933 OUT("%s_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000934 INDENTED(
935 OUT("\tint ilevel, asn_app_consume_bytes_f *cb, void *app_key) {\n");
vlmb2839012004-08-20 13:37:01 +0000936 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000937 OUT("return td->print_struct(td, struct_ptr, ilevel, cb, app_key);\n");
938 );
939 OUT("}\n");
940 OUT("\n");
941
942 p = MKID(expr->Identifier);
vlm9de248e2004-10-20 15:50:55 +0000943 OUT("asn_dec_rval_t\n");
vlma5dcb912004-09-29 13:16:40 +0000944 OUT("%s_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000945 INDENTED(
vlm39ba4c42004-09-22 16:06:28 +0000946 OUT("\tvoid **structure, void *bufptr, size_t size, int tag_mode) {\n");
vlmb2839012004-08-20 13:37:01 +0000947 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlma5dcb912004-09-29 13:16:40 +0000948 OUT("return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);\n");
vlm39ba4c42004-09-22 16:06:28 +0000949 );
950 OUT("}\n");
951 OUT("\n");
952
953 p = MKID(expr->Identifier);
954 OUT("asn_enc_rval_t\n");
vlma5dcb912004-09-29 13:16:40 +0000955 OUT("%s_encode_der(asn_TYPE_descriptor_t *td,\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000956 INDENTED(
957 OUT("\tvoid *structure, int tag_mode, ber_tlv_tag_t tag,\n");
958 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
959 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
960 OUT("return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);\n");
961 );
962 OUT("}\n");
963 OUT("\n");
964
965 p = MKID(expr->Identifier);
vlme03646b2004-10-23 13:34:00 +0000966 OUT("asn_dec_rval_t\n");
967 OUT("%s_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n", p);
968 INDENTED(
969 OUT("\tvoid **structure, const char *opt_mname, void *bufptr, size_t size) {\n");
970 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
971 OUT("return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size);\n");
972 );
973 OUT("}\n");
974 OUT("\n");
975
976 p = MKID(expr->Identifier);
vlm39ba4c42004-09-22 16:06:28 +0000977 OUT("asn_enc_rval_t\n");
vlma5dcb912004-09-29 13:16:40 +0000978 OUT("%s_encode_xer(asn_TYPE_descriptor_t *td, void *structure,\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000979 INDENTED(
980 OUT("\tint ilevel, enum xer_encoder_flags_e flags,\n");
981 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
982 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
983 OUT("return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);\n");
vlmfa67ddc2004-06-03 03:38:44 +0000984 );
985 OUT("}\n");
986 OUT("\n");
987
988 REDIR(OT_FUNC_DECLS);
989
990 p = MKID(expr->Identifier);
vlm12c8f692004-09-06 08:07:29 +0000991 if(HIDE_INNER_DEFS) OUT("/* ");
vlma5dcb912004-09-29 13:16:40 +0000992 OUT("extern asn_TYPE_descriptor_t asn_DEF_%s;", p);
vlm12c8f692004-09-06 08:07:29 +0000993 if(HIDE_INNER_DEFS) OUT(" // (Use -fall-defs-global to expose) */");
994 OUT("\n");
vlm39ba4c42004-09-22 16:06:28 +0000995 OUT("asn_struct_free_f %s_free;\n", p);
996 OUT("asn_struct_print_f %s_print;\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000997 OUT("asn_constr_check_f %s_constraint;\n", p);
998 OUT("ber_type_decoder_f %s_decode_ber;\n", p);
999 OUT("der_type_encoder_f %s_encode_der;\n", p);
vlme03646b2004-10-23 13:34:00 +00001000 OUT("xer_type_decoder_f %s_decode_xer;\n", p);
vlm39ba4c42004-09-22 16:06:28 +00001001 OUT("xer_type_encoder_f %s_encode_xer;\n", p);
vlmfa67ddc2004-06-03 03:38:44 +00001002
vlm33a4ff12004-08-11 05:21:32 +00001003 REDIR(OT_TYPE_DECLS);
1004
vlmfa67ddc2004-06-03 03:38:44 +00001005 return 0;
1006}
1007
1008int
1009asn1c_lang_C_type_EXTENSIBLE(arg_t *arg) {
1010
1011 OUT("/*\n");
1012 OUT(" * This type is extensible,\n");
1013 OUT(" * possible extensions are below.\n");
1014 OUT(" */\n");
1015
1016 return 0;
1017}
1018
vlm79b08d52004-07-01 00:52:50 +00001019static int check_if_extensible(asn1p_expr_t *expr) {
1020 asn1p_expr_t *v;
1021 TQ_FOR(v, &(expr->members), next) {
1022 if(v->expr_type == A1TC_EXTENSIBLE) return 1;
1023 }
1024 return 0;
1025}
1026
vlmfa67ddc2004-06-03 03:38:44 +00001027static int
vlma8a86cc2004-09-10 06:07:18 +00001028_print_tag(arg_t *arg, struct asn1p_type_tag_s *tag) {
vlmfa67ddc2004-06-03 03:38:44 +00001029
1030 OUT("(");
vlma8a86cc2004-09-10 06:07:18 +00001031 switch(tag->tag_class) {
vlmfa67ddc2004-06-03 03:38:44 +00001032 case TC_UNIVERSAL: OUT("ASN_TAG_CLASS_UNIVERSAL"); break;
1033 case TC_APPLICATION: OUT("ASN_TAG_CLASS_APPLICATION"); break;
1034 case TC_CONTEXT_SPECIFIC: OUT("ASN_TAG_CLASS_CONTEXT"); break;
1035 case TC_PRIVATE: OUT("ASN_TAG_CLASS_PRIVATE"); break;
1036 case TC_NOCLASS:
1037 break;
1038 }
vlm47ae1582004-09-24 21:01:43 +00001039 OUT(" | (%" PRIdASN " << 2))", tag->tag_value);
vlmfa67ddc2004-06-03 03:38:44 +00001040
1041 return 0;
1042}
1043
vlm4e03ce22004-06-06 07:20:17 +00001044
1045static int
1046_tag2el_cmp(const void *ap, const void *bp) {
1047 const tag2el_t *a = ap;
1048 const tag2el_t *b = bp;
1049 const struct asn1p_type_tag_s *ta = &a->el_tag;
1050 const struct asn1p_type_tag_s *tb = &b->el_tag;
1051
1052 if(ta->tag_class == tb->tag_class) {
1053 if(ta->tag_value == tb->tag_value) {
1054 /*
1055 * Sort by their respective positions.
1056 */
1057 if(a->el_no < b->el_no)
1058 return -1;
1059 else if(a->el_no > b->el_no)
1060 return 1;
1061 return 0;
1062 } else if(ta->tag_value < tb->tag_value)
1063 return -1;
1064 else
1065 return 1;
1066 } else if(ta->tag_class < tb->tag_class) {
1067 return -1;
1068 } else {
1069 return 1;
1070 }
1071}
1072
vlmfa67ddc2004-06-03 03:38:44 +00001073/*
1074 * For constructed types, number of external tags may be greater than
1075 * number of elements in the type because of CHOICE type.
1076 * T ::= SET { -- Three possible tags:
1077 * a INTEGER, -- One tag is here...
1078 * b Choice1 -- ... and two more tags are there.
1079 * }
1080 * Choice1 ::= CHOICE {
1081 * s1 IA5String,
1082 * s2 ObjectDescriptor
1083 * }
1084 */
1085static int
vlm940bc6b2004-10-03 09:13:30 +00001086_fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
vlmfa67ddc2004-06-03 03:38:44 +00001087 asn1p_expr_t *expr = arg->expr;
1088 arg_t tmparg = *arg;
1089 asn1p_expr_t *v;
1090 int element = 0;
vlm940bc6b2004-10-03 09:13:30 +00001091 int original_count = *count;
1092 int sort_until = -1;
vlmfa67ddc2004-06-03 03:38:44 +00001093
1094 TQ_FOR(v, &(expr->members), next) {
vlm940bc6b2004-10-03 09:13:30 +00001095 if(v->expr_type == A1TC_EXTENSIBLE) {
1096 /*
1097 * CANONICAL-XER mandates sorting
1098 * only for the root part.
1099 */
1100 if(flags == FTE_CANONICAL_XER
1101 && sort_until == -1)
1102 sort_until = *count;
vlmfa67ddc2004-06-03 03:38:44 +00001103 continue;
vlm940bc6b2004-10-03 09:13:30 +00001104 }
vlmfa67ddc2004-06-03 03:38:44 +00001105
1106 tmparg.expr = v;
1107
1108 if(_add_tag2el_member(&tmparg, tag2el, count,
vlm940bc6b2004-10-03 09:13:30 +00001109 (el_no==-1)?element:el_no, flags)) {
vlmfa67ddc2004-06-03 03:38:44 +00001110 return -1;
1111 }
1112
1113 element++;
1114 }
1115
vlm940bc6b2004-10-03 09:13:30 +00001116
1117 if(flags == FTE_CANONICAL_XER) {
1118 if(sort_until == -1) sort_until = *count;
1119 qsort((*tag2el) + original_count,
1120 sort_until - original_count,
1121 sizeof(**tag2el), _tag2el_cmp);
1122 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1123 && (sort_until - original_count) >= 1) {
1124 /* Only take in account the root component */
1125 *count = original_count + 1;
1126 }
1127 } else {
1128 /*
1129 * Sort the map according to canonical order of their
1130 * tags and element numbers.
1131 */
1132 qsort(*tag2el, *count, sizeof(**tag2el), _tag2el_cmp);
1133 }
vlm4e03ce22004-06-06 07:20:17 +00001134
vlmc8aeab42004-06-14 13:09:45 +00001135 /*
1136 * Initialize .toff_{first|last} members.
1137 */
1138 if(*count) {
1139 struct asn1p_type_tag_s *cur_tag = 0;
1140 tag2el_t *cur = *tag2el;
1141 tag2el_t *end = cur + *count;
1142 int occur, i;
1143 for(occur = 0; cur < end; cur++) {
1144 if(cur_tag == 0
1145 || cur_tag->tag_value != cur->el_tag.tag_value
1146 || cur_tag->tag_class != cur->el_tag.tag_class) {
1147 cur_tag = &cur->el_tag;
1148 occur = 0;
1149 } else {
1150 occur++;
1151 }
1152 cur->toff_first = -occur;
1153 for(i = 0; i >= -occur; i--)
1154 cur[i].toff_last = -i;
1155 }
1156 }
1157
vlmfa67ddc2004-06-03 03:38:44 +00001158 return 0;
1159}
1160
1161static int
vlm940bc6b2004-10-03 09:13:30 +00001162_add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
vlmfa67ddc2004-06-03 03:38:44 +00001163 struct asn1p_type_tag_s tag;
1164 int ret;
1165
1166 assert(el_no >= 0);
1167
vlm39ba4c42004-09-22 16:06:28 +00001168 ret = asn1f_fetch_outmost_tag(arg->asn, arg->expr->module,
1169 arg->expr, &tag, 1);
vlmfa67ddc2004-06-03 03:38:44 +00001170 if(ret == 0) {
vlme2070ea2004-09-04 04:42:29 +00001171 tag2el_t *te;
1172 int new_count = (*count) + 1;
vlmfa67ddc2004-06-03 03:38:44 +00001173 void *p;
vlme2070ea2004-09-04 04:42:29 +00001174
vlm2de0e792004-09-05 10:42:33 +00001175 if(tag.tag_value == -1) {
1176 /*
1177 * This is an untagged ANY type,
1178 * proceed without adding a tag
1179 */
1180 return 0;
1181 }
1182
vlme2070ea2004-09-04 04:42:29 +00001183 p = realloc(*tag2el, new_count * sizeof(tag2el_t));
vlmfa67ddc2004-06-03 03:38:44 +00001184 if(p) *tag2el = p;
1185 else return -1;
1186
1187 DEBUG("Found tag for %s: %ld",
1188 arg->expr->Identifier,
1189 (long)tag.tag_value);
1190
vlme2070ea2004-09-04 04:42:29 +00001191 te = &((*tag2el)[*count]);
1192 te->el_tag = tag;
1193 te->el_no = el_no;
1194 te->from_expr = arg->expr;
1195 *count = new_count;
vlmfa67ddc2004-06-03 03:38:44 +00001196 return 0;
1197 }
1198
1199 DEBUG("Searching tag in complex expression %s:%x at line %d",
1200 arg->expr->Identifier,
1201 arg->expr->expr_type,
1202 arg->expr->_lineno);
1203
1204 /*
1205 * Iterate over members of CHOICE type.
1206 */
1207 if(arg->expr->expr_type == ASN_CONSTR_CHOICE) {
vlm940bc6b2004-10-03 09:13:30 +00001208 return _fill_tag2el_map(arg, tag2el, count, el_no, flags);
vlmfa67ddc2004-06-03 03:38:44 +00001209 }
1210
1211 if(arg->expr->expr_type == A1TC_REFERENCE) {
1212 arg_t tmp = *arg;
1213 asn1p_expr_t *expr;
vlmdae7f9d2004-08-22 03:25:24 +00001214 expr = asn1f_lookup_symbol_ex(tmp.asn, tmp.mod, tmp.expr,
vlmfa67ddc2004-06-03 03:38:44 +00001215 arg->expr->reference);
1216 if(expr) {
vlmdae7f9d2004-08-22 03:25:24 +00001217 tmp.mod = expr->module;
vlmfa67ddc2004-06-03 03:38:44 +00001218 tmp.expr = expr;
vlm940bc6b2004-10-03 09:13:30 +00001219 return _add_tag2el_member(&tmp, tag2el, count, el_no, flags);
vlmfa67ddc2004-06-03 03:38:44 +00001220 } else {
1221 FATAL("Cannot dereference %s at line %d",
1222 arg->expr->Identifier,
1223 arg->expr->_lineno);
1224 return -1;
1225 }
1226 }
1227
1228 DEBUG("No tag for %s at line %d",
1229 arg->expr->Identifier,
1230 arg->expr->_lineno);
1231
1232 return -1;
1233}
1234
1235static int
vlm940bc6b2004-10-03 09:13:30 +00001236emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier) {
vlm4e03ce22004-06-06 07:20:17 +00001237 asn1p_expr_t *expr = arg->expr;
1238
vlm940bc6b2004-10-03 09:13:30 +00001239 OUT("static asn_TYPE_tag2member_t asn_DEF_%s_tag2el%s[] = {\n",
1240 MKID(expr->Identifier), opt_modifier?opt_modifier:"");
vlm4e03ce22004-06-06 07:20:17 +00001241 if(tag2el_count) {
1242 int i;
1243 for(i = 0; i < tag2el_count; i++) {
1244 OUT(" { ");
vlma8a86cc2004-09-10 06:07:18 +00001245 _print_tag(arg, &tag2el[i].el_tag);
vlm4e03ce22004-06-06 07:20:17 +00001246 OUT(", ");
vlmc8aeab42004-06-14 13:09:45 +00001247 OUT("%d, ", tag2el[i].el_no);
1248 OUT("%d, ", tag2el[i].toff_first);
1249 OUT("%d ", tag2el[i].toff_last);
vlm4e03ce22004-06-06 07:20:17 +00001250 OUT("}, /* %s at %d */\n",
1251 tag2el[i].from_expr->Identifier,
1252 tag2el[i].from_expr->_lineno
1253 );
1254 }
1255 }
1256 OUT("};\n");
1257
1258 return 0;;
1259}
1260
vlm72425de2004-09-13 08:31:01 +00001261static enum tvm_compat
1262emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tags_count_r, int *all_tags_count_r) {
1263 struct asn1p_type_tag_s *tags = 0; /* Effective tags */
1264 struct asn1p_type_tag_s *all_tags = 0; /* The full array */
vlm6e73a042004-08-11 07:17:22 +00001265 int tags_count = 0;
vlm72425de2004-09-13 08:31:01 +00001266 int all_tags_count = 0;
1267 enum tvm_compat tv_mode = _TVM_SAME;
vlm1308d2b2004-09-10 15:49:15 +00001268 int i;
vlm4a3f5822004-06-28 21:13:46 +00001269
vlmc6de2c42004-09-14 14:10:10 +00001270 /* Cleanup before proceeding. */
1271 *tags_count_r = 0;
1272 *all_tags_count_r = 0;
1273
vlm1308d2b2004-09-10 15:49:15 +00001274 /* Fetch a chain of tags */
vlm39ba4c42004-09-22 16:06:28 +00001275 tags_count = asn1f_fetch_tags(arg->asn, expr->module, expr, &tags, 0);
vlmc6de2c42004-09-14 14:10:10 +00001276 if(tags_count < 0)
1277 return -1;
vlm6e73a042004-08-11 07:17:22 +00001278
vlm72425de2004-09-13 08:31:01 +00001279 /* Fetch a chain of tags */
vlm39ba4c42004-09-22 16:06:28 +00001280 all_tags_count = asn1f_fetch_tags(arg->asn, expr->module, expr,
vlm72425de2004-09-13 08:31:01 +00001281 &all_tags, AFT_FULL_COLLECT);
1282 if(all_tags_count < 0) {
1283 if(tags) free(tags);
1284 return -1;
vlmfb41dbb2004-09-08 00:28:57 +00001285 }
vlm1308d2b2004-09-10 15:49:15 +00001286
vlm72425de2004-09-13 08:31:01 +00001287 assert(tags_count <= all_tags_count);
1288 assert((tags_count?0:1) == (all_tags_count?0:1));
vlm4a3f5822004-06-28 21:13:46 +00001289
vlm72425de2004-09-13 08:31:01 +00001290 if(tags_count <= all_tags_count) {
1291 for(i = 0; i < tags_count; i++) {
1292 if(tags[i].tag_value != all_tags[i].tag_value
1293 || tags[i].tag_class != all_tags[i].tag_class) {
1294 tv_mode = _TVM_DIFFERENT;
1295 break;
1296 }
1297 }
1298 if(i == tags_count && tags_count < all_tags_count)
1299 tv_mode = _TVM_SUBSET;
1300 } else {
1301 tv_mode = _TVM_DIFFERENT;
1302 }
1303
1304#define EMIT_TAGS_TABLE(name, tags, tags_count) do { \
vlma5dcb912004-09-29 13:16:40 +00001305 OUT("static ber_tlv_tag_t asn_DEF_%s%s_tags[] = {\n", \
vlm72425de2004-09-13 08:31:01 +00001306 MKID(expr->Identifier), name); \
1307 INDENT(+1); \
1308 /* Print the array of collected tags */ \
1309 for(i = 0; i < tags_count; i++) { \
1310 if(i) OUT(",\n"); \
1311 _print_tag(arg, &tags[i]); \
1312 } \
1313 OUT("\n"); \
1314 INDENT(-1); \
1315 OUT("};\n"); \
1316 } while(0)
1317
1318 if(tags_count) {
1319 if(tv_mode == _TVM_SUBSET)
1320 EMIT_TAGS_TABLE("", all_tags, all_tags_count);
1321 else
1322 EMIT_TAGS_TABLE("", tags, tags_count);
1323 }
1324
1325 if(all_tags_count) {
1326 if(tv_mode == _TVM_DIFFERENT)
1327 EMIT_TAGS_TABLE("_all", all_tags, all_tags_count);
1328 }
1329
1330 if(tags) free(tags);
1331 if(all_tags) free(all_tags);
1332
1333 *tags_count_r = tags_count;
1334 *all_tags_count_r = all_tags_count;
1335
1336 return tv_mode;
vlm4a3f5822004-06-28 21:13:46 +00001337}
vlmb2839012004-08-20 13:37:01 +00001338
1339static int
vlm4e554992004-08-25 02:03:12 +00001340expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
vlmb2839012004-08-20 13:37:01 +00001341 asn1p_expr_t *topmost_parent;
1342 asn1p_expr_t *v;
1343 int elements = 0;
1344
vlm39ba4c42004-09-22 16:06:28 +00001345 topmost_parent = asn1f_find_terminal_type_ex(arg->asn, expr);
vlmb2839012004-08-20 13:37:01 +00001346 if(!topmost_parent) return 0;
1347
1348 if(!(topmost_parent->expr_type & ASN_CONSTR_MASK))
1349 return 0;
1350
1351 TQ_FOR(v, &(topmost_parent->members), next) {
1352 if(v->expr_type != A1TC_EXTENSIBLE)
1353 elements++;
1354 }
1355
1356 return elements;
1357}
1358
1359static int
vlm4e554992004-08-25 02:03:12 +00001360emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
vlmdae7f9d2004-08-22 03:25:24 +00001361 static int global_memb_unique;
vlmb2839012004-08-20 13:37:01 +00001362 int save_target;
1363 arg_t tmp_arg;
vlm060fe2a2004-09-10 09:37:12 +00001364 struct asn1p_type_tag_s outmost_tag_s;
1365 struct asn1p_type_tag_s *outmost_tag;
vlmb2839012004-08-20 13:37:01 +00001366 char *p;
1367
vlm060fe2a2004-09-10 09:37:12 +00001368 if(asn1f_fetch_outmost_tag(arg->asn,
1369 expr->module, expr, &outmost_tag_s, 1)) {
1370 outmost_tag = 0;
1371 } else {
1372 outmost_tag = &outmost_tag_s;
1373 }
1374
vlmb2839012004-08-20 13:37:01 +00001375 OUT("{ ");
vlm060fe2a2004-09-10 09:37:12 +00001376
1377 if(outmost_tag && outmost_tag->tag_value == -1)
1378 OUT("ATF_OPEN_TYPE | ");
vlma02b74d2004-09-15 11:54:38 +00001379 OUT("%s, ", expr->marker.flags?"ATF_POINTER":"ATF_NOFLAGS");
1380 if((expr->marker.flags & EM_OPTIONAL) == EM_OPTIONAL) {
vlmb2839012004-08-20 13:37:01 +00001381 asn1p_expr_t *tv;
1382 int opts = 0;
vlma02b74d2004-09-15 11:54:38 +00001383 for(tv = expr; tv && tv->marker.flags;
vlmb2839012004-08-20 13:37:01 +00001384 tv = TQ_NEXT(tv, next), opts++) {
1385 if(tv->expr_type == A1TC_EXTENSIBLE)
1386 opts--;
1387 }
1388 OUT("%d, ", opts);
1389 } else {
1390 OUT("0, ");
1391 }
vlm39ba4c42004-09-22 16:06:28 +00001392 if(expr->_anonymous_type) {
1393 assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
1394 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
1395 OUT("0,\n");
1396 } else {
vlmb2839012004-08-20 13:37:01 +00001397 OUT("offsetof(struct %s, ", MKID(arg->expr->Identifier));
1398 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1399 && (!UNNAMED_UNIONS)) OUT("choice.");
1400 OUT("%s),\n", MKID(expr->Identifier));
vlmb2839012004-08-20 13:37:01 +00001401 }
1402 INDENT(+1);
1403 if(C99_MODE) OUT(".tag = ");
vlm060fe2a2004-09-10 09:37:12 +00001404 if(outmost_tag) {
1405 if(outmost_tag->tag_value == -1)
1406 OUT("-1 /* Ambiguous tag (ANY?) */");
1407 else
1408 _print_tag(arg, outmost_tag);
vlma8a86cc2004-09-10 06:07:18 +00001409 } else {
vlm060fe2a2004-09-10 09:37:12 +00001410 OUT("-1 /* Ambiguous tag (CHOICE?) */");
vlma8a86cc2004-09-10 06:07:18 +00001411 }
vlm060fe2a2004-09-10 09:37:12 +00001412
vlmb2839012004-08-20 13:37:01 +00001413 OUT(",\n");
1414 if(C99_MODE) OUT(".tag_mode = ");
1415 if(expr->tag.tag_class) {
1416 if(expr->tag.tag_mode == TM_IMPLICIT)
1417 OUT("-1,\t/* IMPLICIT tag at current level */\n");
1418 else
1419 OUT("+1,\t/* EXPLICIT tag at current level */\n");
1420 } else {
1421 OUT("0,\n");
1422 }
1423 if(C99_MODE) OUT(".type = ");
vlm39ba4c42004-09-22 16:06:28 +00001424 if(expr->_anonymous_type && (expr->expr_type & ASN_CONSTR_MASK)) {
vlma5dcb912004-09-29 13:16:40 +00001425 OUT("(void *)&asn_DEF_%s_member,\n",
vlmdae7f9d2004-08-22 03:25:24 +00001426 MKID(arg->expr->Identifier));
vlm4e554992004-08-25 02:03:12 +00001427 } else if(expr->expr_type & ASN_CONSTR_MASK) {
vlma5dcb912004-09-29 13:16:40 +00001428 OUT("(void *)&asn_DEF_%s,\n",
vlm4e554992004-08-25 02:03:12 +00001429 MKID(expr->Identifier));
vlmdae7f9d2004-08-22 03:25:24 +00001430 } else {
vlma5dcb912004-09-29 13:16:40 +00001431 OUT("(void *)&asn_DEF_%s,\n",
vlmdae7f9d2004-08-22 03:25:24 +00001432 asn1c_type_name(arg, expr, TNF_SAFE));
1433 }
vlmb2839012004-08-20 13:37:01 +00001434 if(C99_MODE) OUT(".memb_constraints = ");
1435 if(expr->constraints) {
vlm86f5ed22004-09-26 13:11:31 +00001436 if(arg->flags & A1C_NO_CONSTRAINTS) {
1437 OUT("0,\t/* No check because of -fno-constraints */\n");
1438 } else {
1439 char *id = MKID(expr->Identifier);
1440 if(expr->_anonymous_type
1441 && !strcmp(expr->Identifier, "member"))
1442 id = asn1c_type_name(arg, expr, TNF_SAFE);
1443 OUT("memb_%s_%d_constraint,\n", id,
1444 ++global_memb_unique);
1445 }
vlmb2839012004-08-20 13:37:01 +00001446 } else {
1447 OUT("0,\t/* Defer to actual type */\n");
1448 }
1449 if(C99_MODE) OUT(".name = ");
vlm39ba4c42004-09-22 16:06:28 +00001450 OUT("\"%s\"\n", expr->_anonymous_type ? "" : expr->Identifier);
vlmb2839012004-08-20 13:37:01 +00001451 OUT("},\n");
1452 INDENT(-1);
1453
vlm86f5ed22004-09-26 13:11:31 +00001454 if(!expr->constraints || (arg->flags & A1C_NO_CONSTRAINTS))
vlmb2839012004-08-20 13:37:01 +00001455 return 0;
1456
1457 save_target = arg->target->target;
1458 REDIR(OT_CODE);
1459
vlm39ba4c42004-09-22 16:06:28 +00001460 if(expr->_anonymous_type && !strcmp(expr->Identifier, "member"))
vlmb2839012004-08-20 13:37:01 +00001461 p = asn1c_type_name(arg, expr, TNF_SAFE);
vlm39ba4c42004-09-22 16:06:28 +00001462 else
1463 p = MKID(expr->Identifier);
vlmb2839012004-08-20 13:37:01 +00001464 OUT("static int\n");
vlma5dcb912004-09-29 13:16:40 +00001465 OUT("memb_%s_%d_constraint(asn_TYPE_descriptor_t *td, const void *sptr,\n", p, global_memb_unique);
vlmb2839012004-08-20 13:37:01 +00001466 INDENT(+1);
1467 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
1468 tmp_arg = *arg;
1469 tmp_arg.expr = expr;
1470 if(asn1c_emit_constraint_checking_code(&tmp_arg) == 1) {
vlm86f5ed22004-09-26 13:11:31 +00001471 OUT("return td->check_constraints"
1472 "(td, sptr, app_errlog, app_key);\n");
vlmb2839012004-08-20 13:37:01 +00001473 }
1474 INDENT(-1);
1475 OUT("}\n");
1476 OUT("\n");
1477
1478 REDIR(save_target);
1479
1480 return 0;
1481}
vlm4e554992004-08-25 02:03:12 +00001482
vlm9de248e2004-10-20 15:50:55 +00001483/*
1484 * Generate "asn_DEF_XXX" type definition.
1485 */
vlm4e554992004-08-25 02:03:12 +00001486static int
vlm86f5ed22004-09-26 13:11:31 +00001487emit_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 +00001488 char *p;
1489
1490 p = MKID(expr->Identifier);
vlm12c8f692004-09-06 08:07:29 +00001491 if(HIDE_INNER_DEFS)
1492 OUT("static /* Use -fall-defs-global to expose */\n");
vlma5dcb912004-09-29 13:16:40 +00001493 OUT("asn_TYPE_descriptor_t asn_DEF_%s = {\n", p);
vlm72425de2004-09-13 08:31:01 +00001494 INDENT(+1);
vlm4e554992004-08-25 02:03:12 +00001495 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
vlm9de248e2004-10-20 15:50:55 +00001496 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
vlm4e554992004-08-25 02:03:12 +00001497
1498 if(expr->expr_type & ASN_CONSTR_MASK) {
1499 p = asn1c_type_name(arg, arg->expr, TNF_SAFE);
1500 }
1501
vlm39ba4c42004-09-22 16:06:28 +00001502 OUT("%s_free,\n", p);
1503 OUT("%s_print,\n", p);
vlm4e554992004-08-25 02:03:12 +00001504 OUT("%s_constraint,\n", p);
1505 OUT("%s_decode_ber,\n", p);
1506 OUT("%s_encode_der,\n", p);
vlm2dbab7c2004-10-23 15:07:45 +00001507 switch(expr->expr_type) {
1508 case ASN_CONSTR_SET:
1509 case ASN_CONSTR_SET_OF:
1510 case ASN_CONSTR_SEQUENCE_OF:
1511 OUT("0,\t\t\t\t/* Not implemented yet */\n");
1512 break;
1513 default:
1514 OUT("%s_decode_xer,\n", p);
1515 }
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}