From d9defbc08c7f6258baddfce311869b5d850968f9 Mon Sep 17 00:00:00 2001 From: Timofey X Date: Thu, 8 Feb 2024 19:07:46 +0700 Subject: [PATCH] [cocas] Move exception class declarations into modules --- cocas/assembler/__init__.py | 1 + cocas/assembler/ast_builder.py | 10 ++--- cocas/assembler/code_block.py | 5 ++- cocas/{error.py => assembler/exceptions.py} | 29 ++------------ cocas/assembler/macro_processor.py | 6 +-- cocas/assembler/object_generator.py | 2 +- .../targets/abstract_code_segments.py | 5 ++- .../assembler/targets/cdm16/code_segments.py | 4 +- .../targets/cdm16/target_instructions.py | 13 +++--- cocas/assembler/targets/cdm8/code_segments.py | 4 +- .../targets/cdm8/target_instructions.py | 13 +++--- .../assembler/targets/cdm8e/code_segments.py | 8 ++-- .../targets/cdm8e/target_instructions.py | 5 +-- cocas/exception_handlers.py | 35 ++++++++++++++++ cocas/linker/__init__.py | 1 + cocas/linker/exceptions.py | 3 ++ cocas/linker/linker.py | 3 +- cocas/main.py | 15 ++----- cocas/object_file/__init__.py | 1 + cocas/object_file/exceptions.py | 21 ++++++++++ cocas/object_file/object_import.py | 40 ++++++++----------- 21 files changed, 125 insertions(+), 99 deletions(-) rename cocas/{error.py => assembler/exceptions.py} (53%) create mode 100644 cocas/exception_handlers.py create mode 100644 cocas/linker/exceptions.py create mode 100644 cocas/object_file/exceptions.py diff --git a/cocas/assembler/__init__.py b/cocas/assembler/__init__.py index 2fedf40..62e615c 100644 --- a/cocas/assembler/__init__.py +++ b/cocas/assembler/__init__.py @@ -1,5 +1,6 @@ from .assembler import assemble_files, assemble_module from .ast_builder import build_ast +from .exceptions import CdmAssemblerException from .macro_processor import process_macros from .object_generator import generate_object_module from .targets import import_target, list_assembler_targets diff --git a/cocas/assembler/ast_builder.py b/cocas/assembler/ast_builder.py index a0976e7..3e32c23 100644 --- a/cocas/assembler/ast_builder.py +++ b/cocas/assembler/ast_builder.py @@ -3,7 +3,6 @@ from antlr4 import CommonTokenStream, InputStream -from cocas.error import AntlrErrorListener, CdmException, CdmExceptionTag from cocas.object_module import CodeLocation from .ast_nodes import ( @@ -25,6 +24,7 @@ UntilLoopNode, WhileLoopNode, ) +from .exceptions import AntlrErrorListener, CdmAssemblerException, CdmExceptionTag from .generated import AsmLexer, AsmParser, AsmParserVisitor @@ -126,8 +126,8 @@ def visitConnective_condition(self, ctx: AsmParser.Connective_conditionContext): cond = self.visitCondition(ctx.condition()) cond.conjunction = ctx.conjunction().getText() if cond.conjunction != 'and' and cond.conjunction != 'or': - raise CdmException(CdmExceptionTag.ASM, self.source_path, ctx.start.line - self.line_offset, - 'Expected "and" or "or" in compound condition') + raise CdmAssemblerException(CdmExceptionTag.ASM, self.source_path, ctx.start.line - self.line_offset, + 'Expected "and" or "or" in compound condition') return cond def visitCondition(self, ctx: AsmParser.ConditionContext): @@ -218,8 +218,8 @@ def visitStandaloneLabel(self, ctx: AsmParser.StandaloneLabelContext) -> LabelDe label_decl = self.visitLabel_declaration(ctx.label_declaration()) label_decl.external = ctx.Ext() is not None if label_decl.entry and label_decl.external: - raise CdmException(CdmExceptionTag.ASM, self.source_path, ctx.start.line - self.line_offset, - f'Label {label_decl.label.name} cannot be both external and entry') + raise CdmAssemblerException(CdmExceptionTag.ASM, self.source_path, ctx.start.line - self.line_offset, + f'Label {label_decl.label.name} cannot be both external and entry') return label_decl def visitLabel_declaration(self, ctx: AsmParser.Label_declarationContext) -> LabelDeclarationNode: diff --git a/cocas/assembler/code_block.py b/cocas/assembler/code_block.py index f23e6ae..535e2a8 100644 --- a/cocas/assembler/code_block.py +++ b/cocas/assembler/code_block.py @@ -1,7 +1,6 @@ from dataclasses import dataclass from typing import Any, Callable, Type -from cocas.error import CdmException, CdmExceptionTag, CdmTempException from cocas.object_module import CodeLocation, ObjectSectionRecord from .ast_nodes import ( @@ -17,6 +16,7 @@ UntilLoopNode, WhileLoopNode, ) +from .exceptions import CdmAssemblerException, CdmExceptionTag, CdmTempException from .targets import ICodeSegment, TargetInstructionsInterface @@ -39,7 +39,8 @@ def __init__(self, address: int, lines: list, target_instructions: Type[TargetIn target_instructions.finish(temp_storage) except CdmTempException as e: # if it isn't ok, must be at least one line - raise CdmException(CdmExceptionTag.ASM, lines[-1].location.file, lines[-1].location.line, e.message) + raise CdmAssemblerException(CdmExceptionTag.ASM, lines[-1].location.file, + lines[-1].location.line, e.message) def append_label(self, label_name): self.labels[label_name] = self.address + self.size diff --git a/cocas/error.py b/cocas/assembler/exceptions.py similarity index 53% rename from cocas/error.py rename to cocas/assembler/exceptions.py index a5fd3d1..6546d9a 100644 --- a/cocas/error.py +++ b/cocas/assembler/exceptions.py @@ -1,8 +1,6 @@ from enum import Enum -from typing import Union from antlr4.error.ErrorListener import ErrorListener -from colorama import Fore, Style from cocas.assembler.generated import AsmParser @@ -10,8 +8,6 @@ class CdmExceptionTag(Enum): MACRO = "Macro" ASM = "Assembler" - OBJ = "Object files" - LINK = "Linker" # this exception should be used when we don't know code location now, @@ -23,32 +19,13 @@ def __init__(self, message: str): self.message = message -class CdmLinkException(Exception): - def __init__(self, message: str): - self.message = message - - -class CdmException(Exception): - def __init__(self, tag: Union[str, CdmExceptionTag], file: str, line: int, description: str): - if isinstance(tag, CdmExceptionTag): - tag = tag.value +class CdmAssemblerException(Exception): + def __init__(self, tag: CdmExceptionTag, file: str, line: int, description: str): self.tag = tag self.file = file self.line = line self.description = description - def log(self): - print( - f'[{self.tag}] {Fore.RED}ERROR{Fore.RESET} at line {Style.BRIGHT}{self.line}{Style.RESET_ALL} of ' - f'{Style.BRIGHT}{self.file}{Style.RESET_ALL}') - print(f'{self.description}') - - -def log_error(tag: str, message: str): - print( - f'[{tag}] {Fore.RED}ERROR{Fore.RESET}') - print(message) - class AntlrErrorListener(ErrorListener): def __init__(self, tag, file): @@ -59,4 +36,4 @@ def syntaxError(self, recognizer, offending_symbol, line, column, msg, e): if isinstance(recognizer, AsmParser): line = line - recognizer.current_offset self.file = recognizer.current_file - raise CdmException(self.tag, self.file, line, msg) + raise CdmAssemblerException(self.tag, self.file, line, msg) diff --git a/cocas/assembler/macro_processor.py b/cocas/assembler/macro_processor.py index 4be3fcc..61f07ac 100644 --- a/cocas/assembler/macro_processor.py +++ b/cocas/assembler/macro_processor.py @@ -7,9 +7,9 @@ from antlr4 import CommonTokenStream, FileStream, InputStream from antlr4.TokenStreamRewriter import TokenStreamRewriter -from cocas.error import AntlrErrorListener, CdmException, CdmExceptionTag, CdmTempException from cocas.object_module import CodeLocation +from .exceptions import AntlrErrorListener, CdmAssemblerException, CdmExceptionTag, CdmTempException from .generated import MacroLexer, MacroParser, MacroVisitor @@ -182,7 +182,7 @@ def visitMlb(self, ctx: MacroParser.MlbContext): try: self.add_macro(self.visitMlb_macro(child)) except CdmTempException as e: - raise CdmException(CdmExceptionTag.MACRO, self.filepath, child.start.line, e.message) + raise CdmAssemblerException(CdmExceptionTag.MACRO, self.filepath, child.start.line, e.message) return self.macros def visitProgram(self, ctx: MacroParser.ProgramContext): @@ -205,7 +205,7 @@ def visitProgram(self, ctx: MacroParser.ProgramContext): self.rewriter.insertBeforeToken(child.start, expanded_text) self.rewriter.delete(self.rewriter.DEFAULT_PROGRAM_NAME, child.start, child.stop) except CdmTempException as e: - raise CdmException(CdmExceptionTag.MACRO, self.filepath, child.start.line, e.message) + raise CdmAssemblerException(CdmExceptionTag.MACRO, self.filepath, child.start.line, e.message) def visitMacro(self, ctx: MacroParser.MacroContext): header = ctx.macro_header() diff --git a/cocas/assembler/object_generator.py b/cocas/assembler/object_generator.py index 4ccde45..145cd8c 100644 --- a/cocas/assembler/object_generator.py +++ b/cocas/assembler/object_generator.py @@ -2,11 +2,11 @@ from typing import Type from cocas.assembler.targets import IVaryingLengthSegment -from cocas.error import CdmExceptionTag from cocas.object_module import CodeLocation, ObjectModule from .ast_nodes import InstructionNode, LabelDeclarationNode, ProgramNode, TemplateSectionNode from .code_block import Section +from .exceptions import CdmExceptionTag from .targets import TargetInstructionsInterface TAG = CdmExceptionTag.ASM diff --git a/cocas/assembler/targets/abstract_code_segments.py b/cocas/assembler/targets/abstract_code_segments.py index 290c665..af26219 100644 --- a/cocas/assembler/targets/abstract_code_segments.py +++ b/cocas/assembler/targets/abstract_code_segments.py @@ -2,9 +2,10 @@ from math import lcm from typing import TYPE_CHECKING -from cocas.error import CdmException, CdmExceptionTag from cocas.object_module import CodeLocation +from ..exceptions import CdmAssemblerException, CdmExceptionTag + if TYPE_CHECKING: from cocas.object_module import ObjectSectionRecord @@ -97,4 +98,4 @@ def fill(self, object_record: "ObjectSectionRecord", section: "Section", labels: def _error(segment: ICodeSegment, message: str): - raise CdmException(CdmExceptionTag.ASM, segment.location.file, segment.location.line, message) + raise CdmAssemblerException(CdmExceptionTag.ASM, segment.location.file, segment.location.line, message) diff --git a/cocas/assembler/targets/cdm16/code_segments.py b/cocas/assembler/targets/cdm16/code_segments.py index d1bcaa9..0602a0f 100644 --- a/cocas/assembler/targets/cdm16/code_segments.py +++ b/cocas/assembler/targets/cdm16/code_segments.py @@ -4,10 +4,10 @@ import bitstruct -from cocas.error import CdmException, CdmExceptionTag from cocas.object_module import CodeLocation, ExternalEntry from ...ast_nodes import LabelNode, RegisterNode, RelocatableExpressionNode, TemplateFieldNode +from ...exceptions import CdmAssemblerException, CdmExceptionTag from .. import IAlignedSegment, IAlignmentPaddingSegment, ICodeSegment, IVaryingLengthSegment if TYPE_CHECKING: @@ -22,7 +22,7 @@ def pack(fmt, *args): def _error(segment: ICodeSegment, message: str): - raise CdmException(CdmExceptionTag.ASM, segment.location.file, segment.location.line, message) + raise CdmAssemblerException(CdmExceptionTag.ASM, segment.location.file, segment.location.line, message) class CodeSegment(ICodeSegment, ABC): diff --git a/cocas/assembler/targets/cdm16/target_instructions.py b/cocas/assembler/targets/cdm16/target_instructions.py index 4e70cbf..6486cf6 100644 --- a/cocas/assembler/targets/cdm16/target_instructions.py +++ b/cocas/assembler/targets/cdm16/target_instructions.py @@ -3,9 +3,8 @@ from dataclasses import dataclass from typing import Callable, Union, get_args, get_origin -from cocas.error import CdmException, CdmExceptionTag, CdmTempException - from ...ast_nodes import InstructionNode, LabelNode, RegisterNode, RelocatableExpressionNode +from ...exceptions import CdmAssemblerException, CdmExceptionTag, CdmTempException from .. import ICodeSegment, TargetInstructionsInterface from .code_segments import ( AlignmentPaddingSegment, @@ -57,10 +56,10 @@ def assemble_instruction(line: InstructionNode, temp_storage: dict) -> list[ICod return h.handler(line, temp_storage, h.instructions[line.mnemonic]) if line.mnemonic.startswith('b'): return TargetInstructions.branch(line) - raise CdmException(CdmExceptionTag.ASM, line.location.file, line.location.line, - f'Unknown instruction "{line.mnemonic}"') + raise CdmAssemblerException(CdmExceptionTag.ASM, line.location.file, line.location.line, + f'Unknown instruction "{line.mnemonic}"') except CdmTempException as e: - raise CdmException(CdmExceptionTag.ASM, line.location.file, line.location.line, e.message) + raise CdmAssemblerException(CdmExceptionTag.ASM, line.location.file, line.location.line, e.message) @staticmethod def finish(temp_storage: dict): @@ -185,8 +184,8 @@ def branch(line: InstructionNode, inverse=False) -> list[ICodeSegment]: branch_code = pair.inv_code if not inverse else pair.code break else: - raise CdmException(CdmExceptionTag.ASM, line.location.file, line.location.line, - f'Invalid branch condition: {cond}') + raise CdmAssemblerException(CdmExceptionTag.ASM, line.location.file, line.location.line, + f'Invalid branch condition: {cond}') assert_count_args(line.arguments, RelocatableExpressionNode) return [Branch(line.location, branch_code, line.arguments[0])] diff --git a/cocas/assembler/targets/cdm8/code_segments.py b/cocas/assembler/targets/cdm8/code_segments.py index d69f0c5..18344c6 100644 --- a/cocas/assembler/targets/cdm8/code_segments.py +++ b/cocas/assembler/targets/cdm8/code_segments.py @@ -2,10 +2,10 @@ from dataclasses import dataclass, field from typing import TYPE_CHECKING -from cocas.error import CdmException, CdmExceptionTag from cocas.object_module import CodeLocation, ExternalEntry from ...ast_nodes import LabelNode, RelocatableExpressionNode, TemplateFieldNode +from ...exceptions import CdmAssemblerException, CdmExceptionTag from .. import IAlignmentPaddingSegment, ICodeSegment if TYPE_CHECKING: @@ -14,7 +14,7 @@ def _error(segment: ICodeSegment, message: str): - raise CdmException(CdmExceptionTag.ASM, segment.location.file, segment.location.line, message) + raise CdmAssemblerException(CdmExceptionTag.ASM, segment.location.file, segment.location.line, message) # noinspection DuplicatedCode diff --git a/cocas/assembler/targets/cdm8/target_instructions.py b/cocas/assembler/targets/cdm8/target_instructions.py index db89103..704e963 100644 --- a/cocas/assembler/targets/cdm8/target_instructions.py +++ b/cocas/assembler/targets/cdm8/target_instructions.py @@ -4,9 +4,8 @@ from bitstruct import pack -from cocas.error import CdmException, CdmExceptionTag, CdmTempException - from ...ast_nodes import InstructionNode, LabelNode, RegisterNode, RelocatableExpressionNode +from ...exceptions import CdmAssemblerException, CdmExceptionTag, CdmTempException from .. import ICodeSegment, TargetInstructionsInterface from .code_segments import AlignmentPaddingSegment, BytesSegment, ExpressionSegment @@ -49,10 +48,10 @@ def assemble_instruction(line: InstructionNode, temp_storage: dict) -> list[ICod return h.handler(line, temp_storage, h.instructions[line.mnemonic]) if line.mnemonic.startswith('b'): return TargetInstructions.branch(line) - raise CdmException(CdmExceptionTag.ASM, line.location.file, line.location.line, - f'Unknown instruction "{line.mnemonic}"') + raise CdmAssemblerException(CdmExceptionTag.ASM, line.location.file, line.location.line, + f'Unknown instruction "{line.mnemonic}"') except CdmTempException as e: - raise CdmException(CdmExceptionTag.ASM, line.location.file, line.location.line, e.message) + raise CdmAssemblerException(CdmExceptionTag.ASM, line.location.file, line.location.line, e.message) @staticmethod def finish(temp_storage: dict): @@ -156,8 +155,8 @@ def branch(line: InstructionNode, inverse=False) -> list[ICodeSegment]: branch_code = pair.inv_code if not inverse else pair.code break else: - raise CdmException(CdmExceptionTag.ASM, line.location.file, line.location.line, - f'Invalid branch condition: {cond}') + raise CdmAssemblerException(CdmExceptionTag.ASM, line.location.file, line.location.line, + f'Invalid branch condition: {cond}') assert_count_args(line.arguments, RelocatableExpressionNode) return [BytesSegment(pack('u4u4', 0xE, branch_code), line.location), ExpressionSegment(line.arguments[0], line.location)] diff --git a/cocas/assembler/targets/cdm8e/code_segments.py b/cocas/assembler/targets/cdm8e/code_segments.py index e6522a7..d738b09 100644 --- a/cocas/assembler/targets/cdm8e/code_segments.py +++ b/cocas/assembler/targets/cdm8e/code_segments.py @@ -2,10 +2,10 @@ from dataclasses import dataclass, field from typing import TYPE_CHECKING -from cocas.error import CdmException, CdmExceptionTag from cocas.object_module import CodeLocation, ExternalEntry from ...ast_nodes import LabelNode, RelocatableExpressionNode, TemplateFieldNode +from ...exceptions import CdmAssemblerException, CdmExceptionTag from .. import ICodeSegment, IVaryingLengthSegment from .simple_instructions import simple_instructions @@ -178,10 +178,10 @@ def update_varying_length(self, pos: int, section: "Section", labels: dict[str, if label_name in labels: labels[label_name] += shift_length return shift_length - except CdmException as e: + except CdmAssemblerException as e: raise e except Exception as e: - raise CdmException(TAG, self.location.file, self.location.line, str(e)) + raise CdmAssemblerException(TAG, self.location.file, self.location.line, str(e)) def fill(self, object_record: "ObjectSectionRecord", section: "Section", labels: dict[str, int], templates: dict[str, dict[str, int]]): @@ -201,7 +201,7 @@ def fill(self, object_record: "ObjectSectionRecord", section: "Section", labels: def _error(segment: ICodeSegment, message: str): - raise CdmException(TAG, segment.location.file, segment.location.line, message) + raise CdmAssemblerException(TAG, segment.location.file, segment.location.line, message) def eval_rel_expr_seg(seg: RelocatableExpressionSegment, s: "Section", diff --git a/cocas/assembler/targets/cdm8e/target_instructions.py b/cocas/assembler/targets/cdm8e/target_instructions.py index e5f0828..85abfb1 100644 --- a/cocas/assembler/targets/cdm8e/target_instructions.py +++ b/cocas/assembler/targets/cdm8e/target_instructions.py @@ -2,9 +2,8 @@ import bitstruct -from cocas.error import CdmException, CdmExceptionTag, CdmTempException - from ...ast_nodes import InstructionNode, LabelNode, RegisterNode, RelocatableExpressionNode +from ...exceptions import CdmAssemblerException, CdmExceptionTag, CdmTempException from .. import ICodeSegment, TargetInstructionsInterface from .code_segments import ( BytesSegment, @@ -54,7 +53,7 @@ def assemble_instruction(line: InstructionNode, temp_storage) \ segment.location = line.location return segments except CdmTempException as e: - raise CdmException(CdmExceptionTag.ASM, line.location.file, line.location.line, e.message) + raise CdmAssemblerException(CdmExceptionTag.ASM, line.location.file, line.location.line, e.message) @staticmethod def finish(temp_storage: dict): diff --git a/cocas/exception_handlers.py b/cocas/exception_handlers.py new file mode 100644 index 0000000..e216c43 --- /dev/null +++ b/cocas/exception_handlers.py @@ -0,0 +1,35 @@ +from colorama import Fore, Style + +from cocas.assembler import CdmAssemblerException +from cocas.linker import CdmLinkException +from cocas.object_file import CdmObjectFileException + + +def log_exception(tag: str, message: str): + print(f'[{tag}] {Fore.RED}ERROR{Fore.RESET}') + print(message) + + +def log_os_error(e: OSError): + message = e.strerror + if e.filename is not None: + message += f': {Style.BRIGHT}{e.filename}{Style.NORMAL}' + log_exception("Main", message) + exit(1) + + +def log_asm_exception(e: CdmAssemblerException): + print(f'[{e.tag.value}] {Fore.RED}ERROR{Fore.RESET} at line {Style.BRIGHT}{e.line}{Style.RESET_ALL} of ' + f'{Style.BRIGHT}{e.file}{Style.RESET_ALL}') + print(f'{e.description}') + + +def log_object_file_exception(e: CdmObjectFileException): + print(f'[Object file] {Fore.RED}ERROR{Fore.RESET} at line {Style.BRIGHT}{e.line}{Style.RESET_ALL} of ' + f'{Style.BRIGHT}{e.file}{Style.RESET_ALL}') + print(f'{e.description}') + + +def log_link_exception(_: CdmLinkException): + # todo: find this code from previous revisions + pass diff --git a/cocas/linker/__init__.py b/cocas/linker/__init__.py index 394d7f7..03a5985 100644 --- a/cocas/linker/__init__.py +++ b/cocas/linker/__init__.py @@ -1,3 +1,4 @@ from .debug_export import debug_export, write_debug_export +from .exceptions import CdmLinkException from .image import write_image from .linker import link diff --git a/cocas/linker/exceptions.py b/cocas/linker/exceptions.py new file mode 100644 index 0000000..7387a12 --- /dev/null +++ b/cocas/linker/exceptions.py @@ -0,0 +1,3 @@ +class CdmLinkException(Exception): + def __init__(self, message: str): + self.message = message diff --git a/cocas/linker/linker.py b/cocas/linker/linker.py index 1c6c9c5..5aed8d8 100644 --- a/cocas/linker/linker.py +++ b/cocas/linker/linker.py @@ -1,9 +1,10 @@ import itertools from typing import Any -from cocas.error import CdmLinkException from cocas.object_module import CodeLocation, ObjectModule, ObjectSectionRecord +from .exceptions import CdmLinkException + def init_bins(asects: list[ObjectSectionRecord]): rsect_bins = [] diff --git a/cocas/main.py b/cocas/main.py index 9276cfc..e23a587 100755 --- a/cocas/main.py +++ b/cocas/main.py @@ -5,18 +5,11 @@ import colorama from cocas.assembler import assemble_files, list_assembler_targets -from cocas.error import CdmException, log_error +from cocas.assembler.exceptions import CdmAssemblerException from cocas.linker import link, write_debug_export, write_image from cocas.object_file import list_object_targets, read_object_files, write_object_file from cocas.object_module import ObjectModule - - -def handle_os_error(e: OSError): - message = e.strerror - if e.filename is not None: - message += f': {colorama.Style.BRIGHT}{e.filename}{colorama.Style.NORMAL}' - log_error("MAIN", message) - exit(1) +from cocas import exception_handlers as handlers def main(): @@ -95,8 +88,8 @@ def main(): objects += assemble_files(target, [filepath], bool(args.debug), relative_path, absolute_path, realpath) - except CdmException as e: - e.log() + except CdmAssemblerException as e: + handlers.log_asm_exception(e) return 1 if args.merge: diff --git a/cocas/object_file/__init__.py b/cocas/object_file/__init__.py index d357e6d..d9941f8 100644 --- a/cocas/object_file/__init__.py +++ b/cocas/object_file/__init__.py @@ -1,3 +1,4 @@ +from .exceptions import CdmObjectFileException from .object_export import export_object, write_object_file from .object_import import import_object, read_object_files from .targets import list_object_targets diff --git a/cocas/object_file/exceptions.py b/cocas/object_file/exceptions.py new file mode 100644 index 0000000..cf0e556 --- /dev/null +++ b/cocas/object_file/exceptions.py @@ -0,0 +1,21 @@ +from antlr4.error.ErrorListener import ErrorListener + +from cocas.assembler.generated import AsmParser + + +class CdmObjectFileException(Exception): + def __init__(self, file: str, line: int, description: str): + self.file = file + self.line = line + self.description = description + + +class AntlrErrorListener(ErrorListener): + def __init__(self, file): + self.file = file + + def syntaxError(self, recognizer, offending_symbol, line, column, msg, e): + if isinstance(recognizer, AsmParser): + line = line - recognizer.current_offset + self.file = recognizer.current_file + raise CdmObjectFileException(self.file, line, msg) diff --git a/cocas/object_file/object_import.py b/cocas/object_file/object_import.py index 02f9116..f93e3f9 100644 --- a/cocas/object_file/object_import.py +++ b/cocas/object_file/object_import.py @@ -6,9 +6,9 @@ import antlr4 from antlr4 import CommonTokenStream, InputStream -from cocas.error import AntlrErrorListener, CdmException, CdmExceptionTag from cocas.object_module import CodeLocation, ExternalEntry, ObjectModule, ObjectSectionRecord +from .exceptions import AntlrErrorListener, CdmObjectFileException from .generated.ObjectFileLexer import ObjectFileLexer from .generated.ObjectFileParser import ObjectFileParser from .generated.ObjectFileParserVisitor import ObjectFileParserVisitor @@ -28,14 +28,14 @@ def visitObject_file(self, ctx: ObjectFileParser.Object_fileContext) -> list[Obj header = self.visitTarg_record(ctx.targ_record()) if header != exp_header: if exp_header: - raise CdmException(CdmExceptionTag.OBJ, self.file, ctx.start.line, - f'Wrong target header {header}, expected {exp_header}') + raise CdmObjectFileException(self.file, ctx.start.line, + f'Wrong target header {header}, expected {exp_header}') else: - raise CdmException(CdmExceptionTag.OBJ, self.file, ctx.start.line, - f'Expected no header for {target_name} target, got {header}') + raise CdmObjectFileException(self.file, ctx.start.line, + f'Expected no header for {target_name} target, got {header}') elif exp_header: - raise CdmException(CdmExceptionTag.OBJ, self.file, ctx.start.line, - f'Expected non-empty target header for {target_name}, got empty') + raise CdmObjectFileException(self.file, ctx.start.line, + f'Expected non-empty target header for {target_name}, got empty') modules = [] for i in ctx.object_block(): @@ -57,8 +57,7 @@ def visitObject_block(self, ctx: ObjectFileParser.Object_blockContext) -> Object for block in ctx.rsect_block(): name, rsect = self.visitRsect_block(block) if name in rsects: - raise CdmException(CdmExceptionTag.OBJ, self.file, block.start.line, - f'Repeating section: {name}') + raise CdmObjectFileException(self.file, block.start.line, f'Repeating section: {name}') rsects[name] = rsect xtrn: ObjectFileParser.Xtrn_recordContext @@ -67,16 +66,15 @@ def visitObject_block(self, ctx: ObjectFileParser.Object_blockContext) -> Object for sect, entry in entries: if sect == '$abs': if not asects: - raise CdmException(CdmExceptionTag.OBJ, self.file, xtrn.start.line, - 'No absolute sections found, but needed for xtrn entry') + raise CdmObjectFileException(self.file, xtrn.start.line, + 'No absolute sections found, but needed for xtrn entry') # what is this? ind = max(bisect.bisect_right(asect_addr, entry.offset) - 1, 0) asects[asect_addr[ind]].external[label].append(entry) elif sect in rsects: rsects[sect].external[label].append(entry) else: - raise CdmException(CdmExceptionTag.OBJ, self.file, xtrn.start.line, - f'Section not found: {sect}') + raise CdmObjectFileException(self.file, xtrn.start.line, f'Section not found: {sect}') if filename: f = Path(filename) for i in (asects | rsects).values(): @@ -174,11 +172,9 @@ def parse_byte(self, byte: str, ctx: ObjectFileParser.DataContext): try: value = int(byte, 16) except ValueError: - raise CdmException(CdmExceptionTag.OBJ, self.file, ctx.start.line, - f'Not a hex number: {byte}') + raise CdmObjectFileException(self.file, ctx.start.line, f'Not a hex number: {byte}') if not 0 <= value <= 255: - raise CdmException(CdmExceptionTag.OBJ, self.file, ctx.start.line, - f'To big hex number: {byte}, expected byte') + raise CdmObjectFileException(self.file, ctx.start.line, f'To big hex number: {byte}, expected byte') return value def visitData(self, ctx: ObjectFileParser.DataContext): @@ -188,15 +184,13 @@ def visitAbs_address(self, ctx: ObjectFileParser.Abs_addressContext): try: return int(ctx.getText(), 16) except ValueError: - raise CdmException(CdmExceptionTag.OBJ, self.file, ctx.start.line, - f'Not a hex number: {ctx.getText()}') + raise CdmObjectFileException(self.file, ctx.start.line, f'Not a hex number: {ctx.getText()}') def visitNumber(self, ctx: ObjectFileParser.NumberContext): try: return int(ctx.getText(), 16) except ValueError: - raise CdmException(CdmExceptionTag.OBJ, self.file, ctx.start.line, - f'Not a hex number: {ctx.getText()}') + raise CdmObjectFileException(self.file, ctx.start.line, f'Not a hex number: {ctx.getText()}') def visitEntry_usage(self, ctx: ObjectFileParser.Entry_usageContext): addr = self.visitNumber(ctx.number()) @@ -229,12 +223,12 @@ def import_object(input_stream: InputStream, filepath: Path, str_path = filepath.absolute().as_posix() lexer = ObjectFileLexer(input_stream) lexer.removeErrorListeners() - lexer.addErrorListener(AntlrErrorListener(CdmExceptionTag.OBJ, str_path)) + lexer.addErrorListener(AntlrErrorListener(str_path)) token_stream = CommonTokenStream(lexer) token_stream.fill() parser = ObjectFileParser(token_stream) parser.removeErrorListeners() - parser.addErrorListener(AntlrErrorListener(CdmExceptionTag.OBJ, str_path)) + parser.addErrorListener(AntlrErrorListener(str_path)) ctx = parser.object_file() visitor = ImportObjectFileVisitor(str_path, target) result = visitor.visit(ctx)