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