blob: eaac64423355cbfc7f4a7ca11217547483c39044 [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);
vlmb2839012004-08-20 13:37:01 +000022static int _expr_elements_count(arg_t *arg, asn1p_expr_t *expr);
23static int _emit_member_table(arg_t *arg, asn1p_expr_t *expr);
vlm4e03ce22004-06-06 07:20:17 +000024
vlmfa67ddc2004-06-03 03:38:44 +000025static int asn1c_lang_C_type_SEQUENCE_def(arg_t *arg);
26static int asn1c_lang_C_type_SET_def(arg_t *arg);
27static int asn1c_lang_C_type_CHOICE_def(arg_t *arg);
28static int asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of);
29static int _print_tag(arg_t *arg, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag_p);
vlm79b08d52004-07-01 00:52:50 +000030static int check_if_extensible(asn1p_expr_t *expr);
vlm6e73a042004-08-11 07:17:22 +000031static int emit_tags_vector(arg_t *arg, asn1p_expr_t *expr, int *tags_impl_skip, int choice_mode);
vlm4e03ce22004-06-06 07:20:17 +000032static int emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count);
vlmfa67ddc2004-06-03 03:38:44 +000033
vlmb2839012004-08-20 13:37:01 +000034#define C99_MODE (!(arg->flags & A1C_NO_C99))
vlmfa67ddc2004-06-03 03:38:44 +000035#define UNNAMED_UNIONS (arg->flags & A1C_UNNAMED_UNIONS)
36
37#define PCTX_DEF INDENTED( \
38 OUT("\n"); \
39 OUT("/* Context for parsing across buffer boundaries */\n"); \
40 OUT("ber_dec_ctx_t _ber_dec_ctx;\n"));
41
vlm33a4ff12004-08-11 05:21:32 +000042#define DEPENDENCIES do { \
vlmdae7f9d2004-08-22 03:25:24 +000043 asn1p_expr_t *__m; \
44 TQ_FOR(__m, &(expr->members), next) { \
45 if((!(__m->expr_type & ASN_CONSTR_MASK) \
46 && __m->expr_type > ASN_CONSTR_MASK) \
47 || __m->meta_type == AMT_TYPEREF) { \
48 GEN_INCLUDE(asn1c_type_name(arg, \
49 __m, TNF_INCLUDE)); \
vlm33a4ff12004-08-11 05:21:32 +000050 } \
51 } \
52 if(expr->expr_type == ASN_CONSTR_SET_OF) \
53 GEN_INCLUDE("asn_SET_OF"); \
54 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF) \
55 GEN_INCLUDE("asn_SEQUENCE_OF"); \
56} while(0)
vlmfa67ddc2004-06-03 03:38:44 +000057
58#define MKID(id) asn1c_make_identifier(0, (id), 0)
59
60int
61asn1c_lang_C_type_ENUMERATED(arg_t *arg) {
62 asn1p_expr_t *expr = arg->expr;
63 asn1p_expr_t *v;
64
65 REDIR(OT_DEPS);
66
67 OUT("typedef enum %s {\n", MKID(expr->Identifier));
68 TQ_FOR(v, &(expr->members), next) {
69 switch(v->expr_type) {
70 case A1TC_UNIVERVAL:
71 OUT("\t%s\t= %lld,\n",
72 asn1c_make_identifier(0,
73 expr->Identifier,
74 v->Identifier, 0),
75 v->value->value.v_integer);
76 break;
77 case A1TC_EXTENSIBLE:
78 OUT("\t/*\n");
79 OUT("\t * Enumeration is extensible\n");
80 OUT("\t */\n");
81 break;
82 default:
83 return -1;
84 }
85 }
86 OUT("} %s_e;\n", MKID(expr->Identifier));
87
88 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
89}
90
91
92int
93asn1c_lang_C_type_INTEGER(arg_t *arg) {
94 asn1p_expr_t *expr = arg->expr;
95 asn1p_expr_t *v;
96
97 REDIR(OT_DEPS);
98
99 if(TQ_FIRST(&(expr->members))) {
100 OUT("typedef enum %s {\n", MKID(expr->Identifier));
101 TQ_FOR(v, &(expr->members), next) {
102 switch(v->expr_type) {
103 case A1TC_UNIVERVAL:
104 OUT("\t%s\t= %lld,\n",
105 asn1c_make_identifier(0,
106 expr->Identifier,
107 v->Identifier, 0),
108 v->value->value.v_integer);
109 break;
110 default:
111 return -1;
112 }
113 }
114 OUT("} %s_e;\n", MKID(expr->Identifier));
115 }
116
117 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
118}
119
120int
121asn1c_lang_C_type_SEQUENCE(arg_t *arg) {
122 asn1p_expr_t *expr = arg->expr;
123 asn1p_expr_t *v;
124 int comp_mode = 0; /* {root,ext=1,root,root,...} */
125
126 DEPENDENCIES;
127
128 if(arg->embed) {
vlmdae7f9d2004-08-22 03:25:24 +0000129 OUT("struct %s {\n", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000130 } else {
131 OUT("typedef struct %s {\n",
132 MKID(expr->Identifier));
133 }
134
135 TQ_FOR(v, &(expr->members), next) {
136 if(v->expr_type == A1TC_EXTENSIBLE) {
137 if(comp_mode < 3) comp_mode++;
138 }
139 if(comp_mode == 1 && !v->marker)
140 v->marker = EM_OPTIONAL;
141 EMBED(v);
142 }
143
144 PCTX_DEF;
vlmdae7f9d2004-08-22 03:25:24 +0000145 OUT("} %s%s%s", expr->marker?"*":"",
146 expr->_anonymous_type ? "" : MKID(expr->Identifier),
147 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000148
149 return asn1c_lang_C_type_SEQUENCE_def(arg);
150}
151
152static int
153asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
154 asn1p_expr_t *expr = arg->expr;
155 asn1p_expr_t *v;
156 int elements; /* Number of elements */
157 int tags_impl_skip = 0;
158 int comp_mode = 0; /* {root,ext=1,root,root,...} */
159 int ext_start = -1;
160 int ext_stop = -1;
vlm4e03ce22004-06-06 07:20:17 +0000161 tag2el_t *tag2el = NULL;
162 int tag2el_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000163 int tags_count;
vlmfa67ddc2004-06-03 03:38:44 +0000164 char *p;
165
vlm4e03ce22004-06-06 07:20:17 +0000166 /*
167 * Fetch every inner tag from the tag to elements map.
168 */
169 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
170 if(tag2el) free(tag2el);
171 return -1;
172 }
173
vlm33a4ff12004-08-11 05:21:32 +0000174 GEN_INCLUDE("constr_SEQUENCE");
175 if(!arg->embed)
176 GEN_DECLARE(expr); /* asn1_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000177
vlm33a4ff12004-08-11 05:21:32 +0000178 REDIR(OT_STAT_DEFS);
vlmfa67ddc2004-06-03 03:38:44 +0000179
180 /*
181 * Print out the table according to which the parsing is performed.
182 */
183 p = MKID(expr->Identifier);
vlmb2839012004-08-20 13:37:01 +0000184 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000185
186 elements = 0;
187 INDENTED(TQ_FOR(v, &(expr->members), next) {
188 if(v->expr_type == A1TC_EXTENSIBLE) {
189 if((++comp_mode) == 1)
190 ext_start = elements - 1;
191 else
192 ext_stop = elements - 1;
193 continue;
194 }
vlmfa67ddc2004-06-03 03:38:44 +0000195 elements++;
vlmb2839012004-08-20 13:37:01 +0000196 _emit_member_table(arg, v);
vlmfa67ddc2004-06-03 03:38:44 +0000197 });
198 OUT("};\n");
199
vlm4a3f5822004-06-28 21:13:46 +0000200 /*
201 * Print out asn1_DEF_<type>_tags[] vector.
202 */
vlm6e73a042004-08-11 07:17:22 +0000203 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000204
vlm4e03ce22004-06-06 07:20:17 +0000205 /*
206 * Tags to elements map.
207 */
208 emit_tag2member_map(arg, tag2el, tag2el_count);
209
vlm4a3f5822004-06-28 21:13:46 +0000210 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000211 OUT("static asn1_SEQUENCE_specifics_t asn1_DEF_%s_specs = {\n", p);
212 INDENTED(
213 OUT("sizeof(struct %s),\n", p);
214 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
vlm4e03ce22004-06-06 07:20:17 +0000215 OUT("asn1_DEF_%s_tag2el,\n", p);
216 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
vlmfa67ddc2004-06-03 03:38:44 +0000217 OUT("%d,\t/* Start extensions */\n",
218 ext_start);
219 OUT("%d\t/* Stop extensions */\n",
220 (ext_stop<ext_start)?elements+1:ext_stop, ext_stop);
221 );
222 OUT("};\n");
223 OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
224 INDENTED(
vlmdae7f9d2004-08-22 03:25:24 +0000225 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000226 OUT("SEQUENCE_constraint,\n");
227 OUT("SEQUENCE_decode_ber,\n");
228 OUT("SEQUENCE_encode_der,\n");
229 OUT("SEQUENCE_print,\n");
230 OUT("SEQUENCE_free,\n");
231 OUT("0,\t/* Use generic outmost tag fetcher */\n");
vlm6e73a042004-08-11 07:17:22 +0000232 if(tags_count) {
233 OUT("asn1_DEF_%s_tags,\n", p);
234 OUT("sizeof(asn1_DEF_%s_tags)\n", p);
235 OUT("\t/sizeof(asn1_DEF_%s_tags[0]), /* %d */\n",
236 p, tags_count);
237 } else {
238 OUT("0,\t/* No explicit tags (pointer) */\n");
239 OUT("0,\t/* No explicit tags (count) */\n");
240 }
vlmfa67ddc2004-06-03 03:38:44 +0000241 OUT("%d,\t/* Tags to skip */\n", tags_impl_skip);
242 OUT("%d,\t/* Whether CONSTRUCTED */\n", 1);
vlmb2839012004-08-20 13:37:01 +0000243 OUT("asn1_MBR_%s,\n", p);
244 OUT("%d,\t/* Elements count */\n", elements);
vlmfa67ddc2004-06-03 03:38:44 +0000245 OUT("&asn1_DEF_%s_specs\t/* Additional specs */\n", p);
246 );
247 OUT("};\n");
248 OUT("\n");
249
vlmfa67ddc2004-06-03 03:38:44 +0000250 REDIR(OT_TYPE_DECLS);
251
252 return 0;
253}
254
255int
vlmfa67ddc2004-06-03 03:38:44 +0000256asn1c_lang_C_type_SET(arg_t *arg) {
257 asn1p_expr_t *expr = arg->expr;
258 asn1p_expr_t *v;
259 long mcount;
260 char *id;
261 int comp_mode = 0; /* {root,ext=1,root,root,...} */
262
263 DEPENDENCIES;
264
265 REDIR(OT_DEPS);
266
267 OUT("\n");
268 OUT("/*\n");
269 OUT(" * Method of determining the components presence\n");
270 OUT(" */\n");
271 mcount = 0;
vlm6e73a042004-08-11 07:17:22 +0000272 OUT("typedef enum %s_PR {\n", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000273 TQ_FOR(v, &(expr->members), next) {
274 if(v->expr_type == A1TC_EXTENSIBLE) continue;
275 INDENTED(
276 id = MKID(expr->Identifier);
277 OUT("%s_PR_", id);
278 id = MKID(v->Identifier);
279 OUT("%s,\t/* Member %s is present */\n",
280 id, id)
281 );
282 mcount++;
283 }
vlm6e73a042004-08-11 07:17:22 +0000284 id = MKID(expr->Identifier);
285 OUT("} %s_PR;\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000286
287 REDIR(OT_TYPE_DECLS);
288
289 if(arg->embed) {
vlm6e73a042004-08-11 07:17:22 +0000290 OUT("struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000291 } else {
vlm6e73a042004-08-11 07:17:22 +0000292 OUT("typedef struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000293 }
294
295 TQ_FOR(v, &(expr->members), next) {
296 if(v->expr_type == A1TC_EXTENSIBLE) {
297 if(comp_mode < 3) comp_mode++;
298 }
299 if(comp_mode == 1 && !v->marker)
300 v->marker = EM_OPTIONAL;
301 EMBED(v);
302 }
303
304 INDENTED(
305 id = MKID(expr->Identifier);
306 OUT("\n");
307 OUT("/* Presence bitmask: ASN_SET_ISPRESENT(p%s, %s_PR_x) */\n",
308 id, id);
309 OUT("unsigned int _presence_map\n");
310 OUT("\t[((%ld+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))];\n", mcount);
311 );
312
313 PCTX_DEF;
vlmdae7f9d2004-08-22 03:25:24 +0000314 OUT("} %s%s%s", expr->marker?"*":"",
315 expr->_anonymous_type ? "" : MKID(expr->Identifier),
316 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000317
318 return asn1c_lang_C_type_SET_def(arg);
319}
320
vlmfa67ddc2004-06-03 03:38:44 +0000321static int
322asn1c_lang_C_type_SET_def(arg_t *arg) {
323 asn1p_expr_t *expr = arg->expr;
324 asn1p_expr_t *v;
325 int elements;
326 int tags_impl_skip = 0;
327 int comp_mode = 0; /* {root,ext=1,root,root,...} */
vlmfa67ddc2004-06-03 03:38:44 +0000328 tag2el_t *tag2el = NULL;
329 int tag2el_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000330 int tags_count;
vlmfa67ddc2004-06-03 03:38:44 +0000331 char *p;
332
333 /*
334 * Fetch every inner tag from the tag to elements map.
335 */
336 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
337 if(tag2el) free(tag2el);
338 return -1;
vlmfa67ddc2004-06-03 03:38:44 +0000339 }
340
vlm33a4ff12004-08-11 05:21:32 +0000341 GEN_INCLUDE("constr_SET");
342 if(!arg->embed)
343 GEN_DECLARE(expr); /* asn1_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000344
345 REDIR(OT_STAT_DEFS);
346
vlmfa67ddc2004-06-03 03:38:44 +0000347 /*
348 * Print out the table according to which the parsing is performed.
349 */
350 p = MKID(expr->Identifier);
vlmb2839012004-08-20 13:37:01 +0000351 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000352
353 elements = 0;
354 INDENTED(TQ_FOR(v, &(expr->members), next) {
355 if(v->expr_type != A1TC_EXTENSIBLE) {
356 if(comp_mode == 1)
357 v->marker = EM_OPTIONAL;
vlmfa67ddc2004-06-03 03:38:44 +0000358 } else {
359 if(comp_mode < 3) comp_mode++;
360 continue;
361 }
vlmb2839012004-08-20 13:37:01 +0000362 elements++;
363 _emit_member_table(arg, v);
vlmfa67ddc2004-06-03 03:38:44 +0000364 });
365 OUT("};\n");
366
vlm4a3f5822004-06-28 21:13:46 +0000367 /*
368 * Print out asn1_DEF_<type>_tags[] vector.
369 */
vlm6e73a042004-08-11 07:17:22 +0000370 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000371
372 /*
373 * Tags to elements map.
374 */
vlm4e03ce22004-06-06 07:20:17 +0000375 emit_tag2member_map(arg, tag2el, tag2el_count);
vlmfa67ddc2004-06-03 03:38:44 +0000376
377 /*
378 * Emit a map of mandatory elements.
379 */
vlm4a3f5822004-06-28 21:13:46 +0000380 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000381 OUT("static uint8_t asn1_DEF_%s_mmap", p);
382 OUT("[(%d + (8 * sizeof(unsigned int)) - 1) / 8]", elements);
383 OUT(" = {\n", p);
384 INDENTED(
385 if(elements) {
386 int delimit = 0;
387 int el = 0;
388 TQ_FOR(v, &(expr->members), next) {
389 if(v->expr_type == A1TC_EXTENSIBLE) continue;
390 if(delimit) {
391 OUT(",\n");
392 delimit = 0;
393 } else if(el) {
394 OUT(" | ");
395 }
396 OUT("(%d << %d)", v->marker?0:1, 7 - (el % 8));
397 if(el && (el % 8) == 0)
398 delimit = 1;
399 el++;
400 }
401 } else {
402 OUT("0");
403 }
404 );
405 OUT("\n");
406 OUT("};\n");
407
408 OUT("static asn1_SET_specifics_t asn1_DEF_%s_specs = {\n", p);
409 INDENTED(
410 OUT("sizeof(struct %s),\n", p);
411 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
412 OUT("offsetof(struct %s, _presence_map),\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000413 OUT("asn1_DEF_%s_tag2el,\n", p);
414 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
vlm79b08d52004-07-01 00:52:50 +0000415 OUT("%d,\t/* Whether extensible */\n",
416 check_if_extensible(expr));
vlmfa67ddc2004-06-03 03:38:44 +0000417 OUT("(unsigned int *)asn1_DEF_%s_mmap\t/* Mandatory elements map */\n", p);
418 );
419 OUT("};\n");
420 OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
421 INDENTED(
vlmdae7f9d2004-08-22 03:25:24 +0000422 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000423 OUT("SET_constraint,\n");
424 OUT("SET_decode_ber,\n");
425 OUT("SET_encode_der,\n");
426 OUT("SET_print,\n");
427 OUT("SET_free,\n");
428 OUT("0,\t/* Use generic outmost tag fetcher */\n");
vlm6e73a042004-08-11 07:17:22 +0000429 if(tags_count) {
430 OUT("asn1_DEF_%s_tags,\n", p);
431 OUT("sizeof(asn1_DEF_%s_tags)\n", p);
432 OUT("\t/sizeof(asn1_DEF_%s_tags[0]), /* %d */\n",
433 p, tags_count);
434 } else {
435 OUT("0,\t/* No explicit tags (pointer) */\n");
436 OUT("0,\t/* No explicit tags (count) */\n");
437 }
vlmfa67ddc2004-06-03 03:38:44 +0000438 OUT("%d,\t/* Tags to skip */\n", tags_impl_skip);
439 OUT("%d,\t/* Whether CONSTRUCTED */\n", 1);
vlmb2839012004-08-20 13:37:01 +0000440 OUT("asn1_MBR_%s,\n", p);
441 OUT("%d,\t/* Elements count */\n", elements);
vlmfa67ddc2004-06-03 03:38:44 +0000442 OUT("&asn1_DEF_%s_specs\t/* Additional specs */\n", p);
443 );
444 OUT("};\n");
445 OUT("\n");
446
vlmfa67ddc2004-06-03 03:38:44 +0000447 REDIR(OT_TYPE_DECLS);
448
449 return 0;
450}
451
452int
vlmdae7f9d2004-08-22 03:25:24 +0000453asn1c_lang_C_type_SEx_OF(arg_t *arg) {
vlmfa67ddc2004-06-03 03:38:44 +0000454 asn1p_expr_t *expr = arg->expr;
vlmdae7f9d2004-08-22 03:25:24 +0000455 asn1p_expr_t *memb;
vlmfa67ddc2004-06-03 03:38:44 +0000456
457 DEPENDENCIES;
458
459 if(arg->embed) {
460 OUT("struct %s {\n", MKID(expr->Identifier));
461 } else {
vlmdae7f9d2004-08-22 03:25:24 +0000462 OUT("typedef struct %s {\n", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000463 }
464
vlmdae7f9d2004-08-22 03:25:24 +0000465 memb = TQ_FIRST(&expr->members);
466
467 INDENT(+1);
468 OUT("A_%s_OF(",
469 (arg->expr->expr_type == ASN_CONSTR_SET_OF)
470 ? "SET" : "SEQUENCE");
471 if(memb->expr_type & ASN_CONSTR_MASK) {
472 arg_t tmp;
473 asn1p_expr_t tmp_memb;
474 arg->embed++;
475 tmp = *arg;
476 tmp.expr = &tmp_memb;
477 tmp_memb = *memb;
478 tmp_memb._anonymous_type = 1;
479 tmp_memb.Identifier = strdup(
480 asn1c_make_identifier(0,
481 expr->Identifier, "member", 0));
482 assert(tmp_memb.Identifier);
483 tmp.default_cb(&tmp);
484 free(tmp_memb.Identifier);
485 arg->embed--;
486 assert(arg->target->target == OT_TYPE_DECLS);
487 } else {
488 OUT("%s", asn1c_type_name(arg, memb, TNF_RSAFE));
vlmfa67ddc2004-06-03 03:38:44 +0000489 }
vlmdae7f9d2004-08-22 03:25:24 +0000490 OUT(") list;\n");
491 INDENT(-1);
vlmfa67ddc2004-06-03 03:38:44 +0000492
493 PCTX_DEF;
vlmdae7f9d2004-08-22 03:25:24 +0000494 OUT("} %s%s%s", expr->marker?"*":"",
495 expr->_anonymous_type ? "" : MKID(expr->Identifier),
496 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000497
498 /*
vlmdae7f9d2004-08-22 03:25:24 +0000499 * SET OF/SEQUENCE OF definition
vlmfa67ddc2004-06-03 03:38:44 +0000500 */
vlmdae7f9d2004-08-22 03:25:24 +0000501 return asn1c_lang_C_type_SEx_OF_def(arg,
502 (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF));
vlmfa67ddc2004-06-03 03:38:44 +0000503}
504
505static int
506asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
507 asn1p_expr_t *expr = arg->expr;
508 asn1p_expr_t *v;
509 int tags_impl_skip = 0;
vlm6e73a042004-08-11 07:17:22 +0000510 int tags_count;
vlmfa67ddc2004-06-03 03:38:44 +0000511 char *p;
512
vlm33a4ff12004-08-11 05:21:32 +0000513 /*
514 * Print out the table according to which the parsing is performed.
515 */
vlmfa67ddc2004-06-03 03:38:44 +0000516 if(seq_of) {
vlm33a4ff12004-08-11 05:21:32 +0000517 GEN_INCLUDE("constr_SEQUENCE_OF");
vlmfa67ddc2004-06-03 03:38:44 +0000518 } else {
vlm33a4ff12004-08-11 05:21:32 +0000519 GEN_INCLUDE("constr_SET_OF");
vlmfa67ddc2004-06-03 03:38:44 +0000520 }
vlm33a4ff12004-08-11 05:21:32 +0000521 if(!arg->embed)
522 GEN_DECLARE(expr); /* asn1_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000523
524 REDIR(OT_STAT_DEFS);
525
526 /*
527 * Print out the table according to which the parsing is performed.
528 */
529 p = MKID(expr->Identifier);
vlmb2839012004-08-20 13:37:01 +0000530 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000531
vlmb2839012004-08-20 13:37:01 +0000532 INDENTED(
vlmfa67ddc2004-06-03 03:38:44 +0000533 v = TQ_FIRST(&(expr->members));
vlmb2839012004-08-20 13:37:01 +0000534 _emit_member_table(arg, v);
vlmfa67ddc2004-06-03 03:38:44 +0000535 );
536 OUT("};\n");
537
vlm4a3f5822004-06-28 21:13:46 +0000538 /*
539 * Print out asn1_DEF_<type>_tags[] vector.
540 */
vlm6e73a042004-08-11 07:17:22 +0000541 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000542
vlm4a3f5822004-06-28 21:13:46 +0000543 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000544 OUT("static asn1_SET_OF_specifics_t asn1_DEF_%s_specs = {\n", p);
545 INDENTED(
546 OUT("sizeof(struct %s),\n", p);
547 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000548 );
549 OUT("};\n");
550 OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
551 INDENTED(
vlmdae7f9d2004-08-22 03:25:24 +0000552 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000553 if(seq_of) {
554 OUT("SEQUENCE_OF_constraint,\n");
555 OUT("SEQUENCE_OF_decode_ber,\n");
556 OUT("SEQUENCE_OF_encode_der,\n");
557 OUT("SEQUENCE_OF_print,\n");
558 OUT("SEQUENCE_OF_free,\n");
559 } else {
560 OUT("SET_OF_constraint,\n");
561 OUT("SET_OF_decode_ber,\n");
562 OUT("SET_OF_encode_der,\n");
563 OUT("SET_OF_print,\n");
564 OUT("SET_OF_free,\n");
565 }
566 OUT("0,\t/* Use generic outmost tag fetcher */\n");
vlm6e73a042004-08-11 07:17:22 +0000567 if(tags_count) {
568 OUT("asn1_DEF_%s_tags,\n", p);
569 OUT("sizeof(asn1_DEF_%s_tags)\n", p);
570 OUT("\t/sizeof(asn1_DEF_%s_tags[0]), /* %d */\n",
571 p, tags_count);
572 } else {
573 OUT("0,\t/* No explicit tags (pointer) */\n");
574 OUT("0,\t/* No explicit tags (count) */\n");
575 }
vlmfa67ddc2004-06-03 03:38:44 +0000576 OUT("%d,\t/* Tags to skip */\n", tags_impl_skip);
577 OUT("%d,\t/* Whether CONSTRUCTED */\n", 1);
vlmb2839012004-08-20 13:37:01 +0000578 OUT("asn1_MBR_%s,\n", p);
579 OUT("1,\t/* Single element */\n");
vlmfa67ddc2004-06-03 03:38:44 +0000580 OUT("&asn1_DEF_%s_specs\t/* Additional specs */\n", p);
581 );
582 OUT("};\n");
583 OUT("\n");
584
vlmfa67ddc2004-06-03 03:38:44 +0000585 REDIR(OT_TYPE_DECLS);
586
587 return 0;
588}
589
590int
591asn1c_lang_C_type_CHOICE(arg_t *arg) {
592 asn1p_expr_t *expr = arg->expr;
593 asn1p_expr_t *v;
vlmdae7f9d2004-08-22 03:25:24 +0000594 char *id;
vlmfa67ddc2004-06-03 03:38:44 +0000595
596 DEPENDENCIES;
597
vlm33a4ff12004-08-11 05:21:32 +0000598 REDIR(OT_DEPS);
599
vlmdae7f9d2004-08-22 03:25:24 +0000600 id = MKID(expr->Identifier);
601 OUT("typedef enum %s_PR {\n", id);
vlm33a4ff12004-08-11 05:21:32 +0000602 INDENTED(
vlm33a4ff12004-08-11 05:21:32 +0000603 OUT("%s_PR_NOTHING,\t"
vlmdae7f9d2004-08-22 03:25:24 +0000604 "/* No components present */\n", id);
vlm33a4ff12004-08-11 05:21:32 +0000605 TQ_FOR(v, &(expr->members), next) {
606 if(v->expr_type == A1TC_EXTENSIBLE) {
607 OUT("/* Extensions may appear below */\n");
608 continue;
609 }
vlmdae7f9d2004-08-22 03:25:24 +0000610 id = MKID(expr->Identifier);
611 OUT("%s_PR_", id);
612 id = MKID(v->Identifier);
613 OUT("%s,\n", id, id);
vlm33a4ff12004-08-11 05:21:32 +0000614 }
615 );
vlmdae7f9d2004-08-22 03:25:24 +0000616 id = MKID(expr->Identifier);
617 OUT("} %s_PR;\n", id);
vlm33a4ff12004-08-11 05:21:32 +0000618
619 REDIR(OT_TYPE_DECLS);
vlmfa67ddc2004-06-03 03:38:44 +0000620
621 if(arg->embed) {
vlmdae7f9d2004-08-22 03:25:24 +0000622 OUT("struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000623 } else {
vlmdae7f9d2004-08-22 03:25:24 +0000624 OUT("typedef struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000625 }
626
627 INDENTED(
vlmdae7f9d2004-08-22 03:25:24 +0000628 OUT("%s_PR present;\n", id);
629 OUT("union {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000630 TQ_FOR(v, &(expr->members), next) {
631 EMBED(v);
632 }
633 if(UNNAMED_UNIONS) OUT("};\n");
634 else OUT("} choice;\n");
635 );
636
637 PCTX_DEF;
vlmdae7f9d2004-08-22 03:25:24 +0000638 OUT("} %s%s%s", expr->marker?"*":"",
639 expr->_anonymous_type ? "" : MKID(expr->Identifier),
640 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000641
642 return asn1c_lang_C_type_CHOICE_def(arg);
643}
644
645static int
646asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
647 asn1p_expr_t *expr = arg->expr;
648 asn1p_expr_t *v;
649 int elements; /* Number of elements */
650 int tags_impl_skip = 0;
651 int comp_mode = 0; /* {root,ext=1,root,root,...} */
vlmfa67ddc2004-06-03 03:38:44 +0000652 tag2el_t *tag2el = NULL;
653 int tag2el_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000654 int tags_count;
vlmfa67ddc2004-06-03 03:38:44 +0000655 char *p;
656
657 /*
658 * Fetch every inner tag from the tag to elements map.
659 */
660 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
661 if(tag2el) free(tag2el);
662 return -1;
vlmfa67ddc2004-06-03 03:38:44 +0000663 }
664
vlm33a4ff12004-08-11 05:21:32 +0000665 GEN_INCLUDE("constr_CHOICE");
666 if(!arg->embed)
667 GEN_DECLARE(expr); /* asn1_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000668
vlm33a4ff12004-08-11 05:21:32 +0000669 REDIR(OT_STAT_DEFS);
vlmfa67ddc2004-06-03 03:38:44 +0000670
671 /*
672 * Print out the table according to which the parsing is performed.
673 */
674 p = MKID(expr->Identifier);
vlmb2839012004-08-20 13:37:01 +0000675 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000676
677 elements = 0;
678 INDENTED(TQ_FOR(v, &(expr->members), next) {
679 if(v->expr_type != A1TC_EXTENSIBLE) {
680 if(comp_mode == 1)
681 v->marker = EM_OPTIONAL;
vlmfa67ddc2004-06-03 03:38:44 +0000682 } else {
683 if(comp_mode < 3) comp_mode++;
684 continue;
685 }
vlmb2839012004-08-20 13:37:01 +0000686 elements++;
687 _emit_member_table(arg, v);
vlmfa67ddc2004-06-03 03:38:44 +0000688 });
689 OUT("};\n");
690
vlm6e73a042004-08-11 07:17:22 +0000691
vlmfa67ddc2004-06-03 03:38:44 +0000692 if(arg->embed) {
693 /*
694 * Our parent structure has already taken this into account.
695 */
vlm6e73a042004-08-11 07:17:22 +0000696 tags_count = 0;
vlmfa67ddc2004-06-03 03:38:44 +0000697 } else {
vlm6e73a042004-08-11 07:17:22 +0000698 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 1);
vlmfa67ddc2004-06-03 03:38:44 +0000699 }
vlmfa67ddc2004-06-03 03:38:44 +0000700
701 /*
702 * Tags to elements map.
703 */
vlm4e03ce22004-06-06 07:20:17 +0000704 emit_tag2member_map(arg, tag2el, tag2el_count);
vlmfa67ddc2004-06-03 03:38:44 +0000705
vlm6e73a042004-08-11 07:17:22 +0000706 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000707 OUT("static asn1_CHOICE_specifics_t asn1_DEF_%s_specs = {\n", p);
708 INDENTED(
709 OUT("sizeof(struct %s),\n", p);
710 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
711 OUT("offsetof(struct %s, present),\n", p);
712 OUT("sizeof(((struct %s *)0)->present),\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000713 OUT("asn1_DEF_%s_tag2el,\n", p);
714 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
vlm79b08d52004-07-01 00:52:50 +0000715 OUT("%d\t/* Whether extensible */\n",
716 check_if_extensible(expr));
vlmfa67ddc2004-06-03 03:38:44 +0000717 );
718 OUT("};\n");
719 OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
720 INDENTED(
vlmdae7f9d2004-08-22 03:25:24 +0000721 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000722 OUT("CHOICE_constraint,\n");
723 OUT("CHOICE_decode_ber,\n");
724 OUT("CHOICE_encode_der,\n");
725 OUT("CHOICE_print,\n");
726 OUT("CHOICE_free,\n");
727 OUT("CHOICE_outmost_tag,\n");
vlm6e73a042004-08-11 07:17:22 +0000728 if(tags_count) {
729 OUT("asn1_DEF_%s_tags,\n", p);
730 OUT("sizeof(asn1_DEF_%s_tags)\n", p);
731 OUT("\t/sizeof(asn1_DEF_%s_tags[0]), /* %d */\n",
732 p, tags_count);
733 } else {
734 OUT("0,\t/* No explicit tags (pointer) */\n");
735 OUT("0,\t/* No explicit tags (count) */\n");
736 }
vlmfa67ddc2004-06-03 03:38:44 +0000737 OUT("%d,\t/* Tags to skip */\n", tags_impl_skip);
738 OUT("%d,\t/* Whether CONSTRUCTED */\n", 1);
vlmb2839012004-08-20 13:37:01 +0000739 OUT("asn1_MBR_%s,\n", p);
740 OUT("%d,\t/* Elements count */\n", elements);
vlmfa67ddc2004-06-03 03:38:44 +0000741 OUT("&asn1_DEF_%s_specs\t/* Additional specs */\n", p);
742 );
743 OUT("};\n");
744 OUT("\n");
745
vlmfa67ddc2004-06-03 03:38:44 +0000746 REDIR(OT_TYPE_DECLS);
747
748 return 0;
749}
750
751int
752asn1c_lang_C_type_REFERENCE(arg_t *arg) {
753 asn1p_ref_t *ref;
754
755 ref = arg->expr->reference;
756 if(ref->components[ref->comp_count-1].name[0] == '&') {
vlmfa67ddc2004-06-03 03:38:44 +0000757 asn1p_expr_t *extract;
758 arg_t tmp;
759 int ret;
760
vlmdae7f9d2004-08-22 03:25:24 +0000761 extract = asn1f_class_access_ex(arg->asn, arg->mod,
762 arg->expr, ref);
vlmfa67ddc2004-06-03 03:38:44 +0000763 if(extract == NULL)
764 return -1;
765
vlmdae7f9d2004-08-22 03:25:24 +0000766 extract = asn1p_expr_clone(extract, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000767 if(extract) {
768 if(extract->Identifier)
769 free(extract->Identifier);
770 extract->Identifier = strdup(arg->expr->Identifier);
771 if(extract->Identifier == NULL) {
772 asn1p_expr_free(extract);
773 return -1;
774 }
775 } else {
776 return -1;
777 }
778
779 tmp = *arg;
780 tmp.asn = arg->asn;
vlmdae7f9d2004-08-22 03:25:24 +0000781 tmp.mod = extract->module;
vlmfa67ddc2004-06-03 03:38:44 +0000782 tmp.expr = extract;
783
784 ret = arg->default_cb(&tmp);
785
786 asn1p_expr_free(extract);
787
788 return ret;
789 }
790
791
792 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
793}
794
795int
796asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
797 asn1p_expr_t *expr = arg->expr;
798 int tags_impl_skip = 0;
vlm6e73a042004-08-11 07:17:22 +0000799 int tags_count;
vlmfa67ddc2004-06-03 03:38:44 +0000800 char *p;
801
802 if(arg->embed) {
803 REDIR(OT_TYPE_DECLS);
804
805 OUT("%s\t", asn1c_type_name(arg, arg->expr,
806 expr->marker?TNF_RSAFE:TNF_CTYPE));
807 OUT("%s", expr->marker?"*":" ");
vlmdae7f9d2004-08-22 03:25:24 +0000808 OUT("%s", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000809 if(expr->marker) OUT("\t/* %s */",
810 (expr->marker==EM_OPTIONAL)?"OPTIONAL":"DEFAULT");
vlmb2839012004-08-20 13:37:01 +0000811
812 REDIR(OT_TYPE_DECLS);
vlmfa67ddc2004-06-03 03:38:44 +0000813 return 0;
814 }
815
vlmfa67ddc2004-06-03 03:38:44 +0000816
vlm33a4ff12004-08-11 05:21:32 +0000817 GEN_INCLUDE(asn1c_type_name(arg, expr, TNF_INCLUDE));
vlmfa67ddc2004-06-03 03:38:44 +0000818
819 REDIR(OT_TYPE_DECLS);
820
821 OUT("typedef %s\t", asn1c_type_name(arg, arg->expr, TNF_CTYPE));
822 OUT("%s", expr->marker?"*":" ");
vlmdae7f9d2004-08-22 03:25:24 +0000823 OUT("%s_t", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000824
825 REDIR(OT_STAT_DEFS);
826
vlm4a3f5822004-06-28 21:13:46 +0000827 /*
828 * Print out asn1_DEF_<type>_tags[] vector.
829 */
vlm6e73a042004-08-11 07:17:22 +0000830 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000831
vlm4a3f5822004-06-28 21:13:46 +0000832 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000833 OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
834 INDENTED(
vlmdae7f9d2004-08-22 03:25:24 +0000835 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000836 OUT("%s_constraint,\n", p);
837 OUT("%s_decode_ber,\n", p);
838 OUT("%s_encode_der,\n", p);
839 OUT("%s_print,\n", p);
840 OUT("%s_free,\n", p);
841 OUT("0,\t/* Use generic outmost tag fetcher */\n");
vlm6e73a042004-08-11 07:17:22 +0000842 if(tags_count) {
843 OUT("asn1_DEF_%s_tags,\n", p);
844 OUT("sizeof(asn1_DEF_%s_tags)\n", p);
845 OUT("\t/sizeof(asn1_DEF_%s_tags[0]), /* %d */\n",
846 p, tags_count);
847 } else {
848 OUT("0,\t/* No explicit tags (pointer) */\n");
849 OUT("0,\t/* No explicit tags (count) */\n");
850 }
vlmfa67ddc2004-06-03 03:38:44 +0000851 OUT("%d,\t/* Tags to skip */\n", tags_impl_skip);
vlm94faa932004-06-05 08:46:50 +0000852 OUT("-0,\t/* Unknown yet */\n");
vlmb2839012004-08-20 13:37:01 +0000853 if(_expr_elements_count(arg, expr))
854 OUT("0, 0,\t/* Defined elsewhere */\n");
855 else
856 OUT("0, 0,\t/* No members */\n");
vlm94faa932004-06-05 08:46:50 +0000857 OUT("0\t/* No specifics */\n");
vlmfa67ddc2004-06-03 03:38:44 +0000858 );
859 OUT("};\n");
860 OUT("\n");
861
vlmb2839012004-08-20 13:37:01 +0000862 REDIR(OT_CODE);
863
vlmfa67ddc2004-06-03 03:38:44 +0000864 /*
865 * Constraint checking.
866 */
vlmfa67ddc2004-06-03 03:38:44 +0000867 p = MKID(expr->Identifier);
868 OUT("int\n");
869 OUT("%s_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,\n", p);
870 INDENTED(
871 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
872 OUT("\n");
vlm1d036692004-08-19 13:29:46 +0000873 if(asn1c_emit_constraint_checking_code(arg) == 1) {
874 if(0) {
vlmfa67ddc2004-06-03 03:38:44 +0000875 OUT("/* Check the constraints of the underlying type */\n");
876 OUT("return asn1_DEF_%s.check_constraints\n",
877 asn1c_type_name(arg, expr, TNF_SAFE));
878 OUT("\t(td, sptr, app_errlog, app_key);\n");
vlm1d036692004-08-19 13:29:46 +0000879 } else {
vlmfa67ddc2004-06-03 03:38:44 +0000880 OUT("/* Make the underlying type checker permanent */\n");
881 OUT("td->check_constraints = asn1_DEF_%s.check_constraints;\n",
882 asn1c_type_name(arg, expr, TNF_SAFE));
883 OUT("return td->check_constraints\n");
884 OUT("\t(td, sptr, app_errlog, app_key);\n");
vlm1d036692004-08-19 13:29:46 +0000885 }
vlmfa67ddc2004-06-03 03:38:44 +0000886 }
887 );
888 OUT("}\n");
889 OUT("\n");
890
891 /*
892 * Emit suicidal functions.
893 */
894
vlmfa67ddc2004-06-03 03:38:44 +0000895 /*
896 * This function replaces certain fields from the definition
897 * of a type with the corresponding fields from the basic type
898 * (from which the current type is inherited).
899 */
vlmfa67ddc2004-06-03 03:38:44 +0000900 OUT("/*\n");
vlmb2839012004-08-20 13:37:01 +0000901 OUT(" * This type is implemented using %s,\n",
902 asn1c_type_name(arg, expr, TNF_SAFE));
vlmfa67ddc2004-06-03 03:38:44 +0000903 OUT(" * so adjust the DEF appropriately.\n");
904 OUT(" */\n");
905 OUT("static void\n");
vlmb2839012004-08-20 13:37:01 +0000906 p = MKID(expr->Identifier);
907 OUT("%s_inherit_TYPE_descriptor(asn1_TYPE_descriptor_t *td) {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000908 INDENT(+1);
vlmb2839012004-08-20 13:37:01 +0000909 {
910 char *type_name = asn1c_type_name(arg, expr, TNF_SAFE);
911 OUT("td->ber_decoder = asn1_DEF_%s.ber_decoder;\n", type_name);
912 OUT("td->der_encoder = asn1_DEF_%s.der_encoder;\n", type_name);
913 OUT("td->free_struct = asn1_DEF_%s.free_struct;\n", type_name);
914 OUT("td->print_struct = asn1_DEF_%s.print_struct;\n", type_name);
915 OUT("td->last_tag_form = asn1_DEF_%s.last_tag_form;\n", type_name);
916 OUT("td->elements = asn1_DEF_%s.elements;\n", type_name);
917 OUT("td->elements_count = asn1_DEF_%s.elements_count;\n", type_name);
918 OUT("td->specifics = asn1_DEF_%s.specifics;\n", type_name);
919 }
vlmfa67ddc2004-06-03 03:38:44 +0000920 INDENT(-1);
921 OUT("}\n");
922 OUT("\n");
vlmfa67ddc2004-06-03 03:38:44 +0000923
924 p = MKID(expr->Identifier);
925 OUT("ber_dec_rval_t\n");
926 OUT("%s_decode_ber(asn1_TYPE_descriptor_t *td,\n", p);
927 INDENTED(
928 OUT("\tvoid **structure, void *bufptr, size_t size, int tag_mode) {\n");
vlmb2839012004-08-20 13:37:01 +0000929 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000930 OUT("return td->ber_decoder(td, structure,\n");
931 OUT("\tbufptr, size, tag_mode);\n");
932 );
933 OUT("}\n");
934 OUT("\n");
935
936 p = MKID(expr->Identifier);
937 OUT("der_enc_rval_t\n");
938 OUT("%s_encode_der(asn1_TYPE_descriptor_t *td,\n", p);
939 INDENTED(
940 OUT("\tvoid *structure, int tag_mode, ber_tlv_tag_t tag,\n");
941 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
vlmb2839012004-08-20 13:37:01 +0000942 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000943 OUT("return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);\n");
944 );
945 OUT("}\n");
946 OUT("\n");
947
948 p = MKID(expr->Identifier);
949 OUT("int\n");
950 OUT("%s_print(asn1_TYPE_descriptor_t *td, const void *struct_ptr,\n", p);
951 INDENTED(
952 OUT("\tint ilevel, asn_app_consume_bytes_f *cb, void *app_key) {\n");
vlmb2839012004-08-20 13:37:01 +0000953 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000954 OUT("return td->print_struct(td, struct_ptr, ilevel, cb, app_key);\n");
955 );
956 OUT("}\n");
957 OUT("\n");
958
959 p = MKID(expr->Identifier);
960 OUT("void\n");
961 OUT("%s_free(asn1_TYPE_descriptor_t *td,\n", p);
962 INDENTED(
963 OUT("\tvoid *struct_ptr, int contents_only) {\n");
vlmb2839012004-08-20 13:37:01 +0000964 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000965 OUT("td->free_struct(td, struct_ptr, contents_only);\n");
966 );
967 OUT("}\n");
968 OUT("\n");
969
970 REDIR(OT_FUNC_DECLS);
971
972 p = MKID(expr->Identifier);
973 OUT("extern asn1_TYPE_descriptor_t asn1_DEF_%s;\n", p);
974 OUT("asn_constr_check_f %s_constraint;\n", p);
975 OUT("ber_type_decoder_f %s_decode_ber;\n", p);
976 OUT("der_type_encoder_f %s_encode_der;\n", p);
977 OUT("asn_struct_print_f %s_print;\n", p);
978 OUT("asn_struct_free_f %s_free;\n", p);
979
vlm33a4ff12004-08-11 05:21:32 +0000980 REDIR(OT_TYPE_DECLS);
981
vlmfa67ddc2004-06-03 03:38:44 +0000982 return 0;
983}
984
985int
986asn1c_lang_C_type_EXTENSIBLE(arg_t *arg) {
987
988 OUT("/*\n");
989 OUT(" * This type is extensible,\n");
990 OUT(" * possible extensions are below.\n");
991 OUT(" */\n");
992
993 return 0;
994}
995
vlm79b08d52004-07-01 00:52:50 +0000996static int check_if_extensible(asn1p_expr_t *expr) {
997 asn1p_expr_t *v;
998 TQ_FOR(v, &(expr->members), next) {
999 if(v->expr_type == A1TC_EXTENSIBLE) return 1;
1000 }
1001 return 0;
1002}
1003
vlmfa67ddc2004-06-03 03:38:44 +00001004static int
1005_print_tag(arg_t *arg, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag_p) {
1006 struct asn1p_type_tag_s tag;
1007
1008 if(tag_p) {
1009 tag = *tag_p;
1010 } else {
1011 if(asn1f_fetch_tag(arg->asn, arg->mod, expr, &tag)) {
1012 OUT("-1 /* Ambiguous tag (CHOICE?) */");
1013 return 0;
1014 }
1015 }
1016
1017 OUT("(");
1018 switch(tag.tag_class) {
1019 case TC_UNIVERSAL: OUT("ASN_TAG_CLASS_UNIVERSAL"); break;
1020 case TC_APPLICATION: OUT("ASN_TAG_CLASS_APPLICATION"); break;
1021 case TC_CONTEXT_SPECIFIC: OUT("ASN_TAG_CLASS_CONTEXT"); break;
1022 case TC_PRIVATE: OUT("ASN_TAG_CLASS_PRIVATE"); break;
1023 case TC_NOCLASS:
1024 break;
1025 }
1026 OUT(" | (%lld << 2))", tag.tag_value);
1027
1028 return 0;
1029}
1030
vlm4e03ce22004-06-06 07:20:17 +00001031
1032static int
1033_tag2el_cmp(const void *ap, const void *bp) {
1034 const tag2el_t *a = ap;
1035 const tag2el_t *b = bp;
1036 const struct asn1p_type_tag_s *ta = &a->el_tag;
1037 const struct asn1p_type_tag_s *tb = &b->el_tag;
1038
1039 if(ta->tag_class == tb->tag_class) {
1040 if(ta->tag_value == tb->tag_value) {
1041 /*
1042 * Sort by their respective positions.
1043 */
1044 if(a->el_no < b->el_no)
1045 return -1;
1046 else if(a->el_no > b->el_no)
1047 return 1;
1048 return 0;
1049 } else if(ta->tag_value < tb->tag_value)
1050 return -1;
1051 else
1052 return 1;
1053 } else if(ta->tag_class < tb->tag_class) {
1054 return -1;
1055 } else {
1056 return 1;
1057 }
1058}
1059
vlmfa67ddc2004-06-03 03:38:44 +00001060/*
1061 * For constructed types, number of external tags may be greater than
1062 * number of elements in the type because of CHOICE type.
1063 * T ::= SET { -- Three possible tags:
1064 * a INTEGER, -- One tag is here...
1065 * b Choice1 -- ... and two more tags are there.
1066 * }
1067 * Choice1 ::= CHOICE {
1068 * s1 IA5String,
1069 * s2 ObjectDescriptor
1070 * }
1071 */
1072static int
1073_fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no) {
1074 asn1p_expr_t *expr = arg->expr;
1075 arg_t tmparg = *arg;
1076 asn1p_expr_t *v;
1077 int element = 0;
1078
1079 TQ_FOR(v, &(expr->members), next) {
1080 if(v->expr_type == A1TC_EXTENSIBLE)
1081 continue;
1082
1083 tmparg.expr = v;
1084
1085 if(_add_tag2el_member(&tmparg, tag2el, count,
1086 (el_no==-1)?element:el_no)) {
1087 return -1;
1088 }
1089
1090 element++;
1091 }
1092
vlm4e03ce22004-06-06 07:20:17 +00001093 /*
vlmc8aeab42004-06-14 13:09:45 +00001094 * Sort the map according to canonical order of their tags
1095 * and element numbers.
vlm4e03ce22004-06-06 07:20:17 +00001096 */
1097 qsort(*tag2el, *count, sizeof(**tag2el), _tag2el_cmp);
1098
vlmc8aeab42004-06-14 13:09:45 +00001099 /*
1100 * Initialize .toff_{first|last} members.
1101 */
1102 if(*count) {
1103 struct asn1p_type_tag_s *cur_tag = 0;
1104 tag2el_t *cur = *tag2el;
1105 tag2el_t *end = cur + *count;
1106 int occur, i;
1107 for(occur = 0; cur < end; cur++) {
1108 if(cur_tag == 0
1109 || cur_tag->tag_value != cur->el_tag.tag_value
1110 || cur_tag->tag_class != cur->el_tag.tag_class) {
1111 cur_tag = &cur->el_tag;
1112 occur = 0;
1113 } else {
1114 occur++;
1115 }
1116 cur->toff_first = -occur;
1117 for(i = 0; i >= -occur; i--)
1118 cur[i].toff_last = -i;
1119 }
1120 }
1121
vlmfa67ddc2004-06-03 03:38:44 +00001122 return 0;
1123}
1124
1125static int
1126_add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no) {
1127 struct asn1p_type_tag_s tag;
1128 int ret;
1129
1130 assert(el_no >= 0);
1131
1132 ret = asn1f_fetch_tag(arg->asn, arg->mod, arg->expr, &tag);
1133 if(ret == 0) {
1134 void *p;
1135 p = realloc(*tag2el, sizeof(tag2el_t) * ((*count) + 1));
1136 if(p) *tag2el = p;
1137 else return -1;
1138
1139 DEBUG("Found tag for %s: %ld",
1140 arg->expr->Identifier,
1141 (long)tag.tag_value);
1142
1143 (*tag2el)[*count].el_tag = tag;
1144 (*tag2el)[*count].el_no = el_no;
1145 (*tag2el)[*count].from_expr = arg->expr;
1146 (*count)++;
1147 return 0;
1148 }
1149
1150 DEBUG("Searching tag in complex expression %s:%x at line %d",
1151 arg->expr->Identifier,
1152 arg->expr->expr_type,
1153 arg->expr->_lineno);
1154
1155 /*
1156 * Iterate over members of CHOICE type.
1157 */
1158 if(arg->expr->expr_type == ASN_CONSTR_CHOICE) {
1159 return _fill_tag2el_map(arg, tag2el, count, el_no);
1160 }
1161
1162 if(arg->expr->expr_type == A1TC_REFERENCE) {
1163 arg_t tmp = *arg;
1164 asn1p_expr_t *expr;
vlmdae7f9d2004-08-22 03:25:24 +00001165 expr = asn1f_lookup_symbol_ex(tmp.asn, tmp.mod, tmp.expr,
vlmfa67ddc2004-06-03 03:38:44 +00001166 arg->expr->reference);
1167 if(expr) {
vlmdae7f9d2004-08-22 03:25:24 +00001168 tmp.mod = expr->module;
vlmfa67ddc2004-06-03 03:38:44 +00001169 tmp.expr = expr;
1170 return _add_tag2el_member(&tmp, tag2el, count, el_no);
1171 } else {
1172 FATAL("Cannot dereference %s at line %d",
1173 arg->expr->Identifier,
1174 arg->expr->_lineno);
1175 return -1;
1176 }
1177 }
1178
1179 DEBUG("No tag for %s at line %d",
1180 arg->expr->Identifier,
1181 arg->expr->_lineno);
1182
1183 return -1;
1184}
1185
1186static int
vlm4e03ce22004-06-06 07:20:17 +00001187emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count) {
1188 asn1p_expr_t *expr = arg->expr;
1189
1190 OUT("static asn1_TYPE_tag2member_t asn1_DEF_%s_tag2el[] = {\n",
1191 MKID(expr->Identifier));
1192 if(tag2el_count) {
1193 int i;
1194 for(i = 0; i < tag2el_count; i++) {
1195 OUT(" { ");
1196 _print_tag(arg, expr, &tag2el[i].el_tag);
1197 OUT(", ");
vlmc8aeab42004-06-14 13:09:45 +00001198 OUT("%d, ", tag2el[i].el_no);
1199 OUT("%d, ", tag2el[i].toff_first);
1200 OUT("%d ", tag2el[i].toff_last);
vlm4e03ce22004-06-06 07:20:17 +00001201 OUT("}, /* %s at %d */\n",
1202 tag2el[i].from_expr->Identifier,
1203 tag2el[i].from_expr->_lineno
1204 );
1205 }
1206 }
1207 OUT("};\n");
1208
1209 return 0;;
1210}
1211
1212static int
vlm6e73a042004-08-11 07:17:22 +00001213emit_tags_vector(arg_t *arg, asn1p_expr_t *expr, int *tags_impl_skip, int choice_mode) {
1214 int tags_count = 0;
1215 int save_target = arg->target->target;
vlm4a3f5822004-06-28 21:13:46 +00001216 char *p;
1217
vlm6e73a042004-08-11 07:17:22 +00001218 if(save_target != OT_IGNORE) {
1219 int save_impl_skip = *tags_impl_skip;
1220 REDIR(OT_IGNORE);
1221 tags_count = emit_tags_vector(arg, expr,
1222 tags_impl_skip, choice_mode);
1223 REDIR(save_target);
1224 if(tags_count) {
1225 *tags_impl_skip = save_impl_skip;
1226 tags_count = 0;
1227 } else {
1228 return 0;
1229 }
1230 }
1231
1232
vlm4a3f5822004-06-28 21:13:46 +00001233 p = MKID(expr->Identifier);
1234 OUT("static ber_tlv_tag_t asn1_DEF_%s_tags[] = {\n", p);
1235 INDENTED(
1236 if(expr->tag.tag_class) {
vlm6e73a042004-08-11 07:17:22 +00001237 tags_count++;
vlm4a3f5822004-06-28 21:13:46 +00001238 _print_tag(arg, expr, &expr->tag);
1239 if(expr->tag.tag_mode != TM_EXPLICIT)
1240 (*tags_impl_skip)++;
1241 } else {
vlm6e73a042004-08-11 07:17:22 +00001242 if(!choice_mode)
1243 (*tags_impl_skip)++;
vlm4a3f5822004-06-28 21:13:46 +00001244 }
vlm6e73a042004-08-11 07:17:22 +00001245 if(!choice_mode) {
1246 if(!expr->tag.tag_class
1247 || (expr->meta_type == AMT_TYPE
1248 && expr->tag.tag_mode == TM_EXPLICIT)) {
1249 struct asn1p_type_tag_s tag;
1250 if(expr->tag.tag_class)
1251 OUT(",\n");
1252 tag.tag_class = TC_UNIVERSAL;
1253 tag.tag_mode = TM_IMPLICIT;
1254 tag.tag_value = expr_type2uclass_value[expr->expr_type];
1255 _print_tag(arg, expr, &tag);
1256 tags_count++;
1257 }
vlm4a3f5822004-06-28 21:13:46 +00001258 }
1259 OUT("\n");
1260 );
1261 OUT("};\n");
1262
vlm6e73a042004-08-11 07:17:22 +00001263 return tags_count;
vlm4a3f5822004-06-28 21:13:46 +00001264}
vlmb2839012004-08-20 13:37:01 +00001265
1266static int
1267_expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
1268 asn1p_expr_t *topmost_parent;
1269 asn1p_expr_t *v;
1270 int elements = 0;
1271
vlmdae7f9d2004-08-22 03:25:24 +00001272 topmost_parent = asn1f_find_terminal_type_ex(arg->asn, arg->mod, expr);
vlmb2839012004-08-20 13:37:01 +00001273 if(!topmost_parent) return 0;
1274
1275 if(!(topmost_parent->expr_type & ASN_CONSTR_MASK))
1276 return 0;
1277
1278 TQ_FOR(v, &(topmost_parent->members), next) {
1279 if(v->expr_type != A1TC_EXTENSIBLE)
1280 elements++;
1281 }
1282
1283 return elements;
1284}
1285
1286static int
1287_emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
vlmdae7f9d2004-08-22 03:25:24 +00001288 static int global_memb_unique;
vlmb2839012004-08-20 13:37:01 +00001289 int save_target;
1290 arg_t tmp_arg;
1291 char *p;
1292
1293 OUT("{ ");
1294 if(expr->marker) {
1295 asn1p_expr_t *tv;
1296 int opts = 0;
1297 for(tv = expr; tv && tv->marker;
1298 tv = TQ_NEXT(tv, next), opts++) {
1299 if(tv->expr_type == A1TC_EXTENSIBLE)
1300 opts--;
1301 }
1302 OUT("%d, ", opts);
1303 } else {
1304 OUT("0, ");
1305 }
1306 if(expr->Identifier) {
1307 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));
1311 } else {
1312 assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
1313 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
1314 OUT("0,\n");
1315 }
1316 INDENT(+1);
1317 if(C99_MODE) OUT(".tag = ");
1318 _print_tag(arg, expr , NULL);
1319 OUT(",\n");
1320 if(C99_MODE) OUT(".tag_mode = ");
1321 if(expr->tag.tag_class) {
1322 if(expr->tag.tag_mode == TM_IMPLICIT)
1323 OUT("-1,\t/* IMPLICIT tag at current level */\n");
1324 else
1325 OUT("+1,\t/* EXPLICIT tag at current level */\n");
1326 } else {
1327 OUT("0,\n");
1328 }
1329 if(C99_MODE) OUT(".type = ");
vlmdae7f9d2004-08-22 03:25:24 +00001330 if((expr->expr_type & ASN_CONSTR_MASK)
1331 && (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF
1332 || arg->expr->expr_type == ASN_CONSTR_SET_OF)) {
1333 OUT("(void *)&asn1_DEF_%s_member,\n",
1334 MKID(arg->expr->Identifier));
1335 } else {
1336 OUT("(void *)&asn1_DEF_%s,\n",
1337 asn1c_type_name(arg, expr, TNF_SAFE));
1338 }
vlmb2839012004-08-20 13:37:01 +00001339 if(C99_MODE) OUT(".memb_constraints = ");
1340 if(expr->constraints) {
1341 p = MKID(expr->Identifier);
1342 if(!expr->Identifier)
1343 p = asn1c_type_name(arg, expr, TNF_SAFE);
vlmdae7f9d2004-08-22 03:25:24 +00001344 OUT("memb_%s_%d_constraint,\n", p,
1345 ++global_memb_unique);
vlmb2839012004-08-20 13:37:01 +00001346 } else {
1347 OUT("0,\t/* Defer to actual type */\n");
1348 }
1349 if(C99_MODE) OUT(".name = ");
1350 OUT("\"%s\"\n", expr->Identifier ? expr->Identifier : "");
1351 OUT("},\n");
1352 INDENT(-1);
1353
1354 if(!expr->constraints)
1355 return 0;
1356
1357 save_target = arg->target->target;
1358 REDIR(OT_CODE);
1359
1360 if(expr->Identifier)
1361 p = MKID(expr->Identifier);
1362 else
1363 p = asn1c_type_name(arg, expr, TNF_SAFE);
1364 OUT("static int\n");
vlmdae7f9d2004-08-22 03:25:24 +00001365 OUT("memb_%s_%d_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,\n", p, global_memb_unique);
vlmb2839012004-08-20 13:37:01 +00001366 INDENT(+1);
1367 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
1368 tmp_arg = *arg;
1369 tmp_arg.expr = expr;
1370 if(asn1c_emit_constraint_checking_code(&tmp_arg) == 1) {
1371 OUT("return td->check_constraints\n");
1372 OUT("\t(td, sptr, app_errlog, app_key);\n");
1373 }
1374 INDENT(-1);
1375 OUT("}\n");
1376 OUT("\n");
1377
1378 REDIR(save_target);
1379
1380 return 0;
1381}