aboutsummaryrefslogtreecommitdiffstats
path: root/libasn1compiler
diff options
context:
space:
mode:
authorLev Walkin <vlm@lionet.info>2005-08-18 13:38:19 +0000
committerLev Walkin <vlm@lionet.info>2005-08-18 13:38:19 +0000
commitb85a8135dae955c09b23197f5497b8ff911d083d (patch)
treeafc3f841706d6e89951802d5d00b2442f2163f84 /libasn1compiler
parente44ea0bdd9f5dd291c1fa3b7b6dbcedddd6c51df (diff)
automatic dependency tracking
Diffstat (limited to 'libasn1compiler')
-rw-r--r--libasn1compiler/asn1c_C.c302
-rw-r--r--libasn1compiler/asn1c_constraint.c4
-rw-r--r--libasn1compiler/asn1c_internal.h2
-rw-r--r--libasn1compiler/asn1c_misc.c5
-rw-r--r--libasn1compiler/asn1c_save.c21
-rw-r--r--libasn1compiler/asn1compiler.c5
6 files changed, 207 insertions, 132 deletions
diff --git a/libasn1compiler/asn1c_C.c b/libasn1compiler/asn1c_C.c
index a2bdcb70..f8962be5 100644
--- a/libasn1compiler/asn1c_C.c
+++ b/libasn1compiler/asn1c_C.c
@@ -42,6 +42,9 @@ 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_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);
enum tvm_compat {
_TVM_SAME = 0, /* tags and all_tags are same */
@@ -274,7 +277,7 @@ 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_INDIRECT;
+ v->marker.flags |= EM_OMITABLE;
EMBED(v);
}
@@ -335,7 +338,7 @@ asn1c_lang_C_type_SEQUENCE_def(arg_t *arg) {
continue;
}
if(comp_mode == 1)
- v->marker.flags |= EM_INDIRECT;
+ v->marker.flags |= EM_OMITABLE;
emit_member_table(arg, v);
elements++;
});
@@ -435,7 +438,7 @@ asn1c_lang_C_type_SET(arg_t *arg) {
if(comp_mode < 3) comp_mode++;
}
if(comp_mode == 1)
- v->marker.flags |= EM_INDIRECT;
+ v->marker.flags |= EM_OMITABLE;
EMBED(v);
}
@@ -509,7 +512,7 @@ asn1c_lang_C_type_SET_def(arg_t *arg) {
if(comp_mode < 3) comp_mode++;
} else {
if(comp_mode == 1)
- v->marker.flags |= EM_INDIRECT;
+ v->marker.flags |= EM_OMITABLE;
emit_member_table(arg, v);
elements++;
}
@@ -552,7 +555,7 @@ asn1c_lang_C_type_SET_def(arg_t *arg) {
OUT(" | ");
}
OUT("(%d << %d)",
- v->marker.flags?0:1,
+ (v->marker.flags & EM_OMITABLE) != EM_OMITABLE,
7 - (el % 8));
if(el && (el % 8) == 0)
delimit = 1;
@@ -943,7 +946,6 @@ asn1c_lang_C_type_REFERENCE(arg_t *arg) {
tmp = *arg;
tmp.asn = arg->asn;
- tmp.mod = extract->module;
tmp.expr = extract;
ret = arg->default_cb(&tmp);
@@ -975,10 +977,7 @@ asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
* as it may recursively include the current structure.
*/
if(expr->marker.flags & (EM_INDIRECT | EM_UNRECURSE)) {
- asn1p_expr_t *terminal;
- terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
- if(terminal
- && (terminal->expr_type & ASN_CONSTR_MASK)) {
+ if(terminal_structable(arg, expr)) {
tnfmt = TNF_RSAFE;
REDIR(OT_FWD_DECLS);
OUT("%s;\n",
@@ -1462,10 +1461,9 @@ _add_tag2el_member(arg_t *arg, tag2el_t **tag2el, int *count, int el_no, fte_e f
if(arg->expr->expr_type == A1TC_REFERENCE) {
arg_t tmp = *arg;
asn1p_expr_t *expr;
- expr = asn1f_lookup_symbol_ex(tmp.asn, tmp.mod, tmp.expr,
+ expr = asn1f_lookup_symbol_ex(tmp.asn, tmp.expr,
arg->expr->reference);
if(expr) {
- tmp.mod = expr->module;
tmp.expr = expr;
return _add_tag2el_member(&tmp, tag2el, count, el_no, flags);
} else {
@@ -1613,106 +1611,6 @@ expr_elements_count(arg_t *arg, asn1p_expr_t *expr) {
}
static int
-emit_include_dependencies(arg_t *arg) {
- asn1p_expr_t *expr = arg->expr;
- asn1p_expr_t *memb;
-
- TQ_FOR(memb, &(expr->members), next) {
-
- /* Avoid recursive definitions. */
- expr_break_recursion(arg, memb);
-
- if(memb->marker.flags & (EM_INDIRECT | EM_UNRECURSE)) {
- asn1p_expr_t *terminal;
- terminal = asn1f_find_terminal_type_ex(arg->asn, memb);
- if(terminal
- && !terminal->parent_expr
- && (terminal->expr_type & ASN_CONSTR_MASK)) {
- int saved_target = arg->target->target;
- REDIR(OT_FWD_DECLS);
- OUT("%s;\n",
- asn1c_type_name(arg, memb, TNF_RSAFE));
- REDIR(saved_target);
- }
- }
-
- if((!(memb->expr_type & ASN_CONSTR_MASK)
- && memb->expr_type > ASN_CONSTR_MASK)
- || memb->meta_type == AMT_TYPEREF) {
- if(memb->marker.flags & EM_UNRECURSE) {
- GEN_POSTINCLUDE(asn1c_type_name(arg,
- memb, TNF_INCLUDE));
- } else {
- GEN_INCLUDE(asn1c_type_name(arg,
- memb, TNF_INCLUDE));
- }
- }
- }
-
- return 0;
-}
-
-/*
- * Check if it is better to make this type indirectly accessed via
- * a pointer.
- * This may be the case for the following recursive definition:
- * Type ::= CHOICE { member Type };
- */
-static int
-expr_break_recursion(arg_t *arg, asn1p_expr_t *expr) {
- asn1p_expr_t *top_parent;
- asn1p_expr_t *terminal;
-
- 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)
- ) {
- /* Break cross-reference */
- expr->marker.flags |= EM_INDIRECT | EM_UNRECURSE;
- return 1;
- }
-
- if((expr->marker.flags & EM_INDIRECT)
- || arg->expr->expr_type == ASN_CONSTR_SET_OF
- || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF) {
- if(terminal
- && !terminal->parent_expr
- && (terminal->expr_type & ASN_CONSTR_MASK)) {
- expr->marker.flags |= EM_UNRECURSE;
-
- if(arg->expr->expr_type == ASN_CONSTR_SET_OF
- || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF) {
- /* Don't put EM_INDIRECT even if recursion */
- return 1;
- }
-
- /* Fall through */
- }
- }
-
- /* Look for recursive back-references */
- top_parent = expr->parent_expr;
- if(top_parent) {
- while(top_parent->parent_expr)
- top_parent = top_parent->parent_expr;
- if(top_parent == terminal) {
- /* Explicitly break the recursion */
- expr->marker.flags |= EM_INDIRECT | EM_UNRECURSE;
- return 1;
- }
- }
-
- return 0;
-}
-
-static int
emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
int save_target;
arg_t tmp_arg;
@@ -1734,10 +1632,11 @@ emit_member_table(arg_t *arg, asn1p_expr_t *expr) {
OUT("ATF_OPEN_TYPE | ");
OUT("%s, ",
(expr->marker.flags & EM_INDIRECT)?"ATF_POINTER":"ATF_NOFLAGS");
- if((expr->marker.flags & EM_OPTIONAL) == EM_OPTIONAL) {
+ if((expr->marker.flags & EM_OMITABLE) == EM_OMITABLE) {
asn1p_expr_t *tv;
int opts = 0;
- for(tv = expr; tv && tv->marker.flags;
+ for(tv = expr;
+ tv && (tv->marker.flags & EM_OMITABLE) == EM_OMITABLE;
tv = TQ_NEXT(tv, next), opts++) {
if(tv->expr_type == A1TC_EXTENSIBLE)
opts--;
@@ -2018,3 +1917,178 @@ out_name_chain(arg_t *arg, enum onc_flags onc_flags) {
return 0;
}
+
+static int
+emit_include_dependencies(arg_t *arg) {
+ asn1p_expr_t *expr = arg->expr;
+ asn1p_expr_t *memb;
+
+ /* Avoid recursive definitions. */
+ TQ_FOR(memb, &(expr->members), next) {
+ expr_break_recursion(arg, memb);
+ }
+
+ TQ_FOR(memb, &(expr->members), next) {
+
+ if(memb->marker.flags & (EM_INDIRECT | EM_UNRECURSE)) {
+ if(terminal_structable(arg, memb)) {
+ int saved_target = arg->target->target;
+ REDIR(OT_FWD_DECLS);
+ OUT("%s;\n",
+ asn1c_type_name(arg, memb, TNF_RSAFE));
+ REDIR(saved_target);
+ }
+ }
+
+ if((!(memb->expr_type & ASN_CONSTR_MASK)
+ && memb->expr_type > ASN_CONSTR_MASK)
+ || memb->meta_type == AMT_TYPEREF) {
+ if(memb->marker.flags & EM_UNRECURSE) {
+ GEN_POSTINCLUDE(asn1c_type_name(arg,
+ memb, TNF_INCLUDE));
+ } else {
+ GEN_INCLUDE(asn1c_type_name(arg,
+ memb, TNF_INCLUDE));
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Check if it is better to make this type indirectly accessed via
+ * a pointer.
+ * This may be the case for the following recursive definition:
+ * Type ::= CHOICE { member Type };
+ */
+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)
+ ) {
+ /* Break cross-reference */
+ expr->marker.flags |= EM_INDIRECT | EM_UNRECURSE;
+ return 1;
+ }
+
+ if((expr->marker.flags & EM_INDIRECT)
+ || arg->expr->expr_type == ASN_CONSTR_SET_OF
+ || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF) {
+ if(terminal_structable(arg, expr)) {
+ expr->marker.flags |= EM_UNRECURSE;
+
+ if(arg->expr->expr_type == ASN_CONSTR_SET_OF
+ || arg->expr->expr_type == ASN_CONSTR_SEQUENCE_OF) {
+ /* Don't put EM_INDIRECT even if recursion */
+ return 1;
+ }
+
+ /* Fall through */
+ }
+ }
+
+ /* Look for recursive back-references */
+ ret = expr_defined_recursively(arg, expr);
+ switch(ret) {
+ case 2: /* Explicitly break the recursion */
+ case 1: /* Use safer typing */
+ expr->marker.flags |= EM_INDIRECT;
+ expr->marker.flags |= EM_UNRECURSE;
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * Check if the type can be represented using simple `struct TYPE`.
+ */
+static asn1p_expr_t *
+terminal_structable(arg_t *arg, asn1p_expr_t *expr) {
+ asn1p_expr_t *terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
+ if(terminal
+ && !terminal->parent_expr
+ && (terminal->expr_type & ASN_CONSTR_MASK)) {
+ return terminal;
+ }
+ return 0;
+}
+
+static int
+asn1c_recurse(arg_t *arg, asn1p_expr_t *expr, int (*callback)(arg_t *arg, void *key), void *key) {
+ arg_t tmp = *arg;
+ int maxret = 0;
+ int ret;
+
+ if(expr->_mark) return 0;
+ expr->_mark |= TM_RECURSION;
+
+ /* Invoke callback for every type going into recursion */
+ tmp.expr = expr;
+ maxret = callback(&tmp, key);
+ if(maxret <= 1) {
+ /*
+ * Recursively invoke myself and the callbacks.
+ */
+ TQ_FOR(tmp.expr, &(expr->members), next) {
+ ret = asn1c_recurse(&tmp, tmp.expr, callback, key);
+ if(ret > maxret)
+ maxret = ret;
+ if(maxret > 1) break;
+ }
+ }
+
+ expr->_mark &= ~TM_RECURSION;
+ return maxret;
+}
+
+static int
+check_is_refer_to(arg_t *arg, void *key) {
+ asn1p_expr_t *terminal = terminal_structable(arg, arg->expr);
+ if(terminal == key) {
+ if(arg->expr->marker.flags & EM_INDIRECT)
+ return 1; /* This is almost safe indirection */
+ return 2;
+ } else if(terminal) {
+ /* This might be N-step circular loop. Dive into it. */
+ return asn1c_recurse(arg, terminal, check_is_refer_to, key);
+ }
+ return 0;
+}
+
+/*
+ * Check if the possibly inner expression defined recursively.
+ */
+static int
+expr_defined_recursively(arg_t *arg, asn1p_expr_t *expr) {
+ asn1p_expr_t *terminal;
+ asn1p_expr_t *topmost;
+
+ /* If expression is top-level, there's no way it can be recursive. */
+ if(expr->parent_expr == 0) return 0;
+ if(expr->expr_type != A1TC_REFERENCE)
+ return 0; /* Basic types are never recursive */
+
+ terminal = terminal_structable(arg, expr);
+ if(!terminal) return 0; /* Terminal cannot be indirected */
+
+ /* Search for the parent container for the given expression */
+ topmost = expr;
+ while(topmost->parent_expr)
+ topmost = topmost->parent_expr;
+
+ /* Look inside the terminal type if it mentions the parent expression */
+ return asn1c_recurse(arg, terminal, check_is_refer_to, topmost);
+}
diff --git a/libasn1compiler/asn1c_constraint.c b/libasn1compiler/asn1c_constraint.c
index 372730fc..8af5e368 100644
--- a/libasn1compiler/asn1c_constraint.c
+++ b/libasn1compiler/asn1c_constraint.c
@@ -609,13 +609,13 @@ emit_value_determination_code(arg_t *arg, asn1p_expr_type_e etype, asn1cnst_rang
default:
WARNING("%s:%d: Value cannot be determined "
"for constraint check for %s",
- arg->mod->source_file_name,
+ arg->expr->module->source_file_name,
arg->expr->_lineno,
arg->expr->Identifier
);
OUT_NOINDENT(
"#error %s:%d: Value of %s cannot be determined\n",
- arg->mod->source_file_name,
+ arg->expr->module->source_file_name,
arg->expr->_lineno,
arg->expr->Identifier
);
diff --git a/libasn1compiler/asn1c_internal.h b/libasn1compiler/asn1c_internal.h
index e32187f5..fdf953d9 100644
--- a/libasn1compiler/asn1c_internal.h
+++ b/libasn1compiler/asn1c_internal.h
@@ -51,7 +51,7 @@ typedef struct arg_s {
struct compiler_streams *target;
asn1p_t *asn;
- asn1p_module_t *mod;
+ //asn1p_module_t *mod;
asn1p_expr_t *expr;
int embed;
diff --git a/libasn1compiler/asn1c_misc.c b/libasn1compiler/asn1c_misc.c
index 7483a200..779426aa 100644
--- a/libasn1compiler/asn1c_misc.c
+++ b/libasn1compiler/asn1c_misc.c
@@ -142,11 +142,10 @@ asn1c_type_name(arg_t *arg, asn1p_expr_t *expr, enum tnfmt _format) {
* This is a reference to a type defined in a class.
* Resolve it and use instead.
*/
- tmp.expr = asn1f_class_access_ex(arg->asn, arg->mod,
- arg->expr, expr->reference);
+ tmp.expr = asn1f_class_access_ex(arg->asn,
+ arg->expr->module, arg->expr, expr->reference);
if(tmp.expr) return NULL;
- tmp.mod = tmp.expr->module;
return asn1c_type_name(&tmp, tmp.expr, _format);
}
diff --git a/libasn1compiler/asn1c_save.c b/libasn1compiler/asn1c_save.c
index 0ab81563..0eb70c98 100644
--- a/libasn1compiler/asn1c_save.c
+++ b/libasn1compiler/asn1c_save.c
@@ -17,6 +17,7 @@ asn1c_save_compiled_output(arg_t *arg, const char *datadir,
int argc, char **argv) {
asn1c_fdeps_t *deps = 0;
asn1c_fdeps_t *dlist;
+ asn1p_module_t *mod;
FILE *mkf;
int i;
@@ -26,8 +27,8 @@ asn1c_save_compiled_output(arg_t *arg, const char *datadir,
"from %s\n", datadir);
}
- TQ_FOR(arg->mod, &(arg->asn->modules), mod_next) {
- TQ_FOR(arg->expr, &(arg->mod->members), next) {
+ TQ_FOR(mod, &(arg->asn->modules), mod_next) {
+ TQ_FOR(arg->expr, &(mod->members), next) {
if(asn1_lang_map[arg->expr->meta_type]
[arg->expr->expr_type].type_cb) {
if(asn1c_dump_streams(arg, deps))
@@ -51,8 +52,8 @@ asn1c_save_compiled_output(arg_t *arg, const char *datadir,
}
fprintf(mkf, "ASN_MODULE_SOURCES=");
- TQ_FOR(arg->mod, &(arg->asn->modules), mod_next) {
- TQ_FOR(arg->expr, &(arg->mod->members), next) {
+ TQ_FOR(mod, &(arg->asn->modules), mod_next) {
+ TQ_FOR(arg->expr, &(mod->members), next) {
if(asn1_lang_map[arg->expr->meta_type]
[arg->expr->expr_type].type_cb) {
fprintf(mkf, "\t\\\n\t%s.c",
@@ -61,8 +62,8 @@ asn1c_save_compiled_output(arg_t *arg, const char *datadir,
}
}
fprintf(mkf, "\n\nASN_MODULE_HEADERS=");
- TQ_FOR(arg->mod, &(arg->asn->modules), mod_next) {
- TQ_FOR(arg->expr, &(arg->mod->members), next) {
+ TQ_FOR(mod, &(arg->asn->modules), mod_next) {
+ TQ_FOR(arg->expr, &(mod->members), next) {
if(asn1_lang_map[arg->expr->meta_type]
[arg->expr->expr_type].type_cb) {
fprintf(mkf, "\t\\\n\t%s.h",
@@ -208,8 +209,8 @@ asn1c_save_streams(arg_t *arg, asn1c_fdeps_t *deps) {
" * From ASN.1 module \"%s\"\n"
" * \tfound in \"%s\"\n"
" */\n\n",
- arg->mod->ModuleName,
- arg->mod->source_file_name
+ expr->module->ModuleName,
+ expr->module->source_file_name
);
fprintf(fp_h,
"/*\n"
@@ -217,8 +218,8 @@ asn1c_save_streams(arg_t *arg, asn1c_fdeps_t *deps) {
" * From ASN.1 module \"%s\"\n"
" * \tfound in \"%s\"\n"
" */\n\n",
- arg->mod->ModuleName,
- arg->mod->source_file_name
+ expr->module->ModuleName,
+ expr->module->source_file_name
);
header_id = asn1c_make_identifier(0, expr->Identifier, NULL);
diff --git a/libasn1compiler/asn1compiler.c b/libasn1compiler/asn1compiler.c
index 31a42278..e8e6739d 100644
--- a/libasn1compiler/asn1compiler.c
+++ b/libasn1compiler/asn1compiler.c
@@ -12,6 +12,7 @@ asn1_compile(asn1p_t *asn, const char *datadir, enum asn1c_flags flags,
int argc, char **argv) {
arg_t arg_s;
arg_t *arg = &arg_s;
+ asn1p_module_t *mod;
int ret;
/*
@@ -29,8 +30,8 @@ asn1_compile(asn1p_t *asn, const char *datadir, enum asn1c_flags flags,
/*
* Compile each individual top level structure.
*/
- TQ_FOR(arg->mod, &(asn->modules), mod_next) {
- TQ_FOR(arg->expr, &(arg->mod->members), next) {
+ TQ_FOR(mod, &(asn->modules), mod_next) {
+ TQ_FOR(arg->expr, &(mod->members), next) {
compiler_streams_t *cs = NULL;
if(asn1c_attach_streams(arg->expr))