blob: c0ff5a1e36b925cdd8765e77822a8cffce42723a [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
vlm80a48592005-02-25 12:10:27 +000088struct value2enum {
89 asn1c_integer_t value;
90 const char *name;
91 int idx;
92};
93static int compar_enumMap_byName(const void *ap, const void *bp) {
94 const struct value2enum *a = (const struct value2enum *)ap;
95 const struct value2enum *b = (const struct value2enum *)bp;
96 return strcmp(a->name, b->name);
97}
98static int compar_enumMap_byValue(const void *ap, const void *bp) {
99 const struct value2enum *a = (const struct value2enum *)ap;
100 const struct value2enum *b = (const struct value2enum *)bp;
101 if(a->value < b->value)
102 return -1;
103 else if(a->value == b->value)
104 return 0;
105 return 1;
106}
107
vlmfa67ddc2004-06-03 03:38:44 +0000108int
vlmf9d178d2004-09-14 12:47:45 +0000109asn1c_lang_C_type_common_INTEGER(arg_t *arg) {
vlmfa67ddc2004-06-03 03:38:44 +0000110 asn1p_expr_t *expr = arg->expr;
111 asn1p_expr_t *v;
vlm80a48592005-02-25 12:10:27 +0000112 int el_count = expr_elements_count(arg, expr);
113 struct value2enum *v2e;
114 int map_is_extensible = (expr->expr_type == ASN_BASIC_INTEGER);
vlmfa67ddc2004-06-03 03:38:44 +0000115
vlm80a48592005-02-25 12:10:27 +0000116 v2e = alloca((el_count + 1) * sizeof(*v2e));
vlmfa67ddc2004-06-03 03:38:44 +0000117
vlm80a48592005-02-25 12:10:27 +0000118 /*
119 * For all ENUMERATED types and for those INTEGER types which
120 * have identifiers, print out an enumeration table and a mapping
121 * between identifiers and associated values.
122 */
123 if(expr->expr_type == ASN_BASIC_ENUMERATED || el_count) {
124 int eidx = 0;
125
126 REDIR(OT_DEPS);
vlmfa67ddc2004-06-03 03:38:44 +0000127 OUT("typedef enum %s {\n", MKID(expr->Identifier));
128 TQ_FOR(v, &(expr->members), next) {
129 switch(v->expr_type) {
130 case A1TC_UNIVERVAL:
vlm80a48592005-02-25 12:10:27 +0000131 OUT("\t%s\t= %" PRIdASN "%s\n",
vlmfa67ddc2004-06-03 03:38:44 +0000132 asn1c_make_identifier(0,
133 expr->Identifier,
134 v->Identifier, 0),
vlm80a48592005-02-25 12:10:27 +0000135 v->value->value.v_integer,
136 (eidx+1 < el_count) ? "," : ""
137 );
138 v2e[eidx].name = v->Identifier;
139 v2e[eidx].value = v->value->value.v_integer;
140 eidx++;
vlmfa67ddc2004-06-03 03:38:44 +0000141 break;
vlmf9d178d2004-09-14 12:47:45 +0000142 case A1TC_EXTENSIBLE:
143 OUT("\t/*\n");
144 OUT("\t * Enumeration is extensible\n");
145 OUT("\t */\n");
vlm80a48592005-02-25 12:10:27 +0000146 map_is_extensible = 1;
vlmf9d178d2004-09-14 12:47:45 +0000147 break;
vlmfa67ddc2004-06-03 03:38:44 +0000148 default:
149 return -1;
150 }
151 }
152 OUT("} %s_e;\n", MKID(expr->Identifier));
vlm80a48592005-02-25 12:10:27 +0000153 assert(eidx == el_count);
154
155 /*
156 * Generate a enumerationName<->value map for XER codec.
157 */
158 REDIR(OT_STAT_DEFS);
159
160 OUT("static asn_INTEGER_enum_map_t asn_MAP_%s_value2enum[] = {\n",
161 MKID_nr(expr->Identifier));
162 qsort(v2e, el_count, sizeof(v2e[0]), compar_enumMap_byValue);
163 for(eidx = 0; eidx < el_count; eidx++) {
164 v2e[eidx].idx = eidx;
165 OUT("\t{ %" PRIdASN ",\t%ld,\t\"%s\" }%s\n",
166 v2e[eidx].value,
167 (long)strlen(v2e[eidx].name), v2e[eidx].name,
168 (eidx + 1 < el_count) ? "," : "");
169 }
170 if(map_is_extensible)
171 OUT("\t/* This list is extensible */\n");
172 OUT("};\n");
173
174 OUT("static unsigned int asn_MAP_%s_enum2value[] = {\n",
175 MKID_nr(expr->Identifier));
176 qsort(v2e, el_count, sizeof(v2e[0]), compar_enumMap_byName);
177 for(eidx = 0; eidx < el_count; eidx++) {
178 OUT("\t%d%s\t/* %s(%" PRIdASN ") */\n",
179 v2e[eidx].idx,
180 (eidx + 1 < el_count) ? "," : "",
181 v2e[eidx].name, v2e[eidx].value);
182 }
183 if(map_is_extensible)
184 OUT("\t/* This list is extensible */\n");
185 OUT("};\n");
186
187 OUT("static asn_INTEGER_specifics_t asn_DEF_%s_specs = {\n",
188 MKID_nr(expr->Identifier));
189 INDENT(+1);
190 OUT("asn_MAP_%s_value2enum,\t"
191 "/* \"tag\" => N; sorted by tag */\n",
192 MKID_nr(expr->Identifier));
193 OUT("asn_MAP_%s_enum2value,\t"
194 "/* N => \"tag\"; sorted by N */\n",
195 MKID_nr(expr->Identifier));
196 OUT("%d,\t/* Number of elements in the maps */\n",
197 el_count);
198 OUT("%d,\t/* Enumeration is %sextensible */\n",
199 map_is_extensible, map_is_extensible ? "": "not ");
200 if(expr->expr_type == ASN_BASIC_ENUMERATED)
201 OUT("1\t/* Strict enumeration */\n");
202 else
203 OUT("0\n");
204 INDENT(-1);
205 OUT("};\n");
vlmfa67ddc2004-06-03 03:38:44 +0000206 }
207
208 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
209}
210
211int
212asn1c_lang_C_type_SEQUENCE(arg_t *arg) {
213 asn1p_expr_t *expr = arg->expr;
214 asn1p_expr_t *v;
215 int comp_mode = 0; /* {root,ext=1,root,root,...} */
216
217 DEPENDENCIES;
218
219 if(arg->embed) {
vlmaf841972005-01-28 12:18:50 +0000220 OUT("struct "); out_identifiers_chain(arg, 1); OUT(" {\n");
vlmfa67ddc2004-06-03 03:38:44 +0000221 } else {
222 OUT("typedef struct %s {\n",
223 MKID(expr->Identifier));
224 }
225
226 TQ_FOR(v, &(expr->members), next) {
227 if(v->expr_type == A1TC_EXTENSIBLE) {
228 if(comp_mode < 3) comp_mode++;
229 }
vlmddd5a7d2004-09-10 09:18:20 +0000230 if(comp_mode == 1
231 || expr_better_indirect(arg, v))
vlma02b74d2004-09-15 11:54:38 +0000232 v->marker.flags |= EM_INDIRECT;
vlmfa67ddc2004-06-03 03:38:44 +0000233 EMBED(v);
234 }
235
236 PCTX_DEF;
vlma02b74d2004-09-15 11:54:38 +0000237 OUT("} %s%s%s", expr->marker.flags?"*":"",
vlmdae7f9d2004-08-22 03:25:24 +0000238 expr->_anonymous_type ? "" : MKID(expr->Identifier),
239 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000240
241 return asn1c_lang_C_type_SEQUENCE_def(arg);
242}
243
244static int
245asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
246 asn1p_expr_t *expr = arg->expr;
247 asn1p_expr_t *v;
248 int elements; /* Number of elements */
vlmfa67ddc2004-06-03 03:38:44 +0000249 int ext_start = -1;
250 int ext_stop = -1;
vlm4e03ce22004-06-06 07:20:17 +0000251 tag2el_t *tag2el = NULL;
252 int tag2el_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000253 int tags_count;
vlm72425de2004-09-13 08:31:01 +0000254 int all_tags_count;
255 enum tvm_compat tv_mode;
vlmfa67ddc2004-06-03 03:38:44 +0000256 char *p;
257
vlm4e03ce22004-06-06 07:20:17 +0000258 /*
259 * Fetch every inner tag from the tag to elements map.
260 */
vlm940bc6b2004-10-03 09:13:30 +0000261 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
vlm4e03ce22004-06-06 07:20:17 +0000262 if(tag2el) free(tag2el);
263 return -1;
264 }
265
vlm33a4ff12004-08-11 05:21:32 +0000266 GEN_INCLUDE("constr_SEQUENCE");
267 if(!arg->embed)
vlma5dcb912004-09-29 13:16:40 +0000268 GEN_DECLARE(expr); /* asn_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000269
vlm33a4ff12004-08-11 05:21:32 +0000270 REDIR(OT_STAT_DEFS);
vlmfa67ddc2004-06-03 03:38:44 +0000271
272 /*
273 * Print out the table according to which the parsing is performed.
274 */
vlm39ba4c42004-09-22 16:06:28 +0000275 if(expr_elements_count(arg, expr)) {
276 int comp_mode = 0; /* {root,ext=1,root,root,...} */
vlmfa67ddc2004-06-03 03:38:44 +0000277
vlmaf841972005-01-28 12:18:50 +0000278 p = MKID_nr(expr->Identifier);
vlma5dcb912004-09-29 13:16:40 +0000279 OUT("static asn_TYPE_member_t asn_MBR_%s[] = {\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000280
281 elements = 0;
282 INDENTED(TQ_FOR(v, &(expr->members), next) {
283 if(v->expr_type == A1TC_EXTENSIBLE) {
284 if((++comp_mode) == 1)
285 ext_start = elements - 1;
286 else
287 ext_stop = elements - 1;
288 continue;
289 }
290 elements++;
291 emit_member_table(arg, v);
292 });
293 OUT("};\n");
294 } else {
295 elements = 0;
296 }
vlmfa67ddc2004-06-03 03:38:44 +0000297
vlm4a3f5822004-06-28 21:13:46 +0000298 /*
vlma5dcb912004-09-29 13:16:40 +0000299 * Print out asn_DEF_<type>_[all_]tags[] vectors.
vlm4a3f5822004-06-28 21:13:46 +0000300 */
vlm72425de2004-09-13 08:31:01 +0000301 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
vlmfa67ddc2004-06-03 03:38:44 +0000302
vlm4e03ce22004-06-06 07:20:17 +0000303 /*
304 * Tags to elements map.
305 */
vlm940bc6b2004-10-03 09:13:30 +0000306 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
vlm4e03ce22004-06-06 07:20:17 +0000307
vlmaf841972005-01-28 12:18:50 +0000308 OUT("static asn_SEQUENCE_specifics_t asn_DEF_%s_specs = {\n",
309 MKID_nr(expr->Identifier));
vlm4a3f5822004-06-28 21:13:46 +0000310 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000311 INDENTED(
312 OUT("sizeof(struct %s),\n", p);
vlma5dcb912004-09-29 13:16:40 +0000313 OUT("offsetof(struct %s, _asn_ctx),\n", p);
vlmaf841972005-01-28 12:18:50 +0000314 OUT("asn_DEF_%s_tag2el,\n", MKID_nr(expr->Identifier));
vlm4e03ce22004-06-06 07:20:17 +0000315 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
vlmfa67ddc2004-06-03 03:38:44 +0000316 OUT("%d,\t/* Start extensions */\n",
317 ext_start);
318 OUT("%d\t/* Stop extensions */\n",
319 (ext_stop<ext_start)?elements+1:ext_stop, ext_stop);
320 );
321 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000322
323 /*
vlma5dcb912004-09-29 13:16:40 +0000324 * Emit asn_DEF_xxx table.
vlm4e554992004-08-25 02:03:12 +0000325 */
vlm72425de2004-09-13 08:31:01 +0000326 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
vlm86f5ed22004-09-26 13:11:31 +0000327 ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000328
vlmfa67ddc2004-06-03 03:38:44 +0000329 REDIR(OT_TYPE_DECLS);
330
331 return 0;
vlmedf203f2005-01-17 11:57:48 +0000332} /* _SEQUENCE_def() */
vlmfa67ddc2004-06-03 03:38:44 +0000333
334int
vlmfa67ddc2004-06-03 03:38:44 +0000335asn1c_lang_C_type_SET(arg_t *arg) {
336 asn1p_expr_t *expr = arg->expr;
337 asn1p_expr_t *v;
338 long mcount;
339 char *id;
340 int comp_mode = 0; /* {root,ext=1,root,root,...} */
341
342 DEPENDENCIES;
343
344 REDIR(OT_DEPS);
345
346 OUT("\n");
347 OUT("/*\n");
348 OUT(" * Method of determining the components presence\n");
349 OUT(" */\n");
350 mcount = 0;
vlmaf841972005-01-28 12:18:50 +0000351 OUT("typedef enum "); out_identifiers_chain(arg, 0); OUT("_PR {\n");
vlmfa67ddc2004-06-03 03:38:44 +0000352 TQ_FOR(v, &(expr->members), next) {
353 if(v->expr_type == A1TC_EXTENSIBLE) continue;
354 INDENTED(
vlmaf841972005-01-28 12:18:50 +0000355 out_identifiers_chain(arg, 0);
356 OUT("_PR_");
357 id = MKID_nr(v->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000358 OUT("%s,\t/* Member %s is present */\n",
359 id, id)
360 );
361 mcount++;
362 }
vlmaf841972005-01-28 12:18:50 +0000363 OUT("} "); out_identifiers_chain(arg, 0); OUT("_PR;\n");
vlmfa67ddc2004-06-03 03:38:44 +0000364
365 REDIR(OT_TYPE_DECLS);
366
367 if(arg->embed) {
vlmaf841972005-01-28 12:18:50 +0000368 OUT("struct "); out_identifiers_chain(arg, 1); OUT(" {\n");
vlmfa67ddc2004-06-03 03:38:44 +0000369 } else {
vlmaf841972005-01-28 12:18:50 +0000370 id = MKID(expr->Identifier);
vlm6e73a042004-08-11 07:17:22 +0000371 OUT("typedef struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000372 }
373
374 TQ_FOR(v, &(expr->members), next) {
375 if(v->expr_type == A1TC_EXTENSIBLE) {
376 if(comp_mode < 3) comp_mode++;
377 }
vlmddd5a7d2004-09-10 09:18:20 +0000378 if(comp_mode == 1
379 || expr_better_indirect(arg, v))
vlma02b74d2004-09-15 11:54:38 +0000380 v->marker.flags |= EM_INDIRECT;
vlmfa67ddc2004-06-03 03:38:44 +0000381 EMBED(v);
382 }
383
384 INDENTED(
vlmaf841972005-01-28 12:18:50 +0000385 id = MKID_nr(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000386 OUT("\n");
387 OUT("/* Presence bitmask: ASN_SET_ISPRESENT(p%s, %s_PR_x) */\n",
388 id, id);
389 OUT("unsigned int _presence_map\n");
390 OUT("\t[((%ld+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))];\n", mcount);
391 );
392
393 PCTX_DEF;
vlma02b74d2004-09-15 11:54:38 +0000394 OUT("} %s%s%s", expr->marker.flags?"*":"",
vlmdae7f9d2004-08-22 03:25:24 +0000395 expr->_anonymous_type ? "" : MKID(expr->Identifier),
396 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000397
398 return asn1c_lang_C_type_SET_def(arg);
399}
400
vlmfa67ddc2004-06-03 03:38:44 +0000401static int
402asn1c_lang_C_type_SET_def(arg_t *arg) {
403 asn1p_expr_t *expr = arg->expr;
404 asn1p_expr_t *v;
405 int elements;
vlmfa67ddc2004-06-03 03:38:44 +0000406 tag2el_t *tag2el = NULL;
407 int tag2el_count = 0;
vlm940bc6b2004-10-03 09:13:30 +0000408 tag2el_t *tag2el_cxer = NULL;
409 int tag2el_cxer_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000410 int tags_count;
vlm72425de2004-09-13 08:31:01 +0000411 int all_tags_count;
412 enum tvm_compat tv_mode;
vlmfa67ddc2004-06-03 03:38:44 +0000413 char *p;
414
415 /*
416 * Fetch every inner tag from the tag to elements map.
417 */
vlm940bc6b2004-10-03 09:13:30 +0000418 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
vlmfa67ddc2004-06-03 03:38:44 +0000419 if(tag2el) free(tag2el);
420 return -1;
vlmfa67ddc2004-06-03 03:38:44 +0000421 }
vlm940bc6b2004-10-03 09:13:30 +0000422 if(_fill_tag2el_map(arg, &tag2el_cxer, &tag2el_cxer_count, -1, FTE_CANONICAL_XER)) {
423 if(tag2el) free(tag2el);
424 if(tag2el_cxer) free(tag2el_cxer);
425 return -1;
426 }
427 if(tag2el_cxer_count == tag2el_count
428 && memcmp(tag2el, tag2el_cxer, tag2el_count) == 0) {
429 free(tag2el_cxer);
430 tag2el_cxer = 0;
431 }
vlmfa67ddc2004-06-03 03:38:44 +0000432
vlm33a4ff12004-08-11 05:21:32 +0000433 GEN_INCLUDE("constr_SET");
434 if(!arg->embed)
vlma5dcb912004-09-29 13:16:40 +0000435 GEN_DECLARE(expr); /* asn_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000436
437 REDIR(OT_STAT_DEFS);
438
vlmfa67ddc2004-06-03 03:38:44 +0000439 /*
440 * Print out the table according to which the parsing is performed.
441 */
vlm39ba4c42004-09-22 16:06:28 +0000442 if(expr_elements_count(arg, expr)) {
443 int comp_mode = 0; /* {root,ext=1,root,root,...} */
vlmfa67ddc2004-06-03 03:38:44 +0000444
vlmaf841972005-01-28 12:18:50 +0000445 OUT("static asn_TYPE_member_t asn_MBR_%s[] = {\n",
446 MKID_nr(expr->Identifier));
vlm39ba4c42004-09-22 16:06:28 +0000447
448 elements = 0;
449 INDENTED(TQ_FOR(v, &(expr->members), next) {
450 if(v->expr_type == A1TC_EXTENSIBLE) {
451 if(comp_mode < 3) comp_mode++;
452 } else {
453 if(comp_mode == 1
454 || expr_better_indirect(arg, v))
455 v->marker.flags |= EM_INDIRECT;
456 elements++;
457 emit_member_table(arg, v);
458 }
459 });
460 OUT("};\n");
461 } else {
462 elements = 0;
463 }
vlmfa67ddc2004-06-03 03:38:44 +0000464
vlm4a3f5822004-06-28 21:13:46 +0000465 /*
vlma5dcb912004-09-29 13:16:40 +0000466 * Print out asn_DEF_<type>_[all_]tags[] vectors.
vlm4a3f5822004-06-28 21:13:46 +0000467 */
vlm72425de2004-09-13 08:31:01 +0000468 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
vlmfa67ddc2004-06-03 03:38:44 +0000469
470 /*
471 * Tags to elements map.
472 */
vlm940bc6b2004-10-03 09:13:30 +0000473 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
474 if(tag2el_cxer)
475 emit_tag2member_map(arg, tag2el_cxer, tag2el_cxer_count, "_cxer");
vlmfa67ddc2004-06-03 03:38:44 +0000476
477 /*
478 * Emit a map of mandatory elements.
479 */
vlmaf841972005-01-28 12:18:50 +0000480 OUT("static uint8_t asn_DEF_%s_mmap",
481 MKID_nr(expr->Identifier));
vlm4a3f5822004-06-28 21:13:46 +0000482 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000483 OUT("[(%d + (8 * sizeof(unsigned int)) - 1) / 8]", elements);
484 OUT(" = {\n", p);
485 INDENTED(
486 if(elements) {
487 int delimit = 0;
488 int el = 0;
489 TQ_FOR(v, &(expr->members), next) {
490 if(v->expr_type == A1TC_EXTENSIBLE) continue;
491 if(delimit) {
492 OUT(",\n");
493 delimit = 0;
494 } else if(el) {
495 OUT(" | ");
496 }
vlmddd5a7d2004-09-10 09:18:20 +0000497 OUT("(%d << %d)",
vlma02b74d2004-09-15 11:54:38 +0000498 v->marker.flags?0:1,
vlmddd5a7d2004-09-10 09:18:20 +0000499 7 - (el % 8));
vlmfa67ddc2004-06-03 03:38:44 +0000500 if(el && (el % 8) == 0)
501 delimit = 1;
502 el++;
503 }
504 } else {
505 OUT("0");
506 }
507 );
508 OUT("\n");
509 OUT("};\n");
510
vlmaf841972005-01-28 12:18:50 +0000511 OUT("static asn_SET_specifics_t asn_DEF_%s_specs = {\n",
512 MKID_nr(expr->Identifier));
513 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000514 INDENTED(
515 OUT("sizeof(struct %s),\n", p);
vlma5dcb912004-09-29 13:16:40 +0000516 OUT("offsetof(struct %s, _asn_ctx),\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000517 OUT("offsetof(struct %s, _presence_map),\n", p);
vlmaf841972005-01-28 12:18:50 +0000518 p = MKID_nr(expr->Identifier);
vlma5dcb912004-09-29 13:16:40 +0000519 OUT("asn_DEF_%s_tag2el,\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000520 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
vlm940bc6b2004-10-03 09:13:30 +0000521 if(tag2el_cxer)
522 OUT("asn_DEF_%s_tag2el_cxer,\n", p);
523 else
524 OUT("asn_DEF_%s_tag2el,\t/* Same as above */\n", p);
vlm80a48592005-02-25 12:10:27 +0000525 OUT("%d,\t/* Count of tags in the CXER map */\n", tag2el_cxer_count);
vlm79b08d52004-07-01 00:52:50 +0000526 OUT("%d,\t/* Whether extensible */\n",
527 check_if_extensible(expr));
vlma5dcb912004-09-29 13:16:40 +0000528 OUT("(unsigned int *)asn_DEF_%s_mmap\t/* Mandatory elements map */\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000529 );
530 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000531
532 /*
vlma5dcb912004-09-29 13:16:40 +0000533 * Emit asn_DEF_xxx table.
vlm4e554992004-08-25 02:03:12 +0000534 */
vlm72425de2004-09-13 08:31:01 +0000535 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
vlm86f5ed22004-09-26 13:11:31 +0000536 ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000537
vlmfa67ddc2004-06-03 03:38:44 +0000538 REDIR(OT_TYPE_DECLS);
539
540 return 0;
vlmedf203f2005-01-17 11:57:48 +0000541} /* _SET_def() */
vlmfa67ddc2004-06-03 03:38:44 +0000542
543int
vlmdae7f9d2004-08-22 03:25:24 +0000544asn1c_lang_C_type_SEx_OF(arg_t *arg) {
vlmfa67ddc2004-06-03 03:38:44 +0000545 asn1p_expr_t *expr = arg->expr;
vlmdae7f9d2004-08-22 03:25:24 +0000546 asn1p_expr_t *memb;
vlmfa67ddc2004-06-03 03:38:44 +0000547
548 DEPENDENCIES;
549
550 if(arg->embed) {
vlmaf841972005-01-28 12:18:50 +0000551 OUT("struct "); out_identifiers_chain(arg, 1); OUT(" {\n");
vlmfa67ddc2004-06-03 03:38:44 +0000552 } else {
vlmdae7f9d2004-08-22 03:25:24 +0000553 OUT("typedef struct %s {\n", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000554 }
555
vlmdae7f9d2004-08-22 03:25:24 +0000556 memb = TQ_FIRST(&expr->members);
557
558 INDENT(+1);
559 OUT("A_%s_OF(",
560 (arg->expr->expr_type == ASN_CONSTR_SET_OF)
561 ? "SET" : "SEQUENCE");
vlm80a48592005-02-25 12:10:27 +0000562 if(memb->expr_type & ASN_CONSTR_MASK
563 || ((memb->expr_type == ASN_BASIC_ENUMERATED
564 || memb->expr_type == ASN_BASIC_INTEGER)
565 && expr_elements_count(arg, memb))) {
vlmdae7f9d2004-08-22 03:25:24 +0000566 arg_t tmp;
567 asn1p_expr_t tmp_memb;
568 arg->embed++;
569 tmp = *arg;
570 tmp.expr = &tmp_memb;
571 tmp_memb = *memb;
572 tmp_memb._anonymous_type = 1;
vlm39ba4c42004-09-22 16:06:28 +0000573 if(tmp_memb.Identifier == 0) {
574 tmp_memb.Identifier = strdup(
575 asn1c_make_identifier(0,
vlmbf3c5112005-02-14 20:41:29 +0000576 expr->Identifier, "Member", 0));
vlm39ba4c42004-09-22 16:06:28 +0000577 assert(tmp_memb.Identifier);
578 }
vlmdae7f9d2004-08-22 03:25:24 +0000579 tmp.default_cb(&tmp);
vlm39ba4c42004-09-22 16:06:28 +0000580 if(tmp_memb.Identifier != memb->Identifier)
581 free(tmp_memb.Identifier);
vlmdae7f9d2004-08-22 03:25:24 +0000582 arg->embed--;
583 assert(arg->target->target == OT_TYPE_DECLS);
584 } else {
vlmaf841972005-01-28 12:18:50 +0000585 OUT("%s", asn1c_type_name(arg, memb, TNF_CTYPE | TNF_CHECK));
vlmfa67ddc2004-06-03 03:38:44 +0000586 }
vlmdae7f9d2004-08-22 03:25:24 +0000587 OUT(") list;\n");
588 INDENT(-1);
vlmfa67ddc2004-06-03 03:38:44 +0000589
590 PCTX_DEF;
vlma02b74d2004-09-15 11:54:38 +0000591 OUT("} %s%s%s", expr->marker.flags?"*":"",
vlmdae7f9d2004-08-22 03:25:24 +0000592 expr->_anonymous_type ? "" : MKID(expr->Identifier),
593 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000594
595 /*
vlmdae7f9d2004-08-22 03:25:24 +0000596 * SET OF/SEQUENCE OF definition
vlmfa67ddc2004-06-03 03:38:44 +0000597 */
vlmdae7f9d2004-08-22 03:25:24 +0000598 return asn1c_lang_C_type_SEx_OF_def(arg,
599 (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF));
vlmfa67ddc2004-06-03 03:38:44 +0000600}
601
602static int
603asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
604 asn1p_expr_t *expr = arg->expr;
605 asn1p_expr_t *v;
vlm6e73a042004-08-11 07:17:22 +0000606 int tags_count;
vlm72425de2004-09-13 08:31:01 +0000607 int all_tags_count;
608 enum tvm_compat tv_mode;
vlmfa67ddc2004-06-03 03:38:44 +0000609 char *p;
610
vlm33a4ff12004-08-11 05:21:32 +0000611 /*
612 * Print out the table according to which the parsing is performed.
613 */
vlmfa67ddc2004-06-03 03:38:44 +0000614 if(seq_of) {
vlm33a4ff12004-08-11 05:21:32 +0000615 GEN_INCLUDE("constr_SEQUENCE_OF");
vlmfa67ddc2004-06-03 03:38:44 +0000616 } else {
vlm33a4ff12004-08-11 05:21:32 +0000617 GEN_INCLUDE("constr_SET_OF");
vlmfa67ddc2004-06-03 03:38:44 +0000618 }
vlm33a4ff12004-08-11 05:21:32 +0000619 if(!arg->embed)
vlma5dcb912004-09-29 13:16:40 +0000620 GEN_DECLARE(expr); /* asn_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000621
622 REDIR(OT_STAT_DEFS);
623
624 /*
625 * Print out the table according to which the parsing is performed.
626 */
627 p = MKID(expr->Identifier);
vlma5dcb912004-09-29 13:16:40 +0000628 OUT("static asn_TYPE_member_t asn_MBR_%s[] = {\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000629 INDENT(+1);
vlmfa67ddc2004-06-03 03:38:44 +0000630 v = TQ_FIRST(&(expr->members));
vlm39ba4c42004-09-22 16:06:28 +0000631 if(!v->Identifier) {
vlmbf3c5112005-02-14 20:41:29 +0000632 v->Identifier = strdup("Member");
vlm39ba4c42004-09-22 16:06:28 +0000633 assert(v->Identifier);
634 }
635 v->_anonymous_type = 1;
636 arg->embed++;
vlm4e554992004-08-25 02:03:12 +0000637 emit_member_table(arg, v);
vlm39ba4c42004-09-22 16:06:28 +0000638 arg->embed--;
639 INDENT(-1);
vlmfa67ddc2004-06-03 03:38:44 +0000640 OUT("};\n");
641
vlm4a3f5822004-06-28 21:13:46 +0000642 /*
vlma5dcb912004-09-29 13:16:40 +0000643 * Print out asn_DEF_<type>_[all_]tags[] vectors.
vlm4a3f5822004-06-28 21:13:46 +0000644 */
vlm72425de2004-09-13 08:31:01 +0000645 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
vlmfa67ddc2004-06-03 03:38:44 +0000646
vlmaf841972005-01-28 12:18:50 +0000647 OUT("static asn_SET_OF_specifics_t asn_DEF_%s_specs = {\n",
648 MKID_nr(expr->Identifier));
vlm4a3f5822004-06-28 21:13:46 +0000649 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000650 INDENTED(
651 OUT("sizeof(struct %s),\n", p);
vlma5dcb912004-09-29 13:16:40 +0000652 OUT("offsetof(struct %s, _asn_ctx),\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000653 if(expr_as_xmlvaluelist(arg, v))
654 OUT("1,\t/* XER encoding is XMLValueList */\n");
655 else
656 OUT("0,\t/* XER encoding is XMLDelimitedItemList */\n");
vlmfa67ddc2004-06-03 03:38:44 +0000657 );
658 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000659
660 /*
vlma5dcb912004-09-29 13:16:40 +0000661 * Emit asn_DEF_xxx table.
vlm4e554992004-08-25 02:03:12 +0000662 */
vlm72425de2004-09-13 08:31:01 +0000663 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, 1,
vlm86f5ed22004-09-26 13:11:31 +0000664 ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000665
vlmfa67ddc2004-06-03 03:38:44 +0000666 REDIR(OT_TYPE_DECLS);
667
668 return 0;
vlmedf203f2005-01-17 11:57:48 +0000669} /* _SEx_OF_def() */
vlmfa67ddc2004-06-03 03:38:44 +0000670
671int
672asn1c_lang_C_type_CHOICE(arg_t *arg) {
673 asn1p_expr_t *expr = arg->expr;
674 asn1p_expr_t *v;
vlmdae7f9d2004-08-22 03:25:24 +0000675 char *id;
vlmfa67ddc2004-06-03 03:38:44 +0000676
677 DEPENDENCIES;
678
vlm33a4ff12004-08-11 05:21:32 +0000679 REDIR(OT_DEPS);
680
vlmaf841972005-01-28 12:18:50 +0000681 OUT("typedef enum "); out_identifiers_chain(arg, 0); OUT("_PR {\n");
vlm33a4ff12004-08-11 05:21:32 +0000682 INDENTED(
vlmaf841972005-01-28 12:18:50 +0000683 out_identifiers_chain(arg, 0);
684 OUT("_PR_NOTHING,\t/* No components present */\n");
vlm33a4ff12004-08-11 05:21:32 +0000685 TQ_FOR(v, &(expr->members), next) {
686 if(v->expr_type == A1TC_EXTENSIBLE) {
687 OUT("/* Extensions may appear below */\n");
688 continue;
689 }
vlmaf841972005-01-28 12:18:50 +0000690 out_identifiers_chain(arg, 0);
691 OUT("_PR_");
692 id = MKID_nr(v->Identifier);
vlmdae7f9d2004-08-22 03:25:24 +0000693 OUT("%s,\n", id, id);
vlm33a4ff12004-08-11 05:21:32 +0000694 }
695 );
vlmaf841972005-01-28 12:18:50 +0000696 OUT("} "); out_identifiers_chain(arg, 0); OUT("_PR;\n");
vlm33a4ff12004-08-11 05:21:32 +0000697
698 REDIR(OT_TYPE_DECLS);
vlmfa67ddc2004-06-03 03:38:44 +0000699
700 if(arg->embed) {
vlmaf841972005-01-28 12:18:50 +0000701 OUT("struct "); out_identifiers_chain(arg, 1); OUT(" {\n");
vlmfa67ddc2004-06-03 03:38:44 +0000702 } else {
vlmaf841972005-01-28 12:18:50 +0000703 id = MKID(expr->Identifier);
vlmdae7f9d2004-08-22 03:25:24 +0000704 OUT("typedef struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000705 }
706
707 INDENTED(
vlmaf841972005-01-28 12:18:50 +0000708 out_identifiers_chain(arg, 0);
709 OUT("_PR present;\n");
710 OUT("union {\n");
vlmfa67ddc2004-06-03 03:38:44 +0000711 TQ_FOR(v, &(expr->members), next) {
vlmddd5a7d2004-09-10 09:18:20 +0000712 if(expr_better_indirect(arg, v))
vlma02b74d2004-09-15 11:54:38 +0000713 v->marker.flags |= EM_INDIRECT;
vlmfa67ddc2004-06-03 03:38:44 +0000714 EMBED(v);
715 }
716 if(UNNAMED_UNIONS) OUT("};\n");
717 else OUT("} choice;\n");
718 );
719
720 PCTX_DEF;
vlma02b74d2004-09-15 11:54:38 +0000721 OUT("} %s%s%s", expr->marker.flags?"*":"",
vlmdae7f9d2004-08-22 03:25:24 +0000722 expr->_anonymous_type ? "" : MKID(expr->Identifier),
723 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000724
725 return asn1c_lang_C_type_CHOICE_def(arg);
726}
727
728static int
729asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
730 asn1p_expr_t *expr = arg->expr;
731 asn1p_expr_t *v;
732 int elements; /* Number of elements */
vlmfa67ddc2004-06-03 03:38:44 +0000733 tag2el_t *tag2el = NULL;
734 int tag2el_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000735 int tags_count;
vlm72425de2004-09-13 08:31:01 +0000736 int all_tags_count;
737 enum tvm_compat tv_mode;
vlmfa67ddc2004-06-03 03:38:44 +0000738 char *p;
739
740 /*
741 * Fetch every inner tag from the tag to elements map.
742 */
vlm940bc6b2004-10-03 09:13:30 +0000743 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1, FTE_ALLTAGS)) {
vlmfa67ddc2004-06-03 03:38:44 +0000744 if(tag2el) free(tag2el);
745 return -1;
vlmfa67ddc2004-06-03 03:38:44 +0000746 }
747
vlm33a4ff12004-08-11 05:21:32 +0000748 GEN_INCLUDE("constr_CHOICE");
749 if(!arg->embed)
vlma5dcb912004-09-29 13:16:40 +0000750 GEN_DECLARE(expr); /* asn_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000751
vlm33a4ff12004-08-11 05:21:32 +0000752 REDIR(OT_STAT_DEFS);
vlmfa67ddc2004-06-03 03:38:44 +0000753
754 /*
755 * Print out the table according to which the parsing is performed.
756 */
vlm39ba4c42004-09-22 16:06:28 +0000757 if(expr_elements_count(arg, expr)) {
vlmfa67ddc2004-06-03 03:38:44 +0000758
vlm39ba4c42004-09-22 16:06:28 +0000759 p = MKID(expr->Identifier);
vlma5dcb912004-09-29 13:16:40 +0000760 OUT("static asn_TYPE_member_t asn_MBR_%s[] = {\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000761
762 elements = 0;
763 INDENTED(TQ_FOR(v, &(expr->members), next) {
vlm34dcd572005-01-17 11:40:49 +0000764 if(v->expr_type == A1TC_EXTENSIBLE)
765 continue;
766 if(expr_better_indirect(arg, v))
767 v->marker.flags |= EM_INDIRECT;
768 elements++;
769 emit_member_table(arg, v);
vlm39ba4c42004-09-22 16:06:28 +0000770 });
771 OUT("};\n");
772 } else {
773 elements = 0;
774 }
vlmfa67ddc2004-06-03 03:38:44 +0000775
vlm6e73a042004-08-11 07:17:22 +0000776
vlmfa67ddc2004-06-03 03:38:44 +0000777 if(arg->embed) {
778 /*
779 * Our parent structure has already taken this into account.
780 */
vlm72425de2004-09-13 08:31:01 +0000781 tv_mode = _TVM_SAME;
782 tags_count = all_tags_count = 0;
vlmfa67ddc2004-06-03 03:38:44 +0000783 } else {
vlm72425de2004-09-13 08:31:01 +0000784 tv_mode = emit_tags_vectors(arg, expr,
785 &tags_count, &all_tags_count);
vlmfa67ddc2004-06-03 03:38:44 +0000786 }
vlmfa67ddc2004-06-03 03:38:44 +0000787
788 /*
789 * Tags to elements map.
790 */
vlm940bc6b2004-10-03 09:13:30 +0000791 emit_tag2member_map(arg, tag2el, tag2el_count, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000792
vlmaf841972005-01-28 12:18:50 +0000793 OUT("static asn_CHOICE_specifics_t asn_DEF_%s_specs = {\n",
794 MKID_nr(expr->Identifier));
vlm6e73a042004-08-11 07:17:22 +0000795 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000796 INDENTED(
797 OUT("sizeof(struct %s),\n", p);
vlma5dcb912004-09-29 13:16:40 +0000798 OUT("offsetof(struct %s, _asn_ctx),\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000799 OUT("offsetof(struct %s, present),\n", p);
800 OUT("sizeof(((struct %s *)0)->present),\n", p);
vlmaf841972005-01-28 12:18:50 +0000801 OUT("asn_DEF_%s_tag2el,\n", MKID_nr(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000802 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
vlm79b08d52004-07-01 00:52:50 +0000803 OUT("%d\t/* Whether extensible */\n",
804 check_if_extensible(expr));
vlmfa67ddc2004-06-03 03:38:44 +0000805 );
806 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000807
808 /*
vlma5dcb912004-09-29 13:16:40 +0000809 * Emit asn_DEF_xxx table.
vlm4e554992004-08-25 02:03:12 +0000810 */
vlm72425de2004-09-13 08:31:01 +0000811 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
vlm86f5ed22004-09-26 13:11:31 +0000812 ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000813
vlmfa67ddc2004-06-03 03:38:44 +0000814 REDIR(OT_TYPE_DECLS);
815
816 return 0;
vlmedf203f2005-01-17 11:57:48 +0000817} /* _CHOICE_def() */
vlmfa67ddc2004-06-03 03:38:44 +0000818
819int
820asn1c_lang_C_type_REFERENCE(arg_t *arg) {
821 asn1p_ref_t *ref;
822
823 ref = arg->expr->reference;
824 if(ref->components[ref->comp_count-1].name[0] == '&') {
vlmfa67ddc2004-06-03 03:38:44 +0000825 asn1p_expr_t *extract;
826 arg_t tmp;
827 int ret;
828
vlm39ba4c42004-09-22 16:06:28 +0000829 extract = asn1f_class_access_ex(arg->asn, arg->expr->module,
vlmdae7f9d2004-08-22 03:25:24 +0000830 arg->expr, ref);
vlmfa67ddc2004-06-03 03:38:44 +0000831 if(extract == NULL)
832 return -1;
833
vlmdae7f9d2004-08-22 03:25:24 +0000834 extract = asn1p_expr_clone(extract, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000835 if(extract) {
836 if(extract->Identifier)
837 free(extract->Identifier);
838 extract->Identifier = strdup(arg->expr->Identifier);
839 if(extract->Identifier == NULL) {
840 asn1p_expr_free(extract);
841 return -1;
842 }
843 } else {
844 return -1;
845 }
846
847 tmp = *arg;
848 tmp.asn = arg->asn;
vlmdae7f9d2004-08-22 03:25:24 +0000849 tmp.mod = extract->module;
vlmfa67ddc2004-06-03 03:38:44 +0000850 tmp.expr = extract;
851
852 ret = arg->default_cb(&tmp);
853
854 asn1p_expr_free(extract);
855
856 return ret;
857 }
858
859
860 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
861}
862
863int
864asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
865 asn1p_expr_t *expr = arg->expr;
vlm6e73a042004-08-11 07:17:22 +0000866 int tags_count;
vlm72425de2004-09-13 08:31:01 +0000867 int all_tags_count;
868 enum tvm_compat tv_mode;
vlm80a48592005-02-25 12:10:27 +0000869 enum etd_spec etd_spec;
vlmfa67ddc2004-06-03 03:38:44 +0000870 char *p;
871
872 if(arg->embed) {
vlma5dcb912004-09-29 13:16:40 +0000873 enum tnfmt tnfmt = TNF_CTYPE;
874
875 /*
876 * If this is an optional compound type,
877 * refer it using "struct X" convention,
878 * as it may recursively include the current structure.
879 */
880 if(expr->marker.flags) {
881 asn1p_expr_t *terminal;
882 terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
883 if(terminal
884 && (terminal->expr_type & ASN_CONSTR_MASK)) {
885 REDIR(OT_DEPS);
886 tnfmt = TNF_RSAFE;
887 OUT("\n");
888 OUT("%s;\t/* Forward declaration */\n",
vlmaf841972005-01-28 12:18:50 +0000889 asn1c_type_name(arg, arg->expr, tnfmt | TNF_CHECK));
vlma5dcb912004-09-29 13:16:40 +0000890 }
891 }
892
vlmfa67ddc2004-06-03 03:38:44 +0000893 REDIR(OT_TYPE_DECLS);
894
vlm80a48592005-02-25 12:10:27 +0000895 OUT("%s", asn1c_type_name(arg, arg->expr, tnfmt | TNF_CHECK));
896 if(!expr->_anonymous_type) {
897 OUT("%s", expr->marker.flags?"\t*":"\t ");
898 OUT("%s", MKID(expr->Identifier));
899 if((expr->marker.flags & EM_DEFAULT) == EM_DEFAULT)
900 OUT("\t/* DEFAULT %s */",
901 asn1f_printable_value(
902 expr->marker.default_value));
903 else if((expr->marker.flags & EM_OPTIONAL) == EM_OPTIONAL)
904 OUT("\t/* OPTIONAL */");
905 }
906
907 } else {
908 GEN_INCLUDE(asn1c_type_name(arg, expr, TNF_INCLUDE));
vlmb2839012004-08-20 13:37:01 +0000909
910 REDIR(OT_TYPE_DECLS);
vlm80a48592005-02-25 12:10:27 +0000911
912 OUT("typedef %s\t",
913 asn1c_type_name(arg, arg->expr, TNF_CTYPE | TNF_CHECK));
914 OUT("%s%s_t",
915 expr->marker.flags?"*":" ",
916 MKID(expr->Identifier));
917 OUT_DEBUG("\t/* %s:%d */", __FILE__, __LINE__);
vlmfa67ddc2004-06-03 03:38:44 +0000918 }
919
vlm80a48592005-02-25 12:10:27 +0000920 if((expr->expr_type == ASN_BASIC_ENUMERATED)
921 || (expr->expr_type == ASN_BASIC_INTEGER
922 && expr_elements_count(arg, expr)))
923 etd_spec = ETD_HAS_SPECIFICS;
924 else
925 etd_spec = ETD_NO_SPECIFICS;
vlmfa67ddc2004-06-03 03:38:44 +0000926
vlm86f5ed22004-09-26 13:11:31 +0000927 /*
928 * If this type just blindly refers the other type, alias it.
929 * Type1 ::= Type2
930 */
vlm80a48592005-02-25 12:10:27 +0000931 if(arg->embed && etd_spec == ETD_NO_SPECIFICS) {
932 REDIR(OT_TYPE_DECLS);
933 return 0;
934 }
vlm86f5ed22004-09-26 13:11:31 +0000935 if((!expr->constraints || (arg->flags & A1C_NO_CONSTRAINTS))
vlm80a48592005-02-25 12:10:27 +0000936 && (arg->embed || expr->tag.tag_class == TC_NOCLASS)
937 && etd_spec == ETD_NO_SPECIFICS) {
vlm86f5ed22004-09-26 13:11:31 +0000938 char *type_name;
939 REDIR(OT_FUNC_DECLS);
940 type_name = asn1c_type_name(arg, expr, TNF_SAFE);
941 OUT("/* This type is equivalent to %s */\n", type_name);
vlm86f5ed22004-09-26 13:11:31 +0000942 if(HIDE_INNER_DEFS) OUT("/* ");
vlmaf841972005-01-28 12:18:50 +0000943 OUT("#define\tasn_DEF_%s\t", MKID_nr(expr->Identifier));
vlm86f5ed22004-09-26 13:11:31 +0000944 type_name = asn1c_type_name(arg, expr, TNF_SAFE);
vlm80a48592005-02-25 12:10:27 +0000945 OUT("asn_DEF_%s", type_name);
vlm86f5ed22004-09-26 13:11:31 +0000946 if(HIDE_INNER_DEFS)
vlm80a48592005-02-25 12:10:27 +0000947 OUT("\t// (Use -fall-defs-global to expose) */");
948 OUT("\n");
vlm86f5ed22004-09-26 13:11:31 +0000949 REDIR(OT_CODE);
950 OUT("/* This type is equivalent to %s */\n", type_name);
951 OUT("\n");
952 REDIR(OT_TYPE_DECLS);
953 return 0;
954 }
955
vlmfa67ddc2004-06-03 03:38:44 +0000956 REDIR(OT_STAT_DEFS);
957
vlm4a3f5822004-06-28 21:13:46 +0000958 /*
vlma5dcb912004-09-29 13:16:40 +0000959 * Print out asn_DEF_<type>_[all_]tags[] vectors.
vlm4a3f5822004-06-28 21:13:46 +0000960 */
vlm72425de2004-09-13 08:31:01 +0000961 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
vlmfa67ddc2004-06-03 03:38:44 +0000962
vlm80a48592005-02-25 12:10:27 +0000963 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count,
964 0, etd_spec);
vlmfa67ddc2004-06-03 03:38:44 +0000965
vlmb2839012004-08-20 13:37:01 +0000966 REDIR(OT_CODE);
967
vlmfa67ddc2004-06-03 03:38:44 +0000968 /*
969 * Constraint checking.
970 */
vlm86f5ed22004-09-26 13:11:31 +0000971 if(!(arg->flags & A1C_NO_CONSTRAINTS)) {
972 p = MKID(expr->Identifier);
vlm80a48592005-02-25 12:10:27 +0000973 if(HIDE_INNER_DEFS) OUT("static ");
vlm86f5ed22004-09-26 13:11:31 +0000974 OUT("int\n");
975 OUT("%s_constraint("
vlma5dcb912004-09-29 13:16:40 +0000976 "asn_TYPE_descriptor_t *td, const void *sptr,\n", p);
vlm86f5ed22004-09-26 13:11:31 +0000977 INDENT(+1);
978 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {");
979 OUT("\n");
980 if(asn1c_emit_constraint_checking_code(arg) == 1) {
981 OUT("/* Replace with underlying type checker */\n");
982 OUT("td->check_constraints "
vlma5dcb912004-09-29 13:16:40 +0000983 "= asn_DEF_%s.check_constraints;\n",
vlm86f5ed22004-09-26 13:11:31 +0000984 asn1c_type_name(arg, expr, TNF_SAFE));
985 OUT("return td->check_constraints"
986 "(td, sptr, app_errlog, app_key);\n");
vlm1d036692004-08-19 13:29:46 +0000987 }
vlm86f5ed22004-09-26 13:11:31 +0000988 INDENT(-1);
989 OUT("}\n");
990 OUT("\n");
vlmfa67ddc2004-06-03 03:38:44 +0000991 }
vlmfa67ddc2004-06-03 03:38:44 +0000992
993 /*
994 * Emit suicidal functions.
995 */
996
vlmfa67ddc2004-06-03 03:38:44 +0000997 /*
998 * This function replaces certain fields from the definition
999 * of a type with the corresponding fields from the basic type
1000 * (from which the current type is inherited).
1001 */
vlmfa67ddc2004-06-03 03:38:44 +00001002 OUT("/*\n");
vlmb2839012004-08-20 13:37:01 +00001003 OUT(" * This type is implemented using %s,\n",
1004 asn1c_type_name(arg, expr, TNF_SAFE));
vlmdcd32fe2004-09-23 22:20:47 +00001005 OUT(" * so here we adjust the DEF accordingly.\n");
vlmfa67ddc2004-06-03 03:38:44 +00001006 OUT(" */\n");
1007 OUT("static void\n");
vlmb2839012004-08-20 13:37:01 +00001008 p = MKID(expr->Identifier);
vlma5dcb912004-09-29 13:16:40 +00001009 OUT("%s_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +00001010 INDENT(+1);
vlm80a48592005-02-25 12:10:27 +00001011 {
vlm39ba4c42004-09-22 16:06:28 +00001012 asn1p_expr_t *terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
vlmb2839012004-08-20 13:37:01 +00001013 char *type_name = asn1c_type_name(arg, expr, TNF_SAFE);
vlma5dcb912004-09-29 13:16:40 +00001014 OUT("td->free_struct = asn_DEF_%s.free_struct;\n", type_name);
1015 OUT("td->print_struct = asn_DEF_%s.print_struct;\n", type_name);
1016 OUT("td->ber_decoder = asn_DEF_%s.ber_decoder;\n", type_name);
1017 OUT("td->der_encoder = asn_DEF_%s.der_encoder;\n", type_name);
1018 OUT("td->xer_decoder = asn_DEF_%s.xer_decoder;\n", type_name);
1019 OUT("td->xer_encoder = asn_DEF_%s.xer_encoder;\n", type_name);
vlm1308d2b2004-09-10 15:49:15 +00001020 if(!terminal && !tags_count) {
vlm72425de2004-09-13 08:31:01 +00001021 OUT("/* The next four lines are here because of -fknown-extern-type */\n");
vlma5dcb912004-09-29 13:16:40 +00001022 OUT("td->tags = asn_DEF_%s.tags;\n", type_name);
1023 OUT("td->tags_count = asn_DEF_%s.tags_count;\n", type_name);
1024 OUT("td->all_tags = asn_DEF_%s.all_tags;\n", type_name);
1025 OUT("td->all_tags_count = asn_DEF_%s.all_tags_count;\n",type_name);
vlm1308d2b2004-09-10 15:49:15 +00001026 OUT("/* End of these lines */\n");
1027 }
vlma5dcb912004-09-29 13:16:40 +00001028 OUT("td->elements = asn_DEF_%s.elements;\n", type_name);
1029 OUT("td->elements_count = asn_DEF_%s.elements_count;\n", type_name);
vlm80a48592005-02-25 12:10:27 +00001030 if(etd_spec != ETD_NO_SPECIFICS) {
1031 INDENT(-1);
1032 OUT(" /* ");
vlmb2839012004-08-20 13:37:01 +00001033 }
vlm80a48592005-02-25 12:10:27 +00001034 OUT("td->specifics = asn_DEF_%s.specifics;", type_name);
1035 if(etd_spec == ETD_NO_SPECIFICS) {
1036 INDENT(-1);
1037 OUT("\n");
1038 } else {
1039 OUT("\t// Defined explicitly */\n");
1040 }
1041 }
vlmfa67ddc2004-06-03 03:38:44 +00001042 OUT("}\n");
1043 OUT("\n");
vlmfa67ddc2004-06-03 03:38:44 +00001044
1045 p = MKID(expr->Identifier);
vlm80a48592005-02-25 12:10:27 +00001046 if(HIDE_INNER_DEFS) OUT("static ");
vlm39ba4c42004-09-22 16:06:28 +00001047 OUT("void\n");
vlma5dcb912004-09-29 13:16:40 +00001048 OUT("%s_free(asn_TYPE_descriptor_t *td,\n", p);
vlmfa67ddc2004-06-03 03:38:44 +00001049 INDENTED(
vlm39ba4c42004-09-22 16:06:28 +00001050 OUT("\tvoid *struct_ptr, int contents_only) {\n");
vlmb2839012004-08-20 13:37:01 +00001051 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlm39ba4c42004-09-22 16:06:28 +00001052 OUT("td->free_struct(td, struct_ptr, contents_only);\n");
vlmfa67ddc2004-06-03 03:38:44 +00001053 );
1054 OUT("}\n");
1055 OUT("\n");
1056
1057 p = MKID(expr->Identifier);
vlm80a48592005-02-25 12:10:27 +00001058 if(HIDE_INNER_DEFS) OUT("static ");
vlmfa67ddc2004-06-03 03:38:44 +00001059 OUT("int\n");
vlma5dcb912004-09-29 13:16:40 +00001060 OUT("%s_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,\n", p);
vlmfa67ddc2004-06-03 03:38:44 +00001061 INDENTED(
1062 OUT("\tint ilevel, asn_app_consume_bytes_f *cb, void *app_key) {\n");
vlmb2839012004-08-20 13:37:01 +00001063 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlmfa67ddc2004-06-03 03:38:44 +00001064 OUT("return td->print_struct(td, struct_ptr, ilevel, cb, app_key);\n");
1065 );
1066 OUT("}\n");
1067 OUT("\n");
1068
1069 p = MKID(expr->Identifier);
vlm80a48592005-02-25 12:10:27 +00001070 if(HIDE_INNER_DEFS) OUT("static ");
vlm9de248e2004-10-20 15:50:55 +00001071 OUT("asn_dec_rval_t\n");
vlma5dcb912004-09-29 13:16:40 +00001072 OUT("%s_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n", p);
vlmfa67ddc2004-06-03 03:38:44 +00001073 INDENTED(
vlm39ba4c42004-09-22 16:06:28 +00001074 OUT("\tvoid **structure, void *bufptr, size_t size, int tag_mode) {\n");
vlmb2839012004-08-20 13:37:01 +00001075 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlma5dcb912004-09-29 13:16:40 +00001076 OUT("return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);\n");
vlm39ba4c42004-09-22 16:06:28 +00001077 );
1078 OUT("}\n");
1079 OUT("\n");
1080
1081 p = MKID(expr->Identifier);
vlm80a48592005-02-25 12:10:27 +00001082 if(HIDE_INNER_DEFS) OUT("static ");
vlm39ba4c42004-09-22 16:06:28 +00001083 OUT("asn_enc_rval_t\n");
vlma5dcb912004-09-29 13:16:40 +00001084 OUT("%s_encode_der(asn_TYPE_descriptor_t *td,\n", p);
vlm39ba4c42004-09-22 16:06:28 +00001085 INDENTED(
1086 OUT("\tvoid *structure, int tag_mode, ber_tlv_tag_t tag,\n");
1087 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
1088 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
1089 OUT("return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);\n");
1090 );
1091 OUT("}\n");
1092 OUT("\n");
1093
1094 p = MKID(expr->Identifier);
vlm80a48592005-02-25 12:10:27 +00001095 if(HIDE_INNER_DEFS) OUT("static ");
vlme03646b2004-10-23 13:34:00 +00001096 OUT("asn_dec_rval_t\n");
1097 OUT("%s_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n", p);
1098 INDENTED(
1099 OUT("\tvoid **structure, const char *opt_mname, void *bufptr, size_t size) {\n");
1100 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
1101 OUT("return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size);\n");
1102 );
1103 OUT("}\n");
1104 OUT("\n");
1105
1106 p = MKID(expr->Identifier);
vlm80a48592005-02-25 12:10:27 +00001107 if(HIDE_INNER_DEFS) OUT("static ");
vlm39ba4c42004-09-22 16:06:28 +00001108 OUT("asn_enc_rval_t\n");
vlma5dcb912004-09-29 13:16:40 +00001109 OUT("%s_encode_xer(asn_TYPE_descriptor_t *td, void *structure,\n", p);
vlm39ba4c42004-09-22 16:06:28 +00001110 INDENTED(
1111 OUT("\tint ilevel, enum xer_encoder_flags_e flags,\n");
1112 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
1113 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
1114 OUT("return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);\n");
vlmfa67ddc2004-06-03 03:38:44 +00001115 );
1116 OUT("}\n");
1117 OUT("\n");
1118
1119 REDIR(OT_FUNC_DECLS);
1120
vlmaf841972005-01-28 12:18:50 +00001121 p = MKID_nr(expr->Identifier);
vlm80a48592005-02-25 12:10:27 +00001122 if(HIDE_INNER_DEFS) {
1123 OUT("/* extern asn_TYPE_descriptor_t asn_DEF_%s;"
1124 "\t// (Use -fall-defs-global to expose) */\n", p);
1125 } else {
1126 OUT("extern asn_TYPE_descriptor_t asn_DEF_%s;\n", p);
1127 OUT("asn_struct_free_f %s_free;\n", p);
1128 OUT("asn_struct_print_f %s_print;\n", p);
1129 OUT("asn_constr_check_f %s_constraint;\n", p);
1130 OUT("ber_type_decoder_f %s_decode_ber;\n", p);
1131 OUT("der_type_encoder_f %s_encode_der;\n", p);
1132 OUT("xer_type_decoder_f %s_decode_xer;\n", p);
1133 OUT("xer_type_encoder_f %s_encode_xer;\n", p);
1134 }
vlmfa67ddc2004-06-03 03:38:44 +00001135
vlm33a4ff12004-08-11 05:21:32 +00001136 REDIR(OT_TYPE_DECLS);
1137
vlmfa67ddc2004-06-03 03:38:44 +00001138 return 0;
1139}
1140
1141int
1142asn1c_lang_C_type_EXTENSIBLE(arg_t *arg) {
1143
1144 OUT("/*\n");
1145 OUT(" * This type is extensible,\n");
1146 OUT(" * possible extensions are below.\n");
1147 OUT(" */\n");
1148
1149 return 0;
1150}
1151
vlm79b08d52004-07-01 00:52:50 +00001152static int check_if_extensible(asn1p_expr_t *expr) {
1153 asn1p_expr_t *v;
1154 TQ_FOR(v, &(expr->members), next) {
1155 if(v->expr_type == A1TC_EXTENSIBLE) return 1;
1156 }
1157 return 0;
1158}
1159
vlmfa67ddc2004-06-03 03:38:44 +00001160static int
vlma8a86cc2004-09-10 06:07:18 +00001161_print_tag(arg_t *arg, struct asn1p_type_tag_s *tag) {
vlmfa67ddc2004-06-03 03:38:44 +00001162
1163 OUT("(");
vlma8a86cc2004-09-10 06:07:18 +00001164 switch(tag->tag_class) {
vlmfa67ddc2004-06-03 03:38:44 +00001165 case TC_UNIVERSAL: OUT("ASN_TAG_CLASS_UNIVERSAL"); break;
1166 case TC_APPLICATION: OUT("ASN_TAG_CLASS_APPLICATION"); break;
1167 case TC_CONTEXT_SPECIFIC: OUT("ASN_TAG_CLASS_CONTEXT"); break;
1168 case TC_PRIVATE: OUT("ASN_TAG_CLASS_PRIVATE"); break;
1169 case TC_NOCLASS:
1170 break;
1171 }
vlm47ae1582004-09-24 21:01:43 +00001172 OUT(" | (%" PRIdASN " << 2))", tag->tag_value);
vlmfa67ddc2004-06-03 03:38:44 +00001173
1174 return 0;
1175}
1176
vlm4e03ce22004-06-06 07:20:17 +00001177
1178static int
1179_tag2el_cmp(const void *ap, const void *bp) {
1180 const tag2el_t *a = ap;
1181 const tag2el_t *b = bp;
1182 const struct asn1p_type_tag_s *ta = &a->el_tag;
1183 const struct asn1p_type_tag_s *tb = &b->el_tag;
1184
1185 if(ta->tag_class == tb->tag_class) {
1186 if(ta->tag_value == tb->tag_value) {
1187 /*
1188 * Sort by their respective positions.
1189 */
1190 if(a->el_no < b->el_no)
1191 return -1;
1192 else if(a->el_no > b->el_no)
1193 return 1;
1194 return 0;
1195 } else if(ta->tag_value < tb->tag_value)
1196 return -1;
1197 else
1198 return 1;
1199 } else if(ta->tag_class < tb->tag_class) {
1200 return -1;
1201 } else {
1202 return 1;
1203 }
1204}
1205
vlmfa67ddc2004-06-03 03:38:44 +00001206/*
1207 * For constructed types, number of external tags may be greater than
1208 * number of elements in the type because of CHOICE type.
1209 * T ::= SET { -- Three possible tags:
1210 * a INTEGER, -- One tag is here...
1211 * b Choice1 -- ... and two more tags are there.
1212 * }
1213 * Choice1 ::= CHOICE {
1214 * s1 IA5String,
1215 * s2 ObjectDescriptor
1216 * }
1217 */
1218static int
vlm940bc6b2004-10-03 09:13:30 +00001219_fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
vlmfa67ddc2004-06-03 03:38:44 +00001220 asn1p_expr_t *expr = arg->expr;
1221 arg_t tmparg = *arg;
1222 asn1p_expr_t *v;
1223 int element = 0;
vlm940bc6b2004-10-03 09:13:30 +00001224 int original_count = *count;
1225 int sort_until = -1;
vlmfa67ddc2004-06-03 03:38:44 +00001226
1227 TQ_FOR(v, &(expr->members), next) {
vlm940bc6b2004-10-03 09:13:30 +00001228 if(v->expr_type == A1TC_EXTENSIBLE) {
1229 /*
vlm80a48592005-02-25 12:10:27 +00001230 * CXER mandates sorting
vlm940bc6b2004-10-03 09:13:30 +00001231 * only for the root part.
1232 */
1233 if(flags == FTE_CANONICAL_XER
1234 && sort_until == -1)
1235 sort_until = *count;
vlmfa67ddc2004-06-03 03:38:44 +00001236 continue;
vlm940bc6b2004-10-03 09:13:30 +00001237 }
vlmfa67ddc2004-06-03 03:38:44 +00001238
1239 tmparg.expr = v;
1240
1241 if(_add_tag2el_member(&tmparg, tag2el, count,
vlm940bc6b2004-10-03 09:13:30 +00001242 (el_no==-1)?element:el_no, flags)) {
vlmfa67ddc2004-06-03 03:38:44 +00001243 return -1;
1244 }
1245
1246 element++;
1247 }
1248
vlm940bc6b2004-10-03 09:13:30 +00001249
1250 if(flags == FTE_CANONICAL_XER) {
1251 if(sort_until == -1) sort_until = *count;
1252 qsort((*tag2el) + original_count,
1253 sort_until - original_count,
1254 sizeof(**tag2el), _tag2el_cmp);
1255 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1256 && (sort_until - original_count) >= 1) {
1257 /* Only take in account the root component */
1258 *count = original_count + 1;
1259 }
1260 } else {
1261 /*
1262 * Sort the map according to canonical order of their
1263 * tags and element numbers.
1264 */
1265 qsort(*tag2el, *count, sizeof(**tag2el), _tag2el_cmp);
1266 }
vlm4e03ce22004-06-06 07:20:17 +00001267
vlmc8aeab42004-06-14 13:09:45 +00001268 /*
1269 * Initialize .toff_{first|last} members.
1270 */
1271 if(*count) {
1272 struct asn1p_type_tag_s *cur_tag = 0;
1273 tag2el_t *cur = *tag2el;
1274 tag2el_t *end = cur + *count;
1275 int occur, i;
1276 for(occur = 0; cur < end; cur++) {
1277 if(cur_tag == 0
1278 || cur_tag->tag_value != cur->el_tag.tag_value
1279 || cur_tag->tag_class != cur->el_tag.tag_class) {
1280 cur_tag = &cur->el_tag;
1281 occur = 0;
1282 } else {
1283 occur++;
1284 }
1285 cur->toff_first = -occur;
1286 for(i = 0; i >= -occur; i--)
1287 cur[i].toff_last = -i;
1288 }
1289 }
1290
vlmfa67ddc2004-06-03 03:38:44 +00001291 return 0;
1292}
1293
1294static int
vlm940bc6b2004-10-03 09:13:30 +00001295_add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e flags) {
vlmfa67ddc2004-06-03 03:38:44 +00001296 struct asn1p_type_tag_s tag;
1297 int ret;
1298
1299 assert(el_no >= 0);
1300
vlm39ba4c42004-09-22 16:06:28 +00001301 ret = asn1f_fetch_outmost_tag(arg->asn, arg->expr->module,
1302 arg->expr, &tag, 1);
vlmfa67ddc2004-06-03 03:38:44 +00001303 if(ret == 0) {
vlme2070ea2004-09-04 04:42:29 +00001304 tag2el_t *te;
1305 int new_count = (*count) + 1;
vlmfa67ddc2004-06-03 03:38:44 +00001306 void *p;
vlme2070ea2004-09-04 04:42:29 +00001307
vlm2de0e792004-09-05 10:42:33 +00001308 if(tag.tag_value == -1) {
1309 /*
1310 * This is an untagged ANY type,
1311 * proceed without adding a tag
1312 */
1313 return 0;
1314 }
1315
vlme2070ea2004-09-04 04:42:29 +00001316 p = realloc(*tag2el, new_count * sizeof(tag2el_t));
vlmfa67ddc2004-06-03 03:38:44 +00001317 if(p) *tag2el = p;
1318 else return -1;
1319
1320 DEBUG("Found tag for %s: %ld",
1321 arg->expr->Identifier,
1322 (long)tag.tag_value);
1323
vlme2070ea2004-09-04 04:42:29 +00001324 te = &((*tag2el)[*count]);
1325 te->el_tag = tag;
1326 te->el_no = el_no;
1327 te->from_expr = arg->expr;
1328 *count = new_count;
vlmfa67ddc2004-06-03 03:38:44 +00001329 return 0;
1330 }
1331
1332 DEBUG("Searching tag in complex expression %s:%x at line %d",
1333 arg->expr->Identifier,
1334 arg->expr->expr_type,
1335 arg->expr->_lineno);
1336
1337 /*
1338 * Iterate over members of CHOICE type.
1339 */
1340 if(arg->expr->expr_type == ASN_CONSTR_CHOICE) {
vlm940bc6b2004-10-03 09:13:30 +00001341 return _fill_tag2el_map(arg, tag2el, count, el_no, flags);
vlmfa67ddc2004-06-03 03:38:44 +00001342 }
1343
1344 if(arg->expr->expr_type == A1TC_REFERENCE) {
1345 arg_t tmp = *arg;
1346 asn1p_expr_t *expr;
vlmdae7f9d2004-08-22 03:25:24 +00001347 expr = asn1f_lookup_symbol_ex(tmp.asn, tmp.mod, tmp.expr,
vlmfa67ddc2004-06-03 03:38:44 +00001348 arg->expr->reference);
1349 if(expr) {
vlmdae7f9d2004-08-22 03:25:24 +00001350 tmp.mod = expr->module;
vlmfa67ddc2004-06-03 03:38:44 +00001351 tmp.expr = expr;
vlm940bc6b2004-10-03 09:13:30 +00001352 return _add_tag2el_member(&tmp, tag2el, count, el_no, flags);
vlmfa67ddc2004-06-03 03:38:44 +00001353 } else {
1354 FATAL("Cannot dereference %s at line %d",
1355 arg->expr->Identifier,
1356 arg->expr->_lineno);
1357 return -1;
1358 }
1359 }
1360
1361 DEBUG("No tag for %s at line %d",
1362 arg->expr->Identifier,
1363 arg->expr->_lineno);
1364
1365 return -1;
1366}
1367
1368static int
vlm940bc6b2004-10-03 09:13:30 +00001369emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier) {
vlm4e03ce22004-06-06 07:20:17 +00001370 asn1p_expr_t *expr = arg->expr;
1371
vlm940bc6b2004-10-03 09:13:30 +00001372 OUT("static asn_TYPE_tag2member_t asn_DEF_%s_tag2el%s[] = {\n",
vlmaf841972005-01-28 12:18:50 +00001373 MKID_nr(expr->Identifier), opt_modifier?opt_modifier:"");
vlm4e03ce22004-06-06 07:20:17 +00001374 if(tag2el_count) {
1375 int i;
1376 for(i = 0; i < tag2el_count; i++) {
1377 OUT(" { ");
vlma8a86cc2004-09-10 06:07:18 +00001378 _print_tag(arg, &tag2el[i].el_tag);
vlm4e03ce22004-06-06 07:20:17 +00001379 OUT(", ");
vlmc8aeab42004-06-14 13:09:45 +00001380 OUT("%d, ", tag2el[i].el_no);
1381 OUT("%d, ", tag2el[i].toff_first);
1382 OUT("%d ", tag2el[i].toff_last);
vlm80a48592005-02-25 12:10:27 +00001383 OUT("}%s /* %s at %d */\n",
1384 (i + 1 < tag2el_count) ? "," : "",
vlm4e03ce22004-06-06 07:20:17 +00001385 tag2el[i].from_expr->Identifier,
1386 tag2el[i].from_expr->_lineno
1387 );
1388 }
1389 }
1390 OUT("};\n");
1391
1392 return 0;;
1393}
1394
vlm72425de2004-09-13 08:31:01 +00001395static enum tvm_compat
1396emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tags_count_r, int *all_tags_count_r) {
1397 struct asn1p_type_tag_s *tags = 0; /* Effective tags */
1398 struct asn1p_type_tag_s *all_tags = 0; /* The full array */
vlm6e73a042004-08-11 07:17:22 +00001399 int tags_count = 0;
vlm72425de2004-09-13 08:31:01 +00001400 int all_tags_count = 0;
1401 enum tvm_compat tv_mode = _TVM_SAME;
vlm1308d2b2004-09-10 15:49:15 +00001402 int i;
vlm4a3f5822004-06-28 21:13:46 +00001403
vlmc6de2c42004-09-14 14:10:10 +00001404 /* Cleanup before proceeding. */
1405 *tags_count_r = 0;
1406 *all_tags_count_r = 0;
1407
vlm1308d2b2004-09-10 15:49:15 +00001408 /* Fetch a chain of tags */
vlm39ba4c42004-09-22 16:06:28 +00001409 tags_count = asn1f_fetch_tags(arg->asn, expr->module, expr, &tags, 0);
vlmc6de2c42004-09-14 14:10:10 +00001410 if(tags_count < 0)
1411 return -1;
vlm6e73a042004-08-11 07:17:22 +00001412
vlm72425de2004-09-13 08:31:01 +00001413 /* Fetch a chain of tags */
vlm39ba4c42004-09-22 16:06:28 +00001414 all_tags_count = asn1f_fetch_tags(arg->asn, expr->module, expr,
vlm72425de2004-09-13 08:31:01 +00001415 &all_tags, AFT_FULL_COLLECT);
1416 if(all_tags_count < 0) {
1417 if(tags) free(tags);
1418 return -1;
vlmfb41dbb2004-09-08 00:28:57 +00001419 }
vlm1308d2b2004-09-10 15:49:15 +00001420
vlm72425de2004-09-13 08:31:01 +00001421 assert(tags_count <= all_tags_count);
1422 assert((tags_count?0:1) == (all_tags_count?0:1));
vlm4a3f5822004-06-28 21:13:46 +00001423
vlm72425de2004-09-13 08:31:01 +00001424 if(tags_count <= all_tags_count) {
1425 for(i = 0; i < tags_count; i++) {
1426 if(tags[i].tag_value != all_tags[i].tag_value
1427 || tags[i].tag_class != all_tags[i].tag_class) {
1428 tv_mode = _TVM_DIFFERENT;
1429 break;
1430 }
1431 }
1432 if(i == tags_count && tags_count < all_tags_count)
1433 tv_mode = _TVM_SUBSET;
1434 } else {
1435 tv_mode = _TVM_DIFFERENT;
1436 }
1437
1438#define EMIT_TAGS_TABLE(name, tags, tags_count) do { \
vlma5dcb912004-09-29 13:16:40 +00001439 OUT("static ber_tlv_tag_t asn_DEF_%s%s_tags[] = {\n", \
vlmaf841972005-01-28 12:18:50 +00001440 MKID_nr(expr->Identifier), name); \
vlm72425de2004-09-13 08:31:01 +00001441 INDENT(+1); \
1442 /* Print the array of collected tags */ \
1443 for(i = 0; i < tags_count; i++) { \
1444 if(i) OUT(",\n"); \
1445 _print_tag(arg, &tags[i]); \
1446 } \
1447 OUT("\n"); \
1448 INDENT(-1); \
1449 OUT("};\n"); \
1450 } while(0)
1451
1452 if(tags_count) {
1453 if(tv_mode == _TVM_SUBSET)
1454 EMIT_TAGS_TABLE("", all_tags, all_tags_count);
1455 else
1456 EMIT_TAGS_TABLE("", tags, tags_count);
1457 }
1458
1459 if(all_tags_count) {
1460 if(tv_mode == _TVM_DIFFERENT)
1461 EMIT_TAGS_TABLE("_all", all_tags, all_tags_count);
1462 }
1463
1464 if(tags) free(tags);
1465 if(all_tags) free(all_tags);
1466
1467 *tags_count_r = tags_count;
1468 *all_tags_count_r = all_tags_count;
1469
1470 return tv_mode;
vlm4a3f5822004-06-28 21:13:46 +00001471}
vlmb2839012004-08-20 13:37:01 +00001472
1473static int
vlm4e554992004-08-25 02:03:12 +00001474expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
vlmb2839012004-08-20 13:37:01 +00001475 asn1p_expr_t *topmost_parent;
1476 asn1p_expr_t *v;
1477 int elements = 0;
1478
vlm39ba4c42004-09-22 16:06:28 +00001479 topmost_parent = asn1f_find_terminal_type_ex(arg->asn, expr);
vlmb2839012004-08-20 13:37:01 +00001480 if(!topmost_parent) return 0;
1481
vlm80a48592005-02-25 12:10:27 +00001482 if(!(topmost_parent->expr_type & ASN_CONSTR_MASK)
1483 && !topmost_parent->expr_type == ASN_BASIC_INTEGER
1484 && !topmost_parent->expr_type == ASN_BASIC_ENUMERATED)
vlmb2839012004-08-20 13:37:01 +00001485 return 0;
1486
1487 TQ_FOR(v, &(topmost_parent->members), next) {
1488 if(v->expr_type != A1TC_EXTENSIBLE)
1489 elements++;
1490 }
1491
1492 return elements;
1493}
1494
1495static int
vlm4e554992004-08-25 02:03:12 +00001496emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
vlmdae7f9d2004-08-22 03:25:24 +00001497 static int global_memb_unique;
vlmb2839012004-08-20 13:37:01 +00001498 int save_target;
1499 arg_t tmp_arg;
vlm060fe2a2004-09-10 09:37:12 +00001500 struct asn1p_type_tag_s outmost_tag_s;
1501 struct asn1p_type_tag_s *outmost_tag;
vlm80a48592005-02-25 12:10:27 +00001502 int complex_contents;
vlmb2839012004-08-20 13:37:01 +00001503 char *p;
1504
vlm060fe2a2004-09-10 09:37:12 +00001505 if(asn1f_fetch_outmost_tag(arg->asn,
1506 expr->module, expr, &outmost_tag_s, 1)) {
1507 outmost_tag = 0;
1508 } else {
1509 outmost_tag = &outmost_tag_s;
1510 }
1511
vlmb2839012004-08-20 13:37:01 +00001512 OUT("{ ");
vlm060fe2a2004-09-10 09:37:12 +00001513
1514 if(outmost_tag && outmost_tag->tag_value == -1)
1515 OUT("ATF_OPEN_TYPE | ");
vlma02b74d2004-09-15 11:54:38 +00001516 OUT("%s, ", expr->marker.flags?"ATF_POINTER":"ATF_NOFLAGS");
1517 if((expr->marker.flags & EM_OPTIONAL) == EM_OPTIONAL) {
vlmb2839012004-08-20 13:37:01 +00001518 asn1p_expr_t *tv;
1519 int opts = 0;
vlma02b74d2004-09-15 11:54:38 +00001520 for(tv = expr; tv && tv->marker.flags;
vlmb2839012004-08-20 13:37:01 +00001521 tv = TQ_NEXT(tv, next), opts++) {
1522 if(tv->expr_type == A1TC_EXTENSIBLE)
1523 opts--;
1524 }
1525 OUT("%d, ", opts);
1526 } else {
1527 OUT("0, ");
1528 }
vlm39ba4c42004-09-22 16:06:28 +00001529 if(expr->_anonymous_type) {
1530 assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
1531 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
1532 OUT("0,\n");
1533 } else {
vlmb2839012004-08-20 13:37:01 +00001534 OUT("offsetof(struct %s, ", MKID(arg->expr->Identifier));
1535 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1536 && (!UNNAMED_UNIONS)) OUT("choice.");
1537 OUT("%s),\n", MKID(expr->Identifier));
vlmb2839012004-08-20 13:37:01 +00001538 }
1539 INDENT(+1);
1540 if(C99_MODE) OUT(".tag = ");
vlm060fe2a2004-09-10 09:37:12 +00001541 if(outmost_tag) {
1542 if(outmost_tag->tag_value == -1)
1543 OUT("-1 /* Ambiguous tag (ANY?) */");
1544 else
1545 _print_tag(arg, outmost_tag);
vlma8a86cc2004-09-10 06:07:18 +00001546 } else {
vlm060fe2a2004-09-10 09:37:12 +00001547 OUT("-1 /* Ambiguous tag (CHOICE?) */");
vlma8a86cc2004-09-10 06:07:18 +00001548 }
vlm060fe2a2004-09-10 09:37:12 +00001549
vlmb2839012004-08-20 13:37:01 +00001550 OUT(",\n");
1551 if(C99_MODE) OUT(".tag_mode = ");
1552 if(expr->tag.tag_class) {
1553 if(expr->tag.tag_mode == TM_IMPLICIT)
1554 OUT("-1,\t/* IMPLICIT tag at current level */\n");
1555 else
1556 OUT("+1,\t/* EXPLICIT tag at current level */\n");
1557 } else {
1558 OUT("0,\n");
1559 }
vlm80a48592005-02-25 12:10:27 +00001560
1561 complex_contents =
1562 (expr->expr_type & ASN_CONSTR_MASK)
1563 || expr->expr_type == ASN_BASIC_ENUMERATED
1564 || (expr->expr_type == ASN_BASIC_INTEGER
1565 && expr_elements_count(arg, expr));
vlmb2839012004-08-20 13:37:01 +00001566 if(C99_MODE) OUT(".type = ");
vlm80a48592005-02-25 12:10:27 +00001567 if(complex_contents
1568 && expr->_anonymous_type
1569 && !strcmp(expr->Identifier, "Member")) {
vlm25f5d272005-02-15 03:37:42 +00001570 OUT("(void *)&asn_DEF_%s_Member,\n",
vlmaf841972005-01-28 12:18:50 +00001571 MKID_nr(arg->expr->Identifier));
vlm80a48592005-02-25 12:10:27 +00001572 } else if(complex_contents) {
vlma5dcb912004-09-29 13:16:40 +00001573 OUT("(void *)&asn_DEF_%s,\n",
vlmaf841972005-01-28 12:18:50 +00001574 MKID_nr(expr->Identifier));
vlmdae7f9d2004-08-22 03:25:24 +00001575 } else {
vlma5dcb912004-09-29 13:16:40 +00001576 OUT("(void *)&asn_DEF_%s,\n",
vlmdae7f9d2004-08-22 03:25:24 +00001577 asn1c_type_name(arg, expr, TNF_SAFE));
1578 }
vlmb2839012004-08-20 13:37:01 +00001579 if(C99_MODE) OUT(".memb_constraints = ");
1580 if(expr->constraints) {
vlm86f5ed22004-09-26 13:11:31 +00001581 if(arg->flags & A1C_NO_CONSTRAINTS) {
1582 OUT("0,\t/* No check because of -fno-constraints */\n");
1583 } else {
vlmaf841972005-01-28 12:18:50 +00001584 char *id = MKID_nr(expr->Identifier);
vlm86f5ed22004-09-26 13:11:31 +00001585 if(expr->_anonymous_type
vlmbf3c5112005-02-14 20:41:29 +00001586 && !strcmp(expr->Identifier, "Member"))
vlm86f5ed22004-09-26 13:11:31 +00001587 id = asn1c_type_name(arg, expr, TNF_SAFE);
1588 OUT("memb_%s_%d_constraint,\n", id,
1589 ++global_memb_unique);
1590 }
vlmb2839012004-08-20 13:37:01 +00001591 } else {
vlm95a476e2005-01-17 12:16:58 +00001592 OUT("0,\t/* Defer constraints checking to the member type */\n");
vlmb2839012004-08-20 13:37:01 +00001593 }
1594 if(C99_MODE) OUT(".name = ");
vlmbf3c5112005-02-14 20:41:29 +00001595 if(1) {
1596 if(expr->_anonymous_type && !strcmp(expr->Identifier, "Member"))
1597 OUT("\"\"\n");
1598 else
1599 OUT("\"%s\"\n", expr->Identifier);
1600 } else {
1601 OUT("\"%s\"\n", expr->_anonymous_type ? "" : expr->Identifier);
1602 }
vlmb2839012004-08-20 13:37:01 +00001603 OUT("},\n");
1604 INDENT(-1);
1605
vlm86f5ed22004-09-26 13:11:31 +00001606 if(!expr->constraints || (arg->flags & A1C_NO_CONSTRAINTS))
vlmb2839012004-08-20 13:37:01 +00001607 return 0;
1608
1609 save_target = arg->target->target;
1610 REDIR(OT_CODE);
1611
vlmbf3c5112005-02-14 20:41:29 +00001612 if(expr->_anonymous_type && !strcmp(expr->Identifier, "Member"))
vlmb2839012004-08-20 13:37:01 +00001613 p = asn1c_type_name(arg, expr, TNF_SAFE);
vlm39ba4c42004-09-22 16:06:28 +00001614 else
vlmaf841972005-01-28 12:18:50 +00001615 p = MKID_nr(expr->Identifier);
vlmb2839012004-08-20 13:37:01 +00001616 OUT("static int\n");
vlma5dcb912004-09-29 13:16:40 +00001617 OUT("memb_%s_%d_constraint(asn_TYPE_descriptor_t *td, const void *sptr,\n", p, global_memb_unique);
vlmb2839012004-08-20 13:37:01 +00001618 INDENT(+1);
1619 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
1620 tmp_arg = *arg;
1621 tmp_arg.expr = expr;
1622 if(asn1c_emit_constraint_checking_code(&tmp_arg) == 1) {
vlm86f5ed22004-09-26 13:11:31 +00001623 OUT("return td->check_constraints"
1624 "(td, sptr, app_errlog, app_key);\n");
vlmb2839012004-08-20 13:37:01 +00001625 }
1626 INDENT(-1);
1627 OUT("}\n");
1628 OUT("\n");
1629
1630 REDIR(save_target);
1631
1632 return 0;
1633}
vlm4e554992004-08-25 02:03:12 +00001634
vlm9de248e2004-10-20 15:50:55 +00001635/*
1636 * Generate "asn_DEF_XXX" type definition.
1637 */
vlm4e554992004-08-25 02:03:12 +00001638static int
vlm86f5ed22004-09-26 13:11:31 +00001639emit_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 +00001640 char *p;
1641
vlm12c8f692004-09-06 08:07:29 +00001642 if(HIDE_INNER_DEFS)
1643 OUT("static /* Use -fall-defs-global to expose */\n");
vlmaf841972005-01-28 12:18:50 +00001644 OUT("asn_TYPE_descriptor_t asn_DEF_%s = {\n",
1645 MKID_nr(expr->Identifier));
1646 p = MKID(expr->Identifier);
vlm72425de2004-09-13 08:31:01 +00001647 INDENT(+1);
vlm4e554992004-08-25 02:03:12 +00001648 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
vlm9de248e2004-10-20 15:50:55 +00001649 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
vlm4e554992004-08-25 02:03:12 +00001650
1651 if(expr->expr_type & ASN_CONSTR_MASK) {
1652 p = asn1c_type_name(arg, arg->expr, TNF_SAFE);
1653 }
1654
vlm39ba4c42004-09-22 16:06:28 +00001655 OUT("%s_free,\n", p);
1656 OUT("%s_print,\n", p);
vlm4e554992004-08-25 02:03:12 +00001657 OUT("%s_constraint,\n", p);
1658 OUT("%s_decode_ber,\n", p);
1659 OUT("%s_encode_der,\n", p);
vlm265ab7c2005-02-14 20:29:54 +00001660 OUT("%s_decode_xer,\n", p);
vlm39ba4c42004-09-22 16:06:28 +00001661 OUT("%s_encode_xer,\n", p);
vlm4e554992004-08-25 02:03:12 +00001662
vlm4e554992004-08-25 02:03:12 +00001663 if(expr->expr_type == ASN_CONSTR_CHOICE) {
1664 OUT("CHOICE_outmost_tag,\n");
1665 } else {
1666 OUT("0,\t/* Use generic outmost tag fetcher */\n");
1667 }
1668
vlmaf841972005-01-28 12:18:50 +00001669 p = MKID_nr(expr->Identifier);
vlm4e554992004-08-25 02:03:12 +00001670 if(tags_count) {
vlma5dcb912004-09-29 13:16:40 +00001671 OUT("asn_DEF_%s_tags,\n", p);
1672 OUT("sizeof(asn_DEF_%s_tags)\n", p);
1673 OUT("\t/sizeof(asn_DEF_%s_tags[0])", p);
vlm72425de2004-09-13 08:31:01 +00001674 if(tv_mode == _TVM_SUBSET
1675 && tags_count != all_tags_count)
1676 OUT(" - %d", all_tags_count - tags_count);
1677 OUT(", /* %d */\n", tags_count);
vlm4e554992004-08-25 02:03:12 +00001678 } else {
vlm72425de2004-09-13 08:31:01 +00001679 OUT("0,\t/* No effective tags (pointer) */\n");
1680 OUT("0,\t/* No effective tags (count) */\n");
1681 }
1682
1683 if(all_tags_count && tv_mode == _TVM_DIFFERENT) {
vlma5dcb912004-09-29 13:16:40 +00001684 OUT("asn_DEF_%s_all_tags,\n", p);
1685 OUT("sizeof(asn_DEF_%s_all_tags)\n", p);
1686 OUT("\t/sizeof(asn_DEF_%s_all_tags[0]), /* %d */\n",
vlm72425de2004-09-13 08:31:01 +00001687 p, all_tags_count);
1688 } else if(all_tags_count) {
vlma5dcb912004-09-29 13:16:40 +00001689 OUT("asn_DEF_%s_tags,\t/* Same as above */\n", p);
1690 OUT("sizeof(asn_DEF_%s_tags)\n", p);
1691 OUT("\t/sizeof(asn_DEF_%s_tags[0]), /* %d */\n",
vlm72425de2004-09-13 08:31:01 +00001692 p, all_tags_count);
1693 } else {
1694 OUT("0,\t/* No tags (pointer) */\n");
1695 OUT("0,\t/* No tags (count) */\n");
vlm4e554992004-08-25 02:03:12 +00001696 }
1697
vlm4e554992004-08-25 02:03:12 +00001698 if(elements_count) {
vlma5dcb912004-09-29 13:16:40 +00001699 OUT("asn_MBR_%s,\n", p);
vlm4e554992004-08-25 02:03:12 +00001700 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF
1701 || expr->expr_type == ASN_CONSTR_SET_OF) {
1702 OUT("%d,\t/* Single element */\n",
1703 elements_count);
1704 assert(elements_count == 1);
1705 } else {
1706 OUT("%d,\t/* Elements count */\n",
1707 elements_count);
1708 }
1709 } else {
1710 //if(expr->meta_type == AMT_TYPEREF)
1711 if(expr_elements_count(arg, expr))
1712 OUT("0, 0,\t/* Defined elsewhere */\n");
1713 else
1714 OUT("0, 0,\t/* No members */\n");
1715 }
1716
1717 switch(spec) {
1718 case ETD_NO_SPECIFICS:
1719 OUT("0\t/* No specifics */\n");
1720 break;
1721 case ETD_HAS_SPECIFICS:
vlma5dcb912004-09-29 13:16:40 +00001722 OUT("&asn_DEF_%s_specs\t/* Additional specs */\n", p);
vlm4e554992004-08-25 02:03:12 +00001723 }
vlm72425de2004-09-13 08:31:01 +00001724 INDENT(-1);
vlm4e554992004-08-25 02:03:12 +00001725 OUT("};\n");
1726 OUT("\n");
vlme2bb4432004-08-26 06:20:34 +00001727
1728 return 0;
vlm4e554992004-08-25 02:03:12 +00001729}
vlmddd5a7d2004-09-10 09:18:20 +00001730
1731/*
1732 * Check if it is better to make this type indirectly accessed via
1733 * a pointer.
1734 * This may be the case for the following recursive definition:
1735 * Type ::= CHOICE { member Type };
1736 */
1737static int
1738expr_better_indirect(arg_t *arg, asn1p_expr_t *expr) {
1739 asn1p_expr_t *top_parent;
1740 asn1p_expr_t *terminal;
1741
1742 if(expr->expr_type != A1TC_REFERENCE)
1743 return 0;
1744
1745 /* Rewind to the topmost parent expression */
1746 if((top_parent = expr->parent_expr)) {
1747 while(top_parent->parent_expr)
1748 top_parent = top_parent->parent_expr;
1749 } else {
1750 return 0;
1751 }
1752
vlm39ba4c42004-09-22 16:06:28 +00001753 terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
vlmddd5a7d2004-09-10 09:18:20 +00001754
1755 return (terminal == top_parent);
1756}
vlm39ba4c42004-09-22 16:06:28 +00001757
1758static int
1759expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr) {
1760 expr = asn1f_find_terminal_type_ex(arg->asn, expr);
1761 if(!expr) return 0;
1762
1763 /* X.680, 25.5, Table 5 */
1764 switch(expr->expr_type) {
1765 case ASN_CONSTR_CHOICE:
1766 case ASN_BASIC_BOOLEAN:
1767 case ASN_BASIC_ENUMERATED:
1768 case ASN_BASIC_NULL:
1769 return 1;
1770 default:
1771 return 0;
1772 }
1773}
vlmaf841972005-01-28 12:18:50 +00001774
1775static int
1776out_identifiers_chain(arg_t *arg, int check_reserved_keywords) {
1777 asn1p_expr_t *expr = arg->expr;
1778 char *id;
1779
1780 assert(expr->Identifier);
1781
1782 if(arg->flags & A1C_DOUBLE_IDENTIFIERS
1783 && expr->parent_expr
1784 && expr->parent_expr->Identifier) {
1785 arg_t tmparg = *arg;
1786
1787 tmparg.expr = expr->parent_expr;
1788 tmparg.flags &= ~A1C_DOUBLE_IDENTIFIERS;
1789 out_identifiers_chain(&tmparg, 0);
1790
1791 OUT("_"); /* a separator between id components */
1792 /* Fall through */
1793 }
1794
1795 if(check_reserved_keywords)
1796 id = MKID(expr->Identifier);
1797 else
1798 id = MKID_nr(expr->Identifier);
1799 OUT("%s", id);
1800
1801 return 0;
1802}