mirror of
https://github.com/michaelcmartin/Ophis.git
synced 2024-12-21 12:29:46 +00:00
New command-line system.
This is a full optparse-based parser for all the options we want to have in Ophis 2.0, but the pass-disablers aren't working yet. This also doesn't handle positional arguments the way we hope to eventually; that will come later. optparse is deprecated in 2.7, but its replacement isn't available in any previous version of Python, so we avoid it so as to not gratuitously break compatibility on older machines. It would be nice to at least stay usable on stock Leopard Macs (2.5).
This commit is contained in:
parent
eae4ea7dcd
commit
e47073bc1d
@ -7,4 +7,4 @@ path.insert(0, join(dirname(realpath(argv[0])), '..', 'src'))
|
||||
|
||||
import Ophis.Main
|
||||
|
||||
Ophis.Main.run_ophis()
|
||||
Ophis.Main.run_ophis(argv[1:])
|
||||
|
@ -1,17 +1,76 @@
|
||||
"""Command line options data.
|
||||
"""Command line options data."""
|
||||
|
||||
verbose:
|
||||
0: Only report errors
|
||||
1: Announce each file as it is read, and data count (default)
|
||||
2: As above, but also announce each pass.
|
||||
3: As above, but print the IR after each pass.
|
||||
4: As above, but print the labels after each pass.
|
||||
|
||||
6510 compatibility and deprecation are handled in Ophis.Main."""
|
||||
import optparse
|
||||
|
||||
# Copyright 2002-2012 Michael C. Martin and additional contributors.
|
||||
# You may use, modify, and distribute this file under the MIT
|
||||
# license: See README for details.
|
||||
|
||||
verbose = 1;
|
||||
enable_collapse = True
|
||||
enable_branch_extend = True
|
||||
enable_undoc_ops = False
|
||||
enable_65c02_exts = False
|
||||
|
||||
warn_on_branch_extend = True
|
||||
|
||||
print_summary = True
|
||||
print_loaded_files = False
|
||||
print_pass = False
|
||||
print_ir = False
|
||||
print_labels = False
|
||||
|
||||
infile = None
|
||||
outfile = None
|
||||
|
||||
def parse_args(raw_args):
|
||||
"Populate the module's globals based on the command-line options given."
|
||||
global enable_collapse, enable_branch_extend, enable_undoc_ops, enable_65c02_exts
|
||||
global warn_on_branch_extend
|
||||
global print_summary, print_loaded_files, print_pass, print_ir, print_labels
|
||||
global infile, outfile
|
||||
|
||||
parser = optparse.OptionParser(usage= "Usage: %prog [options] srcfile outfile", version="Ophis 6502 cross-assembler, version 2.0")
|
||||
|
||||
ingrp = optparse.OptionGroup(parser, "Input options")
|
||||
ingrp.add_option("-u", "--undoc", action="store_true", default=False, help="Enable 6502 undocumented opcodes")
|
||||
ingrp.add_option("-c", "--65c02", action="store_true", default=False, dest="c02", help="Enable 65c02 extended instruction set")
|
||||
|
||||
outgrp = optparse.OptionGroup(parser, "Console output options")
|
||||
outgrp.add_option("-v", "--verbose", action="store_const", const=2, help="Verbose mode", default=1)
|
||||
outgrp.add_option("-q", "--quiet", action="store_const", help="Quiet mode", dest="verbose", const=0)
|
||||
outgrp.add_option("-d", "--debug", action="count", dest="verbose", help=optparse.SUPPRESS_HELP)
|
||||
outgrp.add_option("--no-warn", action="store_false", dest="warn", default=True, help="Do not print warnings")
|
||||
|
||||
bingrp = optparse.OptionGroup(parser, "Binary output options")
|
||||
bingrp.add_option("--no-collapse", action="store_false", dest="enable_collapse", default="True", help="Disable zero-page collapse pass")
|
||||
bingrp.add_option("--no-branch-extend", action="store_false", dest="enable_branch_extend", default="True", help="Disable branch-extension pass")
|
||||
|
||||
parser.add_option_group(ingrp)
|
||||
parser.add_option_group(outgrp)
|
||||
parser.add_option_group(bingrp)
|
||||
|
||||
(options, args) = parser.parse_args(raw_args)
|
||||
|
||||
if len(args) > 2:
|
||||
parser.error("Too many files specified")
|
||||
if len(args) == 1:
|
||||
parser.error("No output file specified")
|
||||
if len(args) == 0:
|
||||
parser.error("No files specified")
|
||||
if options.c02 and options.undoc:
|
||||
parser.error("--undoc and --65c02 are mutually exclusive")
|
||||
|
||||
infile = args[0]
|
||||
outfile = args[1]
|
||||
enable_collapse = options.enable_collapse
|
||||
enable_branch_extend = options.enable_branch_extend
|
||||
enable_undoc_ops = options.undoc
|
||||
enable_65c02_exts = options.c02
|
||||
warn_on_branch_extend = options.warn
|
||||
print_summary = options.verbose > 0 # no options set
|
||||
print_loaded_files = options.verbose > 1 # v
|
||||
print_pass = options.verbose > 2 # dd
|
||||
print_ir = options.verbose > 3 # ddd
|
||||
print_labels = options.verbose > 4 # dddd
|
||||
|
||||
parser.destroy()
|
||||
|
@ -310,7 +310,7 @@ def parse_line(ppt, lexemelist):
|
||||
def parse_file(ppt, filename):
|
||||
"Loads an Ophis source file, and returns an IR list."
|
||||
Err.currentpoint = ppt
|
||||
if Cmd.verbose > 0:
|
||||
if Cmd.print_loaded_files:
|
||||
if filename != '-':
|
||||
print>>sys.stderr, "Loading "+filename
|
||||
else:
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""Main controller routines for the Ophis assembler.
|
||||
|
||||
When invoked as main, interprets its command line and goes from there.
|
||||
Otherwise, use run_all to interpret a file set."""
|
||||
Otherwise, use run_ophis(cmdline-list) to use it inside a script."""
|
||||
|
||||
# Copyright 2002-2012 Michael C. Martin and additional contributors.
|
||||
# You may use, modify, and distribute this file under the MIT
|
||||
@ -17,18 +17,6 @@ import Ophis.Environment
|
||||
import Ophis.CmdLine
|
||||
import Ophis.Opcodes
|
||||
|
||||
|
||||
def usage():
|
||||
"Prints a usage message and quits."
|
||||
print>>sys.stderr, "Usage:"
|
||||
print>>sys.stderr, "\tOphis [options] infile outfile"
|
||||
print>>sys.stderr, ""
|
||||
print>>sys.stderr, "Options:"
|
||||
print>>sys.stderr, "\t-6510 Allow 6510 undocumented opcodes"
|
||||
print>>sys.stderr, "\t-65c02 Enable 65c02 extensions"
|
||||
print>>sys.stderr, "\t-v n Set verbosity to n (0-4, 1=default)"
|
||||
sys.exit(1)
|
||||
|
||||
def run_all(infile, outfile):
|
||||
"Transforms the source infile to a binary outfile."
|
||||
Err.count = 0
|
||||
@ -69,56 +57,17 @@ def run_all(infile, outfile):
|
||||
else:
|
||||
Err.report()
|
||||
|
||||
def run_ophis():
|
||||
infile = None
|
||||
outfile = None
|
||||
|
||||
p65_compatibility_mode = 0
|
||||
chip_extension = None
|
||||
|
||||
reading_arg = 0
|
||||
|
||||
for x in sys.argv[1:]:
|
||||
if reading_arg:
|
||||
try:
|
||||
Ophis.CmdLine.verbose = int(x)
|
||||
reading_arg = 0
|
||||
except ValueError:
|
||||
print>>sys.stderr, "FATAL: Non-integer passed as argument to -v"
|
||||
usage()
|
||||
elif x[0] == '-' and x != '-':
|
||||
if x == '-v':
|
||||
reading_arg = 1
|
||||
elif x == '-6510':
|
||||
chip_extension = Ophis.Opcodes.undocops
|
||||
elif x == '-65c02':
|
||||
chip_extension = Ophis.Opcodes.c02extensions
|
||||
else:
|
||||
print>>sys.stderr, "FATAL: Unknown option "+x
|
||||
usage()
|
||||
elif infile == None:
|
||||
infile = x
|
||||
elif outfile == None:
|
||||
outfile = x
|
||||
else:
|
||||
print>>sys.stderr, "FATAL: Too many files specified"
|
||||
usage()
|
||||
|
||||
if infile is None:
|
||||
print>>sys.stderr, "FATAL: No files specified"
|
||||
usage()
|
||||
|
||||
if outfile is None:
|
||||
print>>sys.stderr, "FATAL: No output file specified"
|
||||
usage()
|
||||
|
||||
def run_ophis(args):
|
||||
Ophis.CmdLine.parse_args(args)
|
||||
Ophis.Frontend.pragma_modules.append(Ophis.CorePragmas)
|
||||
|
||||
if chip_extension is not None:
|
||||
Ophis.Opcodes.opcodes.update(chip_extension)
|
||||
if Ophis.CmdLine.enable_undoc_ops:
|
||||
Ophis.Opcodes.opcodes.update(Ophis.Opcodes.undocops)
|
||||
elif Ophis.CmdLine.enable_65c02_exts:
|
||||
Ophis.Opcodes.opcodes.update(Ophis.Opcodes.c02extensions)
|
||||
|
||||
Ophis.CorePragmas.reset()
|
||||
run_all(infile, outfile)
|
||||
run_all(Ophis.CmdLine.infile, Ophis.CmdLine.outfile)
|
||||
|
||||
if __name__ == '__main__':
|
||||
run_ophis()
|
||||
run_ophis(sys.argv[1:])
|
||||
|
@ -54,16 +54,16 @@ class Pass:
|
||||
"""Prepares the environment and runs this pass, possibly
|
||||
printing debugging information."""
|
||||
if Err.count == 0:
|
||||
if Cmd.verbose > 1: print>>sys.stderr, "Running: "+self.name
|
||||
if Cmd.print_pass: print>>sys.stderr, "Running: "+self.name
|
||||
env.reset()
|
||||
self.prePass()
|
||||
node.accept(self, env)
|
||||
self.postPass()
|
||||
env.reset()
|
||||
if Cmd.verbose > 3:
|
||||
if Cmd.print_labels:
|
||||
print>>sys.stderr, "Current labels:"
|
||||
print>>sys.stderr, env
|
||||
if Cmd.verbose > 2:
|
||||
if Cmd.print_ir:
|
||||
print>>sys.stderr, "Current IR:"
|
||||
print>>sys.stderr, node
|
||||
|
||||
@ -83,7 +83,7 @@ class FixPoint:
|
||||
p.go(node, env)
|
||||
if Err.count != 0: break
|
||||
if self.fixpoint(): break
|
||||
if Cmd.verbose > 1: print>>sys.stderr, "Fixpoint failed, looping back"
|
||||
if Cmd.print_pass: print>>sys.stderr, "Fixpoint failed, looping back"
|
||||
else:
|
||||
Err.log("Can't make %s converge! Maybe there's a recursive dependency somewhere?" % self.name)
|
||||
|
||||
@ -96,7 +96,7 @@ class DefineMacros(Pass):
|
||||
def postPass(self):
|
||||
if self.inDef:
|
||||
Err.log("Unmatched .macro")
|
||||
elif Cmd.verbose > 2:
|
||||
elif Cmd.print_ir:
|
||||
print>>sys.stderr, "Macro definitions:"
|
||||
Macro.dump()
|
||||
def visitMacroBegin(self, node, env):
|
||||
@ -392,7 +392,7 @@ class ExtendBranches(PCTracker):
|
||||
# If BRA - BRanch Always - is out of range, it's a JMP.
|
||||
node.data = ('jmp', expr)
|
||||
node.nodetype = "Absolute"
|
||||
if Cmd.verbose > 0:
|
||||
if Cmd.warn_on_branch_extend:
|
||||
print>>sys.stderr, str(node.ppt) + ": WARNING: bra out of range, replacing with jmp"
|
||||
else:
|
||||
# Otherwise, we replace it with a 'macro' of sorts by hand:
|
||||
@ -403,7 +403,7 @@ class ExtendBranches(PCTracker):
|
||||
IR.Node(node.ppt, "Absolute", 'jmp', expr)]
|
||||
node.nodetype='SEQUENCE'
|
||||
node.data = expansion
|
||||
if Cmd.verbose > 0:
|
||||
if Cmd.warn_on_branch_extend:
|
||||
print>>sys.stderr, str(node.ppt) + ": WARNING: "+opcode+" out of range, replacing with "+ExtendBranches.reversed[opcode] +"/jmp combo"
|
||||
self.expanded += 1
|
||||
node.accept(self, env)
|
||||
@ -435,7 +435,7 @@ class Assembler(Pass):
|
||||
self.filler = 0
|
||||
|
||||
def postPass(self):
|
||||
if Cmd.verbose > 0 and Err.count == 0:
|
||||
if Cmd.print_summary and Err.count == 0:
|
||||
print>>sys.stderr, "Assembly complete: %s bytes output (%s code, %s data, %s filler)" \
|
||||
% (len(self.output), self.code, self.data, self.filler)
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#!/usr/local/bin/python
|
||||
import sys
|
||||
import Ophis.Main
|
||||
|
||||
Ophis.Main.run_ophis()
|
||||
Ophis.Main.run_ophis(sys.argv[1:])
|
||||
|
Loading…
Reference in New Issue
Block a user