Skip to content

Commit 8821bec

Browse files
authored
Merge pull request #315 from kosarev/issue304_support_custom_emitters
[#304] Support custom code emitters.
2 parents 9683218 + 00aee2e commit 8821bec

7 files changed

Lines changed: 90 additions & 20 deletions

File tree

outfmt/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
#!/usr/bin/env python
22
# -*- coding: utf-8 -*-
33

4+
from .binary import BinaryEmitter
5+
from .codeemitter import CodeEmitter
46
from .tzx import TZX
57
from .tap import TAP
68

79

810
__all__ = [
11+
'BinaryEmitter',
12+
'CodeEmitter',
913
'TZX',
1014
'TAP',
1115
]

outfmt/binary.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
4+
# --------------------------------------------
5+
# KopyLeft (K) 2008
6+
# by Jose M. Rodriguez de la Rosa
7+
#
8+
# This program is licensed under the
9+
# GNU Public License v.3.0
10+
#
11+
# The code emission interface.
12+
# --------------------------------------------
13+
14+
from .codeemitter import CodeEmitter
15+
16+
17+
class BinaryEmitter(CodeEmitter):
18+
""" Writes compiled code as raw binary data.
19+
"""
20+
def emit(self, output_filename, program_name, loader_bytes, entry_point,
21+
program_bytes, aux_bin_blocks, aux_headless_bin_blocks):
22+
""" Emits resulting binary file.
23+
"""
24+
with open(output_filename, 'wb') as f:
25+
f.write(bytearray(program_bytes))

outfmt/codeemitter.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
4+
# --------------------------------------------
5+
# KopyLeft (K) 2008
6+
# by Jose M. Rodriguez de la Rosa
7+
#
8+
# This program is licensed under the
9+
# GNU Public License v.3.0
10+
#
11+
# The code emission interface.
12+
# --------------------------------------------
13+
14+
15+
class CodeEmitter(object):
16+
""" The base code emission interface.
17+
"""
18+
19+
pass

outfmt/tzx.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@
1313
# --------------------------------------------
1414

1515

16-
class TZX(object):
16+
from .codeemitter import CodeEmitter
17+
18+
19+
class TZX(CodeEmitter):
1720
""" Class to represent tzx data
1821
"""
1922
VERSION_MAJOR = 1
@@ -131,6 +134,21 @@ def save_program(self, title, bytes, line=32768):
131134
bytes = [self.BLOCK_TYPE_DATA] + [(int(x) & 0xFF) for x in bytes] # & 0xFF truncates to bytes
132135
self.standard_block(bytes)
133136

137+
def emit(self, output_filename, program_name, loader_bytes, entry_point,
138+
program_bytes, aux_bin_blocks, aux_headless_bin_blocks):
139+
""" Emits resulting tape file.
140+
"""
141+
if loader_bytes is not None:
142+
self.save_program('loader', loader_bytes, line=1) # Put line 0 to protect against MERGE
143+
144+
self.save_code(program_name, entry_point, program_bytes)
145+
for name, block in aux_bin_blocks:
146+
self.save_code(name, 0, block)
147+
for block in aux_headless_bin_blocks:
148+
self.standard_block(block)
149+
150+
self.dump(output_filename)
151+
134152

135153
if __name__ == '__main__':
136154
""" Sample test if invoked from command line

zxb/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@
99
# the GNU General License
1010
# ----------------------------------------------------------------------
1111

12+
from outfmt import CodeEmitter # noqa
1213
from .zxb import main # noqa

zxb/zxb.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def output(memory, ofile=None):
7070
ofile.write('%s\n' % m)
7171

7272

73-
def main(args=None):
73+
def main(args=None, emitter=None):
7474
""" Entry point when executed from command line.
7575
You can use zxb.py as a module with import, and this
7676
function won't be executed.
@@ -352,7 +352,8 @@ def main(args=None):
352352
fout.close()
353353
asmparse.generate_binary(OPTIONS.outputFileName.value, OPTIONS.output_file_type.value,
354354
binary_files=options.append_binary,
355-
headless_binary_files=options.append_headless_binary)
355+
headless_binary_files=options.append_headless_binary,
356+
emitter=emitter)
356357
if gl.has_errors:
357358
return 5 # Error in assembly
358359

zxbasm/asmparse.py

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1467,7 +1467,8 @@ def assemble(input_):
14671467
return gl.has_errors
14681468

14691469

1470-
def generate_binary(outputfname, format_, progname='', binary_files=None, headless_binary_files=None):
1470+
def generate_binary(outputfname, format_, progname='', binary_files=None, headless_binary_files=None,
1471+
emitter=None):
14711472
""" Outputs the memory binary to the
14721473
output filename using one of the given
14731474
formats: tap, tzx or bin
@@ -1512,23 +1513,24 @@ def generate_binary(outputfname, format_, progname='', binary_files=None, headle
15121513
else:
15131514
program.add_line([['REM'], ['RANDOMIZE', program.token('USR'), AUTORUN_ADDR]])
15141515

1515-
if format_ in ('tap', 'tzx'):
1516-
t = {'tap': outfmt.TAP, 'tzx': outfmt.TZX}[format_]()
1517-
1518-
if OPTIONS.use_loader.value:
1519-
t.save_program('loader', program.bytes, line=1) # Put line 0 to protect against MERGE
1520-
1521-
t.save_code(progname, org, binary)
1522-
for name, block in bin_blocks:
1523-
t.save_code(name, 0, block)
1524-
for block in headless_bin_blocks:
1525-
t.standard_block(block)
1526-
1527-
t.dump(outputfname)
1516+
if emitter is None:
1517+
if format_ in ('tap', 'tzx'):
1518+
emitter = {'tap': outfmt.TAP, 'tzx': outfmt.TZX}[format_]()
1519+
else:
1520+
emitter = outfmt.BinaryEmitter()
15281521

1529-
else:
1530-
with open(outputfname, 'wb') as f:
1531-
f.write(bytearray(binary))
1522+
loader_bytes = None
1523+
if OPTIONS.use_loader.value:
1524+
loader_bytes = program.bytes
1525+
1526+
assert isinstance(emitter, outfmt.CodeEmitter)
1527+
emitter.emit(output_filename=outputfname,
1528+
program_name=progname,
1529+
loader_bytes=loader_bytes,
1530+
entry_point=AUTORUN_ADDR,
1531+
program_bytes=binary,
1532+
aux_bin_blocks=bin_blocks,
1533+
aux_headless_bin_blocks=headless_bin_blocks)
15321534

15331535

15341536
def main(argv):

0 commit comments

Comments
 (0)