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

📄 dynasm.lua

📁 采用C语言写的Lua的解释器的代码!Lua不用介绍了吧
💻 LUA
📖 第 1 页 / 共 2 页
字号:
-------------------------------------------------------------------------------- DynASM. A dynamic assembler for code generation engines.-- Originally designed and implemented for LuaJIT.---- Copyright (C) 2005-2008 Mike Pall. All rights reserved.-- See below for full copyright notice.-------------------------------------------------------------------------------- Application information.local _info = {  name =	"DynASM",  description =	"A dynamic assembler for code generation engines",  version =	"1.1.4",  vernum =	 10104,  release =	"2008-01-29",  author =	"Mike Pall",  url =		"http://luajit.org/dynasm.html",  license =	"MIT",  copyright =	[[Copyright (C) 2005-2008 Mike Pall. All rights reserved.Permission is hereby granted, free of charge, to any person obtaininga copy of this software and associated documentation files (the"Software"), to deal in the Software without restriction, includingwithout limitation the rights to use, copy, modify, merge, publish,distribute, sublicense, and/or sell copies of the Software, and topermit persons to whom the Software is furnished to do so, subject tothe following conditions:The above copyright notice and this permission notice shall beincluded in all copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OFMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANYCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THESOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.[ MIT license: http://www.opensource.org/licenses/mit-license.php ]]],}-- Cache library functions.local type, pairs, ipairs = type, pairs, ipairslocal pcall, error, assert = pcall, error, assertlocal _s = stringlocal sub, match, gmatch, gsub = _s.sub, _s.match, _s.gmatch, _s.gsublocal format, rep, upper = _s.format, _s.rep, _s.upperlocal _t = tablelocal insert, remove, concat, sort = _t.insert, _t.remove, _t.concat, _t.sortlocal exit = os.exitlocal io = iolocal stdin, stdout, stderr = io.stdin, io.stdout, io.stderr-------------------------------------------------------------------------------- Program options.local g_opt = {}-- Global state for current file.local g_fname, g_curline, g_indent, g_lineno, g_synclineno, g_archlocal g_errcount = 0-- Write buffer for output file.local g_wbuffer, g_capbuffer-------------------------------------------------------------------------------- Write an output line (or callback function) to the buffer.local function wline(line, needindent)  local buf = g_capbuffer or g_wbuffer  buf[#buf+1] = needindent and g_indent..line or line  g_synclineno = g_synclineno + 1end-- Write assembler line as a comment, if requestd.local function wcomment(aline)  if g_opt.comment then    wline(g_opt.comment..aline..g_opt.endcomment, true)  endend-- Resync CPP line numbers.local function wsync()  if g_synclineno ~= g_lineno and g_opt.cpp then    wline("# "..g_lineno..' "'..g_fname..'"')    g_synclineno = g_lineno  endend-- Dummy action flush function. Replaced with arch-specific function later.local function wflush(term)end-- Dump all buffered output lines.local function wdumplines(out, buf)  for _,line in ipairs(buf) do    if type(line) == "string" then      assert(out:write(line, "\n"))    else      -- Special callback to dynamically insert lines after end of processing.      line(out)    end  endend-------------------------------------------------------------------------------- Emit an error. Processing continues with next statement.local function werror(msg)  error(format("%s:%s: error: %s:\n%s", g_fname, g_lineno, msg, g_curline), 0)end-- Emit a fatal error. Processing stops.local function wfatal(msg)  g_errcount = "fatal"  werror(msg)end-- Print a warning. Processing continues.local function wwarn(msg)  stderr:write(format("%s:%s: warning: %s:\n%s\n",    g_fname, g_lineno, msg, g_curline))end-- Print caught error message. But suppress excessive errors.local function wprinterr(...)  if type(g_errcount) == "number" then    -- Regular error.    g_errcount = g_errcount + 1    if g_errcount < 21 then -- Seems to be a reasonable limit.      stderr:write(...)    elseif g_errcount == 21 then      stderr:write(g_fname,	":*: warning: too many errors (suppressed further messages).\n")    end  else    -- Fatal error.    stderr:write(...)    return true -- Stop processing.  endend-------------------------------------------------------------------------------- Map holding all option handlers.local opt_map = {}local opt_current-- Print error and exit with error status.local function opterror(...)  stderr:write("dynasm.lua: ERROR: ", ...)  stderr:write("\n")  exit(1)end-- Get option parameter.local function optparam(args)  local argn = args.argn  local p = args[argn]  if not p then    opterror("missing parameter for option `", opt_current, "'.")  end  args.argn = argn + 1  return pend-------------------------------------------------------------------------------- Core pseudo-opcodes.local map_coreop = {}-- Dummy opcode map. Replaced by arch-specific map.local map_op = {}-- Forward declarations.local dostmtlocal readfile-------------------------------------------------------------------------------- Map for defines (initially empty, chains to arch-specific map).local map_def = {}-- Pseudo-opcode to define a substitution.map_coreop[".define_2"] = function(params, nparams)  if not params then return nparams == 1 and "name" or "name, subst" end  local name, def = params[1], params[2] or "1"  if not match(name, "^[%a_][%w_]*$") then werror("bad or duplicate define") end  map_def[name] = defendmap_coreop[".define_1"] = map_coreop[".define_2"]-- Define a substitution on the command line.function opt_map.D(args)  local namesubst = optparam(args)  local name, subst = match(namesubst, "^([%a_][%w_]*)=(.*)$")  if name then    map_def[name] = subst  elseif match(namesubst, "^[%a_][%w_]*$") then    map_def[namesubst] = "1"  else    opterror("bad define")  endend-- Undefine a substitution on the command line.function opt_map.U(args)  local name = optparam(args)  if match(name, "^[%a_][%w_]*$") then    map_def[name] = nil  else    opterror("bad define")  endend-- Helper for definesubst.local gotsubstlocal function definesubst_one(word)  local subst = map_def[word]  if subst then gotsubst = word; return subst else return word endend-- Iteratively substitute defines.local function definesubst(stmt)  -- Limit number of iterations.  for i=1,100 do    gotsubst = false    stmt = gsub(stmt, "#?[%w_]+", definesubst_one)    if not gotsubst then break end  end  if gotsubst then wfatal("recursive define involving `"..gotsubst.."'") end  return stmtend-- Dump all defines.local function dumpdefines(out, lvl)  local t = {}  for name in pairs(map_def) do    t[#t+1] = name  end  sort(t)  out:write("Defines:\n")  for _,name in ipairs(t) do    local subst = map_def[name]    if g_arch then subst = g_arch.revdef(subst) end    out:write(format("  %-20s %s\n", name, subst))  end  out:write("\n")end-------------------------------------------------------------------------------- Support variables for conditional assembly.local condlevel = 0local condstack = {}-- Evaluate condition with a Lua expression. Substitutions already performed.local function cond_eval(cond)  local func, err = loadstring("return "..cond)  if func then    setfenv(func, {}) -- No globals. All unknown identifiers evaluate to nil.    local ok, res = pcall(func)    if ok then      if res == 0 then return false end -- Oh well.      return not not res    end    err = res  end  wfatal("bad condition: "..err)end-- Skip statements until next conditional pseudo-opcode at the same level.local function stmtskip()  local dostmt_save = dostmt  local lvl = 0  dostmt = function(stmt)    local op = match(stmt, "^%s*(%S+)")    if op == ".if" then      lvl = lvl + 1    elseif lvl ~= 0 then      if op == ".endif" then lvl = lvl - 1 end    elseif op == ".elif" or op == ".else" or op == ".endif" then      dostmt = dostmt_save      dostmt(stmt)    end  endend-- Pseudo-opcodes for conditional assembly.map_coreop[".if_1"] = function(params)  if not params then return "condition" end  local lvl = condlevel + 1  local res = cond_eval(params[1])  condlevel = lvl  condstack[lvl] = res  if not res then stmtskip() endendmap_coreop[".elif_1"] = function(params)  if not params then return "condition" end  if condlevel == 0 then wfatal(".elif without .if") end  local lvl = condlevel  local res = condstack[lvl]  if res then    if res == "else" then wfatal(".elif after .else") end  else    res = cond_eval(params[1])    if res then      condstack[lvl] = res      return    end  end  stmtskip()endmap_coreop[".else_0"] = function(params)  if condlevel == 0 then wfatal(".else without .if") end  local lvl = condlevel  local res = condstack[lvl]  condstack[lvl] = "else"  if res then    if res == "else" then wfatal(".else after .else") end    stmtskip()  endendmap_coreop[".endif_0"] = function(params)  local lvl = condlevel  if lvl == 0 then wfatal(".endif without .if") end  condlevel = lvl - 1end-- Check for unfinished conditionals.local function checkconds()  if g_errcount ~= "fatal" and condlevel ~= 0 then    wprinterr(g_fname, ":*: error: unbalanced conditional\n")  endend-------------------------------------------------------------------------------- Search for a file in the given path and open it for reading.local function pathopen(path, name)  local dirsep = match(package.path, "\\") and "\\" or "/"  for _,p in ipairs(path) do    local fullname = p == "" and name or p..dirsep..name    local fin = io.open(fullname, "r")    if fin then      g_fname = fullname      return fin    end  endend-- Include a file.map_coreop[".include_1"] = function(params)  if not params then return "filename" end  local name = params[1]  -- Save state. Ugly, I know. but upvalues are fast.  local gf, gl, gcl, gi = g_fname, g_lineno, g_curline, g_indent  -- Read the included file.  local fatal = readfile(pathopen(g_opt.include, name) or			 wfatal("include file `"..name.."' not found"))  -- Restore state.  g_synclineno = -1  g_fname, g_lineno, g_curline, g_indent = gf, gl, gcl, gi  if fatal then wfatal("in include file") endend-- Make .include initially available, too.map_op[".include_1"] = map_coreop[".include_1"]-------------------------------------------------------------------------------- Support variables for macros.local mac_capture, mac_lineno, mac_namelocal mac_active = {}local mac_list = {}-- Pseudo-opcode to define a macro.map_coreop[".macro_*"] = function(mparams)  if not mparams then return "name [, params...]" end  -- Split off and validate macro name.  local name = remove(mparams, 1)  if not name then werror("missing macro name") end  if not (match(name, "^[%a_][%w_%.]*$") or match(name, "^%.[%w_%.]+$")) then    wfatal("bad macro name `"..name.."'")  end  -- Validate macro parameter names.  local mdup = {}  for _,mp in ipairs(mparams) do    if not match(mp, "^[%a_][%w_]*$") then      wfatal("bad macro parameter name `"..mp.."'")    end    if mdup[mp] then wfatal("duplicate macro parameter name `"..mp.."'") end    mdup[mp] = true  end  -- Check for duplicate or recursive macro definitions.  local opname = name.."_"..#mparams  if map_op[opname] or map_op[name.."_*"] then    wfatal("duplicate macro `"..name.."' ("..#mparams.." parameters)")  end  if mac_capture then wfatal("recursive macro definition") end  -- Enable statement capture.  local lines = {}  mac_lineno = g_lineno  mac_name = name  mac_capture = function(stmt) -- Statement capture function.    -- Stop macro definition with .endmacro pseudo-opcode.    if not match(stmt, "^%s*.endmacro%s*$") then      lines[#lines+1] = stmt      return    end    mac_capture = nil    mac_lineno = nil    mac_name = nil    mac_list[#mac_list+1] = opname    -- Add macro-op definition.    map_op[opname] = function(params)      if not params then return mparams, lines end      -- Protect against recursive macro invocation.      if mac_active[opname] then wfatal("recursive macro invocation") end      mac_active[opname] = true      -- Setup substitution map.      local subst = {}      for i,mp in ipairs(mparams) do subst[mp] = params[i] end      local mcom      if g_opt.maccomment and g_opt.comment then	mcom = " MACRO "..name.." ("..#mparams..")"	wcomment("{"..mcom)      end      -- Loop through all captured statements      for _,stmt in ipairs(lines) do	-- Substitute macro parameters.	local st = gsub(stmt, "[%w_]+", subst)	st = definesubst(st)	st = gsub(st, "%s*%.%.%s*", "") -- Token paste a..b.	if mcom and sub(st, 1, 1) ~= "|" then wcomment(st) end	-- Emit statement. Use a protected call for better diagnostics.	local ok, err = pcall(dostmt, st)	if not ok then	  -- Add the captured statement to the error.	  wprinterr(err, "\n", g_indent, "|  ", stmt,		    "\t[MACRO ", name, " (", #mparams, ")]\n")	end      end      if mcom then wcomment("}"..mcom) end      mac_active[opname] = nil    end  endend-- An .endmacro pseudo-opcode outside of a macro definition is an error.map_coreop[".endmacro_0"] = function(params)  wfatal(".endmacro without .macro")end-- Dump all macros and their contents (with -PP only).local function dumpmacros(out, lvl)  sort(mac_list)  out:write("Macros:\n")  for _,opname in ipairs(mac_list) do    local name = sub(opname, 1, -3)    local params, lines = map_op[opname]()    out:write(format("  %-20s %s\n", name, concat(params, ", ")))    if lvl > 1 then      for _,line in ipairs(lines) do	out:write("  |", line, "\n")      end      out:write("\n")    end  end  out:write("\n")end-- Check for unfinished macro definitions.local function checkmacros()  if mac_capture then    wprinterr(g_fname, ":", mac_lineno,	      ": error: unfinished .macro `", mac_name ,"'\n")  endend-------------------------------------------------------------------------------- Support variables for captures.local cap_lineno, cap_namelocal cap_buffers = {}local cap_used = {}-- Start a capture.map_coreop[".capture_1"] = function(params)  if not params then return "name" end  wflush()  local name = params[1]  if not match(name, "^[%a_][%w_]*$") then    wfatal("bad capture name `"..name.."'")  end  if cap_name then    wfatal("already capturing to `"..cap_name.."' since line "..cap_lineno)  end  cap_name = name  cap_lineno = g_lineno  -- Create or continue a capture buffer and start the output line capture.  local buf = cap_buffers[name]  if not buf then buf = {}; cap_buffers[name] = buf end  g_capbuffer = buf  g_synclineno = 0end-- Stop a capture.map_coreop[".endcapture_0"] = function(params)  wflush()  if not cap_name then wfatal(".endcapture without a valid .capture") end  cap_name = nil  cap_lineno = nil  g_capbuffer = nil  g_synclineno = 0end-- Dump a capture buffer.map_coreop[".dumpcapture_1"] = function(params)  if not params then return "name" end  wflush()  local name = params[1]  if not match(name, "^[%a_][%w_]*$") then    wfatal("bad capture name `"..name.."'")  end  cap_used[name] = true  wline(function(out)    local buf = cap_buffers[name]    if buf then wdumplines(out, buf) end

⌨️ 快捷键说明

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