NativeEnumerated.c vars NULL init and check
[com/asn1c.git] / libasn1fix / asn1fix_value.c
1 #include "asn1fix_internal.h"
2
3 static int _asn1f_copy_value(arg_t *arg, asn1p_expr_t *to,asn1p_expr_t *from);
4
5 int
6 asn1f_value_resolve(arg_t *arg, asn1p_expr_t *expr, const enum asn1p_constraint_type_e *opt_constr_type) {
7         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
16         if(expr->value->type != ATV_REFERENCED)
17                 return 0;
18
19         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         );
25
26         /*
27          * 1. Find the terminal type for this assignment.
28          */
29         type_expr = asn1f_find_terminal_type(arg, expr);
30         if(type_expr == 0) {
31                 if(errno == EEXIST) {
32                         DEBUG("External type for %s at line %d",
33                                 expr->Identifier, expr->_lineno);
34                         return 0;
35                 } else {
36                         FATAL("Terminal type for %s at line %d not found",
37                                 expr->Identifier, expr->_lineno);
38                         return -1;
39                 }
40         }
41
42         if(asn1f_look_value_in_type(arg, type_expr, expr) == -1) {
43                 FATAL("Value not found in type for %s at line %d",
44                         expr->Identifier, expr->_lineno);
45                 return -1;
46         }
47
48         /*
49          * 2. Find the terminal value also.
50          */
51         value_expr = asn1f_find_terminal_value(arg, expr);
52         if(value_expr) {
53                 DEBUG("Terminal value for %s->%s is %s at line %d",
54                         expr->Identifier, asn1f_printable_value(expr->value),
55                         value_expr->Identifier, value_expr->_lineno);
56         } else {
57                 FATAL("Terminal value for %s->%s not found",
58                         expr->Identifier, asn1f_printable_value(expr->value));
59                 return -1;
60         }
61
62         /*
63          * 3. Find the _type_ of a _terminal value_.
64          */
65         WITH_MODULE(value_expr->module,
66                 val_type_expr = asn1f_find_terminal_type(arg, value_expr));
67         if(val_type_expr) {
68                 DEBUG("Terminal type of value %s->%s is %s at line %d",
69                         expr->Identifier, asn1f_printable_value(expr->value),
70                         val_type_expr->Identifier, val_type_expr->_lineno);
71         } else {
72                 FATAL("Terminal type of value %s->%s not found",
73                         expr->Identifier, asn1f_printable_value(expr->value));
74                 return -1;
75         }
76
77         /*
78          * 4. Check compatibility between the type of the current expression
79          * and the type of the discovered value.
80          */
81         if(opt_constr_type)
82                 ret = asn1constraint_compatible(val_type_expr->expr_type,
83                         *opt_constr_type, 0 /* must not matter here */);
84         else
85                 ret = asn1f_check_type_compatibility(arg,
86                         type_expr, val_type_expr);
87         if(ret == -1) {
88                 switch(type_expr->expr_type) {
89                 default:
90                         if(!(type_expr->expr_type & ASN_STRING_MASK))
91                                 break;
92                         /* Compatibility rules are not defined */
93                         /* Fall through */
94                 case ASN_BASIC_INTEGER:
95                 case ASN_BASIC_ENUMERATED:
96                         FATAL("Incompatible type of \"%s\" (%s) at line %d "
97                         "with \"%s\" (%s) at line %d",
98                         type_expr->Identifier,
99                                 ASN_EXPR_TYPE2STR(type_expr->expr_type),
100                                 type_expr->_lineno,
101                         val_type_expr->Identifier,
102                                 ASN_EXPR_TYPE2STR(val_type_expr->expr_type),
103                                 val_type_expr->_lineno);
104                         return -1;
105                 case ASN_BASIC_OBJECT_IDENTIFIER:
106                         /*
107                          * Ignore this for now.
108                          * We can't deal with OIDs inheritance properly yet.
109                          */
110                         return 0;
111                 }
112                 WARNING("Possibly incompatible type of \"%s\" (%s) at line %d "
113                         "with \"%s\" (%s) at line %d",
114                         type_expr->Identifier,
115                                 ASN_EXPR_TYPE2STR(type_expr->expr_type),
116                                 type_expr->_lineno,
117                         val_type_expr->Identifier,
118                                 ASN_EXPR_TYPE2STR(val_type_expr->expr_type),
119                                 val_type_expr->_lineno);
120                 return 1;
121         }
122
123         if(asn1f_look_value_in_type(arg, val_type_expr, expr) == -1)
124                 return -1;
125
126         /*
127          * 5. Copy value from the terminal value into the current expression.
128          */
129         ret = _asn1f_copy_value(arg, expr, value_expr);
130         if(ret == -1) {
131                 FATAL("Value %s cannot be copied from line %d to line %d",
132                         asn1f_printable_value(value_expr->value),
133                         value_expr->_lineno, expr->_lineno);
134                 return -1;
135         }
136
137         DEBUG("Final value for \"%s\" at line %d is %s",
138                 expr->Identifier, expr->_lineno,
139                 asn1f_printable_value(expr->value));
140
141         return 0;
142 }
143
144 static int
145 _asn1f_copy_value(arg_t *arg, asn1p_expr_t *to, asn1p_expr_t *from) {
146         asn1p_value_t *v;
147
148         v = asn1p_value_clone(from->value);
149         if(v) {
150                 asn1p_value_free(to->value);
151                 to->value = v;
152                 DEBUG("Copied value %s from \"%s\" on line %d "
153                         "to \"%s\" on line %d",
154                         asn1f_printable_value(v),
155                         from->Identifier,
156                         from->_lineno,
157                         to->Identifier,
158                         to->_lineno
159                 );
160                 return 0;
161         } else {
162                 return -1;
163         }
164 }
165
166 int
167 asn1f_look_value_in_type(arg_t *arg,
168                 asn1p_expr_t *type_expr,
169                 asn1p_expr_t *value_expr) {
170         asn1p_expr_t *child_expr;
171         char *identifier;
172
173         if(value_expr->value->type != ATV_REFERENCED
174         || value_expr->value->value.reference->comp_count != 1)
175                 return 0;
176         if(type_expr->expr_type != ASN_BASIC_INTEGER
177         && type_expr->expr_type != ASN_BASIC_ENUMERATED)
178                 return 0;
179
180         DEBUG("(for %s in %s %x) for line %d",
181                 asn1f_printable_value(value_expr->value),
182                 type_expr->Identifier,
183                 type_expr->expr_type,
184                 value_expr->_lineno);
185
186         /*
187          * Look into the definitions of the type itself:
188          * Type1 ::= INTEGER { a(1), b(2) }
189          * value Type1 = b      -- will assign 2
190          */
191         identifier = value_expr->value->value.reference->components[0].name;
192
193         child_expr = asn1f_lookup_child(type_expr, identifier);
194         DEBUG("Looking into a type %s at line %d for %s at line %d: %s",
195                 type_expr->Identifier, type_expr->_lineno,
196                 identifier, value_expr->_lineno,
197                 child_expr
198                         ? asn1f_printable_value(child_expr->value)
199                         : "<not found>"
200                 );
201
202         if(child_expr) {
203                 /* Maybe hasn't been fixed yet. */
204                 if (!child_expr->value) {
205                         asn1p_expr_t *saved_expr = arg->expr;
206                         arg->expr = type_expr;
207                         switch (type_expr->expr_type) {
208                         case ASN_BASIC_INTEGER:
209                                 asn1f_fix_integer(arg);
210                                 break;
211                         case ASN_BASIC_ENUMERATED:
212                                 asn1f_fix_enum(arg);
213                                 break;
214                         default:
215                                 WARNING("Unexpected type %s for %s",
216                                                 type_expr->expr_type,
217                                                 type_expr->Identifier);
218                                 return -1;
219                         }
220                         arg->expr = saved_expr;
221                 }
222                 if(child_expr->value && _asn1f_copy_value(arg,
223                                 value_expr, child_expr))
224                         return -1;
225                 /* Fall through */
226         }
227
228         return 0;
229 }