blob: 485e990aa8953adea97aee46550aa4e6774a9210 [file] [log] [blame]
Lev Walkinf15320b2004-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"
Lev Walkin84cd58e2004-08-19 13:29:46 +00007#include "asn1c_constraint.h"
Lev Walkin59004fa2004-08-20 13:37:01 +00008#include "asn1c_out.h"
9#include "asn1c_misc.h"
Lev Walkin84cd58e2004-08-19 13:29:46 +000010#include <asn1fix_export.h> /* Stuff exported by libasn1fix */
Lev Walkinf15320b2004-06-03 03:38:44 +000011
Lev Walkinfd171ef2004-06-06 07:20:17 +000012typedef struct tag2el_s {
13 struct asn1p_type_tag_s el_tag;
14 int el_no;
Lev Walkin38abe792004-06-14 13:09:45 +000015 int toff_first;
16 int toff_last;
Lev Walkinfd171ef2004-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
Lev Walkinf15320b2004-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);
Lev Walkinc3e29402004-09-10 06:07:18 +000027static int _print_tag(arg_t *arg, struct asn1p_type_tag_s *tag_p);
Lev Walkin35631482004-07-01 00:52:50 +000028static int check_if_extensible(asn1p_expr_t *expr);
Lev Walkincc93b0f2004-09-10 09:18:20 +000029static int expr_better_indirect(arg_t *arg, asn1p_expr_t *expr);
Lev Walkin59964be2004-08-25 02:03:12 +000030static int expr_elements_count(arg_t *arg, asn1p_expr_t *expr);
31static int emit_member_table(arg_t *arg, asn1p_expr_t *expr);
Lev Walkinfd171ef2004-06-06 07:20:17 +000032static int emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count);
Lev Walkinf15320b2004-06-03 03:38:44 +000033
Lev Walkin188ed2c2004-09-13 08:31:01 +000034enum tvm_compat {
35 _TVM_SAME = 0, /* tags and all_tags are same */
36 _TVM_SUBSET = 1, /* tags are subset of all_tags */
37 _TVM_DIFFERENT = 2, /* tags and all_tags are different */
38};
39static enum tvm_compat emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tc, int *atc);
40
Lev Walkin59964be2004-08-25 02:03:12 +000041enum etd_cp {
42 ETD_CP_UNKNOWN = -2,
43 ETD_CP_EITHER = -1,
44 ETD_CP_PRIMITIVE = 0,
45 ETD_CP_CONSTRUCTED = 1,
46};
47enum etd_spec {
48 ETD_NO_SPECIFICS,
49 ETD_HAS_SPECIFICS
50};
Lev Walkin188ed2c2004-09-13 08:31:01 +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_cp, enum etd_spec);
Lev Walkin59964be2004-08-25 02:03:12 +000052
Lev Walkin59004fa2004-08-20 13:37:01 +000053#define C99_MODE (!(arg->flags & A1C_NO_C99))
Lev Walkinf15320b2004-06-03 03:38:44 +000054#define UNNAMED_UNIONS (arg->flags & A1C_UNNAMED_UNIONS)
Lev Walkindd32b592004-09-06 08:07:29 +000055#define HIDE_INNER_DEFS (arg->embed && !(arg->flags & A1C_ALL_DEFS_GLOBAL))
Lev Walkinf15320b2004-06-03 03:38:44 +000056
57#define PCTX_DEF INDENTED( \
58 OUT("\n"); \
59 OUT("/* Context for parsing across buffer boundaries */\n"); \
60 OUT("ber_dec_ctx_t _ber_dec_ctx;\n"));
61
Lev Walkin3dcaafa2004-08-11 05:21:32 +000062#define DEPENDENCIES do { \
Lev Walkin08079b02004-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, \
69 __m, TNF_INCLUDE)); \
Lev Walkin3dcaafa2004-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)
Lev Walkinf15320b2004-06-03 03:38:44 +000077
78#define MKID(id) asn1c_make_identifier(0, (id), 0)
79
80int
81asn1c_lang_C_type_ENUMERATED(arg_t *arg) {
82 asn1p_expr_t *expr = arg->expr;
83 asn1p_expr_t *v;
84
85 REDIR(OT_DEPS);
86
87 OUT("typedef enum %s {\n", MKID(expr->Identifier));
88 TQ_FOR(v, &(expr->members), next) {
89 switch(v->expr_type) {
90 case A1TC_UNIVERVAL:
91 OUT("\t%s\t= %lld,\n",
92 asn1c_make_identifier(0,
93 expr->Identifier,
94 v->Identifier, 0),
95 v->value->value.v_integer);
96 break;
97 case A1TC_EXTENSIBLE:
98 OUT("\t/*\n");
99 OUT("\t * Enumeration is extensible\n");
100 OUT("\t */\n");
101 break;
102 default:
103 return -1;
104 }
105 }
106 OUT("} %s_e;\n", MKID(expr->Identifier));
107
108 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
109}
110
111
112int
113asn1c_lang_C_type_INTEGER(arg_t *arg) {
114 asn1p_expr_t *expr = arg->expr;
115 asn1p_expr_t *v;
116
117 REDIR(OT_DEPS);
118
119 if(TQ_FIRST(&(expr->members))) {
120 OUT("typedef enum %s {\n", MKID(expr->Identifier));
121 TQ_FOR(v, &(expr->members), next) {
122 switch(v->expr_type) {
123 case A1TC_UNIVERVAL:
124 OUT("\t%s\t= %lld,\n",
125 asn1c_make_identifier(0,
126 expr->Identifier,
127 v->Identifier, 0),
128 v->value->value.v_integer);
129 break;
130 default:
131 return -1;
132 }
133 }
134 OUT("} %s_e;\n", MKID(expr->Identifier));
135 }
136
137 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
138}
139
140int
141asn1c_lang_C_type_SEQUENCE(arg_t *arg) {
142 asn1p_expr_t *expr = arg->expr;
143 asn1p_expr_t *v;
144 int comp_mode = 0; /* {root,ext=1,root,root,...} */
145
146 DEPENDENCIES;
147
148 if(arg->embed) {
Lev Walkin08079b02004-08-22 03:25:24 +0000149 OUT("struct %s {\n", MKID(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +0000150 } else {
151 OUT("typedef struct %s {\n",
152 MKID(expr->Identifier));
153 }
154
155 TQ_FOR(v, &(expr->members), next) {
156 if(v->expr_type == A1TC_EXTENSIBLE) {
157 if(comp_mode < 3) comp_mode++;
158 }
Lev Walkincc93b0f2004-09-10 09:18:20 +0000159 if(comp_mode == 1
160 || expr_better_indirect(arg, v))
161 v->marker |= EM_INDIRECT;
Lev Walkinf15320b2004-06-03 03:38:44 +0000162 EMBED(v);
163 }
164
165 PCTX_DEF;
Lev Walkin08079b02004-08-22 03:25:24 +0000166 OUT("} %s%s%s", expr->marker?"*":"",
167 expr->_anonymous_type ? "" : MKID(expr->Identifier),
168 arg->embed ? "" : "_t");
Lev Walkinf15320b2004-06-03 03:38:44 +0000169
170 return asn1c_lang_C_type_SEQUENCE_def(arg);
171}
172
173static int
174asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
175 asn1p_expr_t *expr = arg->expr;
176 asn1p_expr_t *v;
177 int elements; /* Number of elements */
Lev Walkinf15320b2004-06-03 03:38:44 +0000178 int comp_mode = 0; /* {root,ext=1,root,root,...} */
179 int ext_start = -1;
180 int ext_stop = -1;
Lev Walkinfd171ef2004-06-06 07:20:17 +0000181 tag2el_t *tag2el = NULL;
182 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000183 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000184 int all_tags_count;
185 enum tvm_compat tv_mode;
Lev Walkinf15320b2004-06-03 03:38:44 +0000186 char *p;
187
Lev Walkinfd171ef2004-06-06 07:20:17 +0000188 /*
189 * Fetch every inner tag from the tag to elements map.
190 */
191 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
192 if(tag2el) free(tag2el);
193 return -1;
194 }
195
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000196 GEN_INCLUDE("constr_SEQUENCE");
197 if(!arg->embed)
198 GEN_DECLARE(expr); /* asn1_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000199
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000200 REDIR(OT_STAT_DEFS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000201
202 /*
203 * Print out the table according to which the parsing is performed.
204 */
205 p = MKID(expr->Identifier);
Lev Walkin59004fa2004-08-20 13:37:01 +0000206 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000207
208 elements = 0;
209 INDENTED(TQ_FOR(v, &(expr->members), next) {
210 if(v->expr_type == A1TC_EXTENSIBLE) {
211 if((++comp_mode) == 1)
212 ext_start = elements - 1;
213 else
214 ext_stop = elements - 1;
215 continue;
216 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000217 elements++;
Lev Walkin59964be2004-08-25 02:03:12 +0000218 emit_member_table(arg, v);
Lev Walkinf15320b2004-06-03 03:38:44 +0000219 });
220 OUT("};\n");
221
Lev Walkin27ea3802004-06-28 21:13:46 +0000222 /*
Lev Walkin188ed2c2004-09-13 08:31:01 +0000223 * Print out asn1_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +0000224 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000225 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000226
Lev Walkinfd171ef2004-06-06 07:20:17 +0000227 /*
228 * Tags to elements map.
229 */
230 emit_tag2member_map(arg, tag2el, tag2el_count);
231
Lev Walkin27ea3802004-06-28 21:13:46 +0000232 p = MKID(expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000233 OUT("static asn1_SEQUENCE_specifics_t asn1_DEF_%s_specs = {\n", p);
234 INDENTED(
235 OUT("sizeof(struct %s),\n", p);
236 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
Lev Walkinfd171ef2004-06-06 07:20:17 +0000237 OUT("asn1_DEF_%s_tag2el,\n", p);
238 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000239 OUT("%d,\t/* Start extensions */\n",
240 ext_start);
241 OUT("%d\t/* Stop extensions */\n",
242 (ext_stop<ext_start)?elements+1:ext_stop, ext_stop);
243 );
244 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000245
246 /*
247 * Emit asn1_DEF_xxx table.
248 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000249 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
Lev Walkin59964be2004-08-25 02:03:12 +0000250 ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000251
Lev Walkinf15320b2004-06-03 03:38:44 +0000252 REDIR(OT_TYPE_DECLS);
253
254 return 0;
255}
256
257int
Lev Walkinf15320b2004-06-03 03:38:44 +0000258asn1c_lang_C_type_SET(arg_t *arg) {
259 asn1p_expr_t *expr = arg->expr;
260 asn1p_expr_t *v;
261 long mcount;
262 char *id;
263 int comp_mode = 0; /* {root,ext=1,root,root,...} */
264
265 DEPENDENCIES;
266
267 REDIR(OT_DEPS);
268
269 OUT("\n");
270 OUT("/*\n");
271 OUT(" * Method of determining the components presence\n");
272 OUT(" */\n");
273 mcount = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000274 OUT("typedef enum %s_PR {\n", MKID(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +0000275 TQ_FOR(v, &(expr->members), next) {
276 if(v->expr_type == A1TC_EXTENSIBLE) continue;
277 INDENTED(
278 id = MKID(expr->Identifier);
279 OUT("%s_PR_", id);
280 id = MKID(v->Identifier);
281 OUT("%s,\t/* Member %s is present */\n",
282 id, id)
283 );
284 mcount++;
285 }
Lev Walkin64399722004-08-11 07:17:22 +0000286 id = MKID(expr->Identifier);
287 OUT("} %s_PR;\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000288
289 REDIR(OT_TYPE_DECLS);
290
291 if(arg->embed) {
Lev Walkin64399722004-08-11 07:17:22 +0000292 OUT("struct %s {\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000293 } else {
Lev Walkin64399722004-08-11 07:17:22 +0000294 OUT("typedef struct %s {\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000295 }
296
297 TQ_FOR(v, &(expr->members), next) {
298 if(v->expr_type == A1TC_EXTENSIBLE) {
299 if(comp_mode < 3) comp_mode++;
300 }
Lev Walkincc93b0f2004-09-10 09:18:20 +0000301 if(comp_mode == 1
302 || expr_better_indirect(arg, v))
303 v->marker |= EM_INDIRECT;
Lev Walkinf15320b2004-06-03 03:38:44 +0000304 EMBED(v);
305 }
306
307 INDENTED(
308 id = MKID(expr->Identifier);
309 OUT("\n");
310 OUT("/* Presence bitmask: ASN_SET_ISPRESENT(p%s, %s_PR_x) */\n",
311 id, id);
312 OUT("unsigned int _presence_map\n");
313 OUT("\t[((%ld+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))];\n", mcount);
314 );
315
316 PCTX_DEF;
Lev Walkin08079b02004-08-22 03:25:24 +0000317 OUT("} %s%s%s", expr->marker?"*":"",
318 expr->_anonymous_type ? "" : MKID(expr->Identifier),
319 arg->embed ? "" : "_t");
Lev Walkinf15320b2004-06-03 03:38:44 +0000320
321 return asn1c_lang_C_type_SET_def(arg);
322}
323
Lev Walkinf15320b2004-06-03 03:38:44 +0000324static int
325asn1c_lang_C_type_SET_def(arg_t *arg) {
326 asn1p_expr_t *expr = arg->expr;
327 asn1p_expr_t *v;
328 int elements;
Lev Walkinf15320b2004-06-03 03:38:44 +0000329 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Lev Walkinf15320b2004-06-03 03:38:44 +0000330 tag2el_t *tag2el = NULL;
331 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000332 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000333 int all_tags_count;
334 enum tvm_compat tv_mode;
Lev Walkinf15320b2004-06-03 03:38:44 +0000335 char *p;
336
337 /*
338 * Fetch every inner tag from the tag to elements map.
339 */
340 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
341 if(tag2el) free(tag2el);
342 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000343 }
344
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000345 GEN_INCLUDE("constr_SET");
346 if(!arg->embed)
347 GEN_DECLARE(expr); /* asn1_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000348
349 REDIR(OT_STAT_DEFS);
350
Lev Walkinf15320b2004-06-03 03:38:44 +0000351 /*
352 * Print out the table according to which the parsing is performed.
353 */
354 p = MKID(expr->Identifier);
Lev Walkin59004fa2004-08-20 13:37:01 +0000355 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000356
357 elements = 0;
358 INDENTED(TQ_FOR(v, &(expr->members), next) {
Lev Walkincc93b0f2004-09-10 09:18:20 +0000359 if(v->expr_type == A1TC_EXTENSIBLE) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000360 if(comp_mode < 3) comp_mode++;
Lev Walkincc93b0f2004-09-10 09:18:20 +0000361 } else {
362 if(comp_mode == 1
363 || expr_better_indirect(arg, v))
364 v->marker |= EM_INDIRECT;
365 elements++;
366 emit_member_table(arg, v);
Lev Walkinf15320b2004-06-03 03:38:44 +0000367 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000368 });
369 OUT("};\n");
370
Lev Walkin27ea3802004-06-28 21:13:46 +0000371 /*
Lev Walkin188ed2c2004-09-13 08:31:01 +0000372 * Print out asn1_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +0000373 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000374 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000375
376 /*
377 * Tags to elements map.
378 */
Lev Walkinfd171ef2004-06-06 07:20:17 +0000379 emit_tag2member_map(arg, tag2el, tag2el_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000380
381 /*
382 * Emit a map of mandatory elements.
383 */
Lev Walkin27ea3802004-06-28 21:13:46 +0000384 p = MKID(expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000385 OUT("static uint8_t asn1_DEF_%s_mmap", p);
386 OUT("[(%d + (8 * sizeof(unsigned int)) - 1) / 8]", elements);
387 OUT(" = {\n", p);
388 INDENTED(
389 if(elements) {
390 int delimit = 0;
391 int el = 0;
392 TQ_FOR(v, &(expr->members), next) {
393 if(v->expr_type == A1TC_EXTENSIBLE) continue;
394 if(delimit) {
395 OUT(",\n");
396 delimit = 0;
397 } else if(el) {
398 OUT(" | ");
399 }
Lev Walkincc93b0f2004-09-10 09:18:20 +0000400 OUT("(%d << %d)",
401 v->marker?0:1,
402 7 - (el % 8));
Lev Walkinf15320b2004-06-03 03:38:44 +0000403 if(el && (el % 8) == 0)
404 delimit = 1;
405 el++;
406 }
407 } else {
408 OUT("0");
409 }
410 );
411 OUT("\n");
412 OUT("};\n");
413
414 OUT("static asn1_SET_specifics_t asn1_DEF_%s_specs = {\n", p);
415 INDENTED(
416 OUT("sizeof(struct %s),\n", p);
417 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
418 OUT("offsetof(struct %s, _presence_map),\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000419 OUT("asn1_DEF_%s_tag2el,\n", p);
420 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
Lev Walkin35631482004-07-01 00:52:50 +0000421 OUT("%d,\t/* Whether extensible */\n",
422 check_if_extensible(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +0000423 OUT("(unsigned int *)asn1_DEF_%s_mmap\t/* Mandatory elements map */\n", p);
424 );
425 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000426
427 /*
428 * Emit asn1_DEF_xxx table.
429 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000430 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
Lev Walkin59964be2004-08-25 02:03:12 +0000431 ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000432
Lev Walkinf15320b2004-06-03 03:38:44 +0000433 REDIR(OT_TYPE_DECLS);
434
435 return 0;
436}
437
438int
Lev Walkin08079b02004-08-22 03:25:24 +0000439asn1c_lang_C_type_SEx_OF(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000440 asn1p_expr_t *expr = arg->expr;
Lev Walkin08079b02004-08-22 03:25:24 +0000441 asn1p_expr_t *memb;
Lev Walkinf15320b2004-06-03 03:38:44 +0000442
443 DEPENDENCIES;
444
445 if(arg->embed) {
446 OUT("struct %s {\n", MKID(expr->Identifier));
447 } else {
Lev Walkin08079b02004-08-22 03:25:24 +0000448 OUT("typedef struct %s {\n", MKID(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +0000449 }
450
Lev Walkin08079b02004-08-22 03:25:24 +0000451 memb = TQ_FIRST(&expr->members);
452
453 INDENT(+1);
454 OUT("A_%s_OF(",
455 (arg->expr->expr_type == ASN_CONSTR_SET_OF)
456 ? "SET" : "SEQUENCE");
457 if(memb->expr_type & ASN_CONSTR_MASK) {
458 arg_t tmp;
459 asn1p_expr_t tmp_memb;
460 arg->embed++;
461 tmp = *arg;
462 tmp.expr = &tmp_memb;
463 tmp_memb = *memb;
464 tmp_memb._anonymous_type = 1;
465 tmp_memb.Identifier = strdup(
466 asn1c_make_identifier(0,
467 expr->Identifier, "member", 0));
468 assert(tmp_memb.Identifier);
469 tmp.default_cb(&tmp);
470 free(tmp_memb.Identifier);
471 arg->embed--;
472 assert(arg->target->target == OT_TYPE_DECLS);
473 } else {
474 OUT("%s", asn1c_type_name(arg, memb, TNF_RSAFE));
Lev Walkinf15320b2004-06-03 03:38:44 +0000475 }
Lev Walkin08079b02004-08-22 03:25:24 +0000476 OUT(") list;\n");
477 INDENT(-1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000478
479 PCTX_DEF;
Lev Walkin08079b02004-08-22 03:25:24 +0000480 OUT("} %s%s%s", expr->marker?"*":"",
481 expr->_anonymous_type ? "" : MKID(expr->Identifier),
482 arg->embed ? "" : "_t");
Lev Walkinf15320b2004-06-03 03:38:44 +0000483
484 /*
Lev Walkin08079b02004-08-22 03:25:24 +0000485 * SET OF/SEQUENCE OF definition
Lev Walkinf15320b2004-06-03 03:38:44 +0000486 */
Lev Walkin08079b02004-08-22 03:25:24 +0000487 return asn1c_lang_C_type_SEx_OF_def(arg,
488 (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF));
Lev Walkinf15320b2004-06-03 03:38:44 +0000489}
490
491static int
492asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
493 asn1p_expr_t *expr = arg->expr;
494 asn1p_expr_t *v;
Lev Walkin64399722004-08-11 07:17:22 +0000495 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000496 int all_tags_count;
497 enum tvm_compat tv_mode;
Lev Walkinf15320b2004-06-03 03:38:44 +0000498 char *p;
499
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000500 /*
501 * Print out the table according to which the parsing is performed.
502 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000503 if(seq_of) {
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000504 GEN_INCLUDE("constr_SEQUENCE_OF");
Lev Walkinf15320b2004-06-03 03:38:44 +0000505 } else {
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000506 GEN_INCLUDE("constr_SET_OF");
Lev Walkinf15320b2004-06-03 03:38:44 +0000507 }
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000508 if(!arg->embed)
509 GEN_DECLARE(expr); /* asn1_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000510
511 REDIR(OT_STAT_DEFS);
512
513 /*
514 * Print out the table according to which the parsing is performed.
515 */
516 p = MKID(expr->Identifier);
Lev Walkin59004fa2004-08-20 13:37:01 +0000517 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000518
Lev Walkin59004fa2004-08-20 13:37:01 +0000519 INDENTED(
Lev Walkinf15320b2004-06-03 03:38:44 +0000520 v = TQ_FIRST(&(expr->members));
Lev Walkin59964be2004-08-25 02:03:12 +0000521 emit_member_table(arg, v);
Lev Walkinf15320b2004-06-03 03:38:44 +0000522 );
523 OUT("};\n");
524
Lev Walkin27ea3802004-06-28 21:13:46 +0000525 /*
Lev Walkin188ed2c2004-09-13 08:31:01 +0000526 * Print out asn1_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +0000527 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000528 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000529
Lev Walkin27ea3802004-06-28 21:13:46 +0000530 p = MKID(expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000531 OUT("static asn1_SET_OF_specifics_t asn1_DEF_%s_specs = {\n", p);
532 INDENTED(
533 OUT("sizeof(struct %s),\n", p);
534 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000535 );
536 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000537
538 /*
539 * Emit asn1_DEF_xxx table.
540 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000541 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, 1,
Lev Walkin59964be2004-08-25 02:03:12 +0000542 ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000543
Lev Walkinf15320b2004-06-03 03:38:44 +0000544 REDIR(OT_TYPE_DECLS);
545
546 return 0;
547}
548
549int
550asn1c_lang_C_type_CHOICE(arg_t *arg) {
551 asn1p_expr_t *expr = arg->expr;
552 asn1p_expr_t *v;
Lev Walkin08079b02004-08-22 03:25:24 +0000553 char *id;
Lev Walkinf15320b2004-06-03 03:38:44 +0000554
555 DEPENDENCIES;
556
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000557 REDIR(OT_DEPS);
558
Lev Walkin08079b02004-08-22 03:25:24 +0000559 id = MKID(expr->Identifier);
560 OUT("typedef enum %s_PR {\n", id);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000561 INDENTED(
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000562 OUT("%s_PR_NOTHING,\t"
Lev Walkin08079b02004-08-22 03:25:24 +0000563 "/* No components present */\n", id);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000564 TQ_FOR(v, &(expr->members), next) {
565 if(v->expr_type == A1TC_EXTENSIBLE) {
566 OUT("/* Extensions may appear below */\n");
567 continue;
568 }
Lev Walkin08079b02004-08-22 03:25:24 +0000569 id = MKID(expr->Identifier);
570 OUT("%s_PR_", id);
571 id = MKID(v->Identifier);
572 OUT("%s,\n", id, id);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000573 }
574 );
Lev Walkin08079b02004-08-22 03:25:24 +0000575 id = MKID(expr->Identifier);
576 OUT("} %s_PR;\n", id);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000577
578 REDIR(OT_TYPE_DECLS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000579
580 if(arg->embed) {
Lev Walkin08079b02004-08-22 03:25:24 +0000581 OUT("struct %s {\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000582 } else {
Lev Walkin08079b02004-08-22 03:25:24 +0000583 OUT("typedef struct %s {\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000584 }
585
586 INDENTED(
Lev Walkin08079b02004-08-22 03:25:24 +0000587 OUT("%s_PR present;\n", id);
588 OUT("union {\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000589 TQ_FOR(v, &(expr->members), next) {
Lev Walkincc93b0f2004-09-10 09:18:20 +0000590 if(expr_better_indirect(arg, v))
591 v->marker |= EM_INDIRECT;
Lev Walkinf15320b2004-06-03 03:38:44 +0000592 EMBED(v);
593 }
594 if(UNNAMED_UNIONS) OUT("};\n");
595 else OUT("} choice;\n");
596 );
597
598 PCTX_DEF;
Lev Walkin08079b02004-08-22 03:25:24 +0000599 OUT("} %s%s%s", expr->marker?"*":"",
600 expr->_anonymous_type ? "" : MKID(expr->Identifier),
601 arg->embed ? "" : "_t");
Lev Walkinf15320b2004-06-03 03:38:44 +0000602
603 return asn1c_lang_C_type_CHOICE_def(arg);
604}
605
606static int
607asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
608 asn1p_expr_t *expr = arg->expr;
609 asn1p_expr_t *v;
610 int elements; /* Number of elements */
Lev Walkinf15320b2004-06-03 03:38:44 +0000611 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Lev Walkinf15320b2004-06-03 03:38:44 +0000612 tag2el_t *tag2el = NULL;
613 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000614 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000615 int all_tags_count;
616 enum tvm_compat tv_mode;
Lev Walkinf15320b2004-06-03 03:38:44 +0000617 char *p;
618
619 /*
620 * Fetch every inner tag from the tag to elements map.
621 */
622 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
623 if(tag2el) free(tag2el);
624 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000625 }
626
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000627 GEN_INCLUDE("constr_CHOICE");
628 if(!arg->embed)
629 GEN_DECLARE(expr); /* asn1_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000630
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000631 REDIR(OT_STAT_DEFS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000632
633 /*
634 * Print out the table according to which the parsing is performed.
635 */
636 p = MKID(expr->Identifier);
Lev Walkin59004fa2004-08-20 13:37:01 +0000637 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000638
639 elements = 0;
640 INDENTED(TQ_FOR(v, &(expr->members), next) {
Lev Walkincc93b0f2004-09-10 09:18:20 +0000641 if(v->expr_type == A1TC_EXTENSIBLE) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000642 if(comp_mode < 3) comp_mode++;
Lev Walkincc93b0f2004-09-10 09:18:20 +0000643 } else {
644 if(comp_mode == 1
645 || expr_better_indirect(arg, v))
646 v->marker |= EM_INDIRECT;
647 elements++;
648 emit_member_table(arg, v);
Lev Walkinf15320b2004-06-03 03:38:44 +0000649 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000650 });
651 OUT("};\n");
652
Lev Walkin64399722004-08-11 07:17:22 +0000653
Lev Walkinf15320b2004-06-03 03:38:44 +0000654 if(arg->embed) {
655 /*
656 * Our parent structure has already taken this into account.
657 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000658 tv_mode = _TVM_SAME;
659 tags_count = all_tags_count = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000660 } else {
Lev Walkin188ed2c2004-09-13 08:31:01 +0000661 tv_mode = emit_tags_vectors(arg, expr,
662 &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000663 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000664
665 /*
666 * Tags to elements map.
667 */
Lev Walkinfd171ef2004-06-06 07:20:17 +0000668 emit_tag2member_map(arg, tag2el, tag2el_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000669
Lev Walkin64399722004-08-11 07:17:22 +0000670 p = MKID(expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000671 OUT("static asn1_CHOICE_specifics_t asn1_DEF_%s_specs = {\n", p);
672 INDENTED(
673 OUT("sizeof(struct %s),\n", p);
674 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
675 OUT("offsetof(struct %s, present),\n", p);
676 OUT("sizeof(((struct %s *)0)->present),\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000677 OUT("asn1_DEF_%s_tag2el,\n", p);
678 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
Lev Walkin35631482004-07-01 00:52:50 +0000679 OUT("%d\t/* Whether extensible */\n",
680 check_if_extensible(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +0000681 );
682 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000683
684 /*
685 * Emit asn1_DEF_xxx table.
686 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000687 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
Lev Walkin59964be2004-08-25 02:03:12 +0000688 ETD_CP_CONSTRUCTED /*either?!*/, ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000689
Lev Walkinf15320b2004-06-03 03:38:44 +0000690 REDIR(OT_TYPE_DECLS);
691
692 return 0;
693}
694
695int
696asn1c_lang_C_type_REFERENCE(arg_t *arg) {
697 asn1p_ref_t *ref;
698
699 ref = arg->expr->reference;
700 if(ref->components[ref->comp_count-1].name[0] == '&') {
Lev Walkinf15320b2004-06-03 03:38:44 +0000701 asn1p_expr_t *extract;
702 arg_t tmp;
703 int ret;
704
Lev Walkin08079b02004-08-22 03:25:24 +0000705 extract = asn1f_class_access_ex(arg->asn, arg->mod,
706 arg->expr, ref);
Lev Walkinf15320b2004-06-03 03:38:44 +0000707 if(extract == NULL)
708 return -1;
709
Lev Walkin08079b02004-08-22 03:25:24 +0000710 extract = asn1p_expr_clone(extract, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000711 if(extract) {
712 if(extract->Identifier)
713 free(extract->Identifier);
714 extract->Identifier = strdup(arg->expr->Identifier);
715 if(extract->Identifier == NULL) {
716 asn1p_expr_free(extract);
717 return -1;
718 }
719 } else {
720 return -1;
721 }
722
723 tmp = *arg;
724 tmp.asn = arg->asn;
Lev Walkin08079b02004-08-22 03:25:24 +0000725 tmp.mod = extract->module;
Lev Walkinf15320b2004-06-03 03:38:44 +0000726 tmp.expr = extract;
727
728 ret = arg->default_cb(&tmp);
729
730 asn1p_expr_free(extract);
731
732 return ret;
733 }
734
735
736 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
737}
738
739int
740asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
741 asn1p_expr_t *expr = arg->expr;
Lev Walkin64399722004-08-11 07:17:22 +0000742 int tags_count;
Lev Walkin188ed2c2004-09-13 08:31:01 +0000743 int all_tags_count;
744 enum tvm_compat tv_mode;
Lev Walkinf15320b2004-06-03 03:38:44 +0000745 char *p;
746
747 if(arg->embed) {
748 REDIR(OT_TYPE_DECLS);
749
750 OUT("%s\t", asn1c_type_name(arg, arg->expr,
751 expr->marker?TNF_RSAFE:TNF_CTYPE));
752 OUT("%s", expr->marker?"*":" ");
Lev Walkin08079b02004-08-22 03:25:24 +0000753 OUT("%s", MKID(expr->Identifier));
Lev Walkincc93b0f2004-09-10 09:18:20 +0000754 if((expr->marker & EM_DEFAULT) == EM_DEFAULT)
755 OUT("\t/* DEFAULT */");
756 else if((expr->marker & EM_OPTIONAL) == EM_OPTIONAL)
757 OUT("\t/* OPTIONAL */");
Lev Walkin59004fa2004-08-20 13:37:01 +0000758
759 REDIR(OT_TYPE_DECLS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000760 return 0;
761 }
762
Lev Walkinf15320b2004-06-03 03:38:44 +0000763
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000764 GEN_INCLUDE(asn1c_type_name(arg, expr, TNF_INCLUDE));
Lev Walkinf15320b2004-06-03 03:38:44 +0000765
766 REDIR(OT_TYPE_DECLS);
767
768 OUT("typedef %s\t", asn1c_type_name(arg, arg->expr, TNF_CTYPE));
769 OUT("%s", expr->marker?"*":" ");
Lev Walkin08079b02004-08-22 03:25:24 +0000770 OUT("%s_t", MKID(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +0000771
772 REDIR(OT_STAT_DEFS);
773
Lev Walkin27ea3802004-06-28 21:13:46 +0000774 /*
Lev Walkin188ed2c2004-09-13 08:31:01 +0000775 * Print out asn1_DEF_<type>_[all_]tags[] vectors.
Lev Walkin27ea3802004-06-28 21:13:46 +0000776 */
Lev Walkin188ed2c2004-09-13 08:31:01 +0000777 tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000778
Lev Walkin188ed2c2004-09-13 08:31:01 +0000779 emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, 0,
Lev Walkin59964be2004-08-25 02:03:12 +0000780 ETD_CP_UNKNOWN, ETD_NO_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000781
Lev Walkin59004fa2004-08-20 13:37:01 +0000782 REDIR(OT_CODE);
783
Lev Walkinf15320b2004-06-03 03:38:44 +0000784 /*
785 * Constraint checking.
786 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000787 p = MKID(expr->Identifier);
788 OUT("int\n");
789 OUT("%s_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,\n", p);
790 INDENTED(
791 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
792 OUT("\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000793 if(asn1c_emit_constraint_checking_code(arg) == 1) {
794 if(0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000795 OUT("/* Check the constraints of the underlying type */\n");
796 OUT("return asn1_DEF_%s.check_constraints\n",
797 asn1c_type_name(arg, expr, TNF_SAFE));
798 OUT("\t(td, sptr, app_errlog, app_key);\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000799 } else {
Lev Walkinf15320b2004-06-03 03:38:44 +0000800 OUT("/* Make the underlying type checker permanent */\n");
801 OUT("td->check_constraints = asn1_DEF_%s.check_constraints;\n",
802 asn1c_type_name(arg, expr, TNF_SAFE));
803 OUT("return td->check_constraints\n");
804 OUT("\t(td, sptr, app_errlog, app_key);\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000805 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000806 }
807 );
808 OUT("}\n");
809 OUT("\n");
810
811 /*
812 * Emit suicidal functions.
813 */
814
Lev Walkinf15320b2004-06-03 03:38:44 +0000815 /*
816 * This function replaces certain fields from the definition
817 * of a type with the corresponding fields from the basic type
818 * (from which the current type is inherited).
819 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000820 OUT("/*\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000821 OUT(" * This type is implemented using %s,\n",
822 asn1c_type_name(arg, expr, TNF_SAFE));
Lev Walkinf15320b2004-06-03 03:38:44 +0000823 OUT(" * so adjust the DEF appropriately.\n");
824 OUT(" */\n");
825 OUT("static void\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000826 p = MKID(expr->Identifier);
827 OUT("%s_inherit_TYPE_descriptor(asn1_TYPE_descriptor_t *td) {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000828 INDENT(+1);
Lev Walkin59004fa2004-08-20 13:37:01 +0000829 {
Lev Walkin906654e2004-09-10 15:49:15 +0000830 asn1p_expr_t *terminal = asn1f_find_terminal_type_ex(arg->asn, arg->mod, expr);
Lev Walkin59004fa2004-08-20 13:37:01 +0000831 char *type_name = asn1c_type_name(arg, expr, TNF_SAFE);
832 OUT("td->ber_decoder = asn1_DEF_%s.ber_decoder;\n", type_name);
833 OUT("td->der_encoder = asn1_DEF_%s.der_encoder;\n", type_name);
834 OUT("td->free_struct = asn1_DEF_%s.free_struct;\n", type_name);
835 OUT("td->print_struct = asn1_DEF_%s.print_struct;\n", type_name);
Lev Walkin906654e2004-09-10 15:49:15 +0000836 if(!terminal && !tags_count) {
Lev Walkin188ed2c2004-09-13 08:31:01 +0000837 OUT("/* The next four lines are here because of -fknown-extern-type */\n");
Lev Walkin906654e2004-09-10 15:49:15 +0000838 OUT("td->tags = asn1_DEF_%s.tags;\n", type_name);
839 OUT("td->tags_count = asn1_DEF_%s.tags_count;\n", type_name);
Lev Walkin188ed2c2004-09-13 08:31:01 +0000840 OUT("td->all_tags = asn1_DEF_%s.all_tags;\n", type_name);
841 OUT("td->all_tags_count = asn1_DEF_%s.all_tags_count;\n",type_name);
Lev Walkin906654e2004-09-10 15:49:15 +0000842 OUT("/* End of these lines */\n");
843 }
Lev Walkin59004fa2004-08-20 13:37:01 +0000844 OUT("td->last_tag_form = asn1_DEF_%s.last_tag_form;\n", type_name);
845 OUT("td->elements = asn1_DEF_%s.elements;\n", type_name);
846 OUT("td->elements_count = asn1_DEF_%s.elements_count;\n", type_name);
847 OUT("td->specifics = asn1_DEF_%s.specifics;\n", type_name);
848 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000849 INDENT(-1);
850 OUT("}\n");
851 OUT("\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000852
853 p = MKID(expr->Identifier);
854 OUT("ber_dec_rval_t\n");
855 OUT("%s_decode_ber(asn1_TYPE_descriptor_t *td,\n", p);
856 INDENTED(
857 OUT("\tvoid **structure, void *bufptr, size_t size, int tag_mode) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000858 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
Lev Walkin906654e2004-09-10 15:49:15 +0000859 OUT("return td->ber_decoder(td, structure, bufptr, size, tag_mode);\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000860 );
861 OUT("}\n");
862 OUT("\n");
863
864 p = MKID(expr->Identifier);
865 OUT("der_enc_rval_t\n");
866 OUT("%s_encode_der(asn1_TYPE_descriptor_t *td,\n", p);
867 INDENTED(
868 OUT("\tvoid *structure, int tag_mode, ber_tlv_tag_t tag,\n");
869 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000870 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000871 OUT("return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);\n");
872 );
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");
Lev Walkin59004fa2004-08-20 13:37:01 +0000881 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
Lev Walkinf15320b2004-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);
888 OUT("void\n");
889 OUT("%s_free(asn1_TYPE_descriptor_t *td,\n", p);
890 INDENTED(
891 OUT("\tvoid *struct_ptr, int contents_only) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000892 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000893 OUT("td->free_struct(td, struct_ptr, contents_only);\n");
894 );
895 OUT("}\n");
896 OUT("\n");
897
898 REDIR(OT_FUNC_DECLS);
899
900 p = MKID(expr->Identifier);
Lev Walkindd32b592004-09-06 08:07:29 +0000901 if(HIDE_INNER_DEFS) OUT("/* ");
902 OUT("extern asn1_TYPE_descriptor_t asn1_DEF_%s;", p);
903 if(HIDE_INNER_DEFS) OUT(" // (Use -fall-defs-global to expose) */");
904 OUT("\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000905 OUT("asn_constr_check_f %s_constraint;\n", p);
906 OUT("ber_type_decoder_f %s_decode_ber;\n", p);
907 OUT("der_type_encoder_f %s_encode_der;\n", p);
908 OUT("asn_struct_print_f %s_print;\n", p);
909 OUT("asn_struct_free_f %s_free;\n", p);
910
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000911 REDIR(OT_TYPE_DECLS);
912
Lev Walkinf15320b2004-06-03 03:38:44 +0000913 return 0;
914}
915
916int
917asn1c_lang_C_type_EXTENSIBLE(arg_t *arg) {
918
919 OUT("/*\n");
920 OUT(" * This type is extensible,\n");
921 OUT(" * possible extensions are below.\n");
922 OUT(" */\n");
923
924 return 0;
925}
926
Lev Walkin35631482004-07-01 00:52:50 +0000927static int check_if_extensible(asn1p_expr_t *expr) {
928 asn1p_expr_t *v;
929 TQ_FOR(v, &(expr->members), next) {
930 if(v->expr_type == A1TC_EXTENSIBLE) return 1;
931 }
932 return 0;
933}
934
Lev Walkinf15320b2004-06-03 03:38:44 +0000935static int
Lev Walkinc3e29402004-09-10 06:07:18 +0000936_print_tag(arg_t *arg, struct asn1p_type_tag_s *tag) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000937
938 OUT("(");
Lev Walkinc3e29402004-09-10 06:07:18 +0000939 switch(tag->tag_class) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000940 case TC_UNIVERSAL: OUT("ASN_TAG_CLASS_UNIVERSAL"); break;
941 case TC_APPLICATION: OUT("ASN_TAG_CLASS_APPLICATION"); break;
942 case TC_CONTEXT_SPECIFIC: OUT("ASN_TAG_CLASS_CONTEXT"); break;
943 case TC_PRIVATE: OUT("ASN_TAG_CLASS_PRIVATE"); break;
944 case TC_NOCLASS:
945 break;
946 }
Lev Walkinc3e29402004-09-10 06:07:18 +0000947 OUT(" | (%lld << 2))", tag->tag_value);
Lev Walkinf15320b2004-06-03 03:38:44 +0000948
949 return 0;
950}
951
Lev Walkinfd171ef2004-06-06 07:20:17 +0000952
953static int
954_tag2el_cmp(const void *ap, const void *bp) {
955 const tag2el_t *a = ap;
956 const tag2el_t *b = bp;
957 const struct asn1p_type_tag_s *ta = &a->el_tag;
958 const struct asn1p_type_tag_s *tb = &b->el_tag;
959
960 if(ta->tag_class == tb->tag_class) {
961 if(ta->tag_value == tb->tag_value) {
962 /*
963 * Sort by their respective positions.
964 */
965 if(a->el_no < b->el_no)
966 return -1;
967 else if(a->el_no > b->el_no)
968 return 1;
969 return 0;
970 } else if(ta->tag_value < tb->tag_value)
971 return -1;
972 else
973 return 1;
974 } else if(ta->tag_class < tb->tag_class) {
975 return -1;
976 } else {
977 return 1;
978 }
979}
980
Lev Walkinf15320b2004-06-03 03:38:44 +0000981/*
982 * For constructed types, number of external tags may be greater than
983 * number of elements in the type because of CHOICE type.
984 * T ::= SET { -- Three possible tags:
985 * a INTEGER, -- One tag is here...
986 * b Choice1 -- ... and two more tags are there.
987 * }
988 * Choice1 ::= CHOICE {
989 * s1 IA5String,
990 * s2 ObjectDescriptor
991 * }
992 */
993static int
994_fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no) {
995 asn1p_expr_t *expr = arg->expr;
996 arg_t tmparg = *arg;
997 asn1p_expr_t *v;
998 int element = 0;
999
1000 TQ_FOR(v, &(expr->members), next) {
1001 if(v->expr_type == A1TC_EXTENSIBLE)
1002 continue;
1003
1004 tmparg.expr = v;
1005
1006 if(_add_tag2el_member(&tmparg, tag2el, count,
1007 (el_no==-1)?element:el_no)) {
1008 return -1;
1009 }
1010
1011 element++;
1012 }
1013
Lev Walkinfd171ef2004-06-06 07:20:17 +00001014 /*
Lev Walkin38abe792004-06-14 13:09:45 +00001015 * Sort the map according to canonical order of their tags
1016 * and element numbers.
Lev Walkinfd171ef2004-06-06 07:20:17 +00001017 */
1018 qsort(*tag2el, *count, sizeof(**tag2el), _tag2el_cmp);
1019
Lev Walkin38abe792004-06-14 13:09:45 +00001020 /*
1021 * Initialize .toff_{first|last} members.
1022 */
1023 if(*count) {
1024 struct asn1p_type_tag_s *cur_tag = 0;
1025 tag2el_t *cur = *tag2el;
1026 tag2el_t *end = cur + *count;
1027 int occur, i;
1028 for(occur = 0; cur < end; cur++) {
1029 if(cur_tag == 0
1030 || cur_tag->tag_value != cur->el_tag.tag_value
1031 || cur_tag->tag_class != cur->el_tag.tag_class) {
1032 cur_tag = &cur->el_tag;
1033 occur = 0;
1034 } else {
1035 occur++;
1036 }
1037 cur->toff_first = -occur;
1038 for(i = 0; i >= -occur; i--)
1039 cur[i].toff_last = -i;
1040 }
1041 }
1042
Lev Walkinf15320b2004-06-03 03:38:44 +00001043 return 0;
1044}
1045
1046static int
1047_add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no) {
1048 struct asn1p_type_tag_s tag;
1049 int ret;
1050
1051 assert(el_no >= 0);
1052
Lev Walkinc3e29402004-09-10 06:07:18 +00001053 ret = asn1f_fetch_outmost_tag(arg->asn, arg->mod, arg->expr, &tag, 1);
Lev Walkinf15320b2004-06-03 03:38:44 +00001054 if(ret == 0) {
Lev Walkin201943e2004-09-04 04:42:29 +00001055 tag2el_t *te;
1056 int new_count = (*count) + 1;
Lev Walkinf15320b2004-06-03 03:38:44 +00001057 void *p;
Lev Walkin201943e2004-09-04 04:42:29 +00001058
Lev Walkinac7e2292004-09-05 10:42:33 +00001059 if(tag.tag_value == -1) {
1060 /*
1061 * This is an untagged ANY type,
1062 * proceed without adding a tag
1063 */
1064 return 0;
1065 }
1066
Lev Walkin201943e2004-09-04 04:42:29 +00001067 p = realloc(*tag2el, new_count * sizeof(tag2el_t));
Lev Walkinf15320b2004-06-03 03:38:44 +00001068 if(p) *tag2el = p;
1069 else return -1;
1070
1071 DEBUG("Found tag for %s: %ld",
1072 arg->expr->Identifier,
1073 (long)tag.tag_value);
1074
Lev Walkin201943e2004-09-04 04:42:29 +00001075 te = &((*tag2el)[*count]);
1076 te->el_tag = tag;
1077 te->el_no = el_no;
1078 te->from_expr = arg->expr;
1079 *count = new_count;
Lev Walkinf15320b2004-06-03 03:38:44 +00001080 return 0;
1081 }
1082
1083 DEBUG("Searching tag in complex expression %s:%x at line %d",
1084 arg->expr->Identifier,
1085 arg->expr->expr_type,
1086 arg->expr->_lineno);
1087
1088 /*
1089 * Iterate over members of CHOICE type.
1090 */
1091 if(arg->expr->expr_type == ASN_CONSTR_CHOICE) {
1092 return _fill_tag2el_map(arg, tag2el, count, el_no);
1093 }
1094
1095 if(arg->expr->expr_type == A1TC_REFERENCE) {
1096 arg_t tmp = *arg;
1097 asn1p_expr_t *expr;
Lev Walkin08079b02004-08-22 03:25:24 +00001098 expr = asn1f_lookup_symbol_ex(tmp.asn, tmp.mod, tmp.expr,
Lev Walkinf15320b2004-06-03 03:38:44 +00001099 arg->expr->reference);
1100 if(expr) {
Lev Walkin08079b02004-08-22 03:25:24 +00001101 tmp.mod = expr->module;
Lev Walkinf15320b2004-06-03 03:38:44 +00001102 tmp.expr = expr;
1103 return _add_tag2el_member(&tmp, tag2el, count, el_no);
1104 } else {
1105 FATAL("Cannot dereference %s at line %d",
1106 arg->expr->Identifier,
1107 arg->expr->_lineno);
1108 return -1;
1109 }
1110 }
1111
1112 DEBUG("No tag for %s at line %d",
1113 arg->expr->Identifier,
1114 arg->expr->_lineno);
1115
1116 return -1;
1117}
1118
1119static int
Lev Walkinfd171ef2004-06-06 07:20:17 +00001120emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count) {
1121 asn1p_expr_t *expr = arg->expr;
1122
1123 OUT("static asn1_TYPE_tag2member_t asn1_DEF_%s_tag2el[] = {\n",
1124 MKID(expr->Identifier));
1125 if(tag2el_count) {
1126 int i;
1127 for(i = 0; i < tag2el_count; i++) {
1128 OUT(" { ");
Lev Walkinc3e29402004-09-10 06:07:18 +00001129 _print_tag(arg, &tag2el[i].el_tag);
Lev Walkinfd171ef2004-06-06 07:20:17 +00001130 OUT(", ");
Lev Walkin38abe792004-06-14 13:09:45 +00001131 OUT("%d, ", tag2el[i].el_no);
1132 OUT("%d, ", tag2el[i].toff_first);
1133 OUT("%d ", tag2el[i].toff_last);
Lev Walkinfd171ef2004-06-06 07:20:17 +00001134 OUT("}, /* %s at %d */\n",
1135 tag2el[i].from_expr->Identifier,
1136 tag2el[i].from_expr->_lineno
1137 );
1138 }
1139 }
1140 OUT("};\n");
1141
1142 return 0;;
1143}
1144
Lev Walkin188ed2c2004-09-13 08:31:01 +00001145static enum tvm_compat
1146emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tags_count_r, int *all_tags_count_r) {
1147 struct asn1p_type_tag_s *tags = 0; /* Effective tags */
1148 struct asn1p_type_tag_s *all_tags = 0; /* The full array */
Lev Walkin64399722004-08-11 07:17:22 +00001149 int tags_count = 0;
Lev Walkin188ed2c2004-09-13 08:31:01 +00001150 int all_tags_count = 0;
1151 enum tvm_compat tv_mode = _TVM_SAME;
Lev Walkin906654e2004-09-10 15:49:15 +00001152 int i;
Lev Walkin27ea3802004-06-28 21:13:46 +00001153
Lev Walkin906654e2004-09-10 15:49:15 +00001154 /* Fetch a chain of tags */
1155 tags_count = asn1f_fetch_tags(arg->asn, arg->mod, expr, &tags, 0);
Lev Walkin188ed2c2004-09-13 08:31:01 +00001156 if(tags_count < 0) return -1;
Lev Walkin64399722004-08-11 07:17:22 +00001157
Lev Walkin188ed2c2004-09-13 08:31:01 +00001158 /* Fetch a chain of tags */
1159 all_tags_count = asn1f_fetch_tags(arg->asn, arg->mod, expr,
1160 &all_tags, AFT_FULL_COLLECT);
1161 if(all_tags_count < 0) {
1162 if(tags) free(tags);
1163 return -1;
Lev Walkin5a8219a2004-09-08 00:28:57 +00001164 }
Lev Walkin906654e2004-09-10 15:49:15 +00001165
Lev Walkin188ed2c2004-09-13 08:31:01 +00001166 assert(tags_count <= all_tags_count);
1167 assert((tags_count?0:1) == (all_tags_count?0:1));
Lev Walkin27ea3802004-06-28 21:13:46 +00001168
Lev Walkin188ed2c2004-09-13 08:31:01 +00001169 if(tags_count <= all_tags_count) {
1170 for(i = 0; i < tags_count; i++) {
1171 if(tags[i].tag_value != all_tags[i].tag_value
1172 || tags[i].tag_class != all_tags[i].tag_class) {
1173 tv_mode = _TVM_DIFFERENT;
1174 break;
1175 }
1176 }
1177 if(i == tags_count && tags_count < all_tags_count)
1178 tv_mode = _TVM_SUBSET;
1179 } else {
1180 tv_mode = _TVM_DIFFERENT;
1181 }
1182
1183#define EMIT_TAGS_TABLE(name, tags, tags_count) do { \
1184 OUT("static ber_tlv_tag_t asn1_DEF_%s%s_tags[] = {\n", \
1185 MKID(expr->Identifier), name); \
1186 INDENT(+1); \
1187 /* Print the array of collected tags */ \
1188 for(i = 0; i < tags_count; i++) { \
1189 if(i) OUT(",\n"); \
1190 _print_tag(arg, &tags[i]); \
1191 } \
1192 OUT("\n"); \
1193 INDENT(-1); \
1194 OUT("};\n"); \
1195 } while(0)
1196
1197 if(tags_count) {
1198 if(tv_mode == _TVM_SUBSET)
1199 EMIT_TAGS_TABLE("", all_tags, all_tags_count);
1200 else
1201 EMIT_TAGS_TABLE("", tags, tags_count);
1202 }
1203
1204 if(all_tags_count) {
1205 if(tv_mode == _TVM_DIFFERENT)
1206 EMIT_TAGS_TABLE("_all", all_tags, all_tags_count);
1207 }
1208
1209 if(tags) free(tags);
1210 if(all_tags) free(all_tags);
1211
1212 *tags_count_r = tags_count;
1213 *all_tags_count_r = all_tags_count;
1214
1215 return tv_mode;
Lev Walkin27ea3802004-06-28 21:13:46 +00001216}
Lev Walkin59004fa2004-08-20 13:37:01 +00001217
1218static int
Lev Walkin59964be2004-08-25 02:03:12 +00001219expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin59004fa2004-08-20 13:37:01 +00001220 asn1p_expr_t *topmost_parent;
1221 asn1p_expr_t *v;
1222 int elements = 0;
1223
Lev Walkin08079b02004-08-22 03:25:24 +00001224 topmost_parent = asn1f_find_terminal_type_ex(arg->asn, arg->mod, expr);
Lev Walkin59004fa2004-08-20 13:37:01 +00001225 if(!topmost_parent) return 0;
1226
1227 if(!(topmost_parent->expr_type & ASN_CONSTR_MASK))
1228 return 0;
1229
1230 TQ_FOR(v, &(topmost_parent->members), next) {
1231 if(v->expr_type != A1TC_EXTENSIBLE)
1232 elements++;
1233 }
1234
1235 return elements;
1236}
1237
1238static int
Lev Walkin59964be2004-08-25 02:03:12 +00001239emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin08079b02004-08-22 03:25:24 +00001240 static int global_memb_unique;
Lev Walkin59004fa2004-08-20 13:37:01 +00001241 int save_target;
1242 arg_t tmp_arg;
Lev Walkinb9189732004-09-10 09:37:12 +00001243 struct asn1p_type_tag_s outmost_tag_s;
1244 struct asn1p_type_tag_s *outmost_tag;
Lev Walkin59004fa2004-08-20 13:37:01 +00001245 char *p;
1246
Lev Walkinb9189732004-09-10 09:37:12 +00001247 if(asn1f_fetch_outmost_tag(arg->asn,
1248 expr->module, expr, &outmost_tag_s, 1)) {
1249 outmost_tag = 0;
1250 } else {
1251 outmost_tag = &outmost_tag_s;
1252 }
1253
Lev Walkin59004fa2004-08-20 13:37:01 +00001254 OUT("{ ");
Lev Walkinb9189732004-09-10 09:37:12 +00001255
1256 if(outmost_tag && outmost_tag->tag_value == -1)
1257 OUT("ATF_OPEN_TYPE | ");
Lev Walkincc93b0f2004-09-10 09:18:20 +00001258 OUT("%s, ", expr->marker?"ATF_POINTER":"ATF_NOFLAGS");
1259 if((expr->marker & EM_OPTIONAL) == EM_OPTIONAL) {
Lev Walkin59004fa2004-08-20 13:37:01 +00001260 asn1p_expr_t *tv;
1261 int opts = 0;
1262 for(tv = expr; tv && tv->marker;
1263 tv = TQ_NEXT(tv, next), opts++) {
1264 if(tv->expr_type == A1TC_EXTENSIBLE)
1265 opts--;
1266 }
1267 OUT("%d, ", opts);
1268 } else {
1269 OUT("0, ");
1270 }
1271 if(expr->Identifier) {
1272 OUT("offsetof(struct %s, ", MKID(arg->expr->Identifier));
1273 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1274 && (!UNNAMED_UNIONS)) OUT("choice.");
1275 OUT("%s),\n", MKID(expr->Identifier));
1276 } else {
1277 assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
1278 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
1279 OUT("0,\n");
1280 }
1281 INDENT(+1);
1282 if(C99_MODE) OUT(".tag = ");
Lev Walkinb9189732004-09-10 09:37:12 +00001283 if(outmost_tag) {
1284 if(outmost_tag->tag_value == -1)
1285 OUT("-1 /* Ambiguous tag (ANY?) */");
1286 else
1287 _print_tag(arg, outmost_tag);
Lev Walkinc3e29402004-09-10 06:07:18 +00001288 } else {
Lev Walkinb9189732004-09-10 09:37:12 +00001289 OUT("-1 /* Ambiguous tag (CHOICE?) */");
Lev Walkinc3e29402004-09-10 06:07:18 +00001290 }
Lev Walkinb9189732004-09-10 09:37:12 +00001291
Lev Walkin59004fa2004-08-20 13:37:01 +00001292 OUT(",\n");
1293 if(C99_MODE) OUT(".tag_mode = ");
1294 if(expr->tag.tag_class) {
1295 if(expr->tag.tag_mode == TM_IMPLICIT)
1296 OUT("-1,\t/* IMPLICIT tag at current level */\n");
1297 else
1298 OUT("+1,\t/* EXPLICIT tag at current level */\n");
1299 } else {
1300 OUT("0,\n");
1301 }
1302 if(C99_MODE) OUT(".type = ");
Lev Walkin08079b02004-08-22 03:25:24 +00001303 if((expr->expr_type & ASN_CONSTR_MASK)
1304 && (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF
1305 || arg->expr->expr_type == ASN_CONSTR_SET_OF)) {
1306 OUT("(void *)&asn1_DEF_%s_member,\n",
1307 MKID(arg->expr->Identifier));
Lev Walkin59964be2004-08-25 02:03:12 +00001308 } else if(expr->expr_type & ASN_CONSTR_MASK) {
1309 OUT("(void *)&asn1_DEF_%s,\n",
1310 MKID(expr->Identifier));
Lev Walkin08079b02004-08-22 03:25:24 +00001311 } else {
1312 OUT("(void *)&asn1_DEF_%s,\n",
1313 asn1c_type_name(arg, expr, TNF_SAFE));
1314 }
Lev Walkin59004fa2004-08-20 13:37:01 +00001315 if(C99_MODE) OUT(".memb_constraints = ");
1316 if(expr->constraints) {
Lev Walkin59964be2004-08-25 02:03:12 +00001317 char *id = MKID(expr->Identifier);
Lev Walkin59004fa2004-08-20 13:37:01 +00001318 if(!expr->Identifier)
Lev Walkin59964be2004-08-25 02:03:12 +00001319 id = asn1c_type_name(arg, expr, TNF_SAFE);
1320 OUT("memb_%s_%d_constraint,\n", id,
Lev Walkin08079b02004-08-22 03:25:24 +00001321 ++global_memb_unique);
Lev Walkin59004fa2004-08-20 13:37:01 +00001322 } else {
1323 OUT("0,\t/* Defer to actual type */\n");
1324 }
1325 if(C99_MODE) OUT(".name = ");
1326 OUT("\"%s\"\n", expr->Identifier ? expr->Identifier : "");
1327 OUT("},\n");
1328 INDENT(-1);
1329
1330 if(!expr->constraints)
1331 return 0;
1332
1333 save_target = arg->target->target;
1334 REDIR(OT_CODE);
1335
1336 if(expr->Identifier)
1337 p = MKID(expr->Identifier);
1338 else
1339 p = asn1c_type_name(arg, expr, TNF_SAFE);
1340 OUT("static int\n");
Lev Walkin08079b02004-08-22 03:25:24 +00001341 OUT("memb_%s_%d_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,\n", p, global_memb_unique);
Lev Walkin59004fa2004-08-20 13:37:01 +00001342 INDENT(+1);
1343 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
1344 tmp_arg = *arg;
1345 tmp_arg.expr = expr;
1346 if(asn1c_emit_constraint_checking_code(&tmp_arg) == 1) {
1347 OUT("return td->check_constraints\n");
1348 OUT("\t(td, sptr, app_errlog, app_key);\n");
1349 }
1350 INDENT(-1);
1351 OUT("}\n");
1352 OUT("\n");
1353
1354 REDIR(save_target);
1355
1356 return 0;
1357}
Lev Walkin59964be2004-08-25 02:03:12 +00001358
1359static int
Lev Walkin188ed2c2004-09-13 08:31:01 +00001360emit_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) {
Lev Walkin59964be2004-08-25 02:03:12 +00001361 char *p;
1362
1363 p = MKID(expr->Identifier);
Lev Walkindd32b592004-09-06 08:07:29 +00001364 if(HIDE_INNER_DEFS)
1365 OUT("static /* Use -fall-defs-global to expose */\n");
Lev Walkin59964be2004-08-25 02:03:12 +00001366 OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
Lev Walkin188ed2c2004-09-13 08:31:01 +00001367 INDENT(+1);
Lev Walkin59964be2004-08-25 02:03:12 +00001368 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
1369
1370 if(expr->expr_type & ASN_CONSTR_MASK) {
1371 p = asn1c_type_name(arg, arg->expr, TNF_SAFE);
1372 }
1373
1374 OUT("%s_constraint,\n", p);
1375 OUT("%s_decode_ber,\n", p);
1376 OUT("%s_encode_der,\n", p);
1377 OUT("%s_print,\n", p);
1378 OUT("%s_free,\n", p);
1379
1380 p = MKID(expr->Identifier);
1381
1382 if(expr->expr_type == ASN_CONSTR_CHOICE) {
1383 OUT("CHOICE_outmost_tag,\n");
1384 } else {
1385 OUT("0,\t/* Use generic outmost tag fetcher */\n");
1386 }
1387
1388 if(tags_count) {
1389 OUT("asn1_DEF_%s_tags,\n", p);
1390 OUT("sizeof(asn1_DEF_%s_tags)\n", p);
Lev Walkin188ed2c2004-09-13 08:31:01 +00001391 OUT("\t/sizeof(asn1_DEF_%s_tags[0])", p);
1392 if(tv_mode == _TVM_SUBSET
1393 && tags_count != all_tags_count)
1394 OUT(" - %d", all_tags_count - tags_count);
1395 OUT(", /* %d */\n", tags_count);
Lev Walkin59964be2004-08-25 02:03:12 +00001396 } else {
Lev Walkin188ed2c2004-09-13 08:31:01 +00001397 OUT("0,\t/* No effective tags (pointer) */\n");
1398 OUT("0,\t/* No effective tags (count) */\n");
1399 }
1400
1401 if(all_tags_count && tv_mode == _TVM_DIFFERENT) {
1402 OUT("asn1_DEF_%s_all_tags,\n", p);
1403 OUT("sizeof(asn1_DEF_%s_all_tags)\n", p);
1404 OUT("\t/sizeof(asn1_DEF_%s_all_tags[0]), /* %d */\n",
1405 p, all_tags_count);
1406 } else if(all_tags_count) {
1407 OUT("asn1_DEF_%s_tags,\t/* Same as above */\n", p);
1408 OUT("sizeof(asn1_DEF_%s_tags)\n", p);
1409 OUT("\t/sizeof(asn1_DEF_%s_tags[0]), /* %d */\n",
1410 p, all_tags_count);
1411 } else {
1412 OUT("0,\t/* No tags (pointer) */\n");
1413 OUT("0,\t/* No tags (count) */\n");
Lev Walkin59964be2004-08-25 02:03:12 +00001414 }
1415
Lev Walkin59964be2004-08-25 02:03:12 +00001416 switch(cp) {
1417 case ETD_CP_UNKNOWN:
1418 OUT("-0,\t/* Unknown yet */\n");
1419 break;
1420 case ETD_CP_EITHER:
1421 OUT("-1,\t/* Primitive or constructed */\n");
1422 case ETD_CP_PRIMITIVE:
1423 OUT("0,\t/* Primitive */\n");
1424 break;
1425 case ETD_CP_CONSTRUCTED:
1426 OUT("1,\t/* Whether CONSTRUCTED */\n");
1427 break;
1428 }
1429
1430 if(elements_count) {
1431 OUT("asn1_MBR_%s,\n", p);
1432 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF
1433 || expr->expr_type == ASN_CONSTR_SET_OF) {
1434 OUT("%d,\t/* Single element */\n",
1435 elements_count);
1436 assert(elements_count == 1);
1437 } else {
1438 OUT("%d,\t/* Elements count */\n",
1439 elements_count);
1440 }
1441 } else {
1442 //if(expr->meta_type == AMT_TYPEREF)
1443 if(expr_elements_count(arg, expr))
1444 OUT("0, 0,\t/* Defined elsewhere */\n");
1445 else
1446 OUT("0, 0,\t/* No members */\n");
1447 }
1448
1449 switch(spec) {
1450 case ETD_NO_SPECIFICS:
1451 OUT("0\t/* No specifics */\n");
1452 break;
1453 case ETD_HAS_SPECIFICS:
1454 OUT("&asn1_DEF_%s_specs\t/* Additional specs */\n", p);
1455 }
Lev Walkin188ed2c2004-09-13 08:31:01 +00001456 INDENT(-1);
Lev Walkin59964be2004-08-25 02:03:12 +00001457 OUT("};\n");
1458 OUT("\n");
Lev Walkin97298782004-08-26 06:20:34 +00001459
1460 return 0;
Lev Walkin59964be2004-08-25 02:03:12 +00001461}
Lev Walkincc93b0f2004-09-10 09:18:20 +00001462
1463/*
1464 * Check if it is better to make this type indirectly accessed via
1465 * a pointer.
1466 * This may be the case for the following recursive definition:
1467 * Type ::= CHOICE { member Type };
1468 */
1469static int
1470expr_better_indirect(arg_t *arg, asn1p_expr_t *expr) {
1471 asn1p_expr_t *top_parent;
1472 asn1p_expr_t *terminal;
1473
1474 if(expr->expr_type != A1TC_REFERENCE)
1475 return 0;
1476
1477 /* Rewind to the topmost parent expression */
1478 if((top_parent = expr->parent_expr)) {
1479 while(top_parent->parent_expr)
1480 top_parent = top_parent->parent_expr;
1481 } else {
1482 return 0;
1483 }
1484
1485 terminal = asn1f_find_terminal_type_ex(arg->asn, arg->mod, expr);
1486
1487 return (terminal == top_parent);
1488}