⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dynasm.lua

📁 采用C语言写的Lua的解释器的代码!Lua不用介绍了吧
💻 LUA
📖 第 1 页 / 共 2 页
字号:
  end)  g_synclineno = 0end-- Dump all captures and their buffers (with -PP only).local function dumpcaptures(out, lvl)  out:write("Captures:\n")  for name,buf in pairs(cap_buffers) do    out:write(format("  %-20s %4s)\n", name, "("..#buf))    if lvl > 1 then      local bar = rep("=", 76)      out:write("  ", bar, "\n")      for _,line in ipairs(buf) do	out:write("  ", line, "\n")      end      out:write("  ", bar, "\n\n")    end  end  out:write("\n")end-- Check for unfinished or unused captures.local function checkcaptures()  if cap_name then    wprinterr(g_fname, ":", cap_lineno,	      ": error: unfinished .capture `", cap_name,"'\n")    return  end  for name in pairs(cap_buffers) do    if not cap_used[name] then      wprinterr(g_fname, ":*: error: missing .dumpcapture ", name ,"\n")    end  endend-------------------------------------------------------------------------------- Sections names.local map_sections = {}-- Pseudo-opcode to define code sections.-- TODO: Data sections, BSS sections. Needs extra C code and API.map_coreop[".section_*"] = function(params)  if not params then return "name..." end  if #map_sections > 0 then werror("duplicate section definition") end  wflush()  for sn,name in ipairs(params) do    local opname = "."..name.."_0"    if not match(name, "^[%a][%w_]*$") or       map_op[opname] or map_op["."..name.."_*"] then      werror("bad section name `"..name.."'")    end    map_sections[#map_sections+1] = name    wline(format("#define DASM_SECTION_%s\t%d", upper(name), sn-1))    map_op[opname] = function(params) g_arch.section(sn-1) end  end  wline(format("#define DASM_MAXSECTION\t\t%d", #map_sections))end-- Dump all sections.local function dumpsections(out, lvl)  out:write("Sections:\n")  for _,name in ipairs(map_sections) do    out:write(format("  %s\n", name))  end  out:write("\n")end-------------------------------------------------------------------------------- Load architecture-specific module.local function loadarch(arch)  if not match(arch, "^[%w_]+$") then return "bad arch name" end  local ok, m_arch = pcall(require, "dasm_"..arch)  if not ok then return "cannot load module: "..m_arch end  g_arch = m_arch  wflush = m_arch.passcb(wline, werror, wfatal, wwarn)  m_arch.setup(arch, g_opt)  map_op, map_def = m_arch.mergemaps(map_coreop, map_def)end-- Dump architecture description.function opt_map.dumparch(args)  local name = optparam(args)  if not g_arch then    local err = loadarch(name)    if err then opterror(err) end  end  local t = {}  for name in pairs(map_coreop) do t[#t+1] = name end  for name in pairs(map_op) do t[#t+1] = name end  sort(t)  local out = stdout  local _arch = g_arch._info  out:write(format("%s version %s, released %s, %s\n",    _info.name, _info.version, _info.release, _info.url))  g_arch.dumparch(out)  local pseudo = true  out:write("Pseudo-Opcodes:\n")  for _,sname in ipairs(t) do    local name, nparam = match(sname, "^(.+)_([0-9%*])$")    if name then      if pseudo and sub(name, 1, 1) ~= "." then	out:write("\nOpcodes:\n")	pseudo = false      end      local f = map_op[sname]      local s      if nparam ~= "*" then nparam = nparam + 0 end      if nparam == 0 then	s = ""      elseif type(f) == "string" then	s = map_op[".template__"](nil, f, nparam)      else	s = f(nil, nparam)      end      if type(s) == "table" then	for _,s2 in ipairs(s) do	  out:write(format("  %-12s %s\n", name, s2))	end      else	out:write(format("  %-12s %s\n", name, s))      end    end  end  out:write("\n")  exit(0)end-- Pseudo-opcode to set the architecture.-- Only initially available (map_op is replaced when called).map_op[".arch_1"] = function(params)  if not params then return "name" end  local err = loadarch(params[1])  if err then wfatal(err) endend-- Dummy .arch pseudo-opcode to improve the error report.map_coreop[".arch_1"] = function(params)  if not params then return "name" end  wfatal("duplicate .arch statement")end-------------------------------------------------------------------------------- Dummy pseudo-opcode. Don't confuse '.nop' with 'nop'.map_coreop[".nop_*"] = function(params)  if not params then return "[ignored...]" endend-- Pseudo-opcodes to raise errors.map_coreop[".error_1"] = function(params)  if not params then return "message" end  werror(params[1])endmap_coreop[".fatal_1"] = function(params)  if not params then return "message" end  wfatal(params[1])end-- Dump all user defined elements.local function dumpdef(out)  local lvl = g_opt.dumpdef  if lvl == 0 then return end  dumpsections(out, lvl)  dumpdefines(out, lvl)  if g_arch then g_arch.dumpdef(out, lvl) end  dumpmacros(out, lvl)  dumpcaptures(out, lvl)end-------------------------------------------------------------------------------- Helper for splitstmt.local splitlvllocal function splitstmt_one(c)  if c == "(" then    splitlvl = ")"..splitlvl  elseif c == "[" then    splitlvl = "]"..splitlvl  elseif c == ")" or c == "]" then    if sub(splitlvl, 1, 1) ~= c then werror("unbalanced () or []") end    splitlvl = sub(splitlvl, 2)  elseif splitlvl == "" then    return " \0 "  end  return cend-- Split statement into (pseudo-)opcode and params.local function splitstmt(stmt)  -- Convert label with trailing-colon into .label statement.  local label = match(stmt, "^%s*(.+):%s*$")  if label then return ".label", {label} end  -- Split at commas and equal signs, but obey parentheses and brackets.  splitlvl = ""  stmt = gsub(stmt, "[,%(%)%[%]]", splitstmt_one)  if splitlvl ~= "" then werror("unbalanced () or []") end  -- Split off opcode.  local op, other = match(stmt, "^%s*([^%s%z]+)%s*(.*)$")  if not op then werror("bad statement syntax") end  -- Split parameters.  local params = {}  for p in gmatch(other, "%s*(%Z+)%z?") do    params[#params+1] = gsub(p, "%s+$", "")  end  if #params > 16 then werror("too many parameters") end  params.op = op  return op, paramsend-- Process a single statement.dostmt = function(stmt)  -- Ignore empty statements.  if match(stmt, "^%s*$") then return end  -- Capture macro defs before substitution.  if mac_capture then return mac_capture(stmt) end  stmt = definesubst(stmt)  -- Emit C code without parsing the line.  if sub(stmt, 1, 1) == "|" then    local tail = sub(stmt, 2)    wflush()    if sub(tail, 1, 2) == "//" then wcomment(tail) else wline(tail, true) end    return  end  -- Split into (pseudo-)opcode and params.  local op, params = splitstmt(stmt)  -- Get opcode handler (matching # of parameters or generic handler).  local f = map_op[op.."_"..#params] or map_op[op.."_*"]  if not f then    if not g_arch then wfatal("first statement must be .arch") end    -- Improve error report.    for i=0,16 do      if map_op[op.."_"..i] then	werror("wrong number of parameters for `"..op.."'")      end    end    werror("unknown statement `"..op.."'")  end  -- Call opcode handler or special handler for template strings.  if type(f) == "string" then    map_op[".template__"](params, f)  else    f(params)  endend-- Process a single line.local function doline(line)  if g_opt.flushline then wflush() end  -- Assembler line?  local indent, aline = match(line, "^(%s*)%|(.*)$")  if not aline then    -- No, plain C code line, need to flush first.    wflush()    wsync()    wline(line, false)    return  end  g_indent = indent -- Remember current line indentation.  -- Emit C code (even from macros). Avoids echo and line parsing.  if sub(aline, 1, 1) == "|" then    if not mac_capture then      wsync()    elseif g_opt.comment then      wsync()      wcomment(aline)    end    dostmt(aline)    return  end  -- Echo assembler line as a comment.  if g_opt.comment then    wsync()    wcomment(aline)  end  -- Strip assembler comments.  aline = gsub(aline, "//.*$", "")  -- Split line into statements at semicolons.  if match(aline, ";") then    for stmt in gmatch(aline, "[^;]+") do dostmt(stmt) end  else    dostmt(aline)  endend-------------------------------------------------------------------------------- Write DynASM header.local function dasmhead(out)  out:write(format([[/*** This file has been pre-processed with DynASM.** %s** DynASM version %s, DynASM %s version %s** DO NOT EDIT! The original file is in "%s".*/#if DASM_VERSION != %d#error "Version mismatch between DynASM and included encoding engine"#endif]], _info.url,    _info.version, g_arch._info.arch, g_arch._info.version,    g_fname, _info.vernum))end-- Read input file.readfile = function(fin)  g_indent = ""  g_lineno = 0  g_synclineno = -1  -- Process all lines.  for line in fin:lines() do    g_lineno = g_lineno + 1    g_curline = line    local ok, err = pcall(doline, line)    if not ok and wprinterr(err, "\n") then return true end  end  wflush()  -- Close input file.  assert(fin == stdin or fin:close())end-- Write output file.local function writefile(outfile)  local fout  -- Open output file.  if outfile == nil or outfile == "-" then    fout = stdout  else    fout = assert(io.open(outfile, "w"))  end  -- Write all buffered lines  wdumplines(fout, g_wbuffer)  -- Close output file.  assert(fout == stdout or fout:close())  -- Optionally dump definitions.  dumpdef(fout == stdout and stderr or stdout)end-- Translate an input file to an output file.local function translate(infile, outfile)  g_wbuffer = {}  g_indent = ""  g_lineno = 0  g_synclineno = -1  -- Put header.  wline(dasmhead)  -- Read input file.  local fin  if infile == "-" then    g_fname = "(stdin)"    fin = stdin  else    g_fname = infile    fin = assert(io.open(infile, "r"))  end  readfile(fin)  -- Check for errors.  if not g_arch then    wprinterr(g_fname, ":*: error: missing .arch directive\n")  end  checkconds()  checkmacros()  checkcaptures()  if g_errcount ~= 0 then    stderr:write(g_fname, ":*: info: ", g_errcount, " error",      (type(g_errcount) == "number" and g_errcount > 1) and "s" or "",      " in input file -- no output file generated.\n")    dumpdef(stderr)    exit(1)  end  -- Write output file.  writefile(outfile)end-------------------------------------------------------------------------------- Print help text.function opt_map.help()  stdout:write("DynASM -- ", _info.description, ".\n")  stdout:write("DynASM ", _info.version, " ", _info.release, "  ", _info.url, "\n")  stdout:write[[Usage: dynasm [OPTION]... INFILE.dasc|-  -h, --help           Display this help text.  -V, --version        Display version and copyright information.  -o, --outfile FILE   Output file name (default is stdout).  -I, --include DIR    Add directory to the include search path.  -c, --ccomment       Use /* */ comments for assembler lines.  -C, --cppcomment     Use // comments for assembler lines (default).  -N, --nocomment      Suppress assembler lines in output.  -M, --maccomment     Show macro expansions as comments (default off).  -L, --nolineno       Suppress CPP line number information in output.  -F, --flushline      Flush action list for every line.  -D NAME[=SUBST]      Define a substitution.  -U NAME              Undefine a substitution.  -P, --dumpdef        Dump defines, macros, etc. Repeat for more output.  -A, --dumparch ARCH  Load architecture ARCH and dump description.]]  exit(0)end-- Print version information.function opt_map.version()  stdout:write(format("%s version %s, released %s\n%s\n\n%s",    _info.name, _info.version, _info.release, _info.url, _info.copyright))  exit(0)end-- Misc. options.function opt_map.outfile(args) g_opt.outfile = optparam(args) endfunction opt_map.include(args) insert(g_opt.include, 1, optparam(args)) endfunction opt_map.ccomment() g_opt.comment = "/*|"; g_opt.endcomment = " */" endfunction opt_map.cppcomment() g_opt.comment = "//|"; g_opt.endcomment = "" endfunction opt_map.nocomment() g_opt.comment = false endfunction opt_map.maccomment() g_opt.maccomment = true endfunction opt_map.nolineno() g_opt.cpp = false endfunction opt_map.flushline() g_opt.flushline = true endfunction opt_map.dumpdef() g_opt.dumpdef = g_opt.dumpdef + 1 end-------------------------------------------------------------------------------- Short aliases for long options.local opt_alias = {  h = "help", ["?"] = "help", V = "version",  o = "outfile", I = "include",  c = "ccomment", C = "cppcomment", N = "nocomment", M = "maccomment",  L = "nolineno", F = "flushline",  P = "dumpdef", A = "dumparch",}-- Parse single option.local function parseopt(opt, args)  opt_current = #opt == 1 and "-"..opt or "--"..opt  local f = opt_map[opt] or opt_map[opt_alias[opt]]  if not f then    opterror("unrecognized option `", opt_current, "'. Try `--help'.\n")  end  f(args)end-- Parse arguments.local function parseargs(args)  -- Default options.  g_opt.comment = "//|"  g_opt.endcomment = ""  g_opt.cpp = true  g_opt.dumpdef = 0  g_opt.include = { "" }  -- Process all option arguments.  args.argn = 1  repeat    local a = args[args.argn]    if not a then break end    local lopt, opt = match(a, "^%-(%-?)(.+)")    if not opt then break end    args.argn = args.argn + 1    if lopt == "" then      -- Loop through short options.      for o in gmatch(opt, ".") do parseopt(o, args) end    else      -- Long option.      parseopt(opt, args)    end  until false  -- Check for proper number of arguments.  local nargs = #args - args.argn + 1  if nargs ~= 1 then    if nargs == 0 then      if g_opt.dumpdef > 0 then return dumpdef(stdout) end    end    opt_map.help()  end  -- Translate a single input file to a single output file  -- TODO: Handle multiple files?  translate(args[args.argn], g_opt.outfile)end-------------------------------------------------------------------------------- Add the directory dynasm.lua resides in to the Lua module search path.local arg = argif arg and arg[0] then  local prefix = match(arg[0], "^(.*/)")  if prefix then package.path = prefix.."?.lua;"..package.path endend-- Start DynASM.parseargs{...}------------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -