mirror of https://gerrit.osmocom.org/asn1c
166 lines
4.1 KiB
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;
|
|
}
|