libs-ini.lua /size: 6524 b    last modification: 2023-12-21 09:44
1if not modules then modules = { } end modules ['libs-ini'] = {
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-- This is a loader for optional libraries in luametatex with context lmtx. It's
10-- kind of experimental. We also use a different locator than in mkiv because we
11-- don't support loading lua libraries and swiglibs any more. Of course one can
12-- try the regular lua loaders but we just assume that a user then knows what (s)he
13-- is doing.
14
15local type, unpack = type, unpack
16local find = string.find
17
18-- here we implement the resolver
19
20local nameonly      = file.nameonly
21local joinfile      = file.join
22local addsuffix     = file.addsuffix
23local qualifiedpath = file.is_qualified_path
24
25local isfile        = lfs.isfile
26
27local findfile      = resolvers.findfile
28local expandpaths   = resolvers.expandedpathlistfromvariable
29
30local report        = logs.reporter("resolvers","libraries")
31local trace         = false
32local silent        = false
33
34trackers.register("resolvers.lib",        function(v) trace  = v end)
35trackers.register("resolvers.lib.silent", function(v) silent = v end)
36
37local function findlib(required) -- todo: cache
38    local suffix = os.libsuffix or "so"
39    if not qualifiedpath(required) then
40        local list = directives.value("system.librarynames" )
41        local only = nameonly(required)
42        if type(list) == "table" then
43            list = list[only]
44            if type(list) ~= "table" then
45                list = { only }
46            end
47        else
48            list = { only }
49        end
50        if trace then
51            report("using lookup list for library %a: % | t",only,list)
52        end
53        for i=1,#list do
54            local name  = list[i]
55            local found = findfile(name,"lib")
56            if not found or found == "" then
57                found = findfile(addsuffix(name,suffix),"lib")
58            end
59            if found and found ~= "" then
60                if trace then
61                    report("library %a resolved via %a path to %a",name,"tds lib",found)
62                end
63                return found
64            end
65        end
66        if expandpaths then
67            local list = expandpaths("PATH")
68            local base = addsuffix(only,suffix)
69            for i=1,#list do
70                local full  = joinfile(list[i],base)
71                local found = isfile(full) and full
72                if found and found ~= "" then
73                    if trace then
74                        report("library %a resolved via %a path to %a",full,"system",found)
75                    end
76                    return found
77                end
78            end
79        end
80    elseif isfile(addsuffix(required,suffix)) then
81        if trace then
82            report("library with qualified name %a %sfound",required,"")
83        end
84        return required
85    else
86        if trace then
87            report("library with qualified name %a %sfound",required,"not ")
88        end
89    end
90    return false
91end
92
93local foundlibraries = table.setmetatableindex(function(t,k)
94    local v = findlib(k)
95    t[k] = v
96    return v
97end)
98
99function resolvers.findlib(required)
100    return foundlibraries[required]
101end
102
103-- here we implement the loader
104
105local libraries     = { }
106resolvers.libraries = libraries
107
108local report        = logs.reporter("optional")
109
110if optional then optional.loaded = { } end
111
112function libraries.validoptional(name)
113    local thelib = optional and optional[name]
114    if not thelib then
115        -- forget about it, no message here
116    elseif thelib.initialize then
117        return thelib
118    else
119        report("invalid optional library %a",libname)
120    end
121end
122
123function libraries.optionalloaded(name,libnames)
124    local thelib = optional and optional[name]
125    if not thelib then
126        report("no optional %a library found",name)
127    else
128        local thelib_initialize = thelib.initialize
129        if not thelib_initialize then
130            report("invalid optional library %a",name)
131        else
132            if type(libnames) == "string" then
133                libnames = { libnames }
134            end
135            if type(libnames) == "table" then
136                for i=1,#libnames do
137                    local libname  = libnames[i]
138                    local filename = foundlibraries[libname]
139                    if filename and filename ~= "" then
140                        libnames[i] = filename
141                    else
142                        report("unable to locate library %a",libname)
143                        return
144                    end
145                end
146                local initialized = thelib_initialize(unpack(libnames))
147                if not initialized then
148                    report("unable to initialize library '% + t'",libnames)
149                elseif not silent then
150                    report("using library '% + t'",libnames)
151                end
152                return initialized
153            end
154        end
155    end
156end
157
158-- For the moment the next blob is needed when we run \MTXRUN\ on top of \LUATEX\ and
159-- \LUAJITTEX\ but at some point we will {\em always} assume \LUAMETATEX\ as runner.
160
161if FFISUPPORTED and ffi and ffi.load then
162
163    local ffiload = ffi.load
164
165    function ffi.load(name)
166        local full = name and foundlibraries[name]
167        if full then
168            return ffiload(full)
169        else
170            return ffiload(name)
171        end
172    end
173
174end
175
176-- local patterns = {
177--     "libs-imp-%s.mkxl",
178--     "libs-imp-%s.mklx",
179-- }
180--
181-- local function action(name,foundname)
182--     -- could be one command
183--     context.startreadingfile()
184--     context.input(foundname)
185--     context.stopreadingfile()
186-- end
187--
188-- interfaces.implement {
189--     name      = "uselibrary",
190--     arguments = "string"
191--     actions   = function(name)
192--         resolvers.uselibrary {
193--             category = "color definition",
194--             name     = name,
195--             patterns = patterns,
196--             action   = action,
197--             onlyonce = true,
198--         }
199--     end
200-- }
201
202local dofile       = dofile
203local savedrequire = require
204
205function require(name,version)
206    if find(name,"%.lua$") or find(name,"%.lmt$") then
207        local m = dofile(findfile(name))
208        if m then
209            package.loaded[name] = m
210            return m
211        end
212    else
213        return savedrequire(name)
214    end
215end
216
217