blob: 179161f0355bb5f315d0736ddd51a41da45a6c91 [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
20static int _fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no);
21static int _add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no);
22
vlmfa67ddc2004-06-03 03:38:44 +000023static int asn1c_lang_C_type_SEQUENCE_def(arg_t *arg);
24static int asn1c_lang_C_type_SET_def(arg_t *arg);
25static int asn1c_lang_C_type_CHOICE_def(arg_t *arg);
26static int asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of);
vlma8a86cc2004-09-10 06:07:18 +000027static int _print_tag(arg_t *arg, struct asn1p_type_tag_s *tag_p);
vlm79b08d52004-07-01 00:52:50 +000028static int check_if_extensible(asn1p_expr_t *expr);
vlmddd5a7d2004-09-10 09:18:20 +000029static int expr_better_indirect(arg_t *arg, asn1p_expr_t *expr);
vlm39ba4c42004-09-22 16:06:28 +000030static int expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr);
vlm4e554992004-08-25 02:03:12 +000031static int expr_elements_count(arg_t *arg, asn1p_expr_t *expr);
32static int emit_member_table(arg_t *arg, asn1p_expr_t *expr);
vlm4e03ce22004-06-06 07:20:17 +000033static int emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count);
vlmfa67ddc2004-06-03 03:38:44 +000034
vlm72425de2004-09-13 08:31:01 +000035enum tvm_compat {
36 _TVM_SAME = 0, /* tags and all_tags are same */
37 _TVM_SUBSET = 1, /* tags are subset of all_tags */
38 _TVM_DIFFERENT = 2, /* tags and all_tags are different */
39};
40static enum tvm_compat emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tc, int *atc);
41
vlm4e554992004-08-25 02:03:12 +000042enum etd_cp {
43 ETD_CP_UNKNOWN = -2,
44 ETD_CP_EITHER = -1,
45 ETD_CP_PRIMITIVE = 0,
46 ETD_CP_CONSTRUCTED = 1,
47};
48enum etd_spec {
49 ETD_NO_SPECIFICS,
50 ETD_HAS_SPECIFICS
51};
vlm72425de2004-09-13 08:31:01 +000052static 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_cp, enum etd_spec);
vlm4e554992004-08-25 02:03:12 +000053
vlmb2839012004-08-20 13:37:01 +000054#define C99_MODE (!(arg->flags & A1C_NO_C99))
vlmfa67ddc2004-06-03 03:38:44 +000055#define UNNAMED_UNIONS (arg->flags & A1C_UNNAMED_UNIONS)
vlm12c8f692004-09-06 08:07:29 +000056#define HIDE_INNER_DEFS (arg->embed && !(arg->flags & A1C_ALL_DEFS_GLOBAL))
vlmfa67ddc2004-06-03 03:38:44 +000057
58#define PCTX_DEF INDENTED( \
59 OUT("\n"); \
60 OUT("/* Context for parsing across buffer boundaries */\n"); \
61 OUT("ber_dec_ctx_t _ber_dec_ctx;\n"));
62
vlm33a4ff12004-08-11 05:21:32 +000063#define DEPENDENCIES do { \
vlmdae7f9d2004-08-22 03:25:24 +000064 asn1p_expr_t *__m; \
65 TQ_FOR(__m, &(expr->members), next) { \
66 if((!(__m->expr_type & ASN_CONSTR_MASK) \
67 && __m->expr_type > ASN_CONSTR_MASK) \
68 || __m->meta_type == AMT_TYPEREF) { \
69 GEN_INCLUDE(asn1c_type_name(arg, \
70 __m, TNF_INCLUDE)); \
vlm33a4ff12004-08-11 05:21:32 +000071 } \
72 } \
73 if(expr->expr_type == ASN_CONSTR_SET_OF) \
74 GEN_INCLUDE("asn_SET_OF"); \
75 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF) \
76 GEN_INCLUDE("asn_SEQUENCE_OF"); \
77} while(0)
vlmfa67ddc2004-06-03 03:38:44 +000078
79#define MKID(id) asn1c_make_identifier(0, (id), 0)
80
81int
vlmf9d178d2004-09-14 12:47:45 +000082asn1c_lang_C_type_REAL(arg_t *arg) {
vlmfa67ddc2004-06-03 03:38:44 +000083 REDIR(OT_DEPS);
vlmfa67ddc2004-06-03 03:38:44 +000084 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
85}
86
vlmfa67ddc2004-06-03 03:38:44 +000087int
vlmf9d178d2004-09-14 12:47:45 +000088asn1c_lang_C_type_common_INTEGER(arg_t *arg) {
vlmfa67ddc2004-06-03 03:38:44 +000089 asn1p_expr_t *expr = arg->expr;
90 asn1p_expr_t *v;
91
92 REDIR(OT_DEPS);
93
vlmf9d178d2004-09-14 12:47:45 +000094 if(expr->expr_type == ASN_BASIC_ENUMERATED
95 || TQ_FIRST(&(expr->members))
96 ) {
vlmfa67ddc2004-06-03 03:38:44 +000097 OUT("typedef enum %s {\n", MKID(expr->Identifier));
98 TQ_FOR(v, &(expr->members), next) {
99 switch(v->expr_type) {
100 case A1TC_UNIVERVAL:
101 OUT("\t%s\t= %lld,\n",
102 asn1c_make_identifier(0,
103 expr->Identifier,
104 v->Identifier, 0),
105 v->value->value.v_integer);
106 break;
vlmf9d178d2004-09-14 12:47:45 +0000107 case A1TC_EXTENSIBLE:
108 OUT("\t/*\n");
109 OUT("\t * Enumeration is extensible\n");
110 OUT("\t */\n");
111 break;
vlmfa67ddc2004-06-03 03:38:44 +0000112 default:
113 return -1;
114 }
115 }
116 OUT("} %s_e;\n", MKID(expr->Identifier));
117 }
118
119 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
120}
121
122int
123asn1c_lang_C_type_SEQUENCE(arg_t *arg) {
124 asn1p_expr_t *expr = arg->expr;
125 asn1p_expr_t *v;
126 int comp_mode = 0; /* {root,ext=1,root,root,...} */
127
128 DEPENDENCIES;
129
130 if(arg->embed) {
vlmdae7f9d2004-08-22 03:25:24 +0000131 OUT("struct %s {\n", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000132 } else {
133 OUT("typedef struct %s {\n",
134 MKID(expr->Identifier));
135 }
136
137 TQ_FOR(v, &(expr->members), next) {
138 if(v->expr_type == A1TC_EXTENSIBLE) {
139 if(comp_mode < 3) comp_mode++;
140 }
vlmddd5a7d2004-09-10 09:18:20 +0000141 if(comp_mode == 1
142 || expr_better_indirect(arg, v))
vlma02b74d2004-09-15 11:54:38 +0000143 v->marker.flags |= EM_INDIRECT;
vlmfa67ddc2004-06-03 03:38:44 +0000144 EMBED(v);
145 }
146
147 PCTX_DEF;
vlma02b74d2004-09-15 11:54:38 +0000148 OUT("} %s%s%s", expr->marker.flags?"*":"",
vlmdae7f9d2004-08-22 03:25:24 +0000149 expr->_anonymous_type ? "" : MKID(expr->Identifier),
150 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000151
152 return asn1c_lang_C_type_SEQUENCE_def(arg);
153}
154
155static int
156asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
157 asn1p_expr_t *expr = arg->expr;
158 asn1p_expr_t *v;
159 int elements; /* Number of elements */
vlmfa67ddc2004-06-03 03:38:44 +0000160 int ext_start = -1;
161 int ext_stop = -1;
vlm4e03ce22004-06-06 07:20:17 +0000162 tag2el_t *tag2el = NULL;
163 int tag2el_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000164 int tags_count;
vlm72425de2004-09-13 08:31:01 +0000165 int all_tags_count;
166 enum tvm_compat tv_mode;
vlmfa67ddc2004-06-03 03:38:44 +0000167 char *p;
168
vlm4e03ce22004-06-06 07:20:17 +0000169 /*
170 * Fetch every inner tag from the tag to elements map.
171 */
172 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
173 if(tag2el) free(tag2el);
174 return -1;
175 }
176
vlm33a4ff12004-08-11 05:21:32 +0000177 GEN_INCLUDE("constr_SEQUENCE");
178 if(!arg->embed)
179 GEN_DECLARE(expr); /* asn1_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000180
vlm33a4ff12004-08-11 05:21:32 +0000181 REDIR(OT_STAT_DEFS);
vlmfa67ddc2004-06-03 03:38:44 +0000182
183 /*
184 * Print out the table according to which the parsing is performed.
185 */
vlm39ba4c42004-09-22 16:06:28 +0000186 if(expr_elements_count(arg, expr)) {
187 int comp_mode = 0; /* {root,ext=1,root,root,...} */
vlmfa67ddc2004-06-03 03:38:44 +0000188
vlm39ba4c42004-09-22 16:06:28 +0000189 p = MKID(expr->Identifier);
190 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
191
192 elements = 0;
193 INDENTED(TQ_FOR(v, &(expr->members), next) {
194 if(v->expr_type == A1TC_EXTENSIBLE) {
195 if((++comp_mode) == 1)
196 ext_start = elements - 1;
197 else
198 ext_stop = elements - 1;
199 continue;
200 }
201 elements++;
202 emit_member_table(arg, v);
203 });
204 OUT("};\n");
205 } else {
206 elements = 0;
207 }
vlmfa67ddc2004-06-03 03:38:44 +0000208
vlm4a3f5822004-06-28 21:13:46 +0000209 /*
vlm72425de2004-09-13 08:31:01 +0000210 * Print out asn1_DEF_<type>_[all_]tags[] vectors.
vlm4a3f5822004-06-28 21:13:46 +0000211 */
vlm72425de2004-09-13 08:31:01 +0000212 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
vlmfa67ddc2004-06-03 03:38:44 +0000213
vlm4e03ce22004-06-06 07:20:17 +0000214 /*
215 * Tags to elements map.
216 */
217 emit_tag2member_map(arg, tag2el, tag2el_count);
218
vlm4a3f5822004-06-28 21:13:46 +0000219 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000220 OUT("static asn1_SEQUENCE_specifics_t asn1_DEF_%s_specs = {\n", p);
221 INDENTED(
222 OUT("sizeof(struct %s),\n", p);
223 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
vlm4e03ce22004-06-06 07:20:17 +0000224 OUT("asn1_DEF_%s_tag2el,\n", p);
225 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
vlmfa67ddc2004-06-03 03:38:44 +0000226 OUT("%d,\t/* Start extensions */\n",
227 ext_start);
228 OUT("%d\t/* Stop extensions */\n",
229 (ext_stop<ext_start)?elements+1:ext_stop, ext_stop);
230 );
231 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000232
233 /*
234 * Emit asn1_DEF_xxx table.
235 */
vlm72425de2004-09-13 08:31:01 +0000236 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
vlm4e554992004-08-25 02:03:12 +0000237 ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000238
vlmfa67ddc2004-06-03 03:38:44 +0000239 REDIR(OT_TYPE_DECLS);
240
241 return 0;
242}
243
244int
vlmfa67ddc2004-06-03 03:38:44 +0000245asn1c_lang_C_type_SET(arg_t *arg) {
246 asn1p_expr_t *expr = arg->expr;
247 asn1p_expr_t *v;
248 long mcount;
249 char *id;
250 int comp_mode = 0; /* {root,ext=1,root,root,...} */
251
252 DEPENDENCIES;
253
254 REDIR(OT_DEPS);
255
256 OUT("\n");
257 OUT("/*\n");
258 OUT(" * Method of determining the components presence\n");
259 OUT(" */\n");
260 mcount = 0;
vlm6e73a042004-08-11 07:17:22 +0000261 OUT("typedef enum %s_PR {\n", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000262 TQ_FOR(v, &(expr->members), next) {
263 if(v->expr_type == A1TC_EXTENSIBLE) continue;
264 INDENTED(
265 id = MKID(expr->Identifier);
266 OUT("%s_PR_", id);
267 id = MKID(v->Identifier);
268 OUT("%s,\t/* Member %s is present */\n",
269 id, id)
270 );
271 mcount++;
272 }
vlm6e73a042004-08-11 07:17:22 +0000273 id = MKID(expr->Identifier);
274 OUT("} %s_PR;\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000275
276 REDIR(OT_TYPE_DECLS);
277
278 if(arg->embed) {
vlm6e73a042004-08-11 07:17:22 +0000279 OUT("struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000280 } else {
vlm6e73a042004-08-11 07:17:22 +0000281 OUT("typedef struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000282 }
283
284 TQ_FOR(v, &(expr->members), next) {
285 if(v->expr_type == A1TC_EXTENSIBLE) {
286 if(comp_mode < 3) comp_mode++;
287 }
vlmddd5a7d2004-09-10 09:18:20 +0000288 if(comp_mode == 1
289 || expr_better_indirect(arg, v))
vlma02b74d2004-09-15 11:54:38 +0000290 v->marker.flags |= EM_INDIRECT;
vlmfa67ddc2004-06-03 03:38:44 +0000291 EMBED(v);
292 }
293
294 INDENTED(
295 id = MKID(expr->Identifier);
296 OUT("\n");
297 OUT("/* Presence bitmask: ASN_SET_ISPRESENT(p%s, %s_PR_x) */\n",
298 id, id);
299 OUT("unsigned int _presence_map\n");
300 OUT("\t[((%ld+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))];\n", mcount);
301 );
302
303 PCTX_DEF;
vlma02b74d2004-09-15 11:54:38 +0000304 OUT("} %s%s%s", expr->marker.flags?"*":"",
vlmdae7f9d2004-08-22 03:25:24 +0000305 expr->_anonymous_type ? "" : MKID(expr->Identifier),
306 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000307
308 return asn1c_lang_C_type_SET_def(arg);
309}
310
vlmfa67ddc2004-06-03 03:38:44 +0000311static int
312asn1c_lang_C_type_SET_def(arg_t *arg) {
313 asn1p_expr_t *expr = arg->expr;
314 asn1p_expr_t *v;
315 int elements;
vlmfa67ddc2004-06-03 03:38:44 +0000316 tag2el_t *tag2el = NULL;
317 int tag2el_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000318 int tags_count;
vlm72425de2004-09-13 08:31:01 +0000319 int all_tags_count;
320 enum tvm_compat tv_mode;
vlmfa67ddc2004-06-03 03:38:44 +0000321 char *p;
322
323 /*
324 * Fetch every inner tag from the tag to elements map.
325 */
326 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
327 if(tag2el) free(tag2el);
328 return -1;
vlmfa67ddc2004-06-03 03:38:44 +0000329 }
330
vlm33a4ff12004-08-11 05:21:32 +0000331 GEN_INCLUDE("constr_SET");
332 if(!arg->embed)
333 GEN_DECLARE(expr); /* asn1_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000334
335 REDIR(OT_STAT_DEFS);
336
vlmfa67ddc2004-06-03 03:38:44 +0000337 /*
338 * Print out the table according to which the parsing is performed.
339 */
vlm39ba4c42004-09-22 16:06:28 +0000340 if(expr_elements_count(arg, expr)) {
341 int comp_mode = 0; /* {root,ext=1,root,root,...} */
vlmfa67ddc2004-06-03 03:38:44 +0000342
vlm39ba4c42004-09-22 16:06:28 +0000343 p = MKID(expr->Identifier);
344 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
345
346 elements = 0;
347 INDENTED(TQ_FOR(v, &(expr->members), next) {
348 if(v->expr_type == A1TC_EXTENSIBLE) {
349 if(comp_mode < 3) comp_mode++;
350 } else {
351 if(comp_mode == 1
352 || expr_better_indirect(arg, v))
353 v->marker.flags |= EM_INDIRECT;
354 elements++;
355 emit_member_table(arg, v);
356 }
357 });
358 OUT("};\n");
359 } else {
360 elements = 0;
361 }
vlmfa67ddc2004-06-03 03:38:44 +0000362
vlm4a3f5822004-06-28 21:13:46 +0000363 /*
vlm72425de2004-09-13 08:31:01 +0000364 * Print out asn1_DEF_<type>_[all_]tags[] vectors.
vlm4a3f5822004-06-28 21:13:46 +0000365 */
vlm72425de2004-09-13 08:31:01 +0000366 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
vlmfa67ddc2004-06-03 03:38:44 +0000367
368 /*
369 * Tags to elements map.
370 */
vlm4e03ce22004-06-06 07:20:17 +0000371 emit_tag2member_map(arg, tag2el, tag2el_count);
vlmfa67ddc2004-06-03 03:38:44 +0000372
373 /*
374 * Emit a map of mandatory elements.
375 */
vlm4a3f5822004-06-28 21:13:46 +0000376 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000377 OUT("static uint8_t asn1_DEF_%s_mmap", p);
378 OUT("[(%d + (8 * sizeof(unsigned int)) - 1) / 8]", elements);
379 OUT(" = {\n", p);
380 INDENTED(
381 if(elements) {
382 int delimit = 0;
383 int el = 0;
384 TQ_FOR(v, &(expr->members), next) {
385 if(v->expr_type == A1TC_EXTENSIBLE) continue;
386 if(delimit) {
387 OUT(",\n");
388 delimit = 0;
389 } else if(el) {
390 OUT(" | ");
391 }
vlmddd5a7d2004-09-10 09:18:20 +0000392 OUT("(%d << %d)",
vlma02b74d2004-09-15 11:54:38 +0000393 v->marker.flags?0:1,
vlmddd5a7d2004-09-10 09:18:20 +0000394 7 - (el % 8));
vlmfa67ddc2004-06-03 03:38:44 +0000395 if(el && (el % 8) == 0)
396 delimit = 1;
397 el++;
398 }
399 } else {
400 OUT("0");
401 }
402 );
403 OUT("\n");
404 OUT("};\n");
405
406 OUT("static asn1_SET_specifics_t asn1_DEF_%s_specs = {\n", p);
407 INDENTED(
408 OUT("sizeof(struct %s),\n", p);
409 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
410 OUT("offsetof(struct %s, _presence_map),\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000411 OUT("asn1_DEF_%s_tag2el,\n", p);
412 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
vlm79b08d52004-07-01 00:52:50 +0000413 OUT("%d,\t/* Whether extensible */\n",
414 check_if_extensible(expr));
vlmfa67ddc2004-06-03 03:38:44 +0000415 OUT("(unsigned int *)asn1_DEF_%s_mmap\t/* Mandatory elements map */\n", p);
416 );
417 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000418
419 /*
420 * Emit asn1_DEF_xxx table.
421 */
vlm72425de2004-09-13 08:31:01 +0000422 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
vlm4e554992004-08-25 02:03:12 +0000423 ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000424
vlmfa67ddc2004-06-03 03:38:44 +0000425 REDIR(OT_TYPE_DECLS);
426
427 return 0;
428}
429
430int
vlmdae7f9d2004-08-22 03:25:24 +0000431asn1c_lang_C_type_SEx_OF(arg_t *arg) {
vlmfa67ddc2004-06-03 03:38:44 +0000432 asn1p_expr_t *expr = arg->expr;
vlmdae7f9d2004-08-22 03:25:24 +0000433 asn1p_expr_t *memb;
vlmfa67ddc2004-06-03 03:38:44 +0000434
435 DEPENDENCIES;
436
437 if(arg->embed) {
438 OUT("struct %s {\n", MKID(expr->Identifier));
439 } else {
vlmdae7f9d2004-08-22 03:25:24 +0000440 OUT("typedef struct %s {\n", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000441 }
442
vlmdae7f9d2004-08-22 03:25:24 +0000443 memb = TQ_FIRST(&expr->members);
444
445 INDENT(+1);
446 OUT("A_%s_OF(",
447 (arg->expr->expr_type == ASN_CONSTR_SET_OF)
448 ? "SET" : "SEQUENCE");
449 if(memb->expr_type & ASN_CONSTR_MASK) {
450 arg_t tmp;
451 asn1p_expr_t tmp_memb;
452 arg->embed++;
453 tmp = *arg;
454 tmp.expr = &tmp_memb;
455 tmp_memb = *memb;
456 tmp_memb._anonymous_type = 1;
vlm39ba4c42004-09-22 16:06:28 +0000457 if(tmp_memb.Identifier == 0) {
458 tmp_memb.Identifier = strdup(
459 asn1c_make_identifier(0,
460 expr->Identifier, "member", 0));
461 assert(tmp_memb.Identifier);
462 }
vlmdae7f9d2004-08-22 03:25:24 +0000463 tmp.default_cb(&tmp);
vlm39ba4c42004-09-22 16:06:28 +0000464 if(tmp_memb.Identifier != memb->Identifier)
465 free(tmp_memb.Identifier);
vlmdae7f9d2004-08-22 03:25:24 +0000466 arg->embed--;
467 assert(arg->target->target == OT_TYPE_DECLS);
468 } else {
vlmb47f48e2004-09-17 06:32:12 +0000469 OUT("%s", asn1c_type_name(arg, memb, TNF_CTYPE));
vlmfa67ddc2004-06-03 03:38:44 +0000470 }
vlmdae7f9d2004-08-22 03:25:24 +0000471 OUT(") list;\n");
472 INDENT(-1);
vlmfa67ddc2004-06-03 03:38:44 +0000473
474 PCTX_DEF;
vlma02b74d2004-09-15 11:54:38 +0000475 OUT("} %s%s%s", expr->marker.flags?"*":"",
vlmdae7f9d2004-08-22 03:25:24 +0000476 expr->_anonymous_type ? "" : MKID(expr->Identifier),
477 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000478
479 /*
vlmdae7f9d2004-08-22 03:25:24 +0000480 * SET OF/SEQUENCE OF definition
vlmfa67ddc2004-06-03 03:38:44 +0000481 */
vlmdae7f9d2004-08-22 03:25:24 +0000482 return asn1c_lang_C_type_SEx_OF_def(arg,
483 (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF));
vlmfa67ddc2004-06-03 03:38:44 +0000484}
485
486static int
487asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
488 asn1p_expr_t *expr = arg->expr;
489 asn1p_expr_t *v;
vlm6e73a042004-08-11 07:17:22 +0000490 int tags_count;
vlm72425de2004-09-13 08:31:01 +0000491 int all_tags_count;
492 enum tvm_compat tv_mode;
vlmfa67ddc2004-06-03 03:38:44 +0000493 char *p;
494
vlm33a4ff12004-08-11 05:21:32 +0000495 /*
496 * Print out the table according to which the parsing is performed.
497 */
vlmfa67ddc2004-06-03 03:38:44 +0000498 if(seq_of) {
vlm33a4ff12004-08-11 05:21:32 +0000499 GEN_INCLUDE("constr_SEQUENCE_OF");
vlmfa67ddc2004-06-03 03:38:44 +0000500 } else {
vlm33a4ff12004-08-11 05:21:32 +0000501 GEN_INCLUDE("constr_SET_OF");
vlmfa67ddc2004-06-03 03:38:44 +0000502 }
vlm33a4ff12004-08-11 05:21:32 +0000503 if(!arg->embed)
504 GEN_DECLARE(expr); /* asn1_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000505
506 REDIR(OT_STAT_DEFS);
507
508 /*
509 * Print out the table according to which the parsing is performed.
510 */
511 p = MKID(expr->Identifier);
vlmb2839012004-08-20 13:37:01 +0000512 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000513 INDENT(+1);
vlmfa67ddc2004-06-03 03:38:44 +0000514 v = TQ_FIRST(&(expr->members));
vlm39ba4c42004-09-22 16:06:28 +0000515 if(!v->Identifier) {
516 v->Identifier = strdup("member");
517 assert(v->Identifier);
518 }
519 v->_anonymous_type = 1;
520 arg->embed++;
vlm4e554992004-08-25 02:03:12 +0000521 emit_member_table(arg, v);
vlm39ba4c42004-09-22 16:06:28 +0000522 arg->embed--;
523 INDENT(-1);
vlmfa67ddc2004-06-03 03:38:44 +0000524 OUT("};\n");
525
vlm4a3f5822004-06-28 21:13:46 +0000526 /*
vlm72425de2004-09-13 08:31:01 +0000527 * Print out asn1_DEF_<type>_[all_]tags[] vectors.
vlm4a3f5822004-06-28 21:13:46 +0000528 */
vlm72425de2004-09-13 08:31:01 +0000529 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
vlmfa67ddc2004-06-03 03:38:44 +0000530
vlm4a3f5822004-06-28 21:13:46 +0000531 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000532 OUT("static asn1_SET_OF_specifics_t asn1_DEF_%s_specs = {\n", p);
533 INDENTED(
534 OUT("sizeof(struct %s),\n", p);
535 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000536 if(expr_as_xmlvaluelist(arg, v))
537 OUT("1,\t/* XER encoding is XMLValueList */\n");
538 else
539 OUT("0,\t/* XER encoding is XMLDelimitedItemList */\n");
vlmfa67ddc2004-06-03 03:38:44 +0000540 );
541 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000542
543 /*
544 * Emit asn1_DEF_xxx table.
545 */
vlm72425de2004-09-13 08:31:01 +0000546 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, 1,
vlm4e554992004-08-25 02:03:12 +0000547 ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000548
vlmfa67ddc2004-06-03 03:38:44 +0000549 REDIR(OT_TYPE_DECLS);
550
551 return 0;
552}
553
554int
555asn1c_lang_C_type_CHOICE(arg_t *arg) {
556 asn1p_expr_t *expr = arg->expr;
557 asn1p_expr_t *v;
vlmdae7f9d2004-08-22 03:25:24 +0000558 char *id;
vlmfa67ddc2004-06-03 03:38:44 +0000559
560 DEPENDENCIES;
561
vlm33a4ff12004-08-11 05:21:32 +0000562 REDIR(OT_DEPS);
563
vlmdae7f9d2004-08-22 03:25:24 +0000564 id = MKID(expr->Identifier);
565 OUT("typedef enum %s_PR {\n", id);
vlm33a4ff12004-08-11 05:21:32 +0000566 INDENTED(
vlm33a4ff12004-08-11 05:21:32 +0000567 OUT("%s_PR_NOTHING,\t"
vlmdae7f9d2004-08-22 03:25:24 +0000568 "/* No components present */\n", id);
vlm33a4ff12004-08-11 05:21:32 +0000569 TQ_FOR(v, &(expr->members), next) {
570 if(v->expr_type == A1TC_EXTENSIBLE) {
571 OUT("/* Extensions may appear below */\n");
572 continue;
573 }
vlmdae7f9d2004-08-22 03:25:24 +0000574 id = MKID(expr->Identifier);
575 OUT("%s_PR_", id);
576 id = MKID(v->Identifier);
577 OUT("%s,\n", id, id);
vlm33a4ff12004-08-11 05:21:32 +0000578 }
579 );
vlmdae7f9d2004-08-22 03:25:24 +0000580 id = MKID(expr->Identifier);
581 OUT("} %s_PR;\n", id);
vlm33a4ff12004-08-11 05:21:32 +0000582
583 REDIR(OT_TYPE_DECLS);
vlmfa67ddc2004-06-03 03:38:44 +0000584
585 if(arg->embed) {
vlmdae7f9d2004-08-22 03:25:24 +0000586 OUT("struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000587 } else {
vlmdae7f9d2004-08-22 03:25:24 +0000588 OUT("typedef struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000589 }
590
591 INDENTED(
vlmdae7f9d2004-08-22 03:25:24 +0000592 OUT("%s_PR present;\n", id);
593 OUT("union {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000594 TQ_FOR(v, &(expr->members), next) {
vlmddd5a7d2004-09-10 09:18:20 +0000595 if(expr_better_indirect(arg, v))
vlma02b74d2004-09-15 11:54:38 +0000596 v->marker.flags |= EM_INDIRECT;
vlmfa67ddc2004-06-03 03:38:44 +0000597 EMBED(v);
598 }
599 if(UNNAMED_UNIONS) OUT("};\n");
600 else OUT("} choice;\n");
601 );
602
603 PCTX_DEF;
vlma02b74d2004-09-15 11:54:38 +0000604 OUT("} %s%s%s", expr->marker.flags?"*":"",
vlmdae7f9d2004-08-22 03:25:24 +0000605 expr->_anonymous_type ? "" : MKID(expr->Identifier),
606 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000607
608 return asn1c_lang_C_type_CHOICE_def(arg);
609}
610
611static int
612asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
613 asn1p_expr_t *expr = arg->expr;
614 asn1p_expr_t *v;
615 int elements; /* Number of elements */
vlmfa67ddc2004-06-03 03:38:44 +0000616 tag2el_t *tag2el = NULL;
617 int tag2el_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000618 int tags_count;
vlm72425de2004-09-13 08:31:01 +0000619 int all_tags_count;
620 enum tvm_compat tv_mode;
vlmfa67ddc2004-06-03 03:38:44 +0000621 char *p;
622
623 /*
624 * Fetch every inner tag from the tag to elements map.
625 */
626 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
627 if(tag2el) free(tag2el);
628 return -1;
vlmfa67ddc2004-06-03 03:38:44 +0000629 }
630
vlm33a4ff12004-08-11 05:21:32 +0000631 GEN_INCLUDE("constr_CHOICE");
632 if(!arg->embed)
633 GEN_DECLARE(expr); /* asn1_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000634
vlm33a4ff12004-08-11 05:21:32 +0000635 REDIR(OT_STAT_DEFS);
vlmfa67ddc2004-06-03 03:38:44 +0000636
637 /*
638 * Print out the table according to which the parsing is performed.
639 */
vlm39ba4c42004-09-22 16:06:28 +0000640 if(expr_elements_count(arg, expr)) {
641 int comp_mode = 0; /* {root,ext=1,root,root,...} */
vlmfa67ddc2004-06-03 03:38:44 +0000642
vlm39ba4c42004-09-22 16:06:28 +0000643 p = MKID(expr->Identifier);
644 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
645
646 elements = 0;
647 INDENTED(TQ_FOR(v, &(expr->members), next) {
648 if(v->expr_type == A1TC_EXTENSIBLE) {
649 if(comp_mode < 3) comp_mode++;
650 } else {
651 if(comp_mode == 1
652 || expr_better_indirect(arg, v))
653 v->marker.flags |= EM_INDIRECT;
654 elements++;
655 emit_member_table(arg, v);
656 }
657 });
658 OUT("};\n");
659 } else {
660 elements = 0;
661 }
vlmfa67ddc2004-06-03 03:38:44 +0000662
vlm6e73a042004-08-11 07:17:22 +0000663
vlmfa67ddc2004-06-03 03:38:44 +0000664 if(arg->embed) {
665 /*
666 * Our parent structure has already taken this into account.
667 */
vlm72425de2004-09-13 08:31:01 +0000668 tv_mode = _TVM_SAME;
669 tags_count = all_tags_count = 0;
vlmfa67ddc2004-06-03 03:38:44 +0000670 } else {
vlm72425de2004-09-13 08:31:01 +0000671 tv_mode = emit_tags_vectors(arg, expr,
672 &tags_count, &all_tags_count);
vlmfa67ddc2004-06-03 03:38:44 +0000673 }
vlmfa67ddc2004-06-03 03:38:44 +0000674
675 /*
676 * Tags to elements map.
677 */
vlm4e03ce22004-06-06 07:20:17 +0000678 emit_tag2member_map(arg, tag2el, tag2el_count);
vlmfa67ddc2004-06-03 03:38:44 +0000679
vlm6e73a042004-08-11 07:17:22 +0000680 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000681 OUT("static asn1_CHOICE_specifics_t asn1_DEF_%s_specs = {\n", p);
682 INDENTED(
683 OUT("sizeof(struct %s),\n", p);
684 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
685 OUT("offsetof(struct %s, present),\n", p);
686 OUT("sizeof(((struct %s *)0)->present),\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000687 OUT("asn1_DEF_%s_tag2el,\n", p);
688 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
vlm79b08d52004-07-01 00:52:50 +0000689 OUT("%d\t/* Whether extensible */\n",
690 check_if_extensible(expr));
vlmfa67ddc2004-06-03 03:38:44 +0000691 );
692 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000693
694 /*
695 * Emit asn1_DEF_xxx table.
696 */
vlm72425de2004-09-13 08:31:01 +0000697 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
vlm4e554992004-08-25 02:03:12 +0000698 ETD_CP_CONSTRUCTED /*either?!*/, ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000699
vlmfa67ddc2004-06-03 03:38:44 +0000700 REDIR(OT_TYPE_DECLS);
701
702 return 0;
703}
704
705int
706asn1c_lang_C_type_REFERENCE(arg_t *arg) {
707 asn1p_ref_t *ref;
708
709 ref = arg->expr->reference;
710 if(ref->components[ref->comp_count-1].name[0] == '&') {
vlmfa67ddc2004-06-03 03:38:44 +0000711 asn1p_expr_t *extract;
712 arg_t tmp;
713 int ret;
714
vlm39ba4c42004-09-22 16:06:28 +0000715 extract = asn1f_class_access_ex(arg->asn, arg->expr->module,
vlmdae7f9d2004-08-22 03:25:24 +0000716 arg->expr, ref);
vlmfa67ddc2004-06-03 03:38:44 +0000717 if(extract == NULL)
718 return -1;
719
vlmdae7f9d2004-08-22 03:25:24 +0000720 extract = asn1p_expr_clone(extract, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000721 if(extract) {
722 if(extract->Identifier)
723 free(extract->Identifier);
724 extract->Identifier = strdup(arg->expr->Identifier);
725 if(extract->Identifier == NULL) {
726 asn1p_expr_free(extract);
727 return -1;
728 }
729 } else {
730 return -1;
731 }
732
733 tmp = *arg;
734 tmp.asn = arg->asn;
vlmdae7f9d2004-08-22 03:25:24 +0000735 tmp.mod = extract->module;
vlmfa67ddc2004-06-03 03:38:44 +0000736 tmp.expr = extract;
737
738 ret = arg->default_cb(&tmp);
739
740 asn1p_expr_free(extract);
741
742 return ret;
743 }
744
745
746 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
747}
748
749int
750asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
751 asn1p_expr_t *expr = arg->expr;
vlm6e73a042004-08-11 07:17:22 +0000752 int tags_count;
vlm72425de2004-09-13 08:31:01 +0000753 int all_tags_count;
754 enum tvm_compat tv_mode;
vlmfa67ddc2004-06-03 03:38:44 +0000755 char *p;
756
757 if(arg->embed) {
758 REDIR(OT_TYPE_DECLS);
759
vlmb47f48e2004-09-17 06:32:12 +0000760 OUT("%s\t", asn1c_type_name(arg, arg->expr, TNF_CTYPE));
vlma02b74d2004-09-15 11:54:38 +0000761 OUT("%s", expr->marker.flags?"*":" ");
vlmdae7f9d2004-08-22 03:25:24 +0000762 OUT("%s", MKID(expr->Identifier));
vlma02b74d2004-09-15 11:54:38 +0000763 if((expr->marker.flags & EM_DEFAULT) == EM_DEFAULT)
764 OUT("\t/* DEFAULT %s */",
765 asn1f_printable_value(expr->marker.default_value));
766 else if((expr->marker.flags & EM_OPTIONAL) == EM_OPTIONAL)
vlmddd5a7d2004-09-10 09:18:20 +0000767 OUT("\t/* OPTIONAL */");
vlmb2839012004-08-20 13:37:01 +0000768
769 REDIR(OT_TYPE_DECLS);
vlmfa67ddc2004-06-03 03:38:44 +0000770 return 0;
771 }
772
vlmfa67ddc2004-06-03 03:38:44 +0000773
vlm33a4ff12004-08-11 05:21:32 +0000774 GEN_INCLUDE(asn1c_type_name(arg, expr, TNF_INCLUDE));
vlmfa67ddc2004-06-03 03:38:44 +0000775
776 REDIR(OT_TYPE_DECLS);
777
778 OUT("typedef %s\t", asn1c_type_name(arg, arg->expr, TNF_CTYPE));
vlma02b74d2004-09-15 11:54:38 +0000779 OUT("%s", expr->marker.flags?"*":" ");
vlmdae7f9d2004-08-22 03:25:24 +0000780 OUT("%s_t", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000781
782 REDIR(OT_STAT_DEFS);
783
vlm4a3f5822004-06-28 21:13:46 +0000784 /*
vlm72425de2004-09-13 08:31:01 +0000785 * Print out asn1_DEF_<type>_[all_]tags[] vectors.
vlm4a3f5822004-06-28 21:13:46 +0000786 */
vlm72425de2004-09-13 08:31:01 +0000787 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
vlmfa67ddc2004-06-03 03:38:44 +0000788
vlm72425de2004-09-13 08:31:01 +0000789 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, 0,
vlm4e554992004-08-25 02:03:12 +0000790 ETD_CP_UNKNOWN, ETD_NO_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000791
vlmb2839012004-08-20 13:37:01 +0000792 REDIR(OT_CODE);
793
vlmfa67ddc2004-06-03 03:38:44 +0000794 /*
795 * Constraint checking.
796 */
vlmfa67ddc2004-06-03 03:38:44 +0000797 p = MKID(expr->Identifier);
798 OUT("int\n");
799 OUT("%s_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,\n", p);
800 INDENTED(
801 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
802 OUT("\n");
vlm1d036692004-08-19 13:29:46 +0000803 if(asn1c_emit_constraint_checking_code(arg) == 1) {
804 if(0) {
vlmfa67ddc2004-06-03 03:38:44 +0000805 OUT("/* Check the constraints of the underlying type */\n");
806 OUT("return asn1_DEF_%s.check_constraints\n",
807 asn1c_type_name(arg, expr, TNF_SAFE));
808 OUT("\t(td, sptr, app_errlog, app_key);\n");
vlm1d036692004-08-19 13:29:46 +0000809 } else {
vlmfa67ddc2004-06-03 03:38:44 +0000810 OUT("/* Make the underlying type checker permanent */\n");
811 OUT("td->check_constraints = asn1_DEF_%s.check_constraints;\n",
812 asn1c_type_name(arg, expr, TNF_SAFE));
813 OUT("return td->check_constraints\n");
814 OUT("\t(td, sptr, app_errlog, app_key);\n");
vlm1d036692004-08-19 13:29:46 +0000815 }
vlmfa67ddc2004-06-03 03:38:44 +0000816 }
817 );
818 OUT("}\n");
819 OUT("\n");
820
821 /*
822 * Emit suicidal functions.
823 */
824
vlmfa67ddc2004-06-03 03:38:44 +0000825 /*
826 * This function replaces certain fields from the definition
827 * of a type with the corresponding fields from the basic type
828 * (from which the current type is inherited).
829 */
vlmfa67ddc2004-06-03 03:38:44 +0000830 OUT("/*\n");
vlmb2839012004-08-20 13:37:01 +0000831 OUT(" * This type is implemented using %s,\n",
832 asn1c_type_name(arg, expr, TNF_SAFE));
vlmfa67ddc2004-06-03 03:38:44 +0000833 OUT(" * so adjust the DEF appropriately.\n");
834 OUT(" */\n");
835 OUT("static void\n");
vlmb2839012004-08-20 13:37:01 +0000836 p = MKID(expr->Identifier);
837 OUT("%s_inherit_TYPE_descriptor(asn1_TYPE_descriptor_t *td) {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000838 INDENT(+1);
vlmb2839012004-08-20 13:37:01 +0000839 {
vlm39ba4c42004-09-22 16:06:28 +0000840 asn1p_expr_t *terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
vlmb2839012004-08-20 13:37:01 +0000841 char *type_name = asn1c_type_name(arg, expr, TNF_SAFE);
vlmb2839012004-08-20 13:37:01 +0000842 OUT("td->free_struct = asn1_DEF_%s.free_struct;\n", type_name);
843 OUT("td->print_struct = asn1_DEF_%s.print_struct;\n", type_name);
vlm39ba4c42004-09-22 16:06:28 +0000844 OUT("td->ber_decoder = asn1_DEF_%s.ber_decoder;\n", type_name);
845 OUT("td->der_encoder = asn1_DEF_%s.der_encoder;\n", type_name);
846 OUT("td->xer_decoder = asn1_DEF_%s.xer_decoder;\n", type_name);
847 OUT("td->xer_encoder = asn1_DEF_%s.xer_encoder;\n", type_name);
vlm1308d2b2004-09-10 15:49:15 +0000848 if(!terminal && !tags_count) {
vlm72425de2004-09-13 08:31:01 +0000849 OUT("/* The next four lines are here because of -fknown-extern-type */\n");
vlm1308d2b2004-09-10 15:49:15 +0000850 OUT("td->tags = asn1_DEF_%s.tags;\n", type_name);
851 OUT("td->tags_count = asn1_DEF_%s.tags_count;\n", type_name);
vlm72425de2004-09-13 08:31:01 +0000852 OUT("td->all_tags = asn1_DEF_%s.all_tags;\n", type_name);
853 OUT("td->all_tags_count = asn1_DEF_%s.all_tags_count;\n",type_name);
vlm1308d2b2004-09-10 15:49:15 +0000854 OUT("/* End of these lines */\n");
855 }
vlmb2839012004-08-20 13:37:01 +0000856 OUT("td->last_tag_form = asn1_DEF_%s.last_tag_form;\n", type_name);
857 OUT("td->elements = asn1_DEF_%s.elements;\n", type_name);
858 OUT("td->elements_count = asn1_DEF_%s.elements_count;\n", type_name);
859 OUT("td->specifics = asn1_DEF_%s.specifics;\n", type_name);
860 }
vlmfa67ddc2004-06-03 03:38:44 +0000861 INDENT(-1);
862 OUT("}\n");
863 OUT("\n");
vlmfa67ddc2004-06-03 03:38:44 +0000864
865 p = MKID(expr->Identifier);
vlm39ba4c42004-09-22 16:06:28 +0000866 OUT("void\n");
867 OUT("%s_free(asn1_TYPE_descriptor_t *td,\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000868 INDENTED(
vlm39ba4c42004-09-22 16:06:28 +0000869 OUT("\tvoid *struct_ptr, int contents_only) {\n");
vlmb2839012004-08-20 13:37:01 +0000870 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000871 OUT("td->free_struct(td, struct_ptr, contents_only);\n");
vlmfa67ddc2004-06-03 03:38:44 +0000872 );
873 OUT("}\n");
874 OUT("\n");
875
876 p = MKID(expr->Identifier);
877 OUT("int\n");
878 OUT("%s_print(asn1_TYPE_descriptor_t *td, const void *struct_ptr,\n", p);
879 INDENTED(
880 OUT("\tint ilevel, asn_app_consume_bytes_f *cb, void *app_key) {\n");
vlmb2839012004-08-20 13:37:01 +0000881 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000882 OUT("return td->print_struct(td, struct_ptr, ilevel, cb, app_key);\n");
883 );
884 OUT("}\n");
885 OUT("\n");
886
887 p = MKID(expr->Identifier);
vlm39ba4c42004-09-22 16:06:28 +0000888 OUT("ber_dec_rval_t\n");
889 OUT("%s_decode_ber(asn1_TYPE_descriptor_t *td,\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000890 INDENTED(
vlm39ba4c42004-09-22 16:06:28 +0000891 OUT("\tvoid **structure, void *bufptr, size_t size, int tag_mode) {\n");
vlmb2839012004-08-20 13:37:01 +0000892 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000893 OUT("return td->ber_decoder(td, structure, bufptr, size, tag_mode);\n");
894 );
895 OUT("}\n");
896 OUT("\n");
897
898 p = MKID(expr->Identifier);
899 OUT("asn_enc_rval_t\n");
900 OUT("%s_encode_der(asn1_TYPE_descriptor_t *td,\n", p);
901 INDENTED(
902 OUT("\tvoid *structure, int tag_mode, ber_tlv_tag_t tag,\n");
903 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
904 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
905 OUT("return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);\n");
906 );
907 OUT("}\n");
908 OUT("\n");
909
910 p = MKID(expr->Identifier);
911 OUT("asn_enc_rval_t\n");
912 OUT("%s_encode_xer(asn1_TYPE_descriptor_t *td, void *structure,\n", p);
913 INDENTED(
914 OUT("\tint ilevel, enum xer_encoder_flags_e flags,\n");
915 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
916 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
917 OUT("return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);\n");
vlmfa67ddc2004-06-03 03:38:44 +0000918 );
919 OUT("}\n");
920 OUT("\n");
921
922 REDIR(OT_FUNC_DECLS);
923
924 p = MKID(expr->Identifier);
vlm12c8f692004-09-06 08:07:29 +0000925 if(HIDE_INNER_DEFS) OUT("/* ");
926 OUT("extern asn1_TYPE_descriptor_t asn1_DEF_%s;", p);
927 if(HIDE_INNER_DEFS) OUT(" // (Use -fall-defs-global to expose) */");
928 OUT("\n");
vlm39ba4c42004-09-22 16:06:28 +0000929 OUT("asn_struct_free_f %s_free;\n", p);
930 OUT("asn_struct_print_f %s_print;\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000931 OUT("asn_constr_check_f %s_constraint;\n", p);
932 OUT("ber_type_decoder_f %s_decode_ber;\n", p);
933 OUT("der_type_encoder_f %s_encode_der;\n", p);
vlm39ba4c42004-09-22 16:06:28 +0000934 OUT("xer_type_encoder_f %s_encode_xer;\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000935
vlm33a4ff12004-08-11 05:21:32 +0000936 REDIR(OT_TYPE_DECLS);
937
vlmfa67ddc2004-06-03 03:38:44 +0000938 return 0;
939}
940
941int
942asn1c_lang_C_type_EXTENSIBLE(arg_t *arg) {
943
944 OUT("/*\n");
945 OUT(" * This type is extensible,\n");
946 OUT(" * possible extensions are below.\n");
947 OUT(" */\n");
948
949 return 0;
950}
951
vlm79b08d52004-07-01 00:52:50 +0000952static int check_if_extensible(asn1p_expr_t *expr) {
953 asn1p_expr_t *v;
954 TQ_FOR(v, &(expr->members), next) {
955 if(v->expr_type == A1TC_EXTENSIBLE) return 1;
956 }
957 return 0;
958}
959
vlmfa67ddc2004-06-03 03:38:44 +0000960static int
vlma8a86cc2004-09-10 06:07:18 +0000961_print_tag(arg_t *arg, struct asn1p_type_tag_s *tag) {
vlmfa67ddc2004-06-03 03:38:44 +0000962
963 OUT("(");
vlma8a86cc2004-09-10 06:07:18 +0000964 switch(tag->tag_class) {
vlmfa67ddc2004-06-03 03:38:44 +0000965 case TC_UNIVERSAL: OUT("ASN_TAG_CLASS_UNIVERSAL"); break;
966 case TC_APPLICATION: OUT("ASN_TAG_CLASS_APPLICATION"); break;
967 case TC_CONTEXT_SPECIFIC: OUT("ASN_TAG_CLASS_CONTEXT"); break;
968 case TC_PRIVATE: OUT("ASN_TAG_CLASS_PRIVATE"); break;
969 case TC_NOCLASS:
970 break;
971 }
vlma8a86cc2004-09-10 06:07:18 +0000972 OUT(" | (%lld << 2))", tag->tag_value);
vlmfa67ddc2004-06-03 03:38:44 +0000973
974 return 0;
975}
976
vlm4e03ce22004-06-06 07:20:17 +0000977
978static int
979_tag2el_cmp(const void *ap, const void *bp) {
980 const tag2el_t *a = ap;
981 const tag2el_t *b = bp;
982 const struct asn1p_type_tag_s *ta = &a->el_tag;
983 const struct asn1p_type_tag_s *tb = &b->el_tag;
984
985 if(ta->tag_class == tb->tag_class) {
986 if(ta->tag_value == tb->tag_value) {
987 /*
988 * Sort by their respective positions.
989 */
990 if(a->el_no < b->el_no)
991 return -1;
992 else if(a->el_no > b->el_no)
993 return 1;
994 return 0;
995 } else if(ta->tag_value < tb->tag_value)
996 return -1;
997 else
998 return 1;
999 } else if(ta->tag_class < tb->tag_class) {
1000 return -1;
1001 } else {
1002 return 1;
1003 }
1004}
1005
vlmfa67ddc2004-06-03 03:38:44 +00001006/*
1007 * For constructed types, number of external tags may be greater than
1008 * number of elements in the type because of CHOICE type.
1009 * T ::= SET { -- Three possible tags:
1010 * a INTEGER, -- One tag is here...
1011 * b Choice1 -- ... and two more tags are there.
1012 * }
1013 * Choice1 ::= CHOICE {
1014 * s1 IA5String,
1015 * s2 ObjectDescriptor
1016 * }
1017 */
1018static int
1019_fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no) {
1020 asn1p_expr_t *expr = arg->expr;
1021 arg_t tmparg = *arg;
1022 asn1p_expr_t *v;
1023 int element = 0;
1024
1025 TQ_FOR(v, &(expr->members), next) {
1026 if(v->expr_type == A1TC_EXTENSIBLE)
1027 continue;
1028
1029 tmparg.expr = v;
1030
1031 if(_add_tag2el_member(&tmparg, tag2el, count,
1032 (el_no==-1)?element:el_no)) {
1033 return -1;
1034 }
1035
1036 element++;
1037 }
1038
vlm4e03ce22004-06-06 07:20:17 +00001039 /*
vlmc8aeab42004-06-14 13:09:45 +00001040 * Sort the map according to canonical order of their tags
1041 * and element numbers.
vlm4e03ce22004-06-06 07:20:17 +00001042 */
1043 qsort(*tag2el, *count, sizeof(**tag2el), _tag2el_cmp);
1044
vlmc8aeab42004-06-14 13:09:45 +00001045 /*
1046 * Initialize .toff_{first|last} members.
1047 */
1048 if(*count) {
1049 struct asn1p_type_tag_s *cur_tag = 0;
1050 tag2el_t *cur = *tag2el;
1051 tag2el_t *end = cur + *count;
1052 int occur, i;
1053 for(occur = 0; cur < end; cur++) {
1054 if(cur_tag == 0
1055 || cur_tag->tag_value != cur->el_tag.tag_value
1056 || cur_tag->tag_class != cur->el_tag.tag_class) {
1057 cur_tag = &cur->el_tag;
1058 occur = 0;
1059 } else {
1060 occur++;
1061 }
1062 cur->toff_first = -occur;
1063 for(i = 0; i >= -occur; i--)
1064 cur[i].toff_last = -i;
1065 }
1066 }
1067
vlmfa67ddc2004-06-03 03:38:44 +00001068 return 0;
1069}
1070
1071static int
1072_add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no) {
1073 struct asn1p_type_tag_s tag;
1074 int ret;
1075
1076 assert(el_no >= 0);
1077
vlm39ba4c42004-09-22 16:06:28 +00001078 ret = asn1f_fetch_outmost_tag(arg->asn, arg->expr->module,
1079 arg->expr, &tag, 1);
vlmfa67ddc2004-06-03 03:38:44 +00001080 if(ret == 0) {
vlme2070ea2004-09-04 04:42:29 +00001081 tag2el_t *te;
1082 int new_count = (*count) + 1;
vlmfa67ddc2004-06-03 03:38:44 +00001083 void *p;
vlme2070ea2004-09-04 04:42:29 +00001084
vlm2de0e792004-09-05 10:42:33 +00001085 if(tag.tag_value == -1) {
1086 /*
1087 * This is an untagged ANY type,
1088 * proceed without adding a tag
1089 */
1090 return 0;
1091 }
1092
vlme2070ea2004-09-04 04:42:29 +00001093 p = realloc(*tag2el, new_count * sizeof(tag2el_t));
vlmfa67ddc2004-06-03 03:38:44 +00001094 if(p) *tag2el = p;
1095 else return -1;
1096
1097 DEBUG("Found tag for %s: %ld",
1098 arg->expr->Identifier,
1099 (long)tag.tag_value);
1100
vlme2070ea2004-09-04 04:42:29 +00001101 te = &((*tag2el)[*count]);
1102 te->el_tag = tag;
1103 te->el_no = el_no;
1104 te->from_expr = arg->expr;
1105 *count = new_count;
vlmfa67ddc2004-06-03 03:38:44 +00001106 return 0;
1107 }
1108
1109 DEBUG("Searching tag in complex expression %s:%x at line %d",
1110 arg->expr->Identifier,
1111 arg->expr->expr_type,
1112 arg->expr->_lineno);
1113
1114 /*
1115 * Iterate over members of CHOICE type.
1116 */
1117 if(arg->expr->expr_type == ASN_CONSTR_CHOICE) {
1118 return _fill_tag2el_map(arg, tag2el, count, el_no);
1119 }
1120
1121 if(arg->expr->expr_type == A1TC_REFERENCE) {
1122 arg_t tmp = *arg;
1123 asn1p_expr_t *expr;
vlmdae7f9d2004-08-22 03:25:24 +00001124 expr = asn1f_lookup_symbol_ex(tmp.asn, tmp.mod, tmp.expr,
vlmfa67ddc2004-06-03 03:38:44 +00001125 arg->expr->reference);
1126 if(expr) {
vlmdae7f9d2004-08-22 03:25:24 +00001127 tmp.mod = expr->module;
vlmfa67ddc2004-06-03 03:38:44 +00001128 tmp.expr = expr;
1129 return _add_tag2el_member(&tmp, tag2el, count, el_no);
1130 } else {
1131 FATAL("Cannot dereference %s at line %d",
1132 arg->expr->Identifier,
1133 arg->expr->_lineno);
1134 return -1;
1135 }
1136 }
1137
1138 DEBUG("No tag for %s at line %d",
1139 arg->expr->Identifier,
1140 arg->expr->_lineno);
1141
1142 return -1;
1143}
1144
1145static int
vlm4e03ce22004-06-06 07:20:17 +00001146emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count) {
1147 asn1p_expr_t *expr = arg->expr;
1148
1149 OUT("static asn1_TYPE_tag2member_t asn1_DEF_%s_tag2el[] = {\n",
1150 MKID(expr->Identifier));
1151 if(tag2el_count) {
1152 int i;
1153 for(i = 0; i < tag2el_count; i++) {
1154 OUT(" { ");
vlma8a86cc2004-09-10 06:07:18 +00001155 _print_tag(arg, &tag2el[i].el_tag);
vlm4e03ce22004-06-06 07:20:17 +00001156 OUT(", ");
vlmc8aeab42004-06-14 13:09:45 +00001157 OUT("%d, ", tag2el[i].el_no);
1158 OUT("%d, ", tag2el[i].toff_first);
1159 OUT("%d ", tag2el[i].toff_last);
vlm4e03ce22004-06-06 07:20:17 +00001160 OUT("}, /* %s at %d */\n",
1161 tag2el[i].from_expr->Identifier,
1162 tag2el[i].from_expr->_lineno
1163 );
1164 }
1165 }
1166 OUT("};\n");
1167
1168 return 0;;
1169}
1170
vlm72425de2004-09-13 08:31:01 +00001171static enum tvm_compat
1172emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tags_count_r, int *all_tags_count_r) {
1173 struct asn1p_type_tag_s *tags = 0; /* Effective tags */
1174 struct asn1p_type_tag_s *all_tags = 0; /* The full array */
vlm6e73a042004-08-11 07:17:22 +00001175 int tags_count = 0;
vlm72425de2004-09-13 08:31:01 +00001176 int all_tags_count = 0;
1177 enum tvm_compat tv_mode = _TVM_SAME;
vlm1308d2b2004-09-10 15:49:15 +00001178 int i;
vlm4a3f5822004-06-28 21:13:46 +00001179
vlmc6de2c42004-09-14 14:10:10 +00001180 /* Cleanup before proceeding. */
1181 *tags_count_r = 0;
1182 *all_tags_count_r = 0;
1183
vlm1308d2b2004-09-10 15:49:15 +00001184 /* Fetch a chain of tags */
vlm39ba4c42004-09-22 16:06:28 +00001185 tags_count = asn1f_fetch_tags(arg->asn, expr->module, expr, &tags, 0);
vlmc6de2c42004-09-14 14:10:10 +00001186 if(tags_count < 0)
1187 return -1;
vlm6e73a042004-08-11 07:17:22 +00001188
vlm72425de2004-09-13 08:31:01 +00001189 /* Fetch a chain of tags */
vlm39ba4c42004-09-22 16:06:28 +00001190 all_tags_count = asn1f_fetch_tags(arg->asn, expr->module, expr,
vlm72425de2004-09-13 08:31:01 +00001191 &all_tags, AFT_FULL_COLLECT);
1192 if(all_tags_count < 0) {
1193 if(tags) free(tags);
1194 return -1;
vlmfb41dbb2004-09-08 00:28:57 +00001195 }
vlm1308d2b2004-09-10 15:49:15 +00001196
vlm72425de2004-09-13 08:31:01 +00001197 assert(tags_count <= all_tags_count);
1198 assert((tags_count?0:1) == (all_tags_count?0:1));
vlm4a3f5822004-06-28 21:13:46 +00001199
vlm72425de2004-09-13 08:31:01 +00001200 if(tags_count <= all_tags_count) {
1201 for(i = 0; i < tags_count; i++) {
1202 if(tags[i].tag_value != all_tags[i].tag_value
1203 || tags[i].tag_class != all_tags[i].tag_class) {
1204 tv_mode = _TVM_DIFFERENT;
1205 break;
1206 }
1207 }
1208 if(i == tags_count && tags_count < all_tags_count)
1209 tv_mode = _TVM_SUBSET;
1210 } else {
1211 tv_mode = _TVM_DIFFERENT;
1212 }
1213
1214#define EMIT_TAGS_TABLE(name, tags, tags_count) do { \
1215 OUT("static ber_tlv_tag_t asn1_DEF_%s%s_tags[] = {\n", \
1216 MKID(expr->Identifier), name); \
1217 INDENT(+1); \
1218 /* Print the array of collected tags */ \
1219 for(i = 0; i < tags_count; i++) { \
1220 if(i) OUT(",\n"); \
1221 _print_tag(arg, &tags[i]); \
1222 } \
1223 OUT("\n"); \
1224 INDENT(-1); \
1225 OUT("};\n"); \
1226 } while(0)
1227
1228 if(tags_count) {
1229 if(tv_mode == _TVM_SUBSET)
1230 EMIT_TAGS_TABLE("", all_tags, all_tags_count);
1231 else
1232 EMIT_TAGS_TABLE("", tags, tags_count);
1233 }
1234
1235 if(all_tags_count) {
1236 if(tv_mode == _TVM_DIFFERENT)
1237 EMIT_TAGS_TABLE("_all", all_tags, all_tags_count);
1238 }
1239
1240 if(tags) free(tags);
1241 if(all_tags) free(all_tags);
1242
1243 *tags_count_r = tags_count;
1244 *all_tags_count_r = all_tags_count;
1245
1246 return tv_mode;
vlm4a3f5822004-06-28 21:13:46 +00001247}
vlmb2839012004-08-20 13:37:01 +00001248
1249static int
vlm4e554992004-08-25 02:03:12 +00001250expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
vlmb2839012004-08-20 13:37:01 +00001251 asn1p_expr_t *topmost_parent;
1252 asn1p_expr_t *v;
1253 int elements = 0;
1254
vlm39ba4c42004-09-22 16:06:28 +00001255 topmost_parent = asn1f_find_terminal_type_ex(arg->asn, expr);
vlmb2839012004-08-20 13:37:01 +00001256 if(!topmost_parent) return 0;
1257
1258 if(!(topmost_parent->expr_type & ASN_CONSTR_MASK))
1259 return 0;
1260
1261 TQ_FOR(v, &(topmost_parent->members), next) {
1262 if(v->expr_type != A1TC_EXTENSIBLE)
1263 elements++;
1264 }
1265
1266 return elements;
1267}
1268
1269static int
vlm4e554992004-08-25 02:03:12 +00001270emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
vlmdae7f9d2004-08-22 03:25:24 +00001271 static int global_memb_unique;
vlmb2839012004-08-20 13:37:01 +00001272 int save_target;
1273 arg_t tmp_arg;
vlm060fe2a2004-09-10 09:37:12 +00001274 struct asn1p_type_tag_s outmost_tag_s;
1275 struct asn1p_type_tag_s *outmost_tag;
vlmb2839012004-08-20 13:37:01 +00001276 char *p;
1277
vlm060fe2a2004-09-10 09:37:12 +00001278 if(asn1f_fetch_outmost_tag(arg->asn,
1279 expr->module, expr, &outmost_tag_s, 1)) {
1280 outmost_tag = 0;
1281 } else {
1282 outmost_tag = &outmost_tag_s;
1283 }
1284
vlmb2839012004-08-20 13:37:01 +00001285 OUT("{ ");
vlm060fe2a2004-09-10 09:37:12 +00001286
1287 if(outmost_tag && outmost_tag->tag_value == -1)
1288 OUT("ATF_OPEN_TYPE | ");
vlma02b74d2004-09-15 11:54:38 +00001289 OUT("%s, ", expr->marker.flags?"ATF_POINTER":"ATF_NOFLAGS");
1290 if((expr->marker.flags & EM_OPTIONAL) == EM_OPTIONAL) {
vlmb2839012004-08-20 13:37:01 +00001291 asn1p_expr_t *tv;
1292 int opts = 0;
vlma02b74d2004-09-15 11:54:38 +00001293 for(tv = expr; tv && tv->marker.flags;
vlmb2839012004-08-20 13:37:01 +00001294 tv = TQ_NEXT(tv, next), opts++) {
1295 if(tv->expr_type == A1TC_EXTENSIBLE)
1296 opts--;
1297 }
1298 OUT("%d, ", opts);
1299 } else {
1300 OUT("0, ");
1301 }
vlm39ba4c42004-09-22 16:06:28 +00001302 if(expr->_anonymous_type) {
1303 assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
1304 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
1305 OUT("0,\n");
1306 } else {
vlmb2839012004-08-20 13:37:01 +00001307 OUT("offsetof(struct %s, ", MKID(arg->expr->Identifier));
1308 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1309 && (!UNNAMED_UNIONS)) OUT("choice.");
1310 OUT("%s),\n", MKID(expr->Identifier));
vlmb2839012004-08-20 13:37:01 +00001311 }
1312 INDENT(+1);
1313 if(C99_MODE) OUT(".tag = ");
vlm060fe2a2004-09-10 09:37:12 +00001314 if(outmost_tag) {
1315 if(outmost_tag->tag_value == -1)
1316 OUT("-1 /* Ambiguous tag (ANY?) */");
1317 else
1318 _print_tag(arg, outmost_tag);
vlma8a86cc2004-09-10 06:07:18 +00001319 } else {
vlm060fe2a2004-09-10 09:37:12 +00001320 OUT("-1 /* Ambiguous tag (CHOICE?) */");
vlma8a86cc2004-09-10 06:07:18 +00001321 }
vlm060fe2a2004-09-10 09:37:12 +00001322
vlmb2839012004-08-20 13:37:01 +00001323 OUT(",\n");
1324 if(C99_MODE) OUT(".tag_mode = ");
1325 if(expr->tag.tag_class) {
1326 if(expr->tag.tag_mode == TM_IMPLICIT)
1327 OUT("-1,\t/* IMPLICIT tag at current level */\n");
1328 else
1329 OUT("+1,\t/* EXPLICIT tag at current level */\n");
1330 } else {
1331 OUT("0,\n");
1332 }
1333 if(C99_MODE) OUT(".type = ");
vlm39ba4c42004-09-22 16:06:28 +00001334 if(expr->_anonymous_type && (expr->expr_type & ASN_CONSTR_MASK)) {
vlmdae7f9d2004-08-22 03:25:24 +00001335 OUT("(void *)&asn1_DEF_%s_member,\n",
1336 MKID(arg->expr->Identifier));
vlm4e554992004-08-25 02:03:12 +00001337 } else if(expr->expr_type & ASN_CONSTR_MASK) {
1338 OUT("(void *)&asn1_DEF_%s,\n",
1339 MKID(expr->Identifier));
vlmdae7f9d2004-08-22 03:25:24 +00001340 } else {
1341 OUT("(void *)&asn1_DEF_%s,\n",
1342 asn1c_type_name(arg, expr, TNF_SAFE));
1343 }
vlmb2839012004-08-20 13:37:01 +00001344 if(C99_MODE) OUT(".memb_constraints = ");
1345 if(expr->constraints) {
vlm4e554992004-08-25 02:03:12 +00001346 char *id = MKID(expr->Identifier);
vlm39ba4c42004-09-22 16:06:28 +00001347 if(expr->_anonymous_type && !strcmp(expr->Identifier, "member"))
vlm4e554992004-08-25 02:03:12 +00001348 id = asn1c_type_name(arg, expr, TNF_SAFE);
1349 OUT("memb_%s_%d_constraint,\n", id,
vlmdae7f9d2004-08-22 03:25:24 +00001350 ++global_memb_unique);
vlmb2839012004-08-20 13:37:01 +00001351 } else {
1352 OUT("0,\t/* Defer to actual type */\n");
1353 }
1354 if(C99_MODE) OUT(".name = ");
vlm39ba4c42004-09-22 16:06:28 +00001355 OUT("\"%s\"\n", expr->_anonymous_type ? "" : expr->Identifier);
vlmb2839012004-08-20 13:37:01 +00001356 OUT("},\n");
1357 INDENT(-1);
1358
1359 if(!expr->constraints)
1360 return 0;
1361
1362 save_target = arg->target->target;
1363 REDIR(OT_CODE);
1364
vlm39ba4c42004-09-22 16:06:28 +00001365 if(expr->_anonymous_type && !strcmp(expr->Identifier, "member"))
vlmb2839012004-08-20 13:37:01 +00001366 p = asn1c_type_name(arg, expr, TNF_SAFE);
vlm39ba4c42004-09-22 16:06:28 +00001367 else
1368 p = MKID(expr->Identifier);
vlmb2839012004-08-20 13:37:01 +00001369 OUT("static int\n");
vlmdae7f9d2004-08-22 03:25:24 +00001370 OUT("memb_%s_%d_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,\n", p, global_memb_unique);
vlmb2839012004-08-20 13:37:01 +00001371 INDENT(+1);
1372 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
1373 tmp_arg = *arg;
1374 tmp_arg.expr = expr;
1375 if(asn1c_emit_constraint_checking_code(&tmp_arg) == 1) {
1376 OUT("return td->check_constraints\n");
1377 OUT("\t(td, sptr, app_errlog, app_key);\n");
1378 }
1379 INDENT(-1);
1380 OUT("}\n");
1381 OUT("\n");
1382
1383 REDIR(save_target);
1384
1385 return 0;
1386}
vlm4e554992004-08-25 02:03:12 +00001387
1388static int
vlm72425de2004-09-13 08:31:01 +00001389emit_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_cp cp, enum etd_spec spec) {
vlm4e554992004-08-25 02:03:12 +00001390 char *p;
1391
1392 p = MKID(expr->Identifier);
vlm12c8f692004-09-06 08:07:29 +00001393 if(HIDE_INNER_DEFS)
1394 OUT("static /* Use -fall-defs-global to expose */\n");
vlm4e554992004-08-25 02:03:12 +00001395 OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
vlm72425de2004-09-13 08:31:01 +00001396 INDENT(+1);
vlm4e554992004-08-25 02:03:12 +00001397 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
1398
1399 if(expr->expr_type & ASN_CONSTR_MASK) {
1400 p = asn1c_type_name(arg, arg->expr, TNF_SAFE);
1401 }
1402
vlm39ba4c42004-09-22 16:06:28 +00001403 OUT("%s_free,\n", p);
1404 OUT("%s_print,\n", p);
vlm4e554992004-08-25 02:03:12 +00001405 OUT("%s_constraint,\n", p);
1406 OUT("%s_decode_ber,\n", p);
1407 OUT("%s_encode_der,\n", p);
vlm39ba4c42004-09-22 16:06:28 +00001408 OUT("0, /* Not implemented yet */\n");
1409 OUT("%s_encode_xer,\n", p);
vlm4e554992004-08-25 02:03:12 +00001410
1411 p = MKID(expr->Identifier);
1412
1413 if(expr->expr_type == ASN_CONSTR_CHOICE) {
1414 OUT("CHOICE_outmost_tag,\n");
1415 } else {
1416 OUT("0,\t/* Use generic outmost tag fetcher */\n");
1417 }
1418
1419 if(tags_count) {
1420 OUT("asn1_DEF_%s_tags,\n", p);
1421 OUT("sizeof(asn1_DEF_%s_tags)\n", p);
vlm72425de2004-09-13 08:31:01 +00001422 OUT("\t/sizeof(asn1_DEF_%s_tags[0])", p);
1423 if(tv_mode == _TVM_SUBSET
1424 && tags_count != all_tags_count)
1425 OUT(" - %d", all_tags_count - tags_count);
1426 OUT(", /* %d */\n", tags_count);
vlm4e554992004-08-25 02:03:12 +00001427 } else {
vlm72425de2004-09-13 08:31:01 +00001428 OUT("0,\t/* No effective tags (pointer) */\n");
1429 OUT("0,\t/* No effective tags (count) */\n");
1430 }
1431
1432 if(all_tags_count && tv_mode == _TVM_DIFFERENT) {
1433 OUT("asn1_DEF_%s_all_tags,\n", p);
1434 OUT("sizeof(asn1_DEF_%s_all_tags)\n", p);
1435 OUT("\t/sizeof(asn1_DEF_%s_all_tags[0]), /* %d */\n",
1436 p, all_tags_count);
1437 } else if(all_tags_count) {
1438 OUT("asn1_DEF_%s_tags,\t/* Same as above */\n", p);
1439 OUT("sizeof(asn1_DEF_%s_tags)\n", p);
1440 OUT("\t/sizeof(asn1_DEF_%s_tags[0]), /* %d */\n",
1441 p, all_tags_count);
1442 } else {
1443 OUT("0,\t/* No tags (pointer) */\n");
1444 OUT("0,\t/* No tags (count) */\n");
vlm4e554992004-08-25 02:03:12 +00001445 }
1446
vlm4e554992004-08-25 02:03:12 +00001447 switch(cp) {
1448 case ETD_CP_UNKNOWN:
1449 OUT("-0,\t/* Unknown yet */\n");
1450 break;
1451 case ETD_CP_EITHER:
1452 OUT("-1,\t/* Primitive or constructed */\n");
1453 case ETD_CP_PRIMITIVE:
1454 OUT("0,\t/* Primitive */\n");
1455 break;
1456 case ETD_CP_CONSTRUCTED:
1457 OUT("1,\t/* Whether CONSTRUCTED */\n");
1458 break;
1459 }
1460
1461 if(elements_count) {
1462 OUT("asn1_MBR_%s,\n", p);
1463 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF
1464 || expr->expr_type == ASN_CONSTR_SET_OF) {
1465 OUT("%d,\t/* Single element */\n",
1466 elements_count);
1467 assert(elements_count == 1);
1468 } else {
1469 OUT("%d,\t/* Elements count */\n",
1470 elements_count);
1471 }
1472 } else {
1473 //if(expr->meta_type == AMT_TYPEREF)
1474 if(expr_elements_count(arg, expr))
1475 OUT("0, 0,\t/* Defined elsewhere */\n");
1476 else
1477 OUT("0, 0,\t/* No members */\n");
1478 }
1479
1480 switch(spec) {
1481 case ETD_NO_SPECIFICS:
1482 OUT("0\t/* No specifics */\n");
1483 break;
1484 case ETD_HAS_SPECIFICS:
1485 OUT("&asn1_DEF_%s_specs\t/* Additional specs */\n", p);
1486 }
vlm72425de2004-09-13 08:31:01 +00001487 INDENT(-1);
vlm4e554992004-08-25 02:03:12 +00001488 OUT("};\n");
1489 OUT("\n");
vlme2bb4432004-08-26 06:20:34 +00001490
1491 return 0;
vlm4e554992004-08-25 02:03:12 +00001492}
vlmddd5a7d2004-09-10 09:18:20 +00001493
1494/*
1495 * Check if it is better to make this type indirectly accessed via
1496 * a pointer.
1497 * This may be the case for the following recursive definition:
1498 * Type ::= CHOICE { member Type };
1499 */
1500static int
1501expr_better_indirect(arg_t *arg, asn1p_expr_t *expr) {
1502 asn1p_expr_t *top_parent;
1503 asn1p_expr_t *terminal;
1504
1505 if(expr->expr_type != A1TC_REFERENCE)
1506 return 0;
1507
1508 /* Rewind to the topmost parent expression */
1509 if((top_parent = expr->parent_expr)) {
1510 while(top_parent->parent_expr)
1511 top_parent = top_parent->parent_expr;
1512 } else {
1513 return 0;
1514 }
1515
vlm39ba4c42004-09-22 16:06:28 +00001516 terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
vlmddd5a7d2004-09-10 09:18:20 +00001517
1518 return (terminal == top_parent);
1519}
vlm39ba4c42004-09-22 16:06:28 +00001520
1521static int
1522expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr) {
1523 expr = asn1f_find_terminal_type_ex(arg->asn, expr);
1524 if(!expr) return 0;
1525
1526 /* X.680, 25.5, Table 5 */
1527 switch(expr->expr_type) {
1528 case ASN_CONSTR_CHOICE:
1529 case ASN_BASIC_BOOLEAN:
1530 case ASN_BASIC_ENUMERATED:
1531 case ASN_BASIC_NULL:
1532 return 1;
1533 default:
1534 return 0;
1535 }
1536}