hence/src/cli/hence.cr
2022-07-08 21:56:07 +02:00

201 lines
5.1 KiB
Crystal

require "commander"
require "../hence"
CLI = Commander::Command.new do |cmd|
cmd.use = "hence"
cmd.long = "Hence assembler and emulator"
cmd.run do
puts cmd.help
end
# ameba:disable Lint/ShadowingOuterLocalVar
cmd.commands.add do |cmd|
cmd.use = "version"
cmd.short = "Prins current hence version"
cmd.long = cmd.short
cmd.run do
puts Hence::VERSION
end
end
# ameba:disable Lint/ShadowingOuterLocalVar
cmd.commands.add do |cmd|
cmd.use = "firmware"
cmd.short = "Firmware utility"
cmd.long = cmd.short
cmd.flags.add do |flag|
flag.name = "file"
flag.long = "--file"
flag.default = false
flag.description = "Load firmware from file"
flag.persistent = true
end
# ameba:disable Lint/ShadowingOuterLocalVar
cmd.commands.add do |cmd|
cmd.use = "ls"
cmd.short = "Lists available firmwares"
cmd.long = cmd.short
cmd.run do
puts Hence::Firmware::FIRMWARES.keys.join("\n")
end
end
# ameba:disable Lint/ShadowingOuterLocalVar
cmd.commands.add do |cmd|
cmd.use = "compile <firmware> [out]"
cmd.short = "Compiles a firmware"
cmd.long = cmd.short
cmd.flags.add do |flag|
flag.name = "dump"
flag.long = "--dump"
flag.default = false
flag.description = "Hexdumps the firmware"
end
cmd.run do |opts, args|
bin = if opts.bool["file"]
Hence::Firmware.from_yaml(File.read(args[0]))
else
Hence::Firmware::FIRMWARES[args[0]]
end.compile(Hence::Microcode::MICROCODE_NAMES)
File.write(args[1], bin) if args[1]?
puts bin.hexdump if opts.bool["dump"]
end
end
# ameba:disable Lint/ShadowingOuterLocalVar
cmd.commands.add do |cmd|
cmd.use = "doc <firmware> [out]"
cmd.short = "Generates documentation for a firmware"
cmd.long = cmd.short
cmd.flags.add do |flag|
flag.name = "dump"
flag.long = "--dump"
flag.default = false
flag.description = "Hexdumps the firmware"
end
cmd.run do |opts, args|
doc = if opts.bool["file"]
Hence::Firmware.from_yaml(File.read(args[0]))
else
Hence::Firmware::FIRMWARES[args[0]]
end.to_s
File.write(args[1], doc) if args[1]?
puts doc if opts.bool["dump"]
end
end
end
# ameba:disable Lint/ShadowingOuterLocalVar
cmd.commands.add do |cmd|
cmd.use = "parse <src>"
cmd.short = "Parses source code"
cmd.long = cmd.short
cmd.run do |_opts, args|
# ameba:disable Lint/DebugCalls
pp Hence::Parser.parse(File.read(args[0]))
end
end
# ameba:disable Lint/ShadowingOuterLocalVar
cmd.commands.add do |cmd|
cmd.use = "assemble <src> [out]"
cmd.short = "Compiles assembly code into a binary"
cmd.long = cmd.short
cmd.flags.add do |flag|
flag.name = "firmware"
flag.short = "-f"
flag.long = "--firmware"
flag.default = "default"
flag.description = "Custom firmware"
end
cmd.flags.add do |flag|
flag.name = "file"
flag.long = "--file"
flag.default = false
flag.description = "Load firmware from YAML definition file"
end
cmd.flags.add do |flag|
flag.name = "dump"
flag.long = "--dump"
flag.default = false
flag.description = "Hexdumps the binary"
end
cmd.run do |opts, args|
bin = Hence::Assembler.assemble(
Hence::Parser.parse(File.read(args[0])),
if opts.bool["file"]
Hence::Firmware.from_yaml(File.read(opts.string["file"]))
else
Hence::Firmware::FIRMWARES[opts.string["firmware"]]
end.build_opcodes[:names],
Hence::Assembler::Data.new(Path[args[0]])
)
File.write(args[1], bin) if args[1]?
puts bin.hexdump if opts.bool["dump"]
end
end
# ameba:disable Lint/ShadowingOuterLocalVar
cmd.commands.add do |cmd|
cmd.use = "run <bin>"
cmd.short = "Runs a binary"
cmd.long = cmd.short
cmd.flags.add do |flag|
flag.name = "firmware"
flag.short = "-f"
flag.long = "--firmware"
flag.default = "default"
flag.description = "Custom firmware"
end
cmd.flags.add do |flag|
flag.name = "file"
flag.long = "--file"
flag.default = false
flag.description = "Load firmware from file"
end
cmd.run do |opts, args|
bin = Bytes.new({{ 32 * 1024 }})
File.open(args[0]) do |file|
file.gets_to_end.to_slice.copy_to(bin)
end
Hence::Emulator.emulate(
Hence::Emulator::Data.new(
bin,
if opts.bool["file"]
buffer = Bytes.new({{ 32 * 1024 }})
File.open(opts.string["firmware"]) do |file|
file.gets_to_end.to_slice.copy_to(buffer)
end
buffer
else
Hence::Firmware::FIRMWARES[opts.string["firmware"]].compile(Hence::Microcode::MICROCODE_NAMES)
end
)
)
end
end
end
Commander.run(CLI, ARGV)