blob: 8755c2a2ceebe60d88df7c721681cbd6ecf7e312 [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001/*
2 * Don't look into this file. First, because it's a mess, and second, because
3 * it's a brain of the compiler, and you don't wanna mess with brains do you? ;)
4 */
5#include "asn1c_internal.h"
6#include "asn1c_C.h"
Lev Walkin84cd58e2004-08-19 13:29:46 +00007#include "asn1c_constraint.h"
Lev Walkin59004fa2004-08-20 13:37:01 +00008#include "asn1c_out.h"
9#include "asn1c_misc.h"
Lev Walkin84cd58e2004-08-19 13:29:46 +000010#include <asn1fix_export.h> /* Stuff exported by libasn1fix */
Lev Walkinf15320b2004-06-03 03:38:44 +000011
Lev Walkinfd171ef2004-06-06 07:20:17 +000012typedef struct tag2el_s {
13 struct asn1p_type_tag_s el_tag;
14 int el_no;
Lev Walkin38abe792004-06-14 13:09:45 +000015 int toff_first;
16 int toff_last;
Lev Walkinfd171ef2004-06-06 07:20:17 +000017 asn1p_expr_t *from_expr;
18} tag2el_t;
19
20static int _fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no);
21static int _add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no);
22
Lev Walkinf15320b2004-06-03 03:38:44 +000023static int asn1c_lang_C_type_SEQUENCE_def(arg_t *arg);
24static int asn1c_lang_C_type_SET_def(arg_t *arg);
25static int asn1c_lang_C_type_CHOICE_def(arg_t *arg);
26static int asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of);
Lev Walkinc3e29402004-09-10 06:07:18 +000027static int _print_tag(arg_t *arg, struct asn1p_type_tag_s *tag_p);
Lev Walkin35631482004-07-01 00:52:50 +000028static int check_if_extensible(asn1p_expr_t *expr);
Lev Walkincc93b0f2004-09-10 09:18:20 +000029static int expr_better_indirect(arg_t *arg, asn1p_expr_t *expr);
Lev Walkin59964be2004-08-25 02:03:12 +000030static int expr_elements_count(arg_t *arg, asn1p_expr_t *expr);
31static int emit_member_table(arg_t *arg, asn1p_expr_t *expr);
Lev Walkin64399722004-08-11 07:17:22 +000032static int emit_tags_vector(arg_t *arg, asn1p_expr_t *expr, int *tags_impl_skip, int choice_mode);
Lev Walkinfd171ef2004-06-06 07:20:17 +000033static int emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count);
Lev Walkinf15320b2004-06-03 03:38:44 +000034
Lev Walkin59964be2004-08-25 02:03:12 +000035enum etd_cp {
36 ETD_CP_UNKNOWN = -2,
37 ETD_CP_EITHER = -1,
38 ETD_CP_PRIMITIVE = 0,
39 ETD_CP_CONSTRUCTED = 1,
40};
41enum etd_spec {
42 ETD_NO_SPECIFICS,
43 ETD_HAS_SPECIFICS
44};
45static 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);
46
Lev Walkin59004fa2004-08-20 13:37:01 +000047#define C99_MODE (!(arg->flags & A1C_NO_C99))
Lev Walkinf15320b2004-06-03 03:38:44 +000048#define UNNAMED_UNIONS (arg->flags & A1C_UNNAMED_UNIONS)
Lev Walkindd32b592004-09-06 08:07:29 +000049#define HIDE_INNER_DEFS (arg->embed && !(arg->flags & A1C_ALL_DEFS_GLOBAL))
Lev Walkinf15320b2004-06-03 03:38:44 +000050
51#define PCTX_DEF INDENTED( \
52 OUT("\n"); \
53 OUT("/* Context for parsing across buffer boundaries */\n"); \
54 OUT("ber_dec_ctx_t _ber_dec_ctx;\n"));
55
Lev Walkin3dcaafa2004-08-11 05:21:32 +000056#define DEPENDENCIES do { \
Lev Walkin08079b02004-08-22 03:25:24 +000057 asn1p_expr_t *__m; \
58 TQ_FOR(__m, &(expr->members), next) { \
59 if((!(__m->expr_type & ASN_CONSTR_MASK) \
60 && __m->expr_type > ASN_CONSTR_MASK) \
61 || __m->meta_type == AMT_TYPEREF) { \
62 GEN_INCLUDE(asn1c_type_name(arg, \
63 __m, TNF_INCLUDE)); \
Lev Walkin3dcaafa2004-08-11 05:21:32 +000064 } \
65 } \
66 if(expr->expr_type == ASN_CONSTR_SET_OF) \
67 GEN_INCLUDE("asn_SET_OF"); \
68 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF) \
69 GEN_INCLUDE("asn_SEQUENCE_OF"); \
70} while(0)
Lev Walkinf15320b2004-06-03 03:38:44 +000071
72#define MKID(id) asn1c_make_identifier(0, (id), 0)
73
74int
75asn1c_lang_C_type_ENUMERATED(arg_t *arg) {
76 asn1p_expr_t *expr = arg->expr;
77 asn1p_expr_t *v;
78
79 REDIR(OT_DEPS);
80
81 OUT("typedef enum %s {\n", MKID(expr->Identifier));
82 TQ_FOR(v, &(expr->members), next) {
83 switch(v->expr_type) {
84 case A1TC_UNIVERVAL:
85 OUT("\t%s\t= %lld,\n",
86 asn1c_make_identifier(0,
87 expr->Identifier,
88 v->Identifier, 0),
89 v->value->value.v_integer);
90 break;
91 case A1TC_EXTENSIBLE:
92 OUT("\t/*\n");
93 OUT("\t * Enumeration is extensible\n");
94 OUT("\t */\n");
95 break;
96 default:
97 return -1;
98 }
99 }
100 OUT("} %s_e;\n", MKID(expr->Identifier));
101
102 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
103}
104
105
106int
107asn1c_lang_C_type_INTEGER(arg_t *arg) {
108 asn1p_expr_t *expr = arg->expr;
109 asn1p_expr_t *v;
110
111 REDIR(OT_DEPS);
112
113 if(TQ_FIRST(&(expr->members))) {
114 OUT("typedef enum %s {\n", MKID(expr->Identifier));
115 TQ_FOR(v, &(expr->members), next) {
116 switch(v->expr_type) {
117 case A1TC_UNIVERVAL:
118 OUT("\t%s\t= %lld,\n",
119 asn1c_make_identifier(0,
120 expr->Identifier,
121 v->Identifier, 0),
122 v->value->value.v_integer);
123 break;
124 default:
125 return -1;
126 }
127 }
128 OUT("} %s_e;\n", MKID(expr->Identifier));
129 }
130
131 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
132}
133
134int
135asn1c_lang_C_type_SEQUENCE(arg_t *arg) {
136 asn1p_expr_t *expr = arg->expr;
137 asn1p_expr_t *v;
138 int comp_mode = 0; /* {root,ext=1,root,root,...} */
139
140 DEPENDENCIES;
141
142 if(arg->embed) {
Lev Walkin08079b02004-08-22 03:25:24 +0000143 OUT("struct %s {\n", MKID(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +0000144 } else {
145 OUT("typedef struct %s {\n",
146 MKID(expr->Identifier));
147 }
148
149 TQ_FOR(v, &(expr->members), next) {
150 if(v->expr_type == A1TC_EXTENSIBLE) {
151 if(comp_mode < 3) comp_mode++;
152 }
Lev Walkincc93b0f2004-09-10 09:18:20 +0000153 if(comp_mode == 1
154 || expr_better_indirect(arg, v))
155 v->marker |= EM_INDIRECT;
Lev Walkinf15320b2004-06-03 03:38:44 +0000156 EMBED(v);
157 }
158
159 PCTX_DEF;
Lev Walkin08079b02004-08-22 03:25:24 +0000160 OUT("} %s%s%s", expr->marker?"*":"",
161 expr->_anonymous_type ? "" : MKID(expr->Identifier),
162 arg->embed ? "" : "_t");
Lev Walkinf15320b2004-06-03 03:38:44 +0000163
164 return asn1c_lang_C_type_SEQUENCE_def(arg);
165}
166
167static int
168asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
169 asn1p_expr_t *expr = arg->expr;
170 asn1p_expr_t *v;
171 int elements; /* Number of elements */
172 int tags_impl_skip = 0;
173 int comp_mode = 0; /* {root,ext=1,root,root,...} */
174 int ext_start = -1;
175 int ext_stop = -1;
Lev Walkinfd171ef2004-06-06 07:20:17 +0000176 tag2el_t *tag2el = NULL;
177 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000178 int tags_count;
Lev Walkinf15320b2004-06-03 03:38:44 +0000179 char *p;
180
Lev Walkinfd171ef2004-06-06 07:20:17 +0000181 /*
182 * Fetch every inner tag from the tag to elements map.
183 */
184 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
185 if(tag2el) free(tag2el);
186 return -1;
187 }
188
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000189 GEN_INCLUDE("constr_SEQUENCE");
190 if(!arg->embed)
191 GEN_DECLARE(expr); /* asn1_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000192
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000193 REDIR(OT_STAT_DEFS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000194
195 /*
196 * Print out the table according to which the parsing is performed.
197 */
198 p = MKID(expr->Identifier);
Lev Walkin59004fa2004-08-20 13:37:01 +0000199 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000200
201 elements = 0;
202 INDENTED(TQ_FOR(v, &(expr->members), next) {
203 if(v->expr_type == A1TC_EXTENSIBLE) {
204 if((++comp_mode) == 1)
205 ext_start = elements - 1;
206 else
207 ext_stop = elements - 1;
208 continue;
209 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000210 elements++;
Lev Walkin59964be2004-08-25 02:03:12 +0000211 emit_member_table(arg, v);
Lev Walkinf15320b2004-06-03 03:38:44 +0000212 });
213 OUT("};\n");
214
Lev Walkin27ea3802004-06-28 21:13:46 +0000215 /*
216 * Print out asn1_DEF_<type>_tags[] vector.
217 */
Lev Walkin64399722004-08-11 07:17:22 +0000218 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000219
Lev Walkinfd171ef2004-06-06 07:20:17 +0000220 /*
221 * Tags to elements map.
222 */
223 emit_tag2member_map(arg, tag2el, tag2el_count);
224
Lev Walkin27ea3802004-06-28 21:13:46 +0000225 p = MKID(expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000226 OUT("static asn1_SEQUENCE_specifics_t asn1_DEF_%s_specs = {\n", p);
227 INDENTED(
228 OUT("sizeof(struct %s),\n", p);
229 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
Lev Walkinfd171ef2004-06-06 07:20:17 +0000230 OUT("asn1_DEF_%s_tag2el,\n", p);
231 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000232 OUT("%d,\t/* Start extensions */\n",
233 ext_start);
234 OUT("%d\t/* Stop extensions */\n",
235 (ext_stop<ext_start)?elements+1:ext_stop, ext_stop);
236 );
237 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000238
239 /*
240 * Emit asn1_DEF_xxx table.
241 */
242 emit_type_DEF(arg, expr, tags_count, tags_impl_skip, elements,
243 ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000244
Lev Walkinf15320b2004-06-03 03:38:44 +0000245 REDIR(OT_TYPE_DECLS);
246
247 return 0;
248}
249
250int
Lev Walkinf15320b2004-06-03 03:38:44 +0000251asn1c_lang_C_type_SET(arg_t *arg) {
252 asn1p_expr_t *expr = arg->expr;
253 asn1p_expr_t *v;
254 long mcount;
255 char *id;
256 int comp_mode = 0; /* {root,ext=1,root,root,...} */
257
258 DEPENDENCIES;
259
260 REDIR(OT_DEPS);
261
262 OUT("\n");
263 OUT("/*\n");
264 OUT(" * Method of determining the components presence\n");
265 OUT(" */\n");
266 mcount = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000267 OUT("typedef enum %s_PR {\n", MKID(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +0000268 TQ_FOR(v, &(expr->members), next) {
269 if(v->expr_type == A1TC_EXTENSIBLE) continue;
270 INDENTED(
271 id = MKID(expr->Identifier);
272 OUT("%s_PR_", id);
273 id = MKID(v->Identifier);
274 OUT("%s,\t/* Member %s is present */\n",
275 id, id)
276 );
277 mcount++;
278 }
Lev Walkin64399722004-08-11 07:17:22 +0000279 id = MKID(expr->Identifier);
280 OUT("} %s_PR;\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000281
282 REDIR(OT_TYPE_DECLS);
283
284 if(arg->embed) {
Lev Walkin64399722004-08-11 07:17:22 +0000285 OUT("struct %s {\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000286 } else {
Lev Walkin64399722004-08-11 07:17:22 +0000287 OUT("typedef struct %s {\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000288 }
289
290 TQ_FOR(v, &(expr->members), next) {
291 if(v->expr_type == A1TC_EXTENSIBLE) {
292 if(comp_mode < 3) comp_mode++;
293 }
Lev Walkincc93b0f2004-09-10 09:18:20 +0000294 if(comp_mode == 1
295 || expr_better_indirect(arg, v))
296 v->marker |= EM_INDIRECT;
Lev Walkinf15320b2004-06-03 03:38:44 +0000297 EMBED(v);
298 }
299
300 INDENTED(
301 id = MKID(expr->Identifier);
302 OUT("\n");
303 OUT("/* Presence bitmask: ASN_SET_ISPRESENT(p%s, %s_PR_x) */\n",
304 id, id);
305 OUT("unsigned int _presence_map\n");
306 OUT("\t[((%ld+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))];\n", mcount);
307 );
308
309 PCTX_DEF;
Lev Walkin08079b02004-08-22 03:25:24 +0000310 OUT("} %s%s%s", expr->marker?"*":"",
311 expr->_anonymous_type ? "" : MKID(expr->Identifier),
312 arg->embed ? "" : "_t");
Lev Walkinf15320b2004-06-03 03:38:44 +0000313
314 return asn1c_lang_C_type_SET_def(arg);
315}
316
Lev Walkinf15320b2004-06-03 03:38:44 +0000317static int
318asn1c_lang_C_type_SET_def(arg_t *arg) {
319 asn1p_expr_t *expr = arg->expr;
320 asn1p_expr_t *v;
321 int elements;
322 int tags_impl_skip = 0;
323 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Lev Walkinf15320b2004-06-03 03:38:44 +0000324 tag2el_t *tag2el = NULL;
325 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000326 int tags_count;
Lev Walkinf15320b2004-06-03 03:38:44 +0000327 char *p;
328
329 /*
330 * Fetch every inner tag from the tag to elements map.
331 */
332 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
333 if(tag2el) free(tag2el);
334 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000335 }
336
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000337 GEN_INCLUDE("constr_SET");
338 if(!arg->embed)
339 GEN_DECLARE(expr); /* asn1_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000340
341 REDIR(OT_STAT_DEFS);
342
Lev Walkinf15320b2004-06-03 03:38:44 +0000343 /*
344 * Print out the table according to which the parsing is performed.
345 */
346 p = MKID(expr->Identifier);
Lev Walkin59004fa2004-08-20 13:37:01 +0000347 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000348
349 elements = 0;
350 INDENTED(TQ_FOR(v, &(expr->members), next) {
Lev Walkincc93b0f2004-09-10 09:18:20 +0000351 if(v->expr_type == A1TC_EXTENSIBLE) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000352 if(comp_mode < 3) comp_mode++;
Lev Walkincc93b0f2004-09-10 09:18:20 +0000353 } else {
354 if(comp_mode == 1
355 || expr_better_indirect(arg, v))
356 v->marker |= EM_INDIRECT;
357 elements++;
358 emit_member_table(arg, v);
Lev Walkinf15320b2004-06-03 03:38:44 +0000359 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000360 });
361 OUT("};\n");
362
Lev Walkin27ea3802004-06-28 21:13:46 +0000363 /*
364 * Print out asn1_DEF_<type>_tags[] vector.
365 */
Lev Walkin64399722004-08-11 07:17:22 +0000366 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000367
368 /*
369 * Tags to elements map.
370 */
Lev Walkinfd171ef2004-06-06 07:20:17 +0000371 emit_tag2member_map(arg, tag2el, tag2el_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000372
373 /*
374 * Emit a map of mandatory elements.
375 */
Lev Walkin27ea3802004-06-28 21:13:46 +0000376 p = MKID(expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000377 OUT("static uint8_t asn1_DEF_%s_mmap", p);
378 OUT("[(%d + (8 * sizeof(unsigned int)) - 1) / 8]", elements);
379 OUT(" = {\n", p);
380 INDENTED(
381 if(elements) {
382 int delimit = 0;
383 int el = 0;
384 TQ_FOR(v, &(expr->members), next) {
385 if(v->expr_type == A1TC_EXTENSIBLE) continue;
386 if(delimit) {
387 OUT(",\n");
388 delimit = 0;
389 } else if(el) {
390 OUT(" | ");
391 }
Lev Walkincc93b0f2004-09-10 09:18:20 +0000392 OUT("(%d << %d)",
393 v->marker?0:1,
394 7 - (el % 8));
Lev Walkinf15320b2004-06-03 03:38:44 +0000395 if(el && (el % 8) == 0)
396 delimit = 1;
397 el++;
398 }
399 } else {
400 OUT("0");
401 }
402 );
403 OUT("\n");
404 OUT("};\n");
405
406 OUT("static asn1_SET_specifics_t asn1_DEF_%s_specs = {\n", p);
407 INDENTED(
408 OUT("sizeof(struct %s),\n", p);
409 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
410 OUT("offsetof(struct %s, _presence_map),\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000411 OUT("asn1_DEF_%s_tag2el,\n", p);
412 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
Lev Walkin35631482004-07-01 00:52:50 +0000413 OUT("%d,\t/* Whether extensible */\n",
414 check_if_extensible(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +0000415 OUT("(unsigned int *)asn1_DEF_%s_mmap\t/* Mandatory elements map */\n", p);
416 );
417 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000418
419 /*
420 * Emit asn1_DEF_xxx table.
421 */
422 emit_type_DEF(arg, expr, tags_count, tags_impl_skip, elements,
423 ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000424
Lev Walkinf15320b2004-06-03 03:38:44 +0000425 REDIR(OT_TYPE_DECLS);
426
427 return 0;
428}
429
430int
Lev Walkin08079b02004-08-22 03:25:24 +0000431asn1c_lang_C_type_SEx_OF(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000432 asn1p_expr_t *expr = arg->expr;
Lev Walkin08079b02004-08-22 03:25:24 +0000433 asn1p_expr_t *memb;
Lev Walkinf15320b2004-06-03 03:38:44 +0000434
435 DEPENDENCIES;
436
437 if(arg->embed) {
438 OUT("struct %s {\n", MKID(expr->Identifier));
439 } else {
Lev Walkin08079b02004-08-22 03:25:24 +0000440 OUT("typedef struct %s {\n", MKID(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +0000441 }
442
Lev Walkin08079b02004-08-22 03:25:24 +0000443 memb = TQ_FIRST(&expr->members);
444
445 INDENT(+1);
446 OUT("A_%s_OF(",
447 (arg->expr->expr_type == ASN_CONSTR_SET_OF)
448 ? "SET" : "SEQUENCE");
449 if(memb->expr_type & ASN_CONSTR_MASK) {
450 arg_t tmp;
451 asn1p_expr_t tmp_memb;
452 arg->embed++;
453 tmp = *arg;
454 tmp.expr = &tmp_memb;
455 tmp_memb = *memb;
456 tmp_memb._anonymous_type = 1;
457 tmp_memb.Identifier = strdup(
458 asn1c_make_identifier(0,
459 expr->Identifier, "member", 0));
460 assert(tmp_memb.Identifier);
461 tmp.default_cb(&tmp);
462 free(tmp_memb.Identifier);
463 arg->embed--;
464 assert(arg->target->target == OT_TYPE_DECLS);
465 } else {
466 OUT("%s", asn1c_type_name(arg, memb, TNF_RSAFE));
Lev Walkinf15320b2004-06-03 03:38:44 +0000467 }
Lev Walkin08079b02004-08-22 03:25:24 +0000468 OUT(") list;\n");
469 INDENT(-1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000470
471 PCTX_DEF;
Lev Walkin08079b02004-08-22 03:25:24 +0000472 OUT("} %s%s%s", expr->marker?"*":"",
473 expr->_anonymous_type ? "" : MKID(expr->Identifier),
474 arg->embed ? "" : "_t");
Lev Walkinf15320b2004-06-03 03:38:44 +0000475
476 /*
Lev Walkin08079b02004-08-22 03:25:24 +0000477 * SET OF/SEQUENCE OF definition
Lev Walkinf15320b2004-06-03 03:38:44 +0000478 */
Lev Walkin08079b02004-08-22 03:25:24 +0000479 return asn1c_lang_C_type_SEx_OF_def(arg,
480 (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF));
Lev Walkinf15320b2004-06-03 03:38:44 +0000481}
482
483static int
484asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
485 asn1p_expr_t *expr = arg->expr;
486 asn1p_expr_t *v;
487 int tags_impl_skip = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000488 int tags_count;
Lev Walkinf15320b2004-06-03 03:38:44 +0000489 char *p;
490
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000491 /*
492 * Print out the table according to which the parsing is performed.
493 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000494 if(seq_of) {
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000495 GEN_INCLUDE("constr_SEQUENCE_OF");
Lev Walkinf15320b2004-06-03 03:38:44 +0000496 } else {
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000497 GEN_INCLUDE("constr_SET_OF");
Lev Walkinf15320b2004-06-03 03:38:44 +0000498 }
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000499 if(!arg->embed)
500 GEN_DECLARE(expr); /* asn1_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000501
502 REDIR(OT_STAT_DEFS);
503
504 /*
505 * Print out the table according to which the parsing is performed.
506 */
507 p = MKID(expr->Identifier);
Lev Walkin59004fa2004-08-20 13:37:01 +0000508 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000509
Lev Walkin59004fa2004-08-20 13:37:01 +0000510 INDENTED(
Lev Walkinf15320b2004-06-03 03:38:44 +0000511 v = TQ_FIRST(&(expr->members));
Lev Walkin59964be2004-08-25 02:03:12 +0000512 emit_member_table(arg, v);
Lev Walkinf15320b2004-06-03 03:38:44 +0000513 );
514 OUT("};\n");
515
Lev Walkin27ea3802004-06-28 21:13:46 +0000516 /*
517 * Print out asn1_DEF_<type>_tags[] vector.
518 */
Lev Walkin64399722004-08-11 07:17:22 +0000519 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000520
Lev Walkin27ea3802004-06-28 21:13:46 +0000521 p = MKID(expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000522 OUT("static asn1_SET_OF_specifics_t asn1_DEF_%s_specs = {\n", p);
523 INDENTED(
524 OUT("sizeof(struct %s),\n", p);
525 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000526 );
527 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000528
529 /*
530 * Emit asn1_DEF_xxx table.
531 */
532 emit_type_DEF(arg, expr, tags_count, tags_impl_skip, 1,
533 ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000534
Lev Walkinf15320b2004-06-03 03:38:44 +0000535 REDIR(OT_TYPE_DECLS);
536
537 return 0;
538}
539
540int
541asn1c_lang_C_type_CHOICE(arg_t *arg) {
542 asn1p_expr_t *expr = arg->expr;
543 asn1p_expr_t *v;
Lev Walkin08079b02004-08-22 03:25:24 +0000544 char *id;
Lev Walkinf15320b2004-06-03 03:38:44 +0000545
546 DEPENDENCIES;
547
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000548 REDIR(OT_DEPS);
549
Lev Walkin08079b02004-08-22 03:25:24 +0000550 id = MKID(expr->Identifier);
551 OUT("typedef enum %s_PR {\n", id);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000552 INDENTED(
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000553 OUT("%s_PR_NOTHING,\t"
Lev Walkin08079b02004-08-22 03:25:24 +0000554 "/* No components present */\n", id);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000555 TQ_FOR(v, &(expr->members), next) {
556 if(v->expr_type == A1TC_EXTENSIBLE) {
557 OUT("/* Extensions may appear below */\n");
558 continue;
559 }
Lev Walkin08079b02004-08-22 03:25:24 +0000560 id = MKID(expr->Identifier);
561 OUT("%s_PR_", id);
562 id = MKID(v->Identifier);
563 OUT("%s,\n", id, id);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000564 }
565 );
Lev Walkin08079b02004-08-22 03:25:24 +0000566 id = MKID(expr->Identifier);
567 OUT("} %s_PR;\n", id);
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000568
569 REDIR(OT_TYPE_DECLS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000570
571 if(arg->embed) {
Lev Walkin08079b02004-08-22 03:25:24 +0000572 OUT("struct %s {\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000573 } else {
Lev Walkin08079b02004-08-22 03:25:24 +0000574 OUT("typedef struct %s {\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000575 }
576
577 INDENTED(
Lev Walkin08079b02004-08-22 03:25:24 +0000578 OUT("%s_PR present;\n", id);
579 OUT("union {\n", id);
Lev Walkinf15320b2004-06-03 03:38:44 +0000580 TQ_FOR(v, &(expr->members), next) {
Lev Walkincc93b0f2004-09-10 09:18:20 +0000581 if(expr_better_indirect(arg, v))
582 v->marker |= EM_INDIRECT;
Lev Walkinf15320b2004-06-03 03:38:44 +0000583 EMBED(v);
584 }
585 if(UNNAMED_UNIONS) OUT("};\n");
586 else OUT("} choice;\n");
587 );
588
589 PCTX_DEF;
Lev Walkin08079b02004-08-22 03:25:24 +0000590 OUT("} %s%s%s", expr->marker?"*":"",
591 expr->_anonymous_type ? "" : MKID(expr->Identifier),
592 arg->embed ? "" : "_t");
Lev Walkinf15320b2004-06-03 03:38:44 +0000593
594 return asn1c_lang_C_type_CHOICE_def(arg);
595}
596
597static int
598asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
599 asn1p_expr_t *expr = arg->expr;
600 asn1p_expr_t *v;
601 int elements; /* Number of elements */
602 int tags_impl_skip = 0;
603 int comp_mode = 0; /* {root,ext=1,root,root,...} */
Lev Walkinf15320b2004-06-03 03:38:44 +0000604 tag2el_t *tag2el = NULL;
605 int tag2el_count = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000606 int tags_count;
Lev Walkinf15320b2004-06-03 03:38:44 +0000607 char *p;
608
609 /*
610 * Fetch every inner tag from the tag to elements map.
611 */
612 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
613 if(tag2el) free(tag2el);
614 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000615 }
616
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000617 GEN_INCLUDE("constr_CHOICE");
618 if(!arg->embed)
619 GEN_DECLARE(expr); /* asn1_DEF_xxx */
Lev Walkinf15320b2004-06-03 03:38:44 +0000620
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000621 REDIR(OT_STAT_DEFS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000622
623 /*
624 * Print out the table according to which the parsing is performed.
625 */
626 p = MKID(expr->Identifier);
Lev Walkin59004fa2004-08-20 13:37:01 +0000627 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000628
629 elements = 0;
630 INDENTED(TQ_FOR(v, &(expr->members), next) {
Lev Walkincc93b0f2004-09-10 09:18:20 +0000631 if(v->expr_type == A1TC_EXTENSIBLE) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000632 if(comp_mode < 3) comp_mode++;
Lev Walkincc93b0f2004-09-10 09:18:20 +0000633 } else {
634 if(comp_mode == 1
635 || expr_better_indirect(arg, v))
636 v->marker |= EM_INDIRECT;
637 elements++;
638 emit_member_table(arg, v);
Lev Walkinf15320b2004-06-03 03:38:44 +0000639 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000640 });
641 OUT("};\n");
642
Lev Walkin64399722004-08-11 07:17:22 +0000643
Lev Walkinf15320b2004-06-03 03:38:44 +0000644 if(arg->embed) {
645 /*
646 * Our parent structure has already taken this into account.
647 */
Lev Walkin64399722004-08-11 07:17:22 +0000648 tags_count = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000649 } else {
Lev Walkin64399722004-08-11 07:17:22 +0000650 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000651 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000652
653 /*
654 * Tags to elements map.
655 */
Lev Walkinfd171ef2004-06-06 07:20:17 +0000656 emit_tag2member_map(arg, tag2el, tag2el_count);
Lev Walkinf15320b2004-06-03 03:38:44 +0000657
Lev Walkin64399722004-08-11 07:17:22 +0000658 p = MKID(expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000659 OUT("static asn1_CHOICE_specifics_t asn1_DEF_%s_specs = {\n", p);
660 INDENTED(
661 OUT("sizeof(struct %s),\n", p);
662 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
663 OUT("offsetof(struct %s, present),\n", p);
664 OUT("sizeof(((struct %s *)0)->present),\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000665 OUT("asn1_DEF_%s_tag2el,\n", p);
666 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
Lev Walkin35631482004-07-01 00:52:50 +0000667 OUT("%d\t/* Whether extensible */\n",
668 check_if_extensible(expr));
Lev Walkinf15320b2004-06-03 03:38:44 +0000669 );
670 OUT("};\n");
Lev Walkin59964be2004-08-25 02:03:12 +0000671
672 /*
673 * Emit asn1_DEF_xxx table.
674 */
675 emit_type_DEF(arg, expr, tags_count, tags_impl_skip, elements,
676 ETD_CP_CONSTRUCTED /*either?!*/, ETD_HAS_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000677
Lev Walkinf15320b2004-06-03 03:38:44 +0000678 REDIR(OT_TYPE_DECLS);
679
680 return 0;
681}
682
683int
684asn1c_lang_C_type_REFERENCE(arg_t *arg) {
685 asn1p_ref_t *ref;
686
687 ref = arg->expr->reference;
688 if(ref->components[ref->comp_count-1].name[0] == '&') {
Lev Walkinf15320b2004-06-03 03:38:44 +0000689 asn1p_expr_t *extract;
690 arg_t tmp;
691 int ret;
692
Lev Walkin08079b02004-08-22 03:25:24 +0000693 extract = asn1f_class_access_ex(arg->asn, arg->mod,
694 arg->expr, ref);
Lev Walkinf15320b2004-06-03 03:38:44 +0000695 if(extract == NULL)
696 return -1;
697
Lev Walkin08079b02004-08-22 03:25:24 +0000698 extract = asn1p_expr_clone(extract, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000699 if(extract) {
700 if(extract->Identifier)
701 free(extract->Identifier);
702 extract->Identifier = strdup(arg->expr->Identifier);
703 if(extract->Identifier == NULL) {
704 asn1p_expr_free(extract);
705 return -1;
706 }
707 } else {
708 return -1;
709 }
710
711 tmp = *arg;
712 tmp.asn = arg->asn;
Lev Walkin08079b02004-08-22 03:25:24 +0000713 tmp.mod = extract->module;
Lev Walkinf15320b2004-06-03 03:38:44 +0000714 tmp.expr = extract;
715
716 ret = arg->default_cb(&tmp);
717
718 asn1p_expr_free(extract);
719
720 return ret;
721 }
722
723
724 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
725}
726
727int
728asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
729 asn1p_expr_t *expr = arg->expr;
730 int tags_impl_skip = 0;
Lev Walkin64399722004-08-11 07:17:22 +0000731 int tags_count;
Lev Walkinf15320b2004-06-03 03:38:44 +0000732 char *p;
733
734 if(arg->embed) {
735 REDIR(OT_TYPE_DECLS);
736
737 OUT("%s\t", asn1c_type_name(arg, arg->expr,
738 expr->marker?TNF_RSAFE:TNF_CTYPE));
739 OUT("%s", expr->marker?"*":" ");
Lev Walkin08079b02004-08-22 03:25:24 +0000740 OUT("%s", MKID(expr->Identifier));
Lev Walkincc93b0f2004-09-10 09:18:20 +0000741 if((expr->marker & EM_DEFAULT) == EM_DEFAULT)
742 OUT("\t/* DEFAULT */");
743 else if((expr->marker & EM_OPTIONAL) == EM_OPTIONAL)
744 OUT("\t/* OPTIONAL */");
Lev Walkin59004fa2004-08-20 13:37:01 +0000745
746 REDIR(OT_TYPE_DECLS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000747 return 0;
748 }
749
Lev Walkinf15320b2004-06-03 03:38:44 +0000750
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000751 GEN_INCLUDE(asn1c_type_name(arg, expr, TNF_INCLUDE));
Lev Walkinf15320b2004-06-03 03:38:44 +0000752
753 REDIR(OT_TYPE_DECLS);
754
755 OUT("typedef %s\t", asn1c_type_name(arg, arg->expr, TNF_CTYPE));
756 OUT("%s", expr->marker?"*":" ");
Lev Walkin08079b02004-08-22 03:25:24 +0000757 OUT("%s_t", MKID(expr->Identifier));
Lev Walkinf15320b2004-06-03 03:38:44 +0000758
759 REDIR(OT_STAT_DEFS);
760
Lev Walkin27ea3802004-06-28 21:13:46 +0000761 /*
762 * Print out asn1_DEF_<type>_tags[] vector.
763 */
Lev Walkin64399722004-08-11 07:17:22 +0000764 tags_count = emit_tags_vector(arg, expr, &tags_impl_skip, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000765
Lev Walkin59964be2004-08-25 02:03:12 +0000766 emit_type_DEF(arg, expr, tags_count, tags_impl_skip, 0,
767 ETD_CP_UNKNOWN, ETD_NO_SPECIFICS);
Lev Walkinf15320b2004-06-03 03:38:44 +0000768
Lev Walkin59004fa2004-08-20 13:37:01 +0000769 REDIR(OT_CODE);
770
Lev Walkinf15320b2004-06-03 03:38:44 +0000771 /*
772 * Constraint checking.
773 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000774 p = MKID(expr->Identifier);
775 OUT("int\n");
776 OUT("%s_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,\n", p);
777 INDENTED(
778 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
779 OUT("\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000780 if(asn1c_emit_constraint_checking_code(arg) == 1) {
781 if(0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000782 OUT("/* Check the constraints of the underlying type */\n");
783 OUT("return asn1_DEF_%s.check_constraints\n",
784 asn1c_type_name(arg, expr, TNF_SAFE));
785 OUT("\t(td, sptr, app_errlog, app_key);\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000786 } else {
Lev Walkinf15320b2004-06-03 03:38:44 +0000787 OUT("/* Make the underlying type checker permanent */\n");
788 OUT("td->check_constraints = asn1_DEF_%s.check_constraints;\n",
789 asn1c_type_name(arg, expr, TNF_SAFE));
790 OUT("return td->check_constraints\n");
791 OUT("\t(td, sptr, app_errlog, app_key);\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000792 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000793 }
794 );
795 OUT("}\n");
796 OUT("\n");
797
798 /*
799 * Emit suicidal functions.
800 */
801
Lev Walkinf15320b2004-06-03 03:38:44 +0000802 /*
803 * This function replaces certain fields from the definition
804 * of a type with the corresponding fields from the basic type
805 * (from which the current type is inherited).
806 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000807 OUT("/*\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000808 OUT(" * This type is implemented using %s,\n",
809 asn1c_type_name(arg, expr, TNF_SAFE));
Lev Walkinf15320b2004-06-03 03:38:44 +0000810 OUT(" * so adjust the DEF appropriately.\n");
811 OUT(" */\n");
812 OUT("static void\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000813 p = MKID(expr->Identifier);
814 OUT("%s_inherit_TYPE_descriptor(asn1_TYPE_descriptor_t *td) {\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000815 INDENT(+1);
Lev Walkin59004fa2004-08-20 13:37:01 +0000816 {
817 char *type_name = asn1c_type_name(arg, expr, TNF_SAFE);
818 OUT("td->ber_decoder = asn1_DEF_%s.ber_decoder;\n", type_name);
819 OUT("td->der_encoder = asn1_DEF_%s.der_encoder;\n", type_name);
820 OUT("td->free_struct = asn1_DEF_%s.free_struct;\n", type_name);
821 OUT("td->print_struct = asn1_DEF_%s.print_struct;\n", type_name);
822 OUT("td->last_tag_form = asn1_DEF_%s.last_tag_form;\n", type_name);
823 OUT("td->elements = asn1_DEF_%s.elements;\n", type_name);
824 OUT("td->elements_count = asn1_DEF_%s.elements_count;\n", type_name);
825 OUT("td->specifics = asn1_DEF_%s.specifics;\n", type_name);
826 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000827 INDENT(-1);
828 OUT("}\n");
829 OUT("\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000830
831 p = MKID(expr->Identifier);
832 OUT("ber_dec_rval_t\n");
833 OUT("%s_decode_ber(asn1_TYPE_descriptor_t *td,\n", p);
834 INDENTED(
835 OUT("\tvoid **structure, void *bufptr, size_t size, int tag_mode) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000836 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000837 OUT("return td->ber_decoder(td, structure,\n");
838 OUT("\tbufptr, size, tag_mode);\n");
839 );
840 OUT("}\n");
841 OUT("\n");
842
843 p = MKID(expr->Identifier);
844 OUT("der_enc_rval_t\n");
845 OUT("%s_encode_der(asn1_TYPE_descriptor_t *td,\n", p);
846 INDENTED(
847 OUT("\tvoid *structure, int tag_mode, ber_tlv_tag_t tag,\n");
848 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000849 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000850 OUT("return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);\n");
851 );
852 OUT("}\n");
853 OUT("\n");
854
855 p = MKID(expr->Identifier);
856 OUT("int\n");
857 OUT("%s_print(asn1_TYPE_descriptor_t *td, const void *struct_ptr,\n", p);
858 INDENTED(
859 OUT("\tint ilevel, asn_app_consume_bytes_f *cb, void *app_key) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000860 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000861 OUT("return td->print_struct(td, struct_ptr, ilevel, cb, app_key);\n");
862 );
863 OUT("}\n");
864 OUT("\n");
865
866 p = MKID(expr->Identifier);
867 OUT("void\n");
868 OUT("%s_free(asn1_TYPE_descriptor_t *td,\n", p);
869 INDENTED(
870 OUT("\tvoid *struct_ptr, int contents_only) {\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000871 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
Lev Walkinf15320b2004-06-03 03:38:44 +0000872 OUT("td->free_struct(td, struct_ptr, contents_only);\n");
873 );
874 OUT("}\n");
875 OUT("\n");
876
877 REDIR(OT_FUNC_DECLS);
878
879 p = MKID(expr->Identifier);
Lev Walkindd32b592004-09-06 08:07:29 +0000880 if(HIDE_INNER_DEFS) OUT("/* ");
881 OUT("extern asn1_TYPE_descriptor_t asn1_DEF_%s;", p);
882 if(HIDE_INNER_DEFS) OUT(" // (Use -fall-defs-global to expose) */");
883 OUT("\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000884 OUT("asn_constr_check_f %s_constraint;\n", p);
885 OUT("ber_type_decoder_f %s_decode_ber;\n", p);
886 OUT("der_type_encoder_f %s_encode_der;\n", p);
887 OUT("asn_struct_print_f %s_print;\n", p);
888 OUT("asn_struct_free_f %s_free;\n", p);
889
Lev Walkin3dcaafa2004-08-11 05:21:32 +0000890 REDIR(OT_TYPE_DECLS);
891
Lev Walkinf15320b2004-06-03 03:38:44 +0000892 return 0;
893}
894
895int
896asn1c_lang_C_type_EXTENSIBLE(arg_t *arg) {
897
898 OUT("/*\n");
899 OUT(" * This type is extensible,\n");
900 OUT(" * possible extensions are below.\n");
901 OUT(" */\n");
902
903 return 0;
904}
905
Lev Walkin35631482004-07-01 00:52:50 +0000906static int check_if_extensible(asn1p_expr_t *expr) {
907 asn1p_expr_t *v;
908 TQ_FOR(v, &(expr->members), next) {
909 if(v->expr_type == A1TC_EXTENSIBLE) return 1;
910 }
911 return 0;
912}
913
Lev Walkinf15320b2004-06-03 03:38:44 +0000914static int
Lev Walkinc3e29402004-09-10 06:07:18 +0000915_print_tag(arg_t *arg, struct asn1p_type_tag_s *tag) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000916
917 OUT("(");
Lev Walkinc3e29402004-09-10 06:07:18 +0000918 switch(tag->tag_class) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000919 case TC_UNIVERSAL: OUT("ASN_TAG_CLASS_UNIVERSAL"); break;
920 case TC_APPLICATION: OUT("ASN_TAG_CLASS_APPLICATION"); break;
921 case TC_CONTEXT_SPECIFIC: OUT("ASN_TAG_CLASS_CONTEXT"); break;
922 case TC_PRIVATE: OUT("ASN_TAG_CLASS_PRIVATE"); break;
923 case TC_NOCLASS:
924 break;
925 }
Lev Walkinc3e29402004-09-10 06:07:18 +0000926 OUT(" | (%lld << 2))", tag->tag_value);
Lev Walkinf15320b2004-06-03 03:38:44 +0000927
928 return 0;
929}
930
Lev Walkinfd171ef2004-06-06 07:20:17 +0000931
932static int
933_tag2el_cmp(const void *ap, const void *bp) {
934 const tag2el_t *a = ap;
935 const tag2el_t *b = bp;
936 const struct asn1p_type_tag_s *ta = &a->el_tag;
937 const struct asn1p_type_tag_s *tb = &b->el_tag;
938
939 if(ta->tag_class == tb->tag_class) {
940 if(ta->tag_value == tb->tag_value) {
941 /*
942 * Sort by their respective positions.
943 */
944 if(a->el_no < b->el_no)
945 return -1;
946 else if(a->el_no > b->el_no)
947 return 1;
948 return 0;
949 } else if(ta->tag_value < tb->tag_value)
950 return -1;
951 else
952 return 1;
953 } else if(ta->tag_class < tb->tag_class) {
954 return -1;
955 } else {
956 return 1;
957 }
958}
959
Lev Walkinf15320b2004-06-03 03:38:44 +0000960/*
961 * For constructed types, number of external tags may be greater than
962 * number of elements in the type because of CHOICE type.
963 * T ::= SET { -- Three possible tags:
964 * a INTEGER, -- One tag is here...
965 * b Choice1 -- ... and two more tags are there.
966 * }
967 * Choice1 ::= CHOICE {
968 * s1 IA5String,
969 * s2 ObjectDescriptor
970 * }
971 */
972static int
973_fill_tag2el_map(arg_t *arg, tag2el_t **tag2el, int *count, int el_no) {
974 asn1p_expr_t *expr = arg->expr;
975 arg_t tmparg = *arg;
976 asn1p_expr_t *v;
977 int element = 0;
978
979 TQ_FOR(v, &(expr->members), next) {
980 if(v->expr_type == A1TC_EXTENSIBLE)
981 continue;
982
983 tmparg.expr = v;
984
985 if(_add_tag2el_member(&tmparg, tag2el, count,
986 (el_no==-1)?element:el_no)) {
987 return -1;
988 }
989
990 element++;
991 }
992
Lev Walkinfd171ef2004-06-06 07:20:17 +0000993 /*
Lev Walkin38abe792004-06-14 13:09:45 +0000994 * Sort the map according to canonical order of their tags
995 * and element numbers.
Lev Walkinfd171ef2004-06-06 07:20:17 +0000996 */
997 qsort(*tag2el, *count, sizeof(**tag2el), _tag2el_cmp);
998
Lev Walkin38abe792004-06-14 13:09:45 +0000999 /*
1000 * Initialize .toff_{first|last} members.
1001 */
1002 if(*count) {
1003 struct asn1p_type_tag_s *cur_tag = 0;
1004 tag2el_t *cur = *tag2el;
1005 tag2el_t *end = cur + *count;
1006 int occur, i;
1007 for(occur = 0; cur < end; cur++) {
1008 if(cur_tag == 0
1009 || cur_tag->tag_value != cur->el_tag.tag_value
1010 || cur_tag->tag_class != cur->el_tag.tag_class) {
1011 cur_tag = &cur->el_tag;
1012 occur = 0;
1013 } else {
1014 occur++;
1015 }
1016 cur->toff_first = -occur;
1017 for(i = 0; i >= -occur; i--)
1018 cur[i].toff_last = -i;
1019 }
1020 }
1021
Lev Walkinf15320b2004-06-03 03:38:44 +00001022 return 0;
1023}
1024
1025static int
1026_add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no) {
1027 struct asn1p_type_tag_s tag;
1028 int ret;
1029
1030 assert(el_no >= 0);
1031
Lev Walkinc3e29402004-09-10 06:07:18 +00001032 ret = asn1f_fetch_outmost_tag(arg->asn, arg->mod, arg->expr, &tag, 1);
Lev Walkinf15320b2004-06-03 03:38:44 +00001033 if(ret == 0) {
Lev Walkin201943e2004-09-04 04:42:29 +00001034 tag2el_t *te;
1035 int new_count = (*count) + 1;
Lev Walkinf15320b2004-06-03 03:38:44 +00001036 void *p;
Lev Walkin201943e2004-09-04 04:42:29 +00001037
Lev Walkinac7e2292004-09-05 10:42:33 +00001038 if(tag.tag_value == -1) {
1039 /*
1040 * This is an untagged ANY type,
1041 * proceed without adding a tag
1042 */
1043 return 0;
1044 }
1045
Lev Walkin201943e2004-09-04 04:42:29 +00001046 p = realloc(*tag2el, new_count * sizeof(tag2el_t));
Lev Walkinf15320b2004-06-03 03:38:44 +00001047 if(p) *tag2el = p;
1048 else return -1;
1049
1050 DEBUG("Found tag for %s: %ld",
1051 arg->expr->Identifier,
1052 (long)tag.tag_value);
1053
Lev Walkin201943e2004-09-04 04:42:29 +00001054 te = &((*tag2el)[*count]);
1055 te->el_tag = tag;
1056 te->el_no = el_no;
1057 te->from_expr = arg->expr;
1058 *count = new_count;
Lev Walkinf15320b2004-06-03 03:38:44 +00001059 return 0;
1060 }
1061
1062 DEBUG("Searching tag in complex expression %s:%x at line %d",
1063 arg->expr->Identifier,
1064 arg->expr->expr_type,
1065 arg->expr->_lineno);
1066
1067 /*
1068 * Iterate over members of CHOICE type.
1069 */
1070 if(arg->expr->expr_type == ASN_CONSTR_CHOICE) {
1071 return _fill_tag2el_map(arg, tag2el, count, el_no);
1072 }
1073
1074 if(arg->expr->expr_type == A1TC_REFERENCE) {
1075 arg_t tmp = *arg;
1076 asn1p_expr_t *expr;
Lev Walkin08079b02004-08-22 03:25:24 +00001077 expr = asn1f_lookup_symbol_ex(tmp.asn, tmp.mod, tmp.expr,
Lev Walkinf15320b2004-06-03 03:38:44 +00001078 arg->expr->reference);
1079 if(expr) {
Lev Walkin08079b02004-08-22 03:25:24 +00001080 tmp.mod = expr->module;
Lev Walkinf15320b2004-06-03 03:38:44 +00001081 tmp.expr = expr;
1082 return _add_tag2el_member(&tmp, tag2el, count, el_no);
1083 } else {
1084 FATAL("Cannot dereference %s at line %d",
1085 arg->expr->Identifier,
1086 arg->expr->_lineno);
1087 return -1;
1088 }
1089 }
1090
1091 DEBUG("No tag for %s at line %d",
1092 arg->expr->Identifier,
1093 arg->expr->_lineno);
1094
1095 return -1;
1096}
1097
1098static int
Lev Walkinfd171ef2004-06-06 07:20:17 +00001099emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count) {
1100 asn1p_expr_t *expr = arg->expr;
1101
1102 OUT("static asn1_TYPE_tag2member_t asn1_DEF_%s_tag2el[] = {\n",
1103 MKID(expr->Identifier));
1104 if(tag2el_count) {
1105 int i;
1106 for(i = 0; i < tag2el_count; i++) {
1107 OUT(" { ");
Lev Walkinc3e29402004-09-10 06:07:18 +00001108 _print_tag(arg, &tag2el[i].el_tag);
Lev Walkinfd171ef2004-06-06 07:20:17 +00001109 OUT(", ");
Lev Walkin38abe792004-06-14 13:09:45 +00001110 OUT("%d, ", tag2el[i].el_no);
1111 OUT("%d, ", tag2el[i].toff_first);
1112 OUT("%d ", tag2el[i].toff_last);
Lev Walkinfd171ef2004-06-06 07:20:17 +00001113 OUT("}, /* %s at %d */\n",
1114 tag2el[i].from_expr->Identifier,
1115 tag2el[i].from_expr->_lineno
1116 );
1117 }
1118 }
1119 OUT("};\n");
1120
1121 return 0;;
1122}
1123
1124static int
Lev Walkin64399722004-08-11 07:17:22 +00001125emit_tags_vector(arg_t *arg, asn1p_expr_t *expr, int *tags_impl_skip, int choice_mode) {
1126 int tags_count = 0;
1127 int save_target = arg->target->target;
Lev Walkin27ea3802004-06-28 21:13:46 +00001128 char *p;
1129
Lev Walkin64399722004-08-11 07:17:22 +00001130 if(save_target != OT_IGNORE) {
1131 int save_impl_skip = *tags_impl_skip;
1132 REDIR(OT_IGNORE);
1133 tags_count = emit_tags_vector(arg, expr,
1134 tags_impl_skip, choice_mode);
1135 REDIR(save_target);
1136 if(tags_count) {
1137 *tags_impl_skip = save_impl_skip;
1138 tags_count = 0;
1139 } else {
1140 return 0;
1141 }
1142 }
1143
1144
Lev Walkin27ea3802004-06-28 21:13:46 +00001145 p = MKID(expr->Identifier);
1146 OUT("static ber_tlv_tag_t asn1_DEF_%s_tags[] = {\n", p);
Lev Walkin5a8219a2004-09-08 00:28:57 +00001147 INDENT(+1);
1148 if(expr->tag.tag_class) {
1149 tags_count++;
Lev Walkinc3e29402004-09-10 06:07:18 +00001150 _print_tag(arg, &expr->tag);
Lev Walkin5a8219a2004-09-08 00:28:57 +00001151 if(expr->tag.tag_mode != TM_EXPLICIT)
1152 (*tags_impl_skip)++;
1153 } else {
1154 if(!choice_mode)
1155 (*tags_impl_skip)++;
1156 }
1157 if(!choice_mode) {
1158 if(!expr->tag.tag_class
1159 || (expr->meta_type == AMT_TYPE
1160 && expr->tag.tag_mode == TM_EXPLICIT)) {
1161 struct asn1p_type_tag_s tag;
1162 if(expr->tag.tag_class)
1163 OUT(",\n");
1164 tag.tag_class = TC_UNIVERSAL;
1165 tag.tag_mode = TM_IMPLICIT;
1166 tag.tag_value = expr_type2uclass_value[expr->expr_type];
Lev Walkinc3e29402004-09-10 06:07:18 +00001167 _print_tag(arg, &tag);
Lev Walkin64399722004-08-11 07:17:22 +00001168 tags_count++;
Lev Walkin27ea3802004-06-28 21:13:46 +00001169 }
Lev Walkin5a8219a2004-09-08 00:28:57 +00001170 }
1171 OUT("\n");
1172 INDENT(-1);
Lev Walkin27ea3802004-06-28 21:13:46 +00001173 OUT("};\n");
1174
Lev Walkin64399722004-08-11 07:17:22 +00001175 return tags_count;
Lev Walkin27ea3802004-06-28 21:13:46 +00001176}
Lev Walkin59004fa2004-08-20 13:37:01 +00001177
1178static int
Lev Walkin59964be2004-08-25 02:03:12 +00001179expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin59004fa2004-08-20 13:37:01 +00001180 asn1p_expr_t *topmost_parent;
1181 asn1p_expr_t *v;
1182 int elements = 0;
1183
Lev Walkin08079b02004-08-22 03:25:24 +00001184 topmost_parent = asn1f_find_terminal_type_ex(arg->asn, arg->mod, expr);
Lev Walkin59004fa2004-08-20 13:37:01 +00001185 if(!topmost_parent) return 0;
1186
1187 if(!(topmost_parent->expr_type & ASN_CONSTR_MASK))
1188 return 0;
1189
1190 TQ_FOR(v, &(topmost_parent->members), next) {
1191 if(v->expr_type != A1TC_EXTENSIBLE)
1192 elements++;
1193 }
1194
1195 return elements;
1196}
1197
1198static int
Lev Walkin59964be2004-08-25 02:03:12 +00001199emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
Lev Walkin08079b02004-08-22 03:25:24 +00001200 static int global_memb_unique;
Lev Walkin59004fa2004-08-20 13:37:01 +00001201 int save_target;
1202 arg_t tmp_arg;
Lev Walkinc3e29402004-09-10 06:07:18 +00001203 struct asn1p_type_tag_s outmost_tag;
Lev Walkin59004fa2004-08-20 13:37:01 +00001204 char *p;
1205
1206 OUT("{ ");
Lev Walkincc93b0f2004-09-10 09:18:20 +00001207 OUT("%s, ", expr->marker?"ATF_POINTER":"ATF_NOFLAGS");
1208 if((expr->marker & EM_OPTIONAL) == EM_OPTIONAL) {
Lev Walkin59004fa2004-08-20 13:37:01 +00001209 asn1p_expr_t *tv;
1210 int opts = 0;
1211 for(tv = expr; tv && tv->marker;
1212 tv = TQ_NEXT(tv, next), opts++) {
1213 if(tv->expr_type == A1TC_EXTENSIBLE)
1214 opts--;
1215 }
1216 OUT("%d, ", opts);
1217 } else {
1218 OUT("0, ");
1219 }
1220 if(expr->Identifier) {
1221 OUT("offsetof(struct %s, ", MKID(arg->expr->Identifier));
1222 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1223 && (!UNNAMED_UNIONS)) OUT("choice.");
1224 OUT("%s),\n", MKID(expr->Identifier));
1225 } else {
1226 assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
1227 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
1228 OUT("0,\n");
1229 }
1230 INDENT(+1);
1231 if(C99_MODE) OUT(".tag = ");
Lev Walkinc3e29402004-09-10 06:07:18 +00001232 if(asn1f_fetch_outmost_tag(arg->asn,
1233 expr->module, expr, &outmost_tag, 0)) {
1234 OUT("-1 /* Ambiguous tag (CHOICE|ANY?) */");
1235 } else {
1236 _print_tag(arg, &outmost_tag);
1237 }
Lev Walkin59004fa2004-08-20 13:37:01 +00001238 OUT(",\n");
1239 if(C99_MODE) OUT(".tag_mode = ");
1240 if(expr->tag.tag_class) {
1241 if(expr->tag.tag_mode == TM_IMPLICIT)
1242 OUT("-1,\t/* IMPLICIT tag at current level */\n");
1243 else
1244 OUT("+1,\t/* EXPLICIT tag at current level */\n");
1245 } else {
1246 OUT("0,\n");
1247 }
1248 if(C99_MODE) OUT(".type = ");
Lev Walkin08079b02004-08-22 03:25:24 +00001249 if((expr->expr_type & ASN_CONSTR_MASK)
1250 && (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF
1251 || arg->expr->expr_type == ASN_CONSTR_SET_OF)) {
1252 OUT("(void *)&asn1_DEF_%s_member,\n",
1253 MKID(arg->expr->Identifier));
Lev Walkin59964be2004-08-25 02:03:12 +00001254 } else if(expr->expr_type & ASN_CONSTR_MASK) {
1255 OUT("(void *)&asn1_DEF_%s,\n",
1256 MKID(expr->Identifier));
Lev Walkin08079b02004-08-22 03:25:24 +00001257 } else {
1258 OUT("(void *)&asn1_DEF_%s,\n",
1259 asn1c_type_name(arg, expr, TNF_SAFE));
1260 }
Lev Walkin59004fa2004-08-20 13:37:01 +00001261 if(C99_MODE) OUT(".memb_constraints = ");
1262 if(expr->constraints) {
Lev Walkin59964be2004-08-25 02:03:12 +00001263 char *id = MKID(expr->Identifier);
Lev Walkin59004fa2004-08-20 13:37:01 +00001264 if(!expr->Identifier)
Lev Walkin59964be2004-08-25 02:03:12 +00001265 id = asn1c_type_name(arg, expr, TNF_SAFE);
1266 OUT("memb_%s_%d_constraint,\n", id,
Lev Walkin08079b02004-08-22 03:25:24 +00001267 ++global_memb_unique);
Lev Walkin59004fa2004-08-20 13:37:01 +00001268 } else {
1269 OUT("0,\t/* Defer to actual type */\n");
1270 }
1271 if(C99_MODE) OUT(".name = ");
1272 OUT("\"%s\"\n", expr->Identifier ? expr->Identifier : "");
1273 OUT("},\n");
1274 INDENT(-1);
1275
1276 if(!expr->constraints)
1277 return 0;
1278
1279 save_target = arg->target->target;
1280 REDIR(OT_CODE);
1281
1282 if(expr->Identifier)
1283 p = MKID(expr->Identifier);
1284 else
1285 p = asn1c_type_name(arg, expr, TNF_SAFE);
1286 OUT("static int\n");
Lev Walkin08079b02004-08-22 03:25:24 +00001287 OUT("memb_%s_%d_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,\n", p, global_memb_unique);
Lev Walkin59004fa2004-08-20 13:37:01 +00001288 INDENT(+1);
1289 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
1290 tmp_arg = *arg;
1291 tmp_arg.expr = expr;
1292 if(asn1c_emit_constraint_checking_code(&tmp_arg) == 1) {
1293 OUT("return td->check_constraints\n");
1294 OUT("\t(td, sptr, app_errlog, app_key);\n");
1295 }
1296 INDENT(-1);
1297 OUT("}\n");
1298 OUT("\n");
1299
1300 REDIR(save_target);
1301
1302 return 0;
1303}
Lev Walkin59964be2004-08-25 02:03:12 +00001304
1305static int
1306emit_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) {
1307 char *p;
1308
1309 p = MKID(expr->Identifier);
Lev Walkindd32b592004-09-06 08:07:29 +00001310 if(HIDE_INNER_DEFS)
1311 OUT("static /* Use -fall-defs-global to expose */\n");
Lev Walkin59964be2004-08-25 02:03:12 +00001312 OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
1313 INDENTED(
1314 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
1315
1316 if(expr->expr_type & ASN_CONSTR_MASK) {
1317 p = asn1c_type_name(arg, arg->expr, TNF_SAFE);
1318 }
1319
1320 OUT("%s_constraint,\n", p);
1321 OUT("%s_decode_ber,\n", p);
1322 OUT("%s_encode_der,\n", p);
1323 OUT("%s_print,\n", p);
1324 OUT("%s_free,\n", p);
1325
1326 p = MKID(expr->Identifier);
1327
1328 if(expr->expr_type == ASN_CONSTR_CHOICE) {
1329 OUT("CHOICE_outmost_tag,\n");
1330 } else {
1331 OUT("0,\t/* Use generic outmost tag fetcher */\n");
1332 }
1333
1334 if(tags_count) {
1335 OUT("asn1_DEF_%s_tags,\n", p);
1336 OUT("sizeof(asn1_DEF_%s_tags)\n", p);
1337 OUT("\t/sizeof(asn1_DEF_%s_tags[0]), /* %d */\n",
1338 p, tags_count);
1339 } else {
1340 OUT("0,\t/* No explicit tags (pointer) */\n");
1341 OUT("0,\t/* No explicit tags (count) */\n");
1342 }
1343
1344 OUT("%d,\t/* Tags to skip */\n", tags_impl_skip);
1345 switch(cp) {
1346 case ETD_CP_UNKNOWN:
1347 OUT("-0,\t/* Unknown yet */\n");
1348 break;
1349 case ETD_CP_EITHER:
1350 OUT("-1,\t/* Primitive or constructed */\n");
1351 case ETD_CP_PRIMITIVE:
1352 OUT("0,\t/* Primitive */\n");
1353 break;
1354 case ETD_CP_CONSTRUCTED:
1355 OUT("1,\t/* Whether CONSTRUCTED */\n");
1356 break;
1357 }
1358
1359 if(elements_count) {
1360 OUT("asn1_MBR_%s,\n", p);
1361 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF
1362 || expr->expr_type == ASN_CONSTR_SET_OF) {
1363 OUT("%d,\t/* Single element */\n",
1364 elements_count);
1365 assert(elements_count == 1);
1366 } else {
1367 OUT("%d,\t/* Elements count */\n",
1368 elements_count);
1369 }
1370 } else {
1371 //if(expr->meta_type == AMT_TYPEREF)
1372 if(expr_elements_count(arg, expr))
1373 OUT("0, 0,\t/* Defined elsewhere */\n");
1374 else
1375 OUT("0, 0,\t/* No members */\n");
1376 }
1377
1378 switch(spec) {
1379 case ETD_NO_SPECIFICS:
1380 OUT("0\t/* No specifics */\n");
1381 break;
1382 case ETD_HAS_SPECIFICS:
1383 OUT("&asn1_DEF_%s_specs\t/* Additional specs */\n", p);
1384 }
1385 );
1386 OUT("};\n");
1387 OUT("\n");
Lev Walkin97298782004-08-26 06:20:34 +00001388
1389 return 0;
Lev Walkin59964be2004-08-25 02:03:12 +00001390}
Lev Walkincc93b0f2004-09-10 09:18:20 +00001391
1392/*
1393 * Check if it is better to make this type indirectly accessed via
1394 * a pointer.
1395 * This may be the case for the following recursive definition:
1396 * Type ::= CHOICE { member Type };
1397 */
1398static int
1399expr_better_indirect(arg_t *arg, asn1p_expr_t *expr) {
1400 asn1p_expr_t *top_parent;
1401 asn1p_expr_t *terminal;
1402
1403 if(expr->expr_type != A1TC_REFERENCE)
1404 return 0;
1405
1406 /* Rewind to the topmost parent expression */
1407 if((top_parent = expr->parent_expr)) {
1408 while(top_parent->parent_expr)
1409 top_parent = top_parent->parent_expr;
1410 } else {
1411 return 0;
1412 }
1413
1414 terminal = asn1f_find_terminal_type_ex(arg->asn, arg->mod, expr);
1415
1416 return (terminal == top_parent);
1417}