asn1c/libasn1fix/asn1fix_param.c

166 lines
4.1 KiB
C

#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 asn1p_expr_t *_referenced_argument(asn1p_ref_t *ref, 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;
assert(expr->expr_type == A1TC_PARAMETRIZED);
assert(expr->reference);
DEBUG("%s(\"%s\" ::= \"%s\" { %s }) for line %d",
__func__, expr->Identifier,
asn1f_printable_reference(expr->reference),
asn1f_printable_value(expr->value),
expr->_lineno);
/*
* Find the corresponding parametrized type definition.
*/
DEBUG("Looking for parametrized type definition \"%s\"",
asn1f_printable_reference(expr->reference));
ptype = asn1f_lookup_symbol(arg, expr->reference, 0);
if(ptype == NULL) {
DEBUG("%s: missing parametrized type declaration",
asn1f_printable_reference(expr->reference));
return -1;
}
/*
* 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;
}
/*
* Perform an expansion of a parametrized assignment.
*/
return asn1f_parametrize(arg, expr, ptype);
}
#define SUBSTITUTE(to, from) do { \
asn1p_expr_t tmp; \
tmp = *(to); \
*(to) = *(from); \
*(from) = tmp; \
(to)->next = tmp.next; \
memset(&((from)->next), 0, \
sizeof((from)->next)); \
asn1p_expr_free(from); \
} 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;
/*
* 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.
*/
nex = asn1p_expr_clone(ptype);
if(nex == NULL) return -1;
/*
* Cleanup the new expression so there is no ptype-related
* stuff hanging around.
*/
p = strdup(expr->Identifier);
if(p) {
free(nex->Identifier);
nex->Identifier = p;
} else {
asn1p_expr_free(nex);
return -1;
}
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;
}
SUBSTITUTE(expr, nex);
return ret;
}
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;
ra = _referenced_argument(child->reference, ptype, actargs);
if(ra == NULL) continue;
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);
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);
}
return 0;
}
static asn1p_expr_t *
_referenced_argument(asn1p_ref_t *ref, asn1p_expr_t *ptype, asn1p_expr_t *actargs) {
asn1p_expr_t *aa;
int i;
if(ref == NULL || ref->comp_count != 1)
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;
}