blob: 0c838cc59ec2df2fb3b0a06883a01f684e5587d5 [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);
5static asn1p_expr_t *_referenced_argument(asn1p_ref_t *ref, asn1p_expr_t *ptype, asn1p_expr_t *actargs);
6
7int
8asn1f_fix_parametrized_assignment(arg_t *arg) {
9 asn1p_expr_t *expr = arg->expr;
10 asn1p_expr_t *ptype;
11
12 assert(expr->expr_type == A1TC_PARAMETRIZED);
13 assert(expr->reference);
14
15 DEBUG("%s(\"%s\" ::= \"%s\" { %s }) for line %d",
16 __func__, expr->Identifier,
17 asn1f_printable_reference(expr->reference),
18 asn1f_printable_value(expr->value),
19 expr->_lineno);
20
21 /*
22 * Find the corresponding parametrized type definition.
23 */
24 DEBUG("Looking for parametrized type definition \"%s\"",
25 asn1f_printable_reference(expr->reference));
26 ptype = asn1f_lookup_symbol(arg, expr->reference, 0);
27 if(ptype == NULL) {
28 DEBUG("%s: missing parametrized type declaration",
29 asn1f_printable_reference(expr->reference));
30 return -1;
31 }
32
33 /*
34 * Check that the number of arguments which are expected by
35 * the parametrized type declaration is consistent with the
36 * number of arguments supplied by the parametrized assignment.
37 */
38 if(asn1f_count_children(expr) != ptype->params->params_count) {
39 FATAL("Number of actual arguments %d in %s at line %d "
40 "is not equal to number of expected arguments "
41 "%d in %s at line %d",
42 asn1f_count_children(expr),
43 asn1f_printable_reference(expr->reference),
44 expr->_lineno,
45 ptype->params->params_count,
46 ptype->Identifier,
47 ptype->_lineno
48 );
49 return -1;
50 }
51
52 /*
53 * Perform an expansion of a parametrized assignment.
54 */
55 return asn1f_parametrize(arg, expr, ptype);
56}
57
58#define SUBSTITUTE(to, from) do { \
59 asn1p_expr_t tmp; \
60 tmp = *(to); \
61 *(to) = *(from); \
62 *(from) = tmp; \
63 (to)->next = tmp.next; \
64 memset(&((from)->next), 0, \
65 sizeof((from)->next)); \
66 asn1p_expr_free(from); \
67 } while(0)
68
69static int
70asn1f_parametrize(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype) {
71 asn1p_expr_t *nex;
72 void *p;
73 int ret;
74
75 /*
76 * The algorithm goes like that:
77 * 1. Replace the expression's type with parametrized type.
78 * 2. For every child in the parametrized type, import it
79 * as a child of the expression, replacing all occurences of
80 * symbols which are defined as parametrized type arguments
81 * with the actual values.
82 */
83
84 nex = asn1p_expr_clone(ptype);
85 if(nex == NULL) return -1;
86
87 /*
88 * Cleanup the new expression so there is no ptype-related
89 * stuff hanging around.
90 */
91 p = strdup(expr->Identifier);
92 if(p) {
93 free(nex->Identifier);
94 nex->Identifier = p;
95 } else {
96 asn1p_expr_free(nex);
97 return -1;
98 }
99 asn1p_paramlist_free(nex->params);
100 nex->params = NULL;
101 nex->meta_type = expr->meta_type;
102
103 ret = asn1f_param_process_recursive(arg, nex, ptype, expr);
104 if(ret != 0) {
105 asn1p_expr_free(nex);
106 return ret;
107 }
108
109 SUBSTITUTE(expr, nex);
110
111 return ret;
112}
113
114static int
115asn1f_param_process_recursive(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype, asn1p_expr_t *actargs) {
116 asn1p_expr_t *child;
117
118 TQ_FOR(child, &(expr->members), next) {
119 asn1p_expr_t *ra;
120 asn1p_expr_t *ne;
121
122 ra = _referenced_argument(child->reference, ptype, actargs);
123 if(ra == NULL) continue;
124
125 DEBUG("Substituting parameter for %s %s at line %d",
126 child->Identifier,
127 asn1f_printable_reference(child->reference),
128 child->_lineno
129 );
130
131 assert(child->meta_type == AMT_TYPEREF);
132 assert(child->expr_type == A1TC_REFERENCE);
133
134 ne = asn1p_expr_clone(ra);
135 if(ne == NULL) return -1;
136 assert(ne->Identifier == 0);
137 ne->Identifier = strdup(child->Identifier);
138 if(ne->Identifier == 0) {
139 asn1p_expr_free(ne);
140 return -1;
141 }
142 SUBSTITUTE(child, ne);
143 }
144
145 return 0;
146}
147
148static asn1p_expr_t *
149_referenced_argument(asn1p_ref_t *ref, asn1p_expr_t *ptype, asn1p_expr_t *actargs) {
150 asn1p_expr_t *aa;
151 int i;
152
153 if(ref == NULL || ref->comp_count != 1)
154 return NULL;
155
156 aa = TQ_FIRST(&(actargs->members));
157 for(i = 0; i < ptype->params->params_count;
158 i++, aa = TQ_NEXT(aa, next)) {
159 if(strcmp(ref->components[0].name,
160 ptype->params->params[i].argument) == 0)
161 return aa;
162 }
163
164 return NULL;
165}