blob: f54d2d5825f4a84bed7fb66f7742761c7a31e433 [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);
Lev Walkin59004fa2004-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);
Lev Walkinfd171ef2004-06-06 07:20:17 +000024
Lev Walkinf15320b2004-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);
Lev Walkin35631482004-07-01 00:52:50 +000030static int check_if_extensible(asn1p_expr_t *expr);
Lev Walkin64399722004-08-11 07:17:22 +000031static int emit_tags_vector(arg_t *arg, asn1p_expr_t *expr, int *tags_impl_skip, int choice_mode);
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 Walkin59004fa2004-08-20 13:37:01 +000034#define C99_MODE (!(arg->flags & A1C_NO_C99))
Lev Walkinf15320b2004-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
Lev Walkin3dcaafa2004-08-11 05:21:32 +000042#define DEPENDENCIES do { \
43 TQ_FOR(v, &(expr->members), next) { \
44 if((!(v->expr_type & ASN_CONSTR_MASK) \
45 && v->expr_type > ASN_CONSTR_MASK) \
46 || v->meta_type == AMT_TYPEREF) { \
47 GEN_INCLUDE(asn1c_type_name(arg, v, TNF_INCLUDE));\
48 } \
49 } \
50 if(expr->expr_type == ASN_CONSTR_SET_OF) \
51 GEN_INCLUDE("asn_SET_OF"); \
52 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF) \
53 GEN_INCLUDE("asn_SEQUENCE_OF"); \
54} while(0)
Lev Walkinf15320b2004-06-03 03:38:44 +000055
56#define MKID(id) asn1c_make_identifier(0, (id), 0)
57
58int
59asn1c_lang_C_type_ENUMERATED(arg_t *arg) {
60 asn1p_expr_t *expr = arg->expr;
61 asn1p_expr_t *v;
62
63 REDIR(OT_DEPS);
64
65 OUT("typedef enum %s {\n", MKID(expr->Identifier));
66 TQ_FOR(v, &(expr->members), next) {
67 switch(v->expr_type) {
68 case A1TC_UNIVERVAL:
69 OUT("\t%s\t= %lld,\n",
70 asn1c_make_identifier(0,
71 expr->Identifier,
72 v->Identifier, 0),
73 v->value->value.v_integer);
74 break;
75 case A1TC_EXTENSIBLE:
76 OUT("\t/*\n");
77 OUT("\t * Enumeration is extensible\n");
78 OUT("\t */\n");
79 break;
80 default:
81 return -1;
82 }
83 }
84 OUT("} %s_e;\n", MKID(expr->Identifier));
85
86 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
87}
88
89
90int
91asn1c_lang_C_type_INTEGER(arg_t *arg) {
92 asn1p_expr_t *expr = arg->expr;
93 asn1p_expr_t *v;
94
95 REDIR(OT_DEPS);
96
97 if(TQ_FIRST(&(expr->members))) {
98 OUT("typedef enum %s {\n", MKID(expr->Identifier));
99 TQ_FOR(v, &(expr->members), next) {
100 switch(v->expr_type) {
101 case A1TC_UNIVERVAL:
102 OUT("\t%s\t= %lld,\n",
103 asn1c_make_identifier(0,
104 expr->Identifier,
105 v->Identifier, 0),
106 v->value->value.v_integer);
107 break;
108 default:
109 return -1;
110 }
111 }
112 OUT("} %s_e;\n", MKID(expr->Identifier));
113 }
114
115 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
116}
117
118int
119asn1c_lang_C_type_SEQUENCE(arg_t *arg) {
120 asn1p_expr_t *expr = arg->expr;
121 asn1p_expr_t *v;
122 int comp_mode = 0; /* {root,ext=1,root,root,...} */
123
124 DEPENDENCIES;
125
126 if(arg->embed) {
127 OUT("struct %s {\n",
128 MKID(expr->Identifier));
129 } else {
130 OUT("typedef struct %s {\n",
131 MKID(expr->Identifier));
132 }
133
134 TQ_FOR(v, &(expr->members), next) {
135 if(v->expr_type == A1TC_EXTENSIBLE) {
136 if(comp_mode < 3) comp_mode++;
137 }
138 if(comp_mode == 1 && !v->marker)
139 v->marker = EM_OPTIONAL;
140 EMBED(v);
141 }
142
143 PCTX_DEF;
144 OUT("} %s%s", expr->marker?"*":"",
145 MKID(expr->Identifier));
146 if(arg->embed) OUT(";\n"); else OUT("_t;\n");
147
148 return asn1c_lang_C_type_SEQUENCE_def(arg);
149}
150
151static int
152asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
153 asn1p_expr_t *expr = arg->expr;
154 asn1p_expr_t *v;
155 int elements; /* Number of elements */
156 int tags_impl_skip = 0;
157 int comp_mode = 0; /* {root,ext=1,root,root,...} */
158 int ext_start = -1;
159 int ext_stop = -1;
Lev Walkinfd171ef2004-06-06 07:20:17 +0000160 tag2el_t *tag2el = NULL;
161 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000162 int tags_count;
Lev Walkinf15320b2004-06-03 03:38:44 +0000163 char *p;
164
Lev Walkinfd171ef2004-06-06 07:20:17 +0000165 /*
166 * Fetch every inner tag from the tag to elements map.
167 */
168 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
169 if(tag2el) free(tag2el);
170 return -1;
171 }
172
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000173 GEN_INCLUDE("constr_SEQUENCE");
174 if(!arg->embed)
175 GEN_DECLARE(expr); /* asn1_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000176
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000177 REDIR(OT_STAT_DEFS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000178
179 /*
180 * Print out the table according to which the parsing is performed.
181 */
182 p = MKID(expr->Identifier);
Lev Walkin59004fa2004-08-20 13:37:01 +0000183 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000184
185 elements = 0;
186 INDENTED(TQ_FOR(v, &(expr->members), next) {
187 if(v->expr_type == A1TC_EXTENSIBLE) {
188 if((++comp_mode) == 1)
189 ext_start = elements - 1;
190 else
191 ext_stop = elements - 1;
192 continue;
193 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000194 elements++;
Lev Walkin59004fa2004-08-20 13:37:01 +0000195 _emit_member_table(arg, v);
Lev Walkinf15320b2004-06-03 03:38:44 +0000196 });
197 OUT("};\n");
198
Lev Walkin27ea3802004-06-28 21:13:46 +0000199 /*
200 * Print out asn1_DEF_<type>_tags[] vector.
201 */
Lev Walkin64399722004-08-11 07:17:22 +0000202 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000203
Lev Walkinfd171ef2004-06-06 07:20:17 +0000204 /*
205 * Tags to elements map.
206 */
207 emit_tag2member_map(arg, tag2el, tag2el_count);
208
Lev Walkin27ea3802004-06-28 21:13:46 +0000209 p = MKID(expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000210 OUT("static asn1_SEQUENCE_specifics_t asn1_DEF_%s_specs = {\n", p);
211 INDENTED(
212 OUT("sizeof(struct %s),\n", p);
213 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
Lev Walkinfd171ef2004-06-06 07:20:17 +0000214 OUT("asn1_DEF_%s_tag2el,\n", p);
215 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000216 OUT("%d,\t/* Start extensions */\n",
217 ext_start);
218 OUT("%d\t/* Stop extensions */\n",
219 (ext_stop<ext_start)?elements+1:ext_stop, ext_stop);
220 );
221 OUT("};\n");
222 OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
223 INDENTED(
224 OUT("\"%s\",\n", expr->Identifier);
225 OUT("SEQUENCE_constraint,\n");
226 OUT("SEQUENCE_decode_ber,\n");
227 OUT("SEQUENCE_encode_der,\n");
228 OUT("SEQUENCE_print,\n");
229 OUT("SEQUENCE_free,\n");
230 OUT("0,\t/* Use generic outmost tag fetcher */\n");
Lev Walkin64399722004-08-11 07:17:22 +0000231 if(tags_count) {
232 OUT("asn1_DEF_%s_tags,\n", p);
233 OUT("sizeof(asn1_DEF_%s_tags)\n", p);
234 OUT("\t/sizeof(asn1_DEF_%s_tags[0]), /* %d */\n",
235 p, tags_count);
236 } else {
237 OUT("0,\t/* No explicit tags (pointer) */\n");
238 OUT("0,\t/* No explicit tags (count) */\n");
239 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000240 OUT("%d,\t/* Tags to skip */\n", tags_impl_skip);
241 OUT("%d,\t/* Whether CONSTRUCTED */\n", 1);
Lev Walkin59004fa2004-08-20 13:37:01 +0000242 OUT("asn1_MBR_%s,\n", p);
243 OUT("%d,\t/* Elements count */\n", elements);
Lev Walkinf15320b2004-06-03 03:38:44 +0000244 OUT("&asn1_DEF_%s_specs\t/* Additional specs */\n", p);
245 );
246 OUT("};\n");
247 OUT("\n");
248
Lev Walkinf15320b2004-06-03 03:38:44 +0000249 REDIR(OT_TYPE_DECLS);
250
251 return 0;
252}
253
254int
255asn1c_lang_C_type_SEQUENCE_OF(arg_t *arg) {
256 asn1p_expr_t *expr = arg->expr;
257 asn1p_expr_t *v;
258
259 DEPENDENCIES;
260
261 if(arg->embed) {
262 OUT("struct %s {\n", MKID(expr->Identifier));
263 } else {
264 OUT("typedef struct %s {\n", MKID(expr->Identifier));
265 }
266
267 TQ_FOR(v, &(expr->members), next) {
268 INDENTED(OUT("A_SEQUENCE_OF(%s) list;\n",
269 asn1c_type_name(arg, v, TNF_RSAFE)));
270 }
271
272 PCTX_DEF;
273 OUT("} %s%s", expr->marker?"*":"", MKID(expr->Identifier));
274 if(arg->embed) OUT(";\n"); else OUT("_t;\n");
275
276 /*
277 * SET OF/SEQUENCE OF definition, SEQUENCE OF mode.
278 */
279 return asn1c_lang_C_type_SEx_OF_def(arg, 1);
280}
281
282int
283asn1c_lang_C_type_SET(arg_t *arg) {
284 asn1p_expr_t *expr = arg->expr;
285 asn1p_expr_t *v;
286 long mcount;
287 char *id;
288 int comp_mode = 0; /* {root,ext=1,root,root,...} */
289
290 DEPENDENCIES;
291
292 REDIR(OT_DEPS);
293
294 OUT("\n");
295 OUT("/*\n");
296 OUT(" * Method of determining the components presence\n");
297 OUT(" */\n");
298 mcount = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000299 OUT("typedef enum %s_PR {\n", MKID(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +0000300 TQ_FOR(v, &(expr->members), next) {
301 if(v->expr_type == A1TC_EXTENSIBLE) continue;
302 INDENTED(
303 id = MKID(expr->Identifier);
304 OUT("%s_PR_", id);
305 id = MKID(v->Identifier);
306 OUT("%s,\t/* Member %s is present */\n",
307 id, id)
308 );
309 mcount++;
310 }
Lev Walkin64399722004-08-11 07:17:22 +0000311 id = MKID(expr->Identifier);
312 OUT("} %s_PR;\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000313
314 REDIR(OT_TYPE_DECLS);
315
316 if(arg->embed) {
Lev Walkin64399722004-08-11 07:17:22 +0000317 OUT("struct %s {\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000318 } else {
Lev Walkin64399722004-08-11 07:17:22 +0000319 OUT("typedef struct %s {\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000320 }
321
322 TQ_FOR(v, &(expr->members), next) {
323 if(v->expr_type == A1TC_EXTENSIBLE) {
324 if(comp_mode < 3) comp_mode++;
325 }
326 if(comp_mode == 1 && !v->marker)
327 v->marker = EM_OPTIONAL;
328 EMBED(v);
329 }
330
331 INDENTED(
332 id = MKID(expr->Identifier);
333 OUT("\n");
334 OUT("/* Presence bitmask: ASN_SET_ISPRESENT(p%s, %s_PR_x) */\n",
335 id, id);
336 OUT("unsigned int _presence_map\n");
337 OUT("\t[((%ld+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))];\n", mcount);
338 );
339
340 PCTX_DEF;
341 OUT("} %s%s", expr->marker?"*":"", MKID(expr->Identifier));
342 if(arg->embed) OUT(";\n"); else OUT("_t;\n");
343
344 return asn1c_lang_C_type_SET_def(arg);
345}
346
Lev Walkinf15320b2004-06-03 03:38:44 +0000347static int
348asn1c_lang_C_type_SET_def(arg_t *arg) {
349 asn1p_expr_t *expr = arg->expr;
350 asn1p_expr_t *v;
351 int elements;
352 int tags_impl_skip = 0;
353 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Lev Walkinf15320b2004-06-03 03:38:44 +0000354 tag2el_t *tag2el = NULL;
355 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000356 int tags_count;
Lev Walkinf15320b2004-06-03 03:38:44 +0000357 char *p;
358
359 /*
360 * Fetch every inner tag from the tag to elements map.
361 */
362 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
363 if(tag2el) free(tag2el);
364 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000365 }
366
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000367 GEN_INCLUDE("constr_SET");
368 if(!arg->embed)
369 GEN_DECLARE(expr); /* asn1_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000370
371 REDIR(OT_STAT_DEFS);
372
Lev Walkinf15320b2004-06-03 03:38:44 +0000373 /*
374 * Print out the table according to which the parsing is performed.
375 */
376 p = MKID(expr->Identifier);
Lev Walkin59004fa2004-08-20 13:37:01 +0000377 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000378
379 elements = 0;
380 INDENTED(TQ_FOR(v, &(expr->members), next) {
381 if(v->expr_type != A1TC_EXTENSIBLE) {
382 if(comp_mode == 1)
383 v->marker = EM_OPTIONAL;
Lev Walkinf15320b2004-06-03 03:38:44 +0000384 } else {
385 if(comp_mode < 3) comp_mode++;
386 continue;
387 }
Lev Walkin59004fa2004-08-20 13:37:01 +0000388 elements++;
389 _emit_member_table(arg, v);
Lev Walkinf15320b2004-06-03 03:38:44 +0000390 });
391 OUT("};\n");
392
Lev Walkin27ea3802004-06-28 21:13:46 +0000393 /*
394 * Print out asn1_DEF_<type>_tags[] vector.
395 */
Lev Walkin64399722004-08-11 07:17:22 +0000396 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000397
398 /*
399 * Tags to elements map.
400 */
Lev Walkinfd171ef2004-06-06 07:20:17 +0000401 emit_tag2member_map(arg, tag2el, tag2el_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000402
403 /*
404 * Emit a map of mandatory elements.
405 */
Lev Walkin27ea3802004-06-28 21:13:46 +0000406 p = MKID(expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000407 OUT("static uint8_t asn1_DEF_%s_mmap", p);
408 OUT("[(%d + (8 * sizeof(unsigned int)) - 1) / 8]", elements);
409 OUT(" = {\n", p);
410 INDENTED(
411 if(elements) {
412 int delimit = 0;
413 int el = 0;
414 TQ_FOR(v, &(expr->members), next) {
415 if(v->expr_type == A1TC_EXTENSIBLE) continue;
416 if(delimit) {
417 OUT(",\n");
418 delimit = 0;
419 } else if(el) {
420 OUT(" | ");
421 }
422 OUT("(%d << %d)", v->marker?0:1, 7 - (el % 8));
423 if(el && (el % 8) == 0)
424 delimit = 1;
425 el++;
426 }
427 } else {
428 OUT("0");
429 }
430 );
431 OUT("\n");
432 OUT("};\n");
433
434 OUT("static asn1_SET_specifics_t asn1_DEF_%s_specs = {\n", p);
435 INDENTED(
436 OUT("sizeof(struct %s),\n", p);
437 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
438 OUT("offsetof(struct %s, _presence_map),\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000439 OUT("asn1_DEF_%s_tag2el,\n", p);
440 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
Lev Walkin35631482004-07-01 00:52:50 +0000441 OUT("%d,\t/* Whether extensible */\n",
442 check_if_extensible(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +0000443 OUT("(unsigned int *)asn1_DEF_%s_mmap\t/* Mandatory elements map */\n", p);
444 );
445 OUT("};\n");
446 OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
447 INDENTED(
448 OUT("\"%s\",\n", expr->Identifier);
449 OUT("SET_constraint,\n");
450 OUT("SET_decode_ber,\n");
451 OUT("SET_encode_der,\n");
452 OUT("SET_print,\n");
453 OUT("SET_free,\n");
454 OUT("0,\t/* Use generic outmost tag fetcher */\n");
Lev Walkin64399722004-08-11 07:17:22 +0000455 if(tags_count) {
456 OUT("asn1_DEF_%s_tags,\n", p);
457 OUT("sizeof(asn1_DEF_%s_tags)\n", p);
458 OUT("\t/sizeof(asn1_DEF_%s_tags[0]), /* %d */\n",
459 p, tags_count);
460 } else {
461 OUT("0,\t/* No explicit tags (pointer) */\n");
462 OUT("0,\t/* No explicit tags (count) */\n");
463 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000464 OUT("%d,\t/* Tags to skip */\n", tags_impl_skip);
465 OUT("%d,\t/* Whether CONSTRUCTED */\n", 1);
Lev Walkin59004fa2004-08-20 13:37:01 +0000466 OUT("asn1_MBR_%s,\n", p);
467 OUT("%d,\t/* Elements count */\n", elements);
Lev Walkinf15320b2004-06-03 03:38:44 +0000468 OUT("&asn1_DEF_%s_specs\t/* Additional specs */\n", p);
469 );
470 OUT("};\n");
471 OUT("\n");
472
Lev Walkinf15320b2004-06-03 03:38:44 +0000473 REDIR(OT_TYPE_DECLS);
474
475 return 0;
476}
477
478int
479asn1c_lang_C_type_SET_OF(arg_t *arg) {
480 asn1p_expr_t *expr = arg->expr;
481 asn1p_expr_t *v;
482
483 DEPENDENCIES;
484
485 if(arg->embed) {
486 OUT("struct %s {\n", MKID(expr->Identifier));
487 } else {
488 OUT("typedef struct %s {\n",
489 MKID(expr->Identifier));
490 }
491
492 TQ_FOR(v, &(expr->members), next) {
493 INDENTED(OUT("A_SET_OF(%s) list;\n",
494 asn1c_type_name(arg, v, TNF_RSAFE)));
495 }
496
497 PCTX_DEF;
498 OUT("} %s%s", expr->marker?"*":"", MKID(expr->Identifier));
499 if(arg->embed) OUT(";\n"); else OUT("_t;\n");
500
501 /*
502 * SET OF/SEQUENCE OF definition, SET OF mode.
503 */
504 return asn1c_lang_C_type_SEx_OF_def(arg, 0);
505}
506
507static int
508asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
509 asn1p_expr_t *expr = arg->expr;
510 asn1p_expr_t *v;
511 int tags_impl_skip = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000512 int tags_count;
Lev Walkinf15320b2004-06-03 03:38:44 +0000513 char *p;
514
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000515 /*
516 * Print out the table according to which the parsing is performed.
517 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000518 if(seq_of) {
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000519 GEN_INCLUDE("constr_SEQUENCE_OF");
Lev Walkinf15320b2004-06-03 03:38:44 +0000520 } else {
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000521 GEN_INCLUDE("constr_SET_OF");
Lev Walkinf15320b2004-06-03 03:38:44 +0000522 }
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000523 if(!arg->embed)
524 GEN_DECLARE(expr); /* asn1_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000525
526 REDIR(OT_STAT_DEFS);
527
528 /*
529 * Print out the table according to which the parsing is performed.
530 */
531 p = MKID(expr->Identifier);
Lev Walkin59004fa2004-08-20 13:37:01 +0000532 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000533
Lev Walkin59004fa2004-08-20 13:37:01 +0000534 INDENTED(
Lev Walkinf15320b2004-06-03 03:38:44 +0000535 v = TQ_FIRST(&(expr->members));
Lev Walkin59004fa2004-08-20 13:37:01 +0000536 _emit_member_table(arg, v);
Lev Walkinf15320b2004-06-03 03:38:44 +0000537 );
538 OUT("};\n");
539
Lev Walkin27ea3802004-06-28 21:13:46 +0000540 /*
541 * Print out asn1_DEF_<type>_tags[] vector.
542 */
Lev Walkin64399722004-08-11 07:17:22 +0000543 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000544
Lev Walkin27ea3802004-06-28 21:13:46 +0000545 p = MKID(expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000546 OUT("static asn1_SET_OF_specifics_t asn1_DEF_%s_specs = {\n", p);
547 INDENTED(
548 OUT("sizeof(struct %s),\n", p);
549 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000550 );
551 OUT("};\n");
552 OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
553 INDENTED(
554 OUT("\"%s\",\n", expr->Identifier);
555 if(seq_of) {
556 OUT("SEQUENCE_OF_constraint,\n");
557 OUT("SEQUENCE_OF_decode_ber,\n");
558 OUT("SEQUENCE_OF_encode_der,\n");
559 OUT("SEQUENCE_OF_print,\n");
560 OUT("SEQUENCE_OF_free,\n");
561 } else {
562 OUT("SET_OF_constraint,\n");
563 OUT("SET_OF_decode_ber,\n");
564 OUT("SET_OF_encode_der,\n");
565 OUT("SET_OF_print,\n");
566 OUT("SET_OF_free,\n");
567 }
568 OUT("0,\t/* Use generic outmost tag fetcher */\n");
Lev Walkin64399722004-08-11 07:17:22 +0000569 if(tags_count) {
570 OUT("asn1_DEF_%s_tags,\n", p);
571 OUT("sizeof(asn1_DEF_%s_tags)\n", p);
572 OUT("\t/sizeof(asn1_DEF_%s_tags[0]), /* %d */\n",
573 p, tags_count);
574 } else {
575 OUT("0,\t/* No explicit tags (pointer) */\n");
576 OUT("0,\t/* No explicit tags (count) */\n");
577 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000578 OUT("%d,\t/* Tags to skip */\n", tags_impl_skip);
579 OUT("%d,\t/* Whether CONSTRUCTED */\n", 1);
Lev Walkin59004fa2004-08-20 13:37:01 +0000580 OUT("asn1_MBR_%s,\n", p);
581 OUT("1,\t/* Single element */\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000582 OUT("&asn1_DEF_%s_specs\t/* Additional specs */\n", p);
583 );
584 OUT("};\n");
585 OUT("\n");
586
Lev Walkinf15320b2004-06-03 03:38:44 +0000587 REDIR(OT_TYPE_DECLS);
588
589 return 0;
590}
591
592int
593asn1c_lang_C_type_CHOICE(arg_t *arg) {
594 asn1p_expr_t *expr = arg->expr;
595 asn1p_expr_t *v;
596 char *p;
597
598 DEPENDENCIES;
599
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000600 REDIR(OT_DEPS);
601
Lev Walkinf15320b2004-06-03 03:38:44 +0000602 p = MKID(expr->Identifier);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000603 OUT("typedef enum %s_PR {\n", p);
604 INDENTED(
605 p = MKID(expr->Identifier);
606 OUT("%s_PR_NOTHING,\t"
607 "/* No components present */\n", p);
608 TQ_FOR(v, &(expr->members), next) {
609 if(v->expr_type == A1TC_EXTENSIBLE) {
610 OUT("/* Extensions may appear below */\n");
611 continue;
612 }
613 p = MKID(expr->Identifier);
614 OUT("%s_PR_", p);
615 p = MKID(v->Identifier);
616 OUT("%s,\n", p, p);
617 }
618 );
619 p = MKID(expr->Identifier);
Lev Walkin64399722004-08-11 07:17:22 +0000620 OUT("} %s_PR;\n", p);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000621
622 REDIR(OT_TYPE_DECLS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000623
624 if(arg->embed) {
625 OUT("struct %s {\n", p);
626 } else {
627 OUT("typedef struct %s {\n", p);
628 }
629
630 INDENTED(
Lev Walkin64399722004-08-11 07:17:22 +0000631 OUT("%s_PR present;\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000632 OUT("union {\n", p);
633 TQ_FOR(v, &(expr->members), next) {
634 EMBED(v);
635 }
636 if(UNNAMED_UNIONS) OUT("};\n");
637 else OUT("} choice;\n");
638 );
639
640 PCTX_DEF;
641 OUT("} %s%s", expr->marker?"*":"", MKID(expr->Identifier));
642 if(arg->embed) OUT(";\n"); else OUT("_t;\n");
643
644 return asn1c_lang_C_type_CHOICE_def(arg);
645}
646
647static int
648asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
649 asn1p_expr_t *expr = arg->expr;
650 asn1p_expr_t *v;
651 int elements; /* Number of elements */
652 int tags_impl_skip = 0;
653 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Lev Walkinf15320b2004-06-03 03:38:44 +0000654 tag2el_t *tag2el = NULL;
655 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000656 int tags_count;
Lev Walkinf15320b2004-06-03 03:38:44 +0000657 char *p;
658
659 /*
660 * Fetch every inner tag from the tag to elements map.
661 */
662 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
663 if(tag2el) free(tag2el);
664 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000665 }
666
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000667 GEN_INCLUDE("constr_CHOICE");
668 if(!arg->embed)
669 GEN_DECLARE(expr); /* asn1_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000670
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000671 REDIR(OT_STAT_DEFS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000672
673 /*
674 * Print out the table according to which the parsing is performed.
675 */
676 p = MKID(expr->Identifier);
Lev Walkin59004fa2004-08-20 13:37:01 +0000677 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000678
679 elements = 0;
680 INDENTED(TQ_FOR(v, &(expr->members), next) {
681 if(v->expr_type != A1TC_EXTENSIBLE) {
682 if(comp_mode == 1)
683 v->marker = EM_OPTIONAL;
Lev Walkinf15320b2004-06-03 03:38:44 +0000684 } else {
685 if(comp_mode < 3) comp_mode++;
686 continue;
687 }
Lev Walkin59004fa2004-08-20 13:37:01 +0000688 elements++;
689 _emit_member_table(arg, v);
Lev Walkinf15320b2004-06-03 03:38:44 +0000690 });
691 OUT("};\n");
692
Lev Walkin64399722004-08-11 07:17:22 +0000693
Lev Walkinf15320b2004-06-03 03:38:44 +0000694 if(arg->embed) {
695 /*
696 * Our parent structure has already taken this into account.
697 */
Lev Walkin64399722004-08-11 07:17:22 +0000698 tags_count = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000699 } else {
Lev Walkin64399722004-08-11 07:17:22 +0000700 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000701 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000702
703 /*
704 * Tags to elements map.
705 */
Lev Walkinfd171ef2004-06-06 07:20:17 +0000706 emit_tag2member_map(arg, tag2el, tag2el_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000707
Lev Walkin64399722004-08-11 07:17:22 +0000708 p = MKID(expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000709 OUT("static asn1_CHOICE_specifics_t asn1_DEF_%s_specs = {\n", p);
710 INDENTED(
711 OUT("sizeof(struct %s),\n", p);
712 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
713 OUT("offsetof(struct %s, present),\n", p);
714 OUT("sizeof(((struct %s *)0)->present),\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000715 OUT("asn1_DEF_%s_tag2el,\n", p);
716 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
Lev Walkin35631482004-07-01 00:52:50 +0000717 OUT("%d\t/* Whether extensible */\n",
718 check_if_extensible(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +0000719 );
720 OUT("};\n");
721 OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
722 INDENTED(
723 OUT("\"%s\",\n", expr->Identifier);
724 OUT("CHOICE_constraint,\n");
725 OUT("CHOICE_decode_ber,\n");
726 OUT("CHOICE_encode_der,\n");
727 OUT("CHOICE_print,\n");
728 OUT("CHOICE_free,\n");
729 OUT("CHOICE_outmost_tag,\n");
Lev Walkin64399722004-08-11 07:17:22 +0000730 if(tags_count) {
731 OUT("asn1_DEF_%s_tags,\n", p);
732 OUT("sizeof(asn1_DEF_%s_tags)\n", p);
733 OUT("\t/sizeof(asn1_DEF_%s_tags[0]), /* %d */\n",
734 p, tags_count);
735 } else {
736 OUT("0,\t/* No explicit tags (pointer) */\n");
737 OUT("0,\t/* No explicit tags (count) */\n");
738 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000739 OUT("%d,\t/* Tags to skip */\n", tags_impl_skip);
740 OUT("%d,\t/* Whether CONSTRUCTED */\n", 1);
Lev Walkin59004fa2004-08-20 13:37:01 +0000741 OUT("asn1_MBR_%s,\n", p);
742 OUT("%d,\t/* Elements count */\n", elements);
Lev Walkinf15320b2004-06-03 03:38:44 +0000743 OUT("&asn1_DEF_%s_specs\t/* Additional specs */\n", p);
744 );
745 OUT("};\n");
746 OUT("\n");
747
Lev Walkinf15320b2004-06-03 03:38:44 +0000748 REDIR(OT_TYPE_DECLS);
749
750 return 0;
751}
752
753int
754asn1c_lang_C_type_REFERENCE(arg_t *arg) {
755 asn1p_ref_t *ref;
756
757 ref = arg->expr->reference;
758 if(ref->components[ref->comp_count-1].name[0] == '&') {
759 asn1p_module_t *mod;
760 asn1p_expr_t *extract;
761 arg_t tmp;
762 int ret;
763
764 extract = asn1f_class_access_ex(arg->asn, arg->mod, arg->expr,
765 ref, &mod);
766 if(extract == NULL)
767 return -1;
768
769 extract = asn1p_expr_clone(extract);
770 if(extract) {
771 if(extract->Identifier)
772 free(extract->Identifier);
773 extract->Identifier = strdup(arg->expr->Identifier);
774 if(extract->Identifier == NULL) {
775 asn1p_expr_free(extract);
776 return -1;
777 }
778 } else {
779 return -1;
780 }
781
782 tmp = *arg;
783 tmp.asn = arg->asn;
784 tmp.mod = mod;
785 tmp.expr = extract;
786
787 ret = arg->default_cb(&tmp);
788
789 asn1p_expr_free(extract);
790
791 return ret;
792 }
793
794
795 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
796}
797
798int
799asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
800 asn1p_expr_t *expr = arg->expr;
801 int tags_impl_skip = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000802 int tags_count;
Lev Walkinf15320b2004-06-03 03:38:44 +0000803 char *p;
804
805 if(arg->embed) {
806 REDIR(OT_TYPE_DECLS);
807
808 OUT("%s\t", asn1c_type_name(arg, arg->expr,
809 expr->marker?TNF_RSAFE:TNF_CTYPE));
810 OUT("%s", expr->marker?"*":" ");
811 OUT("%s;", MKID(expr->Identifier));
812 if(expr->marker) OUT("\t/* %s */",
813 (expr->marker==EM_OPTIONAL)?"OPTIONAL":"DEFAULT");
814 OUT("\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000815
816 REDIR(OT_TYPE_DECLS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000817 return 0;
818 }
819
Lev Walkinf15320b2004-06-03 03:38:44 +0000820
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000821 GEN_INCLUDE(asn1c_type_name(arg, expr, TNF_INCLUDE));
Lev Walkinf15320b2004-06-03 03:38:44 +0000822
823 REDIR(OT_TYPE_DECLS);
824
825 OUT("typedef %s\t", asn1c_type_name(arg, arg->expr, TNF_CTYPE));
826 OUT("%s", expr->marker?"*":" ");
827 OUT("%s_t;\n", MKID(expr->Identifier));
828 OUT("\n");
829
830 REDIR(OT_STAT_DEFS);
831
Lev Walkin27ea3802004-06-28 21:13:46 +0000832 /*
833 * Print out asn1_DEF_<type>_tags[] vector.
834 */
Lev Walkin64399722004-08-11 07:17:22 +0000835 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000836
Lev Walkin27ea3802004-06-28 21:13:46 +0000837 p = MKID(expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000838 OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
839 INDENTED(
840 OUT("\"%s\",\n", expr->Identifier);
841 OUT("%s_constraint,\n", p);
842 OUT("%s_decode_ber,\n", p);
843 OUT("%s_encode_der,\n", p);
844 OUT("%s_print,\n", p);
845 OUT("%s_free,\n", p);
846 OUT("0,\t/* Use generic outmost tag fetcher */\n");
Lev Walkin64399722004-08-11 07:17:22 +0000847 if(tags_count) {
848 OUT("asn1_DEF_%s_tags,\n", p);
849 OUT("sizeof(asn1_DEF_%s_tags)\n", p);
850 OUT("\t/sizeof(asn1_DEF_%s_tags[0]), /* %d */\n",
851 p, tags_count);
852 } else {
853 OUT("0,\t/* No explicit tags (pointer) */\n");
854 OUT("0,\t/* No explicit tags (count) */\n");
855 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000856 OUT("%d,\t/* Tags to skip */\n", tags_impl_skip);
Lev Walkin51b67e02004-06-05 08:46:50 +0000857 OUT("-0,\t/* Unknown yet */\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000858 if(_expr_elements_count(arg, expr))
859 OUT("0, 0,\t/* Defined elsewhere */\n");
860 else
861 OUT("0, 0,\t/* No members */\n");
Lev Walkin51b67e02004-06-05 08:46:50 +0000862 OUT("0\t/* No specifics */\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000863 );
864 OUT("};\n");
865 OUT("\n");
866
Lev Walkin59004fa2004-08-20 13:37:01 +0000867 REDIR(OT_CODE);
868
Lev Walkinf15320b2004-06-03 03:38:44 +0000869 /*
870 * Constraint checking.
871 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000872 p = MKID(expr->Identifier);
873 OUT("int\n");
874 OUT("%s_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,\n", p);
875 INDENTED(
876 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
877 OUT("\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000878 if(asn1c_emit_constraint_checking_code(arg) == 1) {
879 if(0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000880 OUT("/* Check the constraints of the underlying type */\n");
881 OUT("return asn1_DEF_%s.check_constraints\n",
882 asn1c_type_name(arg, expr, TNF_SAFE));
883 OUT("\t(td, sptr, app_errlog, app_key);\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000884 } else {
Lev Walkinf15320b2004-06-03 03:38:44 +0000885 OUT("/* Make the underlying type checker permanent */\n");
886 OUT("td->check_constraints = asn1_DEF_%s.check_constraints;\n",
887 asn1c_type_name(arg, expr, TNF_SAFE));
888 OUT("return td->check_constraints\n");
889 OUT("\t(td, sptr, app_errlog, app_key);\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000890 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000891 }
892 );
893 OUT("}\n");
894 OUT("\n");
895
896 /*
897 * Emit suicidal functions.
898 */
899
Lev Walkinf15320b2004-06-03 03:38:44 +0000900 /*
901 * This function replaces certain fields from the definition
902 * of a type with the corresponding fields from the basic type
903 * (from which the current type is inherited).
904 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000905 OUT("/*\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000906 OUT(" * This type is implemented using %s,\n",
907 asn1c_type_name(arg, expr, TNF_SAFE));
Lev Walkinf15320b2004-06-03 03:38:44 +0000908 OUT(" * so adjust the DEF appropriately.\n");
909 OUT(" */\n");
910 OUT("static void\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000911 p = MKID(expr->Identifier);
912 OUT("%s_inherit_TYPE_descriptor(asn1_TYPE_descriptor_t *td) {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000913 INDENT(+1);
Lev Walkin59004fa2004-08-20 13:37:01 +0000914 {
915 char *type_name = asn1c_type_name(arg, expr, TNF_SAFE);
916 OUT("td->ber_decoder = asn1_DEF_%s.ber_decoder;\n", type_name);
917 OUT("td->der_encoder = asn1_DEF_%s.der_encoder;\n", type_name);
918 OUT("td->free_struct = asn1_DEF_%s.free_struct;\n", type_name);
919 OUT("td->print_struct = asn1_DEF_%s.print_struct;\n", type_name);
920 OUT("td->last_tag_form = asn1_DEF_%s.last_tag_form;\n", type_name);
921 OUT("td->elements = asn1_DEF_%s.elements;\n", type_name);
922 OUT("td->elements_count = asn1_DEF_%s.elements_count;\n", type_name);
923 OUT("td->specifics = asn1_DEF_%s.specifics;\n", type_name);
924 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000925 INDENT(-1);
926 OUT("}\n");
927 OUT("\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000928
929 p = MKID(expr->Identifier);
930 OUT("ber_dec_rval_t\n");
931 OUT("%s_decode_ber(asn1_TYPE_descriptor_t *td,\n", p);
932 INDENTED(
933 OUT("\tvoid **structure, void *bufptr, size_t size, int tag_mode) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000934 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000935 OUT("return td->ber_decoder(td, structure,\n");
936 OUT("\tbufptr, size, tag_mode);\n");
937 );
938 OUT("}\n");
939 OUT("\n");
940
941 p = MKID(expr->Identifier);
942 OUT("der_enc_rval_t\n");
943 OUT("%s_encode_der(asn1_TYPE_descriptor_t *td,\n", p);
944 INDENTED(
945 OUT("\tvoid *structure, int tag_mode, ber_tlv_tag_t tag,\n");
946 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000947 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000948 OUT("return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);\n");
949 );
950 OUT("}\n");
951 OUT("\n");
952
953 p = MKID(expr->Identifier);
954 OUT("int\n");
955 OUT("%s_print(asn1_TYPE_descriptor_t *td, const void *struct_ptr,\n", p);
956 INDENTED(
957 OUT("\tint ilevel, asn_app_consume_bytes_f *cb, void *app_key) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000958 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000959 OUT("return td->print_struct(td, struct_ptr, ilevel, cb, app_key);\n");
960 );
961 OUT("}\n");
962 OUT("\n");
963
964 p = MKID(expr->Identifier);
965 OUT("void\n");
966 OUT("%s_free(asn1_TYPE_descriptor_t *td,\n", p);
967 INDENTED(
968 OUT("\tvoid *struct_ptr, int contents_only) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000969 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000970 OUT("td->free_struct(td, struct_ptr, contents_only);\n");
971 );
972 OUT("}\n");
973 OUT("\n");
974
975 REDIR(OT_FUNC_DECLS);
976
977 p = MKID(expr->Identifier);
978 OUT("extern asn1_TYPE_descriptor_t asn1_DEF_%s;\n", p);
979 OUT("asn_constr_check_f %s_constraint;\n", p);
980 OUT("ber_type_decoder_f %s_decode_ber;\n", p);
981 OUT("der_type_encoder_f %s_encode_der;\n", p);
982 OUT("asn_struct_print_f %s_print;\n", p);
983 OUT("asn_struct_free_f %s_free;\n", p);
984
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000985 REDIR(OT_TYPE_DECLS);
986
Lev Walkinf15320b2004-06-03 03:38:44 +0000987 return 0;
988}
989
990int
991asn1c_lang_C_type_EXTENSIBLE(arg_t *arg) {
992
993 OUT("/*\n");
994 OUT(" * This type is extensible,\n");
995 OUT(" * possible extensions are below.\n");
996 OUT(" */\n");
997
998 return 0;
999}
1000
Lev Walkin35631482004-07-01 00:52:50 +00001001static int check_if_extensible(asn1p_expr_t *expr) {
1002 asn1p_expr_t *v;
1003 TQ_FOR(v, &(expr->members), next) {
1004 if(v->expr_type == A1TC_EXTENSIBLE) return 1;
1005 }
1006 return 0;
1007}
1008
Lev Walkinf15320b2004-06-03 03:38:44 +00001009static int
1010_print_tag(arg_t *arg, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag_p) {
1011 struct asn1p_type_tag_s tag;
1012
1013 if(tag_p) {
1014 tag = *tag_p;
1015 } else {
1016 if(asn1f_fetch_tag(arg->asn, arg->mod, expr, &tag)) {
1017 OUT("-1 /* Ambiguous tag (CHOICE?) */");
1018 return 0;
1019 }
1020 }
1021
1022 OUT("(");
1023 switch(tag.tag_class) {
1024 case TC_UNIVERSAL: OUT("ASN_TAG_CLASS_UNIVERSAL"); break;
1025 case TC_APPLICATION: OUT("ASN_TAG_CLASS_APPLICATION"); break;
1026 case TC_CONTEXT_SPECIFIC: OUT("ASN_TAG_CLASS_CONTEXT"); break;
1027 case TC_PRIVATE: OUT("ASN_TAG_CLASS_PRIVATE"); break;
1028 case TC_NOCLASS:
1029 break;
1030 }
1031 OUT(" | (%lld << 2))", tag.tag_value);
1032
1033 return 0;
1034}
1035
Lev Walkinfd171ef2004-06-06 07:20:17 +00001036
1037static int
1038_tag2el_cmp(const void *ap, const void *bp) {
1039 const tag2el_t *a = ap;
1040 const tag2el_t *b = bp;
1041 const struct asn1p_type_tag_s *ta = &a->el_tag;
1042 const struct asn1p_type_tag_s *tb = &b->el_tag;
1043
1044 if(ta->tag_class == tb->tag_class) {
1045 if(ta->tag_value == tb->tag_value) {
1046 /*
1047 * Sort by their respective positions.
1048 */
1049 if(a->el_no < b->el_no)
1050 return -1;
1051 else if(a->el_no > b->el_no)
1052 return 1;
1053 return 0;
1054 } else if(ta->tag_value < tb->tag_value)
1055 return -1;
1056 else
1057 return 1;
1058 } else if(ta->tag_class < tb->tag_class) {
1059 return -1;
1060 } else {
1061 return 1;
1062 }
1063}
1064
Lev Walkinf15320b2004-06-03 03:38:44 +00001065/*
1066 * For constructed types, number of external tags may be greater than
1067 * number of elements in the type because of CHOICE type.
1068 * T ::= SET { -- Three possible tags:
1069 * a INTEGER, -- One tag is here...
1070 * b Choice1 -- ... and two more tags are there.
1071 * }
1072 * Choice1 ::= CHOICE {
1073 * s1 IA5String,
1074 * s2 ObjectDescriptor
1075 * }
1076 */
1077static int
1078_fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no) {
1079 asn1p_expr_t *expr = arg->expr;
1080 arg_t tmparg = *arg;
1081 asn1p_expr_t *v;
1082 int element = 0;
1083
1084 TQ_FOR(v, &(expr->members), next) {
1085 if(v->expr_type == A1TC_EXTENSIBLE)
1086 continue;
1087
1088 tmparg.expr = v;
1089
1090 if(_add_tag2el_member(&tmparg, tag2el, count,
1091 (el_no==-1)?element:el_no)) {
1092 return -1;
1093 }
1094
1095 element++;
1096 }
1097
Lev Walkinfd171ef2004-06-06 07:20:17 +00001098 /*
Lev Walkin38abe792004-06-14 13:09:45 +00001099 * Sort the map according to canonical order of their tags
1100 * and element numbers.
Lev Walkinfd171ef2004-06-06 07:20:17 +00001101 */
1102 qsort(*tag2el, *count, sizeof(**tag2el), _tag2el_cmp);
1103
Lev Walkin38abe792004-06-14 13:09:45 +00001104 /*
1105 * Initialize .toff_{first|last} members.
1106 */
1107 if(*count) {
1108 struct asn1p_type_tag_s *cur_tag = 0;
1109 tag2el_t *cur = *tag2el;
1110 tag2el_t *end = cur + *count;
1111 int occur, i;
1112 for(occur = 0; cur < end; cur++) {
1113 if(cur_tag == 0
1114 || cur_tag->tag_value != cur->el_tag.tag_value
1115 || cur_tag->tag_class != cur->el_tag.tag_class) {
1116 cur_tag = &cur->el_tag;
1117 occur = 0;
1118 } else {
1119 occur++;
1120 }
1121 cur->toff_first = -occur;
1122 for(i = 0; i >= -occur; i--)
1123 cur[i].toff_last = -i;
1124 }
1125 }
1126
Lev Walkinf15320b2004-06-03 03:38:44 +00001127 return 0;
1128}
1129
1130static int
1131_add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no) {
1132 struct asn1p_type_tag_s tag;
1133 int ret;
1134
1135 assert(el_no >= 0);
1136
1137 ret = asn1f_fetch_tag(arg->asn, arg->mod, arg->expr, &tag);
1138 if(ret == 0) {
1139 void *p;
1140 p = realloc(*tag2el, sizeof(tag2el_t) * ((*count) + 1));
1141 if(p) *tag2el = p;
1142 else return -1;
1143
1144 DEBUG("Found tag for %s: %ld",
1145 arg->expr->Identifier,
1146 (long)tag.tag_value);
1147
1148 (*tag2el)[*count].el_tag = tag;
1149 (*tag2el)[*count].el_no = el_no;
1150 (*tag2el)[*count].from_expr = arg->expr;
1151 (*count)++;
1152 return 0;
1153 }
1154
1155 DEBUG("Searching tag in complex expression %s:%x at line %d",
1156 arg->expr->Identifier,
1157 arg->expr->expr_type,
1158 arg->expr->_lineno);
1159
1160 /*
1161 * Iterate over members of CHOICE type.
1162 */
1163 if(arg->expr->expr_type == ASN_CONSTR_CHOICE) {
1164 return _fill_tag2el_map(arg, tag2el, count, el_no);
1165 }
1166
1167 if(arg->expr->expr_type == A1TC_REFERENCE) {
1168 arg_t tmp = *arg;
1169 asn1p_expr_t *expr;
1170 expr = asn1f_lookup_symbol_ex(tmp.asn, &tmp.mod, tmp.expr,
1171 arg->expr->reference);
1172 if(expr) {
1173 tmp.expr = expr;
1174 return _add_tag2el_member(&tmp, tag2el, count, el_no);
1175 } else {
1176 FATAL("Cannot dereference %s at line %d",
1177 arg->expr->Identifier,
1178 arg->expr->_lineno);
1179 return -1;
1180 }
1181 }
1182
1183 DEBUG("No tag for %s at line %d",
1184 arg->expr->Identifier,
1185 arg->expr->_lineno);
1186
1187 return -1;
1188}
1189
1190static int
Lev Walkinfd171ef2004-06-06 07:20:17 +00001191emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count) {
1192 asn1p_expr_t *expr = arg->expr;
1193
1194 OUT("static asn1_TYPE_tag2member_t asn1_DEF_%s_tag2el[] = {\n",
1195 MKID(expr->Identifier));
1196 if(tag2el_count) {
1197 int i;
1198 for(i = 0; i < tag2el_count; i++) {
1199 OUT(" { ");
1200 _print_tag(arg, expr, &tag2el[i].el_tag);
1201 OUT(", ");
Lev Walkin38abe792004-06-14 13:09:45 +00001202 OUT("%d, ", tag2el[i].el_no);
1203 OUT("%d, ", tag2el[i].toff_first);
1204 OUT("%d ", tag2el[i].toff_last);
Lev Walkinfd171ef2004-06-06 07:20:17 +00001205 OUT("}, /* %s at %d */\n",
1206 tag2el[i].from_expr->Identifier,
1207 tag2el[i].from_expr->_lineno
1208 );
1209 }
1210 }
1211 OUT("};\n");
1212
1213 return 0;;
1214}
1215
1216static int
Lev Walkin64399722004-08-11 07:17:22 +00001217emit_tags_vector(arg_t *arg, asn1p_expr_t *expr, int *tags_impl_skip, int choice_mode) {
1218 int tags_count = 0;
1219 int save_target = arg->target->target;
Lev Walkin27ea3802004-06-28 21:13:46 +00001220 char *p;
1221
Lev Walkin64399722004-08-11 07:17:22 +00001222 if(save_target != OT_IGNORE) {
1223 int save_impl_skip = *tags_impl_skip;
1224 REDIR(OT_IGNORE);
1225 tags_count = emit_tags_vector(arg, expr,
1226 tags_impl_skip, choice_mode);
1227 REDIR(save_target);
1228 if(tags_count) {
1229 *tags_impl_skip = save_impl_skip;
1230 tags_count = 0;
1231 } else {
1232 return 0;
1233 }
1234 }
1235
1236
Lev Walkin27ea3802004-06-28 21:13:46 +00001237 p = MKID(expr->Identifier);
1238 OUT("static ber_tlv_tag_t asn1_DEF_%s_tags[] = {\n", p);
1239 INDENTED(
1240 if(expr->tag.tag_class) {
Lev Walkin64399722004-08-11 07:17:22 +00001241 tags_count++;
Lev Walkin27ea3802004-06-28 21:13:46 +00001242 _print_tag(arg, expr, &expr->tag);
1243 if(expr->tag.tag_mode != TM_EXPLICIT)
1244 (*tags_impl_skip)++;
1245 } else {
Lev Walkin64399722004-08-11 07:17:22 +00001246 if(!choice_mode)
1247 (*tags_impl_skip)++;
Lev Walkin27ea3802004-06-28 21:13:46 +00001248 }
Lev Walkin64399722004-08-11 07:17:22 +00001249 if(!choice_mode) {
1250 if(!expr->tag.tag_class
1251 || (expr->meta_type == AMT_TYPE
1252 && expr->tag.tag_mode == TM_EXPLICIT)) {
1253 struct asn1p_type_tag_s tag;
1254 if(expr->tag.tag_class)
1255 OUT(",\n");
1256 tag.tag_class = TC_UNIVERSAL;
1257 tag.tag_mode = TM_IMPLICIT;
1258 tag.tag_value = expr_type2uclass_value[expr->expr_type];
1259 _print_tag(arg, expr, &tag);
1260 tags_count++;
1261 }
Lev Walkin27ea3802004-06-28 21:13:46 +00001262 }
1263 OUT("\n");
1264 );
1265 OUT("};\n");
1266
Lev Walkin64399722004-08-11 07:17:22 +00001267 return tags_count;
Lev Walkin27ea3802004-06-28 21:13:46 +00001268}
Lev Walkin59004fa2004-08-20 13:37:01 +00001269
1270static int
1271_expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
1272 asn1p_expr_t *topmost_parent;
1273 asn1p_expr_t *v;
1274 int elements = 0;
1275
1276 topmost_parent = asn1f_find_terminal_type_ex(arg->asn,
1277 arg->mod, expr, 0);
1278 if(!topmost_parent) return 0;
1279
1280 if(!(topmost_parent->expr_type & ASN_CONSTR_MASK))
1281 return 0;
1282
1283 TQ_FOR(v, &(topmost_parent->members), next) {
1284 if(v->expr_type != A1TC_EXTENSIBLE)
1285 elements++;
1286 }
1287
1288 return elements;
1289}
1290
1291static int
1292_emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
1293 int save_target;
1294 arg_t tmp_arg;
1295 char *p;
1296
1297 OUT("{ ");
1298 if(expr->marker) {
1299 asn1p_expr_t *tv;
1300 int opts = 0;
1301 for(tv = expr; tv && tv->marker;
1302 tv = TQ_NEXT(tv, next), opts++) {
1303 if(tv->expr_type == A1TC_EXTENSIBLE)
1304 opts--;
1305 }
1306 OUT("%d, ", opts);
1307 } else {
1308 OUT("0, ");
1309 }
1310 if(expr->Identifier) {
1311 OUT("offsetof(struct %s, ", MKID(arg->expr->Identifier));
1312 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1313 && (!UNNAMED_UNIONS)) OUT("choice.");
1314 OUT("%s),\n", MKID(expr->Identifier));
1315 } else {
1316 assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
1317 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
1318 OUT("0,\n");
1319 }
1320 INDENT(+1);
1321 if(C99_MODE) OUT(".tag = ");
1322 _print_tag(arg, expr , NULL);
1323 OUT(",\n");
1324 if(C99_MODE) OUT(".tag_mode = ");
1325 if(expr->tag.tag_class) {
1326 if(expr->tag.tag_mode == TM_IMPLICIT)
1327 OUT("-1,\t/* IMPLICIT tag at current level */\n");
1328 else
1329 OUT("+1,\t/* EXPLICIT tag at current level */\n");
1330 } else {
1331 OUT("0,\n");
1332 }
1333 if(C99_MODE) OUT(".type = ");
1334 OUT("(void *)&asn1_DEF_%s,\n",
1335 asn1c_type_name(arg, expr, TNF_SAFE));
1336 if(C99_MODE) OUT(".memb_constraints = ");
1337 if(expr->constraints) {
1338 p = MKID(expr->Identifier);
1339 if(!expr->Identifier)
1340 p = asn1c_type_name(arg, expr, TNF_SAFE);
1341 OUT("memb_%s_constraint,\n", p);
1342 } else {
1343 OUT("0,\t/* Defer to actual type */\n");
1344 }
1345 if(C99_MODE) OUT(".name = ");
1346 OUT("\"%s\"\n", expr->Identifier ? expr->Identifier : "");
1347 OUT("},\n");
1348 INDENT(-1);
1349
1350 if(!expr->constraints)
1351 return 0;
1352
1353 save_target = arg->target->target;
1354 REDIR(OT_CODE);
1355
1356 if(expr->Identifier)
1357 p = MKID(expr->Identifier);
1358 else
1359 p = asn1c_type_name(arg, expr, TNF_SAFE);
1360 OUT("static int\n");
1361 OUT("memb_%s_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,\n", p);
1362 INDENT(+1);
1363 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
1364 tmp_arg = *arg;
1365 tmp_arg.expr = expr;
1366 if(asn1c_emit_constraint_checking_code(&tmp_arg) == 1) {
1367 OUT("return td->check_constraints\n");
1368 OUT("\t(td, sptr, app_errlog, app_key);\n");
1369 }
1370 INDENT(-1);
1371 OUT("}\n");
1372 OUT("\n");
1373
1374 REDIR(save_target);
1375
1376 return 0;
1377}