diff --git a/amitools/vamos/astructs/__init__.py b/amitools/vamos/astructs/__init__.py index d9d21c6f..e937515e 100644 --- a/amitools/vamos/astructs/__init__.py +++ b/amitools/vamos/astructs/__init__.py @@ -1,8 +1,8 @@ from .access import AccessStruct from .astruct import AmigaStruct, AmigaStructTypes, APTR_SELF, BPTR_SELF from .astructdef import AmigaStructDef, AmigaClassDef -from .scalar import ULONG, LONG, UWORD, WORD, UBYTE, BYTE -from .pointer import BPTR, APTR, BPTR_VOID, APTR_VOID, PointerType +from .scalar import ULONG, LONG, UWORD, WORD, UBYTE, BYTE, ScalarType +from .pointer import BPTR, APTR, BPTR_VOID, APTR_VOID, PointerType, make_aptr, make_bptr from .array import ARRAY, ArrayIter, ArrayType from .string import CSTR, BSTR, CStringType, BStringType from .dump import TypeDumper diff --git a/amitools/vamos/astructs/pointer.py b/amitools/vamos/astructs/pointer.py index ff221ec4..ba6848fa 100644 --- a/amitools/vamos/astructs/pointer.py +++ b/amitools/vamos/astructs/pointer.py @@ -23,11 +23,16 @@ def get_ref_type(cls): def get_signature(cls): return "{}*".format(cls._ref_type.get_signature()) - def __init__(self, mem=None, addr=None, cpu=None, reg=None, **kwargs): + def __init__( + self, mem=None, addr=None, cpu=None, reg=None, ref=None, ref_addr=0, **kwargs + ): """create pointer type with referenced object""" super(PointerType, self).__init__(mem, addr, cpu, reg, **kwargs) - self._ref = None - self._ref_addr = None + self._ref = ref + if ref: + self._ref_addr = ref.get_addr() + else: + self._ref_addr = ref_addr def setup(self, val, alloc=None, free_refs=None): if val is None: @@ -70,7 +75,9 @@ def set_ref(self, ref): if not ref: self._ref_addr = 0 else: - assert isinstance(ref, self._ref_type) + # ignore VOID + if not issubclass(self._ref_type, VOID): + assert isinstance(ref, self._ref_type) self._ref_addr = ref.get_addr() self._write_pointer(self._ref_addr) @@ -91,8 +98,11 @@ def set(self, ref_addr): def _read_pointer(self): if self._addr is not None: store_addr = self._mem.r32(self._addr) - else: + elif self._reg is not None: store_addr = self._cpu.r_reg(self._reg) + else: + # fake read for unbound pointer (re-use value) + store_addr = self._ref_to_store_addr(self._ref_addr) ref_addr = self._store_to_ref_addr(store_addr) return ref_addr @@ -100,8 +110,11 @@ def _write_pointer(self, ref_addr): store_addr = self._ref_to_store_addr(ref_addr) if self._addr is not None: self._mem.w32(self._addr, store_addr) - else: + elif self._reg is not None: self._cpu.w_reg(self._reg, store_addr) + else: + # fake write for unbound pointers (set value) + self._ref_addr = ref_addr def __repr__(self): return "{}(ref={}, addr={})".format( @@ -214,6 +227,15 @@ def APTR(ref_type): return new_type +def make_aptr(ref_obj, **kw_args): + """create a pointer instance in memory or as reg around given object""" + ref_type = type(ref_obj) + aptr_type = APTR(ref_type) + ptr_obj = aptr_type(**kw_args) + ptr_obj.ref = ref_obj + return ptr_obj + + # pointer type cache BPTRTypes = {} @@ -229,5 +251,14 @@ def BPTR(ref_type): return new_type +def make_bptr(ref_obj, **kw_args): + """create a pointer instance in memory or as reg around given object""" + ref_type = type(ref_obj) + bptr_type = BPTR(ref_type) + ptr_obj = bptr_type(**kw_args) + ptr_obj.ref = ref_obj + return ptr_obj + + APTR_VOID = APTR(VOID) BPTR_VOID = BPTR(VOID) diff --git a/amitools/vamos/lib/DosLibrary.py b/amitools/vamos/lib/DosLibrary.py index 268b46db..0a667535 100644 --- a/amitools/vamos/lib/DosLibrary.py +++ b/amitools/vamos/lib/DosLibrary.py @@ -5,7 +5,7 @@ from amitools.vamos.machine.regs import * from amitools.vamos.libcore import LibImpl -from amitools.vamos.astructs import AccessStruct +from amitools.vamos.astructs import AccessStruct, CSTR from amitools.vamos.libstructs import ( DosLibraryStruct, DosInfoStruct, @@ -25,14 +25,13 @@ DosPacketStruct, PathStruct, ) +from amitools.vamos.libtypes import TagList, DosTag from amitools.vamos.error import * from amitools.vamos.log import log_dos from .dos.Args import * from .dos.Error import * from .dos.AmiTime import * -from .util.TagList import * from .dos import Printf, PathPart -from .dos.DosTags import DosTags from .dos.PatternMatch import Pattern, pattern_parse, pattern_match from .dos.MatchFirstNext import MatchFirstNext from .dos.CommandLine import CommandLine @@ -1510,12 +1509,9 @@ def ReadItem(self, ctx): # ----- System/Execute ----- - def SystemTagList(self, ctx): - cmd_ptr = ctx.cpu.r_reg(REG_D1) - tagitem_ptr = ctx.cpu.r_reg(REG_D2) - cmd = ctx.mem.r_cstr(cmd_ptr) - tag_list = taglist_parse_tagitem_ptr(ctx.mem, tagitem_ptr, DosTags) - log_dos.info("SystemTagList: cmd='%s' tags=%s", cmd, tag_list) + def SystemTagList(self, ctx, cmd: CSTR, tag_list: TagList): + cmd = cmd.get_str() + log_dos.info("SystemTagList: cmd=%s tags=%s ctx=%s", cmd, tag_list, ctx) # cmd is at this point a full string of commands to execute. # If we're running from the Amiga shell, forward this to the shell # anyhow. @@ -1530,17 +1526,20 @@ def SystemTagList(self, ctx): ) return 0xFFFFFFFF # Push-back the commands into the input buffer. - new_input.setbuf(cmd) + if cmd: + new_input.setbuf(cmd) new_stdin = self.file_mgr.open(None, "*", "rw") - outtag = tag_list.find_tag("SYS_Output") + outtag = tag_list.find_tag(DosTag.SYS_Output) # print "setting new input to %s" % new_input # and install this as current input. The shell will read from that # instead until it hits the EOF input_fhsi = cli.r_s("cli_StandardInput") input_fhci = cli.r_s("cli_CurrentInput") - if outtag != None and outtag.data != 0: - output_fhci = cli.r_s("cli_StandardOutput") - cli.w_s("cli_StandardOutput", outtag.data << 2) + if outtag: + data = outtag.get_data() + if data != 0: + output_fhci = cli.r_s("cli_StandardOutput") + cli.w_s("cli_StandardOutput", data << 2) else: output_fhci = None cli.w_s("cli_CurrentInput", new_input.mem.addr) diff --git a/amitools/vamos/lib/LocaleLibrary.py b/amitools/vamos/lib/LocaleLibrary.py index 15657bdf..003c1cc8 100644 --- a/amitools/vamos/lib/LocaleLibrary.py +++ b/amitools/vamos/lib/LocaleLibrary.py @@ -1,6 +1,5 @@ from amitools.vamos.machine.regs import * from amitools.vamos.libcore import LibImpl -from amitools.vamos.lib.util.TagList import * from amitools.vamos.lib.util.AmiDate import * from amitools.vamos.log import * diff --git a/amitools/vamos/lib/UtilityLibrary.py b/amitools/vamos/lib/UtilityLibrary.py index e2deff4e..fce55eae 100644 --- a/amitools/vamos/lib/UtilityLibrary.py +++ b/amitools/vamos/lib/UtilityLibrary.py @@ -1,6 +1,7 @@ -from amitools.vamos.machine.regs import * +from amitools.vamos.machine.regs import REG_D0, REG_D1, REG_A0, REG_A1 +from amitools.vamos.astructs import APTR from amitools.vamos.libcore import LibImpl -from amitools.vamos.lib.util.TagList import * +from amitools.vamos.libtypes import TagList, TagItem from amitools.vamos.lib.util.AmiDate import * from amitools.vamos.log import * @@ -93,38 +94,92 @@ def Strnicmp(self, ctx): # Tags - def NextTagItem(self, ctx): - ti_ptr_addr = ctx.cpu.r_reg(REG_A0) - ti_addr = ctx.mem.r32(tr_ptr_addr) - ti_addr = next_tag_item(ctx, ti_addr) - if ti_addr is None: - next_addr = 0 + def FindTagItem(self, ctx, tag_val, tag_list: TagList) -> TagItem: + if not tag_list: + return 0 + log_utility.info("FindTagItem(tag=%08x, list=%s)", tag_val, tag_list) + tag = tag_list.find_tag(tag_val) + if tag: + log_utility.info("found tag: %r", tag) + return tag else: - next_addr = ti_addr + 8 - ctx.mem.w32(tr_ptr_addr, next_addr) - return ti_addr - - def FindTagItem(self, ctx): - tagValue = ctx.cpu.r_reg(REG_D0) - ti_addr = ctx.cpu.r_reg(REG_A0) - if ti_addr == 0: + log_utility.info("no tag!") + return 0 + + def GetTagData(self, ctx, tag_val, default_val, tag_list_addr): + if tag_list_addr == 0: + return default_val + log_utility.info( + "GetTagData(tag=%08x, def=%08x, list=%08x)", + tag_val, + default_val, + tag_list_addr, + ) + tl = TagList(ctx.mem, tag_list_addr) + data = tl.get_tag_data(tag_val, default_val) + log_utility.info("result data=%08x", data) + return data + + def PackBoolTags(self, ctx, init_flags, tag_list_addr, bool_map_addr): + if tag_list_addr == 0 or bool_map_addr == 0: + return 0 + log_utility.info( + "PackBoolTags(flags=%08x, list=%08x, map=%08x)", + init_flags, + tag_list_addr, + bool_map_addr, + ) + tag_list = TagList(ctx.mem, tag_list_addr) + bool_map = TagList(ctx.mem, bool_map_addr) + result = init_flags + for tag in tag_list: + on_flag = tag.get_data() + bool_tag = bool_map.find_tag(tag) + if bool_tag: + mask_val = bool_tag.get_data() + if on_flag: + result |= mask_val + else: + result &= ~mask_val + log_utility.info("result mask=%08x", result) + return result + + def NextTagItem(self, ctx, ti_ptr: APTR(APTR(TagItem))): + if ti_ptr is None: + return 0 + tag_ptr = ti_ptr.ref + log_utility.info("NextTagItem(ti_ptr=%s) -> tag=%s", ti_ptr, tag_ptr) + if tag_ptr is None: + return 0 + tag = tag_ptr.ref + real_tag = tag.next_real_tag() + if real_tag is None: + log_utility.info("no real tag!") + tag_ptr.ref = None return 0 - while True: - ti_addr = next_tag_item(ctx, ti_addr) - if ti_addr is None: - return 0 - tag, _ = get_tag(ctx, ti_addr) - if tag == tagValue: - return ti_addr - ti_addr += 8 - - def GetTagData(self, ctx): - defaultValue = ctx.cpu.r_reg(REG_D1) - ti_addr = self.FindTagItem(ctx) - if ti_addr != 0: - return get_tag(ctx, ti_addr)[1] else: - return defaultValue + succ_tag = tag.succ_tag() + log_utility.info("real tag=%r, succ_tag=%r", tag, succ_tag) + tag_ptr.ref = succ_tag + return tag.get_addr() + + def FilterTagChanges(self, ctx, change_list: TagList, orig_list: TagList, apply): + if change_list is None or orig_list is None: + return 0 + log_utility.info( + "FilterTagChanges(change=%s, orig=%s, apply=%s)", + change_list, + orig_list, + apply, + ) + for tag in change_list: + orig_tag = orig_list.find_tag(tag) + if orig_tag: + tag_data = tag.get_data() + if tag_data == orig_tag.get_data(): + tag.remove() + elif apply: + orig_tag.set_data(tag_data) # ---- Date ----- diff --git a/amitools/vamos/lib/dos/DosLibCtx.py b/amitools/vamos/lib/dos/DosLibCtx.py index a3beded7..a821342f 100644 --- a/amitools/vamos/lib/dos/DosLibCtx.py +++ b/amitools/vamos/lib/dos/DosLibCtx.py @@ -15,6 +15,13 @@ def __init__( self.exec_lib = None self.dos_lib = None + def __str__(self): + return "[DosLibCtx:cpu=%s,mem=%s,process=%s]" % ( + self.cpu, + self.mem, + self.process, + ) + def set_exec_lib(self, exec_lib): self.exec_lib = exec_lib diff --git a/amitools/vamos/lib/dos/DosTags.py b/amitools/vamos/lib/dos/DosTags.py deleted file mode 100644 index 556f4a93..00000000 --- a/amitools/vamos/lib/dos/DosTags.py +++ /dev/null @@ -1,40 +0,0 @@ -DosTags = { - # System - 33: "SYS_Input", - 34: "SYS_Output", - 35: "SYS_Asynch", - 36: "SYS_UserShell", - 37: "SYS_CustomShell", - # CreateNewProc - 1001: "NP_SegList", - 1002: "NP_FreeSegList", - 1003: "NP_Entry", - 1004: "NP_Input", - 1005: "NP_Output", - 1006: "NP_CloseInput", - 1007: "NP_CloseOutput", - 1008: "NP_Error", - 1009: "NP_CloseError", - 1010: "NP_CurrentDir", - 1011: "NP_StackSize", - 1012: "NP_Name", - 1013: "NP_Priority", - 1014: "NP_ConsoleTask", - 1015: "NP_WindowPtr", - 1016: "NP_HomeDir", - 1017: "NP_CopyVars", - 1018: "NP_Cli", - 1019: "NP_Path", - 1020: "NP_CommandName", - 1021: "NP_Arguments", - 1022: "NP_NotifyOnDeath", - 1023: "NP_Synchronous", - 1024: "NP_ExitCode", - 1025: "NP_ExitData", - # AllocDosObject - 2001: "ADO_FH_Mode", - 2002: "ADO_DirLen", - 2003: "ADR_CommNameLen", - 2004: "ADR_CommFileLen", - 2005: "ADR_PromptLen", -} diff --git a/amitools/vamos/lib/lexec/ExecLibCtx.py b/amitools/vamos/lib/lexec/ExecLibCtx.py index ead729d2..d0d82bb4 100644 --- a/amitools/vamos/lib/lexec/ExecLibCtx.py +++ b/amitools/vamos/lib/lexec/ExecLibCtx.py @@ -19,3 +19,11 @@ def __init__(self, machine, alloc, runner, seg_loader, path_mgr, lib_mgr): def set_cur_task_process(self, task, process): self.task = task self.process = process + + def __str__(self): + return "[DosLibCtx:cpu=%s,mem=%s,task=%s,process=%s]" % ( + self.cpu, + self.mem, + self.task, + self.process, + ) diff --git a/amitools/vamos/lib/util/TagList.py b/amitools/vamos/lib/util/TagList.py deleted file mode 100644 index 3985987d..00000000 --- a/amitools/vamos/lib/util/TagList.py +++ /dev/null @@ -1,89 +0,0 @@ -from amitools.vamos.astructs import AccessStruct -from amitools.vamos.libstructs import TagItemStruct - -TAG_DONE = 0 -TAG_IGNORE = 1 -TAG_MORE = 2 -TAG_SKIP = 3 - -TAG_USER = 1 << 31 - - -class Tag: - def __init__(self, tag, data, tag_info): - self.user = tag & TAG_USER == TAG_USER - self.tag = tag & ~TAG_USER - self.data = data - if tag_info != None and self.tag in tag_info: - self.name = tag_info[self.tag] - else: - self.name = None - - def __str__(self): - if self.user: - return "(U:%s/%08x->%08x)" % (self.name, self.tag, self.data) - else: - return "(S:%s/%08x->%08x)" % (self.name, self.tag, self.data) - - -class TagList: - def __init__(self, tag_info): - self.tags = [] - self.tag_info = tag_info - - def add(self, tag, data): - self.tags.append(Tag(tag, data, self.tag_info)) - - def find_tag(self, tagname): - for tag in self.tags: - if tag.name == tagname: - return tag - return None - - def __str__(self): - return "[%s]" % ",".join(map(str, self.tags)) - - -def taglist_parse_tagitem_ptr(mem, addr, tag_info=None): - result = TagList(tag_info) - while True: - tag = mem.r32(addr) - data = mem.r32(addr + 4) - if tag == TAG_DONE: - break - elif tag == TAG_IGNORE: - addr += 8 - elif tag == TAG_SKIP: - addr += 8 * (1 + data) - elif tag == TAG_MORE: - addr = data - else: - result.add(tag, data) - addr += 8 - return result - - -def next_tag_item(ctx, ti_addr): - if ti_addr == 0: - return None - while True: - tag, data = get_tag(ctx, ti_addr) - if tag == TAG_DONE: - return None - elif tag == TAG_MORE: - ti_addr = data - if data == 0: - return None - elif tag == TAG_IGNORE: - ti_addr += 8 - elif tag == TAG_SKIP: - ti_addr += 8 * (1 + data) - else: - return ti_addr - - -def get_tag(ctx, ti_addr): - ti = AccessStruct(ctx.mem, TagItemStruct, ti_addr) - tag = ti.r_s("ti_Tag") - data = ti.r_s("ti_Data") - return tag, data diff --git a/amitools/vamos/libcore/proxy.py b/amitools/vamos/libcore/proxy.py index 405e4067..fed1db27 100644 --- a/amitools/vamos/libcore/proxy.py +++ b/amitools/vamos/libcore/proxy.py @@ -32,10 +32,24 @@ def input_reg_map(self): reg_map = {} for reg, val in zip(self.arg_regs, self.args): # auto convert strings - if type(val) is str: + if val is None: + val = 0 + elif isinstance(val, int): + pass + elif isinstance(val, str): str_mem = self.ctx.alloc.alloc_cstr(val, label="reg_auto_str") val = str_mem.addr self.auto_strings.append(str_mem) + # complex object? try to get its in memory address via "get_addr" + else: + # has 'addr'? + get_addr = getattr(val, "get_addr", None) + if get_addr is not None: + val = get_addr() + else: + raise ValueError( + f"Invalid argument for proxy call reg={reg} val={val}" + ) reg_map[reg] = val return reg_map diff --git a/amitools/vamos/libcore/stub.py b/amitools/vamos/libcore/stub.py index 49777f32..e0202fe3 100644 --- a/amitools/vamos/libcore/stub.py +++ b/amitools/vamos/libcore/stub.py @@ -2,6 +2,7 @@ import time import traceback +from amitools.vamos.astructs import ScalarType, PointerType from amitools.vamos.machine.regs import REG_D0, REG_D1, REG_A7 @@ -198,6 +199,54 @@ def profile_func(this, *args, **kwargs): # return created func return func + def _set_result(self, ctx, res): + """set result after execution of the lib stub method""" + if res is not None: + if type(res) in (list, tuple): + ctx.cpu.w_reg(REG_D0, res[0] & 0xFFFFFFFF) + ctx.cpu.w_reg(REG_D1, res[1] & 0xFFFFFFFF) + elif type(res) in (int, bool): + ctx.cpu.w_reg(REG_D0, int(res) & 0xFFFFFFFF) + else: + # is type object? then use its addr + get_addr = getattr(res, "get_addr", None) + if get_addr: + addr = get_addr() + ctx.cpu.w_reg(REG_D0, addr) + else: + raise ValueError(f"Invalid result value '{res}'") + + return res + + def _gen_extra_args(self, ctx, extra_args): + """generate the extra arguments passed to a lib method""" + args = [] + + for arg in extra_args: + arg_val = ctx.cpu.r_reg(arg.reg) + arg_type = arg.type + # int: keep value + if issubclass(arg_type, int): + pass + # bool: convert to int + elif issubclass(arg_type, bool): + arg_val = int(arg_val) + # scalar values and pointers are bound to the register + elif issubclass(arg_type, ScalarType) or issubclass(arg_type, PointerType): + arg_val = arg_type(cpu=ctx.cpu, reg=arg.reg, mem=ctx.mem) + # all other types are bound to the address in memory + # (implicit APTR conversion) + else: + if arg_val != 0: + arg_val = arg_type(mem=ctx.mem, addr=arg_val) + else: + # NULL object is none + arg_val = None + + args.append(arg_val) + + return args + def _gen_base_func(self, method, ctx): """generate a function that calls the method with the ctx.""" @@ -205,13 +254,7 @@ def base_func(this, *args, **kwargs): """the base function to call the impl, set return vals, and catch exceptions""" res = method(ctx) - if res is not None: - if type(res) in (list, tuple): - ctx.cpu.w_reg(REG_D0, res[0] & 0xFFFFFFFF) - ctx.cpu.w_reg(REG_D1, res[1] & 0xFFFFFFFF) - else: - ctx.cpu.w_reg(REG_D0, res & 0xFFFFFFFF) - return res + return self._set_result(ctx, res) return base_func @@ -221,23 +264,11 @@ def _gen_base_extra_args_func(self, method, ctx, extra_args): def base_func(this, *args, **kwargs): """the base function to call the impl, set return vals, and catch exceptions""" - args = [] - for arg in extra_args: - arg_val = ctx.cpu.r_reg(arg.reg) - arg_type = arg.type - # int: keep value - if arg_type is not int: - # bind to type - arg_val = arg_type(cpu=ctx.cpu, reg=arg.reg, mem=ctx.mem) - args.append(arg_val) + + args = self._gen_extra_args(ctx, extra_args) + # call function res = method(ctx, *args) - if res is not None: - if type(res) in (list, tuple): - ctx.cpu.w_reg(REG_D0, res[0] & 0xFFFFFFFF) - ctx.cpu.w_reg(REG_D1, res[1] & 0xFFFFFFFF) - else: - ctx.cpu.w_reg(REG_D0, res & 0xFFFFFFFF) - return res + return self._set_result(ctx, res) return base_func diff --git a/amitools/vamos/libtypes/__init__.py b/amitools/vamos/libtypes/__init__.py index ef8424c7..4e834b4a 100644 --- a/amitools/vamos/libtypes/__init__.py +++ b/amitools/vamos/libtypes/__init__.py @@ -10,3 +10,7 @@ # dos from .lock import FileLock, FileHandle from .process import CLI, Process, PathList + +# util +from .tag import CommonTag, TagItem, TagList +from .dostag import DosTag diff --git a/amitools/vamos/libtypes/dostag.py b/amitools/vamos/libtypes/dostag.py new file mode 100644 index 00000000..2072cc63 --- /dev/null +++ b/amitools/vamos/libtypes/dostag.py @@ -0,0 +1,42 @@ +from enum import IntEnum + + +class DosTag(IntEnum): + # System + SYS_Input = 33 + SYS_Output = 34 + SYS_Asynch = 35 + SYS_UserShell = 36 + SYS_CustomShell = 37 + # CreateNewProc + NP_SegList = 1001 + NP_FreeSegList = 1002 + NP_Entry = 1003 + NP_Input = 1004 + NP_Output = 1005 + NP_CloseInput = 1006 + NP_CloseOutput = 1007 + NP_Error = 1008 + NP_CloseError = 1009 + NP_CurrentDir = 1010 + NP_StackSize = 1011 + NP_Name = 1012 + NP_Priority = 1013 + NP_ConsoleTask = 1014 + NP_WindowPtr = 1015 + NP_HomeDir = 1016 + NP_CopyVars = 1017 + NP_Cli = 1018 + NP_Path = 1019 + NP_CommandName = 1020 + NP_Arguments = 1021 + NP_NotifyOnDeath = 1022 + NP_Synchronous = 1023 + NP_ExitCode = 1024 + NP_ExitData = 1025 + # AllocDosObject + ADO_FH_Mode = 2001 + ADO_DirLen = 2002 + ADR_CommNameLen = 2003 + ADR_CommFileLen = 2004 + ADR_PromptLen = 2005 diff --git a/amitools/vamos/libtypes/tag.py b/amitools/vamos/libtypes/tag.py index fd5fd1d8..61402c64 100644 --- a/amitools/vamos/libtypes/tag.py +++ b/amitools/vamos/libtypes/tag.py @@ -2,7 +2,7 @@ from amitools.vamos.libstructs import TagItemStruct -class CommonTags(IntEnum): +class CommonTag(IntEnum): TAG_DONE = 0 TAG_IGNORE = 1 TAG_MORE = 2 @@ -11,16 +11,16 @@ class CommonTags(IntEnum): ControlTags = [ - CommonTags.TAG_DONE, - CommonTags.TAG_IGNORE, - CommonTags.TAG_MORE, - CommonTags.TAG_SKIP, + CommonTag.TAG_DONE, + CommonTag.TAG_IGNORE, + CommonTag.TAG_MORE, + CommonTag.TAG_SKIP, ] -class Tag(TagItemStruct): +class TagItem(TagItemStruct): def __repr__(self): - return f"Tag(@{self.addr:08x})" + return f"TagItem(@{self.addr:08x})" def next_real_tag(self): """return this or the next 'real' tag. @@ -39,26 +39,53 @@ def succ_tag(self): """successor tag after this one""" tag = self.tag.val data = self.data.val - if tag == CommonTags.TAG_DONE: + if tag == CommonTag.TAG_DONE: return None - elif tag == CommonTags.TAG_MORE: + elif tag == CommonTag.TAG_MORE: if data == 0: return None else: - return Tag(self.mem, data) - elif tag == CommonTags.TAG_SKIP: + return TagItem(self.mem, data) + elif tag == CommonTag.TAG_SKIP: addr = self.addr + 8 * (1 + data) - return Tag(self.mem, addr) + return TagItem(self.mem, addr) else: - return Tag(self.mem, self.addr + 8) + return TagItem(self.mem, self.addr + 8) def succ_real_tag(self): succ = self.succ_tag() if succ: return succ.next_real_tag() - def get_tuple(self): - return (self.tag.val, self.data.val) + def get_tuple(self, map_enum=None, do_map=True): + tag = self.get_tag(map_enum=map_enum, do_map=do_map) + data = self.data.val + return (tag, data) + + def get_tag(self, map_enum=None, do_map=True): + tag = self.tag.val + if do_map: + try: + tag = CommonTag(tag) + except ValueError: + if map_enum: + try: + tag = map_enum(tag) + except ValueError: + pass + return tag + + def get_data(self): + return self.data.val + + def set_tag(self, tag): + self.tag.val = tag + + def set_data(self, data): + self.data.val = data + + def remove(self): + self.tag.val = CommonTag.TAG_IGNORE class TagListIter: @@ -78,10 +105,24 @@ def __next__(self): class TagList: def __init__(self, mem, addr): - self.tag = Tag(mem, addr) + self.tag = TagItem(mem, addr) + self._mem = mem + self._addr = addr self._alloc = None self._mem_obj = None + def get_addr(self): + return self._addr + + def get_mem(self): + return self._mem + + def get_first_tag(self): + return self.tag + + def __repr__(self): + return f"[TagList,@{self._addr:08x}]" + def __iter__(self): return TagListIter(self.tag) @@ -93,20 +134,24 @@ def __len__(self): num += 1 return num - def to_list(self): + def to_list(self, map_enum=None, do_map=True): """convert tag list to python list""" tag = self.tag.next_real_tag() result = [] while tag: - result.append(tag.get_tuple()) + result.append(tag.get_tuple(map_enum=map_enum, do_map=do_map)) tag = tag.succ_real_tag() return result - def find_tag(self, tag): - """find tag in list and if found return Tag() or None""" + def find_tag(self, tag_val): + """find tag/tag item in list and if found return TagItem() or None""" + # auto convert tag item + if isinstance(tag_val, TagItem): + tag_val = tag_val.tag.val + tag = self.tag.next_real_tag() while tag: - if tag.tag.val == tag: + if tag.tag.val == tag_val: return tag tag = tag.succ_real_tag() @@ -122,21 +167,28 @@ def delete_tag(self, tag): """find tag and overwrite it with TAG_IGNORE""" tag = self.find_tag(tag) if tag: - tag.tag.val = CommonTags.TAG_IGNORE + tag.tag.val = CommonTag.TAG_IGNORE return True else: return False + def get_tag_data(self, tag_val, def_value=0): + tag = self.find_tag(tag_val) + if tag: + return tag.data.val + else: + return def_value + @classmethod def alloc(cls, alloc, *tag_list, label=None): tag_list = list(tag_list) num_tags = len(tag_list) if num_tags == 0: - tag_list.append((CommonTags.TAG_DONE, 0)) + tag_list.append((CommonTag.TAG_DONE, 0)) num_tags == 1 # auto add TAG DONE if missing - elif tag_list[-1][0] != CommonTags.TAG_DONE: - tag_list.append((CommonTags.TAG_DONE, 0)) + elif tag_list[-1][0] != CommonTag.TAG_DONE: + tag_list.append((CommonTag.TAG_DONE, 0)) num_tags += 1 # size of tag list num_bytes = num_tags * 8 diff --git a/amitools/vamos/mode/base.py b/amitools/vamos/mode/base.py index 526039fa..afd2de6c 100644 --- a/amitools/vamos/mode/base.py +++ b/amitools/vamos/mode/base.py @@ -14,7 +14,7 @@ def run(self, ctx): # generate tasks task_list = self.gen_task_list_func(ctx) if task_list is None: - return 0 + return [255] # add tasks to scheduler for task in task_list: diff --git a/amitools/vamos/mode/proc.py b/amitools/vamos/mode/proc.py index d56347dd..80d07973 100644 --- a/amitools/vamos/mode/proc.py +++ b/amitools/vamos/mode/proc.py @@ -48,6 +48,8 @@ def create_proc(self, mode_ctx): proc = Process( dos_ctx, cmd, arg_str, stack_size=stack_size, shell=shell, cwd=cwd ) + if not proc.ok: + return None return proc def get_cmd_args(self, cmd_cfg, args): diff --git a/amitools/vamos/task/dosproc.py b/amitools/vamos/task/dosproc.py index a9bdd1c7..aacef0a5 100644 --- a/amitools/vamos/task/dosproc.py +++ b/amitools/vamos/task/dosproc.py @@ -13,7 +13,9 @@ def __init__(self, machine, alloc, name, **kw_args): self.proc = Process.alloc(alloc, name=name) self.proc.new_proc() - super().__init__(machine, alloc, name, ami_task=self.proc.task, **kw_args) + super().__init__( + machine, alloc, name, ami_task=self.proc.task, ami_proc=self.proc, **kw_args + ) def free(self): self.proc.free() diff --git a/amitools/vamos/task/exectask.py b/amitools/vamos/task/exectask.py index c3817c05..7d704295 100644 --- a/amitools/vamos/task/exectask.py +++ b/amitools/vamos/task/exectask.py @@ -20,6 +20,7 @@ def __init__( start_regs=None, return_regs=None, ami_task=None, + ami_proc=None, ): # alloc stack, and task self.stack = Stack.alloc(alloc, stack_size, name=name + "_Stack") @@ -44,7 +45,7 @@ def __init__( code = Code(start_pc, sp, start_regs, return_regs) sched_task = NativeTask(name, machine, code) - super().__init__(sched_task, self.task) + super().__init__(sched_task, self.task, ami_proc) def free(self): if self.own_task: diff --git a/test/helper/task.py b/test/helper/task.py index 8feb7180..d524b988 100644 --- a/test/helper/task.py +++ b/test/helper/task.py @@ -4,7 +4,7 @@ class VamosTask: - def run(self, func_list, process=False): + def run(self, func_list, process=False, args=None): def wrap(ctx, func): def wrap_func(task): return func(ctx, task) @@ -33,8 +33,12 @@ def task_gen(mode_ctx): return result mode = BaseMode("task", task_gen) + if args is None: + args = [] exit_codes = main( - args=["-l", "libmgr:info,exec:info"], mode=mode, single_return_code=False + args=args, + mode=mode, + single_return_code=False, ) assert exit_codes is not None return exit_codes diff --git a/test/pytask/pytask_self.py b/test/pytask/pytask_self.py index 60ede895..3f809bd2 100644 --- a/test/pytask/pytask_self.py +++ b/test/pytask/pytask_self.py @@ -1,13 +1,17 @@ import pytest +from amitools.vamos.task import ExecTask, DosProcess + def pytask_self_simple_task_test(vamos_task): """check if pytask feature works""" def task1(ctx, task): + assert type(task.map_task) is ExecTask return 11 def task2(ctx, task): + assert type(task.map_task) is ExecTask return 22 exit_codes = vamos_task.run([task1, task2]) @@ -18,9 +22,11 @@ def pytask_self_simple_process_test(vamos_task): """check if pytask feature works""" def proc1(ctx, task): + assert type(task.map_task) is DosProcess return 42 def proc2(ctx, task): + assert type(task.map_task) is DosProcess return 23 exit_codes = vamos_task.run([proc1, proc2], process=True) diff --git a/test/pytask/pytask_util_tag.py b/test/pytask/pytask_util_tag.py new file mode 100644 index 00000000..8aa7d016 --- /dev/null +++ b/test/pytask/pytask_util_tag.py @@ -0,0 +1,141 @@ +from enum import IntEnum +from amitools.vamos.libtypes import TagList, TagItem +from amitools.vamos.astructs import APTR + + +class MyTag(IntEnum): + FOO_TAG = 1000 + BAR_TAG = 1001 + BAZ_TAG = 1002 + + +def run_util_func(vamos_task, func): + def task(ctx, task): + # try to open utility lib + lib = ctx.proxies.open_lib_proxy("utility.library") + assert lib is not None + # call lib func + func(ctx, lib) + # close lib + ctx.proxies.close_lib_proxy(lib) + return 0 + + exit_codes = vamos_task.run([task], args=["-l", "utility:info"]) + assert exit_codes[0] == 0 + + +def pytask_util_tag_find_tag_item_test(vamos_task): + def func(ctx, lib): + # build tag list + tl = TagList.alloc(ctx.alloc, (MyTag.FOO_TAG, 1), (MyTag.BAR_TAG, 2)) + assert tl is not None + # test func + addr = lib.FindTagItem(MyTag.BAR_TAG, tl) + assert addr == tl.get_addr() + 8 + assert TagItem(ctx.mem, addr).get_tag() == MyTag.BAR_TAG + addr = lib.FindTagItem(MyTag.BAZ_TAG, tl) + assert addr == 0 + # free tag list + tl.free() + + run_util_func(vamos_task, func) + + +def pytask_util_tag_get_tag_data_test(vamos_task): + def func(ctx, lib): + # build tag list + tl = TagList.alloc(ctx.alloc, (MyTag.FOO_TAG, 1), (MyTag.BAR_TAG, 2)) + assert tl is not None + # test func + val = lib.GetTagData(MyTag.BAR_TAG, 21, tl) + assert val == 2 + val = lib.GetTagData(MyTag.BAZ_TAG, 42, tl) + assert val == 42 + # free tag list + tl.free() + + run_util_func(vamos_task, func) + + +def pytask_util_tag_next_tag_item_test(vamos_task): + def func(ctx, lib): + # build tag list + tl = TagList.alloc(ctx.alloc, (MyTag.FOO_TAG, 1), (MyTag.BAR_TAG, 2)) + assert tl is not None + # get a ptr + tag = tl.get_first_tag() + aptr = APTR(TagItem).alloc(ctx.alloc) + aptr.ref = tag + + # no list? + assert lib.NextTagItem(0) == 0 + + # first entry + res = lib.NextTagItem(aptr) + assert res == tl.get_addr() + # ptr points to next + assert aptr.aptr == tl.get_addr() + 8 + + # next entry + res = lib.NextTagItem(aptr) + assert res == tl.get_addr() + 8 + assert aptr.aptr == tl.get_addr() + 16 + + # no more + assert lib.NextTagItem(aptr) == 0 + + # aptr free + aptr.free() + # free tag list + tl.free() + + run_util_func(vamos_task, func) + + +def pytask_util_tag_pack_bool_tags_test(vamos_task): + def func(ctx, lib): + # build tag list + bool_map = TagList.alloc( + ctx.alloc, (MyTag.FOO_TAG, 0x2), (MyTag.BAR_TAG, 0x4), (MyTag.BAZ_TAG, 0x8) + ) + assert bool_map is not None + tag_list = TagList.alloc( + ctx.alloc, (MyTag.FOO_TAG, True), (MyTag.BAR_TAG, False) + ) + assert tag_list is not None + + # map + val = lib.PackBoolTags(0x4, tag_list, bool_map) + assert val == 0x2 + + # free tag list + tag_list.free() + bool_map.free() + + run_util_func(vamos_task, func) + + +def pytask_util_tag_filter_tag_changes_test(vamos_task): + def func(ctx, lib): + # build tag list + orig_list = TagList.alloc( + ctx.alloc, (MyTag.FOO_TAG, 2), (MyTag.BAR_TAG, 4), (MyTag.BAZ_TAG, 8) + ) + assert orig_list is not None + change_list = TagList.alloc(ctx.alloc, (MyTag.FOO_TAG, 2), (MyTag.BAR_TAG, 8)) + assert change_list is not None + + lib.FilterTagChanges(change_list, orig_list, 0) + + assert orig_list.to_list() == [ + (MyTag.FOO_TAG, 2), + (MyTag.BAR_TAG, 4), + (MyTag.BAZ_TAG, 8), + ] + assert change_list.to_list() == [(MyTag.BAR_TAG, 8)] + + # free tag list + change_list.free() + orig_list.free() + + run_util_func(vamos_task, func) diff --git a/test/unit/astructs_pointer.py b/test/unit/astructs_pointer.py index d84feec7..7cc19766 100644 --- a/test/unit/astructs_pointer.py +++ b/test/unit/astructs_pointer.py @@ -45,6 +45,55 @@ def astructs_pointer_aptr_void_test(): void_ptr.val = 12 +def astructs_pointer_aptr_void_cpu_test(): + assert PointerType.get_byte_size() == 4 + void_ptr = APTR_VOID(cpu=cpu, reg=REG_D0) + cpu.w_reg(REG_D0, 0x80) + ref = void_ptr.ref + assert type(ref) is VOID + assert ref.get_addr() == 0x80 + assert void_ptr.get_ref_addr() == 0x80 + assert int(void_ptr) == 0x80 + # change pointer + void_ptr.set_ref_addr(0x100) + assert void_ptr.get_ref_addr() == 0x100 + assert int(void_ptr) == 0x100 + new_ref = void_ptr.ref + assert type(new_ref) is VOID + assert new_ref.get_addr() == 0x100 + assert cpu.r_reg(REG_D0) == 0x100 + # signature + assert void_ptr.get_signature() == "VOID*" + # check 'aptr' + void_ptr.aptr = 0x200 + assert void_ptr.aptr == 0x200 + # invalid .val access + with pytest.raises(AttributeError): + void_ptr.val = 12 + + +def astructs_pointer_aptr_void_unbound_test(): + assert PointerType.get_byte_size() == 4 + # set pointer + void = VOID(mem=mem, addr=0x100) + void_ptr = APTR_VOID(ref=void) + ref = void_ptr.ref + assert type(ref) is VOID + assert void_ptr.get_ref_addr() == 0x100 + assert int(void_ptr) == 0x100 + new_ref = void_ptr.ref + assert type(new_ref) is VOID + assert new_ref.get_addr() == 0x100 + # signature + assert void_ptr.get_signature() == "VOID*" + # check 'aptr' + void_ptr.aptr = 0x100 + assert void_ptr.aptr == 0x100 + # invalid .val access + with pytest.raises(AttributeError): + void_ptr.val = 12 + + def astructs_pointer_aptr_null_test(): null_ptr = APTR_VOID(mem=mem, addr=0x40) mem.w32(0x40, 0) @@ -53,6 +102,21 @@ def astructs_pointer_aptr_null_test(): assert null_ptr.get_ref_addr() == 0 +def astructs_pointer_aptr_null_cpu_test(): + null_ptr = APTR_VOID(cpu=cpu, reg=REG_D0) + cpu.w_reg(REG_D0, 0) + assert null_ptr.ref is None + assert int(null_ptr) == 0 + assert null_ptr.get_ref_addr() == 0 + + +def astructs_pointer_aptr_null_unbound_test(): + void_ptr = APTR_VOID() + assert void_ptr.ref is None + assert int(void_ptr) == 0 + assert void_ptr.get_ref_addr() == 0 + + def astructs_pointer_bptr_void_test(): assert BCPLPointerType.get_byte_size() == 4 void_ptr = BPTR_VOID(mem=mem, addr=0x40) @@ -91,9 +155,55 @@ def astructs_pointer_bptr_void_test(): void_ptr.val = 12 +def astructs_pointer_bptr_void_cpu_test(): + assert BCPLPointerType.get_byte_size() == 4 + void_ptr = BPTR_VOID(cpu=cpu, reg=REG_D0) + cpu.w_reg(REG_D0, 0x20) + ref = void_ptr.ref + assert type(ref) is VOID + assert ref.get_addr() == 0x80 + assert void_ptr.get_ref_addr() == 0x80 + # int conversion is BPTR! + assert int(void_ptr) == 0x20 + # change pointer + void_ptr.set_ref_addr(0x100) + assert void_ptr.get_ref_addr() == 0x100 + new_ref = void_ptr.ref + assert type(new_ref) is VOID + assert new_ref.get_addr() == 0x100 + # int conversion is BPTR! + assert int(void_ptr) == 0x40 + assert cpu.r_reg(REG_D0) == 0x40 # 0x40 = BCPL addr of 0x100 + # change pointer by baddr + void_ptr.set_ref_baddr(0x200) + assert void_ptr.get_ref_addr() == 0x200 << 2 + assert void_ptr.get_ref_baddr() == 0x200 + assert cpu.r_reg(REG_D0) == 0x200 + # signature + assert void_ptr.get_signature() == "VOID#" + # check 'aptr' + void_ptr.aptr = 0x400 + assert void_ptr.aptr == 0x400 + assert void_ptr.get() == 0x100 + void_ptr.bptr = 0x200 + assert void_ptr.bptr == 0x200 + assert void_ptr.get() == 0x200 + # invalid .val access + with pytest.raises(AttributeError): + void_ptr.val = 12 + + def astructs_pointer_bptr_null_test(): null_ptr = BPTR_VOID(mem=mem, addr=0x40) mem.w32(0x40, 0) assert null_ptr.ref is None assert int(null_ptr) == 0 assert null_ptr.get_ref_addr() == 0 + + +def astructs_pointer_bptr_null_cpu_test(): + null_ptr = BPTR_VOID(cpu=cpu, reg=REG_D0) + cpu.w_reg(REG_D0, 0) + assert null_ptr.ref is None + assert int(null_ptr) == 0 + assert null_ptr.get_ref_addr() == 0 diff --git a/test/unit/libtypes_tag.py b/test/unit/libtypes_tag.py index 0666b270..2cbdffe6 100644 --- a/test/unit/libtypes_tag.py +++ b/test/unit/libtypes_tag.py @@ -1,10 +1,13 @@ -from amitools.vamos.libtypes import Tag, TagList, CommonTags +from enum import IntEnum +from amitools.vamos.libtypes import TagItem, TagList, CommonTag from amitools.vamos.machine.mock import MockMemory from amitools.vamos.mem import MemoryAlloc -FOO_TAG = 1000 -BAR_TAG = 1001 -BAZ_TAG = 1002 + +class MyTag(IntEnum): + FOO_TAG = 1000 + BAR_TAG = 1001 + BAZ_TAG = 1002 def build_tag_list(*tag_list, base=0x10, mem=None): @@ -22,12 +25,12 @@ def build_tag_list(*tag_list, base=0x10, mem=None): def libtypes_tag_done_test(): - mem, addr = build_tag_list(CommonTags.TAG_DONE, 0) + mem, addr = build_tag_list(CommonTag.TAG_DONE, 0) # check end tag - tag = Tag(mem, addr) - assert tag.tag.val == CommonTags.TAG_DONE + tag = TagItem(mem, addr) + assert tag.tag.val == CommonTag.TAG_DONE assert tag.data.val == 0 - assert tag.get_tuple() == (CommonTags.TAG_DONE, 0) + assert tag.get_tuple() == (CommonTag.TAG_DONE, 0) # no "real" tag assert tag.next_real_tag() is None assert tag.succ_tag() is None @@ -35,7 +38,7 @@ def libtypes_tag_done_test(): def libtypes_tag_list_done_test(): - mem, addr = build_tag_list(CommonTags.TAG_DONE, 0) + mem, addr = build_tag_list(CommonTag.TAG_DONE, 0) tag_list = TagList(mem, addr) assert len(tag_list) == 0 assert [a for a in tag_list] == [] @@ -46,66 +49,73 @@ def libtypes_tag_list_done_test(): def libtypes_tag_ignore_test(): """empty tag list with TAG_DONE only""" - mem, addr = build_tag_list(CommonTags.TAG_IGNORE, 0, CommonTags.TAG_DONE, 0) + mem, addr = build_tag_list(CommonTag.TAG_IGNORE, 0, CommonTag.TAG_DONE, 0) # check tag - tag = Tag(mem, addr) - assert tag.tag.val == CommonTags.TAG_IGNORE + tag = TagItem(mem, addr) + assert tag.tag.val == CommonTag.TAG_IGNORE assert tag.data.val == 0 - assert tag.get_tuple() == (CommonTags.TAG_IGNORE, 0) + assert tag.get_tuple() == (CommonTag.TAG_IGNORE, 0) # no "real" tag assert tag.next_real_tag() is None - assert tag.succ_tag() == Tag(mem, 0x18) + assert tag.succ_tag() == TagItem(mem, 0x18) assert tag.succ_real_tag() is None def libtypes_tag_list_ignore_test(): """empty tag list with TAG_DONE only""" - mem, addr = build_tag_list(CommonTags.TAG_IGNORE, 0, CommonTags.TAG_DONE, 0) + mem, addr = build_tag_list(CommonTag.TAG_IGNORE, 0, CommonTag.TAG_DONE, 0) tag_list = TagList(mem, addr) assert len(tag_list) == 0 assert [a for a in tag_list] == [] mem, addr = build_tag_list( - FOO_TAG, 12, CommonTags.TAG_IGNORE, 0, BAR_TAG, 13, CommonTags.TAG_DONE, 0 + MyTag.FOO_TAG, + 12, + CommonTag.TAG_IGNORE, + 0, + MyTag.BAR_TAG, + 13, + CommonTag.TAG_DONE, + 0, ) tag_list = TagList(mem, addr) assert len(tag_list) == 2 - assert [a for a in tag_list] == [Tag(mem, 0x10), Tag(mem, 0x20)] - assert tag_list.to_list() == [(FOO_TAG, 12), (BAR_TAG, 13)] + assert [a for a in tag_list] == [TagItem(mem, 0x10), TagItem(mem, 0x20)] + assert tag_list.to_list() == [(MyTag.FOO_TAG, 12), (MyTag.BAR_TAG, 13)] # --- TAG_MORE --- def libtypes_tag_more_test(): - mem, addr = build_tag_list(CommonTags.TAG_MORE, 0x40, CommonTags.TAG_DONE, 0) - build_tag_list(CommonTags.TAG_DONE, 0, mem=mem, base=0x40) + mem, addr = build_tag_list(CommonTag.TAG_MORE, 0x40, CommonTag.TAG_DONE, 0) + build_tag_list(CommonTag.TAG_DONE, 0, mem=mem, base=0x40) # check tag - tag = Tag(mem, addr) - assert tag.tag.val == CommonTags.TAG_MORE + tag = TagItem(mem, addr) + assert tag.tag.val == CommonTag.TAG_MORE assert tag.data.val == 0x40 - assert tag.get_tuple() == (CommonTags.TAG_MORE, 0x40) + assert tag.get_tuple() == (CommonTag.TAG_MORE, 0x40) # no "real" tag assert tag.next_real_tag() is None - assert tag.succ_tag() == Tag(mem, 0x40) + assert tag.succ_tag() == TagItem(mem, 0x40) assert tag.succ_real_tag() is None def libtypes_tag_list_more_test(): - mem, addr = build_tag_list(CommonTags.TAG_MORE, 0x40, CommonTags.TAG_DONE, 0) - build_tag_list(CommonTags.TAG_DONE, 0, mem=mem, base=0x40) + mem, addr = build_tag_list(CommonTag.TAG_MORE, 0x40, CommonTag.TAG_DONE, 0) + build_tag_list(CommonTag.TAG_DONE, 0, mem=mem, base=0x40) tag_list = TagList(mem, addr) assert len(tag_list) == 0 assert [a for a in tag_list] == [] mem, addr = build_tag_list( - FOO_TAG, 12, CommonTags.TAG_MORE, 0x40, CommonTags.TAG_DONE, 0 + MyTag.FOO_TAG, 12, CommonTag.TAG_MORE, 0x40, CommonTag.TAG_DONE, 0 ) - build_tag_list(BAR_TAG, 13, CommonTags.TAG_DONE, 0, mem=mem, base=0x40) + build_tag_list(MyTag.BAR_TAG, 13, CommonTag.TAG_DONE, 0, mem=mem, base=0x40) tag_list = TagList(mem, addr) assert len(tag_list) == 2 - assert [a for a in tag_list] == [Tag(mem, 0x10), Tag(mem, 0x40)] - assert tag_list.to_list() == [(FOO_TAG, 12), (BAR_TAG, 13)] + assert [a for a in tag_list] == [TagItem(mem, 0x10), TagItem(mem, 0x40)] + assert tag_list.to_list() == [(MyTag.FOO_TAG, 12), (MyTag.BAR_TAG, 13)] # --- TAG_SKIP --- @@ -113,48 +123,48 @@ def libtypes_tag_list_more_test(): def libtypes_tag_skip_test(): mem, addr = build_tag_list( - CommonTags.TAG_SKIP, + CommonTag.TAG_SKIP, 2, - FOO_TAG, + MyTag.FOO_TAG, 12, - BAR_TAG, + MyTag.BAR_TAG, 13, - BAZ_TAG, + MyTag.BAZ_TAG, 14, - CommonTags.TAG_DONE, + CommonTag.TAG_DONE, 0, ) # check tag - tag = Tag(mem, addr) - assert tag.tag.val == CommonTags.TAG_SKIP + tag = TagItem(mem, addr) + assert tag.tag.val == CommonTag.TAG_SKIP assert tag.data.val == 2 - assert tag.get_tuple() == (CommonTags.TAG_SKIP, 2) + assert tag.get_tuple() == (CommonTag.TAG_SKIP, 2) # no "real" tag - assert tag.next_real_tag() == Tag(mem, 0x28) - assert tag.succ_tag() == Tag(mem, 0x28) - assert tag.succ_real_tag() == Tag(mem, 0x28) + assert tag.next_real_tag() == TagItem(mem, 0x28) + assert tag.succ_tag() == TagItem(mem, 0x28) + assert tag.succ_real_tag() == TagItem(mem, 0x28) def libtypes_tag_skip_more_test(): mem, addr = build_tag_list( - CommonTags.TAG_SKIP, + CommonTag.TAG_SKIP, 2, - FOO_TAG, + MyTag.FOO_TAG, 12, - BAR_TAG, + MyTag.BAR_TAG, 13, - BAZ_TAG, + MyTag.BAZ_TAG, 14, - CommonTags.TAG_DONE, + CommonTag.TAG_DONE, 0, ) tag_list = TagList(mem, addr) assert len(tag_list) == 1 - assert [a for a in tag_list] == [Tag(mem, 0x28)] - assert tag_list.to_list() == [(BAZ_TAG, 14)] + assert [a for a in tag_list] == [TagItem(mem, 0x28)] + assert tag_list.to_list() == [(MyTag.BAZ_TAG, 14)] -# --- alloc tag list +# --- alloc tag list --- def libtypes_tag_alloc_empty_test(): @@ -170,8 +180,91 @@ def libtypes_tag_alloc_empty_test(): def libtypes_tag_alloc_test(): mem = MockMemory() alloc = MemoryAlloc(mem) - tl = TagList.alloc(alloc, (FOO_TAG, 1), (BAR_TAG, 2)) + tl = TagList.alloc(alloc, (MyTag.FOO_TAG, 1), (MyTag.BAR_TAG, 2)) assert len(tl) == 2 - assert tl.to_list() == [(FOO_TAG, 1), (BAR_TAG, 2)] + assert tl.to_list() == [(MyTag.FOO_TAG, 1), (MyTag.BAR_TAG, 2)] tl.free() assert alloc.is_all_free() + + +# --- tag ops --- + + +def libtypes_tag_get_set_test(): + mem, addr = build_tag_list( + MyTag.FOO_TAG, + 12, + MyTag.BAR_TAG, + 13, + ) + tag = TagItem(mem, addr) + assert tag.get_tag() == MyTag.FOO_TAG + assert tag.get_tag(map_enum=MyTag) is MyTag.FOO_TAG + assert tag.get_data() == 12 + tag.set_tag(MyTag.BAZ_TAG) + assert tag.get_tag() == MyTag.BAZ_TAG + tag.set_data(21) + assert tag.get_data() == 21 + # test control tags + tag.set_tag(CommonTag.TAG_IGNORE) + assert tag.get_tag() is CommonTag.TAG_IGNORE + assert tag.get_tag(do_map=False) == CommonTag.TAG_IGNORE + + +# --- tag list ops --- + + +def libtypes_tag_list_find_test(): + mem, addr = build_tag_list( + MyTag.FOO_TAG, + 12, + MyTag.BAR_TAG, + 13, + ) + tl = TagList(mem, addr) + tag = tl.find_tag(MyTag.BAZ_TAG) + assert tag is None + tag = tl.find_tag(MyTag.FOO_TAG) + assert tag == TagItem(mem, addr) + # find by tag + tag = TagItem(mem, addr) + assert tl.find_tag(tag) == TagItem(mem, addr) + + +def libtypes_tag_list_set_test(): + mem, addr = build_tag_list( + MyTag.FOO_TAG, + 12, + MyTag.BAR_TAG, + 13, + ) + tl = TagList(mem, addr) + assert not tl.set_tag(MyTag.BAZ_TAG, 20) + assert tl.set_tag(MyTag.FOO_TAG, 20) + tag = TagItem(mem, addr) + assert tag.data.val == 20 + + +def libtypes_tag_list_delete_test(): + mem, addr = build_tag_list( + MyTag.FOO_TAG, + 12, + MyTag.BAR_TAG, + 13, + ) + tl = TagList(mem, addr) + assert not tl.delete_tag(MyTag.BAZ_TAG) + assert tl.delete_tag(MyTag.FOO_TAG) + assert tl.to_list() == [(MyTag.BAR_TAG, 13)] + + +def libtypes_tag_list_get_tag_data__test(): + mem, addr = build_tag_list( + MyTag.FOO_TAG, + 12, + MyTag.BAR_TAG, + 13, + ) + tl = TagList(mem, addr) + assert tl.get_tag_data(MyTag.BAZ_TAG, 42) == 42 + assert tl.get_tag_data(MyTag.FOO_TAG, 42) == 12