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.lua367
1 files changed, 230 insertions, 137 deletions
diff --git a/Master/texmf-dist/tex/context/base/mlib-run.lua b/Master/texmf-dist/tex/context/base/mlib-run.lua
index 59dc88b909d..0d7b5aa6dd1 100644
--- a/Master/texmf-dist/tex/context/base/mlib-run.lua
+++ b/Master/texmf-dist/tex/context/base/mlib-run.lua
@@ -29,58 +29,91 @@ 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 type, tostring, tonumber = type, tostring, tonumber
+local format, gsub, match, find = string.format, string.gsub, string.match, string.find
+local concat = table.concat
+local emptystring = string.is_empty
+local lpegmatch, P = lpeg.match, lpeg.P
-local report_metapost = logs.reporter("metapost")
+local trace_graphics = false trackers.register("metapost.graphics", function(v) trace_graphics = v end)
+local trace_tracingall = false trackers.register("metapost.tracingall", function(v) trace_tracingall = v end)
+local report_metapost = logs.reporter("metapost")
local texerrormessage = logs.texerrormessage
-local format, gsub, match, find = string.format, string.gsub, string.match, string.find
-local emptystring = string.is_empty
-
-local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
-local mplib = mplib
+local mplib = mplib
+metapost = metapost or { }
+local metapost = metapost
-metapost = metapost or { }
-local metapost = metapost
+local mplibone = tonumber(mplib.version()) <= 1.50
metapost.showlog = false
metapost.lastlog = ""
+metapost.collapse = true -- currently mplib cannot deal with begingroup/endgroup mismatch in stepwise processing
metapost.texerrors = false
metapost.exectime = metapost.exectime or { } -- hack
-local mplibone = tonumber(mplib.version()) <= 1.50
-
-directives.register("mplib.texerrors", function(v) metapost.texerrors = v end)
+directives.register("mplib.texerrors", function(v) metapost.texerrors = v end)
+trackers.register ("metapost.showlog", function(v) metapost.showlog = v end)
function metapost.resetlastlog()
metapost.lastlog = ""
end
--- local function realfinder(name, mode, ftype)
--- if mode == "w" then
--- return name
--- elseif file.is_qualified_path(name) then
--- return name
--- else
--- return resolvers.findfile(name,ftype)
+----- mpbasepath = lpeg.instringchecker(lpeg.append { "/metapost/context/", "/metapost/base/" })
+local mpbasepath = lpeg.instringchecker(P("/metapost/") * (P("context") + P("base")) * P("/"))
+
+-- local function i_finder(askedname,mode,ftype) -- fake message for mpost.map and metafun.mpvi
+-- local foundname = file.is_qualified_path(askedname) and askedname or resolvers.findfile(askedname,ftype)
+-- if not mpbasepath(foundname) then
+-- -- we could use the via file but we don't have a complete io interface yet
+-- local data, found, forced = metapost.checktexts(io.loaddata(foundname) or "")
+-- if found then
+-- local tempname = luatex.registertempfile(foundname,true)
+-- io.savedata(tempname,data)
+-- foundname = tempname
+-- end
-- end
+-- return foundname
-- end
-local function i_finder(name, mode, ftype) -- fake message for mpost.map and metafun.mpvi
- name = file.is_qualified_path(name) and name or resolvers.findfile(name,ftype)
- if not (find(name,"/metapost/context/base/") or find(name,"/metapost/context/") or find(name,"/metapost/base/")) then
+-- mplib has no real io interface so we have a different mechanism than
+-- tex (as soon as we have more control, we will use the normal code)
+
+local finders = { }
+mplib.finders = finders
+
+-- for some reason mp sometimes calls this function twice which is inefficient
+-- but we cannot catch this
+
+local function preprocessed(name)
+ if not mpbasepath(name) then
+ -- we could use the via file but we don't have a complete io interface yet
local data, found, forced = metapost.checktexts(io.loaddata(name) or "")
if found then
local temp = luatex.registertempfile(name,true)
io.savedata(temp,data)
- name = temp
+ return temp
end
end
return name
end
+mplib.preprocessed = preprocessed -- helper
+
+finders.file = function(specification,name,mode,ftype)
+ return preprocessed(resolvers.findfile(name,ftype))
+end
+
+local function i_finder(name,mode,ftype) -- fake message for mpost.map and metafun.mpvi
+ local specification = url.hashed(name)
+ local finder = finders[specification.scheme] or finders.file
+ return finder(specification,name,mode,ftype)
+end
+
local function o_finder(name, mode, ftype)
return name
end
@@ -128,8 +161,11 @@ function metapost.reporterror(result)
if t and t ~= "" then
(metapost.texerrors and texerrormessage or report_metapost)("terminal: %s",t)
end
+ if e == "" or e == "no-error" then
+ e = nil
+ end
if e then
- (metapost.texerrors and texerrormessage or report_metapost)("error: %s",(e=="" and "?") or e)
+ (metapost.texerrors and texerrormessage or report_metapost)("error: %s",e)
end
if not t and not e and l then
metapost.lastlog = metapost.lastlog .. "\n" .. l
@@ -145,99 +181,103 @@ end
if mplibone then
- local preamble = [[
- boolean mplib ; mplib := true ;
- string mp_parent_version ; mp_parent_version := "%s" ;
- input "%s" ; dump ;
- ]]
-
- metapost.parameters = {
- hash_size = 100000,
- main_memory = 4000000,
- max_in_open = 50,
- param_size = 100000,
- }
-
- function metapost.make(name, target, version)
- starttiming(mplib)
- target = file.replacesuffix(target or name, "mem") -- redundant
- local mpx = mplib.new ( table.merged (
- metapost.parameters,
- {
- ini_version = true,
- find_file = finder,
- job_name = file.removesuffix(target),
- }
- ) )
- if mpx then
- starttiming(metapost.exectime)
- local result = mpx:execute(format(preamble,version or "unknown",name))
- stoptiming(metapost.exectime)
- mpx:finish()
- end
- stoptiming(mplib)
- end
-
- function metapost.load(name)
- 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",
- }
- ) )
- local result
- if not mpx then
- result = { status = 99, error = "out of memory"}
- end
- stoptiming(mplib)
- return mpx, result
- end
-
- function metapost.checkformat(mpsinput)
- local mpsversion = environment.version or "unset version"
- local mpsinput = file.addsuffix(mpsinput or "metafun", "mp")
- local mpsformat = file.removesuffix(file.basename(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 mpsformatfullname = caches.getfirstreadablefile(mpsformat,"formats") or ""
- if mpsformatfullname ~= "" then
- report_metapost("loading '%s' from '%s'", mpsinput, mpsformatfullname)
- local mpx, result = metapost.load(mpsformatfullname)
- if mpx then
- local result = mpx:execute("show mp_parent_version ;")
- if not result.log then
- metapost.reporterror(result)
- else
- local version = match(result.log,">> *(.-)[\n\r]") or "unknown"
- version = gsub(version,"[\'\"]","")
- if version ~= mpsversion then
- report_metapost("version mismatch: %s <> %s", version or "unknown", mpsversion)
- else
- return mpx
- end
- end
- else
- report_metapost("error in loading '%s' from '%s'", mpsinput, mpsformatfullname)
- metapost.reporterror(result)
- end
- end
- local mpsformatfullname = caches.setfirstwritablefile(mpsformat,"formats")
- report_metapost("making '%s' into '%s'", mpsinput, mpsformatfullname)
- metapost.make(mpsinput,mpsformatfullname,mpsversion) -- somehow return ... fails here
- if lfs.isfile(mpsformatfullname) then
- report_metapost("loading '%s' from '%s'", mpsinput, mpsformatfullname)
- return metapost.load(mpsformatfullname)
- else
- report_metapost("problems with '%s' from '%s'", mpsinput, mpsformatfullname)
- end
- end
+ report_metapost("fatal error: mplib is too old")
+
+ os.exit()
+
+ -- local preamble = [[
+ -- boolean mplib ; mplib := true ;
+ -- string mp_parent_version ; mp_parent_version := "%s" ;
+ -- input "%s" ; dump ;
+ -- ]]
+ --
+ -- metapost.parameters = {
+ -- hash_size = 100000,
+ -- main_memory = 4000000,
+ -- max_in_open = 50,
+ -- param_size = 100000,
+ -- }
+ --
+ -- function metapost.make(name, target, version)
+ -- starttiming(mplib)
+ -- target = file.replacesuffix(target or name, "mem") -- redundant
+ -- local mpx = mplib.new ( table.merged (
+ -- metapost.parameters,
+ -- {
+ -- ini_version = true,
+ -- find_file = finder,
+ -- job_name = file.removesuffix(target),
+ -- }
+ -- ) )
+ -- if mpx then
+ -- starttiming(metapost.exectime)
+ -- local result = mpx:execute(format(preamble,version or "unknown",name))
+ -- stoptiming(metapost.exectime)
+ -- mpx:finish()
+ -- end
+ -- stoptiming(mplib)
+ -- end
+ --
+ -- function metapost.load(name)
+ -- 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",
+ -- }
+ -- ) )
+ -- local result
+ -- if not mpx then
+ -- result = { status = 99, error = "out of memory"}
+ -- end
+ -- stoptiming(mplib)
+ -- return mpx, result
+ -- end
+ --
+ -- function metapost.checkformat(mpsinput)
+ -- local mpsversion = environment.version or "unset version"
+ -- local mpsinput = file.addsuffix(mpsinput or "metafun", "mp")
+ -- local mpsformat = file.removesuffix(file.basename(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 mpsformatfullname = caches.getfirstreadablefile(mpsformat,"formats","metapost") or ""
+ -- if mpsformatfullname ~= "" then
+ -- report_metapost("loading %a from %a", mpsinput, mpsformatfullname)
+ -- local mpx, result = metapost.load(mpsformatfullname)
+ -- if mpx then
+ -- local result = mpx:execute("show mp_parent_version ;")
+ -- if not result.log then
+ -- metapost.reporterror(result)
+ -- else
+ -- local version = match(result.log,">> *(.-)[\n\r]") or "unknown"
+ -- version = gsub(version,"[\'\"]","")
+ -- if version ~= mpsversion then
+ -- report_metapost("version mismatch: %s <> %s", version or "unknown", mpsversion)
+ -- else
+ -- return mpx
+ -- end
+ -- end
+ -- else
+ -- report_metapost("error in loading %a from %a", mpsinput, mpsformatfullname)
+ -- metapost.reporterror(result)
+ -- end
+ -- end
+ -- local mpsformatfullname = caches.setfirstwritablefile(mpsformat,"formats")
+ -- report_metapost("making %a into %a", mpsinput, mpsformatfullname)
+ -- metapost.make(mpsinput,mpsformatfullname,mpsversion) -- somehow return ... fails here
+ -- if lfs.isfile(mpsformatfullname) then
+ -- report_metapost("loading %a from %a", mpsinput, mpsformatfullname)
+ -- return metapost.load(mpsformatfullname)
+ -- else
+ -- report_metapost("problems with %a from %a", mpsinput, mpsformatfullname)
+ -- end
+ -- end
else
@@ -247,12 +287,22 @@ else
input "%s" ;
]]
- function metapost.load(name)
+ local methods = {
+ double = "double",
+ scaled = "scaled",
+ default = "scaled",
+ decimal = false, -- for the moment
+ }
+
+ function metapost.load(name,method)
starttiming(mplib)
+ method = method and methods[method] or "scaled"
local mpx = mplib.new {
ini_version = true,
- find_file = finder,
+ find_file = finder,
+ math_mode = method,
}
+ report_metapost("initializing number mode %a",method)
local result
if not mpx then
result = { status = 99, error = "out of memory"}
@@ -264,7 +314,7 @@ else
return mpx, result
end
- function metapost.checkformat(mpsinput)
+ function metapost.checkformat(mpsinput,method)
local mpsversion = environment.version or "unset version"
local mpsinput = mpsinput or "metafun"
local foundfile = ""
@@ -281,14 +331,14 @@ else
foundfile = finder(file.replacesuffix(mpsinput,"mp")) or ""
end
if foundfile == "" then
- report_metapost("loading '%s' fails, format not found",mpsinput)
+ report_metapost("loading %a fails, format not found",mpsinput)
else
- report_metapost("loading '%s': %s",mpsinput,foundfile)
- local mpx, result = metapost.load(foundfile)
+ report_metapost("loading %a as %a using method %a",mpsinput,foundfile,method or "default")
+ local mpx, result = metapost.load(foundfile,method)
if mpx then
return mpx
else
- report_metapost("error in loading '%s'",mpsinput)
+ report_metapost("error in loading %a",mpsinput)
metapost.reporterror(result)
end
end
@@ -306,17 +356,24 @@ end
local mpxformats = { }
-function metapost.format(instance,name)
+function metapost.format(instance,name,method)
+ if not instance or instance == "" then
+ instance = "metafun" -- brrr
+ end
name = name or instance
local mpx = mpxformats[instance]
if not mpx then
- report_metapost("initializing instance '%s' using format '%s'",instance,name)
- mpx = metapost.checkformat(name)
+ report_metapost("initializing instance %a using format %a",instance,name)
+ mpx = metapost.checkformat(name,method)
mpxformats[instance] = mpx
end
return mpx
end
+function metapost.instance(instance)
+ return mpxformats[instance]
+end
+
function metapost.reset(mpx)
if not mpx then
-- nothing
@@ -350,19 +407,52 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass,
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")
+ local jobname = tex.jobname
+ mp_inp[mpx] = io.open(format("%s-mplib-run-%03i.mp", jobname,mp_tag),"w")
+ mp_log[mpx] = io.open(format("%s-mplib-run-%03i.log",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
+ -- this hack is needed because the library currently barks on \n\n
+ -- eventually we can text for "" in the next loop
+ local n = 0
+ local nofsnippets = #data
+ for i=1,nofsnippets do
+ local d = data[i]
+ if d ~= "" then
+ n = n + 1
+ data[n] = d
+ end
+ end
+ for i=nofsnippets,n+1,-1 do
+ data[i] = nil
+ end
+ -- and this one because mp cannot handle snippets due to grouping issues
+ if metapost.collapse then
+ if #data > 1 then
+ data = concat(data,"\n")
+ else
+ data = data[1]
+ end
+ end
+ -- end of hacks
+ end
+ if type(data) == "table" then
+ if trace_tracingall then
+ mpx:execute("tracingall;")
+ end
+ -- table.insert(data,2,"")
for i=1,#data do
local d = data[i]
+ -- d = string.gsub(d,"\r","")
if d then
if trace_graphics then
+ mp_inp[mpx]:write(format("\n%% begin snippet %s\n",i))
mp_inp[mpx]:write(d)
+ mp_inp[mpx]:write(format("\n%% end snippet %s\n",i))
end
starttiming(metapost.exectime)
result = mpx:execute(d)
@@ -375,7 +465,7 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass,
end
if not metapost.reporterror(result) then
if metapost.showlog then
- local str = (result.term ~= "" and result.term) or "no terminal output"
+ local str = result.term ~= "" and result.term or "no terminal output"
if not emptystring(str) then
metapost.lastlog = metapost.lastlog .. "\n" .. str
report_metapost("log: %s",str)
@@ -390,11 +480,14 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass,
end
end
else
+ if trace_tracingall then
+ data = "tracingall;" .. data
+ end
if trace_graphics then
- mp_inp:write(data)
+ mp_inp[mpx]:write(data)
end
starttiming(metapost.exectime)
- result = mpx[mpx]:execute(data)
+ result = mpx:execute(data)
stoptiming(metapost.exectime)
if trace_graphics and result then
local str = result.log or result.error
@@ -412,7 +505,7 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass,
metapost.lastlog = metapost.lastlog .. "\n" .. result.term
report_metapost("info: %s",result.term or "no-term")
end
- if result.fig then
+ if result.fig then
converted = metapost.convert(result, trialrun, flusher, multipass, askedfig)
end
end
@@ -440,13 +533,13 @@ function metapost.directrun(formatname,filename,outputformat,astable,mpdata)
outputformat = "mps"
end
if not data then
- report_metapost("unknown file '%s'",filename or "?")
+ report_metapost("unknown file %a",filename)
else
local mpx = metapost.checkformat(formatname)
if not mpx then
- report_metapost("unknown format '%s'",formatname or "?")
+ report_metapost("unknown format %a",formatname)
else
- report_metapost("processing '%s'",(mpdata and (filename or "data")) or fullname)
+ report_metapost("processing %a",(mpdata and (filename or "data")) or fullname)
local result = mpx:execute(data)
if not result then
report_metapost("error: no result object returned")
@@ -483,7 +576,7 @@ function metapost.directrun(formatname,filename,outputformat,astable,mpdata)
output = figures[v]:svg() -- (3) for prologues
end
local outname = format("%s-%s.%s",basename,v,outputformat)
- report_metapost("saving %s bytes in '%s'",#output,outname)
+ report_metapost("saving %s bytes in %a",#output,outname)
io.savedata(outname,output)
end
return #sorted