| #include "asn1fix_internal.h" |
| |
| static int _asn1f_copy_value(arg_t *arg, asn1p_expr_t *to,asn1p_expr_t *from); |
| |
| int |
| asn1f_value_resolve(arg_t *arg, asn1p_expr_t *expr) { |
| asn1p_expr_t *val_type_expr; |
| asn1p_expr_t *value_expr; |
| asn1p_expr_t *type_expr; |
| int ret; |
| |
| /* Make sure this IS a value assignment */ |
| assert(expr->meta_type == AMT_VALUE); |
| assert(expr->value); |
| |
| if(expr->value->type != ATV_REFERENCED) |
| return 0; |
| |
| DEBUG("%s(=\"%s\", %x)", __func__, |
| asn1f_printable_value(expr->value), expr->expr_type); |
| |
| /* |
| * 1. Find the terminal type for this assignment. |
| */ |
| type_expr = asn1f_find_terminal_type(arg, expr); |
| DEBUG("%s(): terminal type %p", __func__, type_expr); |
| if(type_expr == 0) { |
| FATAL("Terminal type for is %s not found", expr->Identifier); |
| return -1; |
| } |
| |
| if(asn1f_look_value_in_type(arg, type_expr, expr) == -1) { |
| FATAL("Value not found in type for %s", expr->Identifier); |
| return -1; |
| } |
| |
| /* |
| * 2. Find the terminal value also. |
| */ |
| value_expr = asn1f_find_terminal_value(arg, expr); |
| if(value_expr) { |
| DEBUG("\tTerminal value for %s->%s is %s at line %d", |
| expr->Identifier, asn1f_printable_value(expr->value), |
| value_expr->Identifier, value_expr->_lineno); |
| } else { |
| FATAL("Terminal value for %s->%s not found", |
| expr->Identifier, asn1f_printable_value(expr->value)); |
| return -1; |
| } |
| |
| /* |
| * 3. Find the _type_ of a _terminal value_. |
| */ |
| WITH_MODULE(value_expr->module, |
| val_type_expr = asn1f_find_terminal_type(arg, value_expr)); |
| if(val_type_expr) { |
| DEBUG("\tTerminal type of value %s->%s is %s at line %d", |
| expr->Identifier, asn1f_printable_value(expr->value), |
| val_type_expr->Identifier, val_type_expr->_lineno); |
| } else { |
| FATAL("\tTerminal type of value %s->%s not found", |
| expr->Identifier, asn1f_printable_value(expr->value)); |
| return -1; |
| } |
| |
| /* |
| * 4. Check compatibility between the type of the current expression |
| * and the type of the discovered value. |
| */ |
| ret = asn1f_check_type_compatibility(arg, type_expr, val_type_expr); |
| if(ret == -1) { |
| switch(type_expr->expr_type) { |
| case ASN_BASIC_INTEGER: |
| case ASN_BASIC_ENUMERATED: |
| FATAL("Incompatible type of %s at %d with %s at %d", |
| type_expr->Identifier, type_expr->_lineno, |
| val_type_expr->Identifier, val_type_expr->_lineno); |
| return -1; |
| case ASN_BASIC_OBJECT_IDENTIFIER: |
| /* |
| * Ignore this for now. |
| * We can't deal with OIDs inheritance properly yet. |
| */ |
| return 0; |
| default: |
| break; |
| } |
| WARNING("\tIncompatible type of %s at %d with %s at %d", |
| type_expr->Identifier, type_expr->_lineno, |
| val_type_expr->Identifier, val_type_expr->_lineno); |
| return 1; |
| } |
| |
| if(asn1f_look_value_in_type(arg, val_type_expr, expr) == -1) |
| return -1; |
| |
| /* |
| * 5. Copy value from the terminal value into the current expression. |
| */ |
| ret = _asn1f_copy_value(arg, expr, value_expr); |
| if(ret == -1) { |
| FATAL("Value %s cannot be copied from line %d to line %d", |
| asn1f_printable_value(value_expr->value), |
| value_expr->_lineno, expr->_lineno); |
| return -1; |
| } |
| |
| DEBUG("\tFinal value for \"%s\" at line %d is %s", |
| expr->Identifier, expr->_lineno, |
| asn1f_printable_value(expr->value)); |
| |
| return 0; |
| } |
| |
| static int |
| _asn1f_copy_value(arg_t *arg, asn1p_expr_t *to, asn1p_expr_t *from) { |
| asn1p_value_t *v; |
| |
| v = asn1p_value_clone(from->value); |
| if(v) { |
| asn1p_value_free(to->value); |
| to->value = v; |
| DEBUG("Copied value %s from \"%s\" on line %d " |
| "to \"%s\" on line %d", |
| asn1f_printable_value(v), |
| from->Identifier, |
| from->_lineno, |
| to->Identifier, |
| to->_lineno |
| ); |
| return 0; |
| } else { |
| return -1; |
| } |
| } |
| |
| int |
| asn1f_look_value_in_type(arg_t *arg, |
| asn1p_expr_t *type_expr, |
| asn1p_expr_t *value_expr) { |
| asn1p_expr_t *child_expr; |
| char *identifier; |
| |
| if(value_expr->value->type != ATV_REFERENCED |
| || value_expr->value->value.reference->comp_count != 1) |
| return 0; |
| if(type_expr->expr_type != ASN_BASIC_INTEGER |
| && type_expr->expr_type != ASN_BASIC_ENUMERATED) |
| return 0; |
| |
| DEBUG("%s(for %s in %s %x) for line %d", __func__, |
| asn1f_printable_value(value_expr->value), |
| type_expr->Identifier, |
| type_expr->expr_type, |
| value_expr->_lineno); |
| |
| /* |
| * Look into the definitions of the type itself: |
| * Type1 ::= INTEGER { a(1), b(2) } |
| * value Type1 = b -- will assign 2 |
| */ |
| identifier = value_expr->value->value.reference->components[0].name; |
| |
| child_expr = asn1f_lookup_child(type_expr, identifier); |
| DEBUG("\tLooking into a type %s at line %d for %s at line %d: %s", |
| type_expr->Identifier, type_expr->_lineno, |
| identifier, value_expr->_lineno, |
| child_expr |
| ? asn1f_printable_value(child_expr->value) |
| : "<not found>" |
| ); |
| |
| if(child_expr && child_expr->value) { |
| if(_asn1f_copy_value(arg, value_expr, child_expr)) |
| return -1; |
| /* Fall through */ |
| } |
| |
| return 0; |
| } |