aboutsummaryrefslogtreecommitdiffstats
path: root/libasn1compiler/asn1c_C.c
diff options
context:
space:
mode:
Diffstat (limited to 'libasn1compiler/asn1c_C.c')
-rw-r--r--libasn1compiler/asn1c_C.c164
1 files changed, 123 insertions, 41 deletions
diff --git a/libasn1compiler/asn1c_C.c b/libasn1compiler/asn1c_C.c
index c448795a..485e990a 100644
--- a/libasn1compiler/asn1c_C.c
+++ b/libasn1compiler/asn1c_C.c
@@ -29,9 +29,15 @@ static int check_if_extensible(asn1p_expr_t *expr);
static int expr_better_indirect(arg_t *arg, asn1p_expr_t *expr);
static int expr_elements_count(arg_t *arg, asn1p_expr_t *expr);
static int emit_member_table(arg_t *arg, asn1p_expr_t *expr);
-static int emit_tags_vector(arg_t *arg, asn1p_expr_t *expr);
static int emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count);
+enum tvm_compat {
+ _TVM_SAME = 0, /* tags and all_tags are same */
+ _TVM_SUBSET = 1, /* tags are subset of all_tags */
+ _TVM_DIFFERENT = 2, /* tags and all_tags are different */
+};
+static enum tvm_compat emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tc, int *atc);
+
enum etd_cp {
ETD_CP_UNKNOWN = -2,
ETD_CP_EITHER = -1,
@@ -42,7 +48,7 @@ enum etd_spec {
ETD_NO_SPECIFICS,
ETD_HAS_SPECIFICS
};
-static int emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, int tags_count, int elements_count, enum etd_cp, enum etd_spec);
+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_cp, enum etd_spec);
#define C99_MODE (!(arg->flags & A1C_NO_C99))
#define UNNAMED_UNIONS (arg->flags & A1C_UNNAMED_UNIONS)
@@ -175,6 +181,8 @@ asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
tag2el_t *tag2el = NULL;
int tag2el_count = 0;
int tags_count;
+ int all_tags_count;
+ enum tvm_compat tv_mode;
char *p;
/*
@@ -212,9 +220,9 @@ asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
OUT("};\n");
/*
- * Print out asn1_DEF_<type>_tags[] vector.
+ * Print out asn1_DEF_<type>_[all_]tags[] vectors.
*/
- tags_count = emit_tags_vector(arg, expr);
+ tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
/*
* Tags to elements map.
@@ -238,7 +246,7 @@ asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
/*
* Emit asn1_DEF_xxx table.
*/
- emit_type_DEF(arg, expr, tags_count, elements,
+ emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
REDIR(OT_TYPE_DECLS);
@@ -322,6 +330,8 @@ asn1c_lang_C_type_SET_def(arg_t *arg) {
tag2el_t *tag2el = NULL;
int tag2el_count = 0;
int tags_count;
+ int all_tags_count;
+ enum tvm_compat tv_mode;
char *p;
/*
@@ -359,9 +369,9 @@ asn1c_lang_C_type_SET_def(arg_t *arg) {
OUT("};\n");
/*
- * Print out asn1_DEF_<type>_tags[] vector.
+ * Print out asn1_DEF_<type>_[all_]tags[] vectors.
*/
- tags_count = emit_tags_vector(arg, expr);
+ tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
/*
* Tags to elements map.
@@ -417,7 +427,7 @@ asn1c_lang_C_type_SET_def(arg_t *arg) {
/*
* Emit asn1_DEF_xxx table.
*/
- emit_type_DEF(arg, expr, tags_count, elements,
+ emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
REDIR(OT_TYPE_DECLS);
@@ -483,6 +493,8 @@ asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
asn1p_expr_t *expr = arg->expr;
asn1p_expr_t *v;
int tags_count;
+ int all_tags_count;
+ enum tvm_compat tv_mode;
char *p;
/*
@@ -511,9 +523,9 @@ asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
OUT("};\n");
/*
- * Print out asn1_DEF_<type>_tags[] vector.
+ * Print out asn1_DEF_<type>_[all_]tags[] vectors.
*/
- tags_count = emit_tags_vector(arg, expr);
+ tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
p = MKID(expr->Identifier);
OUT("static asn1_SET_OF_specifics_t asn1_DEF_%s_specs = {\n", p);
@@ -526,7 +538,7 @@ asn1c_lang_C_type_SEx_OF_def(arg_t *arg, int seq_of) {
/*
* Emit asn1_DEF_xxx table.
*/
- emit_type_DEF(arg, expr, tags_count, 1,
+ emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, 1,
ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
REDIR(OT_TYPE_DECLS);
@@ -600,6 +612,8 @@ asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
tag2el_t *tag2el = NULL;
int tag2el_count = 0;
int tags_count;
+ int all_tags_count;
+ enum tvm_compat tv_mode;
char *p;
/*
@@ -641,9 +655,11 @@ asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
/*
* Our parent structure has already taken this into account.
*/
- tags_count = 0;
+ tv_mode = _TVM_SAME;
+ tags_count = all_tags_count = 0;
} else {
- tags_count = emit_tags_vector(arg, expr);
+ tv_mode = emit_tags_vectors(arg, expr,
+ &tags_count, &all_tags_count);
}
/*
@@ -668,7 +684,7 @@ asn1c_lang_C_type_CHOICE_def(arg_t *arg) {
/*
* Emit asn1_DEF_xxx table.
*/
- emit_type_DEF(arg, expr, tags_count, elements,
+ emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
ETD_CP_CONSTRUCTED /*either?!*/, ETD_HAS_SPECIFICS);
REDIR(OT_TYPE_DECLS);
@@ -724,6 +740,8 @@ int
asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
asn1p_expr_t *expr = arg->expr;
int tags_count;
+ int all_tags_count;
+ enum tvm_compat tv_mode;
char *p;
if(arg->embed) {
@@ -754,11 +772,11 @@ asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
REDIR(OT_STAT_DEFS);
/*
- * Print out asn1_DEF_<type>_tags[] vector.
+ * Print out asn1_DEF_<type>_[all_]tags[] vectors.
*/
- tags_count = emit_tags_vector(arg, expr);
+ tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
- emit_type_DEF(arg, expr, tags_count, 0,
+ emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, 0,
ETD_CP_UNKNOWN, ETD_NO_SPECIFICS);
REDIR(OT_CODE);
@@ -816,9 +834,11 @@ asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
OUT("td->free_struct = asn1_DEF_%s.free_struct;\n", type_name);
OUT("td->print_struct = asn1_DEF_%s.print_struct;\n", type_name);
if(!terminal && !tags_count) {
- OUT("/* The next two lines are because of -fknown-extern-type */\n");
+ OUT("/* The next four lines are here because of -fknown-extern-type */\n");
OUT("td->tags = asn1_DEF_%s.tags;\n", type_name);
OUT("td->tags_count = asn1_DEF_%s.tags_count;\n", type_name);
+ OUT("td->all_tags = asn1_DEF_%s.all_tags;\n", type_name);
+ OUT("td->all_tags_count = asn1_DEF_%s.all_tags_count;\n",type_name);
OUT("/* End of these lines */\n");
}
OUT("td->last_tag_form = asn1_DEF_%s.last_tag_form;\n", type_name);
@@ -1122,33 +1142,77 @@ emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count) {
return 0;;
}
-static int
-emit_tags_vector(arg_t *arg, asn1p_expr_t *expr) {
- struct asn1p_type_tag_s *tags = 0;
+static enum tvm_compat
+emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tags_count_r, int *all_tags_count_r) {
+ struct asn1p_type_tag_s *tags = 0; /* Effective tags */
+ struct asn1p_type_tag_s *all_tags = 0; /* The full array */
int tags_count = 0;
+ int all_tags_count = 0;
+ enum tvm_compat tv_mode = _TVM_SAME;
int i;
/* Fetch a chain of tags */
tags_count = asn1f_fetch_tags(arg->asn, arg->mod, expr, &tags, 0);
- if(tags_count <= 0)
- return 0;
+ if(tags_count < 0) return -1;
- OUT("static ber_tlv_tag_t asn1_DEF_%s_tags[] = {\n",
- MKID(expr->Identifier));
- INDENT(+1);
+ /* Fetch a chain of tags */
+ all_tags_count = asn1f_fetch_tags(arg->asn, arg->mod, expr,
+ &all_tags, AFT_FULL_COLLECT);
+ if(all_tags_count < 0) {
+ if(tags) free(tags);
+ return -1;
+ }
+
+ assert(tags_count <= all_tags_count);
+ assert((tags_count?0:1) == (all_tags_count?0:1));
- /* Print the array of collected tags */
- for(i = 0; i < tags_count; i++) {
- if(i) OUT(",\n");
- _print_tag(arg, &tags[i]);
+ if(tags_count <= all_tags_count) {
+ for(i = 0; i < tags_count; i++) {
+ if(tags[i].tag_value != all_tags[i].tag_value
+ || tags[i].tag_class != all_tags[i].tag_class) {
+ tv_mode = _TVM_DIFFERENT;
+ break;
+ }
+ }
+ if(i == tags_count && tags_count < all_tags_count)
+ tv_mode = _TVM_SUBSET;
+ } else {
+ tv_mode = _TVM_DIFFERENT;
}
- OUT("\n");
- INDENT(-1);
- OUT("};\n");
+#define EMIT_TAGS_TABLE(name, tags, tags_count) do { \
+ OUT("static ber_tlv_tag_t asn1_DEF_%s%s_tags[] = {\n", \
+ MKID(expr->Identifier), name); \
+ INDENT(+1); \
+ /* Print the array of collected tags */ \
+ for(i = 0; i < tags_count; i++) { \
+ if(i) OUT(",\n"); \
+ _print_tag(arg, &tags[i]); \
+ } \
+ OUT("\n"); \
+ INDENT(-1); \
+ OUT("};\n"); \
+ } while(0)
+
+ if(tags_count) {
+ if(tv_mode == _TVM_SUBSET)
+ EMIT_TAGS_TABLE("", all_tags, all_tags_count);
+ else
+ EMIT_TAGS_TABLE("", tags, tags_count);
+ }
+
+ if(all_tags_count) {
+ if(tv_mode == _TVM_DIFFERENT)
+ EMIT_TAGS_TABLE("_all", all_tags, all_tags_count);
+ }
+
+ if(tags) free(tags);
+ if(all_tags) free(all_tags);
+
+ *tags_count_r = tags_count;
+ *all_tags_count_r = all_tags_count;
- free(tags);
- return tags_count;
+ return tv_mode;
}
static int
@@ -1293,14 +1357,14 @@ emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
}
static int
-emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, int tags_count, int elements_count, enum etd_cp cp, enum etd_spec spec) {
+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_cp cp, enum etd_spec spec) {
char *p;
p = MKID(expr->Identifier);
if(HIDE_INNER_DEFS)
OUT("static /* Use -fall-defs-global to expose */\n");
OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
- INDENTED(
+ INDENT(+1);
OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
if(expr->expr_type & ASN_CONSTR_MASK) {
@@ -1324,11 +1388,29 @@ emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, int tags_count, int elements_count
if(tags_count) {
OUT("asn1_DEF_%s_tags,\n", p);
OUT("sizeof(asn1_DEF_%s_tags)\n", p);
+ OUT("\t/sizeof(asn1_DEF_%s_tags[0])", p);
+ if(tv_mode == _TVM_SUBSET
+ && tags_count != all_tags_count)
+ OUT(" - %d", all_tags_count - tags_count);
+ OUT(", /* %d */\n", tags_count);
+ } else {
+ OUT("0,\t/* No effective tags (pointer) */\n");
+ OUT("0,\t/* No effective tags (count) */\n");
+ }
+
+ if(all_tags_count && tv_mode == _TVM_DIFFERENT) {
+ OUT("asn1_DEF_%s_all_tags,\n", p);
+ OUT("sizeof(asn1_DEF_%s_all_tags)\n", p);
+ OUT("\t/sizeof(asn1_DEF_%s_all_tags[0]), /* %d */\n",
+ p, all_tags_count);
+ } else if(all_tags_count) {
+ OUT("asn1_DEF_%s_tags,\t/* Same as above */\n", p);
+ OUT("sizeof(asn1_DEF_%s_tags)\n", p);
OUT("\t/sizeof(asn1_DEF_%s_tags[0]), /* %d */\n",
- p, tags_count);
+ p, all_tags_count);
} else {
- OUT("0,\t/* No explicit tags (pointer) */\n");
- OUT("0,\t/* No explicit tags (count) */\n");
+ OUT("0,\t/* No tags (pointer) */\n");
+ OUT("0,\t/* No tags (count) */\n");
}
switch(cp) {
@@ -1371,7 +1453,7 @@ emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, int tags_count, int elements_count
case ETD_HAS_SPECIFICS:
OUT("&asn1_DEF_%s_specs\t/* Additional specs */\n", p);
}
- );
+ INDENT(-1);
OUT("};\n");
OUT("\n");