blob: 77daba1302c01047e916638b1cc8c2044ac51f9d [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
2
Lev Walkina00d6b32006-03-21 03:40:38 +00003typedef struct resolver_arg {
4 asn1p_expr_t *(*resolver)(asn1p_expr_t *, void *arg);
5 arg_t *arg;
6 asn1p_expr_t *original_expr;
7 asn1p_paramlist_t *lhs_params;
8 asn1p_expr_t *rhs_pspecs;
9} resolver_arg_t;
Lev Walkind541c252004-09-05 10:36:22 +000010
Lev Walkina00d6b32006-03-21 03:40:38 +000011static asn1p_expr_t *resolve_expr(asn1p_expr_t *, void *resolver_arg);
Lev Walkinf75b8742017-08-23 04:44:18 -070012static int compare_specializations(const asn1p_expr_t *a, const asn1p_expr_t *b);
Bi-Ruei, Chiu214c4912017-10-19 00:31:14 +080013static asn1p_expr_t *find_target_specialization_byvalueset(resolver_arg_t *rarg, asn1p_constraint_t *ct);
Lev Walkina00d6b32006-03-21 03:40:38 +000014static asn1p_expr_t *find_target_specialization_byref(resolver_arg_t *rarg, asn1p_ref_t *ref);
15static asn1p_expr_t *find_target_specialization_bystr(resolver_arg_t *rarg, char *str);
Lev Walkinf15320b2004-06-03 03:38:44 +000016
Lev Walkina00d6b32006-03-21 03:40:38 +000017asn1p_expr_t *
18asn1f_parameterization_fork(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *rhs_pspecs) {
19 resolver_arg_t rarg; /* resolver argument */
20 asn1p_expr_t *exc; /* expr clone */
21 asn1p_expr_t *rpc; /* rhs_pspecs clone */
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +080022 asn1p_expr_t *m; /* expr members */
Bi-Ruei, Chiu214c4912017-10-19 00:31:14 +080023 asn1p_expr_t *target;
Lev Walkinf15320b2004-06-03 03:38:44 +000024 void *p;
Lev Walkina00d6b32006-03-21 03:40:38 +000025 struct asn1p_pspec_s *pspec;
26 int npspecs;
Lev Walkinf15320b2004-06-03 03:38:44 +000027
Lev Walkina00d6b32006-03-21 03:40:38 +000028 assert(rhs_pspecs);
29 assert(expr->lhs_params);
30 assert(expr->parent_expr == 0);
31
Lev Walkinf15320b2004-06-03 03:38:44 +000032 /*
Lev Walkina00d6b32006-03-21 03:40:38 +000033 * Find if this exact specialization has been used already.
Lev Walkinf15320b2004-06-03 03:38:44 +000034 */
Lev Walkina00d6b32006-03-21 03:40:38 +000035 for(npspecs = 0;
36 npspecs < expr->specializations.pspecs_count;
37 npspecs++) {
Lev Walkinf75b8742017-08-23 04:44:18 -070038 if(compare_specializations(rhs_pspecs,
Lev Walkina00d6b32006-03-21 03:40:38 +000039 expr->specializations.pspec[npspecs].rhs_pspecs) == 0) {
40 DEBUG("Reused parameterization for %s",
41 expr->Identifier);
42 return expr->specializations.pspec[npspecs].my_clone;
Lev Walkind5947712005-11-05 12:28:14 +000043 }
Lev Walkinf15320b2004-06-03 03:38:44 +000044 }
Lev Walkinf15320b2004-06-03 03:38:44 +000045
Lev Walkind8e07c52017-08-23 07:38:30 -070046 DEBUG("Forking parameterization at %d for %s (%d alr)",
47 rhs_pspecs->_lineno, expr->Identifier,
48 expr->specializations.pspecs_count);
49
Lev Walkina00d6b32006-03-21 03:40:38 +000050 rarg.resolver = resolve_expr;
51 rarg.arg = arg;
52 rarg.original_expr = expr;
53 rarg.lhs_params = expr->lhs_params;
54 rarg.rhs_pspecs = rhs_pspecs;
55 exc = asn1p_expr_clone_with_resolver(expr, resolve_expr, &rarg);
Lev Walkinc5a5d222007-06-23 17:35:56 +000056 if(!exc) return NULL;
Lev Walkina00d6b32006-03-21 03:40:38 +000057 rpc = asn1p_expr_clone(rhs_pspecs, 0);
Lev Walkinc5a5d222007-06-23 17:35:56 +000058 assert(rpc);
Lev Walkina00d6b32006-03-21 03:40:38 +000059
60 /*
61 * Create a new specialization.
62 */
63 npspecs = expr->specializations.pspecs_count;
64 p = realloc(expr->specializations.pspec,
65 (npspecs + 1) * sizeof(expr->specializations.pspec[0]));
66 assert(p);
67 expr->specializations.pspec = p;
68 pspec = &expr->specializations.pspec[npspecs];
69 memset(pspec, 0, sizeof *pspec);
70
71 pspec->rhs_pspecs = rpc;
72 pspec->my_clone = exc;
73 exc->spec_index = npspecs;
Bi-Ruei, Chiu214c4912017-10-19 00:31:14 +080074 exc->rhs_pspecs = asn1p_expr_clone_with_resolver(expr->rhs_pspecs ?
75 expr->rhs_pspecs : rhs_pspecs,
76 resolve_expr, &rarg);
Lev Walkina00d6b32006-03-21 03:40:38 +000077
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +080078 /* Passing arguments to members and type references */
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +080079
Bi-Ruei, Chiu214c4912017-10-19 00:31:14 +080080 target = TQ_FIRST(&expr->members);
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +080081 TQ_FOR(m, &exc->members, next) {
Bi-Ruei, Chiu214c4912017-10-19 00:31:14 +080082 m->rhs_pspecs = asn1p_expr_clone_with_resolver(target->rhs_pspecs ?
83 target->rhs_pspecs : exc->rhs_pspecs,
84 resolve_expr, &rarg);
85 target = TQ_NEXT(target, next);
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +080086 }
87
Lev Walkina00d6b32006-03-21 03:40:38 +000088 DEBUG("Forked new parameterization for %s", expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +000089
Lev Walkina00d6b32006-03-21 03:40:38 +000090 /* Commit */
91 expr->specializations.pspecs_count = npspecs + 1;
92 return exc;
Lev Walkinf15320b2004-06-03 03:38:44 +000093}
94
95static int
Lev Walkinf75b8742017-08-23 04:44:18 -070096compare_specializations(const asn1p_expr_t *a, const asn1p_expr_t *b) {
97 return asn1p_expr_compare(a, b);
Lev Walkinf15320b2004-06-03 03:38:44 +000098}
99
100static asn1p_expr_t *
Lev Walkina00d6b32006-03-21 03:40:38 +0000101resolve_expr(asn1p_expr_t *expr_to_resolve, void *resolver_arg) {
102 resolver_arg_t *rarg = resolver_arg;
103 arg_t *arg = rarg->arg;
104 asn1p_expr_t *expr;
105 asn1p_expr_t *nex;
Lev Walkinf15320b2004-06-03 03:38:44 +0000106
Lev Walkina00d6b32006-03-21 03:40:38 +0000107 DEBUG("Resolving %s (meta %d)",
108 expr_to_resolve->Identifier, expr_to_resolve->meta_type);
109
110 if(expr_to_resolve->meta_type == AMT_TYPEREF) {
111 expr = find_target_specialization_byref(rarg,
112 expr_to_resolve->reference);
113 if(!expr) return NULL;
114 } else if(expr_to_resolve->meta_type == AMT_VALUE) {
Bi-Ruei, Chiue460c3b2017-10-19 20:49:17 +0800115 if(!expr_to_resolve->value) return NULL;
Lev Walkina00d6b32006-03-21 03:40:38 +0000116 expr = find_target_specialization_bystr(rarg,
117 expr_to_resolve->Identifier);
118 if(!expr) return NULL;
Bi-Ruei, Chiu214c4912017-10-19 00:31:14 +0800119 } else if(expr_to_resolve->meta_type == AMT_VALUESET) {
120 assert(expr_to_resolve->constraints);
121 expr = find_target_specialization_byvalueset(rarg,
122 expr_to_resolve->constraints);
123 if(!expr) return NULL;
Lev Walkina00d6b32006-03-21 03:40:38 +0000124 } else {
125 errno = ESRCH;
Lev Walkinf15320b2004-06-03 03:38:44 +0000126 return NULL;
Lev Walkina00d6b32006-03-21 03:40:38 +0000127 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000128
Lev Walkin5045dfa2006-03-21 09:41:28 +0000129 DEBUG("Found target %s (%d/%x)",
130 expr->Identifier, expr->meta_type, expr->expr_type);
Lev Walkina00d6b32006-03-21 03:40:38 +0000131 if(expr->meta_type == AMT_TYPE
Lev Walkin5045dfa2006-03-21 09:41:28 +0000132 || expr->meta_type == AMT_VALUE
Lev Walkinc5a5d222007-06-23 17:35:56 +0000133 || expr->meta_type == AMT_TYPEREF
Lev Walkin5045dfa2006-03-21 09:41:28 +0000134 || expr->meta_type == AMT_VALUESET) {
Lev Walkina00d6b32006-03-21 03:40:38 +0000135 DEBUG("Target is a simple type %s",
136 ASN_EXPR_TYPE2STR(expr->expr_type));
137 nex = asn1p_expr_clone(expr, 0);
138 free(nex->Identifier);
139 nex->Identifier = expr_to_resolve->Identifier
140 ? strdup(expr_to_resolve->Identifier) : 0;
141 return nex;
142 } else {
Lev Walkin5045dfa2006-03-21 09:41:28 +0000143 FATAL("Feature not implemented for %s (%d/%x), "
144 "please contact the asn1c author",
145 rarg->original_expr->Identifier,
146 expr->meta_type, expr->expr_type);
Lev Walkina00d6b32006-03-21 03:40:38 +0000147 errno = EPERM;
148 return NULL;
Lev Walkinf15320b2004-06-03 03:38:44 +0000149 }
150
151 return NULL;
152}
Lev Walkind541c252004-09-05 10:36:22 +0000153
Lev Walkina00d6b32006-03-21 03:40:38 +0000154static asn1p_expr_t *
Bi-Ruei, Chiu214c4912017-10-19 00:31:14 +0800155find_target_specialization_byvalueset(resolver_arg_t *rarg, asn1p_constraint_t *ct) {
156 asn1p_ref_t *ref;
157
Bi-Ruei, Chiue460c3b2017-10-19 20:49:17 +0800158 if (ct->type != ACT_EL_TYPE) return NULL;
Bi-Ruei, Chiu214c4912017-10-19 00:31:14 +0800159
160 ref = ct->containedSubtype->value.v_type->reference;
161
162 return find_target_specialization_byref(rarg, ref);
163}
164
165static asn1p_expr_t *
Lev Walkina00d6b32006-03-21 03:40:38 +0000166find_target_specialization_byref(resolver_arg_t *rarg, asn1p_ref_t *ref) {
167 char *refstr;
Lev Walkind541c252004-09-05 10:36:22 +0000168
Lev Walkina00d6b32006-03-21 03:40:38 +0000169 if(!ref || ref->comp_count != 1) {
170 errno = ESRCH;
171 return NULL;
Lev Walkind541c252004-09-05 10:36:22 +0000172 }
173
Lev Walkina00d6b32006-03-21 03:40:38 +0000174 refstr = ref->components[0].name; /* T */
175
176 return find_target_specialization_bystr(rarg, refstr);
Lev Walkind541c252004-09-05 10:36:22 +0000177}
178
Lev Walkina00d6b32006-03-21 03:40:38 +0000179static asn1p_expr_t *
180find_target_specialization_bystr(resolver_arg_t *rarg, char *refstr) {
181 arg_t *arg = rarg->arg;
182 asn1p_expr_t *target;
183 int i;
Lev Walkind541c252004-09-05 10:36:22 +0000184
Bi-Ruei, Chiu214c4912017-10-19 00:31:14 +0800185 if(!refstr) return NULL;
186
Lev Walkina00d6b32006-03-21 03:40:38 +0000187 target = TQ_FIRST(&rarg->rhs_pspecs->members);
188 for(i = 0; i < rarg->lhs_params->params_count;
189 i++, target = TQ_NEXT(target, next)) {
190 struct asn1p_param_s *param = &rarg->lhs_params->params[i];
191 if(!target) break;
Lev Walkind541c252004-09-05 10:36:22 +0000192
Lev Walkina00d6b32006-03-21 03:40:38 +0000193 if(strcmp(param->argument, refstr))
194 continue;
Lev Walkind541c252004-09-05 10:36:22 +0000195
Lev Walkina00d6b32006-03-21 03:40:38 +0000196 return target;
197 }
198 if(i != rarg->lhs_params->params_count) {
199 FATAL("Parameterization of %s failed: "
200 "parameters number mismatch",
201 rarg->original_expr->Identifier);
202 errno = EPERM;
203 return NULL;
Lev Walkind541c252004-09-05 10:36:22 +0000204 }
205
Lev Walkina00d6b32006-03-21 03:40:38 +0000206 errno = ESRCH;
207 return NULL;
Lev Walkind541c252004-09-05 10:36:22 +0000208}