blob: 4948016ada0584a3e6763436e95ac1ceebbde03d [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001/*
2 * Don't look into this file. First, because it's a mess, and second, because
3 * it's a brain of the compiler, and you don't wanna mess with brains do you? ;)
4 */
5#include "asn1c_internal.h"
6#include "asn1c_C.h"
Lev Walkin84cd58e2004-08-19 13:29:46 +00007#include "asn1c_constraint.h"
Lev Walkin59004fa2004-08-20 13:37:01 +00008#include "asn1c_out.h"
9#include "asn1c_misc.h"
Lev Walkin84cd58e2004-08-19 13:29:46 +000010#include <asn1fix_export.h> /* Stuff exported by libasn1fix */
Lev Walkinf15320b2004-06-03 03:38:44 +000011
Lev Walkinfd171ef2004-06-06 07:20:17 +000012typedef struct tag2el_s {
13 struct asn1p_type_tag_s el_tag;
14 int el_no;
Lev Walkin38abe792004-06-14 13:09:45 +000015 int toff_first;
16 int toff_last;
Lev Walkinfd171ef2004-06-06 07:20:17 +000017 asn1p_expr_t *from_expr;
18} tag2el_t;
19
20static int _fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no);
21static int _add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no);
22
Lev Walkinf15320b2004-06-03 03:38:44 +000023static int asn1c_lang_C_type_SEQUENCE_def(arg_t *arg);
24static int asn1c_lang_C_type_SET_def(arg_t *arg);
25static int asn1c_lang_C_type_CHOICE_def(arg_t *arg);
26static int asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of);
27static int _print_tag(arg_t *arg, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag_p);
Lev Walkin35631482004-07-01 00:52:50 +000028static int check_if_extensible(asn1p_expr_t *expr);
Lev Walkin59964be2004-08-25 02:03:12 +000029static int expr_elements_count(arg_t *arg, asn1p_expr_t *expr);
30static int emit_member_table(arg_t *arg, 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 Walkin59964be2004-08-25 02:03:12 +000034enum etd_cp {
35 ETD_CP_UNKNOWN = -2,
36 ETD_CP_EITHER = -1,
37 ETD_CP_PRIMITIVE = 0,
38 ETD_CP_CONSTRUCTED = 1,
39};
40enum etd_spec {
41 ETD_NO_SPECIFICS,
42 ETD_HAS_SPECIFICS
43};
44static int emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, int tags_count, int tags_impl_skip, int elements_count, enum etd_cp, enum etd_spec);
45
Lev Walkin59004fa2004-08-20 13:37:01 +000046#define C99_MODE (!(arg->flags & A1C_NO_C99))
Lev Walkinf15320b2004-06-03 03:38:44 +000047#define UNNAMED_UNIONS (arg->flags & A1C_UNNAMED_UNIONS)
48
49#define PCTX_DEF INDENTED( \
50 OUT("\n"); \
51 OUT("/* Context for parsing across buffer boundaries */\n"); \
52 OUT("ber_dec_ctx_t _ber_dec_ctx;\n"));
53
Lev Walkin3dcaafa2004-08-11 05:21:32 +000054#define DEPENDENCIES do { \
Lev Walkin08079b02004-08-22 03:25:24 +000055 asn1p_expr_t *__m; \
56 TQ_FOR(__m, &(expr->members), next) { \
57 if((!(__m->expr_type & ASN_CONSTR_MASK) \
58 && __m->expr_type > ASN_CONSTR_MASK) \
59 || __m->meta_type == AMT_TYPEREF) { \
60 GEN_INCLUDE(asn1c_type_name(arg, \
61 __m, TNF_INCLUDE)); \
Lev Walkin3dcaafa2004-08-11 05:21:32 +000062 } \
63 } \
64 if(expr->expr_type == ASN_CONSTR_SET_OF) \
65 GEN_INCLUDE("asn_SET_OF"); \
66 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF) \
67 GEN_INCLUDE("asn_SEQUENCE_OF"); \
68} while(0)
Lev Walkinf15320b2004-06-03 03:38:44 +000069
70#define MKID(id) asn1c_make_identifier(0, (id), 0)
71
72int
73asn1c_lang_C_type_ENUMERATED(arg_t *arg) {
74 asn1p_expr_t *expr = arg->expr;
75 asn1p_expr_t *v;
76
77 REDIR(OT_DEPS);
78
79 OUT("typedef enum %s {\n", MKID(expr->Identifier));
80 TQ_FOR(v, &(expr->members), next) {
81 switch(v->expr_type) {
82 case A1TC_UNIVERVAL:
83 OUT("\t%s\t= %lld,\n",
84 asn1c_make_identifier(0,
85 expr->Identifier,
86 v->Identifier, 0),
87 v->value->value.v_integer);
88 break;
89 case A1TC_EXTENSIBLE:
90 OUT("\t/*\n");
91 OUT("\t * Enumeration is extensible\n");
92 OUT("\t */\n");
93 break;
94 default:
95 return -1;
96 }
97 }
98 OUT("} %s_e;\n", MKID(expr->Identifier));
99
100 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
101}
102
103
104int
105asn1c_lang_C_type_INTEGER(arg_t *arg) {
106 asn1p_expr_t *expr = arg->expr;
107 asn1p_expr_t *v;
108
109 REDIR(OT_DEPS);
110
111 if(TQ_FIRST(&(expr->members))) {
112 OUT("typedef enum %s {\n", MKID(expr->Identifier));
113 TQ_FOR(v, &(expr->members), next) {
114 switch(v->expr_type) {
115 case A1TC_UNIVERVAL:
116 OUT("\t%s\t= %lld,\n",
117 asn1c_make_identifier(0,
118 expr->Identifier,
119 v->Identifier, 0),
120 v->value->value.v_integer);
121 break;
122 default:
123 return -1;
124 }
125 }
126 OUT("} %s_e;\n", MKID(expr->Identifier));
127 }
128
129 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
130}
131
132int
133asn1c_lang_C_type_SEQUENCE(arg_t *arg) {
134 asn1p_expr_t *expr = arg->expr;
135 asn1p_expr_t *v;
136 int comp_mode = 0; /* {root,ext=1,root,root,...} */
137
138 DEPENDENCIES;
139
140 if(arg->embed) {
Lev Walkin08079b02004-08-22 03:25:24 +0000141 OUT("struct %s {\n", MKID(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +0000142 } else {
143 OUT("typedef struct %s {\n",
144 MKID(expr->Identifier));
145 }
146
147 TQ_FOR(v, &(expr->members), next) {
148 if(v->expr_type == A1TC_EXTENSIBLE) {
149 if(comp_mode < 3) comp_mode++;
150 }
151 if(comp_mode == 1 && !v->marker)
152 v->marker = EM_OPTIONAL;
153 EMBED(v);
154 }
155
156 PCTX_DEF;
Lev Walkin08079b02004-08-22 03:25:24 +0000157 OUT("} %s%s%s", expr->marker?"*":"",
158 expr->_anonymous_type ? "" : MKID(expr->Identifier),
159 arg->embed ? "" : "_t");
Lev Walkinf15320b2004-06-03 03:38:44 +0000160
161 return asn1c_lang_C_type_SEQUENCE_def(arg);
162}
163
164static int
165asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
166 asn1p_expr_t *expr = arg->expr;
167 asn1p_expr_t *v;
168 int elements; /* Number of elements */
169 int tags_impl_skip = 0;
170 int comp_mode = 0; /* {root,ext=1,root,root,...} */
171 int ext_start = -1;
172 int ext_stop = -1;
Lev Walkinfd171ef2004-06-06 07:20:17 +0000173 tag2el_t *tag2el = NULL;
174 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000175 int tags_count;
Lev Walkinf15320b2004-06-03 03:38:44 +0000176 char *p;
177
Lev Walkinfd171ef2004-06-06 07:20:17 +0000178 /*
179 * Fetch every inner tag from the tag to elements map.
180 */
181 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
182 if(tag2el) free(tag2el);
183 return -1;
184 }
185
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000186 GEN_INCLUDE("constr_SEQUENCE");
187 if(!arg->embed)
188 GEN_DECLARE(expr); /* asn1_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000189
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000190 REDIR(OT_STAT_DEFS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000191
192 /*
193 * Print out the table according to which the parsing is performed.
194 */
195 p = MKID(expr->Identifier);
Lev Walkin59004fa2004-08-20 13:37:01 +0000196 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000197
198 elements = 0;
199 INDENTED(TQ_FOR(v, &(expr->members), next) {
200 if(v->expr_type == A1TC_EXTENSIBLE) {
201 if((++comp_mode) == 1)
202 ext_start = elements - 1;
203 else
204 ext_stop = elements - 1;
205 continue;
206 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000207 elements++;
Lev Walkin59964be2004-08-25 02:03:12 +0000208 emit_member_table(arg, v);
Lev Walkinf15320b2004-06-03 03:38:44 +0000209 });
210 OUT("};\n");
211
Lev Walkin27ea3802004-06-28 21:13:46 +0000212 /*
213 * Print out asn1_DEF_<type>_tags[] vector.
214 */
Lev Walkin64399722004-08-11 07:17:22 +0000215 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000216
Lev Walkinfd171ef2004-06-06 07:20:17 +0000217 /*
218 * Tags to elements map.
219 */
220 emit_tag2member_map(arg, tag2el, tag2el_count);
221
Lev Walkin27ea3802004-06-28 21:13:46 +0000222 p = MKID(expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000223 OUT("static asn1_SEQUENCE_specifics_t asn1_DEF_%s_specs = {\n", p);
224 INDENTED(
225 OUT("sizeof(struct %s),\n", p);
226 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
Lev Walkinfd171ef2004-06-06 07:20:17 +0000227 OUT("asn1_DEF_%s_tag2el,\n", p);
228 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000229 OUT("%d,\t/* Start extensions */\n",
230 ext_start);
231 OUT("%d\t/* Stop extensions */\n",
232 (ext_stop<ext_start)?elements+1:ext_stop, ext_stop);
233 );
234 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000235
236 /*
237 * Emit asn1_DEF_xxx table.
238 */
239 emit_type_DEF(arg, expr, tags_count, tags_impl_skip, elements,
240 ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000241
Lev Walkinf15320b2004-06-03 03:38:44 +0000242 REDIR(OT_TYPE_DECLS);
243
244 return 0;
245}
246
247int
Lev Walkinf15320b2004-06-03 03:38:44 +0000248asn1c_lang_C_type_SET(arg_t *arg) {
249 asn1p_expr_t *expr = arg->expr;
250 asn1p_expr_t *v;
251 long mcount;
252 char *id;
253 int comp_mode = 0; /* {root,ext=1,root,root,...} */
254
255 DEPENDENCIES;
256
257 REDIR(OT_DEPS);
258
259 OUT("\n");
260 OUT("/*\n");
261 OUT(" * Method of determining the components presence\n");
262 OUT(" */\n");
263 mcount = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000264 OUT("typedef enum %s_PR {\n", MKID(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +0000265 TQ_FOR(v, &(expr->members), next) {
266 if(v->expr_type == A1TC_EXTENSIBLE) continue;
267 INDENTED(
268 id = MKID(expr->Identifier);
269 OUT("%s_PR_", id);
270 id = MKID(v->Identifier);
271 OUT("%s,\t/* Member %s is present */\n",
272 id, id)
273 );
274 mcount++;
275 }
Lev Walkin64399722004-08-11 07:17:22 +0000276 id = MKID(expr->Identifier);
277 OUT("} %s_PR;\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000278
279 REDIR(OT_TYPE_DECLS);
280
281 if(arg->embed) {
Lev Walkin64399722004-08-11 07:17:22 +0000282 OUT("struct %s {\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000283 } else {
Lev Walkin64399722004-08-11 07:17:22 +0000284 OUT("typedef struct %s {\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000285 }
286
287 TQ_FOR(v, &(expr->members), next) {
288 if(v->expr_type == A1TC_EXTENSIBLE) {
289 if(comp_mode < 3) comp_mode++;
290 }
291 if(comp_mode == 1 && !v->marker)
292 v->marker = EM_OPTIONAL;
293 EMBED(v);
294 }
295
296 INDENTED(
297 id = MKID(expr->Identifier);
298 OUT("\n");
299 OUT("/* Presence bitmask: ASN_SET_ISPRESENT(p%s, %s_PR_x) */\n",
300 id, id);
301 OUT("unsigned int _presence_map\n");
302 OUT("\t[((%ld+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))];\n", mcount);
303 );
304
305 PCTX_DEF;
Lev Walkin08079b02004-08-22 03:25:24 +0000306 OUT("} %s%s%s", expr->marker?"*":"",
307 expr->_anonymous_type ? "" : MKID(expr->Identifier),
308 arg->embed ? "" : "_t");
Lev Walkinf15320b2004-06-03 03:38:44 +0000309
310 return asn1c_lang_C_type_SET_def(arg);
311}
312
Lev Walkinf15320b2004-06-03 03:38:44 +0000313static int
314asn1c_lang_C_type_SET_def(arg_t *arg) {
315 asn1p_expr_t *expr = arg->expr;
316 asn1p_expr_t *v;
317 int elements;
318 int tags_impl_skip = 0;
319 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Lev Walkinf15320b2004-06-03 03:38:44 +0000320 tag2el_t *tag2el = NULL;
321 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000322 int tags_count;
Lev Walkinf15320b2004-06-03 03:38:44 +0000323 char *p;
324
325 /*
326 * Fetch every inner tag from the tag to elements map.
327 */
328 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
329 if(tag2el) free(tag2el);
330 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000331 }
332
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000333 GEN_INCLUDE("constr_SET");
334 if(!arg->embed)
335 GEN_DECLARE(expr); /* asn1_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000336
337 REDIR(OT_STAT_DEFS);
338
Lev Walkinf15320b2004-06-03 03:38:44 +0000339 /*
340 * Print out the table according to which the parsing is performed.
341 */
342 p = MKID(expr->Identifier);
Lev Walkin59004fa2004-08-20 13:37:01 +0000343 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000344
345 elements = 0;
346 INDENTED(TQ_FOR(v, &(expr->members), next) {
347 if(v->expr_type != A1TC_EXTENSIBLE) {
348 if(comp_mode == 1)
349 v->marker = EM_OPTIONAL;
Lev Walkinf15320b2004-06-03 03:38:44 +0000350 } else {
351 if(comp_mode < 3) comp_mode++;
352 continue;
353 }
Lev Walkin59004fa2004-08-20 13:37:01 +0000354 elements++;
Lev Walkin59964be2004-08-25 02:03:12 +0000355 emit_member_table(arg, v);
Lev Walkinf15320b2004-06-03 03:38:44 +0000356 });
357 OUT("};\n");
358
Lev Walkin27ea3802004-06-28 21:13:46 +0000359 /*
360 * Print out asn1_DEF_<type>_tags[] vector.
361 */
Lev Walkin64399722004-08-11 07:17:22 +0000362 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000363
364 /*
365 * Tags to elements map.
366 */
Lev Walkinfd171ef2004-06-06 07:20:17 +0000367 emit_tag2member_map(arg, tag2el, tag2el_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000368
369 /*
370 * Emit a map of mandatory elements.
371 */
Lev Walkin27ea3802004-06-28 21:13:46 +0000372 p = MKID(expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000373 OUT("static uint8_t asn1_DEF_%s_mmap", p);
374 OUT("[(%d + (8 * sizeof(unsigned int)) - 1) / 8]", elements);
375 OUT(" = {\n", p);
376 INDENTED(
377 if(elements) {
378 int delimit = 0;
379 int el = 0;
380 TQ_FOR(v, &(expr->members), next) {
381 if(v->expr_type == A1TC_EXTENSIBLE) continue;
382 if(delimit) {
383 OUT(",\n");
384 delimit = 0;
385 } else if(el) {
386 OUT(" | ");
387 }
388 OUT("(%d << %d)", v->marker?0:1, 7 - (el % 8));
389 if(el && (el % 8) == 0)
390 delimit = 1;
391 el++;
392 }
393 } else {
394 OUT("0");
395 }
396 );
397 OUT("\n");
398 OUT("};\n");
399
400 OUT("static asn1_SET_specifics_t asn1_DEF_%s_specs = {\n", p);
401 INDENTED(
402 OUT("sizeof(struct %s),\n", p);
403 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
404 OUT("offsetof(struct %s, _presence_map),\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000405 OUT("asn1_DEF_%s_tag2el,\n", p);
406 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
Lev Walkin35631482004-07-01 00:52:50 +0000407 OUT("%d,\t/* Whether extensible */\n",
408 check_if_extensible(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +0000409 OUT("(unsigned int *)asn1_DEF_%s_mmap\t/* Mandatory elements map */\n", p);
410 );
411 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000412
413 /*
414 * Emit asn1_DEF_xxx table.
415 */
416 emit_type_DEF(arg, expr, tags_count, tags_impl_skip, elements,
417 ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000418
Lev Walkinf15320b2004-06-03 03:38:44 +0000419 REDIR(OT_TYPE_DECLS);
420
421 return 0;
422}
423
424int
Lev Walkin08079b02004-08-22 03:25:24 +0000425asn1c_lang_C_type_SEx_OF(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000426 asn1p_expr_t *expr = arg->expr;
Lev Walkin08079b02004-08-22 03:25:24 +0000427 asn1p_expr_t *memb;
Lev Walkinf15320b2004-06-03 03:38:44 +0000428
429 DEPENDENCIES;
430
431 if(arg->embed) {
432 OUT("struct %s {\n", MKID(expr->Identifier));
433 } else {
Lev Walkin08079b02004-08-22 03:25:24 +0000434 OUT("typedef struct %s {\n", MKID(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +0000435 }
436
Lev Walkin08079b02004-08-22 03:25:24 +0000437 memb = TQ_FIRST(&expr->members);
438
439 INDENT(+1);
440 OUT("A_%s_OF(",
441 (arg->expr->expr_type == ASN_CONSTR_SET_OF)
442 ? "SET" : "SEQUENCE");
443 if(memb->expr_type & ASN_CONSTR_MASK) {
444 arg_t tmp;
445 asn1p_expr_t tmp_memb;
446 arg->embed++;
447 tmp = *arg;
448 tmp.expr = &tmp_memb;
449 tmp_memb = *memb;
450 tmp_memb._anonymous_type = 1;
451 tmp_memb.Identifier = strdup(
452 asn1c_make_identifier(0,
453 expr->Identifier, "member", 0));
454 assert(tmp_memb.Identifier);
455 tmp.default_cb(&tmp);
456 free(tmp_memb.Identifier);
457 arg->embed--;
458 assert(arg->target->target == OT_TYPE_DECLS);
459 } else {
460 OUT("%s", asn1c_type_name(arg, memb, TNF_RSAFE));
Lev Walkinf15320b2004-06-03 03:38:44 +0000461 }
Lev Walkin08079b02004-08-22 03:25:24 +0000462 OUT(") list;\n");
463 INDENT(-1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000464
465 PCTX_DEF;
Lev Walkin08079b02004-08-22 03:25:24 +0000466 OUT("} %s%s%s", expr->marker?"*":"",
467 expr->_anonymous_type ? "" : MKID(expr->Identifier),
468 arg->embed ? "" : "_t");
Lev Walkinf15320b2004-06-03 03:38:44 +0000469
470 /*
Lev Walkin08079b02004-08-22 03:25:24 +0000471 * SET OF/SEQUENCE OF definition
Lev Walkinf15320b2004-06-03 03:38:44 +0000472 */
Lev Walkin08079b02004-08-22 03:25:24 +0000473 return asn1c_lang_C_type_SEx_OF_def(arg,
474 (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF));
Lev Walkinf15320b2004-06-03 03:38:44 +0000475}
476
477static int
478asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
479 asn1p_expr_t *expr = arg->expr;
480 asn1p_expr_t *v;
481 int tags_impl_skip = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000482 int tags_count;
Lev Walkinf15320b2004-06-03 03:38:44 +0000483 char *p;
484
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000485 /*
486 * Print out the table according to which the parsing is performed.
487 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000488 if(seq_of) {
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000489 GEN_INCLUDE("constr_SEQUENCE_OF");
Lev Walkinf15320b2004-06-03 03:38:44 +0000490 } else {
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000491 GEN_INCLUDE("constr_SET_OF");
Lev Walkinf15320b2004-06-03 03:38:44 +0000492 }
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000493 if(!arg->embed)
494 GEN_DECLARE(expr); /* asn1_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000495
496 REDIR(OT_STAT_DEFS);
497
498 /*
499 * Print out the table according to which the parsing is performed.
500 */
501 p = MKID(expr->Identifier);
Lev Walkin59004fa2004-08-20 13:37:01 +0000502 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000503
Lev Walkin59004fa2004-08-20 13:37:01 +0000504 INDENTED(
Lev Walkinf15320b2004-06-03 03:38:44 +0000505 v = TQ_FIRST(&(expr->members));
Lev Walkin59964be2004-08-25 02:03:12 +0000506 emit_member_table(arg, v);
Lev Walkinf15320b2004-06-03 03:38:44 +0000507 );
508 OUT("};\n");
509
Lev Walkin27ea3802004-06-28 21:13:46 +0000510 /*
511 * Print out asn1_DEF_<type>_tags[] vector.
512 */
Lev Walkin64399722004-08-11 07:17:22 +0000513 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000514
Lev Walkin27ea3802004-06-28 21:13:46 +0000515 p = MKID(expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000516 OUT("static asn1_SET_OF_specifics_t asn1_DEF_%s_specs = {\n", p);
517 INDENTED(
518 OUT("sizeof(struct %s),\n", p);
519 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000520 );
521 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000522
523 /*
524 * Emit asn1_DEF_xxx table.
525 */
526 emit_type_DEF(arg, expr, tags_count, tags_impl_skip, 1,
527 ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000528
Lev Walkinf15320b2004-06-03 03:38:44 +0000529 REDIR(OT_TYPE_DECLS);
530
531 return 0;
532}
533
534int
535asn1c_lang_C_type_CHOICE(arg_t *arg) {
536 asn1p_expr_t *expr = arg->expr;
537 asn1p_expr_t *v;
Lev Walkin08079b02004-08-22 03:25:24 +0000538 char *id;
Lev Walkinf15320b2004-06-03 03:38:44 +0000539
540 DEPENDENCIES;
541
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000542 REDIR(OT_DEPS);
543
Lev Walkin08079b02004-08-22 03:25:24 +0000544 id = MKID(expr->Identifier);
545 OUT("typedef enum %s_PR {\n", id);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000546 INDENTED(
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000547 OUT("%s_PR_NOTHING,\t"
Lev Walkin08079b02004-08-22 03:25:24 +0000548 "/* No components present */\n", id);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000549 TQ_FOR(v, &(expr->members), next) {
550 if(v->expr_type == A1TC_EXTENSIBLE) {
551 OUT("/* Extensions may appear below */\n");
552 continue;
553 }
Lev Walkin08079b02004-08-22 03:25:24 +0000554 id = MKID(expr->Identifier);
555 OUT("%s_PR_", id);
556 id = MKID(v->Identifier);
557 OUT("%s,\n", id, id);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000558 }
559 );
Lev Walkin08079b02004-08-22 03:25:24 +0000560 id = MKID(expr->Identifier);
561 OUT("} %s_PR;\n", id);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000562
563 REDIR(OT_TYPE_DECLS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000564
565 if(arg->embed) {
Lev Walkin08079b02004-08-22 03:25:24 +0000566 OUT("struct %s {\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000567 } else {
Lev Walkin08079b02004-08-22 03:25:24 +0000568 OUT("typedef struct %s {\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000569 }
570
571 INDENTED(
Lev Walkin08079b02004-08-22 03:25:24 +0000572 OUT("%s_PR present;\n", id);
573 OUT("union {\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000574 TQ_FOR(v, &(expr->members), next) {
575 EMBED(v);
576 }
577 if(UNNAMED_UNIONS) OUT("};\n");
578 else OUT("} choice;\n");
579 );
580
581 PCTX_DEF;
Lev Walkin08079b02004-08-22 03:25:24 +0000582 OUT("} %s%s%s", expr->marker?"*":"",
583 expr->_anonymous_type ? "" : MKID(expr->Identifier),
584 arg->embed ? "" : "_t");
Lev Walkinf15320b2004-06-03 03:38:44 +0000585
586 return asn1c_lang_C_type_CHOICE_def(arg);
587}
588
589static int
590asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
591 asn1p_expr_t *expr = arg->expr;
592 asn1p_expr_t *v;
593 int elements; /* Number of elements */
594 int tags_impl_skip = 0;
595 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Lev Walkinf15320b2004-06-03 03:38:44 +0000596 tag2el_t *tag2el = NULL;
597 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000598 int tags_count;
Lev Walkinf15320b2004-06-03 03:38:44 +0000599 char *p;
600
601 /*
602 * Fetch every inner tag from the tag to elements map.
603 */
604 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
605 if(tag2el) free(tag2el);
606 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000607 }
608
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000609 GEN_INCLUDE("constr_CHOICE");
610 if(!arg->embed)
611 GEN_DECLARE(expr); /* asn1_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000612
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000613 REDIR(OT_STAT_DEFS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000614
615 /*
616 * Print out the table according to which the parsing is performed.
617 */
618 p = MKID(expr->Identifier);
Lev Walkin59004fa2004-08-20 13:37:01 +0000619 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000620
621 elements = 0;
622 INDENTED(TQ_FOR(v, &(expr->members), next) {
623 if(v->expr_type != A1TC_EXTENSIBLE) {
624 if(comp_mode == 1)
625 v->marker = EM_OPTIONAL;
Lev Walkinf15320b2004-06-03 03:38:44 +0000626 } else {
627 if(comp_mode < 3) comp_mode++;
628 continue;
629 }
Lev Walkin59004fa2004-08-20 13:37:01 +0000630 elements++;
Lev Walkin59964be2004-08-25 02:03:12 +0000631 emit_member_table(arg, v);
Lev Walkinf15320b2004-06-03 03:38:44 +0000632 });
633 OUT("};\n");
634
Lev Walkin64399722004-08-11 07:17:22 +0000635
Lev Walkinf15320b2004-06-03 03:38:44 +0000636 if(arg->embed) {
637 /*
638 * Our parent structure has already taken this into account.
639 */
Lev Walkin64399722004-08-11 07:17:22 +0000640 tags_count = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000641 } else {
Lev Walkin64399722004-08-11 07:17:22 +0000642 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000643 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000644
645 /*
646 * Tags to elements map.
647 */
Lev Walkinfd171ef2004-06-06 07:20:17 +0000648 emit_tag2member_map(arg, tag2el, tag2el_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000649
Lev Walkin64399722004-08-11 07:17:22 +0000650 p = MKID(expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000651 OUT("static asn1_CHOICE_specifics_t asn1_DEF_%s_specs = {\n", p);
652 INDENTED(
653 OUT("sizeof(struct %s),\n", p);
654 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
655 OUT("offsetof(struct %s, present),\n", p);
656 OUT("sizeof(((struct %s *)0)->present),\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000657 OUT("asn1_DEF_%s_tag2el,\n", p);
658 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
Lev Walkin35631482004-07-01 00:52:50 +0000659 OUT("%d\t/* Whether extensible */\n",
660 check_if_extensible(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +0000661 );
662 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000663
664 /*
665 * Emit asn1_DEF_xxx table.
666 */
667 emit_type_DEF(arg, expr, tags_count, tags_impl_skip, elements,
668 ETD_CP_CONSTRUCTED /*either?!*/, ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000669
Lev Walkinf15320b2004-06-03 03:38:44 +0000670 REDIR(OT_TYPE_DECLS);
671
672 return 0;
673}
674
675int
676asn1c_lang_C_type_REFERENCE(arg_t *arg) {
677 asn1p_ref_t *ref;
678
679 ref = arg->expr->reference;
680 if(ref->components[ref->comp_count-1].name[0] == '&') {
Lev Walkinf15320b2004-06-03 03:38:44 +0000681 asn1p_expr_t *extract;
682 arg_t tmp;
683 int ret;
684
Lev Walkin08079b02004-08-22 03:25:24 +0000685 extract = asn1f_class_access_ex(arg->asn, arg->mod,
686 arg->expr, ref);
Lev Walkinf15320b2004-06-03 03:38:44 +0000687 if(extract == NULL)
688 return -1;
689
Lev Walkin08079b02004-08-22 03:25:24 +0000690 extract = asn1p_expr_clone(extract, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000691 if(extract) {
692 if(extract->Identifier)
693 free(extract->Identifier);
694 extract->Identifier = strdup(arg->expr->Identifier);
695 if(extract->Identifier == NULL) {
696 asn1p_expr_free(extract);
697 return -1;
698 }
699 } else {
700 return -1;
701 }
702
703 tmp = *arg;
704 tmp.asn = arg->asn;
Lev Walkin08079b02004-08-22 03:25:24 +0000705 tmp.mod = extract->module;
Lev Walkinf15320b2004-06-03 03:38:44 +0000706 tmp.expr = extract;
707
708 ret = arg->default_cb(&tmp);
709
710 asn1p_expr_free(extract);
711
712 return ret;
713 }
714
715
716 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
717}
718
719int
720asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
721 asn1p_expr_t *expr = arg->expr;
722 int tags_impl_skip = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000723 int tags_count;
Lev Walkinf15320b2004-06-03 03:38:44 +0000724 char *p;
725
726 if(arg->embed) {
727 REDIR(OT_TYPE_DECLS);
728
729 OUT("%s\t", asn1c_type_name(arg, arg->expr,
730 expr->marker?TNF_RSAFE:TNF_CTYPE));
731 OUT("%s", expr->marker?"*":" ");
Lev Walkin08079b02004-08-22 03:25:24 +0000732 OUT("%s", MKID(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +0000733 if(expr->marker) OUT("\t/* %s */",
734 (expr->marker==EM_OPTIONAL)?"OPTIONAL":"DEFAULT");
Lev Walkin59004fa2004-08-20 13:37:01 +0000735
736 REDIR(OT_TYPE_DECLS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000737 return 0;
738 }
739
Lev Walkinf15320b2004-06-03 03:38:44 +0000740
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000741 GEN_INCLUDE(asn1c_type_name(arg, expr, TNF_INCLUDE));
Lev Walkinf15320b2004-06-03 03:38:44 +0000742
743 REDIR(OT_TYPE_DECLS);
744
745 OUT("typedef %s\t", asn1c_type_name(arg, arg->expr, TNF_CTYPE));
746 OUT("%s", expr->marker?"*":" ");
Lev Walkin08079b02004-08-22 03:25:24 +0000747 OUT("%s_t", MKID(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +0000748
749 REDIR(OT_STAT_DEFS);
750
Lev Walkin27ea3802004-06-28 21:13:46 +0000751 /*
752 * Print out asn1_DEF_<type>_tags[] vector.
753 */
Lev Walkin64399722004-08-11 07:17:22 +0000754 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000755
Lev Walkin59964be2004-08-25 02:03:12 +0000756 emit_type_DEF(arg, expr, tags_count, tags_impl_skip, 0,
757 ETD_CP_UNKNOWN, ETD_NO_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000758
Lev Walkin59004fa2004-08-20 13:37:01 +0000759 REDIR(OT_CODE);
760
Lev Walkinf15320b2004-06-03 03:38:44 +0000761 /*
762 * Constraint checking.
763 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000764 p = MKID(expr->Identifier);
765 OUT("int\n");
766 OUT("%s_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,\n", p);
767 INDENTED(
768 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
769 OUT("\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000770 if(asn1c_emit_constraint_checking_code(arg) == 1) {
771 if(0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000772 OUT("/* Check the constraints of the underlying type */\n");
773 OUT("return asn1_DEF_%s.check_constraints\n",
774 asn1c_type_name(arg, expr, TNF_SAFE));
775 OUT("\t(td, sptr, app_errlog, app_key);\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000776 } else {
Lev Walkinf15320b2004-06-03 03:38:44 +0000777 OUT("/* Make the underlying type checker permanent */\n");
778 OUT("td->check_constraints = asn1_DEF_%s.check_constraints;\n",
779 asn1c_type_name(arg, expr, TNF_SAFE));
780 OUT("return td->check_constraints\n");
781 OUT("\t(td, sptr, app_errlog, app_key);\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000782 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000783 }
784 );
785 OUT("}\n");
786 OUT("\n");
787
788 /*
789 * Emit suicidal functions.
790 */
791
Lev Walkinf15320b2004-06-03 03:38:44 +0000792 /*
793 * This function replaces certain fields from the definition
794 * of a type with the corresponding fields from the basic type
795 * (from which the current type is inherited).
796 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000797 OUT("/*\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000798 OUT(" * This type is implemented using %s,\n",
799 asn1c_type_name(arg, expr, TNF_SAFE));
Lev Walkinf15320b2004-06-03 03:38:44 +0000800 OUT(" * so adjust the DEF appropriately.\n");
801 OUT(" */\n");
802 OUT("static void\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000803 p = MKID(expr->Identifier);
804 OUT("%s_inherit_TYPE_descriptor(asn1_TYPE_descriptor_t *td) {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000805 INDENT(+1);
Lev Walkin59004fa2004-08-20 13:37:01 +0000806 {
807 char *type_name = asn1c_type_name(arg, expr, TNF_SAFE);
808 OUT("td->ber_decoder = asn1_DEF_%s.ber_decoder;\n", type_name);
809 OUT("td->der_encoder = asn1_DEF_%s.der_encoder;\n", type_name);
810 OUT("td->free_struct = asn1_DEF_%s.free_struct;\n", type_name);
811 OUT("td->print_struct = asn1_DEF_%s.print_struct;\n", type_name);
812 OUT("td->last_tag_form = asn1_DEF_%s.last_tag_form;\n", type_name);
813 OUT("td->elements = asn1_DEF_%s.elements;\n", type_name);
814 OUT("td->elements_count = asn1_DEF_%s.elements_count;\n", type_name);
815 OUT("td->specifics = asn1_DEF_%s.specifics;\n", type_name);
816 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000817 INDENT(-1);
818 OUT("}\n");
819 OUT("\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000820
821 p = MKID(expr->Identifier);
822 OUT("ber_dec_rval_t\n");
823 OUT("%s_decode_ber(asn1_TYPE_descriptor_t *td,\n", p);
824 INDENTED(
825 OUT("\tvoid **structure, void *bufptr, size_t size, int tag_mode) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000826 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000827 OUT("return td->ber_decoder(td, structure,\n");
828 OUT("\tbufptr, size, tag_mode);\n");
829 );
830 OUT("}\n");
831 OUT("\n");
832
833 p = MKID(expr->Identifier);
834 OUT("der_enc_rval_t\n");
835 OUT("%s_encode_der(asn1_TYPE_descriptor_t *td,\n", p);
836 INDENTED(
837 OUT("\tvoid *structure, int tag_mode, ber_tlv_tag_t tag,\n");
838 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000839 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000840 OUT("return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);\n");
841 );
842 OUT("}\n");
843 OUT("\n");
844
845 p = MKID(expr->Identifier);
846 OUT("int\n");
847 OUT("%s_print(asn1_TYPE_descriptor_t *td, const void *struct_ptr,\n", p);
848 INDENTED(
849 OUT("\tint ilevel, asn_app_consume_bytes_f *cb, void *app_key) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000850 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000851 OUT("return td->print_struct(td, struct_ptr, ilevel, cb, app_key);\n");
852 );
853 OUT("}\n");
854 OUT("\n");
855
856 p = MKID(expr->Identifier);
857 OUT("void\n");
858 OUT("%s_free(asn1_TYPE_descriptor_t *td,\n", p);
859 INDENTED(
860 OUT("\tvoid *struct_ptr, int contents_only) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000861 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000862 OUT("td->free_struct(td, struct_ptr, contents_only);\n");
863 );
864 OUT("}\n");
865 OUT("\n");
866
867 REDIR(OT_FUNC_DECLS);
868
869 p = MKID(expr->Identifier);
870 OUT("extern asn1_TYPE_descriptor_t asn1_DEF_%s;\n", p);
871 OUT("asn_constr_check_f %s_constraint;\n", p);
872 OUT("ber_type_decoder_f %s_decode_ber;\n", p);
873 OUT("der_type_encoder_f %s_encode_der;\n", p);
874 OUT("asn_struct_print_f %s_print;\n", p);
875 OUT("asn_struct_free_f %s_free;\n", p);
876
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000877 REDIR(OT_TYPE_DECLS);
878
Lev Walkinf15320b2004-06-03 03:38:44 +0000879 return 0;
880}
881
882int
883asn1c_lang_C_type_EXTENSIBLE(arg_t *arg) {
884
885 OUT("/*\n");
886 OUT(" * This type is extensible,\n");
887 OUT(" * possible extensions are below.\n");
888 OUT(" */\n");
889
890 return 0;
891}
892
Lev Walkin35631482004-07-01 00:52:50 +0000893static int check_if_extensible(asn1p_expr_t *expr) {
894 asn1p_expr_t *v;
895 TQ_FOR(v, &(expr->members), next) {
896 if(v->expr_type == A1TC_EXTENSIBLE) return 1;
897 }
898 return 0;
899}
900
Lev Walkinf15320b2004-06-03 03:38:44 +0000901static int
902_print_tag(arg_t *arg, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag_p) {
903 struct asn1p_type_tag_s tag;
904
905 if(tag_p) {
906 tag = *tag_p;
907 } else {
908 if(asn1f_fetch_tag(arg->asn, arg->mod, expr, &tag)) {
909 OUT("-1 /* Ambiguous tag (CHOICE?) */");
910 return 0;
911 }
912 }
913
914 OUT("(");
915 switch(tag.tag_class) {
916 case TC_UNIVERSAL: OUT("ASN_TAG_CLASS_UNIVERSAL"); break;
917 case TC_APPLICATION: OUT("ASN_TAG_CLASS_APPLICATION"); break;
918 case TC_CONTEXT_SPECIFIC: OUT("ASN_TAG_CLASS_CONTEXT"); break;
919 case TC_PRIVATE: OUT("ASN_TAG_CLASS_PRIVATE"); break;
920 case TC_NOCLASS:
921 break;
922 }
923 OUT(" | (%lld << 2))", tag.tag_value);
924
925 return 0;
926}
927
Lev Walkinfd171ef2004-06-06 07:20:17 +0000928
929static int
930_tag2el_cmp(const void *ap, const void *bp) {
931 const tag2el_t *a = ap;
932 const tag2el_t *b = bp;
933 const struct asn1p_type_tag_s *ta = &a->el_tag;
934 const struct asn1p_type_tag_s *tb = &b->el_tag;
935
936 if(ta->tag_class == tb->tag_class) {
937 if(ta->tag_value == tb->tag_value) {
938 /*
939 * Sort by their respective positions.
940 */
941 if(a->el_no < b->el_no)
942 return -1;
943 else if(a->el_no > b->el_no)
944 return 1;
945 return 0;
946 } else if(ta->tag_value < tb->tag_value)
947 return -1;
948 else
949 return 1;
950 } else if(ta->tag_class < tb->tag_class) {
951 return -1;
952 } else {
953 return 1;
954 }
955}
956
Lev Walkinf15320b2004-06-03 03:38:44 +0000957/*
958 * For constructed types, number of external tags may be greater than
959 * number of elements in the type because of CHOICE type.
960 * T ::= SET { -- Three possible tags:
961 * a INTEGER, -- One tag is here...
962 * b Choice1 -- ... and two more tags are there.
963 * }
964 * Choice1 ::= CHOICE {
965 * s1 IA5String,
966 * s2 ObjectDescriptor
967 * }
968 */
969static int
970_fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no) {
971 asn1p_expr_t *expr = arg->expr;
972 arg_t tmparg = *arg;
973 asn1p_expr_t *v;
974 int element = 0;
975
976 TQ_FOR(v, &(expr->members), next) {
977 if(v->expr_type == A1TC_EXTENSIBLE)
978 continue;
979
980 tmparg.expr = v;
981
982 if(_add_tag2el_member(&tmparg, tag2el, count,
983 (el_no==-1)?element:el_no)) {
984 return -1;
985 }
986
987 element++;
988 }
989
Lev Walkinfd171ef2004-06-06 07:20:17 +0000990 /*
Lev Walkin38abe792004-06-14 13:09:45 +0000991 * Sort the map according to canonical order of their tags
992 * and element numbers.
Lev Walkinfd171ef2004-06-06 07:20:17 +0000993 */
994 qsort(*tag2el, *count, sizeof(**tag2el), _tag2el_cmp);
995
Lev Walkin38abe792004-06-14 13:09:45 +0000996 /*
997 * Initialize .toff_{first|last} members.
998 */
999 if(*count) {
1000 struct asn1p_type_tag_s *cur_tag = 0;
1001 tag2el_t *cur = *tag2el;
1002 tag2el_t *end = cur + *count;
1003 int occur, i;
1004 for(occur = 0; cur < end; cur++) {
1005 if(cur_tag == 0
1006 || cur_tag->tag_value != cur->el_tag.tag_value
1007 || cur_tag->tag_class != cur->el_tag.tag_class) {
1008 cur_tag = &cur->el_tag;
1009 occur = 0;
1010 } else {
1011 occur++;
1012 }
1013 cur->toff_first = -occur;
1014 for(i = 0; i >= -occur; i--)
1015 cur[i].toff_last = -i;
1016 }
1017 }
1018
Lev Walkinf15320b2004-06-03 03:38:44 +00001019 return 0;
1020}
1021
1022static int
1023_add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no) {
1024 struct asn1p_type_tag_s tag;
1025 int ret;
1026
1027 assert(el_no >= 0);
1028
1029 ret = asn1f_fetch_tag(arg->asn, arg->mod, arg->expr, &tag);
1030 if(ret == 0) {
1031 void *p;
1032 p = realloc(*tag2el, sizeof(tag2el_t) * ((*count) + 1));
1033 if(p) *tag2el = p;
1034 else return -1;
1035
1036 DEBUG("Found tag for %s: %ld",
1037 arg->expr->Identifier,
1038 (long)tag.tag_value);
1039
1040 (*tag2el)[*count].el_tag = tag;
1041 (*tag2el)[*count].el_no = el_no;
1042 (*tag2el)[*count].from_expr = arg->expr;
1043 (*count)++;
1044 return 0;
1045 }
1046
1047 DEBUG("Searching tag in complex expression %s:%x at line %d",
1048 arg->expr->Identifier,
1049 arg->expr->expr_type,
1050 arg->expr->_lineno);
1051
1052 /*
1053 * Iterate over members of CHOICE type.
1054 */
1055 if(arg->expr->expr_type == ASN_CONSTR_CHOICE) {
1056 return _fill_tag2el_map(arg, tag2el, count, el_no);
1057 }
1058
1059 if(arg->expr->expr_type == A1TC_REFERENCE) {
1060 arg_t tmp = *arg;
1061 asn1p_expr_t *expr;
Lev Walkin08079b02004-08-22 03:25:24 +00001062 expr = asn1f_lookup_symbol_ex(tmp.asn, tmp.mod, tmp.expr,
Lev Walkinf15320b2004-06-03 03:38:44 +00001063 arg->expr->reference);
1064 if(expr) {
Lev Walkin08079b02004-08-22 03:25:24 +00001065 tmp.mod = expr->module;
Lev Walkinf15320b2004-06-03 03:38:44 +00001066 tmp.expr = expr;
1067 return _add_tag2el_member(&tmp, tag2el, count, el_no);
1068 } else {
1069 FATAL("Cannot dereference %s at line %d",
1070 arg->expr->Identifier,
1071 arg->expr->_lineno);
1072 return -1;
1073 }
1074 }
1075
1076 DEBUG("No tag for %s at line %d",
1077 arg->expr->Identifier,
1078 arg->expr->_lineno);
1079
1080 return -1;
1081}
1082
1083static int
Lev Walkinfd171ef2004-06-06 07:20:17 +00001084emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count) {
1085 asn1p_expr_t *expr = arg->expr;
1086
1087 OUT("static asn1_TYPE_tag2member_t asn1_DEF_%s_tag2el[] = {\n",
1088 MKID(expr->Identifier));
1089 if(tag2el_count) {
1090 int i;
1091 for(i = 0; i < tag2el_count; i++) {
1092 OUT(" { ");
1093 _print_tag(arg, expr, &tag2el[i].el_tag);
1094 OUT(", ");
Lev Walkin38abe792004-06-14 13:09:45 +00001095 OUT("%d, ", tag2el[i].el_no);
1096 OUT("%d, ", tag2el[i].toff_first);
1097 OUT("%d ", tag2el[i].toff_last);
Lev Walkinfd171ef2004-06-06 07:20:17 +00001098 OUT("}, /* %s at %d */\n",
1099 tag2el[i].from_expr->Identifier,
1100 tag2el[i].from_expr->_lineno
1101 );
1102 }
1103 }
1104 OUT("};\n");
1105
1106 return 0;;
1107}
1108
1109static int
Lev Walkin64399722004-08-11 07:17:22 +00001110emit_tags_vector(arg_t *arg, asn1p_expr_t *expr, int *tags_impl_skip, int choice_mode) {
1111 int tags_count = 0;
1112 int save_target = arg->target->target;
Lev Walkin27ea3802004-06-28 21:13:46 +00001113 char *p;
1114
Lev Walkin64399722004-08-11 07:17:22 +00001115 if(save_target != OT_IGNORE) {
1116 int save_impl_skip = *tags_impl_skip;
1117 REDIR(OT_IGNORE);
1118 tags_count = emit_tags_vector(arg, expr,
1119 tags_impl_skip, choice_mode);
1120 REDIR(save_target);
1121 if(tags_count) {
1122 *tags_impl_skip = save_impl_skip;
1123 tags_count = 0;
1124 } else {
1125 return 0;
1126 }
1127 }
1128
1129
Lev Walkin27ea3802004-06-28 21:13:46 +00001130 p = MKID(expr->Identifier);
1131 OUT("static ber_tlv_tag_t asn1_DEF_%s_tags[] = {\n", p);
1132 INDENTED(
1133 if(expr->tag.tag_class) {
Lev Walkin64399722004-08-11 07:17:22 +00001134 tags_count++;
Lev Walkin27ea3802004-06-28 21:13:46 +00001135 _print_tag(arg, expr, &expr->tag);
1136 if(expr->tag.tag_mode != TM_EXPLICIT)
1137 (*tags_impl_skip)++;
1138 } else {
Lev Walkin64399722004-08-11 07:17:22 +00001139 if(!choice_mode)
1140 (*tags_impl_skip)++;
Lev Walkin27ea3802004-06-28 21:13:46 +00001141 }
Lev Walkin64399722004-08-11 07:17:22 +00001142 if(!choice_mode) {
1143 if(!expr->tag.tag_class
1144 || (expr->meta_type == AMT_TYPE
1145 && expr->tag.tag_mode == TM_EXPLICIT)) {
1146 struct asn1p_type_tag_s tag;
1147 if(expr->tag.tag_class)
1148 OUT(",\n");
1149 tag.tag_class = TC_UNIVERSAL;
1150 tag.tag_mode = TM_IMPLICIT;
1151 tag.tag_value = expr_type2uclass_value[expr->expr_type];
1152 _print_tag(arg, expr, &tag);
1153 tags_count++;
1154 }
Lev Walkin27ea3802004-06-28 21:13:46 +00001155 }
1156 OUT("\n");
1157 );
1158 OUT("};\n");
1159
Lev Walkin64399722004-08-11 07:17:22 +00001160 return tags_count;
Lev Walkin27ea3802004-06-28 21:13:46 +00001161}
Lev Walkin59004fa2004-08-20 13:37:01 +00001162
1163static int
Lev Walkin59964be2004-08-25 02:03:12 +00001164expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin59004fa2004-08-20 13:37:01 +00001165 asn1p_expr_t *topmost_parent;
1166 asn1p_expr_t *v;
1167 int elements = 0;
1168
Lev Walkin08079b02004-08-22 03:25:24 +00001169 topmost_parent = asn1f_find_terminal_type_ex(arg->asn, arg->mod, expr);
Lev Walkin59004fa2004-08-20 13:37:01 +00001170 if(!topmost_parent) return 0;
1171
1172 if(!(topmost_parent->expr_type & ASN_CONSTR_MASK))
1173 return 0;
1174
1175 TQ_FOR(v, &(topmost_parent->members), next) {
1176 if(v->expr_type != A1TC_EXTENSIBLE)
1177 elements++;
1178 }
1179
1180 return elements;
1181}
1182
1183static int
Lev Walkin59964be2004-08-25 02:03:12 +00001184emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin08079b02004-08-22 03:25:24 +00001185 static int global_memb_unique;
Lev Walkin59004fa2004-08-20 13:37:01 +00001186 int save_target;
1187 arg_t tmp_arg;
1188 char *p;
1189
1190 OUT("{ ");
1191 if(expr->marker) {
1192 asn1p_expr_t *tv;
1193 int opts = 0;
1194 for(tv = expr; tv && tv->marker;
1195 tv = TQ_NEXT(tv, next), opts++) {
1196 if(tv->expr_type == A1TC_EXTENSIBLE)
1197 opts--;
1198 }
1199 OUT("%d, ", opts);
1200 } else {
1201 OUT("0, ");
1202 }
1203 if(expr->Identifier) {
1204 OUT("offsetof(struct %s, ", MKID(arg->expr->Identifier));
1205 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1206 && (!UNNAMED_UNIONS)) OUT("choice.");
1207 OUT("%s),\n", MKID(expr->Identifier));
1208 } else {
1209 assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
1210 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
1211 OUT("0,\n");
1212 }
1213 INDENT(+1);
1214 if(C99_MODE) OUT(".tag = ");
1215 _print_tag(arg, expr , NULL);
1216 OUT(",\n");
1217 if(C99_MODE) OUT(".tag_mode = ");
1218 if(expr->tag.tag_class) {
1219 if(expr->tag.tag_mode == TM_IMPLICIT)
1220 OUT("-1,\t/* IMPLICIT tag at current level */\n");
1221 else
1222 OUT("+1,\t/* EXPLICIT tag at current level */\n");
1223 } else {
1224 OUT("0,\n");
1225 }
1226 if(C99_MODE) OUT(".type = ");
Lev Walkin08079b02004-08-22 03:25:24 +00001227 if((expr->expr_type & ASN_CONSTR_MASK)
1228 && (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF
1229 || arg->expr->expr_type == ASN_CONSTR_SET_OF)) {
1230 OUT("(void *)&asn1_DEF_%s_member,\n",
1231 MKID(arg->expr->Identifier));
Lev Walkin59964be2004-08-25 02:03:12 +00001232 } else if(expr->expr_type & ASN_CONSTR_MASK) {
1233 OUT("(void *)&asn1_DEF_%s,\n",
1234 MKID(expr->Identifier));
Lev Walkin08079b02004-08-22 03:25:24 +00001235 } else {
1236 OUT("(void *)&asn1_DEF_%s,\n",
1237 asn1c_type_name(arg, expr, TNF_SAFE));
1238 }
Lev Walkin59004fa2004-08-20 13:37:01 +00001239 if(C99_MODE) OUT(".memb_constraints = ");
1240 if(expr->constraints) {
Lev Walkin59964be2004-08-25 02:03:12 +00001241 char *id = MKID(expr->Identifier);
Lev Walkin59004fa2004-08-20 13:37:01 +00001242 if(!expr->Identifier)
Lev Walkin59964be2004-08-25 02:03:12 +00001243 id = asn1c_type_name(arg, expr, TNF_SAFE);
1244 OUT("memb_%s_%d_constraint,\n", id,
Lev Walkin08079b02004-08-22 03:25:24 +00001245 ++global_memb_unique);
Lev Walkin59004fa2004-08-20 13:37:01 +00001246 } else {
1247 OUT("0,\t/* Defer to actual type */\n");
1248 }
1249 if(C99_MODE) OUT(".name = ");
1250 OUT("\"%s\"\n", expr->Identifier ? expr->Identifier : "");
1251 OUT("},\n");
1252 INDENT(-1);
1253
1254 if(!expr->constraints)
1255 return 0;
1256
1257 save_target = arg->target->target;
1258 REDIR(OT_CODE);
1259
1260 if(expr->Identifier)
1261 p = MKID(expr->Identifier);
1262 else
1263 p = asn1c_type_name(arg, expr, TNF_SAFE);
1264 OUT("static int\n");
Lev Walkin08079b02004-08-22 03:25:24 +00001265 OUT("memb_%s_%d_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,\n", p, global_memb_unique);
Lev Walkin59004fa2004-08-20 13:37:01 +00001266 INDENT(+1);
1267 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
1268 tmp_arg = *arg;
1269 tmp_arg.expr = expr;
1270 if(asn1c_emit_constraint_checking_code(&tmp_arg) == 1) {
1271 OUT("return td->check_constraints\n");
1272 OUT("\t(td, sptr, app_errlog, app_key);\n");
1273 }
1274 INDENT(-1);
1275 OUT("}\n");
1276 OUT("\n");
1277
1278 REDIR(save_target);
1279
1280 return 0;
1281}
Lev Walkin59964be2004-08-25 02:03:12 +00001282
1283static int
1284emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, int tags_count, int tags_impl_skip, int elements_count, enum etd_cp cp, enum etd_spec spec) {
1285 char *p;
1286
1287 p = MKID(expr->Identifier);
1288 OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
1289 INDENTED(
1290 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
1291
1292 if(expr->expr_type & ASN_CONSTR_MASK) {
1293 p = asn1c_type_name(arg, arg->expr, TNF_SAFE);
1294 }
1295
1296 OUT("%s_constraint,\n", p);
1297 OUT("%s_decode_ber,\n", p);
1298 OUT("%s_encode_der,\n", p);
1299 OUT("%s_print,\n", p);
1300 OUT("%s_free,\n", p);
1301
1302 p = MKID(expr->Identifier);
1303
1304 if(expr->expr_type == ASN_CONSTR_CHOICE) {
1305 OUT("CHOICE_outmost_tag,\n");
1306 } else {
1307 OUT("0,\t/* Use generic outmost tag fetcher */\n");
1308 }
1309
1310 if(tags_count) {
1311 OUT("asn1_DEF_%s_tags,\n", p);
1312 OUT("sizeof(asn1_DEF_%s_tags)\n", p);
1313 OUT("\t/sizeof(asn1_DEF_%s_tags[0]), /* %d */\n",
1314 p, tags_count);
1315 } else {
1316 OUT("0,\t/* No explicit tags (pointer) */\n");
1317 OUT("0,\t/* No explicit tags (count) */\n");
1318 }
1319
1320 OUT("%d,\t/* Tags to skip */\n", tags_impl_skip);
1321 switch(cp) {
1322 case ETD_CP_UNKNOWN:
1323 OUT("-0,\t/* Unknown yet */\n");
1324 break;
1325 case ETD_CP_EITHER:
1326 OUT("-1,\t/* Primitive or constructed */\n");
1327 case ETD_CP_PRIMITIVE:
1328 OUT("0,\t/* Primitive */\n");
1329 break;
1330 case ETD_CP_CONSTRUCTED:
1331 OUT("1,\t/* Whether CONSTRUCTED */\n");
1332 break;
1333 }
1334
1335 if(elements_count) {
1336 OUT("asn1_MBR_%s,\n", p);
1337 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF
1338 || expr->expr_type == ASN_CONSTR_SET_OF) {
1339 OUT("%d,\t/* Single element */\n",
1340 elements_count);
1341 assert(elements_count == 1);
1342 } else {
1343 OUT("%d,\t/* Elements count */\n",
1344 elements_count);
1345 }
1346 } else {
1347 //if(expr->meta_type == AMT_TYPEREF)
1348 if(expr_elements_count(arg, expr))
1349 OUT("0, 0,\t/* Defined elsewhere */\n");
1350 else
1351 OUT("0, 0,\t/* No members */\n");
1352 }
1353
1354 switch(spec) {
1355 case ETD_NO_SPECIFICS:
1356 OUT("0\t/* No specifics */\n");
1357 break;
1358 case ETD_HAS_SPECIFICS:
1359 OUT("&asn1_DEF_%s_specs\t/* Additional specs */\n", p);
1360 }
1361 );
1362 OUT("};\n");
1363 OUT("\n");
1364}