#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, const enum asn1p_constraint_type_e *opt_constr_type) { 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\", %x%s%s)", asn1f_printable_value(expr->value), expr->expr_type, opt_constr_type ? ", " : "", opt_constr_type ? asn1p_constraint_type2str(*opt_constr_type) : "" ); /* * 1. Find the terminal type for this assignment. */ type_expr = asn1f_find_terminal_type(arg, expr); if(type_expr == 0) { if(errno == EEXIST) { DEBUG("External type for %s at line %d", expr->Identifier, expr->_lineno); return 0; } else { FATAL("Terminal type for %s at line %d not found", expr->Identifier, expr->_lineno); return -1; } } if(asn1f_look_value_in_type(arg, type_expr, expr) == -1) { FATAL("Value not found in type for %s at line %d", expr->Identifier, expr->_lineno); return -1; } /* * 2. Find the terminal value also. */ value_expr = asn1f_find_terminal_value(arg, expr); if(value_expr) { DEBUG("Terminal 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("Terminal 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("Terminal 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. */ if(opt_constr_type) ret = asn1constraint_compatible(val_type_expr->expr_type, *opt_constr_type, 0 /* must not matter here */); else ret = asn1f_check_type_compatibility(arg, type_expr, val_type_expr); if(ret == -1) { switch(type_expr->expr_type) { default: if(!(type_expr->expr_type & ASN_STRING_MASK)) break; /* Compatibility rules are not defined */ /* Fall through */ case ASN_BASIC_INTEGER: case ASN_BASIC_ENUMERATED: FATAL("Incompatible type of \"%s\" (%s) at line %d " "with \"%s\" (%s) at line %d", type_expr->Identifier, ASN_EXPR_TYPE2STR(type_expr->expr_type), type_expr->_lineno, val_type_expr->Identifier, ASN_EXPR_TYPE2STR(val_type_expr->expr_type), 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; } WARNING("Possibly incompatible type of \"%s\" (%s) at line %d " "with \"%s\" (%s) at line %d", type_expr->Identifier, ASN_EXPR_TYPE2STR(type_expr->expr_type), type_expr->_lineno, val_type_expr->Identifier, ASN_EXPR_TYPE2STR(val_type_expr->expr_type), 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("Final 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("(for %s in %s %x) for line %d", 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("Looking 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) : "" ); if(child_expr && child_expr->value) { if(_asn1f_copy_value(arg, value_expr, child_expr)) return -1; /* Fall through */ } return 0; }