blob: 1ecdeb10b43cb49c3363f182c9e9234b324e487b [file] [log] [blame]
vlmfa67ddc2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
2
3static int asn1f_parametrize(arg_t *arg, asn1p_expr_t *ex, asn1p_expr_t *ptype);
4static int asn1f_param_process_recursive(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype, asn1p_expr_t *actargs);
vlm76142452004-09-05 10:36:22 +00005static int asn1f_param_process_constraints(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype, asn1p_expr_t *actargs);
6
vlmfa67ddc2004-06-03 03:38:44 +00007static asn1p_expr_t *_referenced_argument(asn1p_ref_t *ref, asn1p_expr_t *ptype, asn1p_expr_t *actargs);
vlm76142452004-09-05 10:36:22 +00008static int _process_constraints(arg_t *arg, asn1p_constraint_t *ct, asn1p_expr_t *ptype, asn1p_expr_t *actargs);
vlmfa67ddc2004-06-03 03:38:44 +00009
10int
11asn1f_fix_parametrized_assignment(arg_t *arg) {
12 asn1p_expr_t *expr = arg->expr;
13 asn1p_expr_t *ptype;
14
15 assert(expr->expr_type == A1TC_PARAMETRIZED);
16 assert(expr->reference);
17
18 DEBUG("%s(\"%s\" ::= \"%s\" { %s }) for line %d",
19 __func__, expr->Identifier,
20 asn1f_printable_reference(expr->reference),
21 asn1f_printable_value(expr->value),
22 expr->_lineno);
23
24 /*
25 * Find the corresponding parametrized type definition.
26 */
27 DEBUG("Looking for parametrized type definition \"%s\"",
28 asn1f_printable_reference(expr->reference));
vlm2e0c1942004-08-22 03:10:23 +000029 ptype = asn1f_lookup_symbol(arg, expr->module, expr->reference);
vlmfa67ddc2004-06-03 03:38:44 +000030 if(ptype == NULL) {
31 DEBUG("%s: missing parametrized type declaration",
32 asn1f_printable_reference(expr->reference));
33 return -1;
34 }
35
36 /*
37 * Check that the number of arguments which are expected by
38 * the parametrized type declaration is consistent with the
39 * number of arguments supplied by the parametrized assignment.
40 */
41 if(asn1f_count_children(expr) != ptype->params->params_count) {
42 FATAL("Number of actual arguments %d in %s at line %d "
43 "is not equal to number of expected arguments "
44 "%d in %s at line %d",
45 asn1f_count_children(expr),
46 asn1f_printable_reference(expr->reference),
47 expr->_lineno,
48 ptype->params->params_count,
49 ptype->Identifier,
50 ptype->_lineno
51 );
52 return -1;
53 }
54
55 /*
56 * Perform an expansion of a parametrized assignment.
57 */
58 return asn1f_parametrize(arg, expr, ptype);
59}
60
vlm6a02a8a2004-09-08 00:28:11 +000061#define SUBSTITUTE(to, from) do { \
62 asn1p_expr_t tmp, *__v; \
63 tmp = *(to); \
64 *(to) = *(from); \
65 TQ_MOVE(&(to)->members, &(from)->members); \
66 *(from) = tmp; \
67 (to)->next = tmp.next; \
68 (to)->parent_expr = tmp.parent_expr; \
69 memset(&((from)->next), 0, \
70 sizeof((from)->next)); \
71 memset(&((from)->members), 0, \
72 sizeof((from)->members)); \
73 asn1p_expr_free(from); \
74 TQ_FOR(__v, &((to)->members), next) { \
75 assert(__v->parent_expr == (from)); \
76 __v->parent_expr = (to); \
77 } \
vlmfa67ddc2004-06-03 03:38:44 +000078 } while(0)
79
80static int
81asn1f_parametrize(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype) {
82 asn1p_expr_t *nex;
83 void *p;
84 int ret;
85
86 /*
87 * The algorithm goes like that:
88 * 1. Replace the expression's type with parametrized type.
89 * 2. For every child in the parametrized type, import it
90 * as a child of the expression, replacing all occurences of
91 * symbols which are defined as parametrized type arguments
92 * with the actual values.
vlm76142452004-09-05 10:36:22 +000093 * 3. Don't forget to parametrize the subtype constraints.
vlmfa67ddc2004-06-03 03:38:44 +000094 */
95
vlm2e0c1942004-08-22 03:10:23 +000096 nex = asn1p_expr_clone(ptype, 0);
vlmfa67ddc2004-06-03 03:38:44 +000097 if(nex == NULL) return -1;
98
99 /*
100 * Cleanup the new expression so there is no ptype-related
101 * stuff hanging around.
102 */
103 p = strdup(expr->Identifier);
104 if(p) {
105 free(nex->Identifier);
106 nex->Identifier = p;
107 } else {
108 asn1p_expr_free(nex);
109 return -1;
110 }
111 asn1p_paramlist_free(nex->params);
112 nex->params = NULL;
113 nex->meta_type = expr->meta_type;
114
115 ret = asn1f_param_process_recursive(arg, nex, ptype, expr);
116 if(ret != 0) {
117 asn1p_expr_free(nex);
118 return ret;
119 }
120
121 SUBSTITUTE(expr, nex);
122
123 return ret;
124}
125
126static int
127asn1f_param_process_recursive(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype, asn1p_expr_t *actargs) {
128 asn1p_expr_t *child;
129
130 TQ_FOR(child, &(expr->members), next) {
131 asn1p_expr_t *ra;
vlm76142452004-09-05 10:36:22 +0000132 asn1p_expr_t *ne; /* new expression (clone) */
133
134 if(asn1f_param_process_constraints(arg, child, ptype, actargs))
135 return -1;
vlmfa67ddc2004-06-03 03:38:44 +0000136
137 ra = _referenced_argument(child->reference, ptype, actargs);
vlm76142452004-09-05 10:36:22 +0000138 if(ra) {
139 DEBUG("Substituting parameter for %s %s at line %d",
140 child->Identifier,
141 asn1f_printable_reference(child->reference),
142 child->_lineno
143 );
144
145 assert(child->meta_type == AMT_TYPEREF);
146 assert(child->expr_type == A1TC_REFERENCE);
147
148 ne = asn1p_expr_clone(ra, 0);
149 if(ne == NULL) return -1;
150 assert(ne->Identifier == 0);
151 ne->Identifier = strdup(child->Identifier);
152 if(ne->Identifier == 0) {
153 asn1p_expr_free(ne);
154 return -1;
155 }
156 SUBSTITUTE(child, ne);
vlmfa67ddc2004-06-03 03:38:44 +0000157 }
vlmfa67ddc2004-06-03 03:38:44 +0000158 }
159
160 return 0;
161}
162
vlm76142452004-09-05 10:36:22 +0000163/*
164 * Check that the given ref looks like an argument of a parametrized type.
165 */
vlmfa67ddc2004-06-03 03:38:44 +0000166static asn1p_expr_t *
167_referenced_argument(asn1p_ref_t *ref, asn1p_expr_t *ptype, asn1p_expr_t *actargs) {
168 asn1p_expr_t *aa;
169 int i;
170
171 if(ref == NULL || ref->comp_count != 1)
172 return NULL;
173
174 aa = TQ_FIRST(&(actargs->members));
175 for(i = 0; i < ptype->params->params_count;
176 i++, aa = TQ_NEXT(aa, next)) {
177 if(strcmp(ref->components[0].name,
178 ptype->params->params[i].argument) == 0)
179 return aa;
180 }
181
182 return NULL;
183}
vlm76142452004-09-05 10:36:22 +0000184
185/*
186 * Search for parameters inside constraints.
187 */
188static int
189asn1f_param_process_constraints(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype, asn1p_expr_t *actargs) {
190 asn1p_constraint_t *cts;
191 int ret;
192
193 if(!expr->constraints) return 0;
194
195 cts = asn1p_constraint_clone(expr->constraints);
196 assert(cts);
197
198 ret = _process_constraints(arg, cts, ptype, actargs);
199 if(ret == 1) {
200 asn1p_constraint_free(expr->constraints);
201 expr->constraints = cts;
202 ret = 0;
203 } else {
204 asn1p_constraint_free(cts);
205 }
206
207 return ret;
208}
209
210static int
211_process_constraints(arg_t *arg, asn1p_constraint_t *ct, asn1p_expr_t *ptype, asn1p_expr_t *actargs) {
212 asn1p_value_t *values[3];
213 int rvalue = 0;
214 size_t i;
215
216 values[0] = ct->value;
217 values[1] = ct->range_start;
218 values[2] = ct->range_stop;
219
220 for(i = 0; i < sizeof(values)/sizeof(values[0]); i++) {
221 asn1p_value_t *v = values[i];
222 asn1p_expr_t *ra;
223 asn1p_ref_t *ref;
224 char *str;
225
226 if(!v || v->type != ATV_REFERENCED) continue;
227
228 ref = v->value.reference;
229 ra = _referenced_argument(ref, ptype, actargs);
230 if(!ra) continue;
231
232 DEBUG("_process_constraints(%s), ra=%s",
233 asn1f_printable_reference(ref), ra->Identifier);
234
235 str = strdup(ra->Identifier);
236 if(!str) return -1;
237
238 assert(ref->comp_count == 1);
239 ref = asn1p_ref_new(ref->_lineno);
240 if(!ref) { free(str); return -1; }
241
242 if(asn1p_ref_add_component(ref, str, 0)) {
243 free(str);
244 return -1;
245 }
246
247 asn1p_ref_free(v->value.reference);
248 v->value.reference = ref;
249 rvalue = 1;
250 }
251
252 /* Process the rest of constraints recursively */
253 for(i = 0; i < ct->el_count; i++) {
254 int ret = _process_constraints(arg, ct->elements[i],
255 ptype, actargs);
256 if(ret == -1)
257 rvalue = -1;
258 else if(ret == 1 && rvalue != -1)
259 rvalue = 1;
260 }
261
262 return rvalue;
263}
264