You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
3.3 KiB
Python
118 lines
3.3 KiB
Python
"""
|
|
RiscEmu (c) 2021 Anton Lydike
|
|
|
|
SPDX-License-Identifier: MIT
|
|
"""
|
|
|
|
from math import log10, ceil
|
|
from typing import Iterable, Iterator, TypeVar, Generic, List, Optional
|
|
|
|
from .types import Int32, UInt32
|
|
from .types.exceptions import *
|
|
|
|
|
|
def align_addr(addr: int, to_bytes: int = 8) -> int:
|
|
"""
|
|
align an address to `to_bytes` (meaning addr & to_bytes = 0)
|
|
|
|
This will increase the address
|
|
"""
|
|
return addr + (-addr % to_bytes)
|
|
|
|
|
|
def parse_numeric_argument(arg: str) -> int:
|
|
"""
|
|
parse hex or int strings
|
|
"""
|
|
try:
|
|
if arg.lower().startswith("0x"):
|
|
return int(arg, 16)
|
|
return int(arg)
|
|
except ValueError as ex:
|
|
raise ParseException(
|
|
'Invalid immediate argument "{}", maybe missing symbol?'.format(arg),
|
|
(arg, ex),
|
|
)
|
|
|
|
|
|
def create_chunks(my_list, chunk_size):
|
|
"""Split a list like [a,b,c,d,e,f,g,h,i,j,k,l,m] into e.g. [[a,b,c,d],[e,f,g,h],[i,j,k,l],[m]]"""
|
|
return [my_list[i : i + chunk_size] for i in range(0, len(my_list), chunk_size)]
|
|
|
|
|
|
def apply_highlight(item, ind, hi_ind):
|
|
"""
|
|
applies some hightlight such as underline to item if ind == hi_ind
|
|
"""
|
|
if ind == hi_ind:
|
|
return FMT_UNDERLINE + FMT_ORANGE + item + FMT_NONE
|
|
return item
|
|
|
|
|
|
def highlight_in_list(items, hi_ind, joiner=" "):
|
|
return joiner.join(
|
|
[apply_highlight(item, i, hi_ind) for i, item in enumerate(items)]
|
|
)
|
|
|
|
|
|
def format_bytes(byte_arr: bytearray, fmt: str, group: int = 1, highlight: int = -1):
|
|
"""Format byte array as per fmt. Group into groups of size `group`, and highlight index `highlight`."""
|
|
chunks = create_chunks(byte_arr, group)
|
|
if fmt == "hex":
|
|
return highlight_in_list(["0x{}".format(ch.hex()) for ch in chunks], highlight)
|
|
if fmt == "int":
|
|
spc = str(ceil(log10(2 ** (group * 8 - 1))) + 1)
|
|
return highlight_in_list(
|
|
[("{:0" + spc + "d}").format(Int32(ch)) for ch in chunks], highlight
|
|
)
|
|
if fmt == "uint":
|
|
spc = str(ceil(log10(2 ** (group * 8))))
|
|
return highlight_in_list(
|
|
[("{:0" + spc + "d}").format(UInt32(ch)) for ch in chunks], highlight
|
|
)
|
|
if fmt == "char":
|
|
return highlight_in_list((repr(chr(b))[1:-1] for b in byte_arr), highlight, "")
|
|
|
|
|
|
T = TypeVar("T")
|
|
|
|
|
|
class Peekable(Generic[T], Iterator[T]):
|
|
def __init__(self, iterable: Iterable[T]):
|
|
self.iterable = iter(iterable)
|
|
self.cache: List[T] = list()
|
|
|
|
def __iter__(self) -> Iterator[T]:
|
|
return self
|
|
|
|
def __next__(self) -> T:
|
|
if self.cache:
|
|
return self.cache.pop()
|
|
return next(self.iterable)
|
|
|
|
def peek(self) -> Optional[T]:
|
|
try:
|
|
if self.cache:
|
|
return self.cache[0]
|
|
pop = next(self.iterable)
|
|
self.cache.append(pop)
|
|
return pop
|
|
except StopIteration:
|
|
return None
|
|
|
|
def push_back(self, item: T):
|
|
self.cache = [item] + self.cache
|
|
|
|
def is_empty(self) -> bool:
|
|
return self.peek() is None
|
|
|
|
|
|
def get_section_base_name(section_name: str) -> str:
|
|
if "." not in section_name:
|
|
print(
|
|
FMT_PARSE
|
|
+ f"Invalid section {section_name}, not starting with a dot!"
|
|
+ FMT_NONE
|
|
)
|
|
return "." + section_name.split(".")[1]
|