summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/mlib-run.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mlib-run.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/mlib-run.lua312
1 files changed, 220 insertions, 92 deletions
diff --git a/Master/texmf-dist/tex/context/base/mlib-run.lua b/Master/texmf-dist/tex/context/base/mlib-run.lua
index 30cd01c736d..7351c332fb4 100644
--- a/Master/texmf-dist/tex/context/base/mlib-run.lua
+++ b/Master/texmf-dist/tex/context/base/mlib-run.lua
@@ -23,35 +23,40 @@ if not modules then modules = { } end modules ['mlib-run'] = {
<p>The directional helpers and pen analysis are more or less translated from the
<l n='c'/> code. It really helps that Taco know that source so well. Taco and I spent
quite some time on speeding up the <l n='lua'/> and <l n='c'/> code. There is not
-much to gain, especially if on ekeeps in mind that when integrated in <l n='tex'/>
+much to gain, especially if one keeps in mind that when integrated in <l n='tex'/>
only a part of the time is spent in <l n='metapost'/>. Of course an integrated
approach is way faster than an external <l n='metapost'/> and processing time
nears zero.</p>
--ldx]]--
+local trace_graphics = false trackers.register("metapost.graphics", function(v) trace_graphics = v end)
+
local format = string.format
+local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming
+
+
metapost = metapost or { }
+metapost.showlog = false
+metapost.lastlog = ""
+
+function metapost.resetlastlog()
+ metapost.lastlog = ""
+end
+
local function finder(name, mode, ftype)
if mode=="w" then
return name
- elseif input.aux.qualified_path(name) then
+ elseif file.is_qualified_path(name) then
return name
else
- return input.find_file((texmf and texmf.instance) or instance,name,ftype)
+ return resolvers.find_file(name,ftype)
end
end
metapost.finder = finder
---~ statistics = {
---~ ["hash_size"]=1774,
---~ ["main_memory"]=50237,
---~ ["max_in_open"]=5,
---~ ["param_size"]=4,
---~ }
-
metapost.parameters = {
hash_size = 100000,
main_memory = 2000000,
@@ -61,103 +66,136 @@ metapost.parameters = {
metapost.exectime = metapost.exectime or { } -- hack
+local preamble = [[
+boolean mplib; string mp_parent_version;
+mplib := true;
+mp_parent_version := "%s";
+input %s ; dump ;
+]]
+
function metapost.make(name, target, version)
- input.starttiming(mplib)
+ starttiming(mplib)
target = file.replacesuffix(target or name, "mem")
local mpx = mplib.new ( table.merged (
metapost.parameters,
{
ini_version = true,
find_file = finder,
- job_name = file.stripsuffix(target),
+ job_name = file.removesuffix(target),
}
) )
if mpx then
- input.starttiming(metapost.exectime)
- local result = mpx:execute(format('\\ ; boolean mplib ; mplib := true ; string mp_parent_version ; mp_parent_version := "%s" ; show mp_parent_version ; input %s ; dump ;', version or "unknown", name))
- input.stoptiming(metapost.exectime)
- if mpx then
- mpx:finish()
- end
+ starttiming(metapost.exectime)
+ local result = mpx:execute(format(preamble,version or "unknown",name))
+ stoptiming(metapost.exectime)
+ mpx:finish()
end
- input.stoptiming(mplib)
- return mpx -- mpx = nil will free memory
+ stoptiming(mplib)
end
function metapost.load(name)
- input.starttiming(mplib)
+ starttiming(mplib)
local mpx = mplib.new ( table.merged (
metapost.parameters,
{
+ ini_version = false,
mem_name = file.replacesuffix(name,"mem"),
find_file = finder,
+ -- job_name = "mplib",
}
) )
- if mpx then
- input.starttiming(metapost.exectime)
- mpx:execute("\\")
- input.stoptiming(metapost.exectime)
+ local result
+ if not mpx then
+ result = { status = 99, error = "out of memory"}
end
- input.stoptiming(mplib)
- return mpx
+ stoptiming(mplib)
+ return mpx, result
end
function metapost.unload(mpx)
- input.starttiming(mplib)
+ starttiming(mplib)
if mpx then
mpx:finish()
end
- input.stoptiming(mplib)
+ stoptiming(mplib)
end
-function metapost.checkformat(mpsinput, mpsformat)
+function metapost.reporterror(result)
+ if not result then
+ metapost.report("mp error: no result object returned")
+ elseif result.status > 0 then
+ local t, e, l = result.term, result.error, result.log
+ if t and t ~= "" then
+ metapost.report("mp terminal: %s",t)
+ end
+ if e then
+ metapost.report("mp error: %s",(e=="" and "?") or e)
+ end
+ if not t and not e and l then
+ metapost.lastlog = metapost.lastlog .. "\n" .. l
+ metapost.report("mp log: %s",l)
+ else
+ metapost.report("mp error: unknown, no error, terminal or log messages")
+ end
+ else
+ return false
+ end
+ return true
+end
+
+function metapost.checkformat(mpsinput, mpsformat, dirname)
mpsinput = file.addsuffix(mpsinput or "metafun", "mp")
- mpsformat = file.stripsuffix(file.basename(mpsformat or texconfig.formatname or tex.formatname or mpsinput))
- local mpsbase = file.stripsuffix(file.basename(mpsinput))
+ mpsformat = file.removesuffix(file.basename(mpsformat or texconfig.formatname or (tex and tex.formatname) or mpsinput))
+ local mpsbase = file.removesuffix(file.basename(mpsinput))
if mpsbase ~= mpsformat then
mpsformat = mpsformat .. "-" .. mpsbase
end
mpsformat = file.addsuffix(mpsformat, "mem")
- local pth = file.dirname(texconfig.formatname or "")
+ local pth = dirname or file.dirname(texconfig.formatname or "")
if pth ~= "" then
mpsformat = file.join(pth,mpsformat)
end
local the_version = environment.version or "unset version"
- if io.exists(mpsformat) then
- commands.writestatus("mplib", format("loading format: %s, name: %s", mpsinput, mpsformat))
- local mpx = metapost.load(mpsformat)
+ if lfs.isfile(mpsformat) then
+ commands.writestatus("mplib","loading '%s' from '%s'", mpsinput, mpsformat)
+ local mpx, result = metapost.load(mpsformat)
if mpx then
- local result = mpx:execute(format("show mp_parent_version ;"))
- local version = result.log:match(">> *(.-)[\n\r]") or "unknown"
- version = version:gsub("[\'\"]","")
- if version ~= the_version then
- commands.writestatus("mplib", format("version mismatch: %s <> %s", version or "unknown", the_version))
+ local result = mpx:execute("show mp_parent_version ;")
+ if not result.log then
+ metapost.reporterror(result)
else
- return mpx
+ local version = result.log:match(">> *(.-)[\n\r]") or "unknown"
+ version = version:gsub("[\'\"]","")
+ if version ~= the_version then
+ commands.writestatus("mplib","version mismatch: %s <> %s", version or "unknown", the_version)
+ else
+ return mpx
+ end
end
+ else
+ commands.writestatus("mplib","error in loading '%s' from '%s'", mpsinput, mpsformat)
+ metapost.reporterror(result)
end
end
- commands.writestatus("mplib", format("making format: %s, name: %s", mpsinput, mpsformat))
+ commands.writestatus("mplib","making '%s' into '%s'", mpsinput, mpsformat)
metapost.make(mpsinput,mpsformat,the_version) -- somehow return ... fails here
- if io.exists(mpsformat) then
- commands.writestatus("mplib", format("loading format: %s, name: %s", mpsinput, mpsformat))
+ if lfs.isfile(mpsformat) then
+ commands.writestatus("mplib","loading '%s' from '%s'", mpsinput, mpsformat)
return metapost.load(mpsformat)
else
- commands.writestatus("mplib", format("problems with format: %s, name: %s", mpsinput, mpsformat))
+ commands.writestatus("mplib","problems with '%s' from '%s'", mpsinput, mpsformat)
end
end
---~ if environment.initex then
---~ metapost.unload(metapost.checkformat("metafun"))
---~ end
+local mpxformats = { }
-local mpxformats = {}
-
-function metapost.format(name)
- local mpx = mpxformats[name]
+function metapost.format(instance,name)
+ name = name or instance
+ local mpx = mpxformats[instance]
if not mpx then
+ commands.writestatus("mplib","initializing instance '%s' using format '%s'",instance,name)
mpx = metapost.checkformat(name)
- mpxformats[name] = mpx
+ mpxformats[instance] = mpx
end
return mpx
end
@@ -171,80 +209,170 @@ function metapost.reset(mpx)
mpxformats[mpx] = nil
end
else
- for name=1,#mpxformats do
- if mpxformats[name] == mpx then
+ for name, instance in pairs(mpxformats) do
+ if instance == mpx then
+ mpx:finish()
mpxformats[name] = nil
break
end
end
- mpx:finish()
end
end
-metapost.showlog = false
+local mp_inp, mp_log, mp_tag = { }, { }, 0
-function metapost.process(mpx, data, trialrun, flusher, multipass)
+function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass, askedfig)
local converted, result = false, {}
if type(mpx) == "string" then
mpx = metapost.format(mpx) -- goody
end
if mpx and data then
- input.starttiming(metapost)
+ starttiming(metapost)
+ if trace_graphics then
+ if not mp_inp[mpx] then
+ mp_tag = mp_tag + 1
+ mp_inp[mpx] = io.open(format("%s-mplib-run-%03i.mp", tex.jobname,mp_tag),"w")
+ mp_log[mpx] = io.open(format("%s-mplib-run-%03i.log",tex.jobname,mp_tag),"w")
+ end
+ local banner = format("%% begin graphic: n=%s, trialrun=%s, multipass=%s, isextrapass=%s\n\n", metapost.n, tostring(trialrun), tostring(multipass), tostring(isextrapass))
+ mp_inp[mpx]:write(banner)
+ mp_log[mpx]:write(banner)
+ end
if type(data) == "table" then
for i=1,#data do
local d = data[i]
if d then
- input.starttiming(metapost.exectime)
+ if trace_graphics then
+ mp_inp[mpx]:write(d)
+ end
+ starttiming(metapost.exectime)
result = mpx:execute(d)
- input.stoptiming(metapost.exectime)
- if not result then
- metapost.report("mp error", "no result object returned")
- elseif result.status > 0 then
- local t, e, l = result.term, result.error, result.log
- if t then
- metapost.report("mp terminal",t)
+ stoptiming(metapost.exectime)
+ if trace_graphics and result then
+ local str = result.log or result.error
+ if str and str ~= "" then
+ mp_log[mpx]:write(str)
end
- if e then
- metapost.report("mp error",e)
+ end
+ if not metapost.reporterror(result) then
+ if metapost.showlog then
+ local str = (result.term ~= "" and result.term) or "no terminal output"
+ if not str:is_empty() then
+ metapost.lastlog = metapost.lastlog .. "\n" .. str
+ metapost.report("mp log: %s",str)
+ end
end
- if not t and not e and l then
- metapost.report("mp log",l)
- else
- metapost.report("mp error","unknown, no error, terminal or log messages")
+ if result.fig then
+ converted = metapost.convert(result, trialrun, flusher, multipass, askedfig)
end
- elseif metapost.showlog then
- metapost.report("mp info",result.term or "no terminal output")
- elseif result.fig then
- converted = metapost.convert(result, trialrun, flusher, multipass)
end
else
- metapost.report("mp error", "invalid graphic component " .. i)
+ metapost.report("mp error: invalid graphic component %s",i)
end
end
else
- input.starttiming(metapost.exectime)
- result = mpx:execute(data)
- input.stoptiming(metapost.exectime)
+ if trace_graphics then
+ mp_inp:write(data)
+ end
+ starttiming(metapost.exectime)
+ result = mpx[mpx]:execute(data)
+ stoptiming(metapost.exectime)
+ if trace_graphics and result then
+ local str = result.log or result.error
+ if str and str ~= "" then
+ mp_log[mpx]:write(str)
+ end
+ end
-- todo: error message
if not result then
- metapost.report("error", "no result object returned")
+ metapost.report("mp error: no result object returned")
elseif result.status > 0 then
- metapost.report("error",(result.term or "no-term") .. "\n" .. (result.error or "no-error"))
- elseif metapost.showlog then
- metapost.report("info",result.term or "no-term")
- elseif result.fig then
- converted = metapost.convert(result, trialrun, flusher, multipass)
+ metapost.report("mp error: %s",(result.term or "no-term") .. "\n" .. (result.error or "no-error"))
+ else
+ if metapost.showlog then
+ metapost.lastlog = metapost.lastlog .. "\n" .. result.term
+ metapost.report("mp info: %s",result.term or "no-term")
+ end
+ if result.fig then
+ converted = metapost.convert(result, trialrun, flusher, multipass, askedfig)
+ end
end
end
- input.stoptiming(metapost)
+ if trace_graphics then
+ local banner = "\n% end graphic\n\n"
+ mp_inp[mpx]:write(banner)
+ mp_log[mpx]:write(banner)
+ end
+ stoptiming(metapost)
end
return converted, result
end
-function metapost.convert(result, trialrun, multipass)
- metapost.report('Warning','no converter set')
+function metapost.convert()
+ metapost.report('mp warning: no converter set')
end
function metapost.report(...)
- logs.report(...)
+ logs.report("mplib",...)
+end
+
+-- handy
+
+function metapost.directrun(formatname,filename,outputformat,astable,mpdata)
+ local fullname = file.addsuffix(filename,"mp")
+ local data = mpdata or io.loaddata(fullname)
+ if outputformat ~= "svg" then
+ outputformat = "mps"
+ end
+ if not data then
+ logs.simple("unknown file '%s'",filename or "?")
+ else
+ local mpx = metapost.checkformat(formatname,formatname,caches.setpath("formats"))
+ if not mpx then
+ logs.simple("unknown format '%s'",formatname or "?")
+ else
+ logs.simple("processing '%s'",(mpdata and (filename or "data")) or fullname)
+ local result = mpx:execute(data)
+ if not result then
+ logs.simple("error: no result object returned")
+ elseif result.status > 0 then
+ logs.simple("error: %s",(result.term or "no-term") .. "\n" .. (result.error or "no-error"))
+ else
+ if metapost.showlog then
+ metapost.lastlog = metapost.lastlog .. "\n" .. result.term
+ logs.simple("info: %s",result.term or "no-term")
+ end
+ local figures = result.fig
+ if figures then
+ local sorted = table.sortedkeys(figures)
+ if astable then
+ local result = { }
+ logs.simple("storing %s figures in table",#sorted)
+ for k, v in ipairs(sorted) do
+ if outputformat == "mps" then
+ result[v] = figures[v]:postscript()
+ else
+ result[v] = figures[v]:svg() -- (3) for prologues
+ end
+ end
+ return result
+ else
+ local basename = file.removesuffix(file.basename(filename))
+ for k, v in ipairs(sorted) do
+ local output
+ if outputformat == "mps" then
+ output = figures[v]:postscript()
+ else
+ output = figures[v]:svg() -- (3) for prologues
+ end
+ local outname = format("%s-%s.%s",basename,v,outputformat)
+ logs.simple("saving %s bytes in '%s'",#output,outname)
+ io.savedata(outname,output)
+ end
+ return #sorted
+ end
+ end
+ end
+ end
+ end
end