blob: dae8659acaaac5f32ac6c9e79650d1296d09e60a [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);
vlmaf841972005-01-28 12:18:50 +000038static int out_identifiers_chain(arg_t *arg, int check_reserved_keywords);
vlmfa67ddc2004-06-03 03:38:44 +000039
vlm72425de2004-09-13 08:31:01 +000040enum tvm_compat {
41 _TVM_SAME = 0, /* tags and all_tags are same */
42 _TVM_SUBSET = 1, /* tags are subset of all_tags */
43 _TVM_DIFFERENT = 2, /* tags and all_tags are different */
44};
45static enum tvm_compat emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tc, int *atc);
46
vlm4e554992004-08-25 02:03:12 +000047enum etd_spec {
48 ETD_NO_SPECIFICS,
49 ETD_HAS_SPECIFICS
50};
vlm86f5ed22004-09-26 13:11:31 +000051static 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 +000052
vlmb2839012004-08-20 13:37:01 +000053#define C99_MODE (!(arg->flags & A1C_NO_C99))
vlmfa67ddc2004-06-03 03:38:44 +000054#define UNNAMED_UNIONS (arg->flags & A1C_UNNAMED_UNIONS)
vlm12c8f692004-09-06 08:07:29 +000055#define HIDE_INNER_DEFS (arg->embed && !(arg->flags & A1C_ALL_DEFS_GLOBAL))
vlmfa67ddc2004-06-03 03:38:44 +000056
57#define PCTX_DEF INDENTED( \
58 OUT("\n"); \
59 OUT("/* Context for parsing across buffer boundaries */\n"); \
vlma5dcb912004-09-29 13:16:40 +000060 OUT("asn_struct_ctx_t _asn_ctx;\n"));
vlmfa67ddc2004-06-03 03:38:44 +000061
vlm33a4ff12004-08-11 05:21:32 +000062#define DEPENDENCIES do { \
vlmdae7f9d2004-08-22 03:25:24 +000063 asn1p_expr_t *__m; \
64 TQ_FOR(__m, &(expr->members), next) { \
65 if((!(__m->expr_type & ASN_CONSTR_MASK) \
66 && __m->expr_type > ASN_CONSTR_MASK) \
67 || __m->meta_type == AMT_TYPEREF) { \
68 GEN_INCLUDE(asn1c_type_name(arg, \
vlmaf841972005-01-28 12:18:50 +000069 __m, TNF_INCLUDE)); \
vlm33a4ff12004-08-11 05:21:32 +000070 } \
71 } \
72 if(expr->expr_type == ASN_CONSTR_SET_OF) \
73 GEN_INCLUDE("asn_SET_OF"); \
74 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF) \
75 GEN_INCLUDE("asn_SEQUENCE_OF"); \
76} while(0)
vlmfa67ddc2004-06-03 03:38:44 +000077
vlmaf841972005-01-28 12:18:50 +000078/* MKID() without checking for reserved keywords */
79#define MKID_nr(id) asn1c_make_identifier(0, (id), 0)
80#define MKID(id) asn1c_make_identifier(AMI_CHECK_RESERVED, (id), 0)
vlmfa67ddc2004-06-03 03:38:44 +000081
82int
vlmf9d178d2004-09-14 12:47:45 +000083asn1c_lang_C_type_REAL(arg_t *arg) {
vlmfa67ddc2004-06-03 03:38:44 +000084 REDIR(OT_DEPS);
vlmfa67ddc2004-06-03 03:38:44 +000085 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
86}
87
vlmfa67ddc2004-06-03 03:38:44 +000088int
vlmf9d178d2004-09-14 12:47:45 +000089asn1c_lang_C_type_common_INTEGER(arg_t *arg) {
vlmfa67ddc2004-06-03 03:38:44 +000090 asn1p_expr_t *expr = arg->expr;
91 asn1p_expr_t *v;
92
93 REDIR(OT_DEPS);
94
vlmf9d178d2004-09-14 12:47:45 +000095 if(expr->expr_type == ASN_BASIC_ENUMERATED
96 || TQ_FIRST(&(expr->members))
97 ) {
vlmfa67ddc2004-06-03 03:38:44 +000098 OUT("typedef enum %s {\n", MKID(expr->Identifier));
99 TQ_FOR(v, &(expr->members), next) {
100 switch(v->expr_type) {
101 case A1TC_UNIVERVAL:
vlm47ae1582004-09-24 21:01:43 +0000102 OUT("\t%s\t= %" PRIdASN ",\n",
vlmfa67ddc2004-06-03 03:38:44 +0000103 asn1c_make_identifier(0,
104 expr->Identifier,
105 v->Identifier, 0),
106 v->value->value.v_integer);
107 break;
vlmf9d178d2004-09-14 12:47:45 +0000108 case A1TC_EXTENSIBLE:
109 OUT("\t/*\n");
110 OUT("\t * Enumeration is extensible\n");
111 OUT("\t */\n");
112 break;
vlmfa67ddc2004-06-03 03:38:44 +0000113 default:
114 return -1;
115 }
116 }
117 OUT("} %s_e;\n", MKID(expr->Identifier));
118 }
119
120 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
121}
122
123int
124asn1c_lang_C_type_SEQUENCE(arg_t *arg) {
125 asn1p_expr_t *expr = arg->expr;
126 asn1p_expr_t *v;
127 int comp_mode = 0; /* {root,ext=1,root,root,...} */
128
129 DEPENDENCIES;
130
131 if(arg->embed) {
vlmaf841972005-01-28 12:18:50 +0000132 OUT("struct "); out_identifiers_chain(arg, 1); OUT(" {\n");
vlmfa67ddc2004-06-03 03:38:44 +0000133 } else {
134 OUT("typedef struct %s {\n",
135 MKID(expr->Identifier));
136 }
137
138 TQ_FOR(v, &(expr->members), next) {
139 if(v->expr_type == A1TC_EXTENSIBLE) {
140 if(comp_mode < 3) comp_mode++;
141 }
vlmddd5a7d2004-09-10 09:18:20 +0000142 if(comp_mode == 1
143 || expr_better_indirect(arg, v))
vlma02b74d2004-09-15 11:54:38 +0000144 v->marker.flags |= EM_INDIRECT;
vlmfa67ddc2004-06-03 03:38:44 +0000145 EMBED(v);
146 }
147
148 PCTX_DEF;
vlma02b74d2004-09-15 11:54:38 +0000149 OUT("} %s%s%s", expr->marker.flags?"*":"",
vlmdae7f9d2004-08-22 03:25:24 +0000150 expr->_anonymous_type ? "" : MKID(expr->Identifier),
151 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000152
153 return asn1c_lang_C_type_SEQUENCE_def(arg);
154}
155
156static int
157asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
158 asn1p_expr_t *expr = arg->expr;
159 asn1p_expr_t *v;
160 int elements; /* Number of elements */
vlmfa67ddc2004-06-03 03:38:44 +0000161 int ext_start = -1;
162 int ext_stop = -1;
vlm4e03ce22004-06-06 07:20:17 +0000163 tag2el_t *tag2el = NULL;
164 int tag2el_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000165 int tags_count;
vlm72425de2004-09-13 08:31:01 +0000166 int all_tags_count;
167 enum tvm_compat tv_mode;
vlmfa67ddc2004-06-03 03:38:44 +0000168 char *p;
169
vlm4e03ce22004-06-06 07:20:17 +0000170 /*
171 * Fetch every inner tag from the tag to elements map.
172 */
vlm940bc6b2004-10-03 09:13:30 +0000173 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
vlm4e03ce22004-06-06 07:20:17 +0000174 if(tag2el) free(tag2el);
175 return -1;
176 }
177
vlm33a4ff12004-08-11 05:21:32 +0000178 GEN_INCLUDE("constr_SEQUENCE");
179 if(!arg->embed)
vlma5dcb912004-09-29 13:16:40 +0000180 GEN_DECLARE(expr); /* asn_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000181
vlm33a4ff12004-08-11 05:21:32 +0000182 REDIR(OT_STAT_DEFS);
vlmfa67ddc2004-06-03 03:38:44 +0000183
184 /*
185 * Print out the table according to which the parsing is performed.
186 */
vlm39ba4c42004-09-22 16:06:28 +0000187 if(expr_elements_count(arg, expr)) {
188 int comp_mode = 0; /* {root,ext=1,root,root,...} */
vlmfa67ddc2004-06-03 03:38:44 +0000189
vlmaf841972005-01-28 12:18:50 +0000190 p = MKID_nr(expr->Identifier);
vlma5dcb912004-09-29 13:16:40 +0000191 OUT("static asn_TYPE_member_t asn_MBR_%s[] = {\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000192
193 elements = 0;
194 INDENTED(TQ_FOR(v, &(expr->members), next) {
195 if(v->expr_type == A1TC_EXTENSIBLE) {
196 if((++comp_mode) == 1)
197 ext_start = elements - 1;
198 else
199 ext_stop = elements - 1;
200 continue;
201 }
202 elements++;
203 emit_member_table(arg, v);
204 });
205 OUT("};\n");
206 } else {
207 elements = 0;
208 }
vlmfa67ddc2004-06-03 03:38:44 +0000209
vlm4a3f5822004-06-28 21:13:46 +0000210 /*
vlma5dcb912004-09-29 13:16:40 +0000211 * Print out asn_DEF_<type>_[all_]tags[] vectors.
vlm4a3f5822004-06-28 21:13:46 +0000212 */
vlm72425de2004-09-13 08:31:01 +0000213 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
vlmfa67ddc2004-06-03 03:38:44 +0000214
vlm4e03ce22004-06-06 07:20:17 +0000215 /*
216 * Tags to elements map.
217 */
vlm940bc6b2004-10-03 09:13:30 +0000218 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
vlm4e03ce22004-06-06 07:20:17 +0000219
vlmaf841972005-01-28 12:18:50 +0000220 OUT("static asn_SEQUENCE_specifics_t asn_DEF_%s_specs = {\n",
221 MKID_nr(expr->Identifier));
vlm4a3f5822004-06-28 21:13:46 +0000222 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000223 INDENTED(
224 OUT("sizeof(struct %s),\n", p);
vlma5dcb912004-09-29 13:16:40 +0000225 OUT("offsetof(struct %s, _asn_ctx),\n", p);
vlmaf841972005-01-28 12:18:50 +0000226 OUT("asn_DEF_%s_tag2el,\n", MKID_nr(expr->Identifier));
vlm4e03ce22004-06-06 07:20:17 +0000227 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
vlmfa67ddc2004-06-03 03:38:44 +0000228 OUT("%d,\t/* Start extensions */\n",
229 ext_start);
230 OUT("%d\t/* Stop extensions */\n",
231 (ext_stop<ext_start)?elements+1:ext_stop, ext_stop);
232 );
233 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000234
235 /*
vlma5dcb912004-09-29 13:16:40 +0000236 * Emit asn_DEF_xxx table.
vlm4e554992004-08-25 02:03:12 +0000237 */
vlm72425de2004-09-13 08:31:01 +0000238 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
vlm86f5ed22004-09-26 13:11:31 +0000239 ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000240
vlmfa67ddc2004-06-03 03:38:44 +0000241 REDIR(OT_TYPE_DECLS);
242
243 return 0;
vlmedf203f2005-01-17 11:57:48 +0000244} /* _SEQUENCE_def() */
vlmfa67ddc2004-06-03 03:38:44 +0000245
246int
vlmfa67ddc2004-06-03 03:38:44 +0000247asn1c_lang_C_type_SET(arg_t *arg) {
248 asn1p_expr_t *expr = arg->expr;
249 asn1p_expr_t *v;
250 long mcount;
251 char *id;
252 int comp_mode = 0; /* {root,ext=1,root,root,...} */
253
254 DEPENDENCIES;
255
256 REDIR(OT_DEPS);
257
258 OUT("\n");
259 OUT("/*\n");
260 OUT(" * Method of determining the components presence\n");
261 OUT(" */\n");
262 mcount = 0;
vlmaf841972005-01-28 12:18:50 +0000263 OUT("typedef enum "); out_identifiers_chain(arg, 0); OUT("_PR {\n");
vlmfa67ddc2004-06-03 03:38:44 +0000264 TQ_FOR(v, &(expr->members), next) {
265 if(v->expr_type == A1TC_EXTENSIBLE) continue;
266 INDENTED(
vlmaf841972005-01-28 12:18:50 +0000267 out_identifiers_chain(arg, 0);
268 OUT("_PR_");
269 id = MKID_nr(v->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000270 OUT("%s,\t/* Member %s is present */\n",
271 id, id)
272 );
273 mcount++;
274 }
vlmaf841972005-01-28 12:18:50 +0000275 OUT("} "); out_identifiers_chain(arg, 0); OUT("_PR;\n");
vlmfa67ddc2004-06-03 03:38:44 +0000276
277 REDIR(OT_TYPE_DECLS);
278
279 if(arg->embed) {
vlmaf841972005-01-28 12:18:50 +0000280 OUT("struct "); out_identifiers_chain(arg, 1); OUT(" {\n");
vlmfa67ddc2004-06-03 03:38:44 +0000281 } else {
vlmaf841972005-01-28 12:18:50 +0000282 id = MKID(expr->Identifier);
vlm6e73a042004-08-11 07:17:22 +0000283 OUT("typedef struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000284 }
285
286 TQ_FOR(v, &(expr->members), next) {
287 if(v->expr_type == A1TC_EXTENSIBLE) {
288 if(comp_mode < 3) comp_mode++;
289 }
vlmddd5a7d2004-09-10 09:18:20 +0000290 if(comp_mode == 1
291 || expr_better_indirect(arg, v))
vlma02b74d2004-09-15 11:54:38 +0000292 v->marker.flags |= EM_INDIRECT;
vlmfa67ddc2004-06-03 03:38:44 +0000293 EMBED(v);
294 }
295
296 INDENTED(
vlmaf841972005-01-28 12:18:50 +0000297 id = MKID_nr(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000298 OUT("\n");
299 OUT("/* Presence bitmask: ASN_SET_ISPRESENT(p%s, %s_PR_x) */\n",
300 id, id);
301 OUT("unsigned int _presence_map\n");
302 OUT("\t[((%ld+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))];\n", mcount);
303 );
304
305 PCTX_DEF;
vlma02b74d2004-09-15 11:54:38 +0000306 OUT("} %s%s%s", expr->marker.flags?"*":"",
vlmdae7f9d2004-08-22 03:25:24 +0000307 expr->_anonymous_type ? "" : MKID(expr->Identifier),
308 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000309
310 return asn1c_lang_C_type_SET_def(arg);
311}
312
vlmfa67ddc2004-06-03 03:38:44 +0000313static int
314asn1c_lang_C_type_SET_def(arg_t *arg) {
315 asn1p_expr_t *expr = arg->expr;
316 asn1p_expr_t *v;
317 int elements;
vlmfa67ddc2004-06-03 03:38:44 +0000318 tag2el_t *tag2el = NULL;
319 int tag2el_count = 0;
vlm940bc6b2004-10-03 09:13:30 +0000320 tag2el_t *tag2el_cxer = NULL;
321 int tag2el_cxer_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000322 int tags_count;
vlm72425de2004-09-13 08:31:01 +0000323 int all_tags_count;
324 enum tvm_compat tv_mode;
vlmfa67ddc2004-06-03 03:38:44 +0000325 char *p;
326
327 /*
328 * Fetch every inner tag from the tag to elements map.
329 */
vlm940bc6b2004-10-03 09:13:30 +0000330 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
vlmfa67ddc2004-06-03 03:38:44 +0000331 if(tag2el) free(tag2el);
332 return -1;
vlmfa67ddc2004-06-03 03:38:44 +0000333 }
vlm940bc6b2004-10-03 09:13:30 +0000334 if(_fill_tag2el_map(arg, &tag2el_cxer, &tag2el_cxer_count, -1, FTE_CANONICAL_XER)) {
335 if(tag2el) free(tag2el);
336 if(tag2el_cxer) free(tag2el_cxer);
337 return -1;
338 }
339 if(tag2el_cxer_count == tag2el_count
340 && memcmp(tag2el, tag2el_cxer, tag2el_count) == 0) {
341 free(tag2el_cxer);
342 tag2el_cxer = 0;
343 }
vlmfa67ddc2004-06-03 03:38:44 +0000344
vlm33a4ff12004-08-11 05:21:32 +0000345 GEN_INCLUDE("constr_SET");
346 if(!arg->embed)
vlma5dcb912004-09-29 13:16:40 +0000347 GEN_DECLARE(expr); /* asn_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000348
349 REDIR(OT_STAT_DEFS);
350
vlmfa67ddc2004-06-03 03:38:44 +0000351 /*
352 * Print out the table according to which the parsing is performed.
353 */
vlm39ba4c42004-09-22 16:06:28 +0000354 if(expr_elements_count(arg, expr)) {
355 int comp_mode = 0; /* {root,ext=1,root,root,...} */
vlmfa67ddc2004-06-03 03:38:44 +0000356
vlmaf841972005-01-28 12:18:50 +0000357 OUT("static asn_TYPE_member_t asn_MBR_%s[] = {\n",
358 MKID_nr(expr->Identifier));
vlm39ba4c42004-09-22 16:06:28 +0000359
360 elements = 0;
361 INDENTED(TQ_FOR(v, &(expr->members), next) {
362 if(v->expr_type == A1TC_EXTENSIBLE) {
363 if(comp_mode < 3) comp_mode++;
364 } else {
365 if(comp_mode == 1
366 || expr_better_indirect(arg, v))
367 v->marker.flags |= EM_INDIRECT;
368 elements++;
369 emit_member_table(arg, v);
370 }
371 });
372 OUT("};\n");
373 } else {
374 elements = 0;
375 }
vlmfa67ddc2004-06-03 03:38:44 +0000376
vlm4a3f5822004-06-28 21:13:46 +0000377 /*
vlma5dcb912004-09-29 13:16:40 +0000378 * Print out asn_DEF_<type>_[all_]tags[] vectors.
vlm4a3f5822004-06-28 21:13:46 +0000379 */
vlm72425de2004-09-13 08:31:01 +0000380 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
vlmfa67ddc2004-06-03 03:38:44 +0000381
382 /*
383 * Tags to elements map.
384 */
vlm940bc6b2004-10-03 09:13:30 +0000385 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
386 if(tag2el_cxer)
387 emit_tag2member_map(arg, tag2el_cxer, tag2el_cxer_count, "_cxer");
vlmfa67ddc2004-06-03 03:38:44 +0000388
389 /*
390 * Emit a map of mandatory elements.
391 */
vlmaf841972005-01-28 12:18:50 +0000392 OUT("static uint8_t asn_DEF_%s_mmap",
393 MKID_nr(expr->Identifier));
vlm4a3f5822004-06-28 21:13:46 +0000394 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000395 OUT("[(%d + (8 * sizeof(unsigned int)) - 1) / 8]", elements);
396 OUT(" = {\n", p);
397 INDENTED(
398 if(elements) {
399 int delimit = 0;
400 int el = 0;
401 TQ_FOR(v, &(expr->members), next) {
402 if(v->expr_type == A1TC_EXTENSIBLE) continue;
403 if(delimit) {
404 OUT(",\n");
405 delimit = 0;
406 } else if(el) {
407 OUT(" | ");
408 }
vlmddd5a7d2004-09-10 09:18:20 +0000409 OUT("(%d << %d)",
vlma02b74d2004-09-15 11:54:38 +0000410 v->marker.flags?0:1,
vlmddd5a7d2004-09-10 09:18:20 +0000411 7 - (el % 8));
vlmfa67ddc2004-06-03 03:38:44 +0000412 if(el && (el % 8) == 0)
413 delimit = 1;
414 el++;
415 }
416 } else {
417 OUT("0");
418 }
419 );
420 OUT("\n");
421 OUT("};\n");
422
vlmaf841972005-01-28 12:18:50 +0000423 OUT("static asn_SET_specifics_t asn_DEF_%s_specs = {\n",
424 MKID_nr(expr->Identifier));
425 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000426 INDENTED(
427 OUT("sizeof(struct %s),\n", p);
vlma5dcb912004-09-29 13:16:40 +0000428 OUT("offsetof(struct %s, _asn_ctx),\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000429 OUT("offsetof(struct %s, _presence_map),\n", p);
vlmaf841972005-01-28 12:18:50 +0000430 p = MKID_nr(expr->Identifier);
vlma5dcb912004-09-29 13:16:40 +0000431 OUT("asn_DEF_%s_tag2el,\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000432 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
vlm940bc6b2004-10-03 09:13:30 +0000433 if(tag2el_cxer)
434 OUT("asn_DEF_%s_tag2el_cxer,\n", p);
435 else
436 OUT("asn_DEF_%s_tag2el,\t/* Same as above */\n", p);
437 OUT("%d,\t/* Count of tags in the CANONICAL-XER map */\n", tag2el_cxer_count);
vlm79b08d52004-07-01 00:52:50 +0000438 OUT("%d,\t/* Whether extensible */\n",
439 check_if_extensible(expr));
vlma5dcb912004-09-29 13:16:40 +0000440 OUT("(unsigned int *)asn_DEF_%s_mmap\t/* Mandatory elements map */\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000441 );
442 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000443
444 /*
vlma5dcb912004-09-29 13:16:40 +0000445 * Emit asn_DEF_xxx table.
vlm4e554992004-08-25 02:03:12 +0000446 */
vlm72425de2004-09-13 08:31:01 +0000447 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
vlm86f5ed22004-09-26 13:11:31 +0000448 ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000449
vlmfa67ddc2004-06-03 03:38:44 +0000450 REDIR(OT_TYPE_DECLS);
451
452 return 0;
vlmedf203f2005-01-17 11:57:48 +0000453} /* _SET_def() */
vlmfa67ddc2004-06-03 03:38:44 +0000454
455int
vlmdae7f9d2004-08-22 03:25:24 +0000456asn1c_lang_C_type_SEx_OF(arg_t *arg) {
vlmfa67ddc2004-06-03 03:38:44 +0000457 asn1p_expr_t *expr = arg->expr;
vlmdae7f9d2004-08-22 03:25:24 +0000458 asn1p_expr_t *memb;
vlmfa67ddc2004-06-03 03:38:44 +0000459
460 DEPENDENCIES;
461
462 if(arg->embed) {
vlmaf841972005-01-28 12:18:50 +0000463 OUT("struct "); out_identifiers_chain(arg, 1); OUT(" {\n");
vlmfa67ddc2004-06-03 03:38:44 +0000464 } else {
vlmdae7f9d2004-08-22 03:25:24 +0000465 OUT("typedef struct %s {\n", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000466 }
467
vlmdae7f9d2004-08-22 03:25:24 +0000468 memb = TQ_FIRST(&expr->members);
469
470 INDENT(+1);
471 OUT("A_%s_OF(",
472 (arg->expr->expr_type == ASN_CONSTR_SET_OF)
473 ? "SET" : "SEQUENCE");
474 if(memb->expr_type & ASN_CONSTR_MASK) {
475 arg_t tmp;
476 asn1p_expr_t tmp_memb;
477 arg->embed++;
478 tmp = *arg;
479 tmp.expr = &tmp_memb;
480 tmp_memb = *memb;
481 tmp_memb._anonymous_type = 1;
vlm39ba4c42004-09-22 16:06:28 +0000482 if(tmp_memb.Identifier == 0) {
483 tmp_memb.Identifier = strdup(
484 asn1c_make_identifier(0,
vlmbf3c5112005-02-14 20:41:29 +0000485 expr->Identifier, "Member", 0));
vlm39ba4c42004-09-22 16:06:28 +0000486 assert(tmp_memb.Identifier);
487 }
vlmdae7f9d2004-08-22 03:25:24 +0000488 tmp.default_cb(&tmp);
vlm39ba4c42004-09-22 16:06:28 +0000489 if(tmp_memb.Identifier != memb->Identifier)
490 free(tmp_memb.Identifier);
vlmdae7f9d2004-08-22 03:25:24 +0000491 arg->embed--;
492 assert(arg->target->target == OT_TYPE_DECLS);
493 } else {
vlmaf841972005-01-28 12:18:50 +0000494 OUT("%s", asn1c_type_name(arg, memb, TNF_CTYPE | TNF_CHECK));
vlmfa67ddc2004-06-03 03:38:44 +0000495 }
vlmdae7f9d2004-08-22 03:25:24 +0000496 OUT(") list;\n");
497 INDENT(-1);
vlmfa67ddc2004-06-03 03:38:44 +0000498
499 PCTX_DEF;
vlma02b74d2004-09-15 11:54:38 +0000500 OUT("} %s%s%s", expr->marker.flags?"*":"",
vlmdae7f9d2004-08-22 03:25:24 +0000501 expr->_anonymous_type ? "" : MKID(expr->Identifier),
502 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000503
504 /*
vlmdae7f9d2004-08-22 03:25:24 +0000505 * SET OF/SEQUENCE OF definition
vlmfa67ddc2004-06-03 03:38:44 +0000506 */
vlmdae7f9d2004-08-22 03:25:24 +0000507 return asn1c_lang_C_type_SEx_OF_def(arg,
508 (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF));
vlmfa67ddc2004-06-03 03:38:44 +0000509}
510
511static int
512asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
513 asn1p_expr_t *expr = arg->expr;
514 asn1p_expr_t *v;
vlm6e73a042004-08-11 07:17:22 +0000515 int tags_count;
vlm72425de2004-09-13 08:31:01 +0000516 int all_tags_count;
517 enum tvm_compat tv_mode;
vlmfa67ddc2004-06-03 03:38:44 +0000518 char *p;
519
vlm33a4ff12004-08-11 05:21:32 +0000520 /*
521 * Print out the table according to which the parsing is performed.
522 */
vlmfa67ddc2004-06-03 03:38:44 +0000523 if(seq_of) {
vlm33a4ff12004-08-11 05:21:32 +0000524 GEN_INCLUDE("constr_SEQUENCE_OF");
vlmfa67ddc2004-06-03 03:38:44 +0000525 } else {
vlm33a4ff12004-08-11 05:21:32 +0000526 GEN_INCLUDE("constr_SET_OF");
vlmfa67ddc2004-06-03 03:38:44 +0000527 }
vlm33a4ff12004-08-11 05:21:32 +0000528 if(!arg->embed)
vlma5dcb912004-09-29 13:16:40 +0000529 GEN_DECLARE(expr); /* asn_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000530
531 REDIR(OT_STAT_DEFS);
532
533 /*
534 * Print out the table according to which the parsing is performed.
535 */
536 p = MKID(expr->Identifier);
vlma5dcb912004-09-29 13:16:40 +0000537 OUT("static asn_TYPE_member_t asn_MBR_%s[] = {\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000538 INDENT(+1);
vlmfa67ddc2004-06-03 03:38:44 +0000539 v = TQ_FIRST(&(expr->members));
vlm39ba4c42004-09-22 16:06:28 +0000540 if(!v->Identifier) {
vlmbf3c5112005-02-14 20:41:29 +0000541 v->Identifier = strdup("Member");
vlm39ba4c42004-09-22 16:06:28 +0000542 assert(v->Identifier);
543 }
544 v->_anonymous_type = 1;
545 arg->embed++;
vlm4e554992004-08-25 02:03:12 +0000546 emit_member_table(arg, v);
vlm39ba4c42004-09-22 16:06:28 +0000547 arg->embed--;
548 INDENT(-1);
vlmfa67ddc2004-06-03 03:38:44 +0000549 OUT("};\n");
550
vlm4a3f5822004-06-28 21:13:46 +0000551 /*
vlma5dcb912004-09-29 13:16:40 +0000552 * Print out asn_DEF_<type>_[all_]tags[] vectors.
vlm4a3f5822004-06-28 21:13:46 +0000553 */
vlm72425de2004-09-13 08:31:01 +0000554 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
vlmfa67ddc2004-06-03 03:38:44 +0000555
vlmaf841972005-01-28 12:18:50 +0000556 OUT("static asn_SET_OF_specifics_t asn_DEF_%s_specs = {\n",
557 MKID_nr(expr->Identifier));
vlm4a3f5822004-06-28 21:13:46 +0000558 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000559 INDENTED(
560 OUT("sizeof(struct %s),\n", p);
vlma5dcb912004-09-29 13:16:40 +0000561 OUT("offsetof(struct %s, _asn_ctx),\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000562 if(expr_as_xmlvaluelist(arg, v))
563 OUT("1,\t/* XER encoding is XMLValueList */\n");
564 else
565 OUT("0,\t/* XER encoding is XMLDelimitedItemList */\n");
vlmfa67ddc2004-06-03 03:38:44 +0000566 );
567 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000568
569 /*
vlma5dcb912004-09-29 13:16:40 +0000570 * Emit asn_DEF_xxx table.
vlm4e554992004-08-25 02:03:12 +0000571 */
vlm72425de2004-09-13 08:31:01 +0000572 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, 1,
vlm86f5ed22004-09-26 13:11:31 +0000573 ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000574
vlmfa67ddc2004-06-03 03:38:44 +0000575 REDIR(OT_TYPE_DECLS);
576
577 return 0;
vlmedf203f2005-01-17 11:57:48 +0000578} /* _SEx_OF_def() */
vlmfa67ddc2004-06-03 03:38:44 +0000579
580int
581asn1c_lang_C_type_CHOICE(arg_t *arg) {
582 asn1p_expr_t *expr = arg->expr;
583 asn1p_expr_t *v;
vlmdae7f9d2004-08-22 03:25:24 +0000584 char *id;
vlmfa67ddc2004-06-03 03:38:44 +0000585
586 DEPENDENCIES;
587
vlm33a4ff12004-08-11 05:21:32 +0000588 REDIR(OT_DEPS);
589
vlmaf841972005-01-28 12:18:50 +0000590 OUT("typedef enum "); out_identifiers_chain(arg, 0); OUT("_PR {\n");
vlm33a4ff12004-08-11 05:21:32 +0000591 INDENTED(
vlmaf841972005-01-28 12:18:50 +0000592 out_identifiers_chain(arg, 0);
593 OUT("_PR_NOTHING,\t/* No components present */\n");
vlm33a4ff12004-08-11 05:21:32 +0000594 TQ_FOR(v, &(expr->members), next) {
595 if(v->expr_type == A1TC_EXTENSIBLE) {
596 OUT("/* Extensions may appear below */\n");
597 continue;
598 }
vlmaf841972005-01-28 12:18:50 +0000599 out_identifiers_chain(arg, 0);
600 OUT("_PR_");
601 id = MKID_nr(v->Identifier);
vlmdae7f9d2004-08-22 03:25:24 +0000602 OUT("%s,\n", id, id);
vlm33a4ff12004-08-11 05:21:32 +0000603 }
604 );
vlmaf841972005-01-28 12:18:50 +0000605 OUT("} "); out_identifiers_chain(arg, 0); OUT("_PR;\n");
vlm33a4ff12004-08-11 05:21:32 +0000606
607 REDIR(OT_TYPE_DECLS);
vlmfa67ddc2004-06-03 03:38:44 +0000608
609 if(arg->embed) {
vlmaf841972005-01-28 12:18:50 +0000610 OUT("struct "); out_identifiers_chain(arg, 1); OUT(" {\n");
vlmfa67ddc2004-06-03 03:38:44 +0000611 } else {
vlmaf841972005-01-28 12:18:50 +0000612 id = MKID(expr->Identifier);
vlmdae7f9d2004-08-22 03:25:24 +0000613 OUT("typedef struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000614 }
615
616 INDENTED(
vlmaf841972005-01-28 12:18:50 +0000617 out_identifiers_chain(arg, 0);
618 OUT("_PR present;\n");
619 OUT("union {\n");
vlmfa67ddc2004-06-03 03:38:44 +0000620 TQ_FOR(v, &(expr->members), next) {
vlmddd5a7d2004-09-10 09:18:20 +0000621 if(expr_better_indirect(arg, v))
vlma02b74d2004-09-15 11:54:38 +0000622 v->marker.flags |= EM_INDIRECT;
vlmfa67ddc2004-06-03 03:38:44 +0000623 EMBED(v);
624 }
625 if(UNNAMED_UNIONS) OUT("};\n");
626 else OUT("} choice;\n");
627 );
628
629 PCTX_DEF;
vlma02b74d2004-09-15 11:54:38 +0000630 OUT("} %s%s%s", expr->marker.flags?"*":"",
vlmdae7f9d2004-08-22 03:25:24 +0000631 expr->_anonymous_type ? "" : MKID(expr->Identifier),
632 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000633
634 return asn1c_lang_C_type_CHOICE_def(arg);
635}
636
637static int
638asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
639 asn1p_expr_t *expr = arg->expr;
640 asn1p_expr_t *v;
641 int elements; /* Number of elements */
vlmfa67ddc2004-06-03 03:38:44 +0000642 tag2el_t *tag2el = NULL;
643 int tag2el_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000644 int tags_count;
vlm72425de2004-09-13 08:31:01 +0000645 int all_tags_count;
646 enum tvm_compat tv_mode;
vlmfa67ddc2004-06-03 03:38:44 +0000647 char *p;
648
649 /*
650 * Fetch every inner tag from the tag to elements map.
651 */
vlm940bc6b2004-10-03 09:13:30 +0000652 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
vlmfa67ddc2004-06-03 03:38:44 +0000653 if(tag2el) free(tag2el);
654 return -1;
vlmfa67ddc2004-06-03 03:38:44 +0000655 }
656
vlm33a4ff12004-08-11 05:21:32 +0000657 GEN_INCLUDE("constr_CHOICE");
658 if(!arg->embed)
vlma5dcb912004-09-29 13:16:40 +0000659 GEN_DECLARE(expr); /* asn_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000660
vlm33a4ff12004-08-11 05:21:32 +0000661 REDIR(OT_STAT_DEFS);
vlmfa67ddc2004-06-03 03:38:44 +0000662
663 /*
664 * Print out the table according to which the parsing is performed.
665 */
vlm39ba4c42004-09-22 16:06:28 +0000666 if(expr_elements_count(arg, expr)) {
vlmfa67ddc2004-06-03 03:38:44 +0000667
vlm39ba4c42004-09-22 16:06:28 +0000668 p = MKID(expr->Identifier);
vlma5dcb912004-09-29 13:16:40 +0000669 OUT("static asn_TYPE_member_t asn_MBR_%s[] = {\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000670
671 elements = 0;
672 INDENTED(TQ_FOR(v, &(expr->members), next) {
vlm34dcd572005-01-17 11:40:49 +0000673 if(v->expr_type == A1TC_EXTENSIBLE)
674 continue;
675 if(expr_better_indirect(arg, v))
676 v->marker.flags |= EM_INDIRECT;
677 elements++;
678 emit_member_table(arg, v);
vlm39ba4c42004-09-22 16:06:28 +0000679 });
680 OUT("};\n");
681 } else {
682 elements = 0;
683 }
vlmfa67ddc2004-06-03 03:38:44 +0000684
vlm6e73a042004-08-11 07:17:22 +0000685
vlmfa67ddc2004-06-03 03:38:44 +0000686 if(arg->embed) {
687 /*
688 * Our parent structure has already taken this into account.
689 */
vlm72425de2004-09-13 08:31:01 +0000690 tv_mode = _TVM_SAME;
691 tags_count = all_tags_count = 0;
vlmfa67ddc2004-06-03 03:38:44 +0000692 } else {
vlm72425de2004-09-13 08:31:01 +0000693 tv_mode = emit_tags_vectors(arg, expr,
694 &tags_count, &all_tags_count);
vlmfa67ddc2004-06-03 03:38:44 +0000695 }
vlmfa67ddc2004-06-03 03:38:44 +0000696
697 /*
698 * Tags to elements map.
699 */
vlm940bc6b2004-10-03 09:13:30 +0000700 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000701
vlmaf841972005-01-28 12:18:50 +0000702 OUT("static asn_CHOICE_specifics_t asn_DEF_%s_specs = {\n",
703 MKID_nr(expr->Identifier));
vlm6e73a042004-08-11 07:17:22 +0000704 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000705 INDENTED(
706 OUT("sizeof(struct %s),\n", p);
vlma5dcb912004-09-29 13:16:40 +0000707 OUT("offsetof(struct %s, _asn_ctx),\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000708 OUT("offsetof(struct %s, present),\n", p);
709 OUT("sizeof(((struct %s *)0)->present),\n", p);
vlmaf841972005-01-28 12:18:50 +0000710 OUT("asn_DEF_%s_tag2el,\n", MKID_nr(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000711 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
vlm79b08d52004-07-01 00:52:50 +0000712 OUT("%d\t/* Whether extensible */\n",
713 check_if_extensible(expr));
vlmfa67ddc2004-06-03 03:38:44 +0000714 );
715 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000716
717 /*
vlma5dcb912004-09-29 13:16:40 +0000718 * Emit asn_DEF_xxx table.
vlm4e554992004-08-25 02:03:12 +0000719 */
vlm72425de2004-09-13 08:31:01 +0000720 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
vlm86f5ed22004-09-26 13:11:31 +0000721 ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000722
vlmfa67ddc2004-06-03 03:38:44 +0000723 REDIR(OT_TYPE_DECLS);
724
725 return 0;
vlmedf203f2005-01-17 11:57:48 +0000726} /* _CHOICE_def() */
vlmfa67ddc2004-06-03 03:38:44 +0000727
728int
729asn1c_lang_C_type_REFERENCE(arg_t *arg) {
730 asn1p_ref_t *ref;
731
732 ref = arg->expr->reference;
733 if(ref->components[ref->comp_count-1].name[0] == '&') {
vlmfa67ddc2004-06-03 03:38:44 +0000734 asn1p_expr_t *extract;
735 arg_t tmp;
736 int ret;
737
vlm39ba4c42004-09-22 16:06:28 +0000738 extract = asn1f_class_access_ex(arg->asn, arg->expr->module,
vlmdae7f9d2004-08-22 03:25:24 +0000739 arg->expr, ref);
vlmfa67ddc2004-06-03 03:38:44 +0000740 if(extract == NULL)
741 return -1;
742
vlmdae7f9d2004-08-22 03:25:24 +0000743 extract = asn1p_expr_clone(extract, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000744 if(extract) {
745 if(extract->Identifier)
746 free(extract->Identifier);
747 extract->Identifier = strdup(arg->expr->Identifier);
748 if(extract->Identifier == NULL) {
749 asn1p_expr_free(extract);
750 return -1;
751 }
752 } else {
753 return -1;
754 }
755
756 tmp = *arg;
757 tmp.asn = arg->asn;
vlmdae7f9d2004-08-22 03:25:24 +0000758 tmp.mod = extract->module;
vlmfa67ddc2004-06-03 03:38:44 +0000759 tmp.expr = extract;
760
761 ret = arg->default_cb(&tmp);
762
763 asn1p_expr_free(extract);
764
765 return ret;
766 }
767
768
769 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
770}
771
772int
773asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
774 asn1p_expr_t *expr = arg->expr;
vlm6e73a042004-08-11 07:17:22 +0000775 int tags_count;
vlm72425de2004-09-13 08:31:01 +0000776 int all_tags_count;
777 enum tvm_compat tv_mode;
vlmfa67ddc2004-06-03 03:38:44 +0000778 char *p;
779
780 if(arg->embed) {
vlma5dcb912004-09-29 13:16:40 +0000781 enum tnfmt tnfmt = TNF_CTYPE;
782
783 /*
784 * If this is an optional compound type,
785 * refer it using "struct X" convention,
786 * as it may recursively include the current structure.
787 */
788 if(expr->marker.flags) {
789 asn1p_expr_t *terminal;
790 terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
791 if(terminal
792 && (terminal->expr_type & ASN_CONSTR_MASK)) {
793 REDIR(OT_DEPS);
794 tnfmt = TNF_RSAFE;
795 OUT("\n");
796 OUT("%s;\t/* Forward declaration */\n",
vlmaf841972005-01-28 12:18:50 +0000797 asn1c_type_name(arg, arg->expr, tnfmt | TNF_CHECK));
vlma5dcb912004-09-29 13:16:40 +0000798 }
799 }
800
vlmfa67ddc2004-06-03 03:38:44 +0000801 REDIR(OT_TYPE_DECLS);
802
vlmaf841972005-01-28 12:18:50 +0000803 OUT("%s\t", asn1c_type_name(arg, arg->expr, tnfmt | TNF_CHECK));
vlma02b74d2004-09-15 11:54:38 +0000804 OUT("%s", expr->marker.flags?"*":" ");
vlmdae7f9d2004-08-22 03:25:24 +0000805 OUT("%s", MKID(expr->Identifier));
vlma02b74d2004-09-15 11:54:38 +0000806 if((expr->marker.flags & EM_DEFAULT) == EM_DEFAULT)
807 OUT("\t/* DEFAULT %s */",
808 asn1f_printable_value(expr->marker.default_value));
809 else if((expr->marker.flags & EM_OPTIONAL) == EM_OPTIONAL)
vlmddd5a7d2004-09-10 09:18:20 +0000810 OUT("\t/* OPTIONAL */");
vlmb2839012004-08-20 13:37:01 +0000811
812 REDIR(OT_TYPE_DECLS);
vlmfa67ddc2004-06-03 03:38:44 +0000813 return 0;
814 }
815
vlmfa67ddc2004-06-03 03:38:44 +0000816
vlm33a4ff12004-08-11 05:21:32 +0000817 GEN_INCLUDE(asn1c_type_name(arg, expr, TNF_INCLUDE));
vlmfa67ddc2004-06-03 03:38:44 +0000818
819 REDIR(OT_TYPE_DECLS);
820
vlmaf841972005-01-28 12:18:50 +0000821 OUT("typedef %s\t", asn1c_type_name(arg, arg->expr, TNF_CTYPE | TNF_CHECK));
vlma02b74d2004-09-15 11:54:38 +0000822 OUT("%s", expr->marker.flags?"*":" ");
vlmdae7f9d2004-08-22 03:25:24 +0000823 OUT("%s_t", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000824
vlm86f5ed22004-09-26 13:11:31 +0000825 /*
826 * If this type just blindly refers the other type, alias it.
827 * Type1 ::= Type2
828 */
829 if((!expr->constraints || (arg->flags & A1C_NO_CONSTRAINTS))
830 && expr->tag.tag_class == TC_NOCLASS
831 && !TQ_FIRST(&(expr->members))
832 ) {
833 char *type_name;
834 REDIR(OT_FUNC_DECLS);
835 type_name = asn1c_type_name(arg, expr, TNF_SAFE);
836 OUT("/* This type is equivalent to %s */\n", type_name);
vlm86f5ed22004-09-26 13:11:31 +0000837 if(HIDE_INNER_DEFS) OUT("/* ");
vlmaf841972005-01-28 12:18:50 +0000838 OUT("#define\tasn_DEF_%s\t", MKID_nr(expr->Identifier));
vlm86f5ed22004-09-26 13:11:31 +0000839 type_name = asn1c_type_name(arg, expr, TNF_SAFE);
vlma5dcb912004-09-29 13:16:40 +0000840 OUT("asn_DEF_%s\n", type_name);
vlm86f5ed22004-09-26 13:11:31 +0000841 if(HIDE_INNER_DEFS)
842 OUT(" // (Use -fall-defs-global to expose) */");
843 REDIR(OT_CODE);
844 OUT("/* This type is equivalent to %s */\n", type_name);
845 OUT("\n");
846 REDIR(OT_TYPE_DECLS);
847 return 0;
848 }
849
vlmfa67ddc2004-06-03 03:38:44 +0000850 REDIR(OT_STAT_DEFS);
851
vlm4a3f5822004-06-28 21:13:46 +0000852 /*
vlma5dcb912004-09-29 13:16:40 +0000853 * Print out asn_DEF_<type>_[all_]tags[] vectors.
vlm4a3f5822004-06-28 21:13:46 +0000854 */
vlm72425de2004-09-13 08:31:01 +0000855 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
vlmfa67ddc2004-06-03 03:38:44 +0000856
vlm72425de2004-09-13 08:31:01 +0000857 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, 0,
vlm86f5ed22004-09-26 13:11:31 +0000858 ETD_NO_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000859
vlmb2839012004-08-20 13:37:01 +0000860 REDIR(OT_CODE);
861
vlmfa67ddc2004-06-03 03:38:44 +0000862 /*
863 * Constraint checking.
864 */
vlm86f5ed22004-09-26 13:11:31 +0000865 if(!(arg->flags & A1C_NO_CONSTRAINTS)) {
866 p = MKID(expr->Identifier);
867 OUT("int\n");
868 OUT("%s_constraint("
vlma5dcb912004-09-29 13:16:40 +0000869 "asn_TYPE_descriptor_t *td, const void *sptr,\n", p);
vlm86f5ed22004-09-26 13:11:31 +0000870 INDENT(+1);
871 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {");
872 OUT("\n");
873 if(asn1c_emit_constraint_checking_code(arg) == 1) {
874 OUT("/* Replace with underlying type checker */\n");
875 OUT("td->check_constraints "
vlma5dcb912004-09-29 13:16:40 +0000876 "= asn_DEF_%s.check_constraints;\n",
vlm86f5ed22004-09-26 13:11:31 +0000877 asn1c_type_name(arg, expr, TNF_SAFE));
878 OUT("return td->check_constraints"
879 "(td, sptr, app_errlog, app_key);\n");
vlm1d036692004-08-19 13:29:46 +0000880 }
vlm86f5ed22004-09-26 13:11:31 +0000881 INDENT(-1);
882 OUT("}\n");
883 OUT("\n");
vlmfa67ddc2004-06-03 03:38:44 +0000884 }
vlmfa67ddc2004-06-03 03:38:44 +0000885
886 /*
887 * Emit suicidal functions.
888 */
889
vlmfa67ddc2004-06-03 03:38:44 +0000890 /*
891 * This function replaces certain fields from the definition
892 * of a type with the corresponding fields from the basic type
893 * (from which the current type is inherited).
894 */
vlmfa67ddc2004-06-03 03:38:44 +0000895 OUT("/*\n");
vlmb2839012004-08-20 13:37:01 +0000896 OUT(" * This type is implemented using %s,\n",
897 asn1c_type_name(arg, expr, TNF_SAFE));
vlmdcd32fe2004-09-23 22:20:47 +0000898 OUT(" * so here we adjust the DEF accordingly.\n");
vlmfa67ddc2004-06-03 03:38:44 +0000899 OUT(" */\n");
900 OUT("static void\n");
vlmb2839012004-08-20 13:37:01 +0000901 p = MKID(expr->Identifier);
vlma5dcb912004-09-29 13:16:40 +0000902 OUT("%s_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000903 INDENT(+1);
vlmb2839012004-08-20 13:37:01 +0000904 {
vlm39ba4c42004-09-22 16:06:28 +0000905 asn1p_expr_t *terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
vlmb2839012004-08-20 13:37:01 +0000906 char *type_name = asn1c_type_name(arg, expr, TNF_SAFE);
vlma5dcb912004-09-29 13:16:40 +0000907 OUT("td->free_struct = asn_DEF_%s.free_struct;\n", type_name);
908 OUT("td->print_struct = asn_DEF_%s.print_struct;\n", type_name);
909 OUT("td->ber_decoder = asn_DEF_%s.ber_decoder;\n", type_name);
910 OUT("td->der_encoder = asn_DEF_%s.der_encoder;\n", type_name);
911 OUT("td->xer_decoder = asn_DEF_%s.xer_decoder;\n", type_name);
912 OUT("td->xer_encoder = asn_DEF_%s.xer_encoder;\n", type_name);
vlm1308d2b2004-09-10 15:49:15 +0000913 if(!terminal && !tags_count) {
vlm72425de2004-09-13 08:31:01 +0000914 OUT("/* The next four lines are here because of -fknown-extern-type */\n");
vlma5dcb912004-09-29 13:16:40 +0000915 OUT("td->tags = asn_DEF_%s.tags;\n", type_name);
916 OUT("td->tags_count = asn_DEF_%s.tags_count;\n", type_name);
917 OUT("td->all_tags = asn_DEF_%s.all_tags;\n", type_name);
918 OUT("td->all_tags_count = asn_DEF_%s.all_tags_count;\n",type_name);
vlm1308d2b2004-09-10 15:49:15 +0000919 OUT("/* End of these lines */\n");
920 }
vlma5dcb912004-09-29 13:16:40 +0000921 OUT("td->elements = asn_DEF_%s.elements;\n", type_name);
922 OUT("td->elements_count = asn_DEF_%s.elements_count;\n", type_name);
923 OUT("td->specifics = asn_DEF_%s.specifics;\n", type_name);
vlmb2839012004-08-20 13:37:01 +0000924 }
vlmfa67ddc2004-06-03 03:38:44 +0000925 INDENT(-1);
926 OUT("}\n");
927 OUT("\n");
vlmfa67ddc2004-06-03 03:38:44 +0000928
929 p = MKID(expr->Identifier);
vlm39ba4c42004-09-22 16:06:28 +0000930 OUT("void\n");
vlma5dcb912004-09-29 13:16:40 +0000931 OUT("%s_free(asn_TYPE_descriptor_t *td,\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000932 INDENTED(
vlm39ba4c42004-09-22 16:06:28 +0000933 OUT("\tvoid *struct_ptr, int contents_only) {\n");
vlmb2839012004-08-20 13:37:01 +0000934 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000935 OUT("td->free_struct(td, struct_ptr, contents_only);\n");
vlmfa67ddc2004-06-03 03:38:44 +0000936 );
937 OUT("}\n");
938 OUT("\n");
939
940 p = MKID(expr->Identifier);
941 OUT("int\n");
vlma5dcb912004-09-29 13:16:40 +0000942 OUT("%s_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000943 INDENTED(
944 OUT("\tint ilevel, asn_app_consume_bytes_f *cb, void *app_key) {\n");
vlmb2839012004-08-20 13:37:01 +0000945 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000946 OUT("return td->print_struct(td, struct_ptr, ilevel, cb, app_key);\n");
947 );
948 OUT("}\n");
949 OUT("\n");
950
951 p = MKID(expr->Identifier);
vlm9de248e2004-10-20 15:50:55 +0000952 OUT("asn_dec_rval_t\n");
vlma5dcb912004-09-29 13:16:40 +0000953 OUT("%s_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000954 INDENTED(
vlm39ba4c42004-09-22 16:06:28 +0000955 OUT("\tvoid **structure, void *bufptr, size_t size, int tag_mode) {\n");
vlmb2839012004-08-20 13:37:01 +0000956 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlma5dcb912004-09-29 13:16:40 +0000957 OUT("return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);\n");
vlm39ba4c42004-09-22 16:06:28 +0000958 );
959 OUT("}\n");
960 OUT("\n");
961
962 p = MKID(expr->Identifier);
963 OUT("asn_enc_rval_t\n");
vlma5dcb912004-09-29 13:16:40 +0000964 OUT("%s_encode_der(asn_TYPE_descriptor_t *td,\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000965 INDENTED(
966 OUT("\tvoid *structure, int tag_mode, ber_tlv_tag_t tag,\n");
967 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
968 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
969 OUT("return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);\n");
970 );
971 OUT("}\n");
972 OUT("\n");
973
974 p = MKID(expr->Identifier);
vlme03646b2004-10-23 13:34:00 +0000975 OUT("asn_dec_rval_t\n");
976 OUT("%s_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n", p);
977 INDENTED(
978 OUT("\tvoid **structure, const char *opt_mname, void *bufptr, size_t size) {\n");
979 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
980 OUT("return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size);\n");
981 );
982 OUT("}\n");
983 OUT("\n");
984
985 p = MKID(expr->Identifier);
vlm39ba4c42004-09-22 16:06:28 +0000986 OUT("asn_enc_rval_t\n");
vlma5dcb912004-09-29 13:16:40 +0000987 OUT("%s_encode_xer(asn_TYPE_descriptor_t *td, void *structure,\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000988 INDENTED(
989 OUT("\tint ilevel, enum xer_encoder_flags_e flags,\n");
990 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
991 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
992 OUT("return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);\n");
vlmfa67ddc2004-06-03 03:38:44 +0000993 );
994 OUT("}\n");
995 OUT("\n");
996
997 REDIR(OT_FUNC_DECLS);
998
vlmaf841972005-01-28 12:18:50 +0000999 p = MKID_nr(expr->Identifier);
vlm12c8f692004-09-06 08:07:29 +00001000 if(HIDE_INNER_DEFS) OUT("/* ");
vlma5dcb912004-09-29 13:16:40 +00001001 OUT("extern asn_TYPE_descriptor_t asn_DEF_%s;", p);
vlm12c8f692004-09-06 08:07:29 +00001002 if(HIDE_INNER_DEFS) OUT(" // (Use -fall-defs-global to expose) */");
1003 OUT("\n");
vlm39ba4c42004-09-22 16:06:28 +00001004 OUT("asn_struct_free_f %s_free;\n", p);
1005 OUT("asn_struct_print_f %s_print;\n", p);
vlmfa67ddc2004-06-03 03:38:44 +00001006 OUT("asn_constr_check_f %s_constraint;\n", p);
1007 OUT("ber_type_decoder_f %s_decode_ber;\n", p);
1008 OUT("der_type_encoder_f %s_encode_der;\n", p);
vlme03646b2004-10-23 13:34:00 +00001009 OUT("xer_type_decoder_f %s_decode_xer;\n", p);
vlm39ba4c42004-09-22 16:06:28 +00001010 OUT("xer_type_encoder_f %s_encode_xer;\n", p);
vlmfa67ddc2004-06-03 03:38:44 +00001011
vlm33a4ff12004-08-11 05:21:32 +00001012 REDIR(OT_TYPE_DECLS);
1013
vlmfa67ddc2004-06-03 03:38:44 +00001014 return 0;
1015}
1016
1017int
1018asn1c_lang_C_type_EXTENSIBLE(arg_t *arg) {
1019
1020 OUT("/*\n");
1021 OUT(" * This type is extensible,\n");
1022 OUT(" * possible extensions are below.\n");
1023 OUT(" */\n");
1024
1025 return 0;
1026}
1027
vlm79b08d52004-07-01 00:52:50 +00001028static int check_if_extensible(asn1p_expr_t *expr) {
1029 asn1p_expr_t *v;
1030 TQ_FOR(v, &(expr->members), next) {
1031 if(v->expr_type == A1TC_EXTENSIBLE) return 1;
1032 }
1033 return 0;
1034}
1035
vlmfa67ddc2004-06-03 03:38:44 +00001036static int
vlma8a86cc2004-09-10 06:07:18 +00001037_print_tag(arg_t *arg, struct asn1p_type_tag_s *tag) {
vlmfa67ddc2004-06-03 03:38:44 +00001038
1039 OUT("(");
vlma8a86cc2004-09-10 06:07:18 +00001040 switch(tag->tag_class) {
vlmfa67ddc2004-06-03 03:38:44 +00001041 case TC_UNIVERSAL: OUT("ASN_TAG_CLASS_UNIVERSAL"); break;
1042 case TC_APPLICATION: OUT("ASN_TAG_CLASS_APPLICATION"); break;
1043 case TC_CONTEXT_SPECIFIC: OUT("ASN_TAG_CLASS_CONTEXT"); break;
1044 case TC_PRIVATE: OUT("ASN_TAG_CLASS_PRIVATE"); break;
1045 case TC_NOCLASS:
1046 break;
1047 }
vlm47ae1582004-09-24 21:01:43 +00001048 OUT(" | (%" PRIdASN " << 2))", tag->tag_value);
vlmfa67ddc2004-06-03 03:38:44 +00001049
1050 return 0;
1051}
1052
vlm4e03ce22004-06-06 07:20:17 +00001053
1054static int
1055_tag2el_cmp(const void *ap, const void *bp) {
1056 const tag2el_t *a = ap;
1057 const tag2el_t *b = bp;
1058 const struct asn1p_type_tag_s *ta = &a->el_tag;
1059 const struct asn1p_type_tag_s *tb = &b->el_tag;
1060
1061 if(ta->tag_class == tb->tag_class) {
1062 if(ta->tag_value == tb->tag_value) {
1063 /*
1064 * Sort by their respective positions.
1065 */
1066 if(a->el_no < b->el_no)
1067 return -1;
1068 else if(a->el_no > b->el_no)
1069 return 1;
1070 return 0;
1071 } else if(ta->tag_value < tb->tag_value)
1072 return -1;
1073 else
1074 return 1;
1075 } else if(ta->tag_class < tb->tag_class) {
1076 return -1;
1077 } else {
1078 return 1;
1079 }
1080}
1081
vlmfa67ddc2004-06-03 03:38:44 +00001082/*
1083 * For constructed types, number of external tags may be greater than
1084 * number of elements in the type because of CHOICE type.
1085 * T ::= SET { -- Three possible tags:
1086 * a INTEGER, -- One tag is here...
1087 * b Choice1 -- ... and two more tags are there.
1088 * }
1089 * Choice1 ::= CHOICE {
1090 * s1 IA5String,
1091 * s2 ObjectDescriptor
1092 * }
1093 */
1094static int
vlm940bc6b2004-10-03 09:13:30 +00001095_fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
vlmfa67ddc2004-06-03 03:38:44 +00001096 asn1p_expr_t *expr = arg->expr;
1097 arg_t tmparg = *arg;
1098 asn1p_expr_t *v;
1099 int element = 0;
vlm940bc6b2004-10-03 09:13:30 +00001100 int original_count = *count;
1101 int sort_until = -1;
vlmfa67ddc2004-06-03 03:38:44 +00001102
1103 TQ_FOR(v, &(expr->members), next) {
vlm940bc6b2004-10-03 09:13:30 +00001104 if(v->expr_type == A1TC_EXTENSIBLE) {
1105 /*
1106 * CANONICAL-XER mandates sorting
1107 * only for the root part.
1108 */
1109 if(flags == FTE_CANONICAL_XER
1110 && sort_until == -1)
1111 sort_until = *count;
vlmfa67ddc2004-06-03 03:38:44 +00001112 continue;
vlm940bc6b2004-10-03 09:13:30 +00001113 }
vlmfa67ddc2004-06-03 03:38:44 +00001114
1115 tmparg.expr = v;
1116
1117 if(_add_tag2el_member(&tmparg, tag2el, count,
vlm940bc6b2004-10-03 09:13:30 +00001118 (el_no==-1)?element:el_no, flags)) {
vlmfa67ddc2004-06-03 03:38:44 +00001119 return -1;
1120 }
1121
1122 element++;
1123 }
1124
vlm940bc6b2004-10-03 09:13:30 +00001125
1126 if(flags == FTE_CANONICAL_XER) {
1127 if(sort_until == -1) sort_until = *count;
1128 qsort((*tag2el) + original_count,
1129 sort_until - original_count,
1130 sizeof(**tag2el), _tag2el_cmp);
1131 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1132 && (sort_until - original_count) >= 1) {
1133 /* Only take in account the root component */
1134 *count = original_count + 1;
1135 }
1136 } else {
1137 /*
1138 * Sort the map according to canonical order of their
1139 * tags and element numbers.
1140 */
1141 qsort(*tag2el, *count, sizeof(**tag2el), _tag2el_cmp);
1142 }
vlm4e03ce22004-06-06 07:20:17 +00001143
vlmc8aeab42004-06-14 13:09:45 +00001144 /*
1145 * Initialize .toff_{first|last} members.
1146 */
1147 if(*count) {
1148 struct asn1p_type_tag_s *cur_tag = 0;
1149 tag2el_t *cur = *tag2el;
1150 tag2el_t *end = cur + *count;
1151 int occur, i;
1152 for(occur = 0; cur < end; cur++) {
1153 if(cur_tag == 0
1154 || cur_tag->tag_value != cur->el_tag.tag_value
1155 || cur_tag->tag_class != cur->el_tag.tag_class) {
1156 cur_tag = &cur->el_tag;
1157 occur = 0;
1158 } else {
1159 occur++;
1160 }
1161 cur->toff_first = -occur;
1162 for(i = 0; i >= -occur; i--)
1163 cur[i].toff_last = -i;
1164 }
1165 }
1166
vlmfa67ddc2004-06-03 03:38:44 +00001167 return 0;
1168}
1169
1170static int
vlm940bc6b2004-10-03 09:13:30 +00001171_add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
vlmfa67ddc2004-06-03 03:38:44 +00001172 struct asn1p_type_tag_s tag;
1173 int ret;
1174
1175 assert(el_no >= 0);
1176
vlm39ba4c42004-09-22 16:06:28 +00001177 ret = asn1f_fetch_outmost_tag(arg->asn, arg->expr->module,
1178 arg->expr, &tag, 1);
vlmfa67ddc2004-06-03 03:38:44 +00001179 if(ret == 0) {
vlme2070ea2004-09-04 04:42:29 +00001180 tag2el_t *te;
1181 int new_count = (*count) + 1;
vlmfa67ddc2004-06-03 03:38:44 +00001182 void *p;
vlme2070ea2004-09-04 04:42:29 +00001183
vlm2de0e792004-09-05 10:42:33 +00001184 if(tag.tag_value == -1) {
1185 /*
1186 * This is an untagged ANY type,
1187 * proceed without adding a tag
1188 */
1189 return 0;
1190 }
1191
vlme2070ea2004-09-04 04:42:29 +00001192 p = realloc(*tag2el, new_count * sizeof(tag2el_t));
vlmfa67ddc2004-06-03 03:38:44 +00001193 if(p) *tag2el = p;
1194 else return -1;
1195
1196 DEBUG("Found tag for %s: %ld",
1197 arg->expr->Identifier,
1198 (long)tag.tag_value);
1199
vlme2070ea2004-09-04 04:42:29 +00001200 te = &((*tag2el)[*count]);
1201 te->el_tag = tag;
1202 te->el_no = el_no;
1203 te->from_expr = arg->expr;
1204 *count = new_count;
vlmfa67ddc2004-06-03 03:38:44 +00001205 return 0;
1206 }
1207
1208 DEBUG("Searching tag in complex expression %s:%x at line %d",
1209 arg->expr->Identifier,
1210 arg->expr->expr_type,
1211 arg->expr->_lineno);
1212
1213 /*
1214 * Iterate over members of CHOICE type.
1215 */
1216 if(arg->expr->expr_type == ASN_CONSTR_CHOICE) {
vlm940bc6b2004-10-03 09:13:30 +00001217 return _fill_tag2el_map(arg, tag2el, count, el_no, flags);
vlmfa67ddc2004-06-03 03:38:44 +00001218 }
1219
1220 if(arg->expr->expr_type == A1TC_REFERENCE) {
1221 arg_t tmp = *arg;
1222 asn1p_expr_t *expr;
vlmdae7f9d2004-08-22 03:25:24 +00001223 expr = asn1f_lookup_symbol_ex(tmp.asn, tmp.mod, tmp.expr,
vlmfa67ddc2004-06-03 03:38:44 +00001224 arg->expr->reference);
1225 if(expr) {
vlmdae7f9d2004-08-22 03:25:24 +00001226 tmp.mod = expr->module;
vlmfa67ddc2004-06-03 03:38:44 +00001227 tmp.expr = expr;
vlm940bc6b2004-10-03 09:13:30 +00001228 return _add_tag2el_member(&tmp, tag2el, count, el_no, flags);
vlmfa67ddc2004-06-03 03:38:44 +00001229 } else {
1230 FATAL("Cannot dereference %s at line %d",
1231 arg->expr->Identifier,
1232 arg->expr->_lineno);
1233 return -1;
1234 }
1235 }
1236
1237 DEBUG("No tag for %s at line %d",
1238 arg->expr->Identifier,
1239 arg->expr->_lineno);
1240
1241 return -1;
1242}
1243
1244static int
vlm940bc6b2004-10-03 09:13:30 +00001245emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier) {
vlm4e03ce22004-06-06 07:20:17 +00001246 asn1p_expr_t *expr = arg->expr;
1247
vlm940bc6b2004-10-03 09:13:30 +00001248 OUT("static asn_TYPE_tag2member_t asn_DEF_%s_tag2el%s[] = {\n",
vlmaf841972005-01-28 12:18:50 +00001249 MKID_nr(expr->Identifier), opt_modifier?opt_modifier:"");
vlm4e03ce22004-06-06 07:20:17 +00001250 if(tag2el_count) {
1251 int i;
1252 for(i = 0; i < tag2el_count; i++) {
1253 OUT(" { ");
vlma8a86cc2004-09-10 06:07:18 +00001254 _print_tag(arg, &tag2el[i].el_tag);
vlm4e03ce22004-06-06 07:20:17 +00001255 OUT(", ");
vlmc8aeab42004-06-14 13:09:45 +00001256 OUT("%d, ", tag2el[i].el_no);
1257 OUT("%d, ", tag2el[i].toff_first);
1258 OUT("%d ", tag2el[i].toff_last);
vlm4e03ce22004-06-06 07:20:17 +00001259 OUT("}, /* %s at %d */\n",
1260 tag2el[i].from_expr->Identifier,
1261 tag2el[i].from_expr->_lineno
1262 );
1263 }
1264 }
1265 OUT("};\n");
1266
1267 return 0;;
1268}
1269
vlm72425de2004-09-13 08:31:01 +00001270static enum tvm_compat
1271emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tags_count_r, int *all_tags_count_r) {
1272 struct asn1p_type_tag_s *tags = 0; /* Effective tags */
1273 struct asn1p_type_tag_s *all_tags = 0; /* The full array */
vlm6e73a042004-08-11 07:17:22 +00001274 int tags_count = 0;
vlm72425de2004-09-13 08:31:01 +00001275 int all_tags_count = 0;
1276 enum tvm_compat tv_mode = _TVM_SAME;
vlm1308d2b2004-09-10 15:49:15 +00001277 int i;
vlm4a3f5822004-06-28 21:13:46 +00001278
vlmc6de2c42004-09-14 14:10:10 +00001279 /* Cleanup before proceeding. */
1280 *tags_count_r = 0;
1281 *all_tags_count_r = 0;
1282
vlm1308d2b2004-09-10 15:49:15 +00001283 /* Fetch a chain of tags */
vlm39ba4c42004-09-22 16:06:28 +00001284 tags_count = asn1f_fetch_tags(arg->asn, expr->module, expr, &tags, 0);
vlmc6de2c42004-09-14 14:10:10 +00001285 if(tags_count < 0)
1286 return -1;
vlm6e73a042004-08-11 07:17:22 +00001287
vlm72425de2004-09-13 08:31:01 +00001288 /* Fetch a chain of tags */
vlm39ba4c42004-09-22 16:06:28 +00001289 all_tags_count = asn1f_fetch_tags(arg->asn, expr->module, expr,
vlm72425de2004-09-13 08:31:01 +00001290 &all_tags, AFT_FULL_COLLECT);
1291 if(all_tags_count < 0) {
1292 if(tags) free(tags);
1293 return -1;
vlmfb41dbb2004-09-08 00:28:57 +00001294 }
vlm1308d2b2004-09-10 15:49:15 +00001295
vlm72425de2004-09-13 08:31:01 +00001296 assert(tags_count <= all_tags_count);
1297 assert((tags_count?0:1) == (all_tags_count?0:1));
vlm4a3f5822004-06-28 21:13:46 +00001298
vlm72425de2004-09-13 08:31:01 +00001299 if(tags_count <= all_tags_count) {
1300 for(i = 0; i < tags_count; i++) {
1301 if(tags[i].tag_value != all_tags[i].tag_value
1302 || tags[i].tag_class != all_tags[i].tag_class) {
1303 tv_mode = _TVM_DIFFERENT;
1304 break;
1305 }
1306 }
1307 if(i == tags_count && tags_count < all_tags_count)
1308 tv_mode = _TVM_SUBSET;
1309 } else {
1310 tv_mode = _TVM_DIFFERENT;
1311 }
1312
1313#define EMIT_TAGS_TABLE(name, tags, tags_count) do { \
vlma5dcb912004-09-29 13:16:40 +00001314 OUT("static ber_tlv_tag_t asn_DEF_%s%s_tags[] = {\n", \
vlmaf841972005-01-28 12:18:50 +00001315 MKID_nr(expr->Identifier), name); \
vlm72425de2004-09-13 08:31:01 +00001316 INDENT(+1); \
1317 /* Print the array of collected tags */ \
1318 for(i = 0; i < tags_count; i++) { \
1319 if(i) OUT(",\n"); \
1320 _print_tag(arg, &tags[i]); \
1321 } \
1322 OUT("\n"); \
1323 INDENT(-1); \
1324 OUT("};\n"); \
1325 } while(0)
1326
1327 if(tags_count) {
1328 if(tv_mode == _TVM_SUBSET)
1329 EMIT_TAGS_TABLE("", all_tags, all_tags_count);
1330 else
1331 EMIT_TAGS_TABLE("", tags, tags_count);
1332 }
1333
1334 if(all_tags_count) {
1335 if(tv_mode == _TVM_DIFFERENT)
1336 EMIT_TAGS_TABLE("_all", all_tags, all_tags_count);
1337 }
1338
1339 if(tags) free(tags);
1340 if(all_tags) free(all_tags);
1341
1342 *tags_count_r = tags_count;
1343 *all_tags_count_r = all_tags_count;
1344
1345 return tv_mode;
vlm4a3f5822004-06-28 21:13:46 +00001346}
vlmb2839012004-08-20 13:37:01 +00001347
1348static int
vlm4e554992004-08-25 02:03:12 +00001349expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
vlmb2839012004-08-20 13:37:01 +00001350 asn1p_expr_t *topmost_parent;
1351 asn1p_expr_t *v;
1352 int elements = 0;
1353
vlm39ba4c42004-09-22 16:06:28 +00001354 topmost_parent = asn1f_find_terminal_type_ex(arg->asn, expr);
vlmb2839012004-08-20 13:37:01 +00001355 if(!topmost_parent) return 0;
1356
1357 if(!(topmost_parent->expr_type & ASN_CONSTR_MASK))
1358 return 0;
1359
1360 TQ_FOR(v, &(topmost_parent->members), next) {
1361 if(v->expr_type != A1TC_EXTENSIBLE)
1362 elements++;
1363 }
1364
1365 return elements;
1366}
1367
1368static int
vlm4e554992004-08-25 02:03:12 +00001369emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
vlmdae7f9d2004-08-22 03:25:24 +00001370 static int global_memb_unique;
vlmb2839012004-08-20 13:37:01 +00001371 int save_target;
1372 arg_t tmp_arg;
vlm060fe2a2004-09-10 09:37:12 +00001373 struct asn1p_type_tag_s outmost_tag_s;
1374 struct asn1p_type_tag_s *outmost_tag;
vlmb2839012004-08-20 13:37:01 +00001375 char *p;
1376
vlm060fe2a2004-09-10 09:37:12 +00001377 if(asn1f_fetch_outmost_tag(arg->asn,
1378 expr->module, expr, &outmost_tag_s, 1)) {
1379 outmost_tag = 0;
1380 } else {
1381 outmost_tag = &outmost_tag_s;
1382 }
1383
vlmb2839012004-08-20 13:37:01 +00001384 OUT("{ ");
vlm060fe2a2004-09-10 09:37:12 +00001385
1386 if(outmost_tag && outmost_tag->tag_value == -1)
1387 OUT("ATF_OPEN_TYPE | ");
vlma02b74d2004-09-15 11:54:38 +00001388 OUT("%s, ", expr->marker.flags?"ATF_POINTER":"ATF_NOFLAGS");
1389 if((expr->marker.flags & EM_OPTIONAL) == EM_OPTIONAL) {
vlmb2839012004-08-20 13:37:01 +00001390 asn1p_expr_t *tv;
1391 int opts = 0;
vlma02b74d2004-09-15 11:54:38 +00001392 for(tv = expr; tv && tv->marker.flags;
vlmb2839012004-08-20 13:37:01 +00001393 tv = TQ_NEXT(tv, next), opts++) {
1394 if(tv->expr_type == A1TC_EXTENSIBLE)
1395 opts--;
1396 }
1397 OUT("%d, ", opts);
1398 } else {
1399 OUT("0, ");
1400 }
vlm39ba4c42004-09-22 16:06:28 +00001401 if(expr->_anonymous_type) {
1402 assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
1403 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
1404 OUT("0,\n");
1405 } else {
vlmb2839012004-08-20 13:37:01 +00001406 OUT("offsetof(struct %s, ", MKID(arg->expr->Identifier));
1407 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1408 && (!UNNAMED_UNIONS)) OUT("choice.");
1409 OUT("%s),\n", MKID(expr->Identifier));
vlmb2839012004-08-20 13:37:01 +00001410 }
1411 INDENT(+1);
1412 if(C99_MODE) OUT(".tag = ");
vlm060fe2a2004-09-10 09:37:12 +00001413 if(outmost_tag) {
1414 if(outmost_tag->tag_value == -1)
1415 OUT("-1 /* Ambiguous tag (ANY?) */");
1416 else
1417 _print_tag(arg, outmost_tag);
vlma8a86cc2004-09-10 06:07:18 +00001418 } else {
vlm060fe2a2004-09-10 09:37:12 +00001419 OUT("-1 /* Ambiguous tag (CHOICE?) */");
vlma8a86cc2004-09-10 06:07:18 +00001420 }
vlm060fe2a2004-09-10 09:37:12 +00001421
vlmb2839012004-08-20 13:37:01 +00001422 OUT(",\n");
1423 if(C99_MODE) OUT(".tag_mode = ");
1424 if(expr->tag.tag_class) {
1425 if(expr->tag.tag_mode == TM_IMPLICIT)
1426 OUT("-1,\t/* IMPLICIT tag at current level */\n");
1427 else
1428 OUT("+1,\t/* EXPLICIT tag at current level */\n");
1429 } else {
1430 OUT("0,\n");
1431 }
1432 if(C99_MODE) OUT(".type = ");
vlm39ba4c42004-09-22 16:06:28 +00001433 if(expr->_anonymous_type && (expr->expr_type & ASN_CONSTR_MASK)) {
vlma5dcb912004-09-29 13:16:40 +00001434 OUT("(void *)&asn_DEF_%s_member,\n",
vlmaf841972005-01-28 12:18:50 +00001435 MKID_nr(arg->expr->Identifier));
vlm4e554992004-08-25 02:03:12 +00001436 } else if(expr->expr_type & ASN_CONSTR_MASK) {
vlma5dcb912004-09-29 13:16:40 +00001437 OUT("(void *)&asn_DEF_%s,\n",
vlmaf841972005-01-28 12:18:50 +00001438 MKID_nr(expr->Identifier));
vlmdae7f9d2004-08-22 03:25:24 +00001439 } else {
vlma5dcb912004-09-29 13:16:40 +00001440 OUT("(void *)&asn_DEF_%s,\n",
vlmdae7f9d2004-08-22 03:25:24 +00001441 asn1c_type_name(arg, expr, TNF_SAFE));
1442 }
vlmb2839012004-08-20 13:37:01 +00001443 if(C99_MODE) OUT(".memb_constraints = ");
1444 if(expr->constraints) {
vlm86f5ed22004-09-26 13:11:31 +00001445 if(arg->flags & A1C_NO_CONSTRAINTS) {
1446 OUT("0,\t/* No check because of -fno-constraints */\n");
1447 } else {
vlmaf841972005-01-28 12:18:50 +00001448 char *id = MKID_nr(expr->Identifier);
vlm86f5ed22004-09-26 13:11:31 +00001449 if(expr->_anonymous_type
vlmbf3c5112005-02-14 20:41:29 +00001450 && !strcmp(expr->Identifier, "Member"))
vlm86f5ed22004-09-26 13:11:31 +00001451 id = asn1c_type_name(arg, expr, TNF_SAFE);
1452 OUT("memb_%s_%d_constraint,\n", id,
1453 ++global_memb_unique);
1454 }
vlmb2839012004-08-20 13:37:01 +00001455 } else {
vlm95a476e2005-01-17 12:16:58 +00001456 OUT("0,\t/* Defer constraints checking to the member type */\n");
vlmb2839012004-08-20 13:37:01 +00001457 }
1458 if(C99_MODE) OUT(".name = ");
vlmbf3c5112005-02-14 20:41:29 +00001459 if(1) {
1460 if(expr->_anonymous_type && !strcmp(expr->Identifier, "Member"))
1461 OUT("\"\"\n");
1462 else
1463 OUT("\"%s\"\n", expr->Identifier);
1464 } else {
1465 OUT("\"%s\"\n", expr->_anonymous_type ? "" : expr->Identifier);
1466 }
vlmb2839012004-08-20 13:37:01 +00001467 OUT("},\n");
1468 INDENT(-1);
1469
vlm86f5ed22004-09-26 13:11:31 +00001470 if(!expr->constraints || (arg->flags & A1C_NO_CONSTRAINTS))
vlmb2839012004-08-20 13:37:01 +00001471 return 0;
1472
1473 save_target = arg->target->target;
1474 REDIR(OT_CODE);
1475
vlmbf3c5112005-02-14 20:41:29 +00001476 if(expr->_anonymous_type && !strcmp(expr->Identifier, "Member"))
vlmb2839012004-08-20 13:37:01 +00001477 p = asn1c_type_name(arg, expr, TNF_SAFE);
vlm39ba4c42004-09-22 16:06:28 +00001478 else
vlmaf841972005-01-28 12:18:50 +00001479 p = MKID_nr(expr->Identifier);
vlmb2839012004-08-20 13:37:01 +00001480 OUT("static int\n");
vlma5dcb912004-09-29 13:16:40 +00001481 OUT("memb_%s_%d_constraint(asn_TYPE_descriptor_t *td, const void *sptr,\n", p, global_memb_unique);
vlmb2839012004-08-20 13:37:01 +00001482 INDENT(+1);
1483 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
1484 tmp_arg = *arg;
1485 tmp_arg.expr = expr;
1486 if(asn1c_emit_constraint_checking_code(&tmp_arg) == 1) {
vlm86f5ed22004-09-26 13:11:31 +00001487 OUT("return td->check_constraints"
1488 "(td, sptr, app_errlog, app_key);\n");
vlmb2839012004-08-20 13:37:01 +00001489 }
1490 INDENT(-1);
1491 OUT("}\n");
1492 OUT("\n");
1493
1494 REDIR(save_target);
1495
1496 return 0;
1497}
vlm4e554992004-08-25 02:03:12 +00001498
vlm9de248e2004-10-20 15:50:55 +00001499/*
1500 * Generate "asn_DEF_XXX" type definition.
1501 */
vlm4e554992004-08-25 02:03:12 +00001502static int
vlm86f5ed22004-09-26 13:11:31 +00001503emit_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 +00001504 char *p;
1505
vlm12c8f692004-09-06 08:07:29 +00001506 if(HIDE_INNER_DEFS)
1507 OUT("static /* Use -fall-defs-global to expose */\n");
vlmaf841972005-01-28 12:18:50 +00001508 OUT("asn_TYPE_descriptor_t asn_DEF_%s = {\n",
1509 MKID_nr(expr->Identifier));
1510 p = MKID(expr->Identifier);
vlm72425de2004-09-13 08:31:01 +00001511 INDENT(+1);
vlm4e554992004-08-25 02:03:12 +00001512 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
vlm9de248e2004-10-20 15:50:55 +00001513 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
vlm4e554992004-08-25 02:03:12 +00001514
1515 if(expr->expr_type & ASN_CONSTR_MASK) {
1516 p = asn1c_type_name(arg, arg->expr, TNF_SAFE);
1517 }
1518
vlm39ba4c42004-09-22 16:06:28 +00001519 OUT("%s_free,\n", p);
1520 OUT("%s_print,\n", p);
vlm4e554992004-08-25 02:03:12 +00001521 OUT("%s_constraint,\n", p);
1522 OUT("%s_decode_ber,\n", p);
1523 OUT("%s_encode_der,\n", p);
vlm265ab7c2005-02-14 20:29:54 +00001524 OUT("%s_decode_xer,\n", p);
vlm39ba4c42004-09-22 16:06:28 +00001525 OUT("%s_encode_xer,\n", p);
vlm4e554992004-08-25 02:03:12 +00001526
vlm4e554992004-08-25 02:03:12 +00001527 if(expr->expr_type == ASN_CONSTR_CHOICE) {
1528 OUT("CHOICE_outmost_tag,\n");
1529 } else {
1530 OUT("0,\t/* Use generic outmost tag fetcher */\n");
1531 }
1532
vlmaf841972005-01-28 12:18:50 +00001533 p = MKID_nr(expr->Identifier);
vlm4e554992004-08-25 02:03:12 +00001534 if(tags_count) {
vlma5dcb912004-09-29 13:16:40 +00001535 OUT("asn_DEF_%s_tags,\n", p);
1536 OUT("sizeof(asn_DEF_%s_tags)\n", p);
1537 OUT("\t/sizeof(asn_DEF_%s_tags[0])", p);
vlm72425de2004-09-13 08:31:01 +00001538 if(tv_mode == _TVM_SUBSET
1539 && tags_count != all_tags_count)
1540 OUT(" - %d", all_tags_count - tags_count);
1541 OUT(", /* %d */\n", tags_count);
vlm4e554992004-08-25 02:03:12 +00001542 } else {
vlm72425de2004-09-13 08:31:01 +00001543 OUT("0,\t/* No effective tags (pointer) */\n");
1544 OUT("0,\t/* No effective tags (count) */\n");
1545 }
1546
1547 if(all_tags_count && tv_mode == _TVM_DIFFERENT) {
vlma5dcb912004-09-29 13:16:40 +00001548 OUT("asn_DEF_%s_all_tags,\n", p);
1549 OUT("sizeof(asn_DEF_%s_all_tags)\n", p);
1550 OUT("\t/sizeof(asn_DEF_%s_all_tags[0]), /* %d */\n",
vlm72425de2004-09-13 08:31:01 +00001551 p, all_tags_count);
1552 } else if(all_tags_count) {
vlma5dcb912004-09-29 13:16:40 +00001553 OUT("asn_DEF_%s_tags,\t/* Same as above */\n", p);
1554 OUT("sizeof(asn_DEF_%s_tags)\n", p);
1555 OUT("\t/sizeof(asn_DEF_%s_tags[0]), /* %d */\n",
vlm72425de2004-09-13 08:31:01 +00001556 p, all_tags_count);
1557 } else {
1558 OUT("0,\t/* No tags (pointer) */\n");
1559 OUT("0,\t/* No tags (count) */\n");
vlm4e554992004-08-25 02:03:12 +00001560 }
1561
vlm4e554992004-08-25 02:03:12 +00001562 if(elements_count) {
vlma5dcb912004-09-29 13:16:40 +00001563 OUT("asn_MBR_%s,\n", p);
vlm4e554992004-08-25 02:03:12 +00001564 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF
1565 || expr->expr_type == ASN_CONSTR_SET_OF) {
1566 OUT("%d,\t/* Single element */\n",
1567 elements_count);
1568 assert(elements_count == 1);
1569 } else {
1570 OUT("%d,\t/* Elements count */\n",
1571 elements_count);
1572 }
1573 } else {
1574 //if(expr->meta_type == AMT_TYPEREF)
1575 if(expr_elements_count(arg, expr))
1576 OUT("0, 0,\t/* Defined elsewhere */\n");
1577 else
1578 OUT("0, 0,\t/* No members */\n");
1579 }
1580
1581 switch(spec) {
1582 case ETD_NO_SPECIFICS:
1583 OUT("0\t/* No specifics */\n");
1584 break;
1585 case ETD_HAS_SPECIFICS:
vlma5dcb912004-09-29 13:16:40 +00001586 OUT("&asn_DEF_%s_specs\t/* Additional specs */\n", p);
vlm4e554992004-08-25 02:03:12 +00001587 }
vlm72425de2004-09-13 08:31:01 +00001588 INDENT(-1);
vlm4e554992004-08-25 02:03:12 +00001589 OUT("};\n");
1590 OUT("\n");
vlme2bb4432004-08-26 06:20:34 +00001591
1592 return 0;
vlm4e554992004-08-25 02:03:12 +00001593}
vlmddd5a7d2004-09-10 09:18:20 +00001594
1595/*
1596 * Check if it is better to make this type indirectly accessed via
1597 * a pointer.
1598 * This may be the case for the following recursive definition:
1599 * Type ::= CHOICE { member Type };
1600 */
1601static int
1602expr_better_indirect(arg_t *arg, asn1p_expr_t *expr) {
1603 asn1p_expr_t *top_parent;
1604 asn1p_expr_t *terminal;
1605
1606 if(expr->expr_type != A1TC_REFERENCE)
1607 return 0;
1608
1609 /* Rewind to the topmost parent expression */
1610 if((top_parent = expr->parent_expr)) {
1611 while(top_parent->parent_expr)
1612 top_parent = top_parent->parent_expr;
1613 } else {
1614 return 0;
1615 }
1616
vlm39ba4c42004-09-22 16:06:28 +00001617 terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
vlmddd5a7d2004-09-10 09:18:20 +00001618
1619 return (terminal == top_parent);
1620}
vlm39ba4c42004-09-22 16:06:28 +00001621
1622static int
1623expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr) {
1624 expr = asn1f_find_terminal_type_ex(arg->asn, expr);
1625 if(!expr) return 0;
1626
1627 /* X.680, 25.5, Table 5 */
1628 switch(expr->expr_type) {
1629 case ASN_CONSTR_CHOICE:
1630 case ASN_BASIC_BOOLEAN:
1631 case ASN_BASIC_ENUMERATED:
1632 case ASN_BASIC_NULL:
1633 return 1;
1634 default:
1635 return 0;
1636 }
1637}
vlmaf841972005-01-28 12:18:50 +00001638
1639static int
1640out_identifiers_chain(arg_t *arg, int check_reserved_keywords) {
1641 asn1p_expr_t *expr = arg->expr;
1642 char *id;
1643
1644 assert(expr->Identifier);
1645
1646 if(arg->flags & A1C_DOUBLE_IDENTIFIERS
1647 && expr->parent_expr
1648 && expr->parent_expr->Identifier) {
1649 arg_t tmparg = *arg;
1650
1651 tmparg.expr = expr->parent_expr;
1652 tmparg.flags &= ~A1C_DOUBLE_IDENTIFIERS;
1653 out_identifiers_chain(&tmparg, 0);
1654
1655 OUT("_"); /* a separator between id components */
1656 /* Fall through */
1657 }
1658
1659 if(check_reserved_keywords)
1660 id = MKID(expr->Identifier);
1661 else
1662 id = MKID_nr(expr->Identifier);
1663 OUT("%s", id);
1664
1665 return 0;
1666}