diff options
author | Lev Walkin <vlm@lionet.info> | 2005-11-26 11:25:14 +0000 |
---|---|---|
committer | Lev Walkin <vlm@lionet.info> | 2005-11-26 11:25:14 +0000 |
commit | 59b176ee355b3e82e6a8649b164c187c7a17a28f (patch) | |
tree | 6d864f02cd16eb75f4ae6e40199d1879d8363152 /libasn1compiler | |
parent | 708530582f5ba965fb596c3e189eec23c52337d9 (diff) |
upgrade: PER related changes
Diffstat (limited to 'libasn1compiler')
-rw-r--r-- | libasn1compiler/asn1c_C.c | 709 | ||||
-rw-r--r-- | libasn1compiler/asn1c_constraint.c | 2 | ||||
-rw-r--r-- | libasn1compiler/asn1c_fdeps.c | 27 | ||||
-rw-r--r-- | libasn1compiler/asn1c_save.c | 68 | ||||
-rw-r--r-- | libasn1compiler/asn1compiler.h | 10 |
5 files changed, 706 insertions, 110 deletions
diff --git a/libasn1compiler/asn1c_C.c b/libasn1compiler/asn1c_C.c index 4df99188..8bce9028 100644 --- a/libasn1compiler/asn1c_C.c +++ b/libasn1compiler/asn1c_C.c @@ -7,7 +7,8 @@ #include "asn1c_constraint.h" #include "asn1c_out.h" #include "asn1c_misc.h" -#include <asn1fix_export.h> /* Stuff exported by libasn1fix */ +#include <asn1fix_crange.h> /* constraint groker from libasn1fix */ +#include <asn1fix_export.h> /* other exportables from libasn1fix */ typedef struct tag2el_s { struct asn1p_type_tag_s el_tag; @@ -35,16 +36,22 @@ static int asn1c_lang_C_type_SET_def(arg_t *arg); static int asn1c_lang_C_type_CHOICE_def(arg_t *arg); static int asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of); static int _print_tag(arg_t *arg, struct asn1p_type_tag_s *tag_p); -static int check_if_extensible(asn1p_expr_t *expr); +static int compute_extensions_start(asn1p_expr_t *expr); static int expr_break_recursion(arg_t *arg, asn1p_expr_t *expr); static int expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr); static int expr_elements_count(arg_t *arg, asn1p_expr_t *expr); +static int emit_single_member_PER_constraint(arg_t *arg, asn1cnst_range_t *range, char *type); +static int emit_single_member_PER_constraints(arg_t *arg, asn1p_expr_t *expr); +static int emit_members_PER_constraints(arg_t *arg); static int emit_member_table(arg_t *arg, asn1p_expr_t *expr); static int emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char *opt_modifier); static int emit_include_dependencies(arg_t *arg); static asn1p_expr_t *terminal_structable(arg_t *arg, asn1p_expr_t *expr); static int expr_defined_recursively(arg_t *arg, asn1p_expr_t *expr); static int asn1c_recurse(arg_t *arg, asn1p_expr_t *expr, int (*callback)(arg_t *arg, void *key), void *key); +static asn1p_expr_type_e expr_get_type(arg_t *arg, asn1p_expr_t *expr); +static int try_inline_default(arg_t *arg, asn1p_expr_t *expr, int out); +static int *compute_canonical_members_order(arg_t *arg, int el_count); enum tvm_compat { _TVM_SAME = 0, /* tags and all_tags are same */ @@ -78,8 +85,9 @@ static int emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, enum tvm_compat tv_mode } while(0) /* MKID_safe() without checking for reserved keywords */ -#define MKID(id) asn1c_make_identifier(0, (id), 0) -#define MKID_safe(id) asn1c_make_identifier(AMI_CHECK_RESERVED, (id), 0) +#define MKID(id) ((id)?asn1c_make_identifier(0, (id), 0):"Member") +#define MKID_safe(id) ((id)?asn1c_make_identifier(AMI_CHECK_RESERVED, \ + (id), 0):"Member") int asn1c_lang_C_type_REAL(arg_t *arg) { @@ -112,7 +120,7 @@ asn1c_lang_C_type_common_INTEGER(arg_t *arg) { asn1p_expr_t *v; int el_count = expr_elements_count(arg, expr); struct value2enum *v2e; - int map_is_extensible = (expr->expr_type == ASN_BASIC_INTEGER); + int map_extensions = (expr->expr_type == ASN_BASIC_INTEGER); int eidx; v2e = alloca((el_count + 1) * sizeof(*v2e)); @@ -144,7 +152,8 @@ asn1c_lang_C_type_common_INTEGER(arg_t *arg) { OUT("\t/*\n"); OUT("\t * Enumeration is extensible\n"); OUT("\t */\n"); - map_is_extensible = 1; + if(!map_extensions) + map_extensions = eidx + 1; break; default: return -1; @@ -168,7 +177,7 @@ asn1c_lang_C_type_common_INTEGER(arg_t *arg) { */ REDIR(OT_STAT_DEFS); - OUT("static asn_INTEGER_enum_map_t asn_MAP_%s_%d_value2enum[] = {\n", + OUT("static asn_INTEGER_enum_map_t asn_MAP_%s_value2enum_%d[] = {\n", MKID(expr->Identifier), expr->_type_unique_index); qsort(v2e, el_count, sizeof(v2e[0]), compar_enumMap_byValue); for(eidx = 0; eidx < el_count; eidx++) { @@ -178,11 +187,11 @@ asn1c_lang_C_type_common_INTEGER(arg_t *arg) { (long)strlen(v2e[eidx].name), v2e[eidx].name, (eidx + 1 < el_count) ? "," : ""); } - if(map_is_extensible) + if(map_extensions) OUT("\t/* This list is extensible */\n"); OUT("};\n"); - OUT("static unsigned int asn_MAP_%s_%d_enum2value[] = {\n", + OUT("static unsigned int asn_MAP_%s_enum2value_%d[] = {\n", MKID(expr->Identifier), expr->_type_unique_index); qsort(v2e, el_count, sizeof(v2e[0]), compar_enumMap_byName); for(eidx = 0; eidx < el_count; eidx++) { @@ -191,25 +200,29 @@ asn1c_lang_C_type_common_INTEGER(arg_t *arg) { (eidx + 1 < el_count) ? "," : "", v2e[eidx].name, v2e[eidx].value); } - if(map_is_extensible) + if(map_extensions) OUT("\t/* This list is extensible */\n"); OUT("};\n"); - OUT("static asn_INTEGER_specifics_t asn_SPC_%s_%d_specs = {\n", + OUT("static asn_INTEGER_specifics_t asn_SPC_%s_specs_%d = {\n", MKID(expr->Identifier), expr->_type_unique_index); INDENT(+1); - OUT("asn_MAP_%s_%d_value2enum,\t" + OUT("asn_MAP_%s_value2enum_%d,\t" "/* \"tag\" => N; sorted by tag */\n", MKID(expr->Identifier), expr->_type_unique_index); - OUT("asn_MAP_%s_%d_enum2value,\t" + OUT("asn_MAP_%s_enum2value_%d,\t" "/* N => \"tag\"; sorted by N */\n", MKID(expr->Identifier), expr->_type_unique_index); OUT("%d,\t/* Number of elements in the maps */\n", el_count); - OUT("%d,\t/* Enumeration is %sextensible */\n", - map_is_extensible, map_is_extensible ? "": "not "); + if(map_extensions) { + OUT("%d,\t/* Extensions before this member */\n", + map_extensions); + } else { + OUT("0,\t/* Enumeration is not extensible */\n"); + } if(expr->expr_type == ASN_BASIC_ENUMERATED) OUT("1\t/* Strict enumeration */\n"); else @@ -277,7 +290,8 @@ asn1c_lang_C_type_SEQUENCE(arg_t *arg) { if(v->expr_type == A1TC_EXTENSIBLE) if(comp_mode < 3) comp_mode++; if(comp_mode == 1) - v->marker.flags |= EM_OMITABLE; + v->marker.flags |= EM_OMITABLE | EM_INDIRECT; + try_inline_default(arg, v, 1); EMBED(v); } @@ -304,6 +318,8 @@ asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) { int tags_count; int all_tags_count; enum tvm_compat tv_mode; + int roms_count; /* Root optional members */ + int aoms_count; /* Additions optional members */ /* * Fetch every inner tag from the tag to elements map. @@ -320,15 +336,19 @@ asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) { REDIR(OT_STAT_DEFS); /* - * Print out the table according to which the parsing is performed. + * Print out the table according to which parsing is performed. */ if(expr_elements_count(arg, expr)) { int comp_mode = 0; /* {root,ext=1,root,root,...} */ + if(emit_members_PER_constraints(arg)) + return -1; OUT("static asn_TYPE_member_t asn_MBR_%s_%d[] = {\n", MKID(expr->Identifier), expr->_type_unique_index); elements = 0; + roms_count = 0; + aoms_count = 0; INDENTED(TQ_FOR(v, &(expr->members), next) { if(v->expr_type == A1TC_EXTENSIBLE) { if((++comp_mode) == 1) @@ -337,14 +357,62 @@ asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) { ext_stop = elements - 1; continue; } - if(comp_mode == 1) - v->marker.flags |= EM_OMITABLE; + if(v->marker.flags & EM_OMITABLE) + comp_mode == 1 ? ++aoms_count : ++roms_count; emit_member_table(arg, v); elements++; }); OUT("};\n"); + + if((roms_count + aoms_count) && (arg->flags & A1C_GEN_PER)) { + int elm = 0; + int comma = 0; + comp_mode = 0; + OUT("static int asn_MAP_%s_oms_%d[] = {", + MKID(expr->Identifier), + expr->_type_unique_index); + TQ_FOR(v, &(expr->members), next) { + if(v->expr_type == A1TC_EXTENSIBLE) { + ++comp_mode; + continue; + } + if((v->marker.flags & EM_OMITABLE) + && comp_mode != 1) { + if(!comma) comma++; + else OUT(","); + OUT(" %d", elm); + } + ++elm; + } + elm = 0; + comp_mode = 0; + TQ_FOR(v, &(expr->members), next) { + if(v->expr_type == A1TC_EXTENSIBLE) { + ++comp_mode; + continue; + } + if((v->marker.flags & EM_OMITABLE) + && comp_mode == 1) { + if(!comma) comma++; + else OUT(","); + OUT(" %d", elm); + } + ++elm; + } + OUT(" };\n"); + if(roms_count > 65536) + FATAL("Too many optional elements in %s " + "at line %d!", + arg->expr->Identifier, + arg->expr->_lineno); + } else { + roms_count = 0; + aoms_count = 0; + } } else { elements = 0; + roms_count = 0; + aoms_count = 0; } /* @@ -357,26 +425,35 @@ asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) { */ emit_tag2member_map(arg, tag2el, tag2el_count, 0); - OUT("static asn_SEQUENCE_specifics_t asn_SPC_%s_%d_specs = {\n", + OUT("static asn_SEQUENCE_specifics_t asn_SPC_%s_specs_%d = {\n", MKID(expr->Identifier), expr->_type_unique_index); - INDENTED( - OUT("sizeof(struct "); out_name_chain(arg, ONC_avoid_keywords); OUT("),\n"); - OUT("offsetof(struct "); out_name_chain(arg, ONC_avoid_keywords); OUT(", _asn_ctx),\n"); + INDENT(+1); + OUT("sizeof(struct "); + out_name_chain(arg, ONC_avoid_keywords); OUT("),\n"); + OUT("offsetof(struct "); + out_name_chain(arg, ONC_avoid_keywords); OUT(", _asn_ctx),\n"); - if(tag2el_count) { - OUT("asn_MAP_%s_%d_tag2el,\n", - MKID(expr->Identifier), - expr->_type_unique_index); - OUT("%d,\t/* Count of tags in the map */\n", tag2el_count); - } else { - OUT("0,\t/* No top level tags */\n"); - OUT("0,\t/* No tags in the map */\n"); - } - OUT("%d,\t/* Start extensions */\n", + if(tag2el_count) { + OUT("asn_MAP_%s_tag2el_%d,\n", + MKID(expr->Identifier), + expr->_type_unique_index); + OUT("%d,\t/* Count of tags in the map */\n", tag2el_count); + } else { + OUT("0,\t/* No top level tags */\n"); + OUT("0,\t/* No tags in the map */\n"); + } + if(roms_count + aoms_count) { + OUT("asn_MAP_%s_oms_%d,\t/* Optional members */\n", + MKID(expr->Identifier), expr->_type_unique_index); + OUT("%d, %d,\t/* Root/Additions */\n", roms_count, aoms_count); + } else { + OUT("0, 0, 0,\t/* Optional elements (not needed) */\n"); + } + OUT("%d,\t/* Start extensions */\n", ext_start); - OUT("%d\t/* Stop extensions */\n", + OUT("%d\t/* Stop extensions */\n", (ext_stop<ext_start)?elements+1:ext_stop, ext_stop); - ); + INDENT(-1); OUT("};\n"); /* @@ -430,15 +507,16 @@ asn1c_lang_C_type_SET(arg_t *arg) { out_name_chain(arg, ONC_avoid_keywords); OUT(" {\n"); } else { - OUT("typedef struct %s {\n", MKID_safe(expr->Identifier)); + OUT("typedef struct %s {\n", + MKID_safe(expr->Identifier)); } TQ_FOR(v, &(expr->members), next) { - if(v->expr_type == A1TC_EXTENSIBLE) { + if(v->expr_type == A1TC_EXTENSIBLE) if(comp_mode < 3) comp_mode++; - } if(comp_mode == 1) - v->marker.flags |= EM_OMITABLE; + v->marker.flags |= EM_OMITABLE | EM_INDIRECT; + try_inline_default(arg, v, 1); EMBED(v); } @@ -498,11 +576,13 @@ asn1c_lang_C_type_SET_def(arg_t *arg) { REDIR(OT_STAT_DEFS); /* - * Print out the table according to which the parsing is performed. + * Print out the table according to which parsing is performed. */ if(expr_elements_count(arg, expr)) { int comp_mode = 0; /* {root,ext=1,root,root,...} */ + if(emit_members_PER_constraints(arg)) + return -1; OUT("static asn_TYPE_member_t asn_MBR_%s_%d[] = {\n", MKID(expr->Identifier), expr->_type_unique_index); @@ -511,8 +591,6 @@ asn1c_lang_C_type_SET_def(arg_t *arg) { if(v->expr_type == A1TC_EXTENSIBLE) { if(comp_mode < 3) comp_mode++; } else { - if(comp_mode == 1) - v->marker.flags |= EM_OMITABLE; emit_member_table(arg, v); elements++; } @@ -537,7 +615,7 @@ asn1c_lang_C_type_SET_def(arg_t *arg) { /* * Emit a map of mandatory elements. */ - OUT("static uint8_t asn_MAP_%s_%d_mmap", + OUT("static uint8_t asn_MAP_%s_mmap_%d", MKID(expr->Identifier), expr->_type_unique_index); p = MKID_safe(expr->Identifier); OUT("[(%d + (8 * sizeof(unsigned int)) - 1) / 8]", elements); @@ -565,7 +643,7 @@ asn1c_lang_C_type_SET_def(arg_t *arg) { OUT("\n"); OUT("};\n"); - OUT("static asn_SET_specifics_t asn_SPC_%s_%d_specs = {\n", + OUT("static asn_SET_specifics_t asn_SPC_%s_specs_%d = {\n", MKID(expr->Identifier), expr->_type_unique_index); INDENTED( OUT("sizeof(struct "); @@ -578,19 +656,19 @@ asn1c_lang_C_type_SET_def(arg_t *arg) { out_name_chain(arg, ONC_avoid_keywords); OUT(", _presence_map),\n"); p = MKID(expr->Identifier); - OUT("asn_MAP_%s_%d_tag2el,\n", p, expr->_type_unique_index); + OUT("asn_MAP_%s_tag2el_%d,\n", p, expr->_type_unique_index); OUT("%d,\t/* Count of tags in the map */\n", tag2el_count); if(tag2el_cxer) - OUT("asn_MAP_%s_%d_tag2el_cxer,\n", + OUT("asn_MAP_%s_tag2el_cxer_%d,\n", p, expr->_type_unique_index); else - OUT("asn_MAP_%s_%d_tag2el,\t/* Same as above */\n", + OUT("asn_MAP_%s_tag2el_%d,\t/* Same as above */\n", p, expr->_type_unique_index); OUT("%d,\t/* Count of tags in the CXER map */\n", tag2el_cxer_count); OUT("%d,\t/* Whether extensible */\n", - check_if_extensible(expr)); - OUT("(unsigned int *)asn_MAP_%s_%d_mmap\t/* Mandatory elements map */\n", + compute_extensions_start(expr) == -1 ? 0 : 1); + OUT("(unsigned int *)asn_MAP_%s_mmap_%d\t/* Mandatory elements map */\n", p, expr->_type_unique_index); ); OUT("};\n"); @@ -690,7 +768,7 @@ asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) { enum tvm_compat tv_mode; /* - * Print out the table according to which the parsing is performed. + * Print out the table according to which parsing is performed. */ if(seq_of) { GEN_INCLUDE("constr_SEQUENCE_OF"); @@ -703,8 +781,10 @@ asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) { REDIR(OT_STAT_DEFS); /* - * Print out the table according to which the parsing is performed. + * Print out the table according to which parsing is performed. */ + if(emit_members_PER_constraints(arg)) + return -1; OUT("static asn_TYPE_member_t asn_MBR_%s_%d[] = {\n", MKID(expr->Identifier), expr->_type_unique_index); INDENT(+1); @@ -725,7 +805,7 @@ asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) { */ tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count); - OUT("static asn_SET_OF_specifics_t asn_SPC_%s_%d_specs = {\n", + OUT("static asn_SET_OF_specifics_t asn_SPC_%s_specs_%d = {\n", MKID(expr->Identifier), expr->_type_unique_index); INDENTED( OUT("sizeof(struct "); @@ -828,6 +908,7 @@ asn1c_lang_C_type_CHOICE_def(arg_t *arg) { int tags_count; int all_tags_count; enum tvm_compat tv_mode; + int *cmap = 0; /* * Fetch every inner tag from the tag to elements map. @@ -844,10 +925,12 @@ asn1c_lang_C_type_CHOICE_def(arg_t *arg) { REDIR(OT_STAT_DEFS); /* - * Print out the table according to which the parsing is performed. + * Print out the table according to which parsing is performed. */ if(expr_elements_count(arg, expr)) { + if(emit_members_PER_constraints(arg)) + return -1; OUT("static asn_TYPE_member_t asn_MBR_%s_%d[] = {\n", MKID(expr->Identifier), expr->_type_unique_index); @@ -863,6 +946,22 @@ asn1c_lang_C_type_CHOICE_def(arg_t *arg) { elements = 0; } + /* Create a canonical elements map */ + if(elements && (arg->flags & A1C_GEN_PER)) { + int i; + cmap = compute_canonical_members_order(arg, elements); + if(cmap) { + OUT("static int asn_MAP_%s_cmap_%d[] = {", + MKID(expr->Identifier), + expr->_type_unique_index); + for(i = 0; i < elements; i++) { + if(i) OUT(","); + OUT(" %d", cmap[i]); + } + OUT(" };\n"); + free(cmap); + } + } if(arg->embed) { /* @@ -880,7 +979,7 @@ asn1c_lang_C_type_CHOICE_def(arg_t *arg) { */ emit_tag2member_map(arg, tag2el, tag2el_count, 0); - OUT("static asn_CHOICE_specifics_t asn_SPC_%s_%d_specs = {\n", + OUT("static asn_CHOICE_specifics_t asn_SPC_%s_specs_%d = {\n", MKID(expr->Identifier), expr->_type_unique_index); INDENTED( OUT("sizeof(struct "); @@ -895,11 +994,16 @@ asn1c_lang_C_type_CHOICE_def(arg_t *arg) { OUT("sizeof(((struct "); out_name_chain(arg, ONC_avoid_keywords); OUT(" *)0)->present),\n"); - OUT("asn_MAP_%s_%d_tag2el,\n", + OUT("asn_MAP_%s_tag2el_%d,\n", MKID(expr->Identifier), expr->_type_unique_index); OUT("%d,\t/* Count of tags in the map */\n", tag2el_count); - OUT("%d\t/* Whether extensible */\n", - check_if_extensible(expr)); + if(C99_MODE) OUT(".canonical_order = "); + if(cmap) OUT("asn_MAP_%s_cmap_%d,\t/* Canonically sorted */\n", + MKID(expr->Identifier), expr->_type_unique_index); + else OUT("0,\n"); + if(C99_MODE) OUT(".ext_start = "); + OUT("%d\t/* Extensions start */\n", + compute_extensions_start(expr)); ); OUT("};\n"); @@ -989,11 +1093,13 @@ asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) { if(!expr->_anonymous_type) { OUT("%s", (expr->marker.flags&EM_INDIRECT)?"\t*":"\t "); OUT("%s", MKID_safe(expr->Identifier)); - if((expr->marker.flags & EM_DEFAULT) == EM_DEFAULT) + if((expr->marker.flags & (EM_DEFAULT & ~EM_INDIRECT)) + == (EM_DEFAULT & ~EM_INDIRECT)) OUT("\t/* DEFAULT %s */", asn1f_printable_value( expr->marker.default_value)); - else if((expr->marker.flags & EM_OPTIONAL) == EM_OPTIONAL) + else if((expr->marker.flags & EM_OPTIONAL) + == EM_OPTIONAL) OUT("\t/* OPTIONAL */"); } @@ -1113,6 +1219,7 @@ asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) { OUT("td->der_encoder = asn_DEF_%s.der_encoder;\n", type_name); OUT("td->xer_decoder = asn_DEF_%s.xer_decoder;\n", type_name); OUT("td->xer_encoder = asn_DEF_%s.xer_encoder;\n", type_name); + OUT("td->uper_decoder = asn_DEF_%s.uper_decoder;\n", type_name); if(!terminal && !tags_count) { OUT("/* The next four lines are here because of -fknown-extern-type */\n"); OUT("td->tags = asn_DEF_%s.tags;\n", type_name); @@ -1121,6 +1228,9 @@ asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) { OUT("td->all_tags_count = asn_DEF_%s.all_tags_count;\n",type_name); OUT("/* End of these lines */\n"); } + OUT("if(!td->per_constraints)\n"); + OUT("\ttd->per_constraints = asn_DEF_%s.per_constraints;\n", + type_name); OUT("td->elements = asn_DEF_%s.elements;\n", type_name); OUT("td->elements_count = asn_DEF_%s.elements_count;\n", type_name); if(etd_spec != ETD_NO_SPECIFICS) { @@ -1230,6 +1340,23 @@ asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) { OUT("}\n"); OUT("\n"); + if(arg->flags & A1C_GEN_PER) { + p = MKID(expr->Identifier); + if(HIDE_INNER_DEFS) OUT("static "); + OUT("asn_dec_rval_t\n"); + OUT("%s", p); + if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index); + OUT("_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,\n"); + INDENTED( + OUT("\tasn_per_constraints_t *constraints, void **structure, asn_per_data_t *per_data) {\n"); + OUT("%s_%d_inherit_TYPE_descriptor(td);\n", + p, expr->_type_unique_index); + OUT("return td->uper_decoder(opt_codec_ctx, td, constraints, structure, per_data);\n"); + ); + OUT("}\n"); + OUT("\n"); + } + REDIR(OT_FUNC_DECLS); p = MKID(expr->Identifier); @@ -1246,6 +1373,8 @@ asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) { OUT("der_type_encoder_f %s_encode_der;\n", p); OUT("xer_type_decoder_f %s_decode_xer;\n", p); OUT("xer_type_encoder_f %s_encode_xer;\n", p); + if(arg->flags & A1C_GEN_PER) + OUT("per_type_decoder_f %s_decode_uper;\n", p); } REDIR(OT_TYPE_DECLS); @@ -1264,12 +1393,16 @@ asn1c_lang_C_type_EXTENSIBLE(arg_t *arg) { return 0; } -static int check_if_extensible(asn1p_expr_t *expr) { +static int +compute_extensions_start(asn1p_expr_t *expr) { asn1p_expr_t *v; + int eidx = 0; TQ_FOR(v, &(expr->members), next) { - if(v->expr_type == A1TC_EXTENSIBLE) return 1; + if(v->expr_type == A1TC_EXTENSIBLE) + return eidx; + eidx++; } - return 0; + return -1; } static int @@ -1414,7 +1547,7 @@ _add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e f assert(el_no >= 0); ret = asn1f_fetch_outmost_tag(arg->asn, arg->expr->module, - arg->expr, &tag, 1); + arg->expr, &tag, AFT_IMAGINARY_ANY); if(ret == 0) { tag2el_t *te; int new_count = (*count) + 1; @@ -1486,9 +1619,9 @@ emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count, const char * if(!tag2el_count) return 0; /* No top level tags */ - OUT("static asn_TYPE_tag2member_t asn_MAP_%s_%d_tag2el%s[] = {\n", - MKID(expr->Identifier), expr->_type_unique_index, - opt_modifier?opt_modifier:""); + OUT("static asn_TYPE_tag2member_t asn_MAP_%s_tag2el%s_%d[] = {\n", + MKID(expr->Identifier), opt_modifier?opt_modifier:"", + expr->_type_unique_index); for(i = 0; i < tag2el_count; i++) { OUT(" { "); _print_tag(arg, &tag2el[i].el_tag); @@ -1551,9 +1684,9 @@ emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tags_count_r, int *all_ta } #define EMIT_TAGS_TABLE(name, tags, tags_count) do { \ - OUT("static ber_tlv_tag_t asn_DEF_%s_%d%s_tags[] = {\n",\ - MKID(expr->Identifier), \ - expr->_type_unique_index, name); \ + OUT("static ber_tlv_tag_t asn_DEF_%s%s_tags_%d[] = {\n",\ + MKID(expr->Identifier), name, \ + expr->_type_unique_index); \ INDENT(+1); \ /* Print the array of collected tags */ \ for(i = 0; i < tags_count; i++) { \ @@ -1608,6 +1741,246 @@ expr_elements_count(arg_t *arg, asn1p_expr_t *expr) { return elements; } +static asn1p_expr_type_e +expr_get_type(arg_t *arg, asn1p_expr_t *expr) { + asn1p_expr_t *terminal; + terminal = asn1f_find_terminal_type_ex(arg->asn, expr); + if(terminal) return terminal->expr_type; + return A1TC_INVALID; +} + +static int +emit_single_member_PER_constraint(arg_t *arg, asn1cnst_range_t *range, char *type) { + if(!range || range->incompatible || range->not_PER_visible) { + OUT("{ APC_UNCONSTRAINED,\t-1, -1, 0, 0 }"); + return 0; + } + + if(range->left.type == ARE_VALUE) { + if(range->right.type == ARE_VALUE) { + asn1c_integer_t cover = 1; + asn1c_integer_t r = 1 + range->right.value + - range->left.value; + int rbits, ebits; + + if(range->empty_constraint) + r = 0; + + /* Compute real constraint */ + for(rbits = 0; rbits < (8 * sizeof(r)); rbits++) { + if(r <= cover) + break; + cover *= 2; /* Can't do shifting */ + if(cover < 0) { + FATAL("Constraint at line %d too wide " + "for %d-bits integer type", + arg->expr->_lineno, + sizeof(r) * 8); + rbits = sizeof(r); + break; + } + } + + if(1) { + /* X.691, #10.9.4.1 */ + for(ebits = 0; ebits <= 16; ebits++) + if(r <= 1 << ebits) break; + if(ebits == 17 + || range->right.value >= 65536) + ebits = -1; + } else { + /* X.691, #10.5.7.1 */ + for(ebits = 0; ebits <= 8; ebits++) + if(r <= 1 << ebits) break; + if(ebits == 9) { + if(r <= 65536) + ebits = 16; + else + ebits = -1; + } + } + OUT("{ APC_CONSTRAINED%s,%s% d, % d, ", + range->extensible + ? " | APC_EXTENSIBLE" : "", + range->extensible ? " " : "\t", rbits, ebits); + } else { + if(range->extensible) { + OUT("{ APC_SEMI_CONSTRAINED | APC_EXTENSIBLE, " + "-1, "); + } else { + OUT("{ APC_SEMI_CONSTRAINED,\t-1, -1, "); + } + } + OUT("% " PRIdASN ", % " PRIdASN " }", + range->left.value, range->right.value); + } else { + OUT("{ APC_UNCONSTRAINED,\t-1, -1, 0, 0 }"); + } + + /* + * Print some courtesy debug information. + */ + if(range->left.type == ARE_VALUE + || range->right.type == ARE_VALUE) { + OUT("\t/* "); + if(type) OUT("(%s", type); + OUT("("); + if(range->left.type == ARE_VALUE) + OUT("%" PRIdASN, range->left.value); + else + OUT("MIN"); + OUT(".."); + if(range->right.type == ARE_VALUE) + OUT("%" PRIdASN, range->right.value); + else + OUT("MAX"); + if(range->extensible) OUT(",..."); + if(type) OUT(")"); + OUT(") */"); + } + + return 0; +} + +static int +emit_single_member_PER_constraints(arg_t *arg, asn1p_expr_t *expr) { + asn1cnst_range_t *range; + asn1p_expr_type_e etype; + + etype = expr_get_type(arg, expr); + + INDENT(+1); + + /* + * ENUMERATED and CHOICE are special. + */ + if(etype == ASN_BASIC_ENUMERATED + || etype == ASN_CONSTR_CHOICE) { + asn1cnst_range_t tmprng; + asn1p_expr_t *v; + int extensible = 0; + int eidx = -1; + + expr = asn1f_find_terminal_type_ex(arg->asn, expr); + assert(expr); + + TQ_FOR(v, &(expr->members), next) { + if(v->expr_type == A1TC_EXTENSIBLE) { + extensible++; + break; + } + eidx++; + } + + memset(&tmprng, 0, sizeof (tmprng)); + tmprng.extensible = extensible; + if(eidx < 0) tmprng.empty_constraint = 1; + tmprng.left.type = ARE_VALUE; + tmprng.left.value = 0; + tmprng.right.type = ARE_VALUE; + tmprng.right.value = eidx < 0 ? 0 : eidx; + if(emit_single_member_PER_constraint(arg, &tmprng, 0)) + return -1; + } else { + range = asn1constraint_compute_PER_range(etype, + expr->combined_constraints, ACT_EL_RANGE, + 0, 0, 0); + if(emit_single_member_PER_constraint(arg, range, 0)) + return -1; + asn1constraint_range_free(range); + } + OUT(",\n"); + + range = asn1constraint_compute_PER_range(etype, + expr->combined_constraints, ACT_CT_SIZE, 0, 0, 0); + if(emit_single_member_PER_constraint(arg, range, "SIZE")) + return -1; + asn1constraint_range_free(range); + OUT("\n"); + + INDENT(-1); + + return 0; +} + +static int +emit_members_PER_constraints(arg_t *arg) { + asn1p_expr_t *expr = arg->expr; + asn1p_expr_t *v; + + if(!(arg->flags & A1C_GEN_PER)) + return 0; + + TQ_FOR(v, &(expr->members), next) { + if(v->constraints + || v->expr_type == ASN_BASIC_ENUMERATED + || v->expr_type == ASN_CONSTR_CHOICE) { + OUT("static asn_per_constraints_t " + "asn_PER_memb_%s_constr_%d = {\n", + MKID(v->Identifier), v->_type_unique_index); + if(emit_single_member_PER_constraints(arg, v)) + return -1; + OUT("};\n"); + } + } + + return 0; +} + +static int +try_inline_default(arg_t *arg, asn1p_expr_t *expr, int out) { + int save_target = arg->target->target; + asn1p_expr_type_e etype = expr_get_type(arg, expr); + int fits_long = 0; + + switch(etype) { + case ASN_BASIC_BOOLEAN: + fits_long = 1; + case ASN_BASIC_INTEGER: + case ASN_BASIC_ENUMERATED: + if(expr->marker.default_value == NULL + || expr->marker.default_value->type != ATV_INTEGER) + break; + if(!fits_long) + fits_long = asn1c_type_fits_long(arg, expr)!=FL_NOTFIT; + if(fits_long && !expr->marker.default_value->value.v_integer) + expr->marker.flags &= ~EM_INDIRECT; + if(!out) return 1; + REDIR(OT_STAT_DEFS); + OUT("static int asn_DFL_%d_set_%" PRIdASN "(void **sptr) {\n", + expr->_type_unique_index, + expr->marker.default_value->value.v_integer); + INDENT(+1); + OUT("%s *st = *sptr;\n", asn1c_type_name(arg, expr, TNF_CTYPE)); + OUT("\n"); + OUT("if(!st) {\n"); + OUT("\tst = (*sptr = CALLOC(1, sizeof(*st)));\n"); + OUT("\tif(!st) return -1;\n"); + OUT("}\n"); + OUT("\n"); + OUT("/* Install default value %" PRIdASN " */\n", + expr->marker.default_value->value.v_integer); + if(fits_long) { + OUT("*st = %" PRIdASN ";\n", + expr->marker.default_value->value.v_integer); + OUT("return 0;\n"); + } else { + OUT("return asn_long2INTEGER(st, %" PRIdASN ");\n", + expr->marker.default_value->value.v_integer); + } + INDENT(-1); + OUT("}\n"); + REDIR(save_target); + return 1; + case ASN_BASIC_NULL: + //expr->marker.flags &= ~EM_INDIRECT; + return 0; + default: + break; + } + return 0; +} + static int emit_member_table(arg_t *arg, asn1p_expr_t *expr) { int save_target; @@ -1618,7 +1991,8 @@ emit_member_table(arg_t *arg, asn1p_expr_t *expr) { char *p; if(asn1f_fetch_outmost_tag(arg->asn, - expr->module, expr, &outmost_tag_s, 1)) { + expr->module, expr, &outmost_tag_s, + AFT_IMAGINARY_ANY)) { outmost_tag = 0; } else { outmost_tag = &outmost_tag_s; @@ -1702,20 +2076,41 @@ emit_member_table(arg_t *arg, asn1p_expr_t *expr) { if(expr->_anonymous_type && !strcmp(expr->Identifier, "Member")) id = asn1c_type_name(arg, expr, TNF_SAFE); - OUT("memb_%s_%d_constraint,\n", id, + OUT("memb_%s_constraint_%d,\n", id, arg->expr->_type_unique_index); } } else { OUT("0,\t/* Defer constraints checking to the member type */\n"); } + if(C99_MODE) OUT(".per_constraints = "); + if(arg->flags & A1C_GEN_PER) { + if(expr->constraints + || expr->expr_type == ASN_BASIC_ENUMERATED + || expr->expr_type == ASN_CONSTR_CHOICE) { + OUT("&asn_PER_memb_%s_constr_%d,\n", + MKID(expr->Identifier), + expr->_type_unique_index); + } else { + OUT("0,\t/* No PER visible constraints */\n"); + } + } else { + OUT("0,\t/* PER is not compiled, use -gen-PER */\n"); + } + if(C99_MODE) OUT(".default_value = "); + if(try_inline_default(arg, expr, 0)) { + OUT("asn_DFL_%d_set_%" PRIdASN + ",\t/* DEFAULT %" PRIdASN " */\n", + expr->_type_unique_index, + expr->marker.default_value->value.v_integer, + expr->marker.default_value->value.v_integer); + } else { + OUT("0,\n"); + } if(C99_MODE) OUT(".name = "); - if(1) { - if(expr->_anonymous_type && !strcmp(expr->Identifier, "Member")) - OUT("\"\"\n"); - else - OUT("\"%s\"\n", expr->Identifier); + if(expr->_anonymous_type && !strcmp(expr->Identifier, "Member")) { + OUT("\"\"\n"); } else { - OUT("\"%s\"\n", expr->_anonymous_type ? "" : expr->Identifier); + OUT("\"%s\"\n", expr->Identifier); } OUT("},\n"); INDENT(-1); @@ -1731,7 +2126,7 @@ emit_member_table(arg_t *arg, asn1p_expr_t *expr) { else p = MKID(expr->Identifier); OUT("static int\n"); - OUT("memb_%s_%d_constraint(asn_TYPE_descriptor_t *td, const void *sptr,\n", p, arg->expr->_type_unique_index); + OUT("memb_%s_constraint_%d(asn_TYPE_descriptor_t *td, const void *sptr,\n", p, arg->expr->_type_unique_index); INDENT(+1); OUT("\t\tasn_app_consume_bytes_f *app_errlog, void *app_key) {\n"); tmp_arg = *arg; @@ -1755,21 +2150,41 @@ emit_member_table(arg_t *arg, asn1p_expr_t *expr) { static int emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, enum tvm_compat tv_mode, int tags_count, int all_tags_count, int elements_count, enum etd_spec spec) { int using_type_name = 0; - char *p; + char *p = MKID(expr->Identifier); + + if((arg->flags & A1C_GEN_PER) + && (expr->constraints + || expr->expr_type == ASN_BASIC_ENUMERATED + || expr->expr_type == ASN_CONSTR_CHOICE) + ) { + OUT("static asn_per_constraints_t asn_PER_%s_constr_%d = {\n", + p, expr->_type_unique_index); + if(emit_single_member_PER_constraints(arg, expr)) + return -1; + OUT("};\n"); + } if(HIDE_INNER_DEFS) OUT("static /* Use -fall-defs-global to expose */\n"); - OUT("asn_TYPE_descriptor_t asn_DEF_%s", MKID(expr->Identifier)); + OUT("asn_TYPE_descriptor_t asn_DEF_%s", p); if(HIDE_INNER_DEFS) OUT("_%d", expr->_type_unique_index); OUT(" = {\n"); - p = MKID(expr->Identifier); INDENT(+1); - OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier); - OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier); + + if(expr->_anonymous_type) { + p = ASN_EXPR_TYPE2STR(expr->expr_type); + OUT("\"%s\",\n", p?p:""); + OUT("\"%s\",\n", MKID(p?p:"")); + } else { + OUT("\"%s\",\n", expr->Identifier); + OUT("\"%s\",\n", expr->Identifier); + } if(expr->expr_type & ASN_CONSTR_MASK) { using_type_name = 1; p = asn1c_type_name(arg, arg->expr, TNF_SAFE); + } else { + p = MKID(expr->Identifier); } #define FUNCREF(foo) do { \ @@ -1786,6 +2201,10 @@ emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, enum tvm_compat tv_mode, int tags_ FUNCREF(encode_der); FUNCREF(decode_xer); FUNCREF(encode_xer); + if(arg->flags & A1C_GEN_PER) + FUNCREF(decode_uper); + else + OUT("0,\t/* No PER decoder, -gen-PER to enable */\n"); if(expr->expr_type == ASN_CONSTR_CHOICE) { OUT("CHOICE_outmost_tag,\n"); @@ -1795,11 +2214,11 @@ emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, enum tvm_compat tv_mode, int tags_ p = MKID(expr->Identifier); if(tags_count) { - OUT("asn_DEF_%s_%d_tags,\n", + OUT("asn_DEF_%s_tags_%d,\n", p, expr->_type_unique_index); - OUT("sizeof(asn_DEF_%s_%d_tags)\n", + OUT("sizeof(asn_DEF_%s_tags_%d)\n", p, expr->_type_unique_index); - OUT("\t/sizeof(asn_DEF_%s_%d_tags[0])", + OUT("\t/sizeof(asn_DEF_%s_tags_%d[0])", p, expr->_type_unique_index); if(tv_mode == _TVM_SUBSET && tags_count != all_tags_count) @@ -1811,24 +2230,37 @@ emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, enum tvm_compat tv_mode, int tags_ } if(all_tags_count && tv_mode == _TVM_DIFFERENT) { - OUT("asn_DEF_%s_%d_all_tags,\n", + OUT("asn_DEF_%s_all_tags_%d,\n", p, expr->_type_unique_index); - OUT("sizeof(asn_DEF_%s_%d_all_tags)\n", + OUT("sizeof(asn_DEF_%s_all_tags_%d)\n", p, expr->_type_unique_index); - OUT("\t/sizeof(asn_DEF_%s_%d_all_tags[0]), /* %d */\n", + OUT("\t/sizeof(asn_DEF_%s_all_tags_%d[0]), /* %d */\n", p, expr->_type_unique_index, all_tags_count); } else if(all_tags_count) { - OUT("asn_DEF_%s_%d_tags,\t/* Same as above */\n", + OUT("asn_DEF_%s_tags_%d,\t/* Same as above */\n", p, expr->_type_unique_index); - OUT("sizeof(asn_DEF_%s_%d_tags)\n", + OUT("sizeof(asn_DEF_%s_tags_%d)\n", p, expr->_type_unique_index); - OUT("\t/sizeof(asn_DEF_%s_%d_tags[0]), /* %d */\n", + OUT("\t/sizeof(asn_DEF_%s_tags_%d[0]), /* %d */\n", p, expr->_type_unique_index, all_tags_count); } else { OUT("0,\t/* No tags (pointer) */\n"); OUT("0,\t/* No tags (count) */\n"); } + if(arg->flags & A1C_GEN_PER) { + if(expr->constraints + || expr->expr_type == ASN_BASIC_ENUMERATED + || expr->expr_type == ASN_CONSTR_CHOICE) { + OUT("&asn_PER_%s_constr_%d,\n", + p, expr->_type_unique_index); + } else { + OUT("0,\t/* No PER visible constraints */\n"); + } + } else { + OUT("0,\t/* No PER visible constraints */\n"); + } + if(elements_count) { OUT("asn_MBR_%s_%d,\n", p, expr->_type_unique_index); if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF @@ -1852,7 +2284,7 @@ emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, enum tvm_compat tv_mode, int tags_ OUT("0\t/* No specifics */\n"); break; case ETD_HAS_SPECIFICS: - OUT("&asn_SPC_%s_%d_specs\t/* Additional specs */\n", + OUT("&asn_SPC_%s_specs_%d\t/* Additional specs */\n", p, expr->_type_unique_index); } INDENT(-1); @@ -1864,13 +2296,10 @@ emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, enum tvm_compat tv_mode, int tags_ static int expr_as_xmlvaluelist(arg_t *arg, asn1p_expr_t *expr) { - expr = asn1f_find_terminal_type_ex(arg->asn, expr); - if(!expr) return 0; - /* * X.680, 25.5, Table 5 */ - switch(expr->expr_type) { + switch(expr_get_type(arg, expr)) { case ASN_BASIC_BOOLEAN: case ASN_BASIC_ENUMERATED: case ASN_BASIC_NULL: @@ -1966,19 +2395,15 @@ emit_include_dependencies(arg_t *arg) { */ static int expr_break_recursion(arg_t *arg, asn1p_expr_t *expr) { - asn1p_expr_t *terminal; int ret; if(expr->marker.flags & EM_UNRECURSE) return 1; /* Already broken */ - terminal = asn1f_find_terminal_type_ex(arg->asn, expr); - /* -findirect-choice compiles members of CHOICE as indirect pointers */ if((arg->flags & A1C_INDIRECT_CHOICE) && arg->expr->expr_type == ASN_CONSTR_CHOICE - && terminal - && (terminal->expr_type & ASN_CONSTR_MASK) + && (expr_get_type(arg, expr) & ASN_CONSTR_MASK) ) { /* Break cross-reference */ expr->marker.flags |= EM_INDIRECT | EM_UNRECURSE; @@ -2094,3 +2519,83 @@ expr_defined_recursively(arg_t *arg, asn1p_expr_t *expr) { /* Look inside the terminal type if it mentions the parent expression */ return asn1c_recurse(arg, terminal, check_is_refer_to, topmost); } + +struct canonical_map_element { + int eidx; + asn1p_expr_t *expr; +}; +static int compar_cameo(const void *ap, const void *bp); +static arg_t *cameo_arg; +static int * +compute_canonical_members_order(arg_t *arg, int el_count) { + struct canonical_map_element *cmap; + int *rmap; + asn1p_expr_t *v; + int eidx = 0; + int ext_start = -1; + int nextmax = -1; + int already_sorted = 1; + + cmap = calloc(el_count, sizeof *cmap); + assert(cmap); + + TQ_FOR(v, &(arg->expr->members), next) { + if(v->expr_type != A1TC_EXTENSIBLE) { + cmap[eidx].eidx = eidx; + cmap[eidx].expr = v; + eidx++; + } else if(ext_start == -1) + ext_start = eidx; + } + + cameo_arg = arg; + if(ext_start == -1) { + /* Sort the whole thing */ + qsort(cmap, el_count, sizeof(*cmap), compar_cameo); + } else { + /* Sort root and extensions independently */ + qsort(cmap, ext_start, sizeof(*cmap), compar_cameo); + qsort(cmap + ext_start, el_count - ext_start, + sizeof(*cmap), compar_cameo); + } + + /* move data back to a simpler map */ + rmap = calloc(el_count, sizeof *rmap); + assert(rmap); + for(eidx = 0; eidx < el_count; eidx++) { + rmap[eidx] = cmap[eidx].eidx; + if(rmap[eidx] <= nextmax) + already_sorted = 0; + else + nextmax = rmap[eidx]; + } + free(cmap); + + if(already_sorted) { free(rmap); rmap = 0; } + return rmap; +} +static int compar_cameo(const void *ap, const void *bp) { + const struct canonical_map_element *a = (const void *)ap; + const struct canonical_map_element *b = (const void *)bp; + struct asn1p_type_tag_s atag, btag; + arg_t *arg = cameo_arg; + + if(asn1f_fetch_outmost_tag(arg->asn, a->expr->module, a->expr, + &atag, AFT_IMAGINARY_ANY | AFT_CANON_CHOICE)) + return 1; + + if(asn1f_fetch_outmost_tag(arg->asn, b->expr->module, b->expr, + &btag, AFT_IMAGINARY_ANY | AFT_CANON_CHOICE)) + return -1; + + if(atag.tag_class < btag.tag_class) + return -1; + if(atag.tag_class > btag.tag_class) + return 1; + if(atag.tag_value < btag.tag_value) + return -1; + if(atag.tag_value > btag.tag_value) + return 1; + return 0; + +} diff --git a/libasn1compiler/asn1c_constraint.c b/libasn1compiler/asn1c_constraint.c index 8af5e368..5388bb3d 100644 --- a/libasn1compiler/asn1c_constraint.c +++ b/libasn1compiler/asn1c_constraint.c @@ -4,7 +4,7 @@ #include "asn1c_out.h" #include <asn1fix_crange.h> /* constraint groker from libasn1fix */ -#include <asn1fix_export.h> /* other exportable stuff from libasn1fix */ +#include <asn1fix_export.h> /* other exportables from libasn1fix */ static int asn1c_emit_constraint_tables(arg_t *arg, int got_size); static int emit_alphabet_check_loop(arg_t *arg, asn1cnst_range_t *range); diff --git a/libasn1compiler/asn1c_fdeps.c b/libasn1compiler/asn1c_fdeps.c index 0066f51a..80ba2f68 100644 --- a/libasn1compiler/asn1c_fdeps.c +++ b/libasn1compiler/asn1c_fdeps.c @@ -66,7 +66,12 @@ asn1c_read_file_dependencies(arg_t *arg, const char *datadir) { asn1c_fdeps_t *cur; char buf[4096]; FILE *f; - int hit_COMMON_FILES = 0; + enum { + SS_DYNAMIC, /* Dynamic list of dependencies */ + SS_CODEC_PER, /* Use contents only if -gen-PER */ + SS_COMMON_FILES, /* Section for dependencies */ + SS_IGNORE /* Ignore contents of this section */ + } special_section = SS_DYNAMIC; (void)arg; @@ -91,17 +96,27 @@ asn1c_read_file_dependencies(arg_t *arg, const char *datadir) { for(p = strtok(buf, " \t\r\n"); p; p = strtok(NULL, " \t\r\n")) { asn1c_fdeps_t *d; + /* - * If hit "COMMON-FILES:", treat everything else - * as a huge dependency. + * Special "prefix" section. */ - if(strcmp(p, "COMMON-FILES:") == 0) { - hit_COMMON_FILES = 1; + if(strchr(p, ':')) { + special_section = SS_IGNORE; + if(strcmp(p, "COMMON-FILES:") == 0) { + special_section = SS_COMMON_FILES; + } else if((arg->flags & A1C_GEN_PER) + && strcmp(p, "CODEC-PER:") == 0) { + special_section = SS_CODEC_PER; + } break; } + + if(special_section == SS_IGNORE) + continue; + d = asn1c_new_dep(p); assert(d); - d->used_somewhere = hit_COMMON_FILES; + d->used_somewhere = special_section; if(asn1c_dep_add(cur, d) == 1) cur = d; diff --git a/libasn1compiler/asn1c_save.c b/libasn1compiler/asn1c_save.c index d35db940..dca0cf1b 100644 --- a/libasn1compiler/asn1c_save.c +++ b/libasn1compiler/asn1c_save.c @@ -11,6 +11,7 @@ static int asn1c_print_streams(arg_t *arg); static int asn1c_save_streams(arg_t *arg, asn1c_fdeps_t *); static int asn1c_copy_over(arg_t *arg, char *path); static int identical_files(const char *fname1, const char *fname2); +static int generate_pdu_collection_file(arg_t *arg); int asn1c_save_compiled_output(arg_t *arg, const char *datadir, @@ -18,7 +19,7 @@ asn1c_save_compiled_output(arg_t *arg, const char *datadir, asn1c_fdeps_t *deps = 0; asn1c_fdeps_t *dlist; asn1p_module_t *mod; - FILE *mkf; + FILE *mkf; /* Makefile.am.sample */ int i; deps = asn1c_read_file_dependencies(arg, datadir); @@ -108,6 +109,12 @@ asn1c_save_compiled_output(arg_t *arg, const char *datadir, } } + if(arg->flags & A1C_PDU_AUTO) { + fprintf(mkf, "ASN_MODULE_SOURCES+=pdu_collection.c\n"); + if(generate_pdu_collection_file(arg)) + return -1; + } + fprintf(mkf, "\n\n" "lib_LTLIBRARIES=libsomething.la\n" "libsomething_la_SOURCES=" @@ -438,3 +445,62 @@ asn1c_copy_over(arg_t *arg, char *path) { return 1; } + +static int +generate_pdu_collection_file(arg_t *arg) { + asn1p_module_t *mod; + FILE *fp; + + fp = asn1c_open_file("pdu_collection", ".c", 0); + if(fp == NULL) { + perror("pdu_collection.c"); + return -1; + } + + fprintf(fp, + "/*\n" + " * Generated by asn1c-" VERSION " (http://lionet.info/asn1c)\n" + " */\n\n"); + fprintf(fp, "struct asn_TYPE_descriptor_s;\t" + "/* Forward declaration */\n\n"); + + TQ_FOR(mod, &(arg->asn->modules), mod_next) { + TQ_FOR(arg->expr, &(mod->members), next) { + if(arg->expr->_type_referenced + || !asn1_lang_map[arg->expr->meta_type] + [arg->expr->expr_type].type_cb) + continue; + fprintf(fp, "extern struct asn_TYPE_descriptor_s " + "asn_DEF_%s;\n", + asn1c_make_identifier(0, arg->expr->Identifier, + NULL)); + } + } + + fprintf(fp, "\n\n"); + fprintf(fp, "struct asn_TYPE_descriptor_s *asn_pdu_collection[] = {\n"); + TQ_FOR(mod, &(arg->asn->modules), mod_next) { + int mod_printed = 0; + TQ_FOR(arg->expr, &(mod->members), next) { + if(arg->expr->_type_referenced + || !asn1_lang_map[arg->expr->meta_type] + [arg->expr->expr_type].type_cb) + continue; + if(!mod_printed++) + fprintf(fp, "\t/* From module %s in %s */\n", + arg->expr->module->ModuleName, + arg->expr->module->source_file_name); + fprintf(fp, "\t&asn_DEF_%s,\t\n", + asn1c_make_identifier(0, arg->expr->Identifier, + NULL)); + } + } + + fprintf(fp, "\t0\n};\n\n"); + + fclose(fp); + fprintf(stderr, "Generated pdu_collection.c\n"); + + return 0; +} + diff --git a/libasn1compiler/asn1compiler.h b/libasn1compiler/asn1compiler.h index 847300ff..e33628f8 100644 --- a/libasn1compiler/asn1compiler.h +++ b/libasn1compiler/asn1compiler.h @@ -56,6 +56,16 @@ enum asn1c_flags { * Copy support files rather than symlink them. */ A1C_SKELETONS_COPY = 0x0800, + /* + * -gen-PER + * Generate PER support code + */ + A1C_GEN_PER = 0x1000, + /* + * -pdu=auto + * Generate PDU table + */ + A1C_PDU_AUTO = 0x2000 }; /* |