diff options
author | Lev Walkin <vlm@lionet.info> | 2006-03-21 03:40:38 +0000 |
---|---|---|
committer | Lev Walkin <vlm@lionet.info> | 2006-03-21 03:40:38 +0000 |
commit | a00d6b371486efc2fbe6e812882d250f5a0bb75c (patch) | |
tree | 24c47f98731c42ea1df33a464c0fbca7ba760489 /libasn1fix | |
parent | 25b8f280603bc4ed70609c3aacc1ef8820b027b3 (diff) |
refactored parameterization support
Diffstat (limited to 'libasn1fix')
-rw-r--r-- | libasn1fix/asn1fix.c | 158 | ||||
-rw-r--r-- | libasn1fix/asn1fix_class.c | 8 | ||||
-rw-r--r-- | libasn1fix/asn1fix_class.h | 8 | ||||
-rw-r--r-- | libasn1fix/asn1fix_constr.c | 3 | ||||
-rw-r--r-- | libasn1fix/asn1fix_constraint.c | 3 | ||||
-rw-r--r-- | libasn1fix/asn1fix_cws.c | 2 | ||||
-rw-r--r-- | libasn1fix/asn1fix_dereft.c | 3 | ||||
-rw-r--r-- | libasn1fix/asn1fix_export.c | 5 | ||||
-rw-r--r-- | libasn1fix/asn1fix_export.h | 2 | ||||
-rw-r--r-- | libasn1fix/asn1fix_integer.c | 3 | ||||
-rw-r--r-- | libasn1fix/asn1fix_internal.h | 2 | ||||
-rw-r--r-- | libasn1fix/asn1fix_misc.c | 11 | ||||
-rw-r--r-- | libasn1fix/asn1fix_param.c | 431 | ||||
-rw-r--r-- | libasn1fix/asn1fix_param.h | 8 | ||||
-rw-r--r-- | libasn1fix/asn1fix_retrieve.c | 45 | ||||
-rw-r--r-- | libasn1fix/asn1fix_retrieve.h | 1 | ||||
-rw-r--r-- | libasn1fix/asn1fix_tags.c | 2 |
17 files changed, 336 insertions, 359 deletions
diff --git a/libasn1fix/asn1fix.c b/libasn1fix/asn1fix.c index d8cc863c..24ba7c8d 100644 --- a/libasn1fix/asn1fix.c +++ b/libasn1fix/asn1fix.c @@ -15,6 +15,7 @@ static int asn1f_resolve_constraints(arg_t *arg); /* For subtype constraints */ static int asn1f_check_constraints(arg_t *arg); /* For subtype constraints */ static int asn1f_check_duplicate(arg_t *arg); static int asn1f_apply_unique_index(arg_t *arg); +static int phase_1_1(arg_t *arg, int prm2); arg_t a1f_replace_me_with_proper_interface_arg; @@ -179,71 +180,21 @@ asn1f_fix_module__phase_1(arg_t *arg) { */ TQ_FOR(expr, &(arg->mod->members), next) { arg->expr = expr; - - /* Check whether this type is a duplicate */ - ret = asn1f_check_duplicate(arg); - RET2RVAL(ret, rvalue); - - if(expr->meta_type == AMT_PARAMTYPE) - /* Do not process the parametrized type just yet */ - continue; - - DEBUG("=== Now processing \"%s\" (%d/0x%x) at line %d ===", - expr->Identifier, expr->meta_type, expr->expr_type, - expr->_lineno); - assert(expr->meta_type != AMT_INVALID); - - /* - * 2.1 Pre-process simple types (ENUMERATED, INTEGER, etc). - */ - ret = asn1f_recurse_expr(arg, asn1f_fix_simple); - RET2RVAL(ret, rvalue); - - /* - * 2.5.4 - */ - ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_types); + ret = phase_1_1(arg, 0); RET2RVAL(ret, rvalue); - - /* - * Fix tagging of top-level types. - */ - ret = asn1f_fix_constr_tag(arg, 1); - RET2RVAL(ret, rvalue); - - /* - * 2.[234] Process SEQUENCE/SET/CHOICE types. - */ - ret = asn1f_recurse_expr(arg, asn1f_fix_constructed); - RET2RVAL(ret, rvalue); - - /* - * 2.5.5 - */ - ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_values); - RET2RVAL(ret, rvalue); - - /* - * Parse class objects and fill up the object class with data. - */ - ret = asn1f_parse_class_object(arg); - RET2RVAL(ret, rvalue); - - /* - * Resolve references in constraints. - */ - ret = asn1f_recurse_expr(arg, asn1f_resolve_constraints); - RET2RVAL(ret, rvalue); - - /* - * 6. INTEGER value processed at 2.5.4. - */ - /* * Make sure everybody's behaving well. */ assert(arg->expr == expr); } + TQ_FOR(expr, &(arg->mod->members), next) { + arg->expr = expr; + ret = phase_1_1(arg, 1); + RET2RVAL(ret, rvalue); + assert(arg->expr == expr); + } + + /* * 5. Automatic tagging @@ -296,15 +247,8 @@ asn1f_fix_module__phase_2(arg_t *arg) { int ret; TQ_FOR(expr, &(arg->mod->members), next) { - } - - TQ_FOR(expr, &(arg->mod->members), next) { arg->expr = expr; - if(expr->meta_type == AMT_PARAMTYPE) - /* Do not process the parametrized types here */ - continue; - /* * Dereference DEFAULT values. */ @@ -331,6 +275,88 @@ asn1f_fix_module__phase_2(arg_t *arg) { } static int +phase_1_1(arg_t *arg, int prm2) { + asn1p_expr_t *expr = arg->expr; + int rvalue = 0; + int ret; + + if(expr->lhs_params && expr->spec_index == -1) { + int i; + if(!prm2) + /* Do not process the parameterized type just yet */ + return 0; + for(i = 0; i < expr->specializations.pspecs_count; i++) { + arg->expr = expr->specializations.pspec[i].my_clone; + ret = phase_1_1(arg, 0); + RET2RVAL(ret, rvalue); + } + arg->expr = expr; /* revert */ + return rvalue; + } else if(prm2) { + return 0; /* Already done! */ + } + + /* Check whether this type is a duplicate */ + if(!expr->lhs_params) { + ret = asn1f_check_duplicate(arg); + RET2RVAL(ret, rvalue); + } + + DEBUG("=== Now processing \"%s\" (%d/0x%x) at line %d ===", + expr->Identifier, expr->meta_type, expr->expr_type, + expr->_lineno); + assert(expr->meta_type != AMT_INVALID); + + /* + * 2.1 Pre-process simple types (ENUMERATED, INTEGER, etc). + */ + ret = asn1f_recurse_expr(arg, asn1f_fix_simple); + RET2RVAL(ret, rvalue); + + /* + * 2.5.4 + */ + ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_types); + RET2RVAL(ret, rvalue); + + /* + * Fix tagging of top-level types. + */ + ret = asn1f_fix_constr_tag(arg, 1); + RET2RVAL(ret, rvalue); + + /* + * 2.[234] Process SEQUENCE/SET/CHOICE types. + */ + ret = asn1f_recurse_expr(arg, asn1f_fix_constructed); + RET2RVAL(ret, rvalue); + + /* + * 2.5.5 + */ + ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_values); + RET2RVAL(ret, rvalue); + + /* + * Parse class objects and fill up the object class with data. + */ + ret = asn1f_parse_class_object(arg); + RET2RVAL(ret, rvalue); + + /* + * Resolve references in constraints. + */ + ret = asn1f_recurse_expr(arg, asn1f_resolve_constraints); + RET2RVAL(ret, rvalue); + + /* + * 6. INTEGER value processed at 2.5.4. + */ + + return rvalue; +} + +static int asn1f_fix_simple(arg_t *arg) { int rvalue = 0; int ret; diff --git a/libasn1fix/asn1fix_class.c b/libasn1fix/asn1fix_class.c index b3bfae57..bf357193 100644 --- a/libasn1fix/asn1fix_class.c +++ b/libasn1fix/asn1fix_class.c @@ -1,7 +1,7 @@ #include "asn1fix_internal.h" asn1p_expr_t * -asn1f_class_access(arg_t *arg, asn1p_module_t *mod, asn1p_ref_t *ref) { +asn1f_class_access(arg_t *arg, asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, asn1p_ref_t *ref) { asn1p_expr_t *ioclass; asn1p_expr_t *classfield; asn1p_expr_t *expr; @@ -20,14 +20,16 @@ asn1f_class_access(arg_t *arg, asn1p_module_t *mod, asn1p_ref_t *ref) { tmpref = *ref; tmpref.comp_count = 1; - ioclass = asn1f_lookup_symbol(arg, mod, &tmpref); + ioclass = asn1f_lookup_symbol(arg, mod, rhs_pspecs, &tmpref); if(ioclass == NULL) { errno = ESRCH; return NULL; } if(ioclass->expr_type == A1TC_REFERENCE) { ioclass = asn1f_lookup_symbol(arg, - ioclass->module, ioclass->reference); + ioclass->module, + ioclass->rhs_pspecs, + ioclass->reference); if(ioclass == NULL) { errno = ESRCH; return NULL; diff --git a/libasn1fix/asn1fix_class.h b/libasn1fix/asn1fix_class.h index 763e48cf..b704ff8b 100644 --- a/libasn1fix/asn1fix_class.h +++ b/libasn1fix/asn1fix_class.h @@ -4,12 +4,6 @@ /* * Fetch the element from the class-related stuff (thing) by its reference. */ -asn1p_expr_t *asn1f_class_access(arg_t *, asn1p_module_t *mod, asn1p_ref_t *); - -/* - * Externally accessible version of above function. - */ -asn1p_expr_t *asn1f_class_access2(asn1p_t *asn, asn1p_module_t *mod, - asn1p_expr_t *expr, asn1p_ref_t *); +asn1p_expr_t *asn1f_class_access(arg_t *, asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, asn1p_ref_t *); #endif /* _ASN1FIX_CLASS_H_ */ diff --git a/libasn1fix/asn1fix_constr.c b/libasn1fix/asn1fix_constr.c index 2c995cc1..353473d4 100644 --- a/libasn1fix/asn1fix_constr.c +++ b/libasn1fix/asn1fix_constr.c @@ -471,7 +471,8 @@ _asn1f_compare_tags(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b) { DEBUG(" %s is a type reference", a->Identifier); - a = asn1f_lookup_symbol(arg, a->module, a->reference); + a = asn1f_lookup_symbol(arg, + a->module, a->rhs_pspecs, a->reference); if(!a) return 0; /* Already FATAL()'ed somewhere else */ WITH_MODULE(a->module, ret = _asn1f_compare_tags(arg, a, b)); return ret; diff --git a/libasn1fix/asn1fix_constraint.c b/libasn1fix/asn1fix_constraint.c index 4afca5aa..23709a4e 100644 --- a/libasn1fix/asn1fix_constraint.c +++ b/libasn1fix/asn1fix_constraint.c @@ -30,7 +30,7 @@ asn1constraint_pullup(arg_t *arg) { asn1p_expr_t *parent_expr; assert(ref); - parent_expr = asn1f_lookup_symbol(arg, expr->module, ref); + parent_expr = asn1f_lookup_symbol(arg, expr->module, expr->rhs_pspecs, ref); if(!parent_expr) { if(errno != EEXIST) { DEBUG("\tWhile fetching parent constraints: " @@ -259,6 +259,7 @@ constraint_type_resolve(arg_t *arg, asn1p_constraint_t *ct) { assert(ct->containedSubtype->type == ATV_REFERENCED); rtype = asn1f_lookup_symbol(arg, arg->expr->module, + arg->expr->rhs_pspecs, ct->containedSubtype->value.reference); if(!rtype) { FATAL("Cannot find type \"%s\" in constraints at line %d", diff --git a/libasn1fix/asn1fix_cws.c b/libasn1fix/asn1fix_cws.c index 0279c96d..c6bd1ab0 100644 --- a/libasn1fix/asn1fix_cws.c +++ b/libasn1fix/asn1fix_cws.c @@ -206,7 +206,7 @@ _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_i asn1p_ref_add_component(ref, p, RLT_UNKNOWN); assert(ref); - expr = asn1f_lookup_symbol(arg, arg->mod, ref); + expr = asn1f_lookup_symbol(arg, arg->mod, arg->expr->rhs_pspecs, ref); if(!expr) { FATAL("Cannot find %s referenced by %s at line %d", p, arg->expr->Identifier, diff --git a/libasn1fix/asn1fix_dereft.c b/libasn1fix/asn1fix_dereft.c index 769abed9..8f570f64 100644 --- a/libasn1fix/asn1fix_dereft.c +++ b/libasn1fix/asn1fix_dereft.c @@ -6,9 +6,6 @@ asn1f_fix_dereference_types(arg_t *arg) { asn1p_expr_t *type_expr; int r_value = 0; - if(expr->expr_type == A1TC_PARAMETRIZED) - return asn1f_fix_parametrized_assignment(arg); - if(expr->expr_type != A1TC_REFERENCE || expr->meta_type != AMT_TYPEREF) { //assert(expr->reference == 0); diff --git a/libasn1fix/asn1fix_export.c b/libasn1fix/asn1fix_export.c index 0a543dc1..6eb8cdad 100644 --- a/libasn1fix/asn1fix_export.c +++ b/libasn1fix/asn1fix_export.c @@ -20,13 +20,14 @@ asn1f_lookup_symbol_ex( arg.debug = a1f_replace_me_with_proper_interface_arg.debug; - return asn1f_lookup_symbol(&arg, expr->module, ref); + return asn1f_lookup_symbol(&arg, expr->module, expr->rhs_pspecs, ref); } asn1p_expr_t * asn1f_class_access_ex(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, + asn1p_expr_t *rhs_pspecs, asn1p_ref_t *ref) { arg_t arg; @@ -38,7 +39,7 @@ asn1f_class_access_ex(asn1p_t *asn, arg.eh = a1f_replace_me_with_proper_interface_arg.eh; arg.debug = a1f_replace_me_with_proper_interface_arg.debug; - return asn1f_class_access(&arg, mod, ref); + return asn1f_class_access(&arg, mod, rhs_pspecs, ref); } asn1p_expr_t * diff --git a/libasn1fix/asn1fix_export.h b/libasn1fix/asn1fix_export.h index 533ba28e..606ddf89 100644 --- a/libasn1fix/asn1fix_export.h +++ b/libasn1fix/asn1fix_export.h @@ -25,7 +25,7 @@ asn1p_expr_t *asn1f_lookup_symbol_ex( * Exportable version of an asn1f_class_access(). */ asn1p_expr_t *asn1f_class_access_ex(asn1p_t *asn, asn1p_module_t *mod, - asn1p_expr_t *expr, asn1p_ref_t *); + asn1p_expr_t *expr, asn1p_expr_t *rhs_rspecs, asn1p_ref_t *); /* * Exportable version of asn1f_find_terminal_type(). diff --git a/libasn1fix/asn1fix_integer.c b/libasn1fix/asn1fix_integer.c index 892e9276..8a144911 100644 --- a/libasn1fix/asn1fix_integer.c +++ b/libasn1fix/asn1fix_integer.c @@ -143,7 +143,8 @@ _asn1f_make_sure_type_is(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_type_e type) * Then, it is a reference. For a reference, try to resolve type * and try again. */ - next_expr = asn1f_lookup_symbol(arg, expr->module, expr->reference); + next_expr = asn1f_lookup_symbol(arg, expr->module, + expr->rhs_pspecs, expr->reference); if(next_expr == NULL) { errno = ESRCH; return -1; diff --git a/libasn1fix/asn1fix_internal.h b/libasn1fix/asn1fix_internal.h index dabf8567..612b718a 100644 --- a/libasn1fix/asn1fix_internal.h +++ b/libasn1fix/asn1fix_internal.h @@ -62,7 +62,7 @@ typedef struct arg_s { #include "asn1fix_constr.h" /* Constructed types */ #include "asn1fix_class.h" /* CLASS support */ #include "asn1fix_cws.h" /* CLASS WITH SYNTAX support */ -#include "asn1fix_param.h" /* Parametrization */ +#include "asn1fix_param.h" /* Parameterization */ #include "asn1fix_retrieve.h" /* Data retrieval */ #include "asn1fix_enum.h" /* Process ENUMERATED */ #include "asn1fix_integer.h" /* Process INTEGER */ diff --git a/libasn1fix/asn1fix_misc.c b/libasn1fix/asn1fix_misc.c index b28a58a2..5728bd4c 100644 --- a/libasn1fix/asn1fix_misc.c +++ b/libasn1fix/asn1fix_misc.c @@ -196,6 +196,17 @@ asn1f_recurse_expr(arg_t *arg, int (*callback)(arg_t *arg)) { assert(expr); + if(expr->lhs_params && expr->spec_index == -1) { + int i; + for(i = 0; i < expr->specializations.pspecs_count; i++) { + arg->expr = expr->specializations.pspec[i].my_clone; + ret = asn1f_recurse_expr(arg, callback); + RET2RVAL(ret, rvalue); + } + arg->expr = expr; /* revert */ + return rvalue; + } + /* * Invoke the callback at this very level. */ diff --git a/libasn1fix/asn1fix_param.c b/libasn1fix/asn1fix_param.c index a4d96902..bbd7cf4d 100644 --- a/libasn1fix/asn1fix_param.c +++ b/libasn1fix/asn1fix_param.c @@ -1,306 +1,217 @@ #include "asn1fix_internal.h" -static int asn1f_parametrize(arg_t *arg, asn1p_expr_t *ex, asn1p_expr_t *ptype); -static int asn1f_param_process_recursive(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype, asn1p_expr_t *actargs); -static int asn1f_param_process_constraints(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype, asn1p_expr_t *actargs); - -static asn1p_expr_t *_referenced_argument(asn1p_ref_t *ref, asn1p_expr_t *ptype, asn1p_expr_t *actargs); -static int _process_constraints(arg_t *arg, asn1p_constraint_t *ct, asn1p_expr_t *ptype, asn1p_expr_t *actargs); - -int -asn1f_fix_parametrized_assignment(arg_t *arg) { - asn1p_expr_t *expr = arg->expr; - asn1p_expr_t *ptype; +typedef struct resolver_arg { + asn1p_expr_t *(*resolver)(asn1p_expr_t *, void *arg); + arg_t *arg; + asn1p_expr_t *original_expr; + asn1p_paramlist_t *lhs_params; + asn1p_expr_t *rhs_pspecs; +} resolver_arg_t; + +static asn1p_expr_t *resolve_expr(asn1p_expr_t *, void *resolver_arg); +static int compare_specializations(arg_t *, asn1p_expr_t *a, asn1p_expr_t *b); +static asn1p_expr_t *find_target_specialization_byref(resolver_arg_t *rarg, asn1p_ref_t *ref); +static asn1p_expr_t *find_target_specialization_bystr(resolver_arg_t *rarg, char *str); + +asn1p_expr_t * +asn1f_parameterization_fork(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *rhs_pspecs) { + resolver_arg_t rarg; /* resolver argument */ + asn1p_expr_t *exc; /* expr clone */ + asn1p_expr_t *rpc; /* rhs_pspecs clone */ + asn1p_expr_t *target; + void *p; + struct asn1p_pspec_s *pspec; + int npspecs; + int i; - assert(expr->expr_type == A1TC_PARAMETRIZED); - assert(expr->reference); + assert(rhs_pspecs); + assert(expr->lhs_params); + assert(expr->parent_expr == 0); - DEBUG("(\"%s\" ::= \"%s\" { %s }) for line %d", - expr->Identifier, - asn1f_printable_reference(expr->reference), - asn1f_printable_value(expr->value), - expr->_lineno); + DEBUG("Forking parameterization at %d for %s (%d alr)", + rhs_pspecs->_lineno, expr->Identifier, + expr->specializations.pspecs_count); /* - * Find the corresponding parametrized type definition. + * Find if this exact specialization has been used already. */ - DEBUG("Looking for parametrized type definition \"%s\"", - asn1f_printable_reference(expr->reference)); - ptype = asn1f_lookup_symbol(arg, expr->module, expr->reference); - if(ptype == NULL) { - DEBUG("%s: missing parametrized type declaration", - asn1f_printable_reference(expr->reference)); - return -1; + for(npspecs = 0; + npspecs < expr->specializations.pspecs_count; + npspecs++) { + if(compare_specializations(arg, rhs_pspecs, + expr->specializations.pspec[npspecs].rhs_pspecs) == 0) { + DEBUG("Reused parameterization for %s", + expr->Identifier); + return expr->specializations.pspec[npspecs].my_clone; + } } - /* - * Check that the number of arguments which are expected by - * the parametrized type declaration is consistent with the - * number of arguments supplied by the parametrized assignment. - */ - if(asn1f_count_children(expr) != ptype->params->params_count) { - FATAL("Number of actual arguments %d in %s at line %d " - "is not equal to number of expected arguments " - "%d in %s at line %d", - asn1f_count_children(expr), - asn1f_printable_reference(expr->reference), - expr->_lineno, - ptype->params->params_count, - ptype->Identifier, - ptype->_lineno - ); - return -1; - } + rarg.resolver = resolve_expr; + rarg.arg = arg; + rarg.original_expr = expr; + rarg.lhs_params = expr->lhs_params; + rarg.rhs_pspecs = rhs_pspecs; + exc = asn1p_expr_clone_with_resolver(expr, resolve_expr, &rarg); + rpc = asn1p_expr_clone(rhs_pspecs, 0); + assert(exc && rpc); /* - * Perform an expansion of a parametrized assignment. + * Create a new specialization. */ - return asn1f_parametrize(arg, expr, ptype); -} - -#define SUBSTITUTE(to, from) do { \ - asn1p_expr_t tmp, *__v; \ - if((to)->tag.tag_class \ - && (from)->tag.tag_class) { \ - FATAL("Layered tagging in parametrization " \ - "is not yet supported, " \ - "contact asn1c author for assistance " \ - "with line %d", (to)->_lineno); \ - return -1; \ - } \ - /* This code shall not be invoked too early */ \ - assert((to)->combined_constraints == NULL); \ - assert((from)->combined_constraints == NULL); \ - /* Copy stuff, and merge some parameters */ \ - tmp = *(to); \ - *(to) = *(from); \ - TQ_MOVE(&(to)->members, &(from)->members); \ - *(from) = tmp; \ - (to)->next = tmp.next; \ - (to)->parent_expr = tmp.parent_expr; \ - assert((to)->marker.flags == EM_NOMARK); \ - (to)->marker = tmp.marker; \ - if(tmp.tag.tag_class) \ - (to)->tag = tmp.tag; \ - if(tmp.constraints) { \ - if((to)->constraints) { \ - asn1p_constraint_t *ct; \ - ct = asn1p_constraint_new( \ - (to)->constraints->_lineno); \ - ct->type = ACT_CA_SET; \ - asn1p_constraint_insert(ct, \ - (to)->constraints); \ - asn1p_constraint_insert(ct, \ - tmp.constraints); \ - (to)->constraints = ct; \ - } else { \ - (to)->constraints = tmp.constraints; \ - } \ - } \ - (from)->constraints = 0; \ - (from)->marker.default_value = 0; \ - memset(&((from)->next), 0, sizeof((from)->next)); \ - memset(&((from)->members), 0, sizeof((from)->members)); \ - asn1p_expr_free(from); \ - TQ_FOR(__v, &((to)->members), next) { \ - assert(__v->parent_expr == (from)); \ - __v->parent_expr = (to); \ - } \ -} while(0) - -static int -asn1f_parametrize(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype) { - asn1p_expr_t *nex; - void *p; - int ret; - - DEBUG("asn1f_parametrize(%s <= %s)", - expr->Identifier, ptype->Identifier); - - /* - * The algorithm goes like that: - * 1. Replace the expression's type with parametrized type. - * 2. For every child in the parametrized type, import it - * as a child of the expression, replacing all occurences of - * symbols which are defined as parametrized type arguments - * with the actual values. - * 3. Don't forget to parametrize the subtype constraints. - */ - - nex = asn1p_expr_clone(ptype, 0); - if(nex == NULL) return -1; - - /* - * Cleanup the new expression so there is no ptype-related - * stuff hanging around. - */ - if(expr->Identifier) { - p = strdup(expr->Identifier); - if(p) { - free(nex->Identifier); - nex->Identifier = p; - } else { - asn1p_expr_free(nex); - return -1; - } + npspecs = expr->specializations.pspecs_count; + p = realloc(expr->specializations.pspec, + (npspecs + 1) * sizeof(expr->specializations.pspec[0])); + assert(p); + expr->specializations.pspec = p; + pspec = &expr->specializations.pspec[npspecs]; + memset(pspec, 0, sizeof *pspec); + + pspec->rhs_pspecs = rpc; + pspec->my_clone = exc; + exc->spec_index = npspecs; + + /* Update LHS->RHS specialization in target */ + target = TQ_FIRST(&rpc->members); + for(i = 0; i < exc->lhs_params->params_count; + i++, target = TQ_NEXT(target, next)) { + if(!target) { target = (void *)0xdeadbeef; break; } + + assert(exc->lhs_params->params[i].into_expr == 0); + exc->lhs_params->params[i].into_expr = target; } - asn1p_paramlist_free(nex->params); - nex->params = NULL; - nex->meta_type = expr->meta_type; - - ret = asn1f_param_process_recursive(arg, nex, ptype, expr); - if(ret != 0) { - asn1p_expr_free(nex); - return ret; + if(target) { + asn1p_expr_free(exc); + asn1p_expr_free(rpc); + FATAL("Parameterization of %s failed: " + "parameters number mismatch", expr->Identifier); + errno = EPERM; + return NULL; } - SUBSTITUTE(expr, nex); + DEBUG("Forked new parameterization for %s", expr->Identifier); - return ret; + /* Commit */ + expr->specializations.pspecs_count = npspecs + 1; + return exc; } static int -asn1f_param_process_recursive(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype, asn1p_expr_t *actargs) { - asn1p_expr_t *child; - - - TQ_FOR(child, &(expr->members), next) { - asn1p_expr_t *ra; - asn1p_expr_t *ne; /* new expression (clone) */ - - if(asn1f_param_process_constraints(arg, child, ptype, actargs)) - return -1; - - ra = _referenced_argument(child->reference, ptype, actargs); - if(ra) { - DEBUG("Substituting parameter for %s %s at line %d", - child->Identifier, - asn1f_printable_reference(child->reference), - child->_lineno - ); - - assert(child->meta_type == AMT_TYPEREF); - assert(child->expr_type == A1TC_REFERENCE); - - ne = asn1p_expr_clone(ra, 0); - if(ne == NULL) return -1; - assert(ne->Identifier == 0); - ne->Identifier = strdup(child->Identifier); - if(ne->Identifier == 0) { - asn1p_expr_free(ne); - return -1; - } - SUBSTITUTE(child, ne); +compare_specializations(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b) { + asn1p_expr_t *ac = TQ_FIRST(&a->members); + asn1p_expr_t *bc = TQ_FIRST(&b->members); + + for(;ac && bc; ac = TQ_NEXT(ac, next), bc = TQ_NEXT(bc, next)) { + retry: + if(ac == bc) continue; + if(ac->meta_type != bc->meta_type) break; + if(ac->expr_type != bc->expr_type) break; + + if(!ac->reference && !bc->reference) + continue; + + if(ac->reference) { + ac = asn1f_lookup_symbol(arg, + ac->module, ac->rhs_pspecs, ac->reference); + if(!ac) break; } + if(bc->reference) { + bc = asn1f_lookup_symbol(arg, + bc->module, bc->rhs_pspecs, bc->reference); + if(!bc) break; + } + goto retry; } + if(ac || bc) + /* Specializations do not match: different size option sets */ + return -1; + return 0; } -/* - * Check that the given ref looks like an argument of a parametrized type. - */ static asn1p_expr_t * -_referenced_argument(asn1p_ref_t *ref, asn1p_expr_t *ptype, asn1p_expr_t *actargs) { - asn1p_expr_t *aa; - int i; +resolve_expr(asn1p_expr_t *expr_to_resolve, void *resolver_arg) { + resolver_arg_t *rarg = resolver_arg; + arg_t *arg = rarg->arg; + asn1p_expr_t *expr; + asn1p_expr_t *nex; - if(ref == NULL || ref->comp_count != 1) + DEBUG("Resolving %s (meta %d)", + expr_to_resolve->Identifier, expr_to_resolve->meta_type); + + if(expr_to_resolve->meta_type == AMT_TYPEREF) { + expr = find_target_specialization_byref(rarg, + expr_to_resolve->reference); + if(!expr) return NULL; + } else if(expr_to_resolve->meta_type == AMT_VALUE) { + assert(expr_to_resolve->value); + expr = find_target_specialization_bystr(rarg, + expr_to_resolve->Identifier); + if(!expr) return NULL; + } else { + errno = ESRCH; return NULL; - - aa = TQ_FIRST(&(actargs->members)); - for(i = 0; i < ptype->params->params_count; - i++, aa = TQ_NEXT(aa, next)) { - if(strcmp(ref->components[0].name, - ptype->params->params[i].argument) == 0) - return aa; } - return NULL; -} - -/* - * Search for parameters inside constraints. - */ -static int -asn1f_param_process_constraints(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype, asn1p_expr_t *actargs) { - asn1p_constraint_t *cts; - int ret; - - if(!expr->constraints) return 0; - - cts = asn1p_constraint_clone(expr->constraints); - assert(cts); - - ret = _process_constraints(arg, cts, ptype, actargs); - if(ret == 1) { - asn1p_constraint_free(expr->constraints); - expr->constraints = cts; - ret = 0; + DEBUG("Found target %s", expr->Identifier); + if(expr->meta_type == AMT_TYPE + || expr->meta_type == AMT_VALUE) { + DEBUG("Target is a simple type %s", + ASN_EXPR_TYPE2STR(expr->expr_type)); + nex = asn1p_expr_clone(expr, 0); + free(nex->Identifier); + nex->Identifier = expr_to_resolve->Identifier + ? strdup(expr_to_resolve->Identifier) : 0; + return nex; } else { - asn1p_constraint_free(cts); + FATAL("Feature not implemented for %s", + rarg->original_expr->Identifier); + errno = EPERM; + return NULL; } - return ret; + return NULL; } -static int -_process_constraints(arg_t *arg, asn1p_constraint_t *ct, asn1p_expr_t *ptype, asn1p_expr_t *actargs) { - asn1p_value_t *values[3]; - int rvalue = 0; - size_t i; - - values[0] = ct->value; - values[1] = ct->range_start; - values[2] = ct->range_stop; - - for(i = 0; i < sizeof(values)/sizeof(values[0]); i++) { - asn1p_value_t *v = values[i]; - asn1p_expr_t *ra; - asn1p_ref_t *ref; - char *str; - - if(!v || v->type != ATV_REFERENCED) continue; +static asn1p_expr_t * +find_target_specialization_byref(resolver_arg_t *rarg, asn1p_ref_t *ref) { + char *refstr; - ref = v->value.reference; - ra = _referenced_argument(ref, ptype, actargs); - if(!ra) continue; + if(!ref || ref->comp_count != 1) { + errno = ESRCH; + return NULL; + } - DEBUG("_process_constraints(%s), ra=%s", - asn1f_printable_reference(ref), ra->Identifier); + refstr = ref->components[0].name; /* T */ - if(ra->expr_type == A1TC_PARAMETRIZED) { - DEBUG("Double %s", "parametrization"); - } + return find_target_specialization_bystr(rarg, refstr); +} - assert(ra->Identifier); - str = strdup(ra->Identifier); - if(!str) return -1; +static asn1p_expr_t * +find_target_specialization_bystr(resolver_arg_t *rarg, char *refstr) { + arg_t *arg = rarg->arg; + asn1p_expr_t *target; + int i; - assert(ref->comp_count == 1); - ref = asn1p_ref_new(ref->_lineno); - if(!ref) { free(str); return -1; } + target = TQ_FIRST(&rarg->rhs_pspecs->members); + for(i = 0; i < rarg->lhs_params->params_count; + i++, target = TQ_NEXT(target, next)) { + struct asn1p_param_s *param = &rarg->lhs_params->params[i]; + if(!target) break; - if(asn1p_ref_add_component(ref, str, 0)) { - free(str); - return -1; - } + if(strcmp(param->argument, refstr)) + continue; - asn1p_ref_free(v->value.reference); - v->value.reference = ref; - rvalue = 1; + return target; } - - /* Process the rest of constraints recursively */ - for(i = 0; i < ct->el_count; i++) { - int ret = _process_constraints(arg, ct->elements[i], - ptype, actargs); - if(ret == -1) - rvalue = -1; - else if(ret == 1 && rvalue != -1) - rvalue = 1; + if(i != rarg->lhs_params->params_count) { + FATAL("Parameterization of %s failed: " + "parameters number mismatch", + rarg->original_expr->Identifier); + errno = EPERM; + return NULL; } - return rvalue; + errno = ESRCH; + return NULL; } - diff --git a/libasn1fix/asn1fix_param.h b/libasn1fix/asn1fix_param.h index 062ad8bd..5940b0e8 100644 --- a/libasn1fix/asn1fix_param.h +++ b/libasn1fix/asn1fix_param.h @@ -1,6 +1,6 @@ -#ifndef _ASN1FIX_PARAMETRIZATION_H_ -#define _ASN1FIX_PARAMETRIZATION_H_ +#ifndef _ASN1FIX_PARAMETERIZATION_H_ +#define _ASN1FIX_PARAMETERIZATION_H_ -int asn1f_fix_parametrized_assignment(arg_t *arg); +asn1p_expr_t *asn1f_parameterization_fork(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *rhs_pspecs); -#endif /* _ASN1FIX_PARAMETRIZATION_H_ */ +#endif /* _ASN1FIX_PARAMETERIZATION_H_ */ diff --git a/libasn1fix/asn1fix_retrieve.c b/libasn1fix/asn1fix_retrieve.c index 2c004be5..52506b81 100644 --- a/libasn1fix/asn1fix_retrieve.c +++ b/libasn1fix/asn1fix_retrieve.c @@ -146,7 +146,7 @@ asn1f_lookup_module(arg_t *arg, const char *module_name, asn1p_oid_t *oid) { } static asn1p_expr_t * -asn1f_lookup_symbol_impl(arg_t *arg, asn1p_module_t *mod, asn1p_ref_t *ref, int recursion_depth) { +asn1f_lookup_symbol_impl(arg_t *arg, asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, asn1p_ref_t *ref, int recursion_depth) { asn1p_expr_t *ref_tc; /* Referenced tc */ asn1p_module_t *imports_from; char *modulename; @@ -193,7 +193,7 @@ asn1f_lookup_symbol_impl(arg_t *arg, asn1p_module_t *mod, asn1p_ref_t *ref, int * This is a reference to a CLASS-related stuff. * Employ a separate function for that. */ - extract = asn1f_class_access(arg, mod, ref); + extract = asn1f_class_access(arg, mod, rhs_pspecs, ref); return extract; } else { @@ -255,7 +255,8 @@ asn1f_lookup_symbol_impl(arg_t *arg, asn1p_module_t *mod, asn1p_ref_t *ref, int assert(tmpref.comp_count > 0); } - expr = asn1f_lookup_symbol_impl(arg, imports_from, &tmpref, recursion_depth); + expr = asn1f_lookup_symbol_impl(arg, imports_from, + rhs_pspecs, &tmpref, recursion_depth); if(!expr && !(arg->expr->_mark & TM_BROKEN) && !(imports_from->_tags & MT_STANDARD_MODULE)) { arg->expr->_mark |= TM_BROKEN; @@ -285,9 +286,38 @@ asn1f_lookup_symbol_impl(arg_t *arg, asn1p_module_t *mod, asn1p_ref_t *ref, int if(strcmp(ref_tc->Identifier, identifier) == 0) break; } - if(ref_tc) + if(ref_tc) { + if(rhs_pspecs && !ref_tc->lhs_params) { + FATAL("Parameterized type %s expected " + "for %s at line %d", + ref_tc->Identifier, + asn1f_printable_reference(ref), + ref->_lineno); + errno = EPERM; + return NULL; + } + if(!rhs_pspecs && ref_tc->lhs_params) { + FATAL("Type %s expects specialization " + "from %s at line %d", + ref_tc->Identifier, + asn1f_printable_reference(ref), + ref->_lineno); + errno = EPERM; + return NULL; + } + if(rhs_pspecs && ref_tc->lhs_params) { + /* Specialize the target */ + ref_tc = asn1f_parameterization_fork(arg, + ref_tc, rhs_pspecs); + } + return ref_tc; + } + /* + * Not found in the current module. + * Search in our default standard module. + */ { /* Search inside standard module */ static asn1p_oid_t *uioc_oid; @@ -335,8 +365,9 @@ asn1f_lookup_symbol_impl(arg_t *arg, asn1p_module_t *mod, asn1p_ref_t *ref, int asn1p_expr_t * -asn1f_lookup_symbol(arg_t *arg, asn1p_module_t *mod, asn1p_ref_t *ref) { - return asn1f_lookup_symbol_impl(arg, mod, ref, 0); +asn1f_lookup_symbol(arg_t *arg, + asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, asn1p_ref_t *ref) { + return asn1f_lookup_symbol_impl(arg, mod, rhs_pspecs, ref, 0); } asn1p_expr_t * @@ -397,7 +428,7 @@ asn1f_find_terminal_thing(arg_t *arg, asn1p_expr_t *expr, enum ftt_what what) { /* * Lookup inside the default module and its IMPORTS section. */ - tc = asn1f_lookup_symbol(arg, expr->module, ref); + tc = asn1f_lookup_symbol(arg, expr->module, expr->rhs_pspecs, ref); if(tc == NULL) { DEBUG("\tSymbol \"%s\" not found: %s", asn1f_printable_reference(ref), diff --git a/libasn1fix/asn1fix_retrieve.h b/libasn1fix/asn1fix_retrieve.h index 8ab02607..2aeb82be 100644 --- a/libasn1fix/asn1fix_retrieve.h +++ b/libasn1fix/asn1fix_retrieve.h @@ -39,6 +39,7 @@ asn1p_module_t *asn1f_lookup_module(arg_t *arg, */ asn1p_expr_t *asn1f_lookup_symbol(arg_t *arg, asn1p_module_t *mod, + asn1p_expr_t *rhs_pspecs, asn1p_ref_t *ref); /* diff --git a/libasn1fix/asn1fix_tags.c b/libasn1fix/asn1fix_tags.c index 3215fff6..db4d4ed1 100644 --- a/libasn1fix/asn1fix_tags.c +++ b/libasn1fix/asn1fix_tags.c @@ -66,7 +66,7 @@ asn1f_fetch_tags_impl(arg_t *arg, struct asn1p_type_tag_s **tags, int count, int if(expr->meta_type == AMT_TYPEREF) { asn1p_expr_t *nexpr; DEBUG("Following the reference %s", expr->Identifier); - nexpr = asn1f_lookup_symbol(arg, expr->module, expr->reference); + nexpr = asn1f_lookup_symbol(arg, expr->module, expr->rhs_pspecs, expr->reference); if(nexpr == NULL) { if(errno != EEXIST) /* -fknown-extern-type */ return -1; |