diff options
author | Lev Walkin <vlm@lionet.info> | 2005-08-18 13:38:19 +0000 |
---|---|---|
committer | Lev Walkin <vlm@lionet.info> | 2005-08-18 13:38:19 +0000 |
commit | b85a8135dae955c09b23197f5497b8ff911d083d (patch) | |
tree | afc3f841706d6e89951802d5d00b2442f2163f84 /libasn1compiler | |
parent | e44ea0bdd9f5dd291c1fa3b7b6dbcedddd6c51df (diff) |
automatic dependency tracking
Diffstat (limited to 'libasn1compiler')
-rw-r--r-- | libasn1compiler/asn1c_C.c | 302 | ||||
-rw-r--r-- | libasn1compiler/asn1c_constraint.c | 4 | ||||
-rw-r--r-- | libasn1compiler/asn1c_internal.h | 2 | ||||
-rw-r--r-- | libasn1compiler/asn1c_misc.c | 5 | ||||
-rw-r--r-- | libasn1compiler/asn1c_save.c | 21 | ||||
-rw-r--r-- | libasn1compiler/asn1compiler.c | 5 |
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)) |