blob: ab7e9a359a059fb7813cdbf6f08799a3a1a40bdd [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
6asn1f_value_resolve(arg_t *arg, asn1p_expr_t *expr) {
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 Walkinf15320b2004-06-03 03:38:44 +000019 DEBUG("%s(=\"%s\", %x)", __func__,
20 asn1f_printable_value(expr->value), expr->expr_type);
21
22 /*
23 * 1. Find the terminal type for this assignment.
24 */
Lev Walkin6fec44d2004-08-22 03:10:23 +000025 type_expr = asn1f_find_terminal_type(arg, expr);
Lev Walkinb45e0672004-08-18 05:42:05 +000026 DEBUG("%s(): terminal type %p", __func__, type_expr);
Lev Walkinf15320b2004-06-03 03:38:44 +000027 if(type_expr == 0) {
Lev Walkincae1cfd2004-09-06 08:06:37 +000028 FATAL("Terminal type for is %s not found", expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +000029 return -1;
30 }
31
Lev Walkina13e73f2004-09-15 11:47:02 +000032 if(asn1f_look_value_in_type(arg, type_expr, expr) == -1) {
33 FATAL("Value not found in type for %s", expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +000034 return -1;
Lev Walkina13e73f2004-09-15 11:47:02 +000035 }
Lev Walkinf15320b2004-06-03 03:38:44 +000036
37 /*
38 * 2. Find the terminal value also.
39 */
Lev Walkin6fec44d2004-08-22 03:10:23 +000040 value_expr = asn1f_find_terminal_value(arg, expr);
Lev Walkinf15320b2004-06-03 03:38:44 +000041 if(value_expr) {
42 DEBUG("\tTerminal value for %s->%s is %s at line %d",
43 expr->Identifier, asn1f_printable_value(expr->value),
44 value_expr->Identifier, value_expr->_lineno);
45 } else {
Lev Walkina13e73f2004-09-15 11:47:02 +000046 FATAL("Terminal value for %s->%s not found",
Lev Walkinf15320b2004-06-03 03:38:44 +000047 expr->Identifier, asn1f_printable_value(expr->value));
48 return -1;
49 }
50
51 /*
52 * 3. Find the _type_ of a _terminal value_.
53 */
Lev Walkin6fec44d2004-08-22 03:10:23 +000054 WITH_MODULE(value_expr->module,
55 val_type_expr = asn1f_find_terminal_type(arg, value_expr));
Lev Walkinf15320b2004-06-03 03:38:44 +000056 if(val_type_expr) {
57 DEBUG("\tTerminal type of value %s->%s is %s at line %d",
58 expr->Identifier, asn1f_printable_value(expr->value),
59 val_type_expr->Identifier, val_type_expr->_lineno);
60 } else {
Lev Walkina13e73f2004-09-15 11:47:02 +000061 FATAL("\tTerminal type of value %s->%s not found",
Lev Walkinf15320b2004-06-03 03:38:44 +000062 expr->Identifier, asn1f_printable_value(expr->value));
63 return -1;
64 }
65
66 /*
67 * 4. Check compatibility between the type of the current expression
68 * and the type of the discovered value.
69 */
70 ret = asn1f_check_type_compatibility(arg, type_expr, val_type_expr);
71 if(ret == -1) {
Lev Walkincae1cfd2004-09-06 08:06:37 +000072 switch(type_expr->expr_type) {
73 case ASN_BASIC_INTEGER:
74 case ASN_BASIC_ENUMERATED:
75 FATAL("Incompatible type of %s at %d with %s at %d",
Lev Walkinf15320b2004-06-03 03:38:44 +000076 type_expr->Identifier, type_expr->_lineno,
77 val_type_expr->Identifier, val_type_expr->_lineno);
Lev Walkincae1cfd2004-09-06 08:06:37 +000078 return -1;
79 case ASN_BASIC_OBJECT_IDENTIFIER:
80 /*
81 * Ignore this for now.
82 * We can't deal with OIDs inheritance properly yet.
83 */
84 return 0;
85 default:
86 break;
87 }
88 WARNING("\tIncompatible type of %s at %d with %s at %d",
89 type_expr->Identifier, type_expr->_lineno,
90 val_type_expr->Identifier, val_type_expr->_lineno);
91 return 1;
Lev Walkinf15320b2004-06-03 03:38:44 +000092 }
93
94 if(asn1f_look_value_in_type(arg, val_type_expr, expr) == -1)
95 return -1;
96
97 /*
98 * 5. Copy value from the terminal value into the current expression.
99 */
100 ret = _asn1f_copy_value(arg, expr, value_expr);
101 if(ret == -1) {
Lev Walkina13e73f2004-09-15 11:47:02 +0000102 FATAL("Value %s cannot be copied from line %d to line %d",
Lev Walkinf15320b2004-06-03 03:38:44 +0000103 asn1f_printable_value(value_expr->value),
104 value_expr->_lineno, expr->_lineno);
105 return -1;
106 }
107
108 DEBUG("\tFinal value for \"%s\" at line %d is %s",
109 expr->Identifier, expr->_lineno,
110 asn1f_printable_value(expr->value));
111
112 return 0;
113}
114
115static int
116_asn1f_copy_value(arg_t *arg, asn1p_expr_t *to, asn1p_expr_t *from) {
117 asn1p_value_t *v;
118
119 v = asn1p_value_clone(from->value);
120 if(v) {
121 asn1p_value_free(to->value);
122 to->value = v;
123 DEBUG("Copied value %s from \"%s\" on line %d "
124 "to \"%s\" on line %d",
125 asn1f_printable_value(v),
126 from->Identifier,
127 from->_lineno,
128 to->Identifier,
129 to->_lineno
130 );
131 return 0;
132 } else {
133 return -1;
134 }
135}
136
137int
138asn1f_look_value_in_type(arg_t *arg,
139 asn1p_expr_t *type_expr,
140 asn1p_expr_t *value_expr) {
141 asn1p_expr_t *child_expr;
142 char *identifier;
143
144 if(value_expr->value->type != ATV_REFERENCED
145 || value_expr->value->value.reference->comp_count != 1)
146 return 0;
147 if(type_expr->expr_type != ASN_BASIC_INTEGER
148 && type_expr->expr_type != ASN_BASIC_ENUMERATED)
149 return 0;
150
151 DEBUG("%s(for %s in %s %x) for line %d", __func__,
152 asn1f_printable_value(value_expr->value),
153 type_expr->Identifier,
154 type_expr->expr_type,
155 value_expr->_lineno);
156
157 /*
158 * Look into the definitions of the type itself:
159 * Type1 ::= INTEGER { a(1), b(2) }
160 * value Type1 = b -- will assign 2
161 */
162 identifier = value_expr->value->value.reference->components[0].name;
163
164 child_expr = asn1f_lookup_child(type_expr, identifier);
165 DEBUG("\tLooking into a type %s at line %d for %s at line %d: %s",
166 type_expr->Identifier, type_expr->_lineno,
167 identifier, value_expr->_lineno,
168 child_expr
169 ? asn1f_printable_value(child_expr->value)
170 : "<not found>"
171 );
172
173 if(child_expr && child_expr->value) {
174 if(_asn1f_copy_value(arg, value_expr, child_expr))
175 return -1;
176 /* Fall through */
177 }
178
179 return 0;
180}