blob: 5ce6b933ba9be549df2d55228deb9a59415ca272 [file] [log] [blame]
Lev Walkinf15320b2004-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);
Lev Walkind541c252004-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
Lev Walkinf15320b2004-06-03 03:38:44 +00007static asn1p_expr_t *_referenced_argument(asn1p_ref_t *ref, asn1p_expr_t *ptype, asn1p_expr_t *actargs);
Lev Walkind541c252004-09-05 10:36:22 +00008static int _process_constraints(arg_t *arg, asn1p_constraint_t *ct, asn1p_expr_t *ptype, asn1p_expr_t *actargs);
Lev Walkinf15320b2004-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));
Lev Walkin6fec44d2004-08-22 03:10:23 +000029 ptype = asn1f_lookup_symbol(arg, expr->module, expr->reference);
Lev Walkinf15320b2004-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
61#define SUBSTITUTE(to, from) do { \
62 asn1p_expr_t tmp; \
63 tmp = *(to); \
64 *(to) = *(from); \
65 *(from) = tmp; \
66 (to)->next = tmp.next; \
67 memset(&((from)->next), 0, \
68 sizeof((from)->next)); \
69 asn1p_expr_free(from); \
70 } while(0)
71
72static int
73asn1f_parametrize(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype) {
74 asn1p_expr_t *nex;
75 void *p;
76 int ret;
77
78 /*
79 * The algorithm goes like that:
80 * 1. Replace the expression's type with parametrized type.
81 * 2. For every child in the parametrized type, import it
82 * as a child of the expression, replacing all occurences of
83 * symbols which are defined as parametrized type arguments
84 * with the actual values.
Lev Walkind541c252004-09-05 10:36:22 +000085 * 3. Don't forget to parametrize the subtype constraints.
Lev Walkinf15320b2004-06-03 03:38:44 +000086 */
87
Lev Walkin6fec44d2004-08-22 03:10:23 +000088 nex = asn1p_expr_clone(ptype, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +000089 if(nex == NULL) return -1;
90
91 /*
92 * Cleanup the new expression so there is no ptype-related
93 * stuff hanging around.
94 */
95 p = strdup(expr->Identifier);
96 if(p) {
97 free(nex->Identifier);
98 nex->Identifier = p;
99 } else {
100 asn1p_expr_free(nex);
101 return -1;
102 }
103 asn1p_paramlist_free(nex->params);
104 nex->params = NULL;
105 nex->meta_type = expr->meta_type;
106
107 ret = asn1f_param_process_recursive(arg, nex, ptype, expr);
108 if(ret != 0) {
109 asn1p_expr_free(nex);
110 return ret;
111 }
112
113 SUBSTITUTE(expr, nex);
114
115 return ret;
116}
117
118static int
119asn1f_param_process_recursive(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype, asn1p_expr_t *actargs) {
120 asn1p_expr_t *child;
121
122 TQ_FOR(child, &(expr->members), next) {
123 asn1p_expr_t *ra;
Lev Walkind541c252004-09-05 10:36:22 +0000124 asn1p_expr_t *ne; /* new expression (clone) */
125
126 if(asn1f_param_process_constraints(arg, child, ptype, actargs))
127 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000128
129 ra = _referenced_argument(child->reference, ptype, actargs);
Lev Walkind541c252004-09-05 10:36:22 +0000130 if(ra) {
131 DEBUG("Substituting parameter for %s %s at line %d",
132 child->Identifier,
133 asn1f_printable_reference(child->reference),
134 child->_lineno
135 );
136
137 assert(child->meta_type == AMT_TYPEREF);
138 assert(child->expr_type == A1TC_REFERENCE);
139
140 ne = asn1p_expr_clone(ra, 0);
141 if(ne == NULL) return -1;
142 assert(ne->Identifier == 0);
143 ne->Identifier = strdup(child->Identifier);
144 if(ne->Identifier == 0) {
145 asn1p_expr_free(ne);
146 return -1;
147 }
148 SUBSTITUTE(child, ne);
Lev Walkinf15320b2004-06-03 03:38:44 +0000149 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000150 }
151
152 return 0;
153}
154
Lev Walkind541c252004-09-05 10:36:22 +0000155/*
156 * Check that the given ref looks like an argument of a parametrized type.
157 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000158static asn1p_expr_t *
159_referenced_argument(asn1p_ref_t *ref, asn1p_expr_t *ptype, asn1p_expr_t *actargs) {
160 asn1p_expr_t *aa;
161 int i;
162
163 if(ref == NULL || ref->comp_count != 1)
164 return NULL;
165
166 aa = TQ_FIRST(&(actargs->members));
167 for(i = 0; i < ptype->params->params_count;
168 i++, aa = TQ_NEXT(aa, next)) {
169 if(strcmp(ref->components[0].name,
170 ptype->params->params[i].argument) == 0)
171 return aa;
172 }
173
174 return NULL;
175}
Lev Walkind541c252004-09-05 10:36:22 +0000176
177/*
178 * Search for parameters inside constraints.
179 */
180static int
181asn1f_param_process_constraints(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype, asn1p_expr_t *actargs) {
182 asn1p_constraint_t *cts;
183 int ret;
184
185 if(!expr->constraints) return 0;
186
187 cts = asn1p_constraint_clone(expr->constraints);
188 assert(cts);
189
190 ret = _process_constraints(arg, cts, ptype, actargs);
191 if(ret == 1) {
192 asn1p_constraint_free(expr->constraints);
193 expr->constraints = cts;
194 ret = 0;
195 } else {
196 asn1p_constraint_free(cts);
197 }
198
199 return ret;
200}
201
202static int
203_process_constraints(arg_t *arg, asn1p_constraint_t *ct, asn1p_expr_t *ptype, asn1p_expr_t *actargs) {
204 asn1p_value_t *values[3];
205 int rvalue = 0;
206 size_t i;
207
208 values[0] = ct->value;
209 values[1] = ct->range_start;
210 values[2] = ct->range_stop;
211
212 for(i = 0; i < sizeof(values)/sizeof(values[0]); i++) {
213 asn1p_value_t *v = values[i];
214 asn1p_expr_t *ra;
215 asn1p_ref_t *ref;
216 char *str;
217
218 if(!v || v->type != ATV_REFERENCED) continue;
219
220 ref = v->value.reference;
221 ra = _referenced_argument(ref, ptype, actargs);
222 if(!ra) continue;
223
224 DEBUG("_process_constraints(%s), ra=%s",
225 asn1f_printable_reference(ref), ra->Identifier);
226
227 str = strdup(ra->Identifier);
228 if(!str) return -1;
229
230 assert(ref->comp_count == 1);
231 ref = asn1p_ref_new(ref->_lineno);
232 if(!ref) { free(str); return -1; }
233
234 if(asn1p_ref_add_component(ref, str, 0)) {
235 free(str);
236 return -1;
237 }
238
239 asn1p_ref_free(v->value.reference);
240 v->value.reference = ref;
241 rvalue = 1;
242 }
243
244 /* Process the rest of constraints recursively */
245 for(i = 0; i < ct->el_count; i++) {
246 int ret = _process_constraints(arg, ct->elements[i],
247 ptype, actargs);
248 if(ret == -1)
249 rvalue = -1;
250 else if(ret == 1 && rvalue != -1)
251 rvalue = 1;
252 }
253
254 return rvalue;
255}
256