blob: a0560edb9ebeb349e86d2f03e482f33b2a97e6b5 [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) {
7 asn1p_module_t *val_mod;
8 asn1p_expr_t *val_type_expr;
9 asn1p_expr_t *value_expr;
10 asn1p_expr_t *type_expr;
11 int ret;
12
13 /* Make sure this IS a value assignment */
14 assert(expr->meta_type == AMT_VALUE);
15 assert(expr->value);
16
17 DEBUG("%s(=\"%s\", %x)", __func__,
18 asn1f_printable_value(expr->value), expr->expr_type);
19
20 /*
21 * 1. Find the terminal type for this assignment.
22 */
23 type_expr = asn1f_find_terminal_type(arg, expr, 0);
Lev Walkinb45e0672004-08-18 05:42:05 +000024 DEBUG("%s(): terminal type %p", __func__, type_expr);
Lev Walkinf15320b2004-06-03 03:38:44 +000025 if(type_expr == 0) {
26 DEBUG("\tTerminal type for %s not found", expr->Identifier);
27 return -1;
28 }
29
30 if(asn1f_look_value_in_type(arg, type_expr, expr) == -1)
31 return -1;
32
33 /*
34 * 2. Find the terminal value also.
35 */
36 value_expr = asn1f_find_terminal_value(arg, expr, &val_mod);
37 if(value_expr) {
38 DEBUG("\tTerminal value for %s->%s is %s at line %d",
39 expr->Identifier, asn1f_printable_value(expr->value),
40 value_expr->Identifier, value_expr->_lineno);
41 } else {
42 DEBUG("\tTerminal value for %s->%s not found",
43 expr->Identifier, asn1f_printable_value(expr->value));
44 return -1;
45 }
46
47 /*
48 * 3. Find the _type_ of a _terminal value_.
49 */
50 WITH_MODULE(val_mod,
51 val_type_expr = asn1f_find_terminal_type(arg, value_expr, 0));
52 if(val_type_expr) {
53 DEBUG("\tTerminal type of value %s->%s is %s at line %d",
54 expr->Identifier, asn1f_printable_value(expr->value),
55 val_type_expr->Identifier, val_type_expr->_lineno);
56 } else {
57 DEBUG("\tTerminal type of value %s->%s not found",
58 expr->Identifier, asn1f_printable_value(expr->value));
59 return -1;
60 }
61
62 /*
63 * 4. Check compatibility between the type of the current expression
64 * and the type of the discovered value.
65 */
66 ret = asn1f_check_type_compatibility(arg, type_expr, val_type_expr);
67 if(ret == -1) {
68 DEBUG("\tIncompatible type of %s at %d with %s at %d",
69 type_expr->Identifier, type_expr->_lineno,
70 val_type_expr->Identifier, val_type_expr->_lineno);
71 return -1;
72 }
73
74 if(asn1f_look_value_in_type(arg, val_type_expr, expr) == -1)
75 return -1;
76
77 /*
78 * 5. Copy value from the terminal value into the current expression.
79 */
80 ret = _asn1f_copy_value(arg, expr, value_expr);
81 if(ret == -1) {
82 DEBUG("\tValue %s cannot be copied from line %d to line %d",
83 asn1f_printable_value(value_expr->value),
84 value_expr->_lineno, expr->_lineno);
85 return -1;
86 }
87
88 DEBUG("\tFinal value for \"%s\" at line %d is %s",
89 expr->Identifier, expr->_lineno,
90 asn1f_printable_value(expr->value));
91
92 return 0;
93}
94
95static int
96_asn1f_copy_value(arg_t *arg, asn1p_expr_t *to, asn1p_expr_t *from) {
97 asn1p_value_t *v;
98
99 v = asn1p_value_clone(from->value);
100 if(v) {
101 asn1p_value_free(to->value);
102 to->value = v;
103 DEBUG("Copied value %s from \"%s\" on line %d "
104 "to \"%s\" on line %d",
105 asn1f_printable_value(v),
106 from->Identifier,
107 from->_lineno,
108 to->Identifier,
109 to->_lineno
110 );
111 return 0;
112 } else {
113 return -1;
114 }
115}
116
117int
118asn1f_look_value_in_type(arg_t *arg,
119 asn1p_expr_t *type_expr,
120 asn1p_expr_t *value_expr) {
121 asn1p_expr_t *child_expr;
122 char *identifier;
123
124 if(value_expr->value->type != ATV_REFERENCED
125 || value_expr->value->value.reference->comp_count != 1)
126 return 0;
127 if(type_expr->expr_type != ASN_BASIC_INTEGER
128 && type_expr->expr_type != ASN_BASIC_ENUMERATED)
129 return 0;
130
131 DEBUG("%s(for %s in %s %x) for line %d", __func__,
132 asn1f_printable_value(value_expr->value),
133 type_expr->Identifier,
134 type_expr->expr_type,
135 value_expr->_lineno);
136
137 /*
138 * Look into the definitions of the type itself:
139 * Type1 ::= INTEGER { a(1), b(2) }
140 * value Type1 = b -- will assign 2
141 */
142 identifier = value_expr->value->value.reference->components[0].name;
143
144 child_expr = asn1f_lookup_child(type_expr, identifier);
145 DEBUG("\tLooking into a type %s at line %d for %s at line %d: %s",
146 type_expr->Identifier, type_expr->_lineno,
147 identifier, value_expr->_lineno,
148 child_expr
149 ? asn1f_printable_value(child_expr->value)
150 : "<not found>"
151 );
152
153 if(child_expr && child_expr->value) {
154 if(_asn1f_copy_value(arg, value_expr, child_expr))
155 return -1;
156 /* Fall through */
157 }
158
159 return 0;
160}