blob: 18d868665985e5dd3d3c75a10cb3d0e245d2caba [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
2
3static int _asn1f_copy_value(arg_t *arg, asn1p_expr_t *to,asn1p_expr_t *from);
4
5int
Lev Walkinfb617702005-03-10 16:15:57 +00006asn1f_value_resolve(arg_t *arg, asn1p_expr_t *expr, const enum asn1p_constraint_type_e *opt_constr_type) {
Lev Walkinf15320b2004-06-03 03:38:44 +00007 asn1p_expr_t *val_type_expr;
8 asn1p_expr_t *value_expr;
9 asn1p_expr_t *type_expr;
10 int ret;
11
12 /* Make sure this IS a value assignment */
13 assert(expr->meta_type == AMT_VALUE);
14 assert(expr->value);
15
Lev Walkina13e73f2004-09-15 11:47:02 +000016 if(expr->value->type != ATV_REFERENCED)
17 return 0;
18
Lev Walkin9288d1c2005-03-10 11:27:13 +000019 DEBUG("(=\"%s\", %x%s%s)",
20 asn1f_printable_value(expr->value), expr->expr_type,
21 opt_constr_type ? ", " : "",
22 opt_constr_type
23 ? asn1p_constraint_type2str(*opt_constr_type) : ""
24 );
Lev Walkinf15320b2004-06-03 03:38:44 +000025
26 /*
27 * 1. Find the terminal type for this assignment.
28 */
Lev Walkin6fec44d2004-08-22 03:10:23 +000029 type_expr = asn1f_find_terminal_type(arg, expr);
Lev Walkin03850182005-03-10 10:02:50 +000030 DEBUG("terminal type %p", type_expr);
Lev Walkinf15320b2004-06-03 03:38:44 +000031 if(type_expr == 0) {
Lev Walkincae1cfd2004-09-06 08:06:37 +000032 FATAL("Terminal type for is %s not found", expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +000033 return -1;
34 }
35
Lev Walkina13e73f2004-09-15 11:47:02 +000036 if(asn1f_look_value_in_type(arg, type_expr, expr) == -1) {
37 FATAL("Value not found in type for %s", expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +000038 return -1;
Lev Walkina13e73f2004-09-15 11:47:02 +000039 }
Lev Walkinf15320b2004-06-03 03:38:44 +000040
41 /*
42 * 2. Find the terminal value also.
43 */
Lev Walkin6fec44d2004-08-22 03:10:23 +000044 value_expr = asn1f_find_terminal_value(arg, expr);
Lev Walkinf15320b2004-06-03 03:38:44 +000045 if(value_expr) {
Lev Walkin9288d1c2005-03-10 11:27:13 +000046 DEBUG("Terminal value for %s->%s is %s at line %d",
Lev Walkinf15320b2004-06-03 03:38:44 +000047 expr->Identifier, asn1f_printable_value(expr->value),
48 value_expr->Identifier, value_expr->_lineno);
49 } else {
Lev Walkina13e73f2004-09-15 11:47:02 +000050 FATAL("Terminal value for %s->%s not found",
Lev Walkinf15320b2004-06-03 03:38:44 +000051 expr->Identifier, asn1f_printable_value(expr->value));
52 return -1;
53 }
54
55 /*
56 * 3. Find the _type_ of a _terminal value_.
57 */
Lev Walkin6fec44d2004-08-22 03:10:23 +000058 WITH_MODULE(value_expr->module,
59 val_type_expr = asn1f_find_terminal_type(arg, value_expr));
Lev Walkinf15320b2004-06-03 03:38:44 +000060 if(val_type_expr) {
Lev Walkin9288d1c2005-03-10 11:27:13 +000061 DEBUG("Terminal type of value %s->%s is %s at line %d",
Lev Walkinf15320b2004-06-03 03:38:44 +000062 expr->Identifier, asn1f_printable_value(expr->value),
63 val_type_expr->Identifier, val_type_expr->_lineno);
64 } else {
Lev Walkin9288d1c2005-03-10 11:27:13 +000065 FATAL("Terminal type of value %s->%s not found",
Lev Walkinf15320b2004-06-03 03:38:44 +000066 expr->Identifier, asn1f_printable_value(expr->value));
67 return -1;
68 }
69
70 /*
71 * 4. Check compatibility between the type of the current expression
72 * and the type of the discovered value.
73 */
Lev Walkin9288d1c2005-03-10 11:27:13 +000074 if(opt_constr_type)
75 ret = asn1constraint_compatible(val_type_expr->expr_type,
76 *opt_constr_type);
77 else
78 ret = asn1f_check_type_compatibility(arg,
79 type_expr, val_type_expr);
Lev Walkinf15320b2004-06-03 03:38:44 +000080 if(ret == -1) {
Lev Walkincae1cfd2004-09-06 08:06:37 +000081 switch(type_expr->expr_type) {
Lev Walkina7247f92005-03-20 11:07:34 +000082 default:
83 if(!(type_expr->expr_type & ASN_STRING_MASK))
84 break;
85 /* Compatibility rules are not defined */
86 /* Fall through */
Lev Walkincae1cfd2004-09-06 08:06:37 +000087 case ASN_BASIC_INTEGER:
88 case ASN_BASIC_ENUMERATED:
Lev Walkin9288d1c2005-03-10 11:27:13 +000089 FATAL("Incompatible type of \"%s\" (%s) at line %d "
90 "with \"%s\" (%s) at line %d",
91 type_expr->Identifier,
92 ASN_EXPR_TYPE2STR(type_expr->expr_type),
93 type_expr->_lineno,
94 val_type_expr->Identifier,
95 ASN_EXPR_TYPE2STR(val_type_expr->expr_type),
96 val_type_expr->_lineno);
Lev Walkincae1cfd2004-09-06 08:06:37 +000097 return -1;
98 case ASN_BASIC_OBJECT_IDENTIFIER:
99 /*
100 * Ignore this for now.
101 * We can't deal with OIDs inheritance properly yet.
102 */
103 return 0;
Lev Walkincae1cfd2004-09-06 08:06:37 +0000104 }
Lev Walkina7247f92005-03-20 11:07:34 +0000105 WARNING("Possibly incompatible type of \"%s\" (%s) at line %d "
Lev Walkin9288d1c2005-03-10 11:27:13 +0000106 "with \"%s\" (%s) at line %d",
107 type_expr->Identifier,
108 ASN_EXPR_TYPE2STR(type_expr->expr_type),
109 type_expr->_lineno,
110 val_type_expr->Identifier,
111 ASN_EXPR_TYPE2STR(val_type_expr->expr_type),
112 val_type_expr->_lineno);
Lev Walkincae1cfd2004-09-06 08:06:37 +0000113 return 1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000114 }
115
116 if(asn1f_look_value_in_type(arg, val_type_expr, expr) == -1)
117 return -1;
118
119 /*
120 * 5. Copy value from the terminal value into the current expression.
121 */
122 ret = _asn1f_copy_value(arg, expr, value_expr);
123 if(ret == -1) {
Lev Walkina13e73f2004-09-15 11:47:02 +0000124 FATAL("Value %s cannot be copied from line %d to line %d",
Lev Walkinf15320b2004-06-03 03:38:44 +0000125 asn1f_printable_value(value_expr->value),
126 value_expr->_lineno, expr->_lineno);
127 return -1;
128 }
129
Lev Walkin9288d1c2005-03-10 11:27:13 +0000130 DEBUG("Final value for \"%s\" at line %d is %s",
Lev Walkinf15320b2004-06-03 03:38:44 +0000131 expr->Identifier, expr->_lineno,
132 asn1f_printable_value(expr->value));
133
134 return 0;
135}
136
137static int
138_asn1f_copy_value(arg_t *arg, asn1p_expr_t *to, asn1p_expr_t *from) {
139 asn1p_value_t *v;
140
141 v = asn1p_value_clone(from->value);
142 if(v) {
143 asn1p_value_free(to->value);
144 to->value = v;
145 DEBUG("Copied value %s from \"%s\" on line %d "
146 "to \"%s\" on line %d",
147 asn1f_printable_value(v),
148 from->Identifier,
149 from->_lineno,
150 to->Identifier,
151 to->_lineno
152 );
153 return 0;
154 } else {
155 return -1;
156 }
157}
158
159int
160asn1f_look_value_in_type(arg_t *arg,
161 asn1p_expr_t *type_expr,
162 asn1p_expr_t *value_expr) {
163 asn1p_expr_t *child_expr;
164 char *identifier;
165
166 if(value_expr->value->type != ATV_REFERENCED
167 || value_expr->value->value.reference->comp_count != 1)
168 return 0;
169 if(type_expr->expr_type != ASN_BASIC_INTEGER
170 && type_expr->expr_type != ASN_BASIC_ENUMERATED)
171 return 0;
172
Lev Walkin03850182005-03-10 10:02:50 +0000173 DEBUG("(for %s in %s %x) for line %d",
Lev Walkinf15320b2004-06-03 03:38:44 +0000174 asn1f_printable_value(value_expr->value),
175 type_expr->Identifier,
176 type_expr->expr_type,
177 value_expr->_lineno);
178
179 /*
180 * Look into the definitions of the type itself:
181 * Type1 ::= INTEGER { a(1), b(2) }
182 * value Type1 = b -- will assign 2
183 */
184 identifier = value_expr->value->value.reference->components[0].name;
185
186 child_expr = asn1f_lookup_child(type_expr, identifier);
Lev Walkin9288d1c2005-03-10 11:27:13 +0000187 DEBUG("Looking into a type %s at line %d for %s at line %d: %s",
Lev Walkinf15320b2004-06-03 03:38:44 +0000188 type_expr->Identifier, type_expr->_lineno,
189 identifier, value_expr->_lineno,
190 child_expr
191 ? asn1f_printable_value(child_expr->value)
192 : "<not found>"
193 );
194
195 if(child_expr && child_expr->value) {
196 if(_asn1f_copy_value(arg, value_expr, child_expr))
197 return -1;
198 /* Fall through */
199 }
200
201 return 0;
202}