aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s+removethis@s-ol.nu>2021-05-22 16:23:57 +0000
committers-ol <s+removethis@s-ol.nu>2021-05-22 16:24:36 +0000
commit0658187afb830fbcf082950b30f0be6cea4455a0 (patch)
treebc174c1d648951157ff7957f1bdf8f34e9e2ae72
parentsupport non-byte aligned data lines (diff)
downloadsubv-0658187afb830fbcf082950b30f0be6cea4455a0.tar.gz
subv-0658187afb830fbcf082950b30f0be6cea4455a0.zip
log offending line when errors occur, across all stages
-rwxr-xr-xelf.py15
-rwxr-xr-xformat.py57
-rwxr-xr-xpack.py2
-rw-r--r--subv.py42
-rwxr-xr-xsurvey.py5
5 files changed, 74 insertions, 47 deletions
diff --git a/elf.py b/elf.py
index 4427263..2759679 100755
--- a/elf.py
+++ b/elf.py
@@ -80,12 +80,11 @@ def write_program_header(segment, c, start):
c += wi(align, 4) # p_align
return c
-if __name__ == "__main__":
+@subv.with_parsed_lines
+def elf(iter):
segments = []
segment = None
- for line in sys.stdin:
- line = subv.parse(line)
-
+ for line in iter:
if line['type'] == 'segment':
(name, addr) = line['segment']
segment = { 'name': name, 'addr': addr, 'content': [] }
@@ -98,8 +97,6 @@ if __name__ == "__main__":
else:
raise ValueError("elf input should contain only segments and data!")
- cursor = 0
-
c = write_elf_header(segments)
segment_start = 0x1000
for seg in segments:
@@ -110,3 +107,9 @@ if __name__ == "__main__":
c = padto(seg['offset'], c)
for part in seg['content']:
c += wi(part[0], 1)
+
+ yield
+
+if __name__ == '__main__':
+ for line in elf(sys.stdin):
+ pass
diff --git a/format.py b/format.py
index 419f6df..aa6c8ba 100755
--- a/format.py
+++ b/format.py
@@ -282,44 +282,27 @@ instr_map = {
'jal': (pack_j, 0x6f),
}
+@subv.with_parsed_lines
def format(iter):
- for line_no, raw_line in enumerate(iter, start=1):
- try:
- line = subv.parse(raw_line)
- except AssertionError as e:
- message = '''
-failed to format line:
-<input>:{} {}
-parsed as {}
- '''.strip().format(line_no, raw_line.strip())
- raise Exception(message) from e
-
- try:
- if line['type'] == 'instr':
- op = line['instr'][0]
- assert len(op) == 2, 'instruction without op label: {}'.format(op)
-
- (op, label) = op
- if label not in instr_map:
- raise ValueError("unknown instruction label: {}".format(label))
- (formatter, expected) = instr_map[label]
- if op != expected:
- raise ValueError("opcode {} doesn't match label {} (expected {})"
- .format(op, label, expected))
-
- formatted = formatter(line['instr'])
- formatted[0] = (*formatted[0], label)
- line['instr'] = formatted
- yield subv.format(line)
- else:
- yield line['raw']
- except AssertionError as e:
- message = '''
-failed to format line:
-<input>:{} {}
-parsed as {}
- '''.strip().format(line_no, raw_line.strip(), subv.dump(line))
- raise Exception(message) from e
+ for line in iter:
+ if line['type'] == 'instr':
+ op = line['instr'][0]
+ assert len(op) == 2, 'instruction without op label: {}'.format(op)
+
+ (op, label) = op
+ if label not in instr_map:
+ raise ValueError("unknown instruction label: {}".format(label))
+ (formatter, expected) = instr_map[label]
+ if op != expected:
+ raise ValueError("opcode {} doesn't match label {} (expected {})"
+ .format(op, label, expected))
+
+ formatted = formatter(line['instr'])
+ formatted[0] = (*formatted[0], label)
+ line['instr'] = formatted
+ line = yield subv.format(line)
+ else:
+ line = yield line['raw']
if __name__ == '__main__':
import sys
diff --git a/pack.py b/pack.py
index 13a4971..29949b4 100755
--- a/pack.py
+++ b/pack.py
@@ -62,6 +62,7 @@ def byteify(word):
out.append(byte[:1])
return out
+@subv.with_parsed_lines
def pack(iter):
segment = None
@@ -78,7 +79,6 @@ def pack(iter):
}
for line in iter:
- line = subv.parse(line)
if line['type'] == 'data':
for part in line['data']:
buf = bits.concat(buf, bits.from_part(part))
diff --git a/subv.py b/subv.py
index 0615159..a280e77 100644
--- a/subv.py
+++ b/subv.py
@@ -288,3 +288,45 @@ def dump(line):
def join_all(gen):
res = '\n'.join(gen)
return res
+
+
+class SubVException(Exception):
+ pass
+
+class LineIterator(object):
+ def __init__(self, stream):
+ self.stream = stream
+ self.iter = enumerate(self.stream, start=1)
+ self.i, self.raw_line, self.line = 0, None, None
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ self.i, self.raw_line = next(self.iter)
+ self.line = None
+ try:
+ self.line = parse(self.raw_line)
+ except Exception as e:
+ raise self.exception("failed to parse line") from e
+ return self.line
+
+ def exception(self, msg):
+ if self.line:
+ msg = msg + "\n{}:{}: {}".format(self.stream.name, self.i, format(self.line))
+ msg = msg + "\nparsed as {}".format(dump(self.line))
+ elif self.raw_line:
+ msg = msg + "\n{}:{}: {}".format(self.stream.name, self.i, self.raw_line.strip())
+ return SubVException(msg)
+
+def with_parsed_lines(process_fn):
+ def _wrapped(iter):
+ iterator = LineIterator(iter)
+ try:
+ yield from process_fn(iterator)
+ except SubVException:
+ raise
+ except Exception as e:
+ raise iterator.exception("failed to {} line".format(process_fn.__name__)) from e
+
+ return _wrapped
diff --git a/survey.py b/survey.py
index 1420e19..e6beb4b 100755
--- a/survey.py
+++ b/survey.py
@@ -90,13 +90,12 @@ def observe(part, rel_addr, map):
return bits.slice(addr, ref['hi'], ref['lo'])
+@subv.with_parsed_lines
def survey(iter):
queue = []
map = {}
- addr = -1
- bits = 0
+ addr, bits = -1, 0
for line in iter:
- line = subv.parse(line)
line['addr'] = addr
queue.append(line)