aboutsummaryrefslogtreecommitdiffstats
path: root/libasn1fix
diff options
context:
space:
mode:
authorLev Walkin <vlm@lionet.info>2006-03-21 03:40:38 +0000
committerLev Walkin <vlm@lionet.info>2006-03-21 03:40:38 +0000
commita00d6b371486efc2fbe6e812882d250f5a0bb75c (patch)
tree24c47f98731c42ea1df33a464c0fbca7ba760489 /libasn1fix
parent25b8f280603bc4ed70609c3aacc1ef8820b027b3 (diff)
refactored parameterization support
Diffstat (limited to 'libasn1fix')
-rw-r--r--libasn1fix/asn1fix.c158
-rw-r--r--libasn1fix/asn1fix_class.c8
-rw-r--r--libasn1fix/asn1fix_class.h8
-rw-r--r--libasn1fix/asn1fix_constr.c3
-rw-r--r--libasn1fix/asn1fix_constraint.c3
-rw-r--r--libasn1fix/asn1fix_cws.c2
-rw-r--r--libasn1fix/asn1fix_dereft.c3
-rw-r--r--libasn1fix/asn1fix_export.c5
-rw-r--r--libasn1fix/asn1fix_export.h2
-rw-r--r--libasn1fix/asn1fix_integer.c3
-rw-r--r--libasn1fix/asn1fix_internal.h2
-rw-r--r--libasn1fix/asn1fix_misc.c11
-rw-r--r--libasn1fix/asn1fix_param.c431
-rw-r--r--libasn1fix/asn1fix_param.h8
-rw-r--r--libasn1fix/asn1fix_retrieve.c45
-rw-r--r--libasn1fix/asn1fix_retrieve.h1
-rw-r--r--libasn1fix/asn1fix_tags.c2
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;