PageRenderTime 26ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/src/host/genminilua.lua

https://bitbucket.org/minux/luajit-2.0
Lua | 428 lines | 394 code | 27 blank | 7 comment | 39 complexity | 293e29f38119bcbf624e10eff1e1fbd8 MD5 | raw file
  1. ----------------------------------------------------------------------------
  2. -- Lua script to generate a customized, minified version of Lua.
  3. -- The resulting 'minilua' is used for the build process of LuaJIT.
  4. ----------------------------------------------------------------------------
  5. -- Copyright (C) 2005-2014 Mike Pall. All rights reserved.
  6. -- Released under the MIT license. See Copyright Notice in luajit.h
  7. ----------------------------------------------------------------------------
  8. local sub, match, gsub = string.sub, string.match, string.gsub
  9. local LUA_VERSION = "5.1.5"
  10. local LUA_SOURCE
  11. local function usage()
  12. io.stderr:write("Usage: ", arg and arg[0] or "genminilua",
  13. " lua-", LUA_VERSION, "-source-dir\n")
  14. os.exit(1)
  15. end
  16. local function find_sources()
  17. LUA_SOURCE = arg and arg[1]
  18. if not LUA_SOURCE then usage() end
  19. if sub(LUA_SOURCE, -1) ~= "/" then LUA_SOURCE = LUA_SOURCE.."/" end
  20. local fp = io.open(LUA_SOURCE .. "lua.h")
  21. if not fp then
  22. LUA_SOURCE = LUA_SOURCE.."src/"
  23. fp = io.open(LUA_SOURCE .. "lua.h")
  24. if not fp then usage() end
  25. end
  26. local all = fp:read("*a")
  27. fp:close()
  28. if not match(all, 'LUA_RELEASE%s*"Lua '..LUA_VERSION..'"') then
  29. io.stderr:write("Error: version mismatch\n")
  30. usage()
  31. end
  32. end
  33. local LUA_FILES = {
  34. "lmem.c", "lobject.c", "ltm.c", "lfunc.c", "ldo.c", "lstring.c", "ltable.c",
  35. "lgc.c", "lstate.c", "ldebug.c", "lzio.c", "lopcodes.c",
  36. "llex.c", "lcode.c", "lparser.c", "lvm.c", "lapi.c", "lauxlib.c",
  37. "lbaselib.c", "ltablib.c", "liolib.c", "loslib.c", "lstrlib.c", "linit.c",
  38. }
  39. local REMOVE_LIB = {}
  40. gsub([[
  41. collectgarbage dofile gcinfo getfenv getmetatable load print rawequal rawset
  42. select tostring xpcall
  43. foreach foreachi getn maxn setn
  44. popen tmpfile seek setvbuf __tostring
  45. clock date difftime execute getenv rename setlocale time tmpname
  46. dump gfind len reverse
  47. LUA_LOADLIBNAME LUA_MATHLIBNAME LUA_DBLIBNAME
  48. ]], "%S+", function(name)
  49. REMOVE_LIB[name] = true
  50. end)
  51. local REMOVE_EXTINC = { ["<assert.h>"] = true, ["<locale.h>"] = true, }
  52. local CUSTOM_MAIN = [[
  53. typedef unsigned int UB;
  54. static UB barg(lua_State *L,int idx){
  55. union{lua_Number n;U64 b;}bn;
  56. bn.n=lua_tonumber(L,idx)+6755399441055744.0;
  57. if (bn.n==0.0&&!lua_isnumber(L,idx))luaL_typerror(L,idx,"number");
  58. return(UB)bn.b;
  59. }
  60. #define BRET(b) lua_pushnumber(L,(lua_Number)(int)(b));return 1;
  61. static int tobit(lua_State *L){
  62. BRET(barg(L,1))}
  63. static int bnot(lua_State *L){
  64. BRET(~barg(L,1))}
  65. static int band(lua_State *L){
  66. int i;UB b=barg(L,1);for(i=lua_gettop(L);i>1;i--)b&=barg(L,i);BRET(b)}
  67. static int bor(lua_State *L){
  68. int i;UB b=barg(L,1);for(i=lua_gettop(L);i>1;i--)b|=barg(L,i);BRET(b)}
  69. static int bxor(lua_State *L){
  70. int i;UB b=barg(L,1);for(i=lua_gettop(L);i>1;i--)b^=barg(L,i);BRET(b)}
  71. static int lshift(lua_State *L){
  72. UB b=barg(L,1),n=barg(L,2)&31;BRET(b<<n)}
  73. static int rshift(lua_State *L){
  74. UB b=barg(L,1),n=barg(L,2)&31;BRET(b>>n)}
  75. static int arshift(lua_State *L){
  76. UB b=barg(L,1),n=barg(L,2)&31;BRET((int)b>>n)}
  77. static int rol(lua_State *L){
  78. UB b=barg(L,1),n=barg(L,2)&31;BRET((b<<n)|(b>>(32-n)))}
  79. static int ror(lua_State *L){
  80. UB b=barg(L,1),n=barg(L,2)&31;BRET((b>>n)|(b<<(32-n)))}
  81. static int bswap(lua_State *L){
  82. UB b=barg(L,1);b=(b>>24)|((b>>8)&0xff00)|((b&0xff00)<<8)|(b<<24);BRET(b)}
  83. static int tohex(lua_State *L){
  84. UB b=barg(L,1);
  85. int n=lua_isnone(L,2)?8:(int)barg(L,2);
  86. const char *hexdigits="0123456789abcdef";
  87. char buf[8];
  88. int i;
  89. if(n<0){n=-n;hexdigits="0123456789ABCDEF";}
  90. if(n>8)n=8;
  91. for(i=(int)n;--i>=0;){buf[i]=hexdigits[b&15];b>>=4;}
  92. lua_pushlstring(L,buf,(size_t)n);
  93. return 1;
  94. }
  95. static const struct luaL_Reg bitlib[] = {
  96. {"tobit",tobit},
  97. {"bnot",bnot},
  98. {"band",band},
  99. {"bor",bor},
  100. {"bxor",bxor},
  101. {"lshift",lshift},
  102. {"rshift",rshift},
  103. {"arshift",arshift},
  104. {"rol",rol},
  105. {"ror",ror},
  106. {"bswap",bswap},
  107. {"tohex",tohex},
  108. {NULL,NULL}
  109. };
  110. int main(int argc, char **argv){
  111. lua_State *L = luaL_newstate();
  112. int i;
  113. luaL_openlibs(L);
  114. luaL_register(L, "bit", bitlib);
  115. if (argc < 2) return sizeof(void *);
  116. lua_createtable(L, 0, 1);
  117. lua_pushstring(L, argv[1]);
  118. lua_rawseti(L, -2, 0);
  119. lua_setglobal(L, "arg");
  120. if (luaL_loadfile(L, argv[1]))
  121. goto err;
  122. for (i = 2; i < argc; i++)
  123. lua_pushstring(L, argv[i]);
  124. if (lua_pcall(L, argc - 2, 0, 0)) {
  125. err:
  126. fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
  127. return 1;
  128. }
  129. lua_close(L);
  130. return 0;
  131. }
  132. ]]
  133. local function read_sources()
  134. local t = {}
  135. for i, name in ipairs(LUA_FILES) do
  136. local fp = assert(io.open(LUA_SOURCE..name, "r"))
  137. t[i] = fp:read("*a")
  138. assert(fp:close())
  139. end
  140. t[#t+1] = CUSTOM_MAIN
  141. return table.concat(t)
  142. end
  143. local includes = {}
  144. local function merge_includes(src)
  145. return gsub(src, '#include%s*"([^"]*)"%s*\n', function(name)
  146. if includes[name] then return "" end
  147. includes[name] = true
  148. local fp = assert(io.open(LUA_SOURCE..name, "r"))
  149. local src = fp:read("*a")
  150. assert(fp:close())
  151. src = gsub(src, "#ifndef%s+%w+_h\n#define%s+%w+_h\n", "")
  152. src = gsub(src, "#endif%s*$", "")
  153. return merge_includes(src)
  154. end)
  155. end
  156. local function get_license(src)
  157. return match(src, "/%*+\n%* Copyright %(.-%*/\n")
  158. end
  159. local function fold_lines(src)
  160. return gsub(src, "\\\n", " ")
  161. end
  162. local strings = {}
  163. local function save_str(str)
  164. local n = #strings+1
  165. strings[n] = str
  166. return "\1"..n.."\2"
  167. end
  168. local function save_strings(src)
  169. src = gsub(src, '"[^"\n]*"', save_str)
  170. return gsub(src, "'[^'\n]*'", save_str)
  171. end
  172. local function restore_strings(src)
  173. return gsub(src, "\1(%d+)\2", function(numstr)
  174. return strings[tonumber(numstr)]
  175. end)
  176. end
  177. local function def_istrue(def)
  178. return def == "INT_MAX > 2147483640L" or
  179. def == "LUAI_BITSINT >= 32" or
  180. def == "SIZE_Bx < LUAI_BITSINT-1" or
  181. def == "cast" or
  182. def == "defined(LUA_CORE)" or
  183. def == "MINSTRTABSIZE" or
  184. def == "LUA_MINBUFFER" or
  185. def == "HARDSTACKTESTS" or
  186. def == "UNUSED"
  187. end
  188. local head, defs = {[[
  189. #ifdef _MSC_VER
  190. typedef unsigned __int64 U64;
  191. #else
  192. typedef unsigned long long U64;
  193. #endif
  194. int _CRT_glob = 0;
  195. ]]}, {}
  196. local function preprocess(src)
  197. local t = { match(src, "^(.-)#") }
  198. local lvl, on, oldon = 0, true, {}
  199. for pp, def, txt in string.gmatch(src, "#(%w+) *([^\n]*)\n([^#]*)") do
  200. if pp == "if" or pp == "ifdef" or pp == "ifndef" then
  201. lvl = lvl + 1
  202. oldon[lvl] = on
  203. on = def_istrue(def)
  204. elseif pp == "else" then
  205. if oldon[lvl] then
  206. if on == false then on = true else on = false end
  207. end
  208. elseif pp == "elif" then
  209. if oldon[lvl] then
  210. on = def_istrue(def)
  211. end
  212. elseif pp == "endif" then
  213. on = oldon[lvl]
  214. lvl = lvl - 1
  215. elseif on then
  216. if pp == "include" then
  217. if not head[def] and not REMOVE_EXTINC[def] then
  218. head[def] = true
  219. head[#head+1] = "#include "..def.."\n"
  220. end
  221. elseif pp == "define" then
  222. local k, sp, v = match(def, "([%w_]+)(%s*)(.*)")
  223. if k and not (sp == "" and sub(v, 1, 1) == "(") then
  224. defs[k] = gsub(v, "%a[%w_]*", function(tok)
  225. return defs[tok] or tok
  226. end)
  227. else
  228. t[#t+1] = "#define "..def.."\n"
  229. end
  230. elseif pp ~= "undef" then
  231. error("unexpected directive: "..pp.." "..def)
  232. end
  233. end
  234. if on then t[#t+1] = txt end
  235. end
  236. return gsub(table.concat(t), "%a[%w_]*", function(tok)
  237. return defs[tok] or tok
  238. end)
  239. end
  240. local function merge_header(src, license)
  241. local hdr = string.format([[
  242. /* This is a heavily customized and minimized copy of Lua %s. */
  243. /* It's only used to build LuaJIT. It does NOT have all standard functions! */
  244. ]], LUA_VERSION)
  245. return hdr..license..table.concat(head)..src
  246. end
  247. local function strip_unused1(src)
  248. return gsub(src, '( {"?([%w_]+)"?,%s+%a[%w_]*},\n)', function(line, func)
  249. return REMOVE_LIB[func] and "" or line
  250. end)
  251. end
  252. local function strip_unused2(src)
  253. return gsub(src, "Symbolic Execution.-}=", "")
  254. end
  255. local function strip_unused3(src)
  256. src = gsub(src, "extern", "static")
  257. src = gsub(src, "\nstatic([^\n]-)%(([^)]*)%)%(", "\nstatic%1 %2(")
  258. src = gsub(src, "#define lua_assert[^\n]*\n", "")
  259. src = gsub(src, "lua_assert%b();?", "")
  260. src = gsub(src, "default:\n}", "default:;\n}")
  261. src = gsub(src, "lua_lock%b();", "")
  262. src = gsub(src, "lua_unlock%b();", "")
  263. src = gsub(src, "luai_threadyield%b();", "")
  264. src = gsub(src, "luai_userstateopen%b();", "{}")
  265. src = gsub(src, "luai_userstate%w+%b();", "")
  266. src = gsub(src, "%(%(c==.*luaY_parser%)", "luaY_parser")
  267. src = gsub(src, "trydecpoint%(ls,seminfo%)",
  268. "luaX_lexerror(ls,\"malformed number\",TK_NUMBER)")
  269. src = gsub(src, "int c=luaZ_lookahead%b();", "")
  270. src = gsub(src, "luaL_register%(L,[^,]*,co_funcs%);\nreturn 2;",
  271. "return 1;")
  272. src = gsub(src, "getfuncname%b():", "NULL:")
  273. src = gsub(src, "getobjname%b():", "NULL:")
  274. src = gsub(src, "if%([^\n]*hookmask[^\n]*%)\n[^\n]*\n", "")
  275. src = gsub(src, "if%([^\n]*hookmask[^\n]*%)%b{}\n", "")
  276. src = gsub(src, "if%([^\n]*hookmask[^\n]*&&\n[^\n]*%b{}\n", "")
  277. src = gsub(src, "(twoto%b()%()", "%1(size_t)")
  278. src = gsub(src, "i<sizenode", "i<(int)sizenode")
  279. return gsub(src, "\n\n+", "\n")
  280. end
  281. local function strip_comments(src)
  282. return gsub(src, "/%*.-%*/", " ")
  283. end
  284. local function strip_whitespace(src)
  285. src = gsub(src, "^%s+", "")
  286. src = gsub(src, "%s*\n%s*", "\n")
  287. src = gsub(src, "[ \t]+", " ")
  288. src = gsub(src, "(%W) ", "%1")
  289. return gsub(src, " (%W)", "%1")
  290. end
  291. local function rename_tokens1(src)
  292. src = gsub(src, "getline", "getline_")
  293. src = gsub(src, "struct ([%w_]+)", "ZX%1")
  294. return gsub(src, "union ([%w_]+)", "ZY%1")
  295. end
  296. local function rename_tokens2(src)
  297. src = gsub(src, "ZX([%w_]+)", "struct %1")
  298. return gsub(src, "ZY([%w_]+)", "union %1")
  299. end
  300. local function func_gather(src)
  301. local nodes, list = {}, {}
  302. local pos, len = 1, #src
  303. while pos < len do
  304. local d, w = match(src, "^(#define ([%w_]+)[^\n]*\n)", pos)
  305. if d then
  306. local n = #list+1
  307. list[n] = d
  308. nodes[w] = n
  309. else
  310. local s
  311. d, w, s = match(src, "^(([%w_]+)[^\n]*([{;])\n)", pos)
  312. if not d then
  313. d, w, s = match(src, "^(([%w_]+)[^(]*%b()([{;])\n)", pos)
  314. if not d then d = match(src, "^[^\n]*\n", pos) end
  315. end
  316. if s == "{" then
  317. d = d..sub(match(src, "^%b{}[^;\n]*;?\n", pos+#d-2), 3)
  318. if sub(d, -2) == "{\n" then
  319. d = d..sub(match(src, "^%b{}[^;\n]*;?\n", pos+#d-2), 3)
  320. end
  321. end
  322. local k, v = nil, d
  323. if w == "typedef" then
  324. if match(d, "^typedef enum") then
  325. head[#head+1] = d
  326. else
  327. k = match(d, "([%w_]+);\n$")
  328. if not k then k = match(d, "^.-%(.-([%w_]+)%)%(") end
  329. end
  330. elseif w == "enum" then
  331. head[#head+1] = v
  332. elseif w ~= nil then
  333. k = match(d, "^[^\n]-([%w_]+)[(%[=]")
  334. if k then
  335. if w ~= "static" and k ~= "main" then v = "static "..d end
  336. else
  337. k = w
  338. end
  339. end
  340. if w and k then
  341. local o = nodes[k]
  342. if o then nodes["*"..k] = o end
  343. local n = #list+1
  344. list[n] = v
  345. nodes[k] = n
  346. end
  347. end
  348. pos = pos + #d
  349. end
  350. return nodes, list
  351. end
  352. local function func_visit(nodes, list, used, n)
  353. local i = nodes[n]
  354. for m in string.gmatch(list[i], "[%w_]+") do
  355. if nodes[m] then
  356. local j = used[m]
  357. if not j then
  358. used[m] = i
  359. func_visit(nodes, list, used, m)
  360. elseif i < j then
  361. used[m] = i
  362. end
  363. end
  364. end
  365. end
  366. local function func_collect(src)
  367. local nodes, list = func_gather(src)
  368. local used = {}
  369. func_visit(nodes, list, used, "main")
  370. for n,i in pairs(nodes) do
  371. local j = used[n]
  372. if j and j < i then used["*"..n] = j end
  373. end
  374. for n,i in pairs(nodes) do
  375. if not used[n] then list[i] = "" end
  376. end
  377. return table.concat(list)
  378. end
  379. find_sources()
  380. local src = read_sources()
  381. src = merge_includes(src)
  382. local license = get_license(src)
  383. src = fold_lines(src)
  384. src = strip_unused1(src)
  385. src = save_strings(src)
  386. src = strip_unused2(src)
  387. src = strip_comments(src)
  388. src = preprocess(src)
  389. src = strip_whitespace(src)
  390. src = strip_unused3(src)
  391. src = rename_tokens1(src)
  392. src = func_collect(src)
  393. src = rename_tokens2(src)
  394. src = restore_strings(src)
  395. src = merge_header(src, license)
  396. io.write(src)