const char bc_lua[] =
"----------------------------------------------------------------------------\n"
"-- LuaJIT bytecode listing module.\n"
"--\n"
"-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.\n"
"-- Released under the MIT license. See Copyright Notice in luajit.h\n"
"----------------------------------------------------------------------------\n"
"--\n"
"-- This module lists the bytecode of a Lua function. If it's loaded by -jbc\n"
"-- it hooks into the parser and lists all functions of a chunk as they\n"
"-- are parsed.\n"
"--\n"
"-- Example usage:\n"
"--\n"
"--   luajit -jbc -e 'local x=0; for i=1,1e6 do x=x+i end; print(x)'\n"
"--   luajit -jbc=- foo.lua\n"
"--   luajit -jbc=foo.list foo.lua\n"
"--\n"
"-- Default output is to stderr. To redirect the output to a file, pass a\n"
"-- filename as an argument (use '-' for stdout) or set the environment\n"
"-- variable LUAJIT_LISTFILE. The file is overwritten every time the module\n"
"-- is started.\n"
"--\n"
"-- This module can also be used programmatically:\n"
"--\n"
"--   local bc = require(\"jit.bc\")\n"
"--\n"
"--   local function foo() print(\"hello\") end\n"
"--\n"
"--   bc.dump(foo)           --> -- BYTECODE -- [...]\n"
"--   print(bc.line(foo, 2)) --> 0002    KSTR     1   1      ; \"hello\"\n"
"--\n"
"--   local out = {\n"
"--     -- Do something with each line:\n"
"--     write = function(t, ...) io.write(...) end,\n"
"--     close = function(t) end,\n"
"--     flush = function(t) end,\n"
"--   }\n"
"--   bc.dump(foo, out)\n"
"--\n"
"------------------------------------------------------------------------------\n"
"\n"
"-- Cache some library functions and objects.\n"
"local jit = require(\"jit\")\n"
"assert(jit.version_num == 20100, \"LuaJIT core/library version mismatch\")\n"
"local jutil = require(\"jit.util\")\n"
"local vmdef = require(\"jit.vmdef\")\n"
"local bit = require(\"bit\")\n"
"local sub, gsub, format = string.sub, string.gsub, string.format\n"
"local byte, band, shr = string.byte, bit.band, bit.rshift\n"
"local funcinfo, funcbc, funck = jutil.funcinfo, jutil.funcbc, jutil.funck\n"
"local funcuvname = jutil.funcuvname\n"
"local bcnames = vmdef.bcnames\n"
"local stdout, stderr = io.stdout, io.stderr\n"
"\n"
"------------------------------------------------------------------------------\n"
"\n"
"local function ctlsub(c)\n"
"  if c == \"\\n\" then return \"\\\\n\"\n"
"  elseif c == \"\\r\" then return \"\\\\r\"\n"
"  elseif c == \"\\t\" then return \"\\\\t\"\n"
"  else return format(\"\\\\%03d\", byte(c))\n"
"  end\n"
"end\n"
"\n"
"-- Return one bytecode line.\n"
"local function bcline(func, pc, prefix)\n"
"  local ins, m = funcbc(func, pc)\n"
"  if not ins then return end\n"
"  local ma, mb, mc = band(m, 7), band(m, 15*8), band(m, 15*128)\n"
"  local a = band(shr(ins, 8), 0xff)\n"
"  local oidx = 6*band(ins, 0xff)\n"
"  local op = sub(bcnames, oidx+1, oidx+6)\n"
"  local s = format(\"%04d %s %-6s %3s \",\n"
"    pc, prefix or \"  \", op, ma == 0 and \"\" or a)\n"
"  local d = shr(ins, 16)\n"
"  if mc == 13*128 then -- BCMjump\n"
"    return format(\"%s=> %04d\\n\", s, pc+d-0x7fff)\n"
"  end\n"
"  if mb ~= 0 then\n"
"    d = band(d, 0xff)\n"
"  elseif mc == 0 then\n"
"    return s..\"\\n\"\n"
"  end\n"
"  local kc\n"
"  if mc == 10*128 then -- BCMstr\n"
"    kc = funck(func, -d-1)\n"
"    kc = format(#kc > 40 and '\"%.40s\"~' or '\"%s\"', gsub(kc, \"%c\", ctlsub))\n"
"  elseif mc == 9*128 then -- BCMnum\n"
"    kc = funck(func, d)\n"
"    if op == \"TSETM \" then kc = kc - 2^52 end\n"
"  elseif mc == 12*128 then -- BCMfunc\n"
"    local fi = funcinfo(funck(func, -d-1))\n"
"    if fi.ffid then\n"
"      kc = vmdef.ffnames[fi.ffid]\n"
"    else\n"
"      kc = fi.loc\n"
"    end\n"
"  elseif mc == 5*128 then -- BCMuv\n"
"    kc = funcuvname(func, d)\n"
"  end\n"
"  if ma == 5 then -- BCMuv\n"
"    local ka = funcuvname(func, a)\n"
"    if kc then kc = ka..\" ; \"..kc else kc = ka end\n"
"  end\n"
"  if mb ~= 0 then\n"
"    local b = shr(ins, 24)\n"
"    if kc then return format(\"%s%3d %3d  ; %s\\n\", s, b, d, kc) end\n"
"    return format(\"%s%3d %3d\\n\", s, b, d)\n"
"  end\n"
"  if kc then return format(\"%s%3d      ; %s\\n\", s, d, kc) end\n"
"  if mc == 7*128 and d > 32767 then d = d - 65536 end -- BCMlits\n"
"  return format(\"%s%3d\\n\", s, d)\n"
"end\n"
"\n"
"-- Collect branch targets of a function.\n"
"local function bctargets(func)\n"
"  local target = {}\n"
"  for pc=1,1000000000 do\n"
"    local ins, m = funcbc(func, pc)\n"
"    if not ins then break end\n"
"    if band(m, 15*128) == 13*128 then target[pc+shr(ins, 16)-0x7fff] = true end\n"
"  end\n"
"  return target\n"
"end\n"
"\n"
"-- Dump bytecode instructions of a function.\n"
"local function bcdump(func, out, all)\n"
"  if not out then out = stdout end\n"
"  local fi = funcinfo(func)\n"
"  if all and fi.children then\n"
"    for n=-1,-1000000000,-1 do\n"
"      local k = funck(func, n)\n"
"      if not k then break end\n"
"      if type(k) == \"proto\" then bcdump(k, out, true) end\n"
"    end\n"
"  end\n"
"  out:write(format(\"-- BYTECODE -- %s-%d\\n\", fi.loc, fi.lastlinedefined))\n"
"  local target = bctargets(func)\n"
"  for pc=1,1000000000 do\n"
"    local s = bcline(func, pc, target[pc] and \"=>\")\n"
"    if not s then break end\n"
"    out:write(s)\n"
"  end\n"
"  out:write(\"\\n\")\n"
"  out:flush()\n"
"end\n"
"\n"
"------------------------------------------------------------------------------\n"
"\n"
"-- Active flag and output file handle.\n"
"local active, out\n"
"\n"
"-- List handler.\n"
"local function h_list(func)\n"
"  return bcdump(func, out)\n"
"end\n"
"\n"
"-- Detach list handler.\n"
"local function bclistoff()\n"
"  if active then\n"
"    active = false\n"
"    jit.attach(h_list)\n"
"    if out and out ~= stdout and out ~= stderr then out:close() end\n"
"    out = nil\n"
"  end\n"
"end\n"
"\n"
"-- Open the output file and attach list handler.\n"
"local function bcliston(outfile)\n"
"  if active then bclistoff() end\n"
"  if not outfile then outfile = os.getenv(\"LUAJIT_LISTFILE\") end\n"
"  if outfile then\n"
"    out = outfile == \"-\" and stdout or assert(io.open(outfile, \"w\"))\n"
"  else\n"
"    out = stderr\n"
"  end\n"
"  jit.attach(h_list, \"bc\")\n"
"  active = true\n"
"end\n"
"\n"
"-- Public module functions.\n"
"return {\n"
"  line = bcline,\n"
"  dump = bcdump,\n"
"  targets = bctargets,\n"
"  on = bcliston,\n"
"  off = bclistoff,\n"
"  start = bcliston -- For -j command line option.\n"
"}\n"
"\n"
""
;
