Advertisement
Kep13

luau

Dec 21st, 2020
19
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.62 KB | None | 0 0
  1. --[[--------------------------------------------------------------------
  2.  
  3. ldump.lua
  4. Save precompiled Lua chunks
  5. This file is part of Yueliang.
  6.  
  7. Copyright (c) 2006 Kein-Hong Man <khman@users.sf.net>
  8. The COPYRIGHT file describes the conditions
  9. under which this software may be distributed.
  10.  
  11. See the ChangeLog for more information.
  12.  
  13. ----------------------------------------------------------------------]]
  14.  
  15. --[[--------------------------------------------------------------------
  16. -- Notes:
  17. -- * WARNING! byte order (little endian) and data type sizes for header
  18. -- signature values hard-coded; see luaU:header
  19. -- * chunk writer generators are included, see below
  20. -- * one significant difference is that instructions are still in table
  21. -- form (with OP/A/B/C/Bx fields) and luaP:Instruction() is needed to
  22. -- convert them into 4-char strings
  23. --
  24. -- Not implemented:
  25. -- * DumpVar, DumpMem has been removed
  26. -- * DumpVector folded into folded into DumpDebug, DumpCode
  27. --
  28. -- Added:
  29. -- * for convenience, the following two functions have been added:
  30. -- luaU:make_setS: create a chunk writer that writes to a string
  31. -- luaU:make_setF: create a chunk writer that writes to a file
  32. -- (lua.h contains a typedef for lua_Writer/lua_Chunkwriter, and
  33. -- a Lua-based implementation exists, writer() in lstrlib.c)
  34. -- * luaU:ttype(o) (from lobject.h)
  35. -- * for converting number types to its binary equivalent:
  36. -- luaU:from_double(x): encode double value for writing
  37. -- luaU:from_int(x): encode integer value for writing
  38. -- (error checking is limited for these conversion functions)
  39. -- (double conversion does not support denormals or NaNs)
  40. --
  41. -- Changed in 5.1.x:
  42. -- * the dumper was mostly rewritten in Lua 5.1.x, so notes on the
  43. -- differences between 5.0.x and 5.1.x is limited
  44. -- * LUAC_VERSION bumped to 0x51, LUAC_FORMAT added
  45. -- * developer is expected to adjust LUAC_FORMAT in order to identify
  46. -- non-standard binary chunk formats
  47. -- * header signature code is smaller, has been simplified, and is
  48. -- tested as a single unit; its logic is shared with the undumper
  49. -- * no more endian conversion, invalid endianness mean rejection
  50. -- * opcode field sizes are no longer exposed in the header
  51. -- * code moved to front of a prototype, followed by constants
  52. -- * debug information moved to the end of the binary chunk, and the
  53. -- relevant functions folded into a single function
  54. -- * luaU:dump returns a writer status code
  55. -- * chunk writer now implements status code because dumper uses it
  56. -- * luaU:endianness removed
  57. ----------------------------------------------------------------------]]
  58.  
  59. --requires luaP
  60. local luaU = {}
  61. local luaP = require(script.Parent.LuaP)
  62.  
  63. -- mark for precompiled code ('<esc>Lua') (from lua.h)
  64. luaU.LUA_SIGNATURE = "\27Lua"
  65.  
  66. -- constants used by dumper (from lua.h)
  67. luaU.LUA_TNUMBER = 3
  68. luaU.LUA_TSTRING = 4
  69. luaU.LUA_TNIL = 0
  70. luaU.LUA_TBOOLEAN = 1
  71. luaU.LUA_TNONE = -1
  72.  
  73. -- constants for header of binary files (from lundump.h)
  74. luaU.LUAC_VERSION = 0x51 -- this is Lua 5.1
  75. luaU.LUAC_FORMAT = 0 -- this is the official format
  76. luaU.LUAC_HEADERSIZE = 12 -- size of header of binary files
  77.  
  78. --[[--------------------------------------------------------------------
  79. -- Additional functions to handle chunk writing
  80. -- * to use make_setS and make_setF, see test_ldump.lua elsewhere
  81. ----------------------------------------------------------------------]]
  82.  
  83. ------------------------------------------------------------------------
  84. -- create a chunk writer that writes to a string
  85. -- * returns the writer function and a table containing the string
  86. -- * to get the final result, look in buff.data
  87. ------------------------------------------------------------------------
  88. function luaU:make_setS()
  89. local buff = {}
  90. buff.data = ""
  91. local writer =
  92. function(s, buff) -- chunk writer
  93. if not s then return 0 end
  94. buff.data = buff.data..s
  95. return 0
  96. end
  97. return writer, buff
  98. end
  99.  
  100. ------------------------------------------------------------------------
  101. -- create a chunk writer that writes to a file
  102. -- * returns the writer function and a table containing the file handle
  103. -- * if a nil is passed, then writer should close the open file
  104. ------------------------------------------------------------------------
  105.  
  106. --[[
  107. function luaU:make_setF(filename)
  108. local buff = {}
  109. buff.h = io.open(filename, "wb")
  110. if not buff.h then return nil end
  111. local writer =
  112. function(s, buff) -- chunk writer
  113. if not buff.h then return 0 end
  114. if not s then
  115. if buff.h:close() then return 0 end
  116. else
  117. if buff.h:write(s) then return 0 end
  118. end
  119. return 1
  120. end
  121. return writer, buff
  122. end--]]
  123.  
  124. ------------------------------------------------------------------------
  125. -- works like the lobject.h version except that TObject used in these
  126. -- scripts only has a 'value' field, no 'tt' field (native types used)
  127. ------------------------------------------------------------------------
  128. function luaU:ttype(o)
  129. local tt = type(o.value)
  130. if tt == "number" then return self.LUA_TNUMBER
  131. elseif tt == "string" then return self.LUA_TSTRING
  132. elseif tt == "nil" then return self.LUA_TNIL
  133. elseif tt == "boolean" then return self.LUA_TBOOLEAN
  134. else
  135. return self.LUA_TNONE -- the rest should not appear
  136. end
  137. end
  138.  
  139. -----------------------------------------------------------------------
  140. -- converts a IEEE754 double number to an 8-byte little-endian string
  141. -- * luaU:from_double() and luaU:from_int() are adapted from ChunkBake
  142. -- * supports +/- Infinity, but not denormals or NaNs
  143. -----------------------------------------------------------------------
  144. function luaU:from_double(x)
  145. local function grab_byte(v)
  146. local c = v % 256
  147. return (v - c) / 256, string.char(c)
  148. end
  149. local sign = 0
  150. if x < 0 then sign = 1; x = -x end
  151. local mantissa, exponent = math.frexp(x)
  152. if x == 0 then -- zero
  153. mantissa, exponent = 0, 0
  154. elseif x == 1/0 then
  155. mantissa, exponent = 0, 2047
  156. else
  157. mantissa = (mantissa * 2 - 1) * math.ldexp(0.5, 53)
  158. exponent = exponent + 1022
  159. end
  160. local v, byte = "" -- convert to bytes
  161. x = math.floor(mantissa)
  162. for i = 1,6 do
  163. x, byte = grab_byte(x); v = v..byte -- 47:0
  164. end
  165. x, byte = grab_byte(exponent * 16 + x); v = v..byte -- 55:48
  166. x, byte = grab_byte(sign * 128 + x); v = v..byte -- 63:56
  167. return v
  168. end
  169.  
  170. -----------------------------------------------------------------------
  171. -- converts a number to a little-endian 32-bit integer string
  172. -- * input value assumed to not overflow, can be signed/unsigned
  173. -----------------------------------------------------------------------
  174. function luaU:from_int(x)
  175. local v = ""
  176. x = math.floor(x)
  177. if x < 0 then x = 4294967296 + x end -- ULONG_MAX+1
  178. for i = 1, 4 do
  179. local c = x % 256
  180. v = v..string.char(c); x = math.floor(x / 256)
  181. end
  182. return v
  183. end
  184.  
  185. --[[--------------------------------------------------------------------
  186. -- Functions to make a binary chunk
  187. -- * many functions have the size parameter removed, since output is
  188. -- in the form of a string and some sizes are implicit or hard-coded
  189. ----------------------------------------------------------------------]]
  190.  
  191. --[[--------------------------------------------------------------------
  192. -- struct DumpState:
  193. -- L -- lua_State (not used in this script)
  194. -- writer -- lua_Writer (chunk writer function)
  195. -- data -- void* (chunk writer context or data already written)
  196. -- strip -- if true, don't write any debug information
  197. -- status -- if non-zero, an error has occured
  198. ----------------------------------------------------------------------]]
  199.  
  200. ------------------------------------------------------------------------
  201. -- dumps a block of bytes
  202. -- * lua_unlock(D.L), lua_lock(D.L) unused
  203. ------------------------------------------------------------------------
  204. function luaU:DumpBlock(b, D)
  205. if D.status == 0 then
  206. -- lua_unlock(D->L);
  207. D.status = D.write(b, D.data)
  208. -- lua_lock(D->L);
  209. end
  210. end
  211.  
  212. ------------------------------------------------------------------------
  213. -- dumps a char
  214. ------------------------------------------------------------------------
  215. function luaU:DumpChar(y, D)
  216. self:DumpBlock(string.char(y), D)
  217. end
  218.  
  219. ------------------------------------------------------------------------
  220. -- dumps a 32-bit signed or unsigned integer (for int) (hard-coded)
  221. ------------------------------------------------------------------------
  222. function luaU:DumpInt(x, D)
  223. self:DumpBlock(self:from_int(x), D)
  224. end
  225.  
  226. ------------------------------------------------------------------------
  227. -- dumps a lua_Number (hard-coded as a double)
  228. ------------------------------------------------------------------------
  229. function luaU:DumpNumber(x, D)
  230. self:DumpBlock(self:from_double(x), D)
  231. end
  232.  
  233. ------------------------------------------------------------------------
  234. -- dumps a Lua string (size type is hard-coded)
  235. ------------------------------------------------------------------------
  236. function luaU:DumpString(s, D)
  237. if s == nil then
  238. self:DumpInt(0, D)
  239. else
  240. s = s.."\0" -- include trailing '\0'
  241. self:DumpInt(#s, D)
  242. self:DumpBlock(s, D)
  243. end
  244. end
  245.  
  246. ------------------------------------------------------------------------
  247. -- dumps instruction block from function prototype
  248. ------------------------------------------------------------------------
  249. function luaU:DumpCode(f, D)
  250. local n = f.sizecode
  251. --was DumpVector
  252. self:DumpInt(n, D)
  253. for i = 0, n - 1 do
  254. self:DumpBlock(luaP:Instruction(f.code[i]), D)
  255. end
  256. end
  257.  
  258. ------------------------------------------------------------------------
  259. -- dump constant pool from function prototype
  260. -- * bvalue(o), nvalue(o) and rawtsvalue(o) macros removed
  261. ------------------------------------------------------------------------
  262. function luaU:DumpConstants(f, D)
  263. local n = f.sizek
  264. self:DumpInt(n, D)
  265. for i = 0, n - 1 do
  266. local o = f.k[i] -- TValue
  267. local tt = self:ttype(o)
  268. self:DumpChar(tt, D)
  269. if tt == self.LUA_TNIL then
  270. elseif tt == self.LUA_TBOOLEAN then
  271. self:DumpChar(o.value and 1 or 0, D)
  272. elseif tt == self.LUA_TNUMBER then
  273. self:DumpNumber(o.value, D)
  274. elseif tt == self.LUA_TSTRING then
  275. self:DumpString(o.value, D)
  276. else
  277. --lua_assert(0) -- cannot happen
  278. end
  279. end
  280. n = f.sizep
  281. self:DumpInt(n, D)
  282. for i = 0, n - 1 do
  283. self:DumpFunction(f.p[i], f.source, D)
  284. end
  285. end
  286.  
  287. ------------------------------------------------------------------------
  288. -- dump debug information
  289. ------------------------------------------------------------------------
  290. function luaU:DumpDebug(f, D)
  291. local n
  292. n = D.strip and 0 or f.sizelineinfo -- dump line information
  293. --was DumpVector
  294. self:DumpInt(n, D)
  295. for i = 0, n - 1 do
  296. self:DumpInt(f.lineinfo[i], D)
  297. end
  298. n = D.strip and 0 or f.sizelocvars -- dump local information
  299. self:DumpInt(n, D)
  300. for i = 0, n - 1 do
  301. self:DumpString(f.locvars[i].varname, D)
  302. self:DumpInt(f.locvars[i].startpc, D)
  303. self:DumpInt(f.locvars[i].endpc, D)
  304. end
  305. n = D.strip and 0 or f.sizeupvalues -- dump upvalue information
  306. self:DumpInt(n, D)
  307. for i = 0, n - 1 do
  308. self:DumpString(f.upvalues[i], D)
  309. end
  310. end
  311.  
  312. ------------------------------------------------------------------------
  313. -- dump child function prototypes from function prototype
  314. ------------------------------------------------------------------------
  315. function luaU:DumpFunction(f, p, D)
  316. local source = f.source
  317. if source == p or D.strip then source = nil end
  318. self:DumpString(source, D)
  319. self:DumpInt(f.lineDefined, D)
  320. self:DumpInt(f.lastlinedefined, D)
  321. self:DumpChar(f.nups, D)
  322. self:DumpChar(f.numparams, D)
  323. self:DumpChar(f.is_vararg, D)
  324. self:DumpChar(f.maxstacksize, D)
  325. self:DumpCode(f, D)
  326. self:DumpConstants(f, D)
  327. self:DumpDebug(f, D)
  328. end
  329.  
  330. ------------------------------------------------------------------------
  331. -- dump Lua header section (some sizes hard-coded)
  332. ------------------------------------------------------------------------
  333. function luaU:DumpHeader(D)
  334. local h = self:header()
  335. assert(#h == self.LUAC_HEADERSIZE) -- fixed buffer now an assert
  336. self:DumpBlock(h, D)
  337. end
  338.  
  339. ------------------------------------------------------------------------
  340. -- make header (from lundump.c)
  341. -- returns the header string
  342. ------------------------------------------------------------------------
  343. function luaU:header()
  344. local x = 1
  345. return self.LUA_SIGNATURE..
  346. string.char(
  347. self.LUAC_VERSION,
  348. self.LUAC_FORMAT,
  349. x, -- endianness (1=little)
  350. 4, -- sizeof(int)
  351. 4, -- sizeof(size_t)
  352. 4, -- sizeof(Instruction)
  353. 8, -- sizeof(lua_Number)
  354. 0) -- is lua_Number integral?
  355. end
  356.  
  357. ------------------------------------------------------------------------
  358. -- dump Lua function as precompiled chunk
  359. -- (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip)
  360. -- * w, data are created from make_setS, make_setF
  361. ------------------------------------------------------------------------
  362. function luaU:dump(L, f, w, data, strip)
  363. local D = {} -- DumpState
  364. D.L = L
  365. D.write = w
  366. D.data = data
  367. D.strip = strip
  368. D.status = 0
  369. self:DumpHeader(D)
  370. self:DumpFunction(f, nil, D)
  371. -- added: for a chunk writer writing to a file, this final call with
  372. -- nil data is to indicate to the writer to close the file
  373. D.write(nil, D.data)
  374. return D.status
  375. end
  376.  
  377. return luaU
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement