mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-07-31 22:33:53 -06:00

This started as a simple script that scanned for regular expressions, but became more and more complex when exceptions to the rules were found. I don't know if this should be maintained in the QEMU source tree long term (maybe it can be reused for other code transformations that Coccinelle can't handle). In either case, this is included as part of the patch series to document how exactly the automated code transformations in the next patches were done. Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> Message-Id: <20200831210740.126168-7-ehabkost@redhat.com> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
72 lines
No EOL
2 KiB
Python
72 lines
No EOL
2 KiB
Python
# Copyright (C) 2020 Red Hat Inc.
|
|
#
|
|
# Authors:
|
|
# Eduardo Habkost <ehabkost@redhat.com>
|
|
#
|
|
# This work is licensed under the terms of the GNU GPL, version 2. See
|
|
# the COPYING file in the top-level directory.
|
|
from typing import *
|
|
|
|
import logging
|
|
logger = logging.getLogger(__name__)
|
|
DBG = logger.debug
|
|
INFO = logger.info
|
|
WARN = logger.warning
|
|
|
|
T = TypeVar('T')
|
|
def opt_compare(a: T, b: T) -> bool:
|
|
"""Compare two values, ignoring mismatches if one of them is None"""
|
|
return (a is None) or (b is None) or (a == b)
|
|
|
|
def merge(a: T, b: T) -> T:
|
|
"""Merge two values if they matched using opt_compare()"""
|
|
assert opt_compare(a, b)
|
|
if a is None:
|
|
return b
|
|
else:
|
|
return a
|
|
|
|
def test_comp_merge():
|
|
assert opt_compare(None, 1) == True
|
|
assert opt_compare(2, None) == True
|
|
assert opt_compare(1, 1) == True
|
|
assert opt_compare(1, 2) == False
|
|
|
|
assert merge(None, None) is None
|
|
assert merge(None, 10) == 10
|
|
assert merge(10, None) == 10
|
|
assert merge(10, 10) == 10
|
|
|
|
|
|
LineNumber = NewType('LineNumber', int)
|
|
ColumnNumber = NewType('ColumnNumber', int)
|
|
class LineAndColumn(NamedTuple):
|
|
line: int
|
|
col: int
|
|
|
|
def __str__(self):
|
|
return '%d:%d' % (self.line, self.col)
|
|
|
|
def line_col(s, position: int) -> LineAndColumn:
|
|
"""Return line and column for a char position in string
|
|
|
|
Character position starts in 0, but lines and columns start in 1.
|
|
"""
|
|
before = s[:position]
|
|
lines = before.split('\n')
|
|
line = len(lines)
|
|
col = len(lines[-1]) + 1
|
|
return LineAndColumn(line, col)
|
|
|
|
def test_line_col():
|
|
assert line_col('abc\ndefg\nhijkl', 0) == (1, 1)
|
|
assert line_col('abc\ndefg\nhijkl', 2) == (1, 3)
|
|
assert line_col('abc\ndefg\nhijkl', 3) == (1, 4)
|
|
assert line_col('abc\ndefg\nhijkl', 4) == (2, 1)
|
|
assert line_col('abc\ndefg\nhijkl', 10) == (3, 2)
|
|
|
|
def not_optional(arg: Optional[T]) -> T:
|
|
assert arg is not None
|
|
return arg
|
|
|
|
__all__ = ['not_optional', 'opt_compare', 'merge', 'line_col', 'LineAndColumn'] |