1 #include "asn1fix_internal.h"
3 typedef struct resolver_arg {
4 asn1p_expr_t *(*resolver)(asn1p_expr_t *, void *arg);
6 asn1p_expr_t *original_expr;
7 asn1p_paramlist_t *lhs_params;
8 asn1p_expr_t *rhs_pspecs;
12 static asn1p_expr_t *resolve_expr(asn1p_expr_t *, void *resolver_arg);
13 static int compare_specializations(const asn1p_expr_t *a, const asn1p_expr_t *b);
14 static asn1p_expr_t *find_target_specialization_byvalueset(resolver_arg_t *rarg, asn1p_constraint_t *ct);
15 static asn1p_expr_t *find_target_specialization_byref(resolver_arg_t *rarg, asn1p_ref_t *ref);
16 static asn1p_expr_t *find_target_specialization_bystr(resolver_arg_t *rarg, char *str);
19 asn1f_parameterization_fork(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *rhs_pspecs) {
20 resolver_arg_t rarg; /* resolver argument */
21 asn1p_expr_t *exc; /* expr clone */
22 asn1p_expr_t *rpc; /* rhs_pspecs clone */
23 asn1p_expr_t *m; /* expr members */
26 struct asn1p_pspec_s *pspec;
30 assert(expr->lhs_params);
31 assert(expr->parent_expr == 0);
34 * Find if this exact specialization has been used already.
37 npspecs < expr->specializations.pspecs_count;
39 if(compare_specializations(rhs_pspecs,
40 expr->specializations.pspec[npspecs].rhs_pspecs) == 0) {
41 DEBUG("Reused parameterization for %s",
43 return expr->specializations.pspec[npspecs].my_clone;
47 DEBUG("Forking parameterization at %d for %s (%d alr)",
48 rhs_pspecs->_lineno, expr->Identifier,
49 expr->specializations.pspecs_count);
51 rarg.resolver = resolve_expr;
53 rarg.original_expr = expr;
54 rarg.lhs_params = expr->lhs_params;
55 rarg.rhs_pspecs = rhs_pspecs;
56 rarg.resolved_name = NULL;
57 exc = asn1p_expr_clone_with_resolver(expr, resolve_expr, &rarg);
59 if(rarg.resolved_name) {
60 free(exc->Identifier);
61 exc->Identifier = strdup(rarg.resolved_name);
64 rpc = asn1p_expr_clone(rhs_pspecs, 0);
68 * Create a new specialization.
70 npspecs = expr->specializations.pspecs_count;
71 p = realloc(expr->specializations.pspec,
72 (npspecs + 1) * sizeof(expr->specializations.pspec[0]));
74 expr->specializations.pspec = p;
75 pspec = &expr->specializations.pspec[npspecs];
76 memset(pspec, 0, sizeof *pspec);
78 pspec->rhs_pspecs = rpc;
79 pspec->my_clone = exc;
80 exc->spec_index = npspecs;
81 exc->rhs_pspecs = asn1p_expr_clone_with_resolver(expr->rhs_pspecs ?
82 expr->rhs_pspecs : rhs_pspecs,
85 /* Passing arguments to members and type references */
87 target = TQ_FIRST(&expr->members);
88 TQ_FOR(m, &exc->members, next) {
89 m->rhs_pspecs = asn1p_expr_clone_with_resolver(target->rhs_pspecs ?
90 target->rhs_pspecs : exc->rhs_pspecs,
92 target = TQ_NEXT(target, next);
95 DEBUG("Forked new parameterization for %s", expr->Identifier);
98 expr->specializations.pspecs_count = npspecs + 1;
103 compare_specializations(const asn1p_expr_t *a, const asn1p_expr_t *b) {
104 return asn1p_expr_compare(a, b);
107 static asn1p_expr_t *
108 resolve_expr(asn1p_expr_t *expr_to_resolve, void *resolver_arg) {
109 resolver_arg_t *rarg = resolver_arg;
110 arg_t *arg = rarg->arg;
114 DEBUG("Resolving %s (meta %d)",
115 expr_to_resolve->Identifier, expr_to_resolve->meta_type);
117 if(expr_to_resolve->meta_type == AMT_TYPEREF) {
118 expr = find_target_specialization_byref(rarg,
119 expr_to_resolve->reference);
120 if(!expr) return NULL;
121 } else if(expr_to_resolve->meta_type == AMT_VALUE) {
122 if(!expr_to_resolve->value) return NULL;
123 expr = find_target_specialization_bystr(rarg,
124 expr_to_resolve->Identifier);
125 if(!expr) return NULL;
126 } else if(expr_to_resolve->meta_type == AMT_VALUESET) {
127 assert(expr_to_resolve->constraints);
128 expr = find_target_specialization_byvalueset(rarg,
129 expr_to_resolve->constraints);
130 if(!expr) return NULL;
136 DEBUG("Found target %s (%d/%x)",
137 expr->Identifier, expr->meta_type, expr->expr_type);
138 if(expr->meta_type == AMT_TYPE
139 || expr->meta_type == AMT_VALUE
140 || expr->meta_type == AMT_TYPEREF
141 || expr->meta_type == AMT_VALUESET) {
142 DEBUG("Target is a simple type %s",
143 ASN_EXPR_TYPE2STR(expr->expr_type));
144 nex = asn1p_expr_clone(expr, 0);
145 free(nex->Identifier);
146 nex->Identifier = expr_to_resolve->Identifier
147 ? strdup(expr_to_resolve->Identifier) : 0;
148 if(expr->meta_type == AMT_TYPEREF) {
149 asn1p_ref_t *ref = expr->reference;
150 rarg->resolved_name = ref->components[ref->comp_count - 1].name;
151 } else if(expr->meta_type == AMT_VALUESET) {
152 asn1p_constraint_t *ct = expr->constraints;
153 if(ct->type == ACT_EL_TYPE) {
154 asn1p_ref_t *ref = ct->containedSubtype->value.v_type->reference;
155 rarg->resolved_name = ref->components[ref->comp_count - 1].name;
160 FATAL("Feature not implemented for %s (%d/%x), "
161 "please contact the asn1c author",
162 rarg->original_expr->Identifier,
163 expr->meta_type, expr->expr_type);
171 static asn1p_expr_t *
172 find_target_specialization_byvalueset(resolver_arg_t *rarg, asn1p_constraint_t *ct) {
175 if (ct->type != ACT_EL_TYPE) return NULL;
177 ref = ct->containedSubtype->value.v_type->reference;
179 return find_target_specialization_byref(rarg, ref);
182 static asn1p_expr_t *
183 find_target_specialization_byref(resolver_arg_t *rarg, asn1p_ref_t *ref) {
186 if(!ref || ref->comp_count != 1) {
191 refstr = ref->components[0].name; /* T */
193 return find_target_specialization_bystr(rarg, refstr);
196 static asn1p_expr_t *
197 find_target_specialization_bystr(resolver_arg_t *rarg, char *refstr) {
198 arg_t *arg = rarg->arg;
199 asn1p_expr_t *target;
202 if(!refstr) return NULL;
204 target = TQ_FIRST(&rarg->rhs_pspecs->members);
205 for(i = 0; i < rarg->lhs_params->params_count;
206 i++, target = TQ_NEXT(target, next)) {
207 struct asn1p_param_s *param = &rarg->lhs_params->params[i];
210 if(strcmp(param->argument, refstr))
215 if(i != rarg->lhs_params->params_count) {
216 FATAL("Parameterization of %s failed: "
217 "parameters number mismatch",
218 rarg->original_expr->Identifier);