1if not modules then modules = { } end modules [ ' l-package ' ] = {
2 version = 1 . 001 ,
3 comment = " companion to luat-lib.mkiv " ,
4 author = " Hans Hagen, PRAGMA-ADE, Hasselt NL " ,
5 copyright = " PRAGMA ADE / ConTeXt Development Team " ,
6 license = " see context related readme files "
7}
8
9
10
11
12
13
14
15
16
17
18
19local type = type
20local gsub , format , find = string . gsub , string . format , string . find
21local insert , remove = table . insert , table . remove
22
23local P , S , Cs , lpegmatch = lpeg . P , lpeg . S , lpeg . Cs , lpeg . match
24
25local package = package
26local searchers = package . searchers or package . loaders
27
28
29
30
31
32
33local filejoin = file and file . join or function ( path , name ) return path . . " / " . . name end
34local isreadable = file and file . is_readable or function ( name ) local f = io . open ( name ) if f then f : close ( ) return true end end
35local addsuffix = file and file . addsuffix or function ( name , suffix ) return name . . " . " . . suffix end
36
37
38
39
40
41
42
43
44
45
46
47local function cleanpath ( path )
48 return path
49end
50
51local pattern = Cs ( ( ( ( 1 - S ( " \\/ " ) ) ^ 0 * ( S ( " \\/ " ) ^ 1 / " / " ) ) ^ 0 * ( P ( " . " ) ^ 1 / " / " + P ( 1 ) ) ^ 1 ) * -1 )
52
53local function lualibfile ( name )
54 return lpegmatch ( pattern , name ) or name
55end
56
57local offset = luarocks and 1 or 0
58
59local helpers = package . helpers or {
60 cleanpath = cleanpath ,
61 lualibfile = lualibfile ,
62 trace = false ,
63 report = function ( ... ) print ( format ( ... ) ) end ,
64 builtin = {
65 [ " preload table " ] = searchers [ 1 + offset ] ,
66 [ " path specification " ] = searchers [ 2 + offset ] ,
67 [ " cpath specification " ] = searchers [ 3 + offset ] ,
68 [ " all in one fallback " ] = searchers [ 4 + offset ] ,
69 } ,
70 methods = {
71 } ,
72 sequence = {
73 " already loaded " ,
74 " preload table " ,
75 " qualified path " ,
76 " lua extra list " ,
77 " lib extra list " ,
78 " path specification " ,
79 " cpath specification " ,
80 " all in one fallback " ,
81 " not loaded " ,
82 }
83}
84
85package . helpers = helpers
86
87local methods = helpers . methods
88local builtin = helpers . builtin
89
90
91
92local extraluapaths = { }
93local extralibpaths = { }
94local luapaths = nil
95local libpaths = nil
96local oldluapath = nil
97local oldlibpath = nil
98
99local nofextralua = -1
100local nofextralib = -1
101local nofpathlua = -1
102local nofpathlib = -1
103
104local function listpaths ( what , paths )
105 local nofpaths = # paths
106 if nofpaths > 0 then
107 for i = 1 , nofpaths do
108 helpers . report ( " using %s path %i: %s " , what , i , paths [ i ] )
109 end
110 else
111 helpers . report ( " no %s paths defined " , what )
112 end
113 return nofpaths
114end
115
116local function getextraluapaths ( )
117 if helpers . trace and # extraluapaths ~ = nofextralua then
118 nofextralua = listpaths ( " extra lua " , extraluapaths )
119 end
120 return extraluapaths
121end
122
123local function getextralibpaths ( )
124 if helpers . trace and # extralibpaths ~ = nofextralib then
125 nofextralib = listpaths ( " extra lib " , extralibpaths )
126 end
127 return extralibpaths
128end
129
130local function getluapaths ( )
131 local luapath = package . path or " "
132 if oldluapath ~ = luapath then
133 luapaths = file . splitpath ( luapath , " ; " )
134 oldluapath = luapath
135 nofpathlua = -1
136 end
137 if helpers . trace and # luapaths ~ = nofpathlua then
138 nofpathlua = listpaths ( " builtin lua " , luapaths )
139 end
140 return luapaths
141end
142
143local function getlibpaths ( )
144 local libpath = package . cpath or " "
145 if oldlibpath ~ = libpath then
146 libpaths = file . splitpath ( libpath , " ; " )
147 oldlibpath = libpath
148 nofpathlib = -1
149 end
150 if helpers . trace and # libpaths ~ = nofpathlib then
151 nofpathlib = listpaths ( " builtin lib " , libpaths )
152 end
153 return libpaths
154end
155
156package . luapaths = getluapaths
157package . libpaths = getlibpaths
158package . extraluapaths = getextraluapaths
159package . extralibpaths = getextralibpaths
160
161local hashes = {
162 lua = { } ,
163 lib = { } ,
164}
165
166local function registerpath ( tag , what , target , ... )
167 local pathlist = { ... }
168 local cleanpath = helpers . cleanpath
169 local trace = helpers . trace
170 local report = helpers . report
171 local hash = hashes [ what ]
172
173 local function add ( path )
174 local path = cleanpath ( path )
175 if not hash [ path ] then
176 target [ # target + 1 ] = path
177 hash [ path ] = true
178 if trace then
179 report ( " registered %s path %s: %s " , tag , # target , path )
180 end
181 else
182 if trace then
183 report ( " duplicate %s path: %s " , tag , path )
184 end
185 end
186 end
187
188 for p = 1 , # pathlist do
189 local path = pathlist [ p ]
190 if type ( path ) = = " table " then
191 for i = 1 , # path do
192 add ( path [ i ] )
193 end
194 else
195 add ( path )
196 end
197 end
198end
199
200local function pushpath ( tag , what , target , path )
201 local path = helpers . cleanpath ( path )
202 insert ( target , 1 , path )
203 if helpers . trace then
204 helpers . report ( " pushing %s path in front: %s " , tag , path )
205 end
206end
207
208local function poppath ( tag , what , target )
209 local path = remove ( target , 1 )
210 if helpers . trace then
211 if path then
212 helpers . report ( " popping %s path from front: %s " , tag , path )
213 else
214 helpers . report ( " no %s path to pop " , tag )
215 end
216 end
217end
218
219helpers . registerpath = registerpath
220
221function package . extraluapath ( ... )
222 registerpath ( " extra lua " , " lua " , extraluapaths , ... )
223end
224function package . pushluapath ( path )
225 pushpath ( " extra lua " , " lua " , extraluapaths , path )
226end
227function package . popluapath ( )
228 poppath ( " extra lua " , " lua " , extraluapaths )
229end
230
231function package . extralibpath ( ... )
232 registerpath ( " extra lib " , " lib " , extralibpaths , ... )
233end
234function package . pushlibpath ( path )
235 pushpath ( " extra lib " , " lib " , extralibpaths , path )
236end
237function package . poplibpath ( )
238 poppath ( " extra lib " , " lua " , extralibpaths )
239end
240
241
242
243local function loadedaslib ( resolved , rawname )
244 local base = gsub ( rawname , " %. " , " _ " )
245
246
247 local init = " luaopen_ " . . gsub ( base , " %. " , " _ " )
248 if helpers . trace then
249 helpers . report ( " calling loadlib with '%s' with init '%s' " , resolved , init )
250 end
251 return package . loadlib ( resolved , init )
252end
253
254helpers . loadedaslib = loadedaslib
255
256
257
258local function loadedbypath ( name , rawname , paths , islib , what )
259 local trace = helpers . trace
260 for p = 1 , # paths do
261 local path = paths [ p ]
262 local resolved = filejoin ( path , name )
263 if trace then
264 helpers . report ( " %s path, identifying '%s' on '%s' " , what , name , path )
265 end
266 if isreadable ( resolved ) then
267 if trace then
268 helpers . report ( " %s path, '%s' found on '%s' " , what , name , resolved )
269 end
270 if islib then
271 return loadedaslib ( resolved , rawname )
272 else
273 return loadfile ( resolved )
274 end
275 end
276 end
277end
278
279helpers . loadedbypath = loadedbypath
280
281local function loadedbyname ( name , rawname )
282 if find ( name , " ^/ " ) or find ( name , " ^[a-zA-Z]:/ " ) then
283 local trace = helpers . trace
284 if trace then
285 helpers . report ( " qualified name, identifying '%s' " , what , name )
286 end
287 if isreadable ( name ) then
288 if trace then
289 helpers . report ( " qualified name, '%s' found " , what , name )
290 end
291 return loadfile ( name )
292 end
293 end
294end
295
296helpers . loadedbyname = loadedbyname
297
298methods [ " already loaded " ] = function ( name )
299 return package . loaded [ name ]
300end
301
302methods [ " preload table " ] = function ( name )
303 return builtin [ " preload table " ] ( name )
304end
305
306methods [ " qualified path " ] = function ( name )
307 return loadedbyname ( addsuffix ( lualibfile ( name ) , " lua " ) , name )
308end
309
310methods [ " lua extra list " ] = function ( name )
311 return loadedbypath ( addsuffix ( lualibfile ( name ) , " lua " ) , name , getextraluapaths ( ) , false , " lua " )
312end
313
314methods [ " lib extra list " ] = function ( name )
315 return loadedbypath ( addsuffix ( lualibfile ( name ) , os . libsuffix ) , name , getextralibpaths ( ) , true , " lib " )
316end
317
318methods [ " path specification " ] = function ( name )
319 getluapaths ( )
320 return builtin [ " path specification " ] ( name )
321end
322
323methods [ " cpath specification " ] = function ( name )
324 getlibpaths ( )
325 return builtin [ " cpath specification " ] ( name )
326end
327
328methods [ " all in one fallback " ] = function ( name )
329 return builtin [ " all in one fallback " ] ( name )
330end
331
332methods [ " not loaded " ] = function ( name )
333 if helpers . trace then
334 helpers . report ( " unable to locate '%s' " , name or " ? " )
335 end
336 return nil
337end
338
339local level = 0
340local used = { }
341
342helpers . traceused = false
343
344function helpers . loaded ( name )
345 local sequence = helpers . sequence
346 level = level + 1
347 for i = 1 , # sequence do
348 local method = sequence [ i ]
349 if helpers . trace then
350 helpers . report ( " %s, level '%s', method '%s', name '%s' " , " locating " , level , method , name )
351 end
352 local result , rest = methods [ method ] ( name )
353 if type ( result ) = = " function " then
354 if helpers . trace then
355 helpers . report ( " %s, level '%s', method '%s', name '%s' " , " found " , level , method , name )
356 end
357 if helpers . traceused then
358 used [ # used + 1 ] = { level = level , name = name }
359 end
360 level = level - 1
361 return result , rest
362 end
363 end
364
365 level = level - 1
366 return nil
367end
368
369function helpers . showused ( )
370 local n = # used
371 if n > 0 then
372 helpers . report ( " %s libraries loaded: " , n )
373 helpers . report ( )
374 for i = 1 , n do
375 local u = used [ i ]
376 helpers . report ( " %i %a " , u . level , u . name )
377 end
378 helpers . report ( )
379 end
380end
381
382function helpers . unload ( name )
383 if helpers . trace then
384 if package . loaded [ name ] then
385 helpers . report ( " unloading, name '%s', %s " , name , " done " )
386 else
387 helpers . report ( " unloading, name '%s', %s " , name , " not loaded " )
388 end
389 end
390 package . loaded [ name ] = nil
391end
392
393
394
395
396table . insert ( searchers , 1 , helpers . loaded )
397
398if context then
399 package . path = " "
400end
401 |