blob: 81ae97160238809c50f7dfc39b8352ed6b70d678 [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)
vlm12c8f692004-09-06 08:07:29 +000048#define HIDE_INNER_DEFS (arg->embed && !(arg->flags & A1C_ALL_DEFS_GLOBAL))
vlmfa67ddc2004-06-03 03:38:44 +000049
50#define PCTX_DEF INDENTED( \
51 OUT("\n"); \
52 OUT("/* Context for parsing across buffer boundaries */\n"); \
53 OUT("ber_dec_ctx_t _ber_dec_ctx;\n"));
54
vlm33a4ff12004-08-11 05:21:32 +000055#define DEPENDENCIES do { \
vlmdae7f9d2004-08-22 03:25:24 +000056 asn1p_expr_t *__m; \
57 TQ_FOR(__m, &(expr->members), next) { \
58 if((!(__m->expr_type & ASN_CONSTR_MASK) \
59 && __m->expr_type > ASN_CONSTR_MASK) \
60 || __m->meta_type == AMT_TYPEREF) { \
61 GEN_INCLUDE(asn1c_type_name(arg, \
62 __m, TNF_INCLUDE)); \
vlm33a4ff12004-08-11 05:21:32 +000063 } \
64 } \
65 if(expr->expr_type == ASN_CONSTR_SET_OF) \
66 GEN_INCLUDE("asn_SET_OF"); \
67 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF) \
68 GEN_INCLUDE("asn_SEQUENCE_OF"); \
69} while(0)
vlmfa67ddc2004-06-03 03:38:44 +000070
71#define MKID(id) asn1c_make_identifier(0, (id), 0)
72
73int
74asn1c_lang_C_type_ENUMERATED(arg_t *arg) {
75 asn1p_expr_t *expr = arg->expr;
76 asn1p_expr_t *v;
77
78 REDIR(OT_DEPS);
79
80 OUT("typedef enum %s {\n", MKID(expr->Identifier));
81 TQ_FOR(v, &(expr->members), next) {
82 switch(v->expr_type) {
83 case A1TC_UNIVERVAL:
84 OUT("\t%s\t= %lld,\n",
85 asn1c_make_identifier(0,
86 expr->Identifier,
87 v->Identifier, 0),
88 v->value->value.v_integer);
89 break;
90 case A1TC_EXTENSIBLE:
91 OUT("\t/*\n");
92 OUT("\t * Enumeration is extensible\n");
93 OUT("\t */\n");
94 break;
95 default:
96 return -1;
97 }
98 }
99 OUT("} %s_e;\n", MKID(expr->Identifier));
100
101 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
102}
103
104
105int
106asn1c_lang_C_type_INTEGER(arg_t *arg) {
107 asn1p_expr_t *expr = arg->expr;
108 asn1p_expr_t *v;
109
110 REDIR(OT_DEPS);
111
112 if(TQ_FIRST(&(expr->members))) {
113 OUT("typedef enum %s {\n", MKID(expr->Identifier));
114 TQ_FOR(v, &(expr->members), next) {
115 switch(v->expr_type) {
116 case A1TC_UNIVERVAL:
117 OUT("\t%s\t= %lld,\n",
118 asn1c_make_identifier(0,
119 expr->Identifier,
120 v->Identifier, 0),
121 v->value->value.v_integer);
122 break;
123 default:
124 return -1;
125 }
126 }
127 OUT("} %s_e;\n", MKID(expr->Identifier));
128 }
129
130 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
131}
132
133int
134asn1c_lang_C_type_SEQUENCE(arg_t *arg) {
135 asn1p_expr_t *expr = arg->expr;
136 asn1p_expr_t *v;
137 int comp_mode = 0; /* {root,ext=1,root,root,...} */
138
139 DEPENDENCIES;
140
141 if(arg->embed) {
vlmdae7f9d2004-08-22 03:25:24 +0000142 OUT("struct %s {\n", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000143 } else {
144 OUT("typedef struct %s {\n",
145 MKID(expr->Identifier));
146 }
147
148 TQ_FOR(v, &(expr->members), next) {
149 if(v->expr_type == A1TC_EXTENSIBLE) {
150 if(comp_mode < 3) comp_mode++;
151 }
152 if(comp_mode == 1 && !v->marker)
153 v->marker = EM_OPTIONAL;
154 EMBED(v);
155 }
156
157 PCTX_DEF;
vlmdae7f9d2004-08-22 03:25:24 +0000158 OUT("} %s%s%s", expr->marker?"*":"",
159 expr->_anonymous_type ? "" : MKID(expr->Identifier),
160 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000161
162 return asn1c_lang_C_type_SEQUENCE_def(arg);
163}
164
165static int
166asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
167 asn1p_expr_t *expr = arg->expr;
168 asn1p_expr_t *v;
169 int elements; /* Number of elements */
170 int tags_impl_skip = 0;
171 int comp_mode = 0; /* {root,ext=1,root,root,...} */
172 int ext_start = -1;
173 int ext_stop = -1;
vlm4e03ce22004-06-06 07:20:17 +0000174 tag2el_t *tag2el = NULL;
175 int tag2el_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000176 int tags_count;
vlmfa67ddc2004-06-03 03:38:44 +0000177 char *p;
178
vlm4e03ce22004-06-06 07:20:17 +0000179 /*
180 * Fetch every inner tag from the tag to elements map.
181 */
182 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
183 if(tag2el) free(tag2el);
184 return -1;
185 }
186
vlm33a4ff12004-08-11 05:21:32 +0000187 GEN_INCLUDE("constr_SEQUENCE");
188 if(!arg->embed)
189 GEN_DECLARE(expr); /* asn1_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000190
vlm33a4ff12004-08-11 05:21:32 +0000191 REDIR(OT_STAT_DEFS);
vlmfa67ddc2004-06-03 03:38:44 +0000192
193 /*
194 * Print out the table according to which the parsing is performed.
195 */
196 p = MKID(expr->Identifier);
vlmb2839012004-08-20 13:37:01 +0000197 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000198
199 elements = 0;
200 INDENTED(TQ_FOR(v, &(expr->members), next) {
201 if(v->expr_type == A1TC_EXTENSIBLE) {
202 if((++comp_mode) == 1)
203 ext_start = elements - 1;
204 else
205 ext_stop = elements - 1;
206 continue;
207 }
vlmfa67ddc2004-06-03 03:38:44 +0000208 elements++;
vlm4e554992004-08-25 02:03:12 +0000209 emit_member_table(arg, v);
vlmfa67ddc2004-06-03 03:38:44 +0000210 });
211 OUT("};\n");
212
vlm4a3f5822004-06-28 21:13:46 +0000213 /*
214 * Print out asn1_DEF_<type>_tags[] vector.
215 */
vlm6e73a042004-08-11 07:17:22 +0000216 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000217
vlm4e03ce22004-06-06 07:20:17 +0000218 /*
219 * Tags to elements map.
220 */
221 emit_tag2member_map(arg, tag2el, tag2el_count);
222
vlm4a3f5822004-06-28 21:13:46 +0000223 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000224 OUT("static asn1_SEQUENCE_specifics_t asn1_DEF_%s_specs = {\n", p);
225 INDENTED(
226 OUT("sizeof(struct %s),\n", p);
227 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
vlm4e03ce22004-06-06 07:20:17 +0000228 OUT("asn1_DEF_%s_tag2el,\n", p);
229 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
vlmfa67ddc2004-06-03 03:38:44 +0000230 OUT("%d,\t/* Start extensions */\n",
231 ext_start);
232 OUT("%d\t/* Stop extensions */\n",
233 (ext_stop<ext_start)?elements+1:ext_stop, ext_stop);
234 );
235 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000236
237 /*
238 * Emit asn1_DEF_xxx table.
239 */
240 emit_type_DEF(arg, expr, tags_count, tags_impl_skip, elements,
241 ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000242
vlmfa67ddc2004-06-03 03:38:44 +0000243 REDIR(OT_TYPE_DECLS);
244
245 return 0;
246}
247
248int
vlmfa67ddc2004-06-03 03:38:44 +0000249asn1c_lang_C_type_SET(arg_t *arg) {
250 asn1p_expr_t *expr = arg->expr;
251 asn1p_expr_t *v;
252 long mcount;
253 char *id;
254 int comp_mode = 0; /* {root,ext=1,root,root,...} */
255
256 DEPENDENCIES;
257
258 REDIR(OT_DEPS);
259
260 OUT("\n");
261 OUT("/*\n");
262 OUT(" * Method of determining the components presence\n");
263 OUT(" */\n");
264 mcount = 0;
vlm6e73a042004-08-11 07:17:22 +0000265 OUT("typedef enum %s_PR {\n", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000266 TQ_FOR(v, &(expr->members), next) {
267 if(v->expr_type == A1TC_EXTENSIBLE) continue;
268 INDENTED(
269 id = MKID(expr->Identifier);
270 OUT("%s_PR_", id);
271 id = MKID(v->Identifier);
272 OUT("%s,\t/* Member %s is present */\n",
273 id, id)
274 );
275 mcount++;
276 }
vlm6e73a042004-08-11 07:17:22 +0000277 id = MKID(expr->Identifier);
278 OUT("} %s_PR;\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000279
280 REDIR(OT_TYPE_DECLS);
281
282 if(arg->embed) {
vlm6e73a042004-08-11 07:17:22 +0000283 OUT("struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000284 } else {
vlm6e73a042004-08-11 07:17:22 +0000285 OUT("typedef struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000286 }
287
288 TQ_FOR(v, &(expr->members), next) {
289 if(v->expr_type == A1TC_EXTENSIBLE) {
290 if(comp_mode < 3) comp_mode++;
291 }
292 if(comp_mode == 1 && !v->marker)
293 v->marker = EM_OPTIONAL;
294 EMBED(v);
295 }
296
297 INDENTED(
298 id = MKID(expr->Identifier);
299 OUT("\n");
300 OUT("/* Presence bitmask: ASN_SET_ISPRESENT(p%s, %s_PR_x) */\n",
301 id, id);
302 OUT("unsigned int _presence_map\n");
303 OUT("\t[((%ld+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))];\n", mcount);
304 );
305
306 PCTX_DEF;
vlmdae7f9d2004-08-22 03:25:24 +0000307 OUT("} %s%s%s", expr->marker?"*":"",
308 expr->_anonymous_type ? "" : MKID(expr->Identifier),
309 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000310
311 return asn1c_lang_C_type_SET_def(arg);
312}
313
vlmfa67ddc2004-06-03 03:38:44 +0000314static int
315asn1c_lang_C_type_SET_def(arg_t *arg) {
316 asn1p_expr_t *expr = arg->expr;
317 asn1p_expr_t *v;
318 int elements;
319 int tags_impl_skip = 0;
320 int comp_mode = 0; /* {root,ext=1,root,root,...} */
vlmfa67ddc2004-06-03 03:38:44 +0000321 tag2el_t *tag2el = NULL;
322 int tag2el_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000323 int tags_count;
vlmfa67ddc2004-06-03 03:38:44 +0000324 char *p;
325
326 /*
327 * Fetch every inner tag from the tag to elements map.
328 */
329 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
330 if(tag2el) free(tag2el);
331 return -1;
vlmfa67ddc2004-06-03 03:38:44 +0000332 }
333
vlm33a4ff12004-08-11 05:21:32 +0000334 GEN_INCLUDE("constr_SET");
335 if(!arg->embed)
336 GEN_DECLARE(expr); /* asn1_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000337
338 REDIR(OT_STAT_DEFS);
339
vlmfa67ddc2004-06-03 03:38:44 +0000340 /*
341 * Print out the table according to which the parsing is performed.
342 */
343 p = MKID(expr->Identifier);
vlmb2839012004-08-20 13:37:01 +0000344 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000345
346 elements = 0;
347 INDENTED(TQ_FOR(v, &(expr->members), next) {
348 if(v->expr_type != A1TC_EXTENSIBLE) {
349 if(comp_mode == 1)
350 v->marker = EM_OPTIONAL;
vlmfa67ddc2004-06-03 03:38:44 +0000351 } else {
352 if(comp_mode < 3) comp_mode++;
353 continue;
354 }
vlmb2839012004-08-20 13:37:01 +0000355 elements++;
vlm4e554992004-08-25 02:03:12 +0000356 emit_member_table(arg, v);
vlmfa67ddc2004-06-03 03:38:44 +0000357 });
358 OUT("};\n");
359
vlm4a3f5822004-06-28 21:13:46 +0000360 /*
361 * Print out asn1_DEF_<type>_tags[] vector.
362 */
vlm6e73a042004-08-11 07:17:22 +0000363 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000364
365 /*
366 * Tags to elements map.
367 */
vlm4e03ce22004-06-06 07:20:17 +0000368 emit_tag2member_map(arg, tag2el, tag2el_count);
vlmfa67ddc2004-06-03 03:38:44 +0000369
370 /*
371 * Emit a map of mandatory elements.
372 */
vlm4a3f5822004-06-28 21:13:46 +0000373 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000374 OUT("static uint8_t asn1_DEF_%s_mmap", p);
375 OUT("[(%d + (8 * sizeof(unsigned int)) - 1) / 8]", elements);
376 OUT(" = {\n", p);
377 INDENTED(
378 if(elements) {
379 int delimit = 0;
380 int el = 0;
381 TQ_FOR(v, &(expr->members), next) {
382 if(v->expr_type == A1TC_EXTENSIBLE) continue;
383 if(delimit) {
384 OUT(",\n");
385 delimit = 0;
386 } else if(el) {
387 OUT(" | ");
388 }
389 OUT("(%d << %d)", v->marker?0:1, 7 - (el % 8));
390 if(el && (el % 8) == 0)
391 delimit = 1;
392 el++;
393 }
394 } else {
395 OUT("0");
396 }
397 );
398 OUT("\n");
399 OUT("};\n");
400
401 OUT("static asn1_SET_specifics_t asn1_DEF_%s_specs = {\n", p);
402 INDENTED(
403 OUT("sizeof(struct %s),\n", p);
404 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
405 OUT("offsetof(struct %s, _presence_map),\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000406 OUT("asn1_DEF_%s_tag2el,\n", p);
407 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
vlm79b08d52004-07-01 00:52:50 +0000408 OUT("%d,\t/* Whether extensible */\n",
409 check_if_extensible(expr));
vlmfa67ddc2004-06-03 03:38:44 +0000410 OUT("(unsigned int *)asn1_DEF_%s_mmap\t/* Mandatory elements map */\n", p);
411 );
412 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000413
414 /*
415 * Emit asn1_DEF_xxx table.
416 */
417 emit_type_DEF(arg, expr, tags_count, tags_impl_skip, elements,
418 ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000419
vlmfa67ddc2004-06-03 03:38:44 +0000420 REDIR(OT_TYPE_DECLS);
421
422 return 0;
423}
424
425int
vlmdae7f9d2004-08-22 03:25:24 +0000426asn1c_lang_C_type_SEx_OF(arg_t *arg) {
vlmfa67ddc2004-06-03 03:38:44 +0000427 asn1p_expr_t *expr = arg->expr;
vlmdae7f9d2004-08-22 03:25:24 +0000428 asn1p_expr_t *memb;
vlmfa67ddc2004-06-03 03:38:44 +0000429
430 DEPENDENCIES;
431
432 if(arg->embed) {
433 OUT("struct %s {\n", MKID(expr->Identifier));
434 } else {
vlmdae7f9d2004-08-22 03:25:24 +0000435 OUT("typedef struct %s {\n", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000436 }
437
vlmdae7f9d2004-08-22 03:25:24 +0000438 memb = TQ_FIRST(&expr->members);
439
440 INDENT(+1);
441 OUT("A_%s_OF(",
442 (arg->expr->expr_type == ASN_CONSTR_SET_OF)
443 ? "SET" : "SEQUENCE");
444 if(memb->expr_type & ASN_CONSTR_MASK) {
445 arg_t tmp;
446 asn1p_expr_t tmp_memb;
447 arg->embed++;
448 tmp = *arg;
449 tmp.expr = &tmp_memb;
450 tmp_memb = *memb;
451 tmp_memb._anonymous_type = 1;
452 tmp_memb.Identifier = strdup(
453 asn1c_make_identifier(0,
454 expr->Identifier, "member", 0));
455 assert(tmp_memb.Identifier);
456 tmp.default_cb(&tmp);
457 free(tmp_memb.Identifier);
458 arg->embed--;
459 assert(arg->target->target == OT_TYPE_DECLS);
460 } else {
461 OUT("%s", asn1c_type_name(arg, memb, TNF_RSAFE));
vlmfa67ddc2004-06-03 03:38:44 +0000462 }
vlmdae7f9d2004-08-22 03:25:24 +0000463 OUT(") list;\n");
464 INDENT(-1);
vlmfa67ddc2004-06-03 03:38:44 +0000465
466 PCTX_DEF;
vlmdae7f9d2004-08-22 03:25:24 +0000467 OUT("} %s%s%s", expr->marker?"*":"",
468 expr->_anonymous_type ? "" : MKID(expr->Identifier),
469 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000470
471 /*
vlmdae7f9d2004-08-22 03:25:24 +0000472 * SET OF/SEQUENCE OF definition
vlmfa67ddc2004-06-03 03:38:44 +0000473 */
vlmdae7f9d2004-08-22 03:25:24 +0000474 return asn1c_lang_C_type_SEx_OF_def(arg,
475 (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF));
vlmfa67ddc2004-06-03 03:38:44 +0000476}
477
478static int
479asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
480 asn1p_expr_t *expr = arg->expr;
481 asn1p_expr_t *v;
482 int tags_impl_skip = 0;
vlm6e73a042004-08-11 07:17:22 +0000483 int tags_count;
vlmfa67ddc2004-06-03 03:38:44 +0000484 char *p;
485
vlm33a4ff12004-08-11 05:21:32 +0000486 /*
487 * Print out the table according to which the parsing is performed.
488 */
vlmfa67ddc2004-06-03 03:38:44 +0000489 if(seq_of) {
vlm33a4ff12004-08-11 05:21:32 +0000490 GEN_INCLUDE("constr_SEQUENCE_OF");
vlmfa67ddc2004-06-03 03:38:44 +0000491 } else {
vlm33a4ff12004-08-11 05:21:32 +0000492 GEN_INCLUDE("constr_SET_OF");
vlmfa67ddc2004-06-03 03:38:44 +0000493 }
vlm33a4ff12004-08-11 05:21:32 +0000494 if(!arg->embed)
495 GEN_DECLARE(expr); /* asn1_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000496
497 REDIR(OT_STAT_DEFS);
498
499 /*
500 * Print out the table according to which the parsing is performed.
501 */
502 p = MKID(expr->Identifier);
vlmb2839012004-08-20 13:37:01 +0000503 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000504
vlmb2839012004-08-20 13:37:01 +0000505 INDENTED(
vlmfa67ddc2004-06-03 03:38:44 +0000506 v = TQ_FIRST(&(expr->members));
vlm4e554992004-08-25 02:03:12 +0000507 emit_member_table(arg, v);
vlmfa67ddc2004-06-03 03:38:44 +0000508 );
509 OUT("};\n");
510
vlm4a3f5822004-06-28 21:13:46 +0000511 /*
512 * Print out asn1_DEF_<type>_tags[] vector.
513 */
vlm6e73a042004-08-11 07:17:22 +0000514 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000515
vlm4a3f5822004-06-28 21:13:46 +0000516 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000517 OUT("static asn1_SET_OF_specifics_t asn1_DEF_%s_specs = {\n", p);
518 INDENTED(
519 OUT("sizeof(struct %s),\n", p);
520 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000521 );
522 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000523
524 /*
525 * Emit asn1_DEF_xxx table.
526 */
527 emit_type_DEF(arg, expr, tags_count, tags_impl_skip, 1,
528 ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000529
vlmfa67ddc2004-06-03 03:38:44 +0000530 REDIR(OT_TYPE_DECLS);
531
532 return 0;
533}
534
535int
536asn1c_lang_C_type_CHOICE(arg_t *arg) {
537 asn1p_expr_t *expr = arg->expr;
538 asn1p_expr_t *v;
vlmdae7f9d2004-08-22 03:25:24 +0000539 char *id;
vlmfa67ddc2004-06-03 03:38:44 +0000540
541 DEPENDENCIES;
542
vlm33a4ff12004-08-11 05:21:32 +0000543 REDIR(OT_DEPS);
544
vlmdae7f9d2004-08-22 03:25:24 +0000545 id = MKID(expr->Identifier);
546 OUT("typedef enum %s_PR {\n", id);
vlm33a4ff12004-08-11 05:21:32 +0000547 INDENTED(
vlm33a4ff12004-08-11 05:21:32 +0000548 OUT("%s_PR_NOTHING,\t"
vlmdae7f9d2004-08-22 03:25:24 +0000549 "/* No components present */\n", id);
vlm33a4ff12004-08-11 05:21:32 +0000550 TQ_FOR(v, &(expr->members), next) {
551 if(v->expr_type == A1TC_EXTENSIBLE) {
552 OUT("/* Extensions may appear below */\n");
553 continue;
554 }
vlmdae7f9d2004-08-22 03:25:24 +0000555 id = MKID(expr->Identifier);
556 OUT("%s_PR_", id);
557 id = MKID(v->Identifier);
558 OUT("%s,\n", id, id);
vlm33a4ff12004-08-11 05:21:32 +0000559 }
560 );
vlmdae7f9d2004-08-22 03:25:24 +0000561 id = MKID(expr->Identifier);
562 OUT("} %s_PR;\n", id);
vlm33a4ff12004-08-11 05:21:32 +0000563
564 REDIR(OT_TYPE_DECLS);
vlmfa67ddc2004-06-03 03:38:44 +0000565
566 if(arg->embed) {
vlmdae7f9d2004-08-22 03:25:24 +0000567 OUT("struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000568 } else {
vlmdae7f9d2004-08-22 03:25:24 +0000569 OUT("typedef struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000570 }
571
572 INDENTED(
vlmdae7f9d2004-08-22 03:25:24 +0000573 OUT("%s_PR present;\n", id);
574 OUT("union {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000575 TQ_FOR(v, &(expr->members), next) {
576 EMBED(v);
577 }
578 if(UNNAMED_UNIONS) OUT("};\n");
579 else OUT("} choice;\n");
580 );
581
582 PCTX_DEF;
vlmdae7f9d2004-08-22 03:25:24 +0000583 OUT("} %s%s%s", expr->marker?"*":"",
584 expr->_anonymous_type ? "" : MKID(expr->Identifier),
585 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000586
587 return asn1c_lang_C_type_CHOICE_def(arg);
588}
589
590static int
591asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
592 asn1p_expr_t *expr = arg->expr;
593 asn1p_expr_t *v;
594 int elements; /* Number of elements */
595 int tags_impl_skip = 0;
596 int comp_mode = 0; /* {root,ext=1,root,root,...} */
vlmfa67ddc2004-06-03 03:38:44 +0000597 tag2el_t *tag2el = NULL;
598 int tag2el_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000599 int tags_count;
vlmfa67ddc2004-06-03 03:38:44 +0000600 char *p;
601
602 /*
603 * Fetch every inner tag from the tag to elements map.
604 */
605 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
606 if(tag2el) free(tag2el);
607 return -1;
vlmfa67ddc2004-06-03 03:38:44 +0000608 }
609
vlm33a4ff12004-08-11 05:21:32 +0000610 GEN_INCLUDE("constr_CHOICE");
611 if(!arg->embed)
612 GEN_DECLARE(expr); /* asn1_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000613
vlm33a4ff12004-08-11 05:21:32 +0000614 REDIR(OT_STAT_DEFS);
vlmfa67ddc2004-06-03 03:38:44 +0000615
616 /*
617 * Print out the table according to which the parsing is performed.
618 */
619 p = MKID(expr->Identifier);
vlmb2839012004-08-20 13:37:01 +0000620 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000621
622 elements = 0;
623 INDENTED(TQ_FOR(v, &(expr->members), next) {
624 if(v->expr_type != A1TC_EXTENSIBLE) {
625 if(comp_mode == 1)
626 v->marker = EM_OPTIONAL;
vlmfa67ddc2004-06-03 03:38:44 +0000627 } else {
628 if(comp_mode < 3) comp_mode++;
629 continue;
630 }
vlmb2839012004-08-20 13:37:01 +0000631 elements++;
vlm4e554992004-08-25 02:03:12 +0000632 emit_member_table(arg, v);
vlmfa67ddc2004-06-03 03:38:44 +0000633 });
634 OUT("};\n");
635
vlm6e73a042004-08-11 07:17:22 +0000636
vlmfa67ddc2004-06-03 03:38:44 +0000637 if(arg->embed) {
638 /*
639 * Our parent structure has already taken this into account.
640 */
vlm6e73a042004-08-11 07:17:22 +0000641 tags_count = 0;
vlmfa67ddc2004-06-03 03:38:44 +0000642 } else {
vlm6e73a042004-08-11 07:17:22 +0000643 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 1);
vlmfa67ddc2004-06-03 03:38:44 +0000644 }
vlmfa67ddc2004-06-03 03:38:44 +0000645
646 /*
647 * Tags to elements map.
648 */
vlm4e03ce22004-06-06 07:20:17 +0000649 emit_tag2member_map(arg, tag2el, tag2el_count);
vlmfa67ddc2004-06-03 03:38:44 +0000650
vlm6e73a042004-08-11 07:17:22 +0000651 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000652 OUT("static asn1_CHOICE_specifics_t asn1_DEF_%s_specs = {\n", p);
653 INDENTED(
654 OUT("sizeof(struct %s),\n", p);
655 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
656 OUT("offsetof(struct %s, present),\n", p);
657 OUT("sizeof(((struct %s *)0)->present),\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000658 OUT("asn1_DEF_%s_tag2el,\n", p);
659 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
vlm79b08d52004-07-01 00:52:50 +0000660 OUT("%d\t/* Whether extensible */\n",
661 check_if_extensible(expr));
vlmfa67ddc2004-06-03 03:38:44 +0000662 );
663 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000664
665 /*
666 * Emit asn1_DEF_xxx table.
667 */
668 emit_type_DEF(arg, expr, tags_count, tags_impl_skip, elements,
669 ETD_CP_CONSTRUCTED /*either?!*/, ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000670
vlmfa67ddc2004-06-03 03:38:44 +0000671 REDIR(OT_TYPE_DECLS);
672
673 return 0;
674}
675
676int
677asn1c_lang_C_type_REFERENCE(arg_t *arg) {
678 asn1p_ref_t *ref;
679
680 ref = arg->expr->reference;
681 if(ref->components[ref->comp_count-1].name[0] == '&') {
vlmfa67ddc2004-06-03 03:38:44 +0000682 asn1p_expr_t *extract;
683 arg_t tmp;
684 int ret;
685
vlmdae7f9d2004-08-22 03:25:24 +0000686 extract = asn1f_class_access_ex(arg->asn, arg->mod,
687 arg->expr, ref);
vlmfa67ddc2004-06-03 03:38:44 +0000688 if(extract == NULL)
689 return -1;
690
vlmdae7f9d2004-08-22 03:25:24 +0000691 extract = asn1p_expr_clone(extract, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000692 if(extract) {
693 if(extract->Identifier)
694 free(extract->Identifier);
695 extract->Identifier = strdup(arg->expr->Identifier);
696 if(extract->Identifier == NULL) {
697 asn1p_expr_free(extract);
698 return -1;
699 }
700 } else {
701 return -1;
702 }
703
704 tmp = *arg;
705 tmp.asn = arg->asn;
vlmdae7f9d2004-08-22 03:25:24 +0000706 tmp.mod = extract->module;
vlmfa67ddc2004-06-03 03:38:44 +0000707 tmp.expr = extract;
708
709 ret = arg->default_cb(&tmp);
710
711 asn1p_expr_free(extract);
712
713 return ret;
714 }
715
716
717 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
718}
719
720int
721asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
722 asn1p_expr_t *expr = arg->expr;
723 int tags_impl_skip = 0;
vlm6e73a042004-08-11 07:17:22 +0000724 int tags_count;
vlmfa67ddc2004-06-03 03:38:44 +0000725 char *p;
726
727 if(arg->embed) {
728 REDIR(OT_TYPE_DECLS);
729
730 OUT("%s\t", asn1c_type_name(arg, arg->expr,
731 expr->marker?TNF_RSAFE:TNF_CTYPE));
732 OUT("%s", expr->marker?"*":" ");
vlmdae7f9d2004-08-22 03:25:24 +0000733 OUT("%s", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000734 if(expr->marker) OUT("\t/* %s */",
735 (expr->marker==EM_OPTIONAL)?"OPTIONAL":"DEFAULT");
vlmb2839012004-08-20 13:37:01 +0000736
737 REDIR(OT_TYPE_DECLS);
vlmfa67ddc2004-06-03 03:38:44 +0000738 return 0;
739 }
740
vlmfa67ddc2004-06-03 03:38:44 +0000741
vlm33a4ff12004-08-11 05:21:32 +0000742 GEN_INCLUDE(asn1c_type_name(arg, expr, TNF_INCLUDE));
vlmfa67ddc2004-06-03 03:38:44 +0000743
744 REDIR(OT_TYPE_DECLS);
745
746 OUT("typedef %s\t", asn1c_type_name(arg, arg->expr, TNF_CTYPE));
747 OUT("%s", expr->marker?"*":" ");
vlmdae7f9d2004-08-22 03:25:24 +0000748 OUT("%s_t", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000749
750 REDIR(OT_STAT_DEFS);
751
vlm4a3f5822004-06-28 21:13:46 +0000752 /*
753 * Print out asn1_DEF_<type>_tags[] vector.
754 */
vlm6e73a042004-08-11 07:17:22 +0000755 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000756
vlm4e554992004-08-25 02:03:12 +0000757 emit_type_DEF(arg, expr, tags_count, tags_impl_skip, 0,
758 ETD_CP_UNKNOWN, ETD_NO_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000759
vlmb2839012004-08-20 13:37:01 +0000760 REDIR(OT_CODE);
761
vlmfa67ddc2004-06-03 03:38:44 +0000762 /*
763 * Constraint checking.
764 */
vlmfa67ddc2004-06-03 03:38:44 +0000765 p = MKID(expr->Identifier);
766 OUT("int\n");
767 OUT("%s_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,\n", p);
768 INDENTED(
769 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
770 OUT("\n");
vlm1d036692004-08-19 13:29:46 +0000771 if(asn1c_emit_constraint_checking_code(arg) == 1) {
772 if(0) {
vlmfa67ddc2004-06-03 03:38:44 +0000773 OUT("/* Check the constraints of the underlying type */\n");
774 OUT("return asn1_DEF_%s.check_constraints\n",
775 asn1c_type_name(arg, expr, TNF_SAFE));
776 OUT("\t(td, sptr, app_errlog, app_key);\n");
vlm1d036692004-08-19 13:29:46 +0000777 } else {
vlmfa67ddc2004-06-03 03:38:44 +0000778 OUT("/* Make the underlying type checker permanent */\n");
779 OUT("td->check_constraints = asn1_DEF_%s.check_constraints;\n",
780 asn1c_type_name(arg, expr, TNF_SAFE));
781 OUT("return td->check_constraints\n");
782 OUT("\t(td, sptr, app_errlog, app_key);\n");
vlm1d036692004-08-19 13:29:46 +0000783 }
vlmfa67ddc2004-06-03 03:38:44 +0000784 }
785 );
786 OUT("}\n");
787 OUT("\n");
788
789 /*
790 * Emit suicidal functions.
791 */
792
vlmfa67ddc2004-06-03 03:38:44 +0000793 /*
794 * This function replaces certain fields from the definition
795 * of a type with the corresponding fields from the basic type
796 * (from which the current type is inherited).
797 */
vlmfa67ddc2004-06-03 03:38:44 +0000798 OUT("/*\n");
vlmb2839012004-08-20 13:37:01 +0000799 OUT(" * This type is implemented using %s,\n",
800 asn1c_type_name(arg, expr, TNF_SAFE));
vlmfa67ddc2004-06-03 03:38:44 +0000801 OUT(" * so adjust the DEF appropriately.\n");
802 OUT(" */\n");
803 OUT("static void\n");
vlmb2839012004-08-20 13:37:01 +0000804 p = MKID(expr->Identifier);
805 OUT("%s_inherit_TYPE_descriptor(asn1_TYPE_descriptor_t *td) {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000806 INDENT(+1);
vlmb2839012004-08-20 13:37:01 +0000807 {
808 char *type_name = asn1c_type_name(arg, expr, TNF_SAFE);
809 OUT("td->ber_decoder = asn1_DEF_%s.ber_decoder;\n", type_name);
810 OUT("td->der_encoder = asn1_DEF_%s.der_encoder;\n", type_name);
811 OUT("td->free_struct = asn1_DEF_%s.free_struct;\n", type_name);
812 OUT("td->print_struct = asn1_DEF_%s.print_struct;\n", type_name);
813 OUT("td->last_tag_form = asn1_DEF_%s.last_tag_form;\n", type_name);
814 OUT("td->elements = asn1_DEF_%s.elements;\n", type_name);
815 OUT("td->elements_count = asn1_DEF_%s.elements_count;\n", type_name);
816 OUT("td->specifics = asn1_DEF_%s.specifics;\n", type_name);
817 }
vlmfa67ddc2004-06-03 03:38:44 +0000818 INDENT(-1);
819 OUT("}\n");
820 OUT("\n");
vlmfa67ddc2004-06-03 03:38:44 +0000821
822 p = MKID(expr->Identifier);
823 OUT("ber_dec_rval_t\n");
824 OUT("%s_decode_ber(asn1_TYPE_descriptor_t *td,\n", p);
825 INDENTED(
826 OUT("\tvoid **structure, void *bufptr, size_t size, int tag_mode) {\n");
vlmb2839012004-08-20 13:37:01 +0000827 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000828 OUT("return td->ber_decoder(td, structure,\n");
829 OUT("\tbufptr, size, tag_mode);\n");
830 );
831 OUT("}\n");
832 OUT("\n");
833
834 p = MKID(expr->Identifier);
835 OUT("der_enc_rval_t\n");
836 OUT("%s_encode_der(asn1_TYPE_descriptor_t *td,\n", p);
837 INDENTED(
838 OUT("\tvoid *structure, int tag_mode, ber_tlv_tag_t tag,\n");
839 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
vlmb2839012004-08-20 13:37:01 +0000840 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000841 OUT("return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);\n");
842 );
843 OUT("}\n");
844 OUT("\n");
845
846 p = MKID(expr->Identifier);
847 OUT("int\n");
848 OUT("%s_print(asn1_TYPE_descriptor_t *td, const void *struct_ptr,\n", p);
849 INDENTED(
850 OUT("\tint ilevel, asn_app_consume_bytes_f *cb, void *app_key) {\n");
vlmb2839012004-08-20 13:37:01 +0000851 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000852 OUT("return td->print_struct(td, struct_ptr, ilevel, cb, app_key);\n");
853 );
854 OUT("}\n");
855 OUT("\n");
856
857 p = MKID(expr->Identifier);
858 OUT("void\n");
859 OUT("%s_free(asn1_TYPE_descriptor_t *td,\n", p);
860 INDENTED(
861 OUT("\tvoid *struct_ptr, int contents_only) {\n");
vlmb2839012004-08-20 13:37:01 +0000862 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000863 OUT("td->free_struct(td, struct_ptr, contents_only);\n");
864 );
865 OUT("}\n");
866 OUT("\n");
867
868 REDIR(OT_FUNC_DECLS);
869
870 p = MKID(expr->Identifier);
vlm12c8f692004-09-06 08:07:29 +0000871 if(HIDE_INNER_DEFS) OUT("/* ");
872 OUT("extern asn1_TYPE_descriptor_t asn1_DEF_%s;", p);
873 if(HIDE_INNER_DEFS) OUT(" // (Use -fall-defs-global to expose) */");
874 OUT("\n");
vlmfa67ddc2004-06-03 03:38:44 +0000875 OUT("asn_constr_check_f %s_constraint;\n", p);
876 OUT("ber_type_decoder_f %s_decode_ber;\n", p);
877 OUT("der_type_encoder_f %s_encode_der;\n", p);
878 OUT("asn_struct_print_f %s_print;\n", p);
879 OUT("asn_struct_free_f %s_free;\n", p);
880
vlm33a4ff12004-08-11 05:21:32 +0000881 REDIR(OT_TYPE_DECLS);
882
vlmfa67ddc2004-06-03 03:38:44 +0000883 return 0;
884}
885
886int
887asn1c_lang_C_type_EXTENSIBLE(arg_t *arg) {
888
889 OUT("/*\n");
890 OUT(" * This type is extensible,\n");
891 OUT(" * possible extensions are below.\n");
892 OUT(" */\n");
893
894 return 0;
895}
896
vlm79b08d52004-07-01 00:52:50 +0000897static int check_if_extensible(asn1p_expr_t *expr) {
898 asn1p_expr_t *v;
899 TQ_FOR(v, &(expr->members), next) {
900 if(v->expr_type == A1TC_EXTENSIBLE) return 1;
901 }
902 return 0;
903}
904
vlmfa67ddc2004-06-03 03:38:44 +0000905static int
906_print_tag(arg_t *arg, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag_p) {
907 struct asn1p_type_tag_s tag;
908
909 if(tag_p) {
910 tag = *tag_p;
911 } else {
vlm2de0e792004-09-05 10:42:33 +0000912 if(asn1f_fetch_tag(arg->asn, arg->mod, expr, &tag, 0)) {
vlme2070ea2004-09-04 04:42:29 +0000913 OUT("-1 /* Ambiguous tag (CHOICE|ANY?) */");
vlmfa67ddc2004-06-03 03:38:44 +0000914 return 0;
915 }
916 }
917
918 OUT("(");
919 switch(tag.tag_class) {
920 case TC_UNIVERSAL: OUT("ASN_TAG_CLASS_UNIVERSAL"); break;
921 case TC_APPLICATION: OUT("ASN_TAG_CLASS_APPLICATION"); break;
922 case TC_CONTEXT_SPECIFIC: OUT("ASN_TAG_CLASS_CONTEXT"); break;
923 case TC_PRIVATE: OUT("ASN_TAG_CLASS_PRIVATE"); break;
924 case TC_NOCLASS:
925 break;
926 }
927 OUT(" | (%lld << 2))", tag.tag_value);
928
929 return 0;
930}
931
vlm4e03ce22004-06-06 07:20:17 +0000932
933static int
934_tag2el_cmp(const void *ap, const void *bp) {
935 const tag2el_t *a = ap;
936 const tag2el_t *b = bp;
937 const struct asn1p_type_tag_s *ta = &a->el_tag;
938 const struct asn1p_type_tag_s *tb = &b->el_tag;
939
940 if(ta->tag_class == tb->tag_class) {
941 if(ta->tag_value == tb->tag_value) {
942 /*
943 * Sort by their respective positions.
944 */
945 if(a->el_no < b->el_no)
946 return -1;
947 else if(a->el_no > b->el_no)
948 return 1;
949 return 0;
950 } else if(ta->tag_value < tb->tag_value)
951 return -1;
952 else
953 return 1;
954 } else if(ta->tag_class < tb->tag_class) {
955 return -1;
956 } else {
957 return 1;
958 }
959}
960
vlmfa67ddc2004-06-03 03:38:44 +0000961/*
962 * For constructed types, number of external tags may be greater than
963 * number of elements in the type because of CHOICE type.
964 * T ::= SET { -- Three possible tags:
965 * a INTEGER, -- One tag is here...
966 * b Choice1 -- ... and two more tags are there.
967 * }
968 * Choice1 ::= CHOICE {
969 * s1 IA5String,
970 * s2 ObjectDescriptor
971 * }
972 */
973static int
974_fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no) {
975 asn1p_expr_t *expr = arg->expr;
976 arg_t tmparg = *arg;
977 asn1p_expr_t *v;
978 int element = 0;
979
980 TQ_FOR(v, &(expr->members), next) {
981 if(v->expr_type == A1TC_EXTENSIBLE)
982 continue;
983
984 tmparg.expr = v;
985
986 if(_add_tag2el_member(&tmparg, tag2el, count,
987 (el_no==-1)?element:el_no)) {
988 return -1;
989 }
990
991 element++;
992 }
993
vlm4e03ce22004-06-06 07:20:17 +0000994 /*
vlmc8aeab42004-06-14 13:09:45 +0000995 * Sort the map according to canonical order of their tags
996 * and element numbers.
vlm4e03ce22004-06-06 07:20:17 +0000997 */
998 qsort(*tag2el, *count, sizeof(**tag2el), _tag2el_cmp);
999
vlmc8aeab42004-06-14 13:09:45 +00001000 /*
1001 * Initialize .toff_{first|last} members.
1002 */
1003 if(*count) {
1004 struct asn1p_type_tag_s *cur_tag = 0;
1005 tag2el_t *cur = *tag2el;
1006 tag2el_t *end = cur + *count;
1007 int occur, i;
1008 for(occur = 0; cur < end; cur++) {
1009 if(cur_tag == 0
1010 || cur_tag->tag_value != cur->el_tag.tag_value
1011 || cur_tag->tag_class != cur->el_tag.tag_class) {
1012 cur_tag = &cur->el_tag;
1013 occur = 0;
1014 } else {
1015 occur++;
1016 }
1017 cur->toff_first = -occur;
1018 for(i = 0; i >= -occur; i--)
1019 cur[i].toff_last = -i;
1020 }
1021 }
1022
vlmfa67ddc2004-06-03 03:38:44 +00001023 return 0;
1024}
1025
1026static int
1027_add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no) {
1028 struct asn1p_type_tag_s tag;
1029 int ret;
1030
1031 assert(el_no >= 0);
1032
vlm2de0e792004-09-05 10:42:33 +00001033 ret = asn1f_fetch_tag(arg->asn, arg->mod, arg->expr, &tag, 1);
vlmfa67ddc2004-06-03 03:38:44 +00001034 if(ret == 0) {
vlme2070ea2004-09-04 04:42:29 +00001035 tag2el_t *te;
1036 int new_count = (*count) + 1;
vlmfa67ddc2004-06-03 03:38:44 +00001037 void *p;
vlme2070ea2004-09-04 04:42:29 +00001038
vlm2de0e792004-09-05 10:42:33 +00001039 if(tag.tag_value == -1) {
1040 /*
1041 * This is an untagged ANY type,
1042 * proceed without adding a tag
1043 */
1044 return 0;
1045 }
1046
vlme2070ea2004-09-04 04:42:29 +00001047 p = realloc(*tag2el, new_count * sizeof(tag2el_t));
vlmfa67ddc2004-06-03 03:38:44 +00001048 if(p) *tag2el = p;
1049 else return -1;
1050
1051 DEBUG("Found tag for %s: %ld",
1052 arg->expr->Identifier,
1053 (long)tag.tag_value);
1054
vlme2070ea2004-09-04 04:42:29 +00001055 te = &((*tag2el)[*count]);
1056 te->el_tag = tag;
1057 te->el_no = el_no;
1058 te->from_expr = arg->expr;
1059 *count = new_count;
vlmfa67ddc2004-06-03 03:38:44 +00001060 return 0;
1061 }
1062
1063 DEBUG("Searching tag in complex expression %s:%x at line %d",
1064 arg->expr->Identifier,
1065 arg->expr->expr_type,
1066 arg->expr->_lineno);
1067
1068 /*
1069 * Iterate over members of CHOICE type.
1070 */
1071 if(arg->expr->expr_type == ASN_CONSTR_CHOICE) {
1072 return _fill_tag2el_map(arg, tag2el, count, el_no);
1073 }
1074
1075 if(arg->expr->expr_type == A1TC_REFERENCE) {
1076 arg_t tmp = *arg;
1077 asn1p_expr_t *expr;
vlmdae7f9d2004-08-22 03:25:24 +00001078 expr = asn1f_lookup_symbol_ex(tmp.asn, tmp.mod, tmp.expr,
vlmfa67ddc2004-06-03 03:38:44 +00001079 arg->expr->reference);
1080 if(expr) {
vlmdae7f9d2004-08-22 03:25:24 +00001081 tmp.mod = expr->module;
vlmfa67ddc2004-06-03 03:38:44 +00001082 tmp.expr = expr;
1083 return _add_tag2el_member(&tmp, tag2el, count, el_no);
1084 } else {
1085 FATAL("Cannot dereference %s at line %d",
1086 arg->expr->Identifier,
1087 arg->expr->_lineno);
1088 return -1;
1089 }
1090 }
1091
1092 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);
vlmfb41dbb2004-09-08 00:28:57 +00001148 INDENT(+1);
1149 if(expr->tag.tag_class) {
1150 tags_count++;
1151 _print_tag(arg, expr, &expr->tag);
1152 if(expr->tag.tag_mode != TM_EXPLICIT)
1153 (*tags_impl_skip)++;
1154 } else {
1155 if(!choice_mode)
1156 (*tags_impl_skip)++;
1157 }
1158 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);
vlm6e73a042004-08-11 07:17:22 +00001169 tags_count++;
vlm4a3f5822004-06-28 21:13:46 +00001170 }
vlmfb41dbb2004-09-08 00:28:57 +00001171 }
1172 OUT("\n");
1173 INDENT(-1);
vlm4a3f5822004-06-28 21:13:46 +00001174 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);
vlm12c8f692004-09-06 08:07:29 +00001304 if(HIDE_INNER_DEFS)
1305 OUT("static /* Use -fall-defs-global to expose */\n");
vlm4e554992004-08-25 02:03:12 +00001306 OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
1307 INDENTED(
1308 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
1309
1310 if(expr->expr_type & ASN_CONSTR_MASK) {
1311 p = asn1c_type_name(arg, arg->expr, TNF_SAFE);
1312 }
1313
1314 OUT("%s_constraint,\n", p);
1315 OUT("%s_decode_ber,\n", p);
1316 OUT("%s_encode_der,\n", p);
1317 OUT("%s_print,\n", p);
1318 OUT("%s_free,\n", p);
1319
1320 p = MKID(expr->Identifier);
1321
1322 if(expr->expr_type == ASN_CONSTR_CHOICE) {
1323 OUT("CHOICE_outmost_tag,\n");
1324 } else {
1325 OUT("0,\t/* Use generic outmost tag fetcher */\n");
1326 }
1327
1328 if(tags_count) {
1329 OUT("asn1_DEF_%s_tags,\n", p);
1330 OUT("sizeof(asn1_DEF_%s_tags)\n", p);
1331 OUT("\t/sizeof(asn1_DEF_%s_tags[0]), /* %d */\n",
1332 p, tags_count);
1333 } else {
1334 OUT("0,\t/* No explicit tags (pointer) */\n");
1335 OUT("0,\t/* No explicit tags (count) */\n");
1336 }
1337
1338 OUT("%d,\t/* Tags to skip */\n", tags_impl_skip);
1339 switch(cp) {
1340 case ETD_CP_UNKNOWN:
1341 OUT("-0,\t/* Unknown yet */\n");
1342 break;
1343 case ETD_CP_EITHER:
1344 OUT("-1,\t/* Primitive or constructed */\n");
1345 case ETD_CP_PRIMITIVE:
1346 OUT("0,\t/* Primitive */\n");
1347 break;
1348 case ETD_CP_CONSTRUCTED:
1349 OUT("1,\t/* Whether CONSTRUCTED */\n");
1350 break;
1351 }
1352
1353 if(elements_count) {
1354 OUT("asn1_MBR_%s,\n", p);
1355 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF
1356 || expr->expr_type == ASN_CONSTR_SET_OF) {
1357 OUT("%d,\t/* Single element */\n",
1358 elements_count);
1359 assert(elements_count == 1);
1360 } else {
1361 OUT("%d,\t/* Elements count */\n",
1362 elements_count);
1363 }
1364 } else {
1365 //if(expr->meta_type == AMT_TYPEREF)
1366 if(expr_elements_count(arg, expr))
1367 OUT("0, 0,\t/* Defined elsewhere */\n");
1368 else
1369 OUT("0, 0,\t/* No members */\n");
1370 }
1371
1372 switch(spec) {
1373 case ETD_NO_SPECIFICS:
1374 OUT("0\t/* No specifics */\n");
1375 break;
1376 case ETD_HAS_SPECIFICS:
1377 OUT("&asn1_DEF_%s_specs\t/* Additional specs */\n", p);
1378 }
1379 );
1380 OUT("};\n");
1381 OUT("\n");
vlme2bb4432004-08-26 06:20:34 +00001382
1383 return 0;
vlm4e554992004-08-25 02:03:12 +00001384}