blob: c448795ab513f6e2266f63cff0e1ff1879c9ae62 [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);
vlma8a86cc2004-09-10 06:07:18 +000027static int _print_tag(arg_t *arg, struct asn1p_type_tag_s *tag_p);
vlm79b08d52004-07-01 00:52:50 +000028static int check_if_extensible(asn1p_expr_t *expr);
vlmddd5a7d2004-09-10 09:18:20 +000029static int expr_better_indirect(arg_t *arg, asn1p_expr_t *expr);
vlm4e554992004-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);
vlm1308d2b2004-09-10 15:49:15 +000032static int emit_tags_vector(arg_t *arg, asn1p_expr_t *expr);
vlm4e03ce22004-06-06 07:20:17 +000033static int emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count);
vlmfa67ddc2004-06-03 03:38:44 +000034
vlm4e554992004-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};
vlm1308d2b2004-09-10 15:49:15 +000045static int emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, int tags_count, int elements_count, enum etd_cp, enum etd_spec);
vlm4e554992004-08-25 02:03:12 +000046
vlmb2839012004-08-20 13:37:01 +000047#define C99_MODE (!(arg->flags & A1C_NO_C99))
vlmfa67ddc2004-06-03 03:38:44 +000048#define UNNAMED_UNIONS (arg->flags & A1C_UNNAMED_UNIONS)
vlm12c8f692004-09-06 08:07:29 +000049#define HIDE_INNER_DEFS (arg->embed && !(arg->flags & A1C_ALL_DEFS_GLOBAL))
vlmfa67ddc2004-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
vlm33a4ff12004-08-11 05:21:32 +000056#define DEPENDENCIES do { \
vlmdae7f9d2004-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)); \
vlm33a4ff12004-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)
vlmfa67ddc2004-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) {
vlmdae7f9d2004-08-22 03:25:24 +0000143 OUT("struct %s {\n", MKID(expr->Identifier));
vlmfa67ddc2004-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 }
vlmddd5a7d2004-09-10 09:18:20 +0000153 if(comp_mode == 1
154 || expr_better_indirect(arg, v))
155 v->marker |= EM_INDIRECT;
vlmfa67ddc2004-06-03 03:38:44 +0000156 EMBED(v);
157 }
158
159 PCTX_DEF;
vlmdae7f9d2004-08-22 03:25:24 +0000160 OUT("} %s%s%s", expr->marker?"*":"",
161 expr->_anonymous_type ? "" : MKID(expr->Identifier),
162 arg->embed ? "" : "_t");
vlmfa67ddc2004-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 */
vlmfa67ddc2004-06-03 03:38:44 +0000172 int comp_mode = 0; /* {root,ext=1,root,root,...} */
173 int ext_start = -1;
174 int ext_stop = -1;
vlm4e03ce22004-06-06 07:20:17 +0000175 tag2el_t *tag2el = NULL;
176 int tag2el_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000177 int tags_count;
vlmfa67ddc2004-06-03 03:38:44 +0000178 char *p;
179
vlm4e03ce22004-06-06 07:20:17 +0000180 /*
181 * Fetch every inner tag from the tag to elements map.
182 */
183 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
184 if(tag2el) free(tag2el);
185 return -1;
186 }
187
vlm33a4ff12004-08-11 05:21:32 +0000188 GEN_INCLUDE("constr_SEQUENCE");
189 if(!arg->embed)
190 GEN_DECLARE(expr); /* asn1_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000191
vlm33a4ff12004-08-11 05:21:32 +0000192 REDIR(OT_STAT_DEFS);
vlmfa67ddc2004-06-03 03:38:44 +0000193
194 /*
195 * Print out the table according to which the parsing is performed.
196 */
197 p = MKID(expr->Identifier);
vlmb2839012004-08-20 13:37:01 +0000198 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000199
200 elements = 0;
201 INDENTED(TQ_FOR(v, &(expr->members), next) {
202 if(v->expr_type == A1TC_EXTENSIBLE) {
203 if((++comp_mode) == 1)
204 ext_start = elements - 1;
205 else
206 ext_stop = elements - 1;
207 continue;
208 }
vlmfa67ddc2004-06-03 03:38:44 +0000209 elements++;
vlm4e554992004-08-25 02:03:12 +0000210 emit_member_table(arg, v);
vlmfa67ddc2004-06-03 03:38:44 +0000211 });
212 OUT("};\n");
213
vlm4a3f5822004-06-28 21:13:46 +0000214 /*
215 * Print out asn1_DEF_<type>_tags[] vector.
216 */
vlm1308d2b2004-09-10 15:49:15 +0000217 tags_count = emit_tags_vector(arg, expr);
vlmfa67ddc2004-06-03 03:38:44 +0000218
vlm4e03ce22004-06-06 07:20:17 +0000219 /*
220 * Tags to elements map.
221 */
222 emit_tag2member_map(arg, tag2el, tag2el_count);
223
vlm4a3f5822004-06-28 21:13:46 +0000224 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000225 OUT("static asn1_SEQUENCE_specifics_t asn1_DEF_%s_specs = {\n", p);
226 INDENTED(
227 OUT("sizeof(struct %s),\n", p);
228 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
vlm4e03ce22004-06-06 07:20:17 +0000229 OUT("asn1_DEF_%s_tag2el,\n", p);
230 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
vlmfa67ddc2004-06-03 03:38:44 +0000231 OUT("%d,\t/* Start extensions */\n",
232 ext_start);
233 OUT("%d\t/* Stop extensions */\n",
234 (ext_stop<ext_start)?elements+1:ext_stop, ext_stop);
235 );
236 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000237
238 /*
239 * Emit asn1_DEF_xxx table.
240 */
vlm1308d2b2004-09-10 15:49:15 +0000241 emit_type_DEF(arg, expr, tags_count, elements,
vlm4e554992004-08-25 02:03:12 +0000242 ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000243
vlmfa67ddc2004-06-03 03:38:44 +0000244 REDIR(OT_TYPE_DECLS);
245
246 return 0;
247}
248
249int
vlmfa67ddc2004-06-03 03:38:44 +0000250asn1c_lang_C_type_SET(arg_t *arg) {
251 asn1p_expr_t *expr = arg->expr;
252 asn1p_expr_t *v;
253 long mcount;
254 char *id;
255 int comp_mode = 0; /* {root,ext=1,root,root,...} */
256
257 DEPENDENCIES;
258
259 REDIR(OT_DEPS);
260
261 OUT("\n");
262 OUT("/*\n");
263 OUT(" * Method of determining the components presence\n");
264 OUT(" */\n");
265 mcount = 0;
vlm6e73a042004-08-11 07:17:22 +0000266 OUT("typedef enum %s_PR {\n", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000267 TQ_FOR(v, &(expr->members), next) {
268 if(v->expr_type == A1TC_EXTENSIBLE) continue;
269 INDENTED(
270 id = MKID(expr->Identifier);
271 OUT("%s_PR_", id);
272 id = MKID(v->Identifier);
273 OUT("%s,\t/* Member %s is present */\n",
274 id, id)
275 );
276 mcount++;
277 }
vlm6e73a042004-08-11 07:17:22 +0000278 id = MKID(expr->Identifier);
279 OUT("} %s_PR;\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000280
281 REDIR(OT_TYPE_DECLS);
282
283 if(arg->embed) {
vlm6e73a042004-08-11 07:17:22 +0000284 OUT("struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000285 } else {
vlm6e73a042004-08-11 07:17:22 +0000286 OUT("typedef struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000287 }
288
289 TQ_FOR(v, &(expr->members), next) {
290 if(v->expr_type == A1TC_EXTENSIBLE) {
291 if(comp_mode < 3) comp_mode++;
292 }
vlmddd5a7d2004-09-10 09:18:20 +0000293 if(comp_mode == 1
294 || expr_better_indirect(arg, v))
295 v->marker |= EM_INDIRECT;
vlmfa67ddc2004-06-03 03:38:44 +0000296 EMBED(v);
297 }
298
299 INDENTED(
300 id = MKID(expr->Identifier);
301 OUT("\n");
302 OUT("/* Presence bitmask: ASN_SET_ISPRESENT(p%s, %s_PR_x) */\n",
303 id, id);
304 OUT("unsigned int _presence_map\n");
305 OUT("\t[((%ld+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))];\n", mcount);
306 );
307
308 PCTX_DEF;
vlmdae7f9d2004-08-22 03:25:24 +0000309 OUT("} %s%s%s", expr->marker?"*":"",
310 expr->_anonymous_type ? "" : MKID(expr->Identifier),
311 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000312
313 return asn1c_lang_C_type_SET_def(arg);
314}
315
vlmfa67ddc2004-06-03 03:38:44 +0000316static int
317asn1c_lang_C_type_SET_def(arg_t *arg) {
318 asn1p_expr_t *expr = arg->expr;
319 asn1p_expr_t *v;
320 int elements;
vlmfa67ddc2004-06-03 03:38:44 +0000321 int comp_mode = 0; /* {root,ext=1,root,root,...} */
vlmfa67ddc2004-06-03 03:38:44 +0000322 tag2el_t *tag2el = NULL;
323 int tag2el_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000324 int tags_count;
vlmfa67ddc2004-06-03 03:38:44 +0000325 char *p;
326
327 /*
328 * Fetch every inner tag from the tag to elements map.
329 */
330 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
331 if(tag2el) free(tag2el);
332 return -1;
vlmfa67ddc2004-06-03 03:38:44 +0000333 }
334
vlm33a4ff12004-08-11 05:21:32 +0000335 GEN_INCLUDE("constr_SET");
336 if(!arg->embed)
337 GEN_DECLARE(expr); /* asn1_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000338
339 REDIR(OT_STAT_DEFS);
340
vlmfa67ddc2004-06-03 03:38:44 +0000341 /*
342 * Print out the table according to which the parsing is performed.
343 */
344 p = MKID(expr->Identifier);
vlmb2839012004-08-20 13:37:01 +0000345 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000346
347 elements = 0;
348 INDENTED(TQ_FOR(v, &(expr->members), next) {
vlmddd5a7d2004-09-10 09:18:20 +0000349 if(v->expr_type == A1TC_EXTENSIBLE) {
vlmfa67ddc2004-06-03 03:38:44 +0000350 if(comp_mode < 3) comp_mode++;
vlmddd5a7d2004-09-10 09:18:20 +0000351 } else {
352 if(comp_mode == 1
353 || expr_better_indirect(arg, v))
354 v->marker |= EM_INDIRECT;
355 elements++;
356 emit_member_table(arg, v);
vlmfa67ddc2004-06-03 03:38:44 +0000357 }
vlmfa67ddc2004-06-03 03:38:44 +0000358 });
359 OUT("};\n");
360
vlm4a3f5822004-06-28 21:13:46 +0000361 /*
362 * Print out asn1_DEF_<type>_tags[] vector.
363 */
vlm1308d2b2004-09-10 15:49:15 +0000364 tags_count = emit_tags_vector(arg, expr);
vlmfa67ddc2004-06-03 03:38:44 +0000365
366 /*
367 * Tags to elements map.
368 */
vlm4e03ce22004-06-06 07:20:17 +0000369 emit_tag2member_map(arg, tag2el, tag2el_count);
vlmfa67ddc2004-06-03 03:38:44 +0000370
371 /*
372 * Emit a map of mandatory elements.
373 */
vlm4a3f5822004-06-28 21:13:46 +0000374 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000375 OUT("static uint8_t asn1_DEF_%s_mmap", p);
376 OUT("[(%d + (8 * sizeof(unsigned int)) - 1) / 8]", elements);
377 OUT(" = {\n", p);
378 INDENTED(
379 if(elements) {
380 int delimit = 0;
381 int el = 0;
382 TQ_FOR(v, &(expr->members), next) {
383 if(v->expr_type == A1TC_EXTENSIBLE) continue;
384 if(delimit) {
385 OUT(",\n");
386 delimit = 0;
387 } else if(el) {
388 OUT(" | ");
389 }
vlmddd5a7d2004-09-10 09:18:20 +0000390 OUT("(%d << %d)",
391 v->marker?0:1,
392 7 - (el % 8));
vlmfa67ddc2004-06-03 03:38:44 +0000393 if(el && (el % 8) == 0)
394 delimit = 1;
395 el++;
396 }
397 } else {
398 OUT("0");
399 }
400 );
401 OUT("\n");
402 OUT("};\n");
403
404 OUT("static asn1_SET_specifics_t asn1_DEF_%s_specs = {\n", p);
405 INDENTED(
406 OUT("sizeof(struct %s),\n", p);
407 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
408 OUT("offsetof(struct %s, _presence_map),\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000409 OUT("asn1_DEF_%s_tag2el,\n", p);
410 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
vlm79b08d52004-07-01 00:52:50 +0000411 OUT("%d,\t/* Whether extensible */\n",
412 check_if_extensible(expr));
vlmfa67ddc2004-06-03 03:38:44 +0000413 OUT("(unsigned int *)asn1_DEF_%s_mmap\t/* Mandatory elements map */\n", p);
414 );
415 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000416
417 /*
418 * Emit asn1_DEF_xxx table.
419 */
vlm1308d2b2004-09-10 15:49:15 +0000420 emit_type_DEF(arg, expr, tags_count, elements,
vlm4e554992004-08-25 02:03:12 +0000421 ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000422
vlmfa67ddc2004-06-03 03:38:44 +0000423 REDIR(OT_TYPE_DECLS);
424
425 return 0;
426}
427
428int
vlmdae7f9d2004-08-22 03:25:24 +0000429asn1c_lang_C_type_SEx_OF(arg_t *arg) {
vlmfa67ddc2004-06-03 03:38:44 +0000430 asn1p_expr_t *expr = arg->expr;
vlmdae7f9d2004-08-22 03:25:24 +0000431 asn1p_expr_t *memb;
vlmfa67ddc2004-06-03 03:38:44 +0000432
433 DEPENDENCIES;
434
435 if(arg->embed) {
436 OUT("struct %s {\n", MKID(expr->Identifier));
437 } else {
vlmdae7f9d2004-08-22 03:25:24 +0000438 OUT("typedef struct %s {\n", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000439 }
440
vlmdae7f9d2004-08-22 03:25:24 +0000441 memb = TQ_FIRST(&expr->members);
442
443 INDENT(+1);
444 OUT("A_%s_OF(",
445 (arg->expr->expr_type == ASN_CONSTR_SET_OF)
446 ? "SET" : "SEQUENCE");
447 if(memb->expr_type & ASN_CONSTR_MASK) {
448 arg_t tmp;
449 asn1p_expr_t tmp_memb;
450 arg->embed++;
451 tmp = *arg;
452 tmp.expr = &tmp_memb;
453 tmp_memb = *memb;
454 tmp_memb._anonymous_type = 1;
455 tmp_memb.Identifier = strdup(
456 asn1c_make_identifier(0,
457 expr->Identifier, "member", 0));
458 assert(tmp_memb.Identifier);
459 tmp.default_cb(&tmp);
460 free(tmp_memb.Identifier);
461 arg->embed--;
462 assert(arg->target->target == OT_TYPE_DECLS);
463 } else {
464 OUT("%s", asn1c_type_name(arg, memb, TNF_RSAFE));
vlmfa67ddc2004-06-03 03:38:44 +0000465 }
vlmdae7f9d2004-08-22 03:25:24 +0000466 OUT(") list;\n");
467 INDENT(-1);
vlmfa67ddc2004-06-03 03:38:44 +0000468
469 PCTX_DEF;
vlmdae7f9d2004-08-22 03:25:24 +0000470 OUT("} %s%s%s", expr->marker?"*":"",
471 expr->_anonymous_type ? "" : MKID(expr->Identifier),
472 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000473
474 /*
vlmdae7f9d2004-08-22 03:25:24 +0000475 * SET OF/SEQUENCE OF definition
vlmfa67ddc2004-06-03 03:38:44 +0000476 */
vlmdae7f9d2004-08-22 03:25:24 +0000477 return asn1c_lang_C_type_SEx_OF_def(arg,
478 (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF));
vlmfa67ddc2004-06-03 03:38:44 +0000479}
480
481static int
482asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
483 asn1p_expr_t *expr = arg->expr;
484 asn1p_expr_t *v;
vlm6e73a042004-08-11 07:17:22 +0000485 int tags_count;
vlmfa67ddc2004-06-03 03:38:44 +0000486 char *p;
487
vlm33a4ff12004-08-11 05:21:32 +0000488 /*
489 * Print out the table according to which the parsing is performed.
490 */
vlmfa67ddc2004-06-03 03:38:44 +0000491 if(seq_of) {
vlm33a4ff12004-08-11 05:21:32 +0000492 GEN_INCLUDE("constr_SEQUENCE_OF");
vlmfa67ddc2004-06-03 03:38:44 +0000493 } else {
vlm33a4ff12004-08-11 05:21:32 +0000494 GEN_INCLUDE("constr_SET_OF");
vlmfa67ddc2004-06-03 03:38:44 +0000495 }
vlm33a4ff12004-08-11 05:21:32 +0000496 if(!arg->embed)
497 GEN_DECLARE(expr); /* asn1_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000498
499 REDIR(OT_STAT_DEFS);
500
501 /*
502 * Print out the table according to which the parsing is performed.
503 */
504 p = MKID(expr->Identifier);
vlmb2839012004-08-20 13:37:01 +0000505 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000506
vlmb2839012004-08-20 13:37:01 +0000507 INDENTED(
vlmfa67ddc2004-06-03 03:38:44 +0000508 v = TQ_FIRST(&(expr->members));
vlm4e554992004-08-25 02:03:12 +0000509 emit_member_table(arg, v);
vlmfa67ddc2004-06-03 03:38:44 +0000510 );
511 OUT("};\n");
512
vlm4a3f5822004-06-28 21:13:46 +0000513 /*
514 * Print out asn1_DEF_<type>_tags[] vector.
515 */
vlm1308d2b2004-09-10 15:49:15 +0000516 tags_count = emit_tags_vector(arg, expr);
vlmfa67ddc2004-06-03 03:38:44 +0000517
vlm4a3f5822004-06-28 21:13:46 +0000518 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000519 OUT("static asn1_SET_OF_specifics_t asn1_DEF_%s_specs = {\n", p);
520 INDENTED(
521 OUT("sizeof(struct %s),\n", p);
522 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000523 );
524 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000525
526 /*
527 * Emit asn1_DEF_xxx table.
528 */
vlm1308d2b2004-09-10 15:49:15 +0000529 emit_type_DEF(arg, expr, tags_count, 1,
vlm4e554992004-08-25 02:03:12 +0000530 ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000531
vlmfa67ddc2004-06-03 03:38:44 +0000532 REDIR(OT_TYPE_DECLS);
533
534 return 0;
535}
536
537int
538asn1c_lang_C_type_CHOICE(arg_t *arg) {
539 asn1p_expr_t *expr = arg->expr;
540 asn1p_expr_t *v;
vlmdae7f9d2004-08-22 03:25:24 +0000541 char *id;
vlmfa67ddc2004-06-03 03:38:44 +0000542
543 DEPENDENCIES;
544
vlm33a4ff12004-08-11 05:21:32 +0000545 REDIR(OT_DEPS);
546
vlmdae7f9d2004-08-22 03:25:24 +0000547 id = MKID(expr->Identifier);
548 OUT("typedef enum %s_PR {\n", id);
vlm33a4ff12004-08-11 05:21:32 +0000549 INDENTED(
vlm33a4ff12004-08-11 05:21:32 +0000550 OUT("%s_PR_NOTHING,\t"
vlmdae7f9d2004-08-22 03:25:24 +0000551 "/* No components present */\n", id);
vlm33a4ff12004-08-11 05:21:32 +0000552 TQ_FOR(v, &(expr->members), next) {
553 if(v->expr_type == A1TC_EXTENSIBLE) {
554 OUT("/* Extensions may appear below */\n");
555 continue;
556 }
vlmdae7f9d2004-08-22 03:25:24 +0000557 id = MKID(expr->Identifier);
558 OUT("%s_PR_", id);
559 id = MKID(v->Identifier);
560 OUT("%s,\n", id, id);
vlm33a4ff12004-08-11 05:21:32 +0000561 }
562 );
vlmdae7f9d2004-08-22 03:25:24 +0000563 id = MKID(expr->Identifier);
564 OUT("} %s_PR;\n", id);
vlm33a4ff12004-08-11 05:21:32 +0000565
566 REDIR(OT_TYPE_DECLS);
vlmfa67ddc2004-06-03 03:38:44 +0000567
568 if(arg->embed) {
vlmdae7f9d2004-08-22 03:25:24 +0000569 OUT("struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000570 } else {
vlmdae7f9d2004-08-22 03:25:24 +0000571 OUT("typedef struct %s {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000572 }
573
574 INDENTED(
vlmdae7f9d2004-08-22 03:25:24 +0000575 OUT("%s_PR present;\n", id);
576 OUT("union {\n", id);
vlmfa67ddc2004-06-03 03:38:44 +0000577 TQ_FOR(v, &(expr->members), next) {
vlmddd5a7d2004-09-10 09:18:20 +0000578 if(expr_better_indirect(arg, v))
579 v->marker |= EM_INDIRECT;
vlmfa67ddc2004-06-03 03:38:44 +0000580 EMBED(v);
581 }
582 if(UNNAMED_UNIONS) OUT("};\n");
583 else OUT("} choice;\n");
584 );
585
586 PCTX_DEF;
vlmdae7f9d2004-08-22 03:25:24 +0000587 OUT("} %s%s%s", expr->marker?"*":"",
588 expr->_anonymous_type ? "" : MKID(expr->Identifier),
589 arg->embed ? "" : "_t");
vlmfa67ddc2004-06-03 03:38:44 +0000590
591 return asn1c_lang_C_type_CHOICE_def(arg);
592}
593
594static int
595asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
596 asn1p_expr_t *expr = arg->expr;
597 asn1p_expr_t *v;
598 int elements; /* Number of elements */
vlmfa67ddc2004-06-03 03:38:44 +0000599 int comp_mode = 0; /* {root,ext=1,root,root,...} */
vlmfa67ddc2004-06-03 03:38:44 +0000600 tag2el_t *tag2el = NULL;
601 int tag2el_count = 0;
vlm6e73a042004-08-11 07:17:22 +0000602 int tags_count;
vlmfa67ddc2004-06-03 03:38:44 +0000603 char *p;
604
605 /*
606 * Fetch every inner tag from the tag to elements map.
607 */
608 if(_fill_tag2el_map(arg, &tag2el, &tag2el_count, -1)) {
609 if(tag2el) free(tag2el);
610 return -1;
vlmfa67ddc2004-06-03 03:38:44 +0000611 }
612
vlm33a4ff12004-08-11 05:21:32 +0000613 GEN_INCLUDE("constr_CHOICE");
614 if(!arg->embed)
615 GEN_DECLARE(expr); /* asn1_DEF_xxx */
vlmfa67ddc2004-06-03 03:38:44 +0000616
vlm33a4ff12004-08-11 05:21:32 +0000617 REDIR(OT_STAT_DEFS);
vlmfa67ddc2004-06-03 03:38:44 +0000618
619 /*
620 * Print out the table according to which the parsing is performed.
621 */
622 p = MKID(expr->Identifier);
vlmb2839012004-08-20 13:37:01 +0000623 OUT("static asn1_TYPE_member_t asn1_MBR_%s[] = {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000624
625 elements = 0;
626 INDENTED(TQ_FOR(v, &(expr->members), next) {
vlmddd5a7d2004-09-10 09:18:20 +0000627 if(v->expr_type == A1TC_EXTENSIBLE) {
vlmfa67ddc2004-06-03 03:38:44 +0000628 if(comp_mode < 3) comp_mode++;
vlmddd5a7d2004-09-10 09:18:20 +0000629 } else {
630 if(comp_mode == 1
631 || expr_better_indirect(arg, v))
632 v->marker |= EM_INDIRECT;
633 elements++;
634 emit_member_table(arg, v);
vlmfa67ddc2004-06-03 03:38:44 +0000635 }
vlmfa67ddc2004-06-03 03:38:44 +0000636 });
637 OUT("};\n");
638
vlm6e73a042004-08-11 07:17:22 +0000639
vlmfa67ddc2004-06-03 03:38:44 +0000640 if(arg->embed) {
641 /*
642 * Our parent structure has already taken this into account.
643 */
vlm6e73a042004-08-11 07:17:22 +0000644 tags_count = 0;
vlmfa67ddc2004-06-03 03:38:44 +0000645 } else {
vlm1308d2b2004-09-10 15:49:15 +0000646 tags_count = emit_tags_vector(arg, expr);
vlmfa67ddc2004-06-03 03:38:44 +0000647 }
vlmfa67ddc2004-06-03 03:38:44 +0000648
649 /*
650 * Tags to elements map.
651 */
vlm4e03ce22004-06-06 07:20:17 +0000652 emit_tag2member_map(arg, tag2el, tag2el_count);
vlmfa67ddc2004-06-03 03:38:44 +0000653
vlm6e73a042004-08-11 07:17:22 +0000654 p = MKID(expr->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +0000655 OUT("static asn1_CHOICE_specifics_t asn1_DEF_%s_specs = {\n", p);
656 INDENTED(
657 OUT("sizeof(struct %s),\n", p);
658 OUT("offsetof(struct %s, _ber_dec_ctx),\n", p);
659 OUT("offsetof(struct %s, present),\n", p);
660 OUT("sizeof(((struct %s *)0)->present),\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000661 OUT("asn1_DEF_%s_tag2el,\n", p);
662 OUT("%d,\t/* Count of tags in the map */\n", tag2el_count);
vlm79b08d52004-07-01 00:52:50 +0000663 OUT("%d\t/* Whether extensible */\n",
664 check_if_extensible(expr));
vlmfa67ddc2004-06-03 03:38:44 +0000665 );
666 OUT("};\n");
vlm4e554992004-08-25 02:03:12 +0000667
668 /*
669 * Emit asn1_DEF_xxx table.
670 */
vlm1308d2b2004-09-10 15:49:15 +0000671 emit_type_DEF(arg, expr, tags_count, elements,
vlm4e554992004-08-25 02:03:12 +0000672 ETD_CP_CONSTRUCTED /*either?!*/, ETD_HAS_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000673
vlmfa67ddc2004-06-03 03:38:44 +0000674 REDIR(OT_TYPE_DECLS);
675
676 return 0;
677}
678
679int
680asn1c_lang_C_type_REFERENCE(arg_t *arg) {
681 asn1p_ref_t *ref;
682
683 ref = arg->expr->reference;
684 if(ref->components[ref->comp_count-1].name[0] == '&') {
vlmfa67ddc2004-06-03 03:38:44 +0000685 asn1p_expr_t *extract;
686 arg_t tmp;
687 int ret;
688
vlmdae7f9d2004-08-22 03:25:24 +0000689 extract = asn1f_class_access_ex(arg->asn, arg->mod,
690 arg->expr, ref);
vlmfa67ddc2004-06-03 03:38:44 +0000691 if(extract == NULL)
692 return -1;
693
vlmdae7f9d2004-08-22 03:25:24 +0000694 extract = asn1p_expr_clone(extract, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000695 if(extract) {
696 if(extract->Identifier)
697 free(extract->Identifier);
698 extract->Identifier = strdup(arg->expr->Identifier);
699 if(extract->Identifier == NULL) {
700 asn1p_expr_free(extract);
701 return -1;
702 }
703 } else {
704 return -1;
705 }
706
707 tmp = *arg;
708 tmp.asn = arg->asn;
vlmdae7f9d2004-08-22 03:25:24 +0000709 tmp.mod = extract->module;
vlmfa67ddc2004-06-03 03:38:44 +0000710 tmp.expr = extract;
711
712 ret = arg->default_cb(&tmp);
713
714 asn1p_expr_free(extract);
715
716 return ret;
717 }
718
719
720 return asn1c_lang_C_type_SIMPLE_TYPE(arg);
721}
722
723int
724asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
725 asn1p_expr_t *expr = arg->expr;
vlm6e73a042004-08-11 07:17:22 +0000726 int tags_count;
vlmfa67ddc2004-06-03 03:38:44 +0000727 char *p;
728
729 if(arg->embed) {
730 REDIR(OT_TYPE_DECLS);
731
732 OUT("%s\t", asn1c_type_name(arg, arg->expr,
733 expr->marker?TNF_RSAFE:TNF_CTYPE));
734 OUT("%s", expr->marker?"*":" ");
vlmdae7f9d2004-08-22 03:25:24 +0000735 OUT("%s", MKID(expr->Identifier));
vlmddd5a7d2004-09-10 09:18:20 +0000736 if((expr->marker & EM_DEFAULT) == EM_DEFAULT)
737 OUT("\t/* DEFAULT */");
738 else if((expr->marker & EM_OPTIONAL) == EM_OPTIONAL)
739 OUT("\t/* OPTIONAL */");
vlmb2839012004-08-20 13:37:01 +0000740
741 REDIR(OT_TYPE_DECLS);
vlmfa67ddc2004-06-03 03:38:44 +0000742 return 0;
743 }
744
vlmfa67ddc2004-06-03 03:38:44 +0000745
vlm33a4ff12004-08-11 05:21:32 +0000746 GEN_INCLUDE(asn1c_type_name(arg, expr, TNF_INCLUDE));
vlmfa67ddc2004-06-03 03:38:44 +0000747
748 REDIR(OT_TYPE_DECLS);
749
750 OUT("typedef %s\t", asn1c_type_name(arg, arg->expr, TNF_CTYPE));
751 OUT("%s", expr->marker?"*":" ");
vlmdae7f9d2004-08-22 03:25:24 +0000752 OUT("%s_t", MKID(expr->Identifier));
vlmfa67ddc2004-06-03 03:38:44 +0000753
754 REDIR(OT_STAT_DEFS);
755
vlm4a3f5822004-06-28 21:13:46 +0000756 /*
757 * Print out asn1_DEF_<type>_tags[] vector.
758 */
vlm1308d2b2004-09-10 15:49:15 +0000759 tags_count = emit_tags_vector(arg, expr);
vlmfa67ddc2004-06-03 03:38:44 +0000760
vlm1308d2b2004-09-10 15:49:15 +0000761 emit_type_DEF(arg, expr, tags_count, 0,
vlm4e554992004-08-25 02:03:12 +0000762 ETD_CP_UNKNOWN, ETD_NO_SPECIFICS);
vlmfa67ddc2004-06-03 03:38:44 +0000763
vlmb2839012004-08-20 13:37:01 +0000764 REDIR(OT_CODE);
765
vlmfa67ddc2004-06-03 03:38:44 +0000766 /*
767 * Constraint checking.
768 */
vlmfa67ddc2004-06-03 03:38:44 +0000769 p = MKID(expr->Identifier);
770 OUT("int\n");
771 OUT("%s_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,\n", p);
772 INDENTED(
773 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
774 OUT("\n");
vlm1d036692004-08-19 13:29:46 +0000775 if(asn1c_emit_constraint_checking_code(arg) == 1) {
776 if(0) {
vlmfa67ddc2004-06-03 03:38:44 +0000777 OUT("/* Check the constraints of the underlying type */\n");
778 OUT("return asn1_DEF_%s.check_constraints\n",
779 asn1c_type_name(arg, expr, TNF_SAFE));
780 OUT("\t(td, sptr, app_errlog, app_key);\n");
vlm1d036692004-08-19 13:29:46 +0000781 } else {
vlmfa67ddc2004-06-03 03:38:44 +0000782 OUT("/* Make the underlying type checker permanent */\n");
783 OUT("td->check_constraints = asn1_DEF_%s.check_constraints;\n",
784 asn1c_type_name(arg, expr, TNF_SAFE));
785 OUT("return td->check_constraints\n");
786 OUT("\t(td, sptr, app_errlog, app_key);\n");
vlm1d036692004-08-19 13:29:46 +0000787 }
vlmfa67ddc2004-06-03 03:38:44 +0000788 }
789 );
790 OUT("}\n");
791 OUT("\n");
792
793 /*
794 * Emit suicidal functions.
795 */
796
vlmfa67ddc2004-06-03 03:38:44 +0000797 /*
798 * This function replaces certain fields from the definition
799 * of a type with the corresponding fields from the basic type
800 * (from which the current type is inherited).
801 */
vlmfa67ddc2004-06-03 03:38:44 +0000802 OUT("/*\n");
vlmb2839012004-08-20 13:37:01 +0000803 OUT(" * This type is implemented using %s,\n",
804 asn1c_type_name(arg, expr, TNF_SAFE));
vlmfa67ddc2004-06-03 03:38:44 +0000805 OUT(" * so adjust the DEF appropriately.\n");
806 OUT(" */\n");
807 OUT("static void\n");
vlmb2839012004-08-20 13:37:01 +0000808 p = MKID(expr->Identifier);
809 OUT("%s_inherit_TYPE_descriptor(asn1_TYPE_descriptor_t *td) {\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000810 INDENT(+1);
vlmb2839012004-08-20 13:37:01 +0000811 {
vlm1308d2b2004-09-10 15:49:15 +0000812 asn1p_expr_t *terminal = asn1f_find_terminal_type_ex(arg->asn, arg->mod, expr);
vlmb2839012004-08-20 13:37:01 +0000813 char *type_name = asn1c_type_name(arg, expr, TNF_SAFE);
814 OUT("td->ber_decoder = asn1_DEF_%s.ber_decoder;\n", type_name);
815 OUT("td->der_encoder = asn1_DEF_%s.der_encoder;\n", type_name);
816 OUT("td->free_struct = asn1_DEF_%s.free_struct;\n", type_name);
817 OUT("td->print_struct = asn1_DEF_%s.print_struct;\n", type_name);
vlm1308d2b2004-09-10 15:49:15 +0000818 if(!terminal && !tags_count) {
819 OUT("/* The next two lines are because of -fknown-extern-type */\n");
820 OUT("td->tags = asn1_DEF_%s.tags;\n", type_name);
821 OUT("td->tags_count = asn1_DEF_%s.tags_count;\n", type_name);
822 OUT("/* End of these lines */\n");
823 }
vlmb2839012004-08-20 13:37:01 +0000824 OUT("td->last_tag_form = asn1_DEF_%s.last_tag_form;\n", type_name);
825 OUT("td->elements = asn1_DEF_%s.elements;\n", type_name);
826 OUT("td->elements_count = asn1_DEF_%s.elements_count;\n", type_name);
827 OUT("td->specifics = asn1_DEF_%s.specifics;\n", type_name);
828 }
vlmfa67ddc2004-06-03 03:38:44 +0000829 INDENT(-1);
830 OUT("}\n");
831 OUT("\n");
vlmfa67ddc2004-06-03 03:38:44 +0000832
833 p = MKID(expr->Identifier);
834 OUT("ber_dec_rval_t\n");
835 OUT("%s_decode_ber(asn1_TYPE_descriptor_t *td,\n", p);
836 INDENTED(
837 OUT("\tvoid **structure, void *bufptr, size_t size, int tag_mode) {\n");
vlmb2839012004-08-20 13:37:01 +0000838 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlm1308d2b2004-09-10 15:49:15 +0000839 OUT("return td->ber_decoder(td, structure, bufptr, size, tag_mode);\n");
vlmfa67ddc2004-06-03 03:38:44 +0000840 );
841 OUT("}\n");
842 OUT("\n");
843
844 p = MKID(expr->Identifier);
845 OUT("der_enc_rval_t\n");
846 OUT("%s_encode_der(asn1_TYPE_descriptor_t *td,\n", p);
847 INDENTED(
848 OUT("\tvoid *structure, int tag_mode, ber_tlv_tag_t tag,\n");
849 OUT("\tasn_app_consume_bytes_f *cb, void *app_key) {\n");
vlmb2839012004-08-20 13:37:01 +0000850 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000851 OUT("return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);\n");
852 );
853 OUT("}\n");
854 OUT("\n");
855
856 p = MKID(expr->Identifier);
857 OUT("int\n");
858 OUT("%s_print(asn1_TYPE_descriptor_t *td, const void *struct_ptr,\n", p);
859 INDENTED(
860 OUT("\tint ilevel, asn_app_consume_bytes_f *cb, void *app_key) {\n");
vlmb2839012004-08-20 13:37:01 +0000861 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000862 OUT("return td->print_struct(td, struct_ptr, ilevel, cb, app_key);\n");
863 );
864 OUT("}\n");
865 OUT("\n");
866
867 p = MKID(expr->Identifier);
868 OUT("void\n");
869 OUT("%s_free(asn1_TYPE_descriptor_t *td,\n", p);
870 INDENTED(
871 OUT("\tvoid *struct_ptr, int contents_only) {\n");
vlmb2839012004-08-20 13:37:01 +0000872 OUT("%s_inherit_TYPE_descriptor(td);\n", p);
vlmfa67ddc2004-06-03 03:38:44 +0000873 OUT("td->free_struct(td, struct_ptr, contents_only);\n");
874 );
875 OUT("}\n");
876 OUT("\n");
877
878 REDIR(OT_FUNC_DECLS);
879
880 p = MKID(expr->Identifier);
vlm12c8f692004-09-06 08:07:29 +0000881 if(HIDE_INNER_DEFS) OUT("/* ");
882 OUT("extern asn1_TYPE_descriptor_t asn1_DEF_%s;", p);
883 if(HIDE_INNER_DEFS) OUT(" // (Use -fall-defs-global to expose) */");
884 OUT("\n");
vlmfa67ddc2004-06-03 03:38:44 +0000885 OUT("asn_constr_check_f %s_constraint;\n", p);
886 OUT("ber_type_decoder_f %s_decode_ber;\n", p);
887 OUT("der_type_encoder_f %s_encode_der;\n", p);
888 OUT("asn_struct_print_f %s_print;\n", p);
889 OUT("asn_struct_free_f %s_free;\n", p);
890
vlm33a4ff12004-08-11 05:21:32 +0000891 REDIR(OT_TYPE_DECLS);
892
vlmfa67ddc2004-06-03 03:38:44 +0000893 return 0;
894}
895
896int
897asn1c_lang_C_type_EXTENSIBLE(arg_t *arg) {
898
899 OUT("/*\n");
900 OUT(" * This type is extensible,\n");
901 OUT(" * possible extensions are below.\n");
902 OUT(" */\n");
903
904 return 0;
905}
906
vlm79b08d52004-07-01 00:52:50 +0000907static int check_if_extensible(asn1p_expr_t *expr) {
908 asn1p_expr_t *v;
909 TQ_FOR(v, &(expr->members), next) {
910 if(v->expr_type == A1TC_EXTENSIBLE) return 1;
911 }
912 return 0;
913}
914
vlmfa67ddc2004-06-03 03:38:44 +0000915static int
vlma8a86cc2004-09-10 06:07:18 +0000916_print_tag(arg_t *arg, struct asn1p_type_tag_s *tag) {
vlmfa67ddc2004-06-03 03:38:44 +0000917
918 OUT("(");
vlma8a86cc2004-09-10 06:07:18 +0000919 switch(tag->tag_class) {
vlmfa67ddc2004-06-03 03:38:44 +0000920 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 }
vlma8a86cc2004-09-10 06:07:18 +0000927 OUT(" | (%lld << 2))", tag->tag_value);
vlmfa67ddc2004-06-03 03:38:44 +0000928
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
vlma8a86cc2004-09-10 06:07:18 +00001033 ret = asn1f_fetch_outmost_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(" { ");
vlma8a86cc2004-09-10 06:07:18 +00001109 _print_tag(arg, &tag2el[i].el_tag);
vlm4e03ce22004-06-06 07:20:17 +00001110 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
vlm1308d2b2004-09-10 15:49:15 +00001126emit_tags_vector(arg_t *arg, asn1p_expr_t *expr) {
1127 struct asn1p_type_tag_s *tags = 0;
vlm6e73a042004-08-11 07:17:22 +00001128 int tags_count = 0;
vlm1308d2b2004-09-10 15:49:15 +00001129 int i;
vlm4a3f5822004-06-28 21:13:46 +00001130
vlm1308d2b2004-09-10 15:49:15 +00001131 /* Fetch a chain of tags */
1132 tags_count = asn1f_fetch_tags(arg->asn, arg->mod, expr, &tags, 0);
1133 if(tags_count <= 0)
1134 return 0;
vlm6e73a042004-08-11 07:17:22 +00001135
vlm1308d2b2004-09-10 15:49:15 +00001136 OUT("static ber_tlv_tag_t asn1_DEF_%s_tags[] = {\n",
1137 MKID(expr->Identifier));
vlmfb41dbb2004-09-08 00:28:57 +00001138 INDENT(+1);
vlm1308d2b2004-09-10 15:49:15 +00001139
1140 /* Print the array of collected tags */
1141 for(i = 0; i < tags_count; i++) {
1142 if(i) OUT(",\n");
1143 _print_tag(arg, &tags[i]);
vlmfb41dbb2004-09-08 00:28:57 +00001144 }
vlm1308d2b2004-09-10 15:49:15 +00001145
vlmfb41dbb2004-09-08 00:28:57 +00001146 OUT("\n");
1147 INDENT(-1);
vlm4a3f5822004-06-28 21:13:46 +00001148 OUT("};\n");
1149
vlm1308d2b2004-09-10 15:49:15 +00001150 free(tags);
vlm6e73a042004-08-11 07:17:22 +00001151 return tags_count;
vlm4a3f5822004-06-28 21:13:46 +00001152}
vlmb2839012004-08-20 13:37:01 +00001153
1154static int
vlm4e554992004-08-25 02:03:12 +00001155expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
vlmb2839012004-08-20 13:37:01 +00001156 asn1p_expr_t *topmost_parent;
1157 asn1p_expr_t *v;
1158 int elements = 0;
1159
vlmdae7f9d2004-08-22 03:25:24 +00001160 topmost_parent = asn1f_find_terminal_type_ex(arg->asn, arg->mod, expr);
vlmb2839012004-08-20 13:37:01 +00001161 if(!topmost_parent) return 0;
1162
1163 if(!(topmost_parent->expr_type & ASN_CONSTR_MASK))
1164 return 0;
1165
1166 TQ_FOR(v, &(topmost_parent->members), next) {
1167 if(v->expr_type != A1TC_EXTENSIBLE)
1168 elements++;
1169 }
1170
1171 return elements;
1172}
1173
1174static int
vlm4e554992004-08-25 02:03:12 +00001175emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
vlmdae7f9d2004-08-22 03:25:24 +00001176 static int global_memb_unique;
vlmb2839012004-08-20 13:37:01 +00001177 int save_target;
1178 arg_t tmp_arg;
vlm060fe2a2004-09-10 09:37:12 +00001179 struct asn1p_type_tag_s outmost_tag_s;
1180 struct asn1p_type_tag_s *outmost_tag;
vlmb2839012004-08-20 13:37:01 +00001181 char *p;
1182
vlm060fe2a2004-09-10 09:37:12 +00001183 if(asn1f_fetch_outmost_tag(arg->asn,
1184 expr->module, expr, &outmost_tag_s, 1)) {
1185 outmost_tag = 0;
1186 } else {
1187 outmost_tag = &outmost_tag_s;
1188 }
1189
vlmb2839012004-08-20 13:37:01 +00001190 OUT("{ ");
vlm060fe2a2004-09-10 09:37:12 +00001191
1192 if(outmost_tag && outmost_tag->tag_value == -1)
1193 OUT("ATF_OPEN_TYPE | ");
vlmddd5a7d2004-09-10 09:18:20 +00001194 OUT("%s, ", expr->marker?"ATF_POINTER":"ATF_NOFLAGS");
1195 if((expr->marker & EM_OPTIONAL) == EM_OPTIONAL) {
vlmb2839012004-08-20 13:37:01 +00001196 asn1p_expr_t *tv;
1197 int opts = 0;
1198 for(tv = expr; tv && tv->marker;
1199 tv = TQ_NEXT(tv, next), opts++) {
1200 if(tv->expr_type == A1TC_EXTENSIBLE)
1201 opts--;
1202 }
1203 OUT("%d, ", opts);
1204 } else {
1205 OUT("0, ");
1206 }
1207 if(expr->Identifier) {
1208 OUT("offsetof(struct %s, ", MKID(arg->expr->Identifier));
1209 if(arg->expr->expr_type == ASN_CONSTR_CHOICE
1210 && (!UNNAMED_UNIONS)) OUT("choice.");
1211 OUT("%s),\n", MKID(expr->Identifier));
1212 } else {
1213 assert(arg->expr->expr_type == ASN_CONSTR_SET_OF
1214 || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF);
1215 OUT("0,\n");
1216 }
1217 INDENT(+1);
1218 if(C99_MODE) OUT(".tag = ");
vlm060fe2a2004-09-10 09:37:12 +00001219 if(outmost_tag) {
1220 if(outmost_tag->tag_value == -1)
1221 OUT("-1 /* Ambiguous tag (ANY?) */");
1222 else
1223 _print_tag(arg, outmost_tag);
vlma8a86cc2004-09-10 06:07:18 +00001224 } else {
vlm060fe2a2004-09-10 09:37:12 +00001225 OUT("-1 /* Ambiguous tag (CHOICE?) */");
vlma8a86cc2004-09-10 06:07:18 +00001226 }
vlm060fe2a2004-09-10 09:37:12 +00001227
vlmb2839012004-08-20 13:37:01 +00001228 OUT(",\n");
1229 if(C99_MODE) OUT(".tag_mode = ");
1230 if(expr->tag.tag_class) {
1231 if(expr->tag.tag_mode == TM_IMPLICIT)
1232 OUT("-1,\t/* IMPLICIT tag at current level */\n");
1233 else
1234 OUT("+1,\t/* EXPLICIT tag at current level */\n");
1235 } else {
1236 OUT("0,\n");
1237 }
1238 if(C99_MODE) OUT(".type = ");
vlmdae7f9d2004-08-22 03:25:24 +00001239 if((expr->expr_type & ASN_CONSTR_MASK)
1240 && (arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF
1241 || arg->expr->expr_type == ASN_CONSTR_SET_OF)) {
1242 OUT("(void *)&asn1_DEF_%s_member,\n",
1243 MKID(arg->expr->Identifier));
vlm4e554992004-08-25 02:03:12 +00001244 } else if(expr->expr_type & ASN_CONSTR_MASK) {
1245 OUT("(void *)&asn1_DEF_%s,\n",
1246 MKID(expr->Identifier));
vlmdae7f9d2004-08-22 03:25:24 +00001247 } else {
1248 OUT("(void *)&asn1_DEF_%s,\n",
1249 asn1c_type_name(arg, expr, TNF_SAFE));
1250 }
vlmb2839012004-08-20 13:37:01 +00001251 if(C99_MODE) OUT(".memb_constraints = ");
1252 if(expr->constraints) {
vlm4e554992004-08-25 02:03:12 +00001253 char *id = MKID(expr->Identifier);
vlmb2839012004-08-20 13:37:01 +00001254 if(!expr->Identifier)
vlm4e554992004-08-25 02:03:12 +00001255 id = asn1c_type_name(arg, expr, TNF_SAFE);
1256 OUT("memb_%s_%d_constraint,\n", id,
vlmdae7f9d2004-08-22 03:25:24 +00001257 ++global_memb_unique);
vlmb2839012004-08-20 13:37:01 +00001258 } else {
1259 OUT("0,\t/* Defer to actual type */\n");
1260 }
1261 if(C99_MODE) OUT(".name = ");
1262 OUT("\"%s\"\n", expr->Identifier ? expr->Identifier : "");
1263 OUT("},\n");
1264 INDENT(-1);
1265
1266 if(!expr->constraints)
1267 return 0;
1268
1269 save_target = arg->target->target;
1270 REDIR(OT_CODE);
1271
1272 if(expr->Identifier)
1273 p = MKID(expr->Identifier);
1274 else
1275 p = asn1c_type_name(arg, expr, TNF_SAFE);
1276 OUT("static int\n");
vlmdae7f9d2004-08-22 03:25:24 +00001277 OUT("memb_%s_%d_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,\n", p, global_memb_unique);
vlmb2839012004-08-20 13:37:01 +00001278 INDENT(+1);
1279 OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n");
1280 tmp_arg = *arg;
1281 tmp_arg.expr = expr;
1282 if(asn1c_emit_constraint_checking_code(&tmp_arg) == 1) {
1283 OUT("return td->check_constraints\n");
1284 OUT("\t(td, sptr, app_errlog, app_key);\n");
1285 }
1286 INDENT(-1);
1287 OUT("}\n");
1288 OUT("\n");
1289
1290 REDIR(save_target);
1291
1292 return 0;
1293}
vlm4e554992004-08-25 02:03:12 +00001294
1295static int
vlm1308d2b2004-09-10 15:49:15 +00001296emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, int tags_count, int elements_count, enum etd_cp cp, enum etd_spec spec) {
vlm4e554992004-08-25 02:03:12 +00001297 char *p;
1298
1299 p = MKID(expr->Identifier);
vlm12c8f692004-09-06 08:07:29 +00001300 if(HIDE_INNER_DEFS)
1301 OUT("static /* Use -fall-defs-global to expose */\n");
vlm4e554992004-08-25 02:03:12 +00001302 OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
1303 INDENTED(
1304 OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
1305
1306 if(expr->expr_type & ASN_CONSTR_MASK) {
1307 p = asn1c_type_name(arg, arg->expr, TNF_SAFE);
1308 }
1309
1310 OUT("%s_constraint,\n", p);
1311 OUT("%s_decode_ber,\n", p);
1312 OUT("%s_encode_der,\n", p);
1313 OUT("%s_print,\n", p);
1314 OUT("%s_free,\n", p);
1315
1316 p = MKID(expr->Identifier);
1317
1318 if(expr->expr_type == ASN_CONSTR_CHOICE) {
1319 OUT("CHOICE_outmost_tag,\n");
1320 } else {
1321 OUT("0,\t/* Use generic outmost tag fetcher */\n");
1322 }
1323
1324 if(tags_count) {
1325 OUT("asn1_DEF_%s_tags,\n", p);
1326 OUT("sizeof(asn1_DEF_%s_tags)\n", p);
1327 OUT("\t/sizeof(asn1_DEF_%s_tags[0]), /* %d */\n",
1328 p, tags_count);
1329 } else {
1330 OUT("0,\t/* No explicit tags (pointer) */\n");
1331 OUT("0,\t/* No explicit tags (count) */\n");
1332 }
1333
vlm4e554992004-08-25 02:03:12 +00001334 switch(cp) {
1335 case ETD_CP_UNKNOWN:
1336 OUT("-0,\t/* Unknown yet */\n");
1337 break;
1338 case ETD_CP_EITHER:
1339 OUT("-1,\t/* Primitive or constructed */\n");
1340 case ETD_CP_PRIMITIVE:
1341 OUT("0,\t/* Primitive */\n");
1342 break;
1343 case ETD_CP_CONSTRUCTED:
1344 OUT("1,\t/* Whether CONSTRUCTED */\n");
1345 break;
1346 }
1347
1348 if(elements_count) {
1349 OUT("asn1_MBR_%s,\n", p);
1350 if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF
1351 || expr->expr_type == ASN_CONSTR_SET_OF) {
1352 OUT("%d,\t/* Single element */\n",
1353 elements_count);
1354 assert(elements_count == 1);
1355 } else {
1356 OUT("%d,\t/* Elements count */\n",
1357 elements_count);
1358 }
1359 } else {
1360 //if(expr->meta_type == AMT_TYPEREF)
1361 if(expr_elements_count(arg, expr))
1362 OUT("0, 0,\t/* Defined elsewhere */\n");
1363 else
1364 OUT("0, 0,\t/* No members */\n");
1365 }
1366
1367 switch(spec) {
1368 case ETD_NO_SPECIFICS:
1369 OUT("0\t/* No specifics */\n");
1370 break;
1371 case ETD_HAS_SPECIFICS:
1372 OUT("&asn1_DEF_%s_specs\t/* Additional specs */\n", p);
1373 }
1374 );
1375 OUT("};\n");
1376 OUT("\n");
vlme2bb4432004-08-26 06:20:34 +00001377
1378 return 0;
vlm4e554992004-08-25 02:03:12 +00001379}
vlmddd5a7d2004-09-10 09:18:20 +00001380
1381/*
1382 * Check if it is better to make this type indirectly accessed via
1383 * a pointer.
1384 * This may be the case for the following recursive definition:
1385 * Type ::= CHOICE { member Type };
1386 */
1387static int
1388expr_better_indirect(arg_t *arg, asn1p_expr_t *expr) {
1389 asn1p_expr_t *top_parent;
1390 asn1p_expr_t *terminal;
1391
1392 if(expr->expr_type != A1TC_REFERENCE)
1393 return 0;
1394
1395 /* Rewind to the topmost parent expression */
1396 if((top_parent = expr->parent_expr)) {
1397 while(top_parent->parent_expr)
1398 top_parent = top_parent->parent_expr;
1399 } else {
1400 return 0;
1401 }
1402
1403 terminal = asn1f_find_terminal_type_ex(arg->asn, arg->mod, expr);
1404
1405 return (terminal == top_parent);
1406}