1if not modules then modules = { } end modules ['luat-basics-gen'] = {
2 version = 1.100,
3 comment = "companion to luatex-*.tex",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9if context then
10 os.exit()
11end
12
13
14
15
16
17local match, gmatch, gsub, lower = string.match, string.gmatch, string.gsub, string.lower
18local formatters, split, format, dump = string.formatters, string.split, string.format, string.dump
19local loadfile, type = loadfile, type
20local setmetatable, getmetatable, collectgarbage = setmetatable, getmetatable, collectgarbage
21local floor = math.floor
22
23local dummyfunction = function()
24end
25
26local dummyreporter = function(c)
27 return function(f,...)
28 local r = texio.reporter or texio.write_nl
29 if f then
30 r(c .. " : " .. (formatters or format)(f,...))
31 else
32 r("")
33 end
34 end
35end
36
37local dummyreport = function(c,f,...)
38 local r = texio.reporter or texio.write_nl
39 if f then
40 r(c .. " : " .. (formatters or format)(f,...))
41 else
42 r("")
43 end
44end
45
46statistics = {
47 register = dummyfunction,
48 starttiming = dummyfunction,
49 stoptiming = dummyfunction,
50 elapsedtime = nil,
51}
52
53directives = {
54 register = dummyfunction,
55 enable = dummyfunction,
56 disable = dummyfunction,
57}
58
59trackers = {
60 register = dummyfunction,
61 enable = dummyfunction,
62 disable = dummyfunction,
63}
64
65experiments = {
66 register = dummyfunction,
67 enable = dummyfunction,
68 disable = dummyfunction,
69}
70
71storage = {
72 register = dummyfunction,
73 shared = { },
74}
75
76logs = {
77 new = dummyreporter,
78 reporter = dummyreporter,
79 messenger = dummyreporter,
80 report = dummyreport,
81}
82
83callbacks = {
84 register = function(n,f)
85 return callback.register(n,f)
86 end,
87}
88
89utilities = utilities or { }
90
91utilities.storage = utilities.storage or {
92 allocate = function(t)
93 return t or { }
94 end,
95 mark = function(t)
96 return t or { }
97 end,
98}
99
100utilities.parsers = utilities.parsers or {
101
102
103 settings_to_array = function(s)
104 return split(s,",")
105 end,
106 settings_to_hash = function(s)
107 local t = { }
108 for k, v in gmatch((gsub(s,"^{(.*)}$", "%1")),"([^%s,=]+)=([^%s,]+)") do
109 t[k] = v
110 end
111 return t
112 end,
113 settings_to_hash_colon_too = function(s)
114 local t = { }
115 for k, v in gmatch((gsub(s,"^{(.*)}$", "%1")),"([^%s,=:]+)[=:]([^%s,]+)") do
116 t[k] = v
117 end
118 return t
119 end,
120}
121
122characters = characters or {
123 data = { }
124}
125
126
127
128texconfig.kpse_init = true
129
130resolvers = resolvers or { }
131
132local remapper = {
133 otf = "opentype fonts",
134 ttf = "truetype fonts",
135 ttc = "truetype fonts",
136 cid = "cid maps",
137 cidmap = "cid maps",
138
139 pfb = "type1 fonts",
140 afm = "afm",
141 enc = "enc files",
142 lua = "tex",
143}
144
145function resolvers.findfile(name,fileformat)
146 name = gsub(name,"\\","/")
147 if not fileformat or fileformat == "" then
148 fileformat = file.suffix(name)
149 if fileformat == "" then
150 fileformat = "tex"
151 end
152 end
153 fileformat = lower(fileformat)
154 fileformat = remapper[fileformat] or fileformat
155 local found = kpse.find_file(name,fileformat)
156 if not found or found == "" then
157 found = kpse.find_file(name,"other text files")
158 end
159 return found
160end
161
162resolvers.findbinfile = resolvers.findfile
163
164function resolvers.loadbinfile(filename,filetype)
165 local data = io.loaddata(filename)
166 return true, data, #data
167end
168
169function resolvers.resolve(s)
170 return s
171end
172
173function resolvers.unresolve(s)
174 return s
175end
176
177
178
179
180
181
182
183
184
185caches = { }
186
187local writable = nil
188local readables = { }
189local usingjit = jit
190
191if not caches.namespace or caches.namespace == "" or caches.namespace == "context" then
192 caches.namespace = 'generic'
193end
194
195do
196
197
198
199 local cachepaths = kpse.expand_var('$TEXMFCACHE') or ""
200
201
202
203 if cachepaths == "" or cachepaths == "$TEXMFCACHE" then
204 cachepaths = kpse.expand_var('$TEXMFVAR') or ""
205 end
206
207
208
209 if cachepaths == "" or cachepaths == "$TEXMFVAR" then
210 cachepaths = kpse.expand_var('$VARTEXMF') or ""
211 end
212
213
214
215 if cachepaths == "" then
216 local fallbacks = { "TMPDIR", "TEMPDIR", "TMP", "TEMP", "HOME", "HOMEPATH" }
217 for i=1,#fallbacks do
218 cachepaths = os.getenv(fallbacks[i]) or ""
219 if cachepath ~= "" and lfs.isdir(cachepath) then
220 break
221 end
222 end
223 end
224
225 if cachepaths == "" then
226 cachepaths = "."
227 end
228
229 cachepaths = split(cachepaths,os.type == "windows" and ";" or ":")
230
231 for i=1,#cachepaths do
232 local cachepath = cachepaths[i]
233 if not lfs.isdir(cachepath) then
234 lfs.mkdirs(cachepath)
235 if lfs.isdir(cachepath) then
236 logs.report("system","creating cache path '%s'",cachepath)
237 end
238 end
239 if file.is_writable(cachepath) then
240 writable = file.join(cachepath,"luatex-cache")
241 lfs.mkdir(writable)
242 writable = file.join(writable,caches.namespace)
243 lfs.mkdir(writable)
244 break
245 end
246 end
247
248 for i=1,#cachepaths do
249 if file.is_readable(cachepaths[i]) then
250 readables[#readables+1] = file.join(cachepaths[i],"luatex-cache",caches.namespace)
251 end
252 end
253
254 if not writable then
255 logs.report("system","no writeable cache path, quiting")
256 os.exit()
257 elseif #readables == 0 then
258 logs.report("system","no readable cache path, quiting")
259 os.exit()
260 elseif #readables == 1 and readables[1] == writable then
261 logs.report("system","using cache '%s'",writable)
262 else
263 logs.report("system","using write cache '%s'",writable)
264 logs.report("system","using read cache '%s'",table.concat(readables," "))
265 end
266
267end
268
269function caches.getwritablepath(category,subcategory)
270 local path = file.join(writable,category)
271 lfs.mkdir(path)
272 path = file.join(path,subcategory)
273 lfs.mkdir(path)
274 return path
275end
276
277function caches.getreadablepaths(category,subcategory)
278 local t = { }
279 for i=1,#readables do
280 t[i] = file.join(readables[i],category,subcategory)
281 end
282 return t
283end
284
285local function makefullname(path,name)
286 if path and path ~= "" then
287 return file.addsuffix(file.join(path,name),"lua"), file.addsuffix(file.join(path,name),usingjit and "lub" or "luc")
288 end
289end
290
291function caches.is_writable(path,name)
292 local fullname = makefullname(path,name)
293 return fullname and file.is_writable(fullname)
294end
295
296function caches.loaddata(readables,name,writable)
297 for i=1,#readables do
298 local path = readables[i]
299 local loader = false
300 local luaname, lucname = makefullname(path,name)
301 if lfs.isfile(lucname) then
302 logs.report("system","loading luc file '%s'",lucname)
303 loader = loadfile(lucname)
304 end
305 if not loader and lfs.isfile(luaname) then
306
307 local luacrap, lucname = makefullname(writable,name)
308 logs.report("system","compiling luc file '%s'",lucname)
309 if lfs.isfile(lucname) then
310 loader = loadfile(lucname)
311 end
312 caches.compile(data,luaname,lucname)
313 if lfs.isfile(lucname) then
314 logs.report("system","loading luc file '%s'",lucname)
315 loader = loadfile(lucname)
316 else
317 logs.report("system","error in loading luc file '%s'",lucname)
318 end
319 if not loader then
320 logs.report("system","loading lua file '%s'",luaname)
321 loader = loadfile(luaname)
322 else
323 logs.report("system","error in loading lua file '%s'",luaname)
324 end
325 end
326 if loader then
327 loader = loader()
328 collectgarbage("step")
329 return loader
330 end
331 end
332 return false
333end
334
335function caches.savedata(path,name,data)
336 local luaname, lucname = makefullname(path,name)
337 if luaname then
338 logs.report("system","saving lua file '%s'",luaname)
339 table.tofile(luaname,data,true)
340 if lucname and type(caches.compile) == "function" then
341 os.remove(lucname)
342 logs.report("system","saving luc file '%s'",lucname)
343 caches.compile(data,luaname,lucname)
344 end
345 end
346end
347
348
349
350
351
352function caches.compile(data,luaname,lucname)
353 local d = io.loaddata(luaname)
354 if not d or d == "" then
355 d = table.serialize(data,true)
356 end
357 if d and d ~= "" then
358 local f = io.open(lucname,'wb')
359 if f then
360 local s = loadstring(d)
361 if s then
362 f:write(dump(s,true))
363 end
364 f:close()
365 end
366 end
367end
368
369
370
371function table.setmetatableindex(t,f)
372 if type(t) ~= "table" then
373 f, t = t, { }
374 end
375 local m = getmetatable(t)
376 if f == "table" then
377 f = function(t,k) local v = { } t[k] = v return v end
378 end
379 if m then
380 m.__index = f
381 else
382 setmetatable(t,{ __index = f })
383 end
384 return t
385end
386
387function table.makeweak(t)
388 local m = getmetatable(t)
389 if m then
390 m.__mode = "v"
391 else
392 setmetatable(t,{ __mode = "v" })
393 end
394 return t
395end
396
397
398
399arguments = { }
400
401if arg then
402 for i=1,#arg do
403 local k, v = match(arg[i],"^%-%-([^=]+)=?(.-)$")
404 if k and v then
405 arguments[k] = v
406 end
407 end
408end
409
410
411
412if not number.idiv then
413 function number.idiv(i,d)
414 return floor(i/d)
415 end
416end
417
418
419
420local u = unicode and unicode.utf8
421
422if u then
423
424 utf.lower = u.lower
425 utf.upper = u.upper
426 utf.char = u.char
427 utf.byte = u.byte
428 utf.len = u.len
429
430
431
432 if lpeg.setutfcasers then
433 lpeg.setutfcasers(u.lower,u.upper)
434 end
435
436
437
438 local bytepairs = string.bytepairs
439 local utfchar = utf.char
440 local concat = table.concat
441
442 function utf.utf16_to_utf8_be(s)
443 if not s then
444 return nil
445 elseif s == "" then
446 return ""
447 end
448 local result, r, more = { }, 0, 0
449 for left, right in bytepairs(s) do
450 if right then
451 local now = 256*left + right
452 if more > 0 then
453 now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
454 more = 0
455 r = r + 1
456 result[r] = utfchar(now)
457 elseif now >= 0xD800 and now <= 0xDBFF then
458 more = now
459 else
460 r = r + 1
461 result[r] = utfchar(now)
462 end
463 end
464 end
465 return concat(result)
466 end
467
468 local characters = string.utfcharacters
469
470 function utf.split(str)
471 local t, n = { }, 0
472 for s in characters(str) do
473 n = n + 1
474 t[n] = s
475 end
476 return t
477 end
478
479end
480 |