blob: 0bf556c1ef3416eef4b8da5cfa552e1eb0cf6c36 [file] [log] [blame]
vlmfa67ddc2004-06-03 03:38:44 +00001/*
2 * Don't look into this file. First, because it's a mess, and second, because
3 * it's a brain of the compiler, and you don't wanna mess with brains do you? ;)
4 */
5#include "asn1c_internal.h"
6#include "asn1c_C.h"
vlm1d036692004-08-19 13:29:46 +00007#include "asn1c_constraint.h"
vlmb2839012004-08-20 13:37:01 +00008#include "asn1c_out.h"
9#include "asn1c_misc.h"
vlm1d036692004-08-19 13:29:46 +000010#include <asn1fix_export.h> /* Stuff exported by libasn1fix */
vlmfa67ddc2004-06-03 03:38:44 +000011
vlm4e03ce22004-06-06 07:20:17 +000012typedef struct tag2el_s {
13 struct asn1p_type_tag_s el_tag;
14 int el_no;
vlmc8aeab42004-06-14 13:09:45 +000015 int toff_first;
16 int toff_last;
vlm4e03ce22004-06-06 07:20:17 +000017 asn1p_expr_t *from_expr;
18} tag2el_t;
19
20static int _fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no);
21static int _add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no);
22
vlmfa67ddc2004-06-03 03:38:44 +000023static int asn1c_lang_C_type_SEQUENCE_def(arg_t *arg);
24static int asn1c_lang_C_type_SET_def(arg_t *arg);
25static int asn1c_lang_C_type_CHOICE_def(arg_t *arg);
26static int asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of);
27static int _print_tag(arg_t *arg, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag_p);
vlm79b08d52004-07-01 00:52:50 +000028static int check_if_extensible(asn1p_expr_t *expr);
vlm4e554992004-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);
vlm6e73a042004-08-11 07:17:22 +000031static int emit_tags_vector(arg_t *arg, asn1p_expr_t *expr, int *tags_impl_skip, int choice_mode);
vlm4e03ce22004-06-06 07:20:17 +000032static int emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count);
vlmfa67ddc2004-06-03 03:38:44 +000033
vlm4e554992004-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
vlmb2839012004-08-20 13:37:01 +000046#define C99_MODE (!(arg->flags & A1C_NO_C99))
vlmfa67ddc2004-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
vlm33a4ff12004-08-11 05:21:32 +000054#define DEPENDENCIES do { \
vlmdae7f9d2004-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)); \
vlm33a4ff12004-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)
vlmfa67ddc2004-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) {
vlmdae7f9d2004-08-22 03:25:24 +0000141 OUT("struct %s {\n", MKID(expr->Identifier));
vlmfa67ddc2004-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;
vlmdae7f9d2004-08-22 03:25:24 +0000157 OUT("} %s%s%s", expr->marker?"*":"",
158 expr->_anonymous_type ? "" : MKID(expr->Identifier),
159 arg->embed ? "" : "_t");
vlmfa67ddc2004-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;
vlm4e03ce22004-06-06 07:20:17 +0000173 tag2el_t *tag2el = NULL;
174 int tag2el_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000175 int tags_count;
vlmfa67ddc2004-06-03 03:38:44 +0000176 char *p;
177
vlm4e03ce22004-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
vlm33a4ff12004-08-11 05:21:32 +0000186 GEN_INCLUDE("constr_SEQUENCE");
187 if(!arg->embed)
188 GEN_DECLARE(expr); /* asn1_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000189
vlm33a4ff12004-08-11 05:21:32 +0000190 REDIR(OT_STAT_DEFS);
vlmfa67ddc2004-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);
vlmb2839012004-08-20 13:37:01 +0000196 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
vlmfa67ddc2004-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 }
vlmfa67ddc2004-06-03 03:38:44 +0000207 elements++;
vlm4e554992004-08-25 02:03:12 +0000208 emit_member_table(arg, v);
vlmfa67ddc2004-06-03 03:38:44 +0000209 });
210 OUT("};\n");
211
vlm4a3f5822004-06-28 21:13:46 +0000212 /*
213 * Print out asn1_DEF_<type>_tags[] vector.
214 */
vlm6e73a042004-08-11 07:17:22 +0000215 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000216
vlm4e03ce22004-06-06 07:20:17 +0000217 /*
218 * Tags to elements map.
219 */
220 emit_tag2member_map(arg, tag2el, tag2el_count);
221
vlm4a3f5822004-06-28 21:13:46 +0000222 p = MKID(expr->Identifier);
vlmfa67ddc2004-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);
vlm4e03ce22004-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);
vlmfa67ddc2004-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");
vlm4e554992004-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);
vlmfa67ddc2004-06-03 03:38:44 +0000241
vlmfa67ddc2004-06-03 03:38:44 +0000242 REDIR(OT_TYPE_DECLS);
243
244 return 0;
245}
246
247int
vlmfa67ddc2004-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;
vlm6e73a042004-08-11 07:17:22 +0000264 OUT("typedef enum %s_PR {\n", MKID(expr->Identifier));
vlmfa67ddc2004-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 }
vlm6e73a042004-08-11 07:17:22 +0000276 id = MKID(expr->Identifier);
277 OUT("} %s_PR;\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000278
279 REDIR(OT_TYPE_DECLS);
280
281 if(arg->embed) {
vlm6e73a042004-08-11 07:17:22 +0000282 OUT("struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000283 } else {
vlm6e73a042004-08-11 07:17:22 +0000284 OUT("typedef struct %s {\n", id);
vlmfa67ddc2004-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;
vlmdae7f9d2004-08-22 03:25:24 +0000306 OUT("} %s%s%s", expr->marker?"*":"",
307 expr->_anonymous_type ? "" : MKID(expr->Identifier),
308 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000309
310 return asn1c_lang_C_type_SET_def(arg);
311}
312
vlmfa67ddc2004-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,...} */
vlmfa67ddc2004-06-03 03:38:44 +0000320 tag2el_t *tag2el = NULL;
321 int tag2el_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000322 int tags_count;
vlmfa67ddc2004-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;
vlmfa67ddc2004-06-03 03:38:44 +0000331 }
332
vlm33a4ff12004-08-11 05:21:32 +0000333 GEN_INCLUDE("constr_SET");
334 if(!arg->embed)
335 GEN_DECLARE(expr); /* asn1_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000336
337 REDIR(OT_STAT_DEFS);
338
vlmfa67ddc2004-06-03 03:38:44 +0000339 /*
340 * Print out the table according to which the parsing is performed.
341 */
342 p = MKID(expr->Identifier);
vlmb2839012004-08-20 13:37:01 +0000343 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
vlmfa67ddc2004-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;
vlmfa67ddc2004-06-03 03:38:44 +0000350 } else {
351 if(comp_mode < 3) comp_mode++;
352 continue;
353 }
vlmb2839012004-08-20 13:37:01 +0000354 elements++;
vlm4e554992004-08-25 02:03:12 +0000355 emit_member_table(arg, v);
vlmfa67ddc2004-06-03 03:38:44 +0000356 });
357 OUT("};\n");
358
vlm4a3f5822004-06-28 21:13:46 +0000359 /*
360 * Print out asn1_DEF_<type>_tags[] vector.
361 */
vlm6e73a042004-08-11 07:17:22 +0000362 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000363
364 /*
365 * Tags to elements map.
366 */
vlm4e03ce22004-06-06 07:20:17 +0000367 emit_tag2member_map(arg, tag2el, tag2el_count);
vlmfa67ddc2004-06-03 03:38:44 +0000368
369 /*
370 * Emit a map of mandatory elements.
371 */
vlm4a3f5822004-06-28 21:13:46 +0000372 p = MKID(expr->Identifier);
vlmfa67ddc2004-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);
vlmfa67ddc2004-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);
vlm79b08d52004-07-01 00:52:50 +0000407 OUT("%d,\t/* Whether extensible */\n",
408 check_if_extensible(expr));
vlmfa67ddc2004-06-03 03:38:44 +0000409 OUT("(unsigned int *)asn1_DEF_%s_mmap\t/* Mandatory elements map */\n", p);
410 );
411 OUT("};\n");
vlm4e554992004-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);
vlmfa67ddc2004-06-03 03:38:44 +0000418
vlmfa67ddc2004-06-03 03:38:44 +0000419 REDIR(OT_TYPE_DECLS);
420
421 return 0;
422}
423
424int
vlmdae7f9d2004-08-22 03:25:24 +0000425asn1c_lang_C_type_SEx_OF(arg_t *arg) {
vlmfa67ddc2004-06-03 03:38:44 +0000426 asn1p_expr_t *expr = arg->expr;
vlmdae7f9d2004-08-22 03:25:24 +0000427 asn1p_expr_t *memb;
vlmfa67ddc2004-06-03 03:38:44 +0000428
429 DEPENDENCIES;
430
431 if(arg->embed) {
432 OUT("struct %s {\n", MKID(expr->Identifier));
433 } else {
vlmdae7f9d2004-08-22 03:25:24 +0000434 OUT("typedef struct %s {\n", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000435 }
436
vlmdae7f9d2004-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));
vlmfa67ddc2004-06-03 03:38:44 +0000461 }
vlmdae7f9d2004-08-22 03:25:24 +0000462 OUT(") list;\n");
463 INDENT(-1);
vlmfa67ddc2004-06-03 03:38:44 +0000464
465 PCTX_DEF;
vlmdae7f9d2004-08-22 03:25:24 +0000466 OUT("} %s%s%s", expr->marker?"*":"",
467 expr->_anonymous_type ? "" : MKID(expr->Identifier),
468 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000469
470 /*
vlmdae7f9d2004-08-22 03:25:24 +0000471 * SET OF/SEQUENCE OF definition
vlmfa67ddc2004-06-03 03:38:44 +0000472 */
vlmdae7f9d2004-08-22 03:25:24 +0000473 return asn1c_lang_C_type_SEx_OF_def(arg,
474 (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF));
vlmfa67ddc2004-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;
vlm6e73a042004-08-11 07:17:22 +0000482 int tags_count;
vlmfa67ddc2004-06-03 03:38:44 +0000483 char *p;
484
vlm33a4ff12004-08-11 05:21:32 +0000485 /*
486 * Print out the table according to which the parsing is performed.
487 */
vlmfa67ddc2004-06-03 03:38:44 +0000488 if(seq_of) {
vlm33a4ff12004-08-11 05:21:32 +0000489 GEN_INCLUDE("constr_SEQUENCE_OF");
vlmfa67ddc2004-06-03 03:38:44 +0000490 } else {
vlm33a4ff12004-08-11 05:21:32 +0000491 GEN_INCLUDE("constr_SET_OF");
vlmfa67ddc2004-06-03 03:38:44 +0000492 }
vlm33a4ff12004-08-11 05:21:32 +0000493 if(!arg->embed)
494 GEN_DECLARE(expr); /* asn1_DEF_xxx */
vlmfa67ddc2004-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);
vlmb2839012004-08-20 13:37:01 +0000502 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000503
vlmb2839012004-08-20 13:37:01 +0000504 INDENTED(
vlmfa67ddc2004-06-03 03:38:44 +0000505 v = TQ_FIRST(&(expr->members));
vlm4e554992004-08-25 02:03:12 +0000506 emit_member_table(arg, v);
vlmfa67ddc2004-06-03 03:38:44 +0000507 );
508 OUT("};\n");
509
vlm4a3f5822004-06-28 21:13:46 +0000510 /*
511 * Print out asn1_DEF_<type>_tags[] vector.
512 */
vlm6e73a042004-08-11 07:17:22 +0000513 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000514
vlm4a3f5822004-06-28 21:13:46 +0000515 p = MKID(expr->Identifier);
vlmfa67ddc2004-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);
vlmfa67ddc2004-06-03 03:38:44 +0000520 );
521 OUT("};\n");
vlm4e554992004-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);
vlmfa67ddc2004-06-03 03:38:44 +0000528
vlmfa67ddc2004-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;
vlmdae7f9d2004-08-22 03:25:24 +0000538 char *id;
vlmfa67ddc2004-06-03 03:38:44 +0000539
540 DEPENDENCIES;
541
vlm33a4ff12004-08-11 05:21:32 +0000542 REDIR(OT_DEPS);
543
vlmdae7f9d2004-08-22 03:25:24 +0000544 id = MKID(expr->Identifier);
545 OUT("typedef enum %s_PR {\n", id);
vlm33a4ff12004-08-11 05:21:32 +0000546 INDENTED(
vlm33a4ff12004-08-11 05:21:32 +0000547 OUT("%s_PR_NOTHING,\t"
vlmdae7f9d2004-08-22 03:25:24 +0000548 "/* No components present */\n", id);
vlm33a4ff12004-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 }
vlmdae7f9d2004-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);
vlm33a4ff12004-08-11 05:21:32 +0000558 }
559 );
vlmdae7f9d2004-08-22 03:25:24 +0000560 id = MKID(expr->Identifier);
561 OUT("} %s_PR;\n", id);
vlm33a4ff12004-08-11 05:21:32 +0000562
563 REDIR(OT_TYPE_DECLS);
vlmfa67ddc2004-06-03 03:38:44 +0000564
565 if(arg->embed) {
vlmdae7f9d2004-08-22 03:25:24 +0000566 OUT("struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000567 } else {
vlmdae7f9d2004-08-22 03:25:24 +0000568 OUT("typedef struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000569 }
570
571 INDENTED(
vlmdae7f9d2004-08-22 03:25:24 +0000572 OUT("%s_PR present;\n", id);
573 OUT("union {\n", id);
vlmfa67ddc2004-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;
vlmdae7f9d2004-08-22 03:25:24 +0000582 OUT("} %s%s%s", expr->marker?"*":"",
583 expr->_anonymous_type ? "" : MKID(expr->Identifier),
584 arg->embed ? "" : "_t");
vlmfa67ddc2004-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,...} */
vlmfa67ddc2004-06-03 03:38:44 +0000596 tag2el_t *tag2el = NULL;
597 int tag2el_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000598 int tags_count;
vlmfa67ddc2004-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;
vlmfa67ddc2004-06-03 03:38:44 +0000607 }
608
vlm33a4ff12004-08-11 05:21:32 +0000609 GEN_INCLUDE("constr_CHOICE");
610 if(!arg->embed)
611 GEN_DECLARE(expr); /* asn1_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000612
vlm33a4ff12004-08-11 05:21:32 +0000613 REDIR(OT_STAT_DEFS);
vlmfa67ddc2004-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);
vlmb2839012004-08-20 13:37:01 +0000619 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
vlmfa67ddc2004-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;
vlmfa67ddc2004-06-03 03:38:44 +0000626 } else {
627 if(comp_mode < 3) comp_mode++;
628 continue;
629 }
vlmb2839012004-08-20 13:37:01 +0000630 elements++;
vlm4e554992004-08-25 02:03:12 +0000631 emit_member_table(arg, v);
vlmfa67ddc2004-06-03 03:38:44 +0000632 });
633 OUT("};\n");
634
vlm6e73a042004-08-11 07:17:22 +0000635
vlmfa67ddc2004-06-03 03:38:44 +0000636 if(arg->embed) {
637 /*
638 * Our parent structure has already taken this into account.
639 */
vlm6e73a042004-08-11 07:17:22 +0000640 tags_count = 0;
vlmfa67ddc2004-06-03 03:38:44 +0000641 } else {
vlm6e73a042004-08-11 07:17:22 +0000642 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 1);
vlmfa67ddc2004-06-03 03:38:44 +0000643 }
vlmfa67ddc2004-06-03 03:38:44 +0000644
645 /*
646 * Tags to elements map.
647 */
vlm4e03ce22004-06-06 07:20:17 +0000648 emit_tag2member_map(arg, tag2el, tag2el_count);
vlmfa67ddc2004-06-03 03:38:44 +0000649
vlm6e73a042004-08-11 07:17:22 +0000650 p = MKID(expr->Identifier);
vlmfa67ddc2004-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);
vlmfa67ddc2004-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);
vlm79b08d52004-07-01 00:52:50 +0000659 OUT("%d\t/* Whether extensible */\n",
660 check_if_extensible(expr));
vlmfa67ddc2004-06-03 03:38:44 +0000661 );
662 OUT("};\n");
vlm4e554992004-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);
vlmfa67ddc2004-06-03 03:38:44 +0000669
vlmfa67ddc2004-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] == '&') {
vlmfa67ddc2004-06-03 03:38:44 +0000681 asn1p_expr_t *extract;
682 arg_t tmp;
683 int ret;
684
vlmdae7f9d2004-08-22 03:25:24 +0000685 extract = asn1f_class_access_ex(arg->asn, arg->mod,
686 arg->expr, ref);
vlmfa67ddc2004-06-03 03:38:44 +0000687 if(extract == NULL)
688 return -1;
689
vlmdae7f9d2004-08-22 03:25:24 +0000690 extract = asn1p_expr_clone(extract, 0);
vlmfa67ddc2004-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;
vlmdae7f9d2004-08-22 03:25:24 +0000705 tmp.mod = extract->module;
vlmfa67ddc2004-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;
vlm6e73a042004-08-11 07:17:22 +0000723 int tags_count;
vlmfa67ddc2004-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?"*":" ");
vlmdae7f9d2004-08-22 03:25:24 +0000732 OUT("%s", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000733 if(expr->marker) OUT("\t/* %s */",
734 (expr->marker==EM_OPTIONAL)?"OPTIONAL":"DEFAULT");
vlmb2839012004-08-20 13:37:01 +0000735
736 REDIR(OT_TYPE_DECLS);
vlmfa67ddc2004-06-03 03:38:44 +0000737 return 0;
738 }
739
vlmfa67ddc2004-06-03 03:38:44 +0000740
vlm33a4ff12004-08-11 05:21:32 +0000741 GEN_INCLUDE(asn1c_type_name(arg, expr, TNF_INCLUDE));
vlmfa67ddc2004-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?"*":" ");
vlmdae7f9d2004-08-22 03:25:24 +0000747 OUT("%s_t", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000748
749 REDIR(OT_STAT_DEFS);
750
vlm4a3f5822004-06-28 21:13:46 +0000751 /*
752 * Print out asn1_DEF_<type>_tags[] vector.
753 */
vlm6e73a042004-08-11 07:17:22 +0000754 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000755
vlm4e554992004-08-25 02:03:12 +0000756 emit_type_DEF(arg, expr, tags_count, tags_impl_skip, 0,
757 ETD_CP_UNKNOWN, ETD_NO_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000758
vlmb2839012004-08-20 13:37:01 +0000759 REDIR(OT_CODE);
760
vlmfa67ddc2004-06-03 03:38:44 +0000761 /*
762 * Constraint checking.
763 */
vlmfa67ddc2004-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");
vlm1d036692004-08-19 13:29:46 +0000770 if(asn1c_emit_constraint_checking_code(arg) == 1) {
771 if(0) {
vlmfa67ddc2004-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");
vlm1d036692004-08-19 13:29:46 +0000776 } else {
vlmfa67ddc2004-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");
vlm1d036692004-08-19 13:29:46 +0000782 }
vlmfa67ddc2004-06-03 03:38:44 +0000783 }
784 );
785 OUT("}\n");
786 OUT("\n");
787
788 /*
789 * Emit suicidal functions.
790 */
791
vlmfa67ddc2004-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 */
vlmfa67ddc2004-06-03 03:38:44 +0000797 OUT("/*\n");
vlmb2839012004-08-20 13:37:01 +0000798 OUT(" * This type is implemented using %s,\n",
799 asn1c_type_name(arg, expr, TNF_SAFE));
vlmfa67ddc2004-06-03 03:38:44 +0000800 OUT(" * so adjust the DEF appropriately.\n");
801 OUT(" */\n");
802 OUT("static void\n");
vlmb2839012004-08-20 13:37:01 +0000803 p = MKID(expr->Identifier);
804 OUT("%s_inherit_TYPE_descriptor(asn1_TYPE_descriptor_t *td) {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000805 INDENT(+1);
vlmb2839012004-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 }
vlmfa67ddc2004-06-03 03:38:44 +0000817 INDENT(-1);
818 OUT("}\n");
819 OUT("\n");
vlmfa67ddc2004-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");
vlmb2839012004-08-20 13:37:01 +0000826 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlmfa67ddc2004-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");
vlmb2839012004-08-20 13:37:01 +0000839 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlmfa67ddc2004-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");
vlmb2839012004-08-20 13:37:01 +0000850 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlmfa67ddc2004-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");
vlmb2839012004-08-20 13:37:01 +0000861 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlmfa67ddc2004-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
vlm33a4ff12004-08-11 05:21:32 +0000877 REDIR(OT_TYPE_DECLS);
878
vlmfa67ddc2004-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
vlm79b08d52004-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
vlmfa67ddc2004-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)) {
vlme2070ea2004-09-04 04:42:29 +0000909 OUT("-1 /* Ambiguous tag (CHOICE|ANY?) */");
vlmfa67ddc2004-06-03 03:38:44 +0000910 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
vlm4e03ce22004-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
vlmfa67ddc2004-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
vlm4e03ce22004-06-06 07:20:17 +0000990 /*
vlmc8aeab42004-06-14 13:09:45 +0000991 * Sort the map according to canonical order of their tags
992 * and element numbers.
vlm4e03ce22004-06-06 07:20:17 +0000993 */
994 qsort(*tag2el, *count, sizeof(**tag2el), _tag2el_cmp);
995
vlmc8aeab42004-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
vlmfa67ddc2004-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) {
vlme2070ea2004-09-04 04:42:29 +00001031 tag2el_t *te;
1032 int new_count = (*count) + 1;
vlmfa67ddc2004-06-03 03:38:44 +00001033 void *p;
vlme2070ea2004-09-04 04:42:29 +00001034
1035 p = realloc(*tag2el, new_count * sizeof(tag2el_t));
vlmfa67ddc2004-06-03 03:38:44 +00001036 if(p) *tag2el = p;
1037 else return -1;
1038
1039 DEBUG("Found tag for %s: %ld",
1040 arg->expr->Identifier,
1041 (long)tag.tag_value);
1042
vlme2070ea2004-09-04 04:42:29 +00001043 te = &((*tag2el)[*count]);
1044 te->el_tag = tag;
1045 te->el_no = el_no;
1046 te->from_expr = arg->expr;
1047 *count = new_count;
vlmfa67ddc2004-06-03 03:38:44 +00001048 return 0;
1049 }
1050
1051 DEBUG("Searching tag in complex expression %s:%x at line %d",
1052 arg->expr->Identifier,
1053 arg->expr->expr_type,
1054 arg->expr->_lineno);
1055
1056 /*
1057 * Iterate over members of CHOICE type.
1058 */
1059 if(arg->expr->expr_type == ASN_CONSTR_CHOICE) {
1060 return _fill_tag2el_map(arg, tag2el, count, el_no);
1061 }
1062
1063 if(arg->expr->expr_type == A1TC_REFERENCE) {
1064 arg_t tmp = *arg;
1065 asn1p_expr_t *expr;
vlmdae7f9d2004-08-22 03:25:24 +00001066 expr = asn1f_lookup_symbol_ex(tmp.asn, tmp.mod, tmp.expr,
vlmfa67ddc2004-06-03 03:38:44 +00001067 arg->expr->reference);
1068 if(expr) {
vlmdae7f9d2004-08-22 03:25:24 +00001069 tmp.mod = expr->module;
vlmfa67ddc2004-06-03 03:38:44 +00001070 tmp.expr = expr;
1071 return _add_tag2el_member(&tmp, tag2el, count, el_no);
1072 } else {
1073 FATAL("Cannot dereference %s at line %d",
1074 arg->expr->Identifier,
1075 arg->expr->_lineno);
1076 return -1;
1077 }
1078 }
1079
vlme2070ea2004-09-04 04:42:29 +00001080 if(arg->expr->expr_type == ASN_TYPE_ANY
1081 && arg->expr->tag.tag_class == TC_NOCLASS) {
1082 if(arg->expr->marker) {
1083 FATAL("Untagged optional ANY type for %s at line %d",
1084 arg->expr->Identifier,
1085 arg->expr->_lineno);
1086 return -1;
1087 }
1088 /* Allow to proceed without adding a tag */
1089 return 0;
1090 }
1091
vlmfa67ddc2004-06-03 03:38:44 +00001092 DEBUG("No tag for %s at line %d",
1093 arg->expr->Identifier,
1094 arg->expr->_lineno);
1095
1096 return -1;
1097}
1098
1099static int
vlm4e03ce22004-06-06 07:20:17 +00001100emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count) {
1101 asn1p_expr_t *expr = arg->expr;
1102
1103 OUT("static asn1_TYPE_tag2member_t asn1_DEF_%s_tag2el[] = {\n",
1104 MKID(expr->Identifier));
1105 if(tag2el_count) {
1106 int i;
1107 for(i = 0; i < tag2el_count; i++) {
1108 OUT(" { ");
1109 _print_tag(arg, expr, &tag2el[i].el_tag);
1110 OUT(", ");
vlmc8aeab42004-06-14 13:09:45 +00001111 OUT("%d, ", tag2el[i].el_no);
1112 OUT("%d, ", tag2el[i].toff_first);
1113 OUT("%d ", tag2el[i].toff_last);
vlm4e03ce22004-06-06 07:20:17 +00001114 OUT("}, /* %s at %d */\n",
1115 tag2el[i].from_expr->Identifier,
1116 tag2el[i].from_expr->_lineno
1117 );
1118 }
1119 }
1120 OUT("};\n");
1121
1122 return 0;;
1123}
1124
1125static int
vlm6e73a042004-08-11 07:17:22 +00001126emit_tags_vector(arg_t *arg, asn1p_expr_t *expr, int *tags_impl_skip, int choice_mode) {
1127 int tags_count = 0;
1128 int save_target = arg->target->target;
vlm4a3f5822004-06-28 21:13:46 +00001129 char *p;
1130
vlm6e73a042004-08-11 07:17:22 +00001131 if(save_target != OT_IGNORE) {
1132 int save_impl_skip = *tags_impl_skip;
1133 REDIR(OT_IGNORE);
1134 tags_count = emit_tags_vector(arg, expr,
1135 tags_impl_skip, choice_mode);
1136 REDIR(save_target);
1137 if(tags_count) {
1138 *tags_impl_skip = save_impl_skip;
1139 tags_count = 0;
1140 } else {
1141 return 0;
1142 }
1143 }
1144
1145
vlm4a3f5822004-06-28 21:13:46 +00001146 p = MKID(expr->Identifier);
1147 OUT("static ber_tlv_tag_t asn1_DEF_%s_tags[] = {\n", p);
1148 INDENTED(
1149 if(expr->tag.tag_class) {
vlm6e73a042004-08-11 07:17:22 +00001150 tags_count++;
vlm4a3f5822004-06-28 21:13:46 +00001151 _print_tag(arg, expr, &expr->tag);
1152 if(expr->tag.tag_mode != TM_EXPLICIT)
1153 (*tags_impl_skip)++;
1154 } else {
vlm6e73a042004-08-11 07:17:22 +00001155 if(!choice_mode)
1156 (*tags_impl_skip)++;
vlm4a3f5822004-06-28 21:13:46 +00001157 }
vlm6e73a042004-08-11 07:17:22 +00001158 if(!choice_mode) {
1159 if(!expr->tag.tag_class
1160 || (expr->meta_type == AMT_TYPE
1161 && expr->tag.tag_mode == TM_EXPLICIT)) {
1162 struct asn1p_type_tag_s tag;
1163 if(expr->tag.tag_class)
1164 OUT(",\n");
1165 tag.tag_class = TC_UNIVERSAL;
1166 tag.tag_mode = TM_IMPLICIT;
1167 tag.tag_value = expr_type2uclass_value[expr->expr_type];
1168 _print_tag(arg, expr, &tag);
1169 tags_count++;
1170 }
vlm4a3f5822004-06-28 21:13:46 +00001171 }
1172 OUT("\n");
1173 );
1174 OUT("};\n");
1175
vlm6e73a042004-08-11 07:17:22 +00001176 return tags_count;
vlm4a3f5822004-06-28 21:13:46 +00001177}
vlmb2839012004-08-20 13:37:01 +00001178
1179static int
vlm4e554992004-08-25 02:03:12 +00001180expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
vlmb2839012004-08-20 13:37:01 +00001181 asn1p_expr_t *topmost_parent;
1182 asn1p_expr_t *v;
1183 int elements = 0;
1184
vlmdae7f9d2004-08-22 03:25:24 +00001185 topmost_parent = asn1f_find_terminal_type_ex(arg->asn, arg->mod, expr);
vlmb2839012004-08-20 13:37:01 +00001186 if(!topmost_parent) return 0;
1187
1188 if(!(topmost_parent->expr_type & ASN_CONSTR_MASK))
1189 return 0;
1190
1191 TQ_FOR(v, &(topmost_parent->members), next) {
1192 if(v->expr_type != A1TC_EXTENSIBLE)
1193 elements++;
1194 }
1195
1196 return elements;
1197}
1198
1199static int
vlm4e554992004-08-25 02:03:12 +00001200emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
vlmdae7f9d2004-08-22 03:25:24 +00001201 static int global_memb_unique;
vlmb2839012004-08-20 13:37:01 +00001202 int save_target;
1203 arg_t tmp_arg;
1204 char *p;
1205
1206 OUT("{ ");
1207 if(expr->marker) {
1208 asn1p_expr_t *tv;
1209 int opts = 0;
1210 for(tv = expr; tv && tv->marker;
1211 tv = TQ_NEXT(tv, next), opts++) {
1212 if(tv->expr_type == A1TC_EXTENSIBLE)
1213 opts--;
1214 }
1215 OUT("%d, ", opts);
1216 } else {
1217 OUT("0, ");
1218 }
1219 if(expr->Identifier) {
1220 OUT("offsetof(struct %s, ", MKID(arg->expr->Identifier));
1221 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1222 && (!UNNAMED_UNIONS)) OUT("choice.");
1223 OUT("%s),\n", MKID(expr->Identifier));
1224 } else {
1225 assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
1226 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
1227 OUT("0,\n");
1228 }
1229 INDENT(+1);
1230 if(C99_MODE) OUT(".tag = ");
1231 _print_tag(arg, expr , NULL);
1232 OUT(",\n");
1233 if(C99_MODE) OUT(".tag_mode = ");
1234 if(expr->tag.tag_class) {
1235 if(expr->tag.tag_mode == TM_IMPLICIT)
1236 OUT("-1,\t/* IMPLICIT tag at current level */\n");
1237 else
1238 OUT("+1,\t/* EXPLICIT tag at current level */\n");
1239 } else {
1240 OUT("0,\n");
1241 }
1242 if(C99_MODE) OUT(".type = ");
vlmdae7f9d2004-08-22 03:25:24 +00001243 if((expr->expr_type & ASN_CONSTR_MASK)
1244 && (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF
1245 || arg->expr->expr_type == ASN_CONSTR_SET_OF)) {
1246 OUT("(void *)&asn1_DEF_%s_member,\n",
1247 MKID(arg->expr->Identifier));
vlm4e554992004-08-25 02:03:12 +00001248 } else if(expr->expr_type & ASN_CONSTR_MASK) {
1249 OUT("(void *)&asn1_DEF_%s,\n",
1250 MKID(expr->Identifier));
vlmdae7f9d2004-08-22 03:25:24 +00001251 } else {
1252 OUT("(void *)&asn1_DEF_%s,\n",
1253 asn1c_type_name(arg, expr, TNF_SAFE));
1254 }
vlmb2839012004-08-20 13:37:01 +00001255 if(C99_MODE) OUT(".memb_constraints = ");
1256 if(expr->constraints) {
vlm4e554992004-08-25 02:03:12 +00001257 char *id = MKID(expr->Identifier);
vlmb2839012004-08-20 13:37:01 +00001258 if(!expr->Identifier)
vlm4e554992004-08-25 02:03:12 +00001259 id = asn1c_type_name(arg, expr, TNF_SAFE);
1260 OUT("memb_%s_%d_constraint,\n", id,
vlmdae7f9d2004-08-22 03:25:24 +00001261 ++global_memb_unique);
vlmb2839012004-08-20 13:37:01 +00001262 } else {
1263 OUT("0,\t/* Defer to actual type */\n");
1264 }
1265 if(C99_MODE) OUT(".name = ");
1266 OUT("\"%s\"\n", expr->Identifier ? expr->Identifier : "");
1267 OUT("},\n");
1268 INDENT(-1);
1269
1270 if(!expr->constraints)
1271 return 0;
1272
1273 save_target = arg->target->target;
1274 REDIR(OT_CODE);
1275
1276 if(expr->Identifier)
1277 p = MKID(expr->Identifier);
1278 else
1279 p = asn1c_type_name(arg, expr, TNF_SAFE);
1280 OUT("static int\n");
vlmdae7f9d2004-08-22 03:25:24 +00001281 OUT("memb_%s_%d_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,\n", p, global_memb_unique);
vlmb2839012004-08-20 13:37:01 +00001282 INDENT(+1);
1283 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
1284 tmp_arg = *arg;
1285 tmp_arg.expr = expr;
1286 if(asn1c_emit_constraint_checking_code(&tmp_arg) == 1) {
1287 OUT("return td->check_constraints\n");
1288 OUT("\t(td, sptr, app_errlog, app_key);\n");
1289 }
1290 INDENT(-1);
1291 OUT("}\n");
1292 OUT("\n");
1293
1294 REDIR(save_target);
1295
1296 return 0;
1297}
vlm4e554992004-08-25 02:03:12 +00001298
1299static int
1300emit_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) {
1301 char *p;
1302
1303 p = MKID(expr->Identifier);
1304 OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
1305 INDENTED(
1306 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
1307
1308 if(expr->expr_type & ASN_CONSTR_MASK) {
1309 p = asn1c_type_name(arg, arg->expr, TNF_SAFE);
1310 }
1311
1312 OUT("%s_constraint,\n", p);
1313 OUT("%s_decode_ber,\n", p);
1314 OUT("%s_encode_der,\n", p);
1315 OUT("%s_print,\n", p);
1316 OUT("%s_free,\n", p);
1317
1318 p = MKID(expr->Identifier);
1319
1320 if(expr->expr_type == ASN_CONSTR_CHOICE) {
1321 OUT("CHOICE_outmost_tag,\n");
1322 } else {
1323 OUT("0,\t/* Use generic outmost tag fetcher */\n");
1324 }
1325
1326 if(tags_count) {
1327 OUT("asn1_DEF_%s_tags,\n", p);
1328 OUT("sizeof(asn1_DEF_%s_tags)\n", p);
1329 OUT("\t/sizeof(asn1_DEF_%s_tags[0]), /* %d */\n",
1330 p, tags_count);
1331 } else {
1332 OUT("0,\t/* No explicit tags (pointer) */\n");
1333 OUT("0,\t/* No explicit tags (count) */\n");
1334 }
1335
1336 OUT("%d,\t/* Tags to skip */\n", tags_impl_skip);
1337 switch(cp) {
1338 case ETD_CP_UNKNOWN:
1339 OUT("-0,\t/* Unknown yet */\n");
1340 break;
1341 case ETD_CP_EITHER:
1342 OUT("-1,\t/* Primitive or constructed */\n");
1343 case ETD_CP_PRIMITIVE:
1344 OUT("0,\t/* Primitive */\n");
1345 break;
1346 case ETD_CP_CONSTRUCTED:
1347 OUT("1,\t/* Whether CONSTRUCTED */\n");
1348 break;
1349 }
1350
1351 if(elements_count) {
1352 OUT("asn1_MBR_%s,\n", p);
1353 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF
1354 || expr->expr_type == ASN_CONSTR_SET_OF) {
1355 OUT("%d,\t/* Single element */\n",
1356 elements_count);
1357 assert(elements_count == 1);
1358 } else {
1359 OUT("%d,\t/* Elements count */\n",
1360 elements_count);
1361 }
1362 } else {
1363 //if(expr->meta_type == AMT_TYPEREF)
1364 if(expr_elements_count(arg, expr))
1365 OUT("0, 0,\t/* Defined elsewhere */\n");
1366 else
1367 OUT("0, 0,\t/* No members */\n");
1368 }
1369
1370 switch(spec) {
1371 case ETD_NO_SPECIFICS:
1372 OUT("0\t/* No specifics */\n");
1373 break;
1374 case ETD_HAS_SPECIFICS:
1375 OUT("&asn1_DEF_%s_specs\t/* Additional specs */\n", p);
1376 }
1377 );
1378 OUT("};\n");
1379 OUT("\n");
vlme2bb4432004-08-26 06:20:34 +00001380
1381 return 0;
vlm4e554992004-08-25 02:03:12 +00001382}