1if not modules then modules = { } end modules ['util-lua'] = {
2 version = 1.001,
3 comment = "companion to luat-lib.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 comment = "the strip code is written by Peter Cawley",
6 copyright = "PRAGMA ADE / ConTeXt Development Team",
7 license = "see context related readme files"
8}
9
10
11
12local rep, sub, byte, dump, format = string.rep, string.sub, string.byte, string.dump, string.format
13local load, loadfile, type, collectgarbage = load, loadfile, type, collectgarbage
14
15utilities = utilities or {}
16utilities.lua = utilities.lua or { }
17local luautilities = utilities.lua
18
19local report_lua = logs.reporter("system","lua")
20local report_mem = logs.reporter("system","lua memory")
21
22local tracestripping = false
23local tracememory = false
24luautilities.stripcode = true
25luautilities.alwaysstripcode = false
26luautilities.nofstrippedchunks = 0
27luautilities.nofstrippedbytes = 0
28local strippedchunks = { }
29luautilities.strippedchunks = strippedchunks
30
31if not LUATEXENGINE then
32
33 LUATEXENGINE = status.luatex_engine and string.lower(status.luatex_engine)
34 JITSUPPORTED = LUATEXENGINE == "luajittex" or jit
35 CONTEXTLMTXMODE = CONTEXTLMTXMODE or (LUATEXENGINE == "luametatex" and 1) or 0
36end
37
38luautilities.suffixes = {
39 tma = "tma",
40 tmc = (CONTEXTLMTXMODE and CONTEXTLMTXMODE > 0 and "tmd") or (jit and "tmb") or "tmc",
41 lua = "lua",
42 luc = (CONTEXTLMTXMODE and CONTEXTLMTXMODE > 0 and "lud") or (jit and "lub") or "luc",
43 lui = "lui",
44 luv = "luv",
45 luj = "luj",
46 tua = "tua",
47
48 tuc = (CONTEXTLMTXMODE and CONTEXTLMTXMODE > 0 and "tud") or (jit and "tub") or "tuc",
49}
50
51
52
53local function register(name)
54 if tracestripping then
55 report_lua("stripped bytecode from %a",name or "unknown")
56 end
57 strippedchunks[#strippedchunks+1] = name
58 luautilities.nofstrippedchunks = luautilities.nofstrippedchunks + 1
59end
60
61local function stupidcompile(luafile,lucfile,strip)
62 local code = io.loaddata(luafile)
63 if code and code ~= "" then
64 code = load(code)
65 if code then
66 code = dump(code,strip and luautilities.stripcode or luautilities.alwaysstripcode)
67 if code and code ~= "" then
68 register(name)
69 io.savedata(lucfile,code)
70 return true, 0
71 end
72 else
73 report_lua("fatal error %a in file %a",1,luafile)
74 end
75 else
76 report_lua("fatal error %a in file %a",2,luafile)
77 end
78 return false, 0
79end
80
81
82
83function luautilities.loadedluacode(fullname,forcestrip,name,macros)
84
85 name = name or fullname
86 if macros then
87 macros = lua.macros
88 end
89 local code, message
90 if macros then
91 code, message = macros.loaded(fullname,true,false)
92 else
93 code, message = loadfile(fullname)
94 end
95 if code then
96 code()
97 else
98 report_lua("loading of file %a failed:\n\t%s",fullname,message or "no message")
99 code, message = loadfile(fullname)
100 end
101 if forcestrip and luautilities.stripcode then
102 if type(forcestrip) == "function" then
103 forcestrip = forcestrip(fullname)
104 end
105 if forcestrip or luautilities.alwaysstripcode then
106 register(name)
107 return load(dump(code,true)), 0
108 else
109 return code, 0
110 end
111 elseif luautilities.alwaysstripcode then
112 register(name)
113 return load(dump(code,true)), 0
114 else
115 return code, 0
116 end
117end
118
119function luautilities.strippedloadstring(code,name,forcestrip)
120 local code, message = load(code)
121 if not code then
122 report_lua("loading of file %a failed:\n\t%s",name,message or "no message")
123 end
124 if forcestrip and luautilities.stripcode or luautilities.alwaysstripcode then
125 register(name)
126 return load(dump(code,true)), 0
127 else
128 return code, 0
129 end
130end
131
132function luautilities.loadstring(code,name)
133 local code, message = load(code)
134 if not code then
135 report_lua("loading of file %a failed:\n\t%s",name,message or "no message")
136 end
137 return code, 0
138end
139
140function luautilities.compile(luafile,lucfile,cleanup,strip,fallback)
141 report_lua("compiling %a into %a",luafile,lucfile)
142 os.remove(lucfile)
143 local done = stupidcompile(luafile,lucfile,strip ~= false)
144 if done then
145 report_lua("dumping %a into %a stripped",luafile,lucfile)
146 if cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
147 report_lua("removing %a",luafile)
148 os.remove(luafile)
149 end
150 end
151 return done
152end
153
154function luautilities.loadstripped(...)
155 local l = load(...)
156 if l then
157 return load(dump(l,true))
158 end
159end
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187local finalizers = { }
188
189setmetatable(finalizers, {
190 __gc = function(t)
191 for i=1,#t do
192 pcall(t[i])
193 end
194 end
195} )
196
197function luautilities.registerfinalizer(f)
198 finalizers[#finalizers+1] = f
199end
200
201function luautilities.checkmemory(previous,threshold,trace)
202 local current = collectgarbage("count")
203 if previous then
204 local checked = (threshold or 64)*1024
205 local delta = current - previous
206 if current - previous > checked then
207 collectgarbage("collect")
208 local afterwards = collectgarbage("count")
209 if trace or tracememory then
210 report_mem("previous %r MB, current %r MB, delta %r MB, threshold %r MB, afterwards %r MB",
211 previous/1024,current/1024,delta/1024,threshold,afterwards)
212 end
213 return afterwards
214 elseif trace or tracememory then
215 report_mem("previous %r MB, current %r MB, delta %r MB, threshold %r MB",
216 previous/1024,current/1024,delta/1024,threshold)
217 end
218 end
219 return current
220end
221 |