summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/back-out.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/back-out.lua')
-rw-r--r--tex/context/base/mkiv/back-out.lua291
1 files changed, 291 insertions, 0 deletions
diff --git a/tex/context/base/mkiv/back-out.lua b/tex/context/base/mkiv/back-out.lua
new file mode 100644
index 000000000..a0e05afca
--- /dev/null
+++ b/tex/context/base/mkiv/back-out.lua
@@ -0,0 +1,291 @@
+if not modules then modules = { } end modules ['back-out'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+if CONTEXTLMTXMODE == 0 then
+
+ return
+
+elseif CONTEXTLMTXMODE == 1 then
+
+ local type = type
+ local getdata = nodes.nuts.getdata
+ local loadstring = loadstring
+
+ function backends.latelua(current,pos_h,pos_v,cur_h,cur_v)
+ data = getdata(current)
+ local kind = type(data)
+ if kind == "function" then
+ data()
+ elseif kind == "table" then
+ data.action(data)
+ else
+ -- if kind ~= "string" then
+ -- data = tokentostring(data)
+ -- end
+ if #data ~= "" then
+ local code = loadstring(data)
+ if code then
+ code()
+ end
+ end
+ end
+ end
+
+ return
+end
+
+local type = type
+local loadstring = loadstring
+
+local context = context
+
+-- tokens.scanners.....
+
+local get = token.get_index
+local scaninteger = token.scan_int
+local scanstring = token.scan_string
+local scankeyword = token.scan_keyword
+local scantokenlist = token.scan_tokenlist
+local scancode = token.scan_code
+
+local tokentostring = token.to_string
+
+local logwriter = logs.writer
+local openfile = io.open
+
+local nuts = nodes.nuts
+local tonode = nuts.tonode
+local copynode = nuts.copy
+local nodepool = nuts.pool
+
+local getdata = nuts.getdata
+
+local whatsit_code = nodes.nodecodes.whatsit
+
+local whatsitcodes = nodes.whatsitcodes
+
+local literalvalues = nodes.literalvalues
+local originliteral_code = literalvalues.origin
+local pageliteral_code = literalvalues.page
+local directliteral_code = literalvalues.direct
+local rawliteral_code = literalvalues.raw
+
+local nodeproperties = nodes.properties.data
+
+local channels = { }
+
+local register = nodepool.register
+local newnut = nuts.new
+
+local opennode = register(newnut(whatsit_code,whatsitcodes.open))
+local writenode = register(newnut(whatsit_code,whatsitcodes.write))
+local closenode = register(newnut(whatsit_code,whatsitcodes.close))
+local lateluanode = register(newnut(whatsit_code,whatsitcodes.latelua))
+local literalnode = register(newnut(whatsit_code,whatsitcodes.literal))
+local savenode = register(newnut(whatsit_code,whatsitcodes.save))
+local restorenode = register(newnut(whatsit_code,whatsitcodes.restore))
+local setmatrixnode = register(newnut(whatsit_code,whatsitcodes.setmatrix))
+
+local tomatrix = drivers.helpers.tomatrix
+
+local open_command, write_command, close_command
+
+backends = backends or { }
+
+local function openout(immediate)
+ local channel = scaninteger()
+ scankeyword("=") -- hack
+ local filename = scanstring()
+ if not immediate then
+ local n = copynode(opennode)
+ nodeproperties[n] = { channel = channel, filename = filename } -- action = "open"
+ return context(tonode(n))
+ elseif not channels[channel] then
+ local handle = openfile(filename,"wb") or false
+ if handle then
+ channels[channel] = handle
+ else
+ -- error
+ end
+ end
+end
+
+function backends.openout(n)
+ local p = nodeproperties[n]
+ if p then
+ local handle = openfile(p.filename,"wb") or false
+ if handle then
+ channels[p.channel] = handle
+ else
+ -- error
+ end
+ end
+end
+
+local function write(immediate)
+ local channel = scaninteger()
+ if not immediate then
+ local t = scantokenlist()
+ local n = copynode(writenode)
+ nodeproperties[n] = { channel = channel, data = t } -- action = "write"
+ return context(tonode(n))
+ else
+ local content = scanstring()
+ local handle = channels[channel]
+ if handle then
+ handle:write(content,"\n")
+ else
+ logwriter(content,"\n")
+ end
+ end
+end
+
+function backends.writeout(n)
+ local p = nodeproperties[n]
+ if p then
+ local handle = channels[p.channel]
+ local content = tokentostring(p.data)
+ if handle then
+ handle:write(content,"\n")
+ else
+ logwriter(content,"\n")
+ end
+ end
+end
+
+local function closeout(immediate)
+ local channel = scaninteger()
+ if not immediate then
+ local n = copynode(closenode)
+ nodeproperties[n] = { channel = channel } -- action = "close"
+ return context(tonode(n))
+ else
+ local handle = channels[channel]
+ if handle then
+ handle:close()
+ channels[channel] = false
+ else
+ -- error
+ end
+ end
+end
+
+function backends.closeout(n)
+ local p = nodeproperties[n]
+ if p then
+ local channel = p.channel
+ local handle = channels[channel]
+ if handle then
+ handle:close()
+ channels[channel] = false
+ else
+ -- error
+ end
+ end
+end
+
+local function immediate()
+ local command = scancode()
+ if command == write_command then
+ write(true)
+ elseif command == open_command then
+ openout(true)
+ elseif command == close_command then
+ closeout(true)
+ end
+end
+
+local noflatelua = 0
+
+local function latelua()
+ local node = copynode(lateluanode)
+ local name = "latelua"
+ if scankeyword("name") then
+ name = scanstring()
+ end
+ local data = scantokenlist()
+ nodeproperties[node] = { name = name, data = data }
+ return context(tonode(node))
+end
+
+function backends.latelua(current,pos_h,pos_v,cur_h,cur_v)
+ local p = nodeproperties[current]
+ if p then
+ data = p.data
+ else
+ data = getdata(current)
+ end
+ noflatelua = noflatelua + 1
+ local kind = type(data)
+ if kind == "table" then
+ data.action(data.specification or data)
+ elseif kind == "function" then
+ data()
+ else
+ if kind ~= "string" then
+ data = tokentostring(data)
+ end
+ if #data ~= "" then
+ local code = loadstring(data)
+ if code then
+ code()
+ end
+ end
+ end
+end
+
+function backends.noflatelua()
+ return noflatelua
+end
+
+function nodepool.originliteral(str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = originliteral_code } return t end
+function nodepool.pageliteral (str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = pageliteral_code } return t end
+function nodepool.directliteral(str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = directliteral_code } return t end
+function nodepool.rawliteral (str) local t = copynode(literalnode) nodeproperties[t] = { data = str, mode = rawliteral_code } return t end
+
+local pdfliterals = {
+ [originliteral_code] = originliteral_code, [literalvalues[originliteral_code]] = originliteral_code,
+ [pageliteral_code] = pageliteral_code, [literalvalues[pageliteral_code]] = pageliteral_code,
+ [directliteral_code] = directliteral_code, [literalvalues[directliteral_code]] = directliteral_code,
+ [rawliteral_code] = rawliteral_code, [literalvalues[rawliteral_code]] = rawliteral_code,
+}
+
+function nodepool.literal(mode,str)
+ local t = copynode(literalnode)
+ if str then
+ nodeproperties[t] = { data = str, mode = pdfliterals[mode] or pageliteral_code }
+ else
+ nodeproperties[t] = { data = mode, mode = pageliteral_code }
+ end
+ return t
+end
+
+function nodepool.save()
+ return copynode(savenode)
+end
+
+function nodepool.restore()
+ return copynode(restorenode)
+end
+
+function nodepool.setmatrix(rx,sx,sy,ry,tx,ty)
+ local t = copynode(setmatrixnode)
+ nodeproperties[t] = { matrix = tomatrix(rx,sx,sy,ry,tx,ty) }
+ return t
+end
+
+interfaces.implement { name = "immediate", actions = immediate, public = true, protected = true }
+interfaces.implement { name = "openout", actions = openout, public = true, protected = true }
+interfaces.implement { name = "write", actions = write, public = true, protected = true }
+interfaces.implement { name = "closeout", actions = closeout, public = true, protected = true }
+interfaces.implement { name = "latelua", actions = latelua, public = true, protected = true }
+interfaces.implement { name = "special", actions = scanstring, public = true, protected = true }
+
+open_command = get(token.create("openout"))
+write_command = get(token.create("write"))
+close_command = get(token.create("closeout"))