summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/luat-env.lua
blob: 1620a26e52151d8bead66d83d99aa129693277ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
 if not modules then modules = { } end modules ['luat-env'] = {
    version   = 1.001,
    comment   = "companion to luat-lib.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

-- A former version provided functionality for non embeded core scripts i.e. runtime
-- library loading. Given the amount of Lua code we use now, this no longer makes
-- sense. Much of this evolved before bytecode arrays were available and so a lot of
-- code has disappeared already.

local rawset, loadfile = rawset, loadfile
local gsub = string.gsub

local trace_locating = false  trackers.register("resolvers.locating", function(v) trace_locating = v end)

local report_lua = logs.reporter("resolvers","lua")

local luautilities = utilities.lua
local luasuffixes  = luautilities.suffixes

local texgettoks   = tex and tex.gettoks

environment        = environment or { }
local environment  = environment

-- environment

local mt = {
    __index = function(_,k)
        if k == "version" then
            local version = texgettoks and texgettoks("contextversiontoks")
            if version and version ~= "" then
                rawset(environment,"version",version)
                return version
            else
                return "unknown"
            end
        elseif k == "kind" then
            local kind = texgettoks and texgettoks("contextkindtoks")
            if kind and kind ~= "" then
                rawset(environment,"kind",kind)
                return kind
            else
                return "unknown"
            end
        elseif k == "jobname" or k == "formatname" then
            local name = tex and tex[k]
            if name or name== "" then
                rawset(environment,k,name)
                return name
            else
                return "unknown"
            end
        elseif k == "outputfilename" then
            local name = environment.jobname
            rawset(environment,k,name)
            return name
        end
    end
}

setmetatable(environment,mt)

-- weird place ... depends on a not yet loaded module

function environment.texfile(filename)
    return resolvers.findfile(filename,'tex')
end

function environment.luafile(filename) -- needs checking

    if CONTEXTLMTXMODE and CONTEXTLMTXMODE > 0 and file.suffix(filename) == "lua" then
        -- no "tex", as that's pretty slow when not found (suffixes get appended, shouldn't happen)
     -- trackers.enable("resolvers.*")
        local resolved = resolvers.findfile(file.replacesuffix(filename,"lmt")) or ""
     -- trackers.disable("resolvers.*")
        if resolved ~= "" then
            return resolved
        end
    end

    local resolved = resolvers.findfile(filename,'tex') or ""
    if resolved ~= "" then
        return resolved
    end
    resolved = resolvers.findfile(filename,'texmfscripts') or ""
    if resolved ~= "" then
        return resolved
    end
    return resolvers.findfile(filename,'luatexlibs') or ""
end

-- local function checkstrip(filename)
--     local modu = modules[file.nameonly(filename)]
--     return modu and modu.dataonly
-- end

local stripindeed = false  directives.register("system.compile.strip", function(v) stripindeed = v end)

local function strippable(filename)
    if stripindeed then
        local modu = modules[file.nameonly(filename)]
        return modu and modu.dataonly
    else
        return false
    end
end

function environment.luafilechunk(filename,silent,macros) -- used for loading lua bytecode in the format
    filename = file.replacesuffix(filename, "lua")
    local fullname = environment.luafile(filename)
    if fullname and fullname ~= "" then
        local data = luautilities.loadedluacode(fullname,strippable,filename,macros)
        if not silent then
            report_lua("loading file %a %s",fullname,not data and "failed" or "succeeded")
        end
        return data
    else
        if not silent then
            report_lua("unknown file %a",filename)
        end
        return nil
    end
end

-- the next ones can use the previous ones / combine

function environment.loadluafile(filename, version)
    local lucname, luaname, chunk
    local basename = file.removesuffix(filename)
    if basename == filename then
        luaname = file.addsuffix(basename,luasuffixes.lua)
        lucname = file.addsuffix(basename,luasuffixes.luc)
    else
        luaname = filename -- forced suffix
        lucname = nil
    end
    -- when not overloaded by explicit suffix we look for a luc file first
    local fullname = (lucname and environment.luafile(lucname)) or ""
    if fullname ~= "" then
        if trace_locating then
            report_lua("loading %a",fullname)
        end
        -- maybe: package.loaded[file.nameonly(fullname)] = true
        chunk = loadfile(fullname) -- this way we don't need a file exists check
    end
    if chunk then
        chunk()
        if version then
            -- we check of the version number of this chunk matches
            local v = version -- can be nil
            if modules and modules[filename] then
                v = modules[filename].version -- new method
            elseif versions and versions[filename] then
                v = versions[filename]        -- old method
            end
            if v == version then
                return true
            else
                if trace_locating then
                    report_lua("version mismatch for %a, lua version %a, luc version %a",filename,v,version)
                end
                environment.loadluafile(filename)
            end
        else
            return true
        end
    end
    fullname = (luaname and environment.luafile(luaname)) or ""
    if fullname ~= "" then
        if trace_locating then
            report_lua("loading %a",fullname)
        end
        chunk = loadfile(fullname) -- this way we don't need a file exists check
        if not chunk then
            if trace_locating then
                report_lua("unknown file %a",filename)
            end
        else
            chunk()
            return true
        end
    end
    return false
end

environment.filenames = setmetatable( { }, {
    __index = function(t,k)
        local v = environment.files[k]
        if v then
            return (gsub(v,"%.+$",""))
        end
    end,
    __newindex = function(t,k)
        -- nothing
    end,
    __len = function(t)
        return #environment.files
    end,
} )