Enable the import of files

master
Joachim Stolberg 2022-04-01 18:30:56 +02:00
parent bee2943e05
commit 7fd7fb36bb
7 changed files with 228 additions and 389 deletions

View File

@ -7,24 +7,21 @@
AGPL v3
See LICENSE.txt for more information
The Assembler accepts a list with following code items:
{CTYPE, LINENO, CODESTR, ADDRESS, OPCODES}
{"code", 2, "move A, #1", 10, {0x1020, 0x0001}}
]]--
local version = "2.2"
-- Tok Elems {1, "add A, 1", "add A, 1 ; start value", CODESEC, 10, {0x1234, 0x001}}
local LINENO = 1
local CODESTR = 2
local TXTLINE = 3
local SECTION = 4
local ADDRESS = 5
local OPCODES = 6
-- Sections
local DATASEC = 1
local CODESEC = 2
local TEXTSEC = 3
local CTEXTSEC = 4
local COMMENT = 5
local CTYPE = 1
local LINENO = 2
local CODESTR = 3
local ADDRESS = 4
local OPCODES = 5
local tOpcodes = {}
local tOperands = {}
@ -74,19 +71,15 @@ for idx,s in pairs(Operands) do
end
local tSections = {
[".data"] = DATASEC,
[".code"] = CODESEC,
[".text"] = TEXTSEC,
[".ctext"] = CTEXTSEC,
[".data"] = true,
[".code"] = true,
[".text"] = true,
[".ctext"] = true,
}
-------------------------------------------------------------------------------
-- Helper functions
-------------------------------------------------------------------------------
local strfind = string.find
local strsub = string.sub
local tinsert = table.insert
local function strsplit(s)
local words = {}
string.gsub(s, "([^%s,]+)", function(w)
@ -95,23 +88,6 @@ local function strsplit(s)
return words
end
local function linessplit(text)
local list = {}
local pos = 1
while true do
local first, last = strfind(text, "\n", pos)
if first then -- found?
tinsert(list, strsub(text, pos, first-1))
pos = last+1
else
tinsert(list, strsub(text, pos))
break
end
end
return list
end
local function constant(s)
if s and string.sub(s, 1, 1) == "#" then
if string.sub(s, 2, 2) == "$" then
@ -188,12 +164,10 @@ local Asm = {}
function Asm:new(o)
o = o or {}
o.section = o.section or CODESEC
o.address = o.address or 0
o.support_namespaces = o.support_namespaces
o.globals = {}
o.symbols = {}
o.errors = {}
o.namespace_cnt = 1
setmetatable(o, self)
self.__index = self
@ -201,26 +175,28 @@ function Asm:new(o)
end
function Asm:err_msg(err)
local s = string.format("%s(%d): %s!", self.filename, self.lineno or 0, err)
append(self.errors, s)
self.error = true
error(string.format("%s(%d): %s!", self.filename, self.lineno or 0, err))
end
function Asm:scanner(text)
function Asm:scanner(text, filename)
local lOut = {} -- {lineno, codestr, txtline}
self.filename = filename
self.lineno = 0
if not vm16.is_ascii(text) then
return nil, "Error: Invalid ASCII file format!"
self:err_msg("Invalid ASCII file format!")
end
for lineno, txtline in ipairs(linessplit(text)) do
append(lOut, {"file", 0, "test.c"})
self.ctype = "code"
for lineno, txtline in ipairs(vm16.splitlines(text)) do
local _, _, codestr = txtline:find("(.+);")
codestr = string.trim(codestr or txtline)
if string.byte(codestr, 1) == 59 then -- ';'
append(lOut, {lineno, "", txtline})
elseif codestr == "" then
append(lOut, {lineno, "", txtline})
else
append(lOut, {lineno, codestr, txtline})
if tSections[codestr] then
self.ctype = string.sub(codestr, 2)
elseif codestr ~= "" and string.byte(codestr, 1) ~= 59 then -- ';'
append(lOut, {self.ctype, lineno, codestr})
end
end
return lOut
@ -246,6 +222,7 @@ function Asm:address_label(tok)
self.symbols[self:postfix(label)] = self.address
end
tok[CODESTR] = codestr:sub(pos+1, -1)
self.label = label
end
return tok
end
@ -263,16 +240,6 @@ function Asm:global_def(tok)
return tok
end
-- New assembler section
function Asm:section_def(tok)
local codestr = tok[CODESTR]
if tSections[codestr] then
self.section = tSections[codestr]
tok[CODESTR] = ""
end
return tok
end
function Asm:org_directive(tok)
local codestr = tok[CODESTR]
local _, _, addr = codestr:find("^%.org +([%$%x]+)$")
@ -307,24 +274,12 @@ function Asm:operand(s)
return
end
function Asm:no_code(tok)
local pos1, pos2 = tok[TXTLINE]:find(";")
if pos1 == 1 and pos2 == 1 then
return {tok[LINENO], tok[CODESTR], tok[TXTLINE], COMMENT, self.address, {}}
else
return {tok[LINENO], tok[CODESTR], tok[TXTLINE], self.section, self.address, {}}
end
end
function Asm:decode_code(tok)
local codestr = tok[CODESTR]
local words = strsplit(codestr)
if codestr == "" then
return self:no_code(tok)
end
if codestr == "namespace" then
self.namespace_cnt = self.namespace_cnt + 1
return self:no_code(tok)
return
end
-- Aliases
if words[2] == "=" then
@ -337,7 +292,7 @@ function Asm:decode_code(tok)
else
self:err_msg("Invalid left value")
end
return self:no_code(tok)
return
end
-- Opcodes
@ -346,7 +301,6 @@ function Asm:decode_code(tok)
opcode = tOpcodes[words[1]]
if not opcode then
self:err_msg("Syntax error")
return self:no_code(tok)
end
if #words == 2 and opcode < 4 then
local num = constant(words[2]) % 1024
@ -357,13 +311,8 @@ function Asm:decode_code(tok)
opnd2, val2 = self:operand(words[3])
end
-- some checks
-- if val1 and val2 then
-- self:err_msg("Syntax error")
-- return self:no_code(tok)
-- end
if not opnd1 and not opnd2 then
self:err_msg("Syntax error")
return self:no_code(tok)
end
-- code correction for all jump/branch opcodes: from '0' to '#0'
if JumpInst[words[1]] then
@ -375,16 +324,13 @@ function Asm:decode_code(tok)
if val1 then tbl[#tbl+1] = val1 end
if val2 then tbl[#tbl+1] = val2 end
tok = {tok[LINENO], tok[CODESTR], tok[TXTLINE], self.section, self.address, tbl}
tok = {"code", tok[LINENO], tok[CODESTR], self.address, tbl}
self.address = self.address + #tbl
return tok
end
function Asm:decode_data(tok)
local codestr = tok[CODESTR]
if codestr == "" then
return self:no_code(tok)
end
local words = strsplit(codestr)
local tbl = {}
for _,word in ipairs(words) do
@ -392,16 +338,14 @@ function Asm:decode_data(tok)
append(tbl, value(word))
end
end
tok = {tok[LINENO], tok[CODESTR], tok[TXTLINE], self.section, self.address, tbl}
-- restore original label
tok = {"data", tok[LINENO], self.label, self.address, tbl}
self.address = self.address + #tbl
return tok
end
function Asm:decode_text(tok)
local codestr = tok[CODESTR]
if codestr == "" then
return {self:no_code(tok)}
end
if codestr:byte(1) == 34 and codestr:byte(-1) == 34 then
codestr = codestr:gsub("\\0", "\0")
codestr = codestr:gsub("\\n", "\n")
@ -414,22 +358,18 @@ function Asm:decode_text(tok)
for i = idx, math.min(idx + 7, ln) do
append(tbl, codestr:byte(i))
end
tok = {tok[LINENO], codestr:sub(idx, idx + 7), tok[TXTLINE], self.section, self.address, tbl}
tok = {"text", tok[LINENO], codestr:sub(idx, idx + 7), self.address, tbl}
self.address = self.address + #tbl
append(out, tok)
end
return out
else
self:err_msg("Invalid string")
return {self:no_code(tok)}
end
end
function Asm:decode_ctext(tok)
local codestr = tok[CODESTR]
if codestr == "" then
return {self:no_code(tok)}
end
if codestr:byte(1) == 34 and codestr:byte(-1) == 34 then
codestr = codestr:gsub("\\0", "\0\0")
codestr = codestr:gsub("\\n", "\n")
@ -442,14 +382,13 @@ function Asm:decode_ctext(tok)
for i = idx, math.min(idx + 15, ln), 2 do
append(tbl, word_val(codestr, i))
end
tok = {tok[LINENO], codestr:sub(idx, idx + 7), tok[TXTLINE], self.section, self.address, tbl}
tok = {"ctext", tok[LINENO], codestr:sub(idx, idx + 7), self.address, tbl}
self.address = self.address + #tbl
append(out, tok)
end
return out
else
self:err_msg("Invalid string")
return {self:no_code(tok)}
end
end
@ -483,19 +422,26 @@ function Asm:assembler(filename, lToken)
self.filename = filename
self.namespace_cnt = 1
for _,tok in ipairs(lToken or {}) do
self.ctype = tok[CTYPE]
self.lineno = tok[LINENO]
tok = self:section_def(tok)
tok = self:org_directive(tok)
tok = self:address_label(tok)
if self.section == CODESEC then
append(lOut, self:decode_code(tok))
elseif self.section == DATASEC then
append(lOut, self:decode_data(tok))
elseif self.section == TEXTSEC then
extend(lOut, self:decode_text(tok))
elseif self.section == CTEXTSEC then
extend(lOut, self:decode_ctext(tok))
if tok[CODESTR] ~= "" then
if self.ctype == "code" then
append(lOut, self:decode_code(tok))
elseif self.ctype == "data" then
append(lOut, self:decode_data(tok))
elseif self.ctype == "text" then
extend(lOut, self:decode_text(tok))
elseif self.ctype == "ctext" then
extend(lOut, self:decode_ctext(tok))
elseif self.ctype == "endf" then
tok[ADDRESS] = self.address
append(lOut, tok)
else
append(lOut, tok)
end
end
end
@ -505,26 +451,30 @@ function Asm:assembler(filename, lToken)
self.lineno = tok[LINENO]
if tok[CODESTR] == "namespace" then
self.namespace_cnt = self.namespace_cnt + 1
end
for i, opc in ipairs(tok[OPCODES] or {}) do
if type(opc) == "string" then
if not self:handle_rip_label(tok, i, opc) then
self:handle_label(tok, i, opc)
elseif tok[CTYPE] == "func" then
local addr = self.symbols[tok[CODESTR]] or 0
tok[ADDRESS] = addr
elseif tok[CTYPE] == "call" then
local addr = self.symbols[tok[CODESTR]] or 0
tok[ADDRESS] = addr
else
for i, opc in ipairs(tok[OPCODES] or {}) do
if type(opc) == "string" then
if not self:handle_rip_label(tok, i, opc) then
self:handle_label(tok, i, opc)
end
end
end
end
end
if self.error then
return nil, table.concat(self.errors, "\n")
end
return lOut
end
function Asm:listing(lToken)
local mydump = function(tbl)
local t = {}
for _,e in ipairs(tbl) do
for _,e in ipairs(tbl or {}) do
if type(e) == "number" then
table.insert(t, string.format("%04X", e))
else
@ -536,13 +486,7 @@ function Asm:listing(lToken)
local out = {}
for _,tok in ipairs(lToken) do
if #tok[OPCODES] > 3 then
append(out, string.format(" %-15s %s\n%04X: %s", "", tok[TXTLINE], tok[ADDRESS], mydump(tok[OPCODES])))
elseif #tok[OPCODES] > 0 then
append(out, string.format("%04X: %-15s %s", tok[ADDRESS], mydump(tok[OPCODES]), tok[TXTLINE]))
else
append(out, string.format(" %-15s %s", "", tok[TXTLINE]))
end
append(out, string.format("%5s %3d %04X: %-15s %s", tok[CTYPE], tok[LINENO] or 0, tok[ADDRESS] or 0, tok[CODESTR], mydump(tok[OPCODES])))
end
return table.concat(out, "\n")
end
@ -550,16 +494,9 @@ end
vm16.Asm = Asm
vm16.Asm.version = version
vm16.Asm.CTYPE = CTYPE
vm16.Asm.LINENO = LINENO
vm16.Asm.CODESTR = CODESTR
vm16.Asm.TXTLINE = TXTLINE
vm16.Asm.SECTION = SECTION
vm16.Asm.ADDRESS = ADDRESS
vm16.Asm.OPCODES = OPCODES
vm16.Asm.DATASEC = DATASEC
vm16.Asm.CODESEC = CODESEC
vm16.Asm.TEXTSEC = TEXTSEC
vm16.Asm.CTEXTSEC = CTEXTSEC
vm16.Asm.COMMENT = COMMENT

View File

@ -13,6 +13,7 @@
The compiler generates a list with tokens according to:
{<type>, <lineno>, <asm-code>}
{"file", 0, "test.c"} -- File info
{"code", 2, "move A, #1"} -- ASM code
{"data", 3, "va1: 0"} -- Variable
{"ctext", 4, "str: 'Hallo'"} -- String
@ -23,61 +24,16 @@
And a table with local variable definitions:
{foo = {<name> = <offs>, ...} -- positive offs = parameter, negative offs = stack variable
The assembler adds address and opcode information:
{CTYPE, LINENO, CODESTR, ADDRESS, OPCODES}
{"code", 2, "move A, #1", 10, {0x1020, 0x0001}}
--]]
local version = "1.1"
local function extend(into, from)
if into and from then
for _, t in ipairs(from or {}) do
into[#into + 1] = t
end
end
end
local function gen_comp_output(lCode, lData, lString)
local out = {}
for idx,line in ipairs(lCode) do
table.insert(out, line)
end
table.insert(out, "")
for idx,line in ipairs(lData) do
table.insert(out, line)
end
if #lString > 1 then
table.insert(out, "")
for idx,line in ipairs(lString) do
table.insert(out, line)
end
end
return table.concat(out, "\n")
end
local function get_glob_variables(prs, symbols)
local out = {}
for ident,addr in pairs(symbols or {}) do
if prs:is_global_var(ident) then
out[ident] = addr
end
end
return out
end
local function lineno_to_Function(prs, lToken)
local out = {}
local fname = ""
for _, tok in ipairs(lToken) do
if tok.lineno and tok.address then
fname = prs.tLineno2Func[tok.lineno] or fname
out[tok.lineno] = fname
end
end
return out
end
local function error_msg(err)
local t = string.split(err, "\001")
if t and #t > 1 then
@ -86,158 +42,32 @@ local function error_msg(err)
return err
end
local function format_output_for_sourcecode_debugging(lToken)
local out = {}
local tok
local lineno
local inline_asm = false
for _,item in ipairs(lToken) do
if item[vm16.Asm.SECTION] == vm16.Asm.COMMENT then
inline_asm = string.find(item[vm16.Asm.TXTLINE], "_asm_")
if tok then
out[#out + 1] = tok
tok = nil
end
lineno = tonumber(item[vm16.Asm.TXTLINE]:sub(2,5))
tok = {lineno = lineno}
elseif inline_asm then
-- Add each line until the next comment line
lineno = lineno + 1
out[#out + 1] = {lineno = lineno, address = item[vm16.Asm.ADDRESS], opcodes = item[vm16.Asm.OPCODES]}
else
if tok and tok.address then
extend(tok.opcodes, item[vm16.Asm.OPCODES])
local function comp_code_listing(lCode, filename)
local mydump = function(tbl)
local t = {}
for _,e in ipairs(tbl or {}) do
if type(e) == "number" then
table.insert(t, string.format("%04X", e))
else
tok = tok or {}
tok.address = item[vm16.Asm.ADDRESS]
tok.opcodes = item[vm16.Asm.OPCODES]
table.insert(t, "'"..e.."'")
end
end
return table.concat(t, " ")
end
out[#out + 1] = tok
return out
local out = {"##### " .. vm16.file_base(filename) .. ".lst" .. " #####"}
for _,item in ipairs(lCode) do
local ctype, lineno, scode, address, opcodes = unpack(item)
table.insert(out, string.format("%5s %3d %04X: %-15s %s", ctype, lineno, address or 0, scode, mydump(opcodes)))
end
return table.concat(out, "\n")
end
local function format_output_for_assembler_debugging(lToken)
local out = {}
for _,item in ipairs(lToken) do
if item[vm16.Asm.SECTION] ~= vm16.Asm.COMMENT then
out[#out + 1] = {
lineno = item[vm16.Asm.LINENO],
address = item[vm16.Asm.ADDRESS],
opcodes = item[vm16.Asm.OPCODES],
}
end
end
return out
end
function vm16.gen_obj_code(filename, code)
local out = {}
local prs = vm16.BPars:new({text = code})
prs.filename = filename
prs:bpars_init()
local status, err = pcall(prs.main, prs)
if not err then
local asm = vm16.Asm:new({})
local lToken = gen_asm_token_list(prs.lCode, prs.lData, prs.lString)
lToken, err = asm:assembler(file_base(filename) .. ".asm", lToken)
if lToken then
local output = format_output_for_sourcecode_debugging(lToken)
return {
locals = prs.all_locals,
output = output,
globals = get_glob_variables(prs, asm.symbols),
functions = lineno_to_Function(prs, output)}
end
return {
locals = {},
output = {},
globals = {},
functions = {},
errors = err}
end
local fname = prs.filename or ""
local lineno = prs.lineno or "0"
local errors = string.format("%s(%d): %s", fname, lineno, error_msg(err))
return {
locals = {},
output = {},
globals = {},
functions = {},
errors = errors}
end
function vm16.gen_asm_code(filename, code)
local out = {}
local prs = vm16.BPars:new({text = code, add_sourcecode = true})
prs.filename = filename
prs:bpars_init()
local status, err = pcall(prs.main, prs)
if not err then
return gen_comp_output(prs.lCode, prs.lData, prs.lString)
else
local fname = prs.filename or ""
local lineno = prs.lineno or "0"
return gen_comp_output(prs.lCode, prs.lData, prs.lString),
string.format("%s(%d): %s", fname, lineno, error_msg(err))
end
end
function vm16.assemble(filename, code)
local a = vm16.Asm:new({})
code = code:gsub("\t", " ")
local lToken, err = a:scanner(code)
if lToken then
lToken, err = a:assembler(file_base(filename) .. ".asm", lToken)
if lToken then
local output = format_output_for_assembler_debugging(lToken)
return {
locals = {},
output = output,
globals = {},
functions = {}}
end
return {
locals = {},
output = {},
globals = {},
functions = {},
errors = err}
end
return {
locals = {},
output = {},
globals = {},
functions = {},
errors = err}
end
function vm16.compile(pos, filename, readfile, debug)
local prs = vm16.BPars:new({pos = pos, readfile = readfile})
prs:bpars_init()
local sts, res = pcall(prs.scanner, prs, filename)
if not sts then
return false, error_msg(res)
end
sts, res = pcall(prs.main, prs)
if not sts then
return false, error_msg(res)
end
if debug then
local output = prs:gen_output()
return true, prs:gen_dbg_dump(output)
end
return true, prs:gen_output()
end
function vm16.gen_asm_code(output, sourcecode)
local out = {}
local function gen_asm_code(output, text, filename)
local out = {";##### " .. vm16.file_base(filename) .. ".asm" .. " #####"}
local oldlineno = 0
local sourcecode = vm16.splitlines(text)
local add_src_code = function(lineno)
for no = oldlineno + 1, lineno do
if sourcecode[no] and sourcecode[no] ~= "" then
@ -285,3 +115,71 @@ function vm16.gen_asm_code(output, sourcecode)
return table.concat(out, "\n")
end
;------------------------------------------------------------------------------
;-- API
;------------------------------------------------------------------------------
function vm16.assemble(pos, filename, readfile, debug)
local code = readfile(pos, filename)
code = code:gsub("\t", " ")
local a = vm16.Asm:new({})
local sts, res = pcall(a.scanner, a, code, filename)
if not sts then
return false, error_msg(res)
end
sts, res = pcall(a.assembler, a, filename, res)
if not sts then
return false, error_msg(res)
end
if debug then
return true, a:listing(res)
end
return true, res
end
function vm16.compile(pos, filename, readfile, output_format)
local prs = vm16.BPars:new({pos = pos, readfile = readfile})
prs:bpars_init()
local sts, res = pcall(prs.scanner, prs, filename)
if not sts then
return false, error_msg(res)
end
if output_format == "tok" then
return true, prs:scan_dbg_dump()
end
sts, res = pcall(prs.main, prs)
if not sts then
return false, error_msg(res)
end
local output = prs:gen_output()
if output_format == "dbg" then
return true, prs:gen_dbg_dump(output)
end
if output_format == "asm" then
local text = readfile(pos, filename)
return true, gen_asm_code(output, text, filename)
end
local asm = vm16.Asm:new({})
sts, res = pcall(asm.assembler, asm, filename, output.lCode)
if not sts then
return false, error_msg(res)
end
if output_format == "lst" then
return true, comp_code_listing(res, filename)
end
return true, {lCode = res, locals = output.locals}
end

View File

@ -21,6 +21,13 @@ local CLOSING_INSTR = {move=1, push=1, add=1, addc=1, mul=1, mulc=1, div=1, sub=
mod=1, ["and"]=1, ["or"]=1, xor=1, ["not"]=1, ["in"]=1, out=1,
push=1, shl=1, shr=1}
local tSections = {
[".data"] = true,
[".code"] = true,
[".text"] = true,
[".ctext"] = true,
}
local BGen = {}
function BGen:new(o)
@ -28,6 +35,7 @@ function BGen:new(o)
o.label_cnt = 0
o.string_cnt = 0
o.reg_cnt = 0
o.ctype = "code"
o.reg_cnt_stack = {}
o.lInit = {}
o.lCode = {}
@ -157,8 +165,24 @@ function BGen:add_label(lbl)
table.insert(self.lCode, {"code", self.lineno, lbl .. ":"})
end
function BGen:add_asm_code(code)
table.insert(self.lCode, {"code", self.lineno, code})
function BGen:add_asm_token(tok)
local _, _, codestr = tok.val:find("(.+);")
codestr = string.trim(codestr or "")
if tSections[codestr] then
self.ctype = string.sub(codestr, 2)
elseif codestr ~= "" and string.byte(codestr, 1) ~= 59 then -- ';'
if self.ctype == "code" then
table.insert(self.lCode, {"code", tok.lineno, codestr})
elseif self.ctype == "data" then
table.insert(self.lData, {"data", tok.lineno, codestr})
elseif self.ctype == "ctext" then
table.insert(self.lText, {"ctext", tok.lineno, codestr})
end
end
end
function BGen:end_asm_code()
self.ctype = "code"
end
function BGen:add_then_label()
@ -209,7 +233,7 @@ function BGen:switch_to_func_def()
end
function BGen:gen_output()
local out = {{"code", 0, ".code"}}
local out = {}
if #self.lInit > 0 then
for _,item in ipairs(self.lInit) do
@ -226,13 +250,11 @@ function BGen:gen_output()
end
end
if #self.lData > 0 then
table.insert(out, {"data", 999, ".data"})
for _,item in ipairs(self.lData) do
table.insert(out, item)
end
end
if #self.lText > 0 then
table.insert(out, {"ctext", 999, ".ctext"})
for _,item in ipairs(self.lText) do
table.insert(out, item)
end
@ -243,13 +265,13 @@ end
function BGen:gen_dbg_dump(output)
local out = {}
out[#out + 1] = "############ Code ###########"
out[#out + 1] = "#### Code ####"
for idx,tok in ipairs(output.lCode) do
local ctype, lineno, code = tok[1], tok[2], tok[3]
out[#out + 1] = string.format('%5s: (%d) "%s"', ctype, lineno, code)
end
out[#out + 1] = "############ Locals ###########"
out[#out + 1] = "#### Locals ####"
for func, item in pairs(output.locals) do
out[#out + 1] = string.format('function %s (%d):', func, item["@nsv@"]) -- number of variables
for id, offs in pairs(item) do

View File

@ -59,8 +59,9 @@ function BPars:definition()
elseif tok.type == T_NEWFILE then
self:add_item("file", tok.lineno, tok.val)
self:tk_match(T_NEWFILE)
self:end_asm_code()
elseif tok.type == T_ASMCODE then
self:add_item("code", tok.lineno, tok.val)
self:add_asm_token(tok)
self:tk_match(T_ASMCODE)
elseif tok.val ~= nil then
error(string.format("Unexpected item '%s'", tok.val))
@ -379,9 +380,10 @@ function BPars:asm_declaration()
local tok = self:tk_peek()
while tok.type == T_ASMCODE do
self:tk_match()
self:add_asm_code(tok.val)
self:add_asm_token(tok)
tok = self:tk_peek()
end
self:end_asm_code()
end
--[[

View File

@ -46,32 +46,11 @@ local lTypeString = {"ident", "number", "operand", "brace", "string", "asm code"
local lToken = {}
local tScannedFiles = {}
local strfind = string.find
local strsub = string.sub
local tinsert = table.insert
local function file_ext(filename)
local _, ext = unpack(string.split(filename, ".", true, 1))
return ext
end
local function split_into_lines(text)
local list = {}
local pos = 1
while true do
local first, last = strfind(text, "\n", pos)
if first then -- found?
tinsert(list, strsub(text, pos, first-1))
pos = last+1
else
tinsert(list, strsub(text, pos))
break
end
end
return list
end
local function char_to_val(char)
if #char == 2 then
return char:byte(1) * 256 + char:byte(2)
@ -80,7 +59,6 @@ local function char_to_val(char)
end
end
local BScan = vm16.BGen:new({})
function BScan:bscan_init()
@ -178,7 +156,7 @@ function BScan:scanner(filename)
table.insert(lToken, {type = T_NEWFILE, val = filename, lineno = 0})
local text = self.readfile(self.pos, filename)
for lineno, line in ipairs(split_into_lines(text)) do
for lineno, line in ipairs(vm16.splitlines(text)) do
self.lineno = lineno
if self.is_asm_code then
line = line:trim()
@ -222,7 +200,7 @@ function BScan:scan_dbg_dump()
for idx,tok in ipairs(self.lTok) do
if tok.type == T_NEWFILE then
out[idx] = string.format('%8s: ######## "%s" ########', lTypeString[tok.type], tok.val)
out[idx] = string.format('%8s: #### "%s" ####', lTypeString[tok.type], tok.val)
else
out[idx] = string.format('%8s: (%d) "%s"', lTypeString[tok.type], tok.lineno, tok.val)
end

32
lib.lua
View File

@ -8,6 +8,10 @@
See LICENSE.txt for more information
]]--
local strfind = string.find
local strsub = string.sub
local tinsert = table.insert
-- Returns the number of operands (0,1,2) based on the given opcode
function vm16.num_operands(opcode)
if opcode then
@ -25,3 +29,31 @@ function vm16.hex2number(s)
if not addr or addr == "" then addr = "0" end
return (tonumber(addr, 16) % 0x10000) or 0
end
-- Split a multi-line string into a list of lines
function vm16.splitlines(text)
local list = {}
local pos = 1
while true do
local first, last = strfind(text, "\n", pos)
if first then -- found?
tinsert(list, strsub(text, pos, first-1))
pos = last+1
else
tinsert(list, strsub(text, pos))
break
end
end
return list
end
function vm16.file_ext(filename)
local _, ext = unpack(string.split(filename, ".", true, 1))
return ext
end
function vm16.file_base(filename)
local name, _ = unpack(string.split(filename, ".", true, 1))
return name
end

View File

@ -12,9 +12,6 @@
-- for lazy programmers
local M = minetest.get_meta
local strfind = string.find
local strsub = string.sub
local tinsert = table.insert
local Cache = {} -- [hash] = {}
@ -41,23 +38,6 @@ function vm16.prog.get_linenum(lToken, addr)
return 0
end
function vm16.prog.strsplit(text)
local list = {}
local pos = 1
while true do
local first, last = strfind(text, "\n", pos)
if first then -- found?
tinsert(list, strsub(text, pos, first-1))
pos = last+1
else
tinsert(list, strsub(text, pos))
break
end
end
return list
end
function vm16.prog.to_char(val)
if val >= 32 and val <= 127 then
return string.char(val)
@ -80,13 +60,3 @@ function vm16.prog.get_cpu_def(cpu_pos)
return ndef.vm16_cpu
end
end
function vm16.prog.file_ext(filename)
local _, ext = unpack(string.split(filename, ".", true, 1))
return ext
end
function vm16.prog.file_base(filename)
local name, _ = unpack(string.split(filename, ".", true, 1))
return name
end