blob: 10142ca7dc0935ff806f8469c0a9bc1235132c6e [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 {
vlm2de0e792004-09-05 10:42:33 +0000908 if(asn1f_fetch_tag(arg->asn, arg->mod, expr, &tag, 0)) {
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
vlm2de0e792004-09-05 10:42:33 +00001029 ret = asn1f_fetch_tag(arg->asn, arg->mod, arg->expr, &tag, 1);
vlmfa67ddc2004-06-03 03:38:44 +00001030 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
vlm2de0e792004-09-05 10:42:33 +00001035 if(tag.tag_value == -1) {
1036 /*
1037 * This is an untagged ANY type,
1038 * proceed without adding a tag
1039 */
1040 return 0;
1041 }
1042
vlme2070ea2004-09-04 04:42:29 +00001043 p = realloc(*tag2el, new_count * sizeof(tag2el_t));
vlmfa67ddc2004-06-03 03:38:44 +00001044 if(p) *tag2el = p;
1045 else return -1;
1046
1047 DEBUG("Found tag for %s: %ld",
1048 arg->expr->Identifier,
1049 (long)tag.tag_value);
1050
vlme2070ea2004-09-04 04:42:29 +00001051 te = &((*tag2el)[*count]);
1052 te->el_tag = tag;
1053 te->el_no = el_no;
1054 te->from_expr = arg->expr;
1055 *count = new_count;
vlmfa67ddc2004-06-03 03:38:44 +00001056 return 0;
1057 }
1058
1059 DEBUG("Searching tag in complex expression %s:%x at line %d",
1060 arg->expr->Identifier,
1061 arg->expr->expr_type,
1062 arg->expr->_lineno);
1063
1064 /*
1065 * Iterate over members of CHOICE type.
1066 */
1067 if(arg->expr->expr_type == ASN_CONSTR_CHOICE) {
1068 return _fill_tag2el_map(arg, tag2el, count, el_no);
1069 }
1070
1071 if(arg->expr->expr_type == A1TC_REFERENCE) {
1072 arg_t tmp = *arg;
1073 asn1p_expr_t *expr;
vlmdae7f9d2004-08-22 03:25:24 +00001074 expr = asn1f_lookup_symbol_ex(tmp.asn, tmp.mod, tmp.expr,
vlmfa67ddc2004-06-03 03:38:44 +00001075 arg->expr->reference);
1076 if(expr) {
vlmdae7f9d2004-08-22 03:25:24 +00001077 tmp.mod = expr->module;
vlmfa67ddc2004-06-03 03:38:44 +00001078 tmp.expr = expr;
1079 return _add_tag2el_member(&tmp, tag2el, count, el_no);
1080 } else {
1081 FATAL("Cannot dereference %s at line %d",
1082 arg->expr->Identifier,
1083 arg->expr->_lineno);
1084 return -1;
1085 }
1086 }
1087
1088 DEBUG("No tag for %s at line %d",
1089 arg->expr->Identifier,
1090 arg->expr->_lineno);
1091
1092 return -1;
1093}
1094
1095static int
vlm4e03ce22004-06-06 07:20:17 +00001096emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count) {
1097 asn1p_expr_t *expr = arg->expr;
1098
1099 OUT("static asn1_TYPE_tag2member_t asn1_DEF_%s_tag2el[] = {\n",
1100 MKID(expr->Identifier));
1101 if(tag2el_count) {
1102 int i;
1103 for(i = 0; i < tag2el_count; i++) {
1104 OUT(" { ");
1105 _print_tag(arg, expr, &tag2el[i].el_tag);
1106 OUT(", ");
vlmc8aeab42004-06-14 13:09:45 +00001107 OUT("%d, ", tag2el[i].el_no);
1108 OUT("%d, ", tag2el[i].toff_first);
1109 OUT("%d ", tag2el[i].toff_last);
vlm4e03ce22004-06-06 07:20:17 +00001110 OUT("}, /* %s at %d */\n",
1111 tag2el[i].from_expr->Identifier,
1112 tag2el[i].from_expr->_lineno
1113 );
1114 }
1115 }
1116 OUT("};\n");
1117
1118 return 0;;
1119}
1120
1121static int
vlm6e73a042004-08-11 07:17:22 +00001122emit_tags_vector(arg_t *arg, asn1p_expr_t *expr, int *tags_impl_skip, int choice_mode) {
1123 int tags_count = 0;
1124 int save_target = arg->target->target;
vlm4a3f5822004-06-28 21:13:46 +00001125 char *p;
1126
vlm6e73a042004-08-11 07:17:22 +00001127 if(save_target != OT_IGNORE) {
1128 int save_impl_skip = *tags_impl_skip;
1129 REDIR(OT_IGNORE);
1130 tags_count = emit_tags_vector(arg, expr,
1131 tags_impl_skip, choice_mode);
1132 REDIR(save_target);
1133 if(tags_count) {
1134 *tags_impl_skip = save_impl_skip;
1135 tags_count = 0;
1136 } else {
1137 return 0;
1138 }
1139 }
1140
1141
vlm4a3f5822004-06-28 21:13:46 +00001142 p = MKID(expr->Identifier);
1143 OUT("static ber_tlv_tag_t asn1_DEF_%s_tags[] = {\n", p);
1144 INDENTED(
1145 if(expr->tag.tag_class) {
vlm6e73a042004-08-11 07:17:22 +00001146 tags_count++;
vlm4a3f5822004-06-28 21:13:46 +00001147 _print_tag(arg, expr, &expr->tag);
1148 if(expr->tag.tag_mode != TM_EXPLICIT)
1149 (*tags_impl_skip)++;
1150 } else {
vlm6e73a042004-08-11 07:17:22 +00001151 if(!choice_mode)
1152 (*tags_impl_skip)++;
vlm4a3f5822004-06-28 21:13:46 +00001153 }
vlm6e73a042004-08-11 07:17:22 +00001154 if(!choice_mode) {
1155 if(!expr->tag.tag_class
1156 || (expr->meta_type == AMT_TYPE
1157 && expr->tag.tag_mode == TM_EXPLICIT)) {
1158 struct asn1p_type_tag_s tag;
1159 if(expr->tag.tag_class)
1160 OUT(",\n");
1161 tag.tag_class = TC_UNIVERSAL;
1162 tag.tag_mode = TM_IMPLICIT;
1163 tag.tag_value = expr_type2uclass_value[expr->expr_type];
1164 _print_tag(arg, expr, &tag);
1165 tags_count++;
1166 }
vlm4a3f5822004-06-28 21:13:46 +00001167 }
1168 OUT("\n");
1169 );
1170 OUT("};\n");
1171
vlm6e73a042004-08-11 07:17:22 +00001172 return tags_count;
vlm4a3f5822004-06-28 21:13:46 +00001173}
vlmb2839012004-08-20 13:37:01 +00001174
1175static int
vlm4e554992004-08-25 02:03:12 +00001176expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
vlmb2839012004-08-20 13:37:01 +00001177 asn1p_expr_t *topmost_parent;
1178 asn1p_expr_t *v;
1179 int elements = 0;
1180
vlmdae7f9d2004-08-22 03:25:24 +00001181 topmost_parent = asn1f_find_terminal_type_ex(arg->asn, arg->mod, expr);
vlmb2839012004-08-20 13:37:01 +00001182 if(!topmost_parent) return 0;
1183
1184 if(!(topmost_parent->expr_type & ASN_CONSTR_MASK))
1185 return 0;
1186
1187 TQ_FOR(v, &(topmost_parent->members), next) {
1188 if(v->expr_type != A1TC_EXTENSIBLE)
1189 elements++;
1190 }
1191
1192 return elements;
1193}
1194
1195static int
vlm4e554992004-08-25 02:03:12 +00001196emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
vlmdae7f9d2004-08-22 03:25:24 +00001197 static int global_memb_unique;
vlmb2839012004-08-20 13:37:01 +00001198 int save_target;
1199 arg_t tmp_arg;
1200 char *p;
1201
1202 OUT("{ ");
1203 if(expr->marker) {
1204 asn1p_expr_t *tv;
1205 int opts = 0;
1206 for(tv = expr; tv && tv->marker;
1207 tv = TQ_NEXT(tv, next), opts++) {
1208 if(tv->expr_type == A1TC_EXTENSIBLE)
1209 opts--;
1210 }
1211 OUT("%d, ", opts);
1212 } else {
1213 OUT("0, ");
1214 }
1215 if(expr->Identifier) {
1216 OUT("offsetof(struct %s, ", MKID(arg->expr->Identifier));
1217 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1218 && (!UNNAMED_UNIONS)) OUT("choice.");
1219 OUT("%s),\n", MKID(expr->Identifier));
1220 } else {
1221 assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
1222 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
1223 OUT("0,\n");
1224 }
1225 INDENT(+1);
1226 if(C99_MODE) OUT(".tag = ");
1227 _print_tag(arg, expr , NULL);
1228 OUT(",\n");
1229 if(C99_MODE) OUT(".tag_mode = ");
1230 if(expr->tag.tag_class) {
1231 if(expr->tag.tag_mode == TM_IMPLICIT)
1232 OUT("-1,\t/* IMPLICIT tag at current level */\n");
1233 else
1234 OUT("+1,\t/* EXPLICIT tag at current level */\n");
1235 } else {
1236 OUT("0,\n");
1237 }
1238 if(C99_MODE) OUT(".type = ");
vlmdae7f9d2004-08-22 03:25:24 +00001239 if((expr->expr_type & ASN_CONSTR_MASK)
1240 && (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF
1241 || arg->expr->expr_type == ASN_CONSTR_SET_OF)) {
1242 OUT("(void *)&asn1_DEF_%s_member,\n",
1243 MKID(arg->expr->Identifier));
vlm4e554992004-08-25 02:03:12 +00001244 } else if(expr->expr_type & ASN_CONSTR_MASK) {
1245 OUT("(void *)&asn1_DEF_%s,\n",
1246 MKID(expr->Identifier));
vlmdae7f9d2004-08-22 03:25:24 +00001247 } else {
1248 OUT("(void *)&asn1_DEF_%s,\n",
1249 asn1c_type_name(arg, expr, TNF_SAFE));
1250 }
vlmb2839012004-08-20 13:37:01 +00001251 if(C99_MODE) OUT(".memb_constraints = ");
1252 if(expr->constraints) {
vlm4e554992004-08-25 02:03:12 +00001253 char *id = MKID(expr->Identifier);
vlmb2839012004-08-20 13:37:01 +00001254 if(!expr->Identifier)
vlm4e554992004-08-25 02:03:12 +00001255 id = asn1c_type_name(arg, expr, TNF_SAFE);
1256 OUT("memb_%s_%d_constraint,\n", id,
vlmdae7f9d2004-08-22 03:25:24 +00001257 ++global_memb_unique);
vlmb2839012004-08-20 13:37:01 +00001258 } else {
1259 OUT("0,\t/* Defer to actual type */\n");
1260 }
1261 if(C99_MODE) OUT(".name = ");
1262 OUT("\"%s\"\n", expr->Identifier ? expr->Identifier : "");
1263 OUT("},\n");
1264 INDENT(-1);
1265
1266 if(!expr->constraints)
1267 return 0;
1268
1269 save_target = arg->target->target;
1270 REDIR(OT_CODE);
1271
1272 if(expr->Identifier)
1273 p = MKID(expr->Identifier);
1274 else
1275 p = asn1c_type_name(arg, expr, TNF_SAFE);
1276 OUT("static int\n");
vlmdae7f9d2004-08-22 03:25:24 +00001277 OUT("memb_%s_%d_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,\n", p, global_memb_unique);
vlmb2839012004-08-20 13:37:01 +00001278 INDENT(+1);
1279 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
1280 tmp_arg = *arg;
1281 tmp_arg.expr = expr;
1282 if(asn1c_emit_constraint_checking_code(&tmp_arg) == 1) {
1283 OUT("return td->check_constraints\n");
1284 OUT("\t(td, sptr, app_errlog, app_key);\n");
1285 }
1286 INDENT(-1);
1287 OUT("}\n");
1288 OUT("\n");
1289
1290 REDIR(save_target);
1291
1292 return 0;
1293}
vlm4e554992004-08-25 02:03:12 +00001294
1295static int
1296emit_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) {
1297 char *p;
1298
1299 p = MKID(expr->Identifier);
1300 OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
1301 INDENTED(
1302 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
1303
1304 if(expr->expr_type & ASN_CONSTR_MASK) {
1305 p = asn1c_type_name(arg, arg->expr, TNF_SAFE);
1306 }
1307
1308 OUT("%s_constraint,\n", p);
1309 OUT("%s_decode_ber,\n", p);
1310 OUT("%s_encode_der,\n", p);
1311 OUT("%s_print,\n", p);
1312 OUT("%s_free,\n", p);
1313
1314 p = MKID(expr->Identifier);
1315
1316 if(expr->expr_type == ASN_CONSTR_CHOICE) {
1317 OUT("CHOICE_outmost_tag,\n");
1318 } else {
1319 OUT("0,\t/* Use generic outmost tag fetcher */\n");
1320 }
1321
1322 if(tags_count) {
1323 OUT("asn1_DEF_%s_tags,\n", p);
1324 OUT("sizeof(asn1_DEF_%s_tags)\n", p);
1325 OUT("\t/sizeof(asn1_DEF_%s_tags[0]), /* %d */\n",
1326 p, tags_count);
1327 } else {
1328 OUT("0,\t/* No explicit tags (pointer) */\n");
1329 OUT("0,\t/* No explicit tags (count) */\n");
1330 }
1331
1332 OUT("%d,\t/* Tags to skip */\n", tags_impl_skip);
1333 switch(cp) {
1334 case ETD_CP_UNKNOWN:
1335 OUT("-0,\t/* Unknown yet */\n");
1336 break;
1337 case ETD_CP_EITHER:
1338 OUT("-1,\t/* Primitive or constructed */\n");
1339 case ETD_CP_PRIMITIVE:
1340 OUT("0,\t/* Primitive */\n");
1341 break;
1342 case ETD_CP_CONSTRUCTED:
1343 OUT("1,\t/* Whether CONSTRUCTED */\n");
1344 break;
1345 }
1346
1347 if(elements_count) {
1348 OUT("asn1_MBR_%s,\n", p);
1349 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF
1350 || expr->expr_type == ASN_CONSTR_SET_OF) {
1351 OUT("%d,\t/* Single element */\n",
1352 elements_count);
1353 assert(elements_count == 1);
1354 } else {
1355 OUT("%d,\t/* Elements count */\n",
1356 elements_count);
1357 }
1358 } else {
1359 //if(expr->meta_type == AMT_TYPEREF)
1360 if(expr_elements_count(arg, expr))
1361 OUT("0, 0,\t/* Defined elsewhere */\n");
1362 else
1363 OUT("0, 0,\t/* No members */\n");
1364 }
1365
1366 switch(spec) {
1367 case ETD_NO_SPECIFICS:
1368 OUT("0\t/* No specifics */\n");
1369 break;
1370 case ETD_HAS_SPECIFICS:
1371 OUT("&asn1_DEF_%s_specs\t/* Additional specs */\n", p);
1372 }
1373 );
1374 OUT("};\n");
1375 OUT("\n");
vlme2bb4432004-08-26 06:20:34 +00001376
1377 return 0;
vlm4e554992004-08-25 02:03:12 +00001378}