def value(entry, expr, params=None, magic_expression=None, magic_name=None, ref_name=None): """ Convert an expression object to a valid C expression. entry -- The entry that will use this value. expr -- The bdec.expression.Expression instance to represent in C code. params -- The parameters to use for finding variables. If None, it will use the decode parameters (decode_params). magic_expression -- If the 'magic_expression' is found it will be replaced with the 'magic_name'. magic_name -- The 'magic' name to use when 'magic_expression' is found. """ ref_name = ref_name or local_reference_name if params is None: params = decode_params if expr is magic_expression: return magic_name elif isinstance(expr, int): return str(expr) elif isinstance(expr, Constant): if int(expr.value) >= (1 << 61): return "%iULL" % expr.value if int(expr.value) >= (1 << 32): return "%iLL" % expr.value elif int(expr.value) > (1 << 31): return "%iU" % expr.value else: return int(expr.value) elif isinstance(expr, ReferenceExpression): return ref_name(entry, expr, params)[1] elif isinstance(expr, ArithmeticExpression): left = value(entry, expr.left, params, magic_expression, magic_name, ref_name) right = value(entry, expr.right, params, magic_expression, magic_name, ref_name) cast = "" left_type = type_from_range(expression_range(expr.left, entry, raw_params)) right_type = type_from_range(expression_range(expr.right, entry, raw_params)) result_type = type_from_range(expression_range(expr, entry, raw_params)) types = unsigned_types.copy() types.update(signed_types) if types[result_type][0] > max(types[left_type][0], types[right_type][0]): # If the result will be bigger than both left and right, we will # explicitly cast to make sure the operation is valid. For example, # '1 << 63' is invalid, but '(long long)1 << 63' is ok. cast = "(%s)" % result_type return "(%s%s %s %s)" % (cast, left, _OPERATORS[expr.op], right) elif isinstance(expr, RoundUpDivisionExpression): left = value(entry, expr.numerator, params, magic_expression, magic_name, ref_name) right = value(entry, expr.denominator, params, magic_expression, magic_name, ref_name) rounding = '1' if expr.should_round_up else '0' return function('divide with rounding') + '(%s, %s, %s)' % (left, right, rounding) else: raise Exception('Unknown length value', expr)
def sequenceof_count_ctype(entry): assert isinstance(entry, SequenceOf) assert len(entry.children) == 1 if entry.count is not None: return type_from_range(expression_range(entry.count, entry, raw_params)) if entry.length is not None: range = expression_range(entry.length, entry, raw_params) / \ EntryLengthType(entry.children[0].entry).range(raw_params) return type_from_range(range) # No count, no type, so use the longest possible. return type_from_range(Range(0, None))
def test_subtract_range(self): a = parse('95 - (100 - 20)') self.assertEqual(15, expression_range(a).min) self.assertEqual(15, expression_range(a).max)
def test_add_range(self): a = parse('(10 + 3) + 7') self.assertEqual(20, expression_range(a).min) self.assertEqual(20, expression_range(a).max)
def test_mod_range(self): a = parse('100 % 2') self.assertEqual(Range(0, 1), expression_range(a))
def test_divide_range(self): a = parse('16 / 2 / 4') self.assertEqual(2, expression_range(a).min) self.assertEqual(2, expression_range(a).max)
def test_multiple_range(self): a = parse('8 * 1 * 4') self.assertEqual(32, expression_range(a).min) self.assertEqual(32, expression_range(a).max)
def test_constant_range(self): a = parse('8') self.assertEqual(8, expression_range(a).min) self.assertEqual(8, expression_range(a).max)