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