summaryrefslogtreecommitdiff
path: root/tex
diff options
context:
space:
mode:
authorHans Hagen <pragma@wxs.nl>2010-12-02 12:05:00 +0100
committerHans Hagen <pragma@wxs.nl>2010-12-02 12:05:00 +0100
commitf0515ed4b1a731629538988c70d8309f44391bf2 (patch)
tree807746fe9712e126dd7fc32f8c1864b420399a63 /tex
parent85d005e999920a82d104e89012385adb864d7a10 (diff)
downloadcontext-f0515ed4b1a731629538988c70d8309f44391bf2.tar.gz
beta 2010.12.02 12:05
Diffstat (limited to 'tex')
-rw-r--r--tex/context/base/luat-mac.lua14
-rw-r--r--tex/context/base/tabl-ntb.mkiv19
-rw-r--r--tex/context/base/tabl-tab.mkiv2
-rw-r--r--tex/generic/context/luatex-fonts.tex3
-rw-r--r--tex/generic/context/luatex-mplib.lua491
-rw-r--r--tex/generic/context/luatex-mplib.tex3
-rw-r--r--tex/generic/context/luatex-preprocessor-test.tex30
-rw-r--r--tex/generic/context/luatex-preprocessor.lua163
-rw-r--r--tex/generic/context/luatex-preprocessor.tex14
9 files changed, 238 insertions, 501 deletions
diff --git a/tex/context/base/luat-mac.lua b/tex/context/base/luat-mac.lua
index 4a9e53b0e..8010f34a5 100644
--- a/tex/context/base/luat-mac.lua
+++ b/tex/context/base/luat-mac.lua
@@ -10,7 +10,7 @@ local P, V, S, R, C, Cs, Cmt = lpeg.P, lpeg.V, lpeg.S, lpeg.R, lpeg.C, lpeg.Cs,
local lpegmatch, patterns = lpeg.match, lpeg.patterns
local insert, remove = table.insert, table.remove
-local rep = string.rep
+local rep, sub = string.rep, string.sub
local setmetatable = setmetatable
local report_macros = logs.new("macros")
@@ -55,7 +55,7 @@ local function pop()
top = remove(stack)
end
-local leftbrace = P("{")
+local leftbrace = P("{") -- will be in patterns
local rightbrace = P("}")
local escape = P("\\")
@@ -64,8 +64,12 @@ local spaces = space^1
local newline = patterns.newline
local nobrace = 1 - leftbrace - rightbrace
+local longleft = leftbrace -- P("(")
+local longright = rightbrace -- P(")")
+local nolong = 1 - longleft - longright
+
local name = R("AZ","az")^1 -- @?! -- utf?
-local longname = (leftbrace/"") * (nobrace^1) * (rightbrace/"")
+local longname = (longleft/"") * (nolong^1) * (longright/"")
local variable = P("#") * Cs(name + longname)
local escapedname = escape * name
local definer = escape * (P("def") + P("egdx") * P("def"))
@@ -80,7 +84,7 @@ local declaration = variable / set
local identifier = variable / get
local function matcherror(str,pos)
- report_macros("runaway definition at: %s",string.sub(str,pos-30,pos))
+ report_macros("runaway definition at: %s",sub(str,pos-30,pos))
end
local grammar = { "converter",
@@ -132,7 +136,7 @@ function macros.preprocessed(str)
return lpegmatch(parser,str)
end
-function macros.convertfile(oldname,newname)
+function macros.convertfile(oldname,newname) -- beware, no testing on oldname == newname
local data = resolvers.loadtexfile(oldname)
data = interfaces.preprocessed(data) or ""
io.savedata(newname,data)
diff --git a/tex/context/base/tabl-ntb.mkiv b/tex/context/base/tabl-ntb.mkiv
index d5eee61a0..34c4e8bb2 100644
--- a/tex/context/base/tabl-ntb.mkiv
+++ b/tex/context/base/tabl-ntb.mkiv
@@ -14,6 +14,7 @@
%D This is an unfinished, preliminary module. At least two
%D runs are needed to get the table fixed. Ugly code.
+% todo: TABLE TBL -> ntb
% todo: special parsetb for argless variant
% todo: protect \tbl...
% todo: tblnx also count
@@ -21,6 +22,24 @@
% todo: fast if
% todo: avoid halign (just do it manual) and thereby globals
+
+% \unexpanded\def\startrow {\bTR}
+% \unexpanded\def\stoprow {\eTR}
+% \unexpanded\def\startcell#1\stopcell{\bTD#1\eTD}
+% \let\stopcell \relax
+% \let\startcelltable \bTABLE
+% \let\stopcelltable \eTABLE
+
+% \starttext
+% \startcelltable[|c|c|]
+% \startrow \startcell a \stopcell \stoprow
+% \startrow \startcell a \stopcell \stoprow
+% \startrow \startcell a \stopcell \stoprow
+% \startrow \startcell a \stopcell \stoprow
+% \stopcelltable
+% \stoptext
+
+
% optie=rek beschrijven
\writestatus{loading}{ConTeXt Table Macros / Natural Tables}
diff --git a/tex/context/base/tabl-tab.mkiv b/tex/context/base/tabl-tab.mkiv
index b5f79ff4b..fd05aae55 100644
--- a/tex/context/base/tabl-tab.mkiv
+++ b/tex/context/base/tabl-tab.mkiv
@@ -2269,7 +2269,7 @@
\to \localtabledefinitions
\def\dochecktabledivision
- {\ifcondition\istabledivision\else
+ {\ifconditional\istabledivision\else
\dochucktableautorow
\global\currenttablecolumn\zerocount
\global\settrue\istabledivision
diff --git a/tex/generic/context/luatex-fonts.tex b/tex/generic/context/luatex-fonts.tex
index 644d168f5..8ccc9f3d5 100644
--- a/tex/generic/context/luatex-fonts.tex
+++ b/tex/generic/context/luatex-fonts.tex
@@ -4,8 +4,7 @@
%D title=\LUATEX\ Support Macros,
%D subtitle=Generic \OPENTYPE\ Font Handler,
%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright=public domain]
+%D copyright=see context related readme files]
%D \subject{Welcome}
%D
diff --git a/tex/generic/context/luatex-mplib.lua b/tex/generic/context/luatex-mplib.lua
deleted file mode 100644
index c6628acb3..000000000
--- a/tex/generic/context/luatex-mplib.lua
+++ /dev/null
@@ -1,491 +0,0 @@
-if not modules then modules = { } end modules ['luatex-mplib'] = {
- version = 1.001,
- comment = "companion to luatex-mplib.tex",
- author = "Hans Hagen & Taco Hoekwater",
- copyright = "ConTeXt Development Team",
- license = "public domain",
-}
-
---[[ldx--
-<p>This module is a stripped down version of libraries that are used
-by <l n='context'/>. It can be used in other macro packages and/or
-serve as an example. Embedding in a macro package is upto others and
-normally boils down to inputting <t>supp-mpl.tex</t>.</p>
---ldx]]--
-
-if metapost and metapost.version then
-
- --[[ldx--
- <p>Let's silently quit and make sure that no one loads it
- manually in <l n='context'/>.</p>
- --ldx]]--
-
-else
-
- local format, concat, abs, match = string.format, table.concat, math.abs, string.match
-
- local mplib = require ('mplib')
- local kpse = require ('kpse')
-
- --[[ldx--
- <p>We create a namespace and some variables to it. If a namespace is
- already defined it wil not be initialized. This permits hooking
- in code beforehand.</p>
-
- <p>We don't make a format automatically. After all, distributions
- might have their own preferences and normally a format (mem) file will
- have some special place in the <l n='tex'/> tree. Also, there can already
- be format files, different memort settings and other nasty pitfalls that
- we don't want to interfere with. If you want, you can define a function
- <t>metapost.make(name,mem_name) that does the job.</t></p>
- --ldx]]--
-
- metapost = metapost or { }
- metapost.version = 1.00
- metapost.showlog = metapost.showlog or false
- metapost.lastlog = ""
-
- --[[ldx--
- <p>A few helpers, taken from <t>l-file.lua</t>.</p>
- --ldx]]--
-
- local file = file or { }
-
- function file.replacesuffix(filename, suffix)
- return (string.gsub(filename,"%.[%a%d]+$","")) .. "." .. suffix
- end
-
- function file.stripsuffix(filename)
- return (string.gsub(filename,"%.[%a%d]+$",""))
- end
-
- --[[ldx--
- <p>We use the <l n='kpse'/> library unless a finder is already
- defined.</p>
- --ldx]]--
-
- local mpkpse = kpse.new("luatex","mpost")
-
- metapost.finder = metapost.finder or function(name, mode, ftype)
- if mode == "w" then
- return name
- else
- return mpkpse:find_file(name,ftype)
- end
- end
-
- --[[ldx--
- <p>You can use your own reported if needed, as long as it handles multiple
- arguments and formatted strings.</p>
- --ldx]]--
-
- metapost.report = metapost.report or function(...)
- texio.write(format("<mplib: %s>",format(...)))
- end
-
- --[[ldx--
- <p>The rest of this module is not documented. More info can be found in the
- <l n='luatex'/> manual, articles in user group journals and the files that
- ship with <l n='context'/>.</p>
- --ldx]]--
-
- function metapost.resetlastlog()
- metapost.lastlog = ""
- end
-
- local mplibone = tonumber(mplib.version()) <= 1.50
-
- if mplibone then
-
- metapost.make = metapost.make or function(name,mem_name,dump)
- local t = os.clock()
- local mpx = mplib.new {
- ini_version = true,
- find_file = metapost.finder,
- job_name = file.stripsuffix(name)
- }
- mpx:execute(string.format("input %s ;",name))
- if dump then
- mpx:execute("dump ;")
- metapost.report("format %s made and dumped for %s in %0.3f seconds",mem_name,name,os.clock()-t)
- else
- metapost.report("%s read in %0.3f seconds",name,os.clock()-t)
- end
- return mpx
- end
-
- function metapost.load(name)
- local mem_name = file.replacesuffix(name,"mem")
- local mpx = mplib.new {
- ini_version = false,
- mem_name = mem_name,
- find_file = metapost.finder
- }
- if not mpx and type(metapost.make) == "function" then
- -- when i have time i'll locate the format and dump
- mpx = metapost.make(name,mem_name)
- end
- if mpx then
- metapost.report("using format %s",mem_name,false)
- return mpx, nil
- else
- return nil, { status = 99, error = "out of memory or invalid format" }
- end
- end
-
- else
-
- local preamble = [[
- boolean mplib ; mplib := true ;
- let dump = endinput ;
- input %s ;
- ]]
-
- metapost.make = metapost.make or function()
- end
-
- function metapost.load(name)
- local mpx = mplib.new {
- ini_version = true,
- find_file = metapost.finder,
- }
- local result
- if not mpx then
- result = { status = 99, error = "out of memory"}
- else
- result = mpx:execute(format(preamble, file.replacesuffix(name,"mp")))
- end
- metapost.reporterror(result)
- return mpx, result
- end
-
- end
-
- function metapost.unload(mpx)
- if mpx then
- mpx:finish()
- end
- end
-
- 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 then
- metapost.report("mp terminal: %s",t)
- end
- if e then
- metapost.report("mp error: %s", 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.process(mpx, data)
- local converted, result = false, {}
- mpx = metapost.load(mpx)
- if mpx and data then
- local result = mpx:execute(data)
- if not result then
- metapost.report("mp error: no result object returned")
- elseif result.status > 0 then
- metapost.report("mp error: %s",(result.term or "no-term") .. "\n" .. (result.error or "no-error"))
- elseif metapost.showlog then
- metapost.lastlog = metapost.lastlog .. "\n" .. result.term
- metapost.report("mp info: %s",result.term or "no-term")
- elseif result.fig then
- converted = metapost.convert(result)
- else
- metapost.report("mp error: unknown error, maybe no beginfig/endfig")
- end
- else
- metapost.report("mp error: mem file not found")
- end
- return converted, result
- end
-
- local function getobjects(result,figure,f)
- return figure:objects()
- end
-
- function metapost.convert(result, flusher)
- metapost.flush(result, flusher)
- return true -- done
- end
-
- --[[ldx--
- <p>We removed some message and tracing code. We might even remove the flusher</p>
- --ldx]]--
-
- local function pdf_startfigure(n,llx,lly,urx,ury)
- tex.sprint(format("\\startMPLIBtoPDF{%s}{%s}{%s}{%s}",llx,lly,urx,ury))
- end
-
- local function pdf_stopfigure()
- tex.sprint("\\stopMPLIBtoPDF")
- end
-
- function pdf_literalcode(fmt,...) -- table
- tex.sprint(format("\\MPLIBtoPDF{%s}",format(fmt,...)))
- end
-
- function pdf_textfigure(font,size,text,width,height,depth)
- text = text:gsub(".","\\hbox{%1}") -- kerning happens in metapost
- tex.sprint(format("\\MPLIBtextext{%s}{%s}{%s}{%s}{%s}",font,size,text,0,-( 7200/ 7227)/65536*depth))
- end
-
- local bend_tolerance = 131/65536
-
- local rx, sx, sy, ry, tx, ty, divider = 1, 0, 0, 1, 0, 0, 1
-
- local function pen_characteristics(object)
- local t = mplib.pen_info(object)
- rx, ry, sx, sy, tx, ty = t.rx, t.ry, t.sx, t.sy, t.tx, t.ty
- divider = sx*sy - rx*ry
- return not (sx==1 and rx==0 and ry==0 and sy==1 and tx==0 and ty==0), t.width
- end
-
- local function concat(px, py) -- no tx, ty here
- return (sy*px-ry*py)/divider,(sx*py-rx*px)/divider
- end
-
- local function curved(ith,pth)
- local d = pth.left_x - ith.right_x
- if abs(ith.right_x - ith.x_coord - d) <= bend_tolerance and abs(pth.x_coord - pth.left_x - d) <= bend_tolerance then
- d = pth.left_y - ith.right_y
- if abs(ith.right_y - ith.y_coord - d) <= bend_tolerance and abs(pth.y_coord - pth.left_y - d) <= bend_tolerance then
- return false
- end
- end
- return true
- end
-
- local function flushnormalpath(path,open)
- local pth, ith
- for i=1,#path do
- pth = path[i]
- if not ith then
- pdf_literalcode("%f %f m",pth.x_coord,pth.y_coord)
- elseif curved(ith,pth) then
- pdf_literalcode("%f %f %f %f %f %f c",ith.right_x,ith.right_y,pth.left_x,pth.left_y,pth.x_coord,pth.y_coord)
- else
- pdf_literalcode("%f %f l",pth.x_coord,pth.y_coord)
- end
- ith = pth
- end
- if not open then
- local one = path[1]
- if curved(pth,one) then
- pdf_literalcode("%f %f %f %f %f %f c",pth.right_x,pth.right_y,one.left_x,one.left_y,one.x_coord,one.y_coord )
- else
- pdf_literalcode("%f %f l",one.x_coord,one.y_coord)
- end
- elseif #path == 1 then
- -- special case .. draw point
- local one = path[1]
- pdf_literalcode("%f %f l",one.x_coord,one.y_coord)
- end
- return t
- end
-
- local function flushconcatpath(path,open)
- pdf_literalcode("%f %f %f %f %f %f cm", sx, rx, ry, sy, tx ,ty)
- local pth, ith
- for i=1,#path do
- pth = path[i]
- if not ith then
- pdf_literalcode("%f %f m",concat(pth.x_coord,pth.y_coord))
- elseif curved(ith,pth) then
- local a, b = concat(ith.right_x,ith.right_y)
- local c, d = concat(pth.left_x,pth.left_y)
- pdf_literalcode("%f %f %f %f %f %f c",a,b,c,d,concat(pth.x_coord, pth.y_coord))
- else
- pdf_literalcode("%f %f l",concat(pth.x_coord, pth.y_coord))
- end
- ith = pth
- end
- if not open then
- local one = path[1]
- if curved(pth,one) then
- local a, b = concat(pth.right_x,pth.right_y)
- local c, d = concat(one.left_x,one.left_y)
- pdf_literalcode("%f %f %f %f %f %f c",a,b,c,d,concat(one.x_coord, one.y_coord))
- else
- pdf_literalcode("%f %f l",concat(one.x_coord,one.y_coord))
- end
- elseif #path == 1 then
- -- special case .. draw point
- local one = path[1]
- pdf_literalcode("%f %f l",concat(one.x_coord,one.y_coord))
- end
- return t
- end
-
- --[[ldx--
- <p>Support for specials has been removed.</p>
- --ldx]]--
-
- function metapost.flush(result,flusher)
- if result then
- local figures = result.fig
- if figures then
- for f=1, #figures do
- metapost.report("flushing figure %s",f)
- local figure = figures[f]
- local objects = getobjects(result,figure,f)
- local fignum = tonumber(match(figure:filename(),"([%d]+)$") or figure:charcode() or 0)
- local miterlimit, linecap, linejoin, dashed = -1, -1, -1, false
- local bbox = figure:boundingbox()
- local llx, lly, urx, ury = bbox[1], bbox[2], bbox[3], bbox[4] -- faster than unpack
- if urx < llx then
- -- invalid
- pdf_startfigure(fignum,0,0,0,0)
- pdf_stopfigure()
- else
- pdf_startfigure(fignum,llx,lly,urx,ury)
- pdf_literalcode("q")
- if objects then
- for o=1,#objects do
- local object = objects[o]
- local objecttype = object.type
- if objecttype == "start_bounds" or objecttype == "stop_bounds" then
- -- skip
- elseif objecttype == "start_clip" then
- pdf_literalcode("q")
- flushnormalpath(object.path,t,false)
- pdf_literalcode("W n")
- elseif objecttype == "stop_clip" then
- pdf_literalcode("Q")
- miterlimit, linecap, linejoin, dashed = -1, -1, -1, false
- elseif objecttype == "special" then
- -- not supported
- elseif objecttype == "text" then
- local ot = object.transform -- 3,4,5,6,1,2
- pdf_literalcode("q %f %f %f %f %f %f cm",ot[3],ot[4],ot[5],ot[6],ot[1],ot[2])
- pdf_textfigure(object.font,object.dsize,object.text,object.width,object.height,object.depth)
- pdf_literalcode("Q")
- else
- local cs = object.color
- if cs and #cs > 0 then
- pdf_literalcode(metapost.colorconverter(cs))
- end
- local ml = object.miterlimit
- if ml and ml ~= miterlimit then
- miterlimit = ml
- pdf_literalcode("%f M",ml)
- end
- local lj = object.linejoin
- if lj and lj ~= linejoin then
- linejoin = lj
- pdf_literalcode("%i j",lj)
- end
- local lc = object.linecap
- if lc and lc ~= linecap then
- linecap = lc
- pdf_literalcode("%i J",lc)
- end
- local dl = object.dash
- if dl then
- local d = format("[%s] %i d",concat(dl.dashes or {}," "),dl.offset)
- if d ~= dashed then
- dashed = d
- pdf_literalcode(dashed)
- end
- elseif dashed then
- pdf_literalcode("[] 0 d")
- dashed = false
- end
- local path = object.path
- local transformed, penwidth = false, 1
- local open = path and path[1].left_type and path[#path].right_type
- local pen = object.pen
- if pen then
- if pen.type == 'elliptical' then
- transformed, penwidth = pen_characteristics(object) -- boolean, value
- pdf_literalcode("%f w",penwidth)
- if objecttype == 'fill' then
- objecttype = 'both'
- end
- else -- calculated by mplib itself
- objecttype = 'fill'
- end
- end
- if transformed then
- pdf_literalcode("q")
- end
- if path then
- if transformed then
- flushconcatpath(path,open)
- else
- flushnormalpath(path,open)
- end
- if objecttype == "fill" then
- pdf_literalcode("h f")
- elseif objecttype == "outline" then
- pdf_literalcode((open and "S") or "h S")
- elseif objecttype == "both" then
- pdf_literalcode("h B")
- end
- end
- if transformed then
- pdf_literalcode("Q")
- end
- local path = object.htap
- if path then
- if transformed then
- pdf_literalcode("q")
- end
- if transformed then
- flushconcatpath(path,open)
- else
- flushnormalpath(path,open)
- end
- if objecttype == "fill" then
- pdf_literalcode("h f")
- elseif objecttype == "outline" then
- pdf_literalcode((open and "S") or "h S")
- elseif objecttype == "both" then
- pdf_literalcode("h B")
- end
- if transformed then
- pdf_literalcode("Q")
- end
- end
- if cr then
- pdf_literalcode(cr)
- end
- end
- end
- end
- pdf_literalcode("Q")
- pdf_stopfigure()
- end
- end
- end
- end
- end
-
- function metapost.colorconverter(cr)
- local n = #cr
- if n == 4 then
- local c, m, y, k = cr[1], cr[2], cr[3], cr[4]
- return format("%.3f %.3f %.3f %.3f k %.3f %.3f %.3f %.3f K",c,m,y,k,c,m,y,k), "0 g 0 G"
- elseif n == 3 then
- local r, g, b = cr[1], cr[2], cr[3]
- return format("%.3f %.3f %.3f rg %.3f %.3f %.3f RG",r,g,b,r,g,b), "0 g 0 G"
- else
- local s = cr[1]
- return format("%.3f g %.3f G",s,s), "0 g 0 G"
- end
- end
-
-end
diff --git a/tex/generic/context/luatex-mplib.tex b/tex/generic/context/luatex-mplib.tex
index 206518d7d..691958646 100644
--- a/tex/generic/context/luatex-mplib.tex
+++ b/tex/generic/context/luatex-mplib.tex
@@ -4,8 +4,7 @@
%D title=\LUATEX\ Support Macros,
%D subtitle=\METAPOST\ to \PDF\ conversion,
%D author=Taco Hoekwater \& Hans Hagen,
-%D date=\currentdate,
-%D copyright=public domain]
+%D copyright=see context related readme files]
%D This is the companion to the \LUA\ module \type {supp-mpl.lua}. Further
%D embedding is up to others. A simple example of usage in plain \TEX\ is:
diff --git a/tex/generic/context/luatex-preprocessor-test.tex b/tex/generic/context/luatex-preprocessor-test.tex
new file mode 100644
index 000000000..857b28f83
--- /dev/null
+++ b/tex/generic/context/luatex-preprocessor-test.tex
@@ -0,0 +1,30 @@
+\ifdefined\inputpreprocessed
+
+ \def\TestOne[#1]%
+ {test one: [#1]\par}
+
+ \def\TestTwo#some%
+ {test two: #some\par}
+
+ \def\TestThree[#whatever][#more]%
+ {test three: [#more] and [#whatever]\par}
+
+ \def\TestFour[#one]#two%
+ {\def\TestFive[#alpha][#one]%
+ {test four and five: [#one], [#two] and [#alpha]}\par}
+
+ \def\TestSix[#{one}]#{two}%
+ {test six: [#{one}] and #{two}\par}
+
+ \TestOne [one]
+ \TestTwo {one}
+ \TestThree[one][two]
+ \TestFour [one]{two}
+ \TestFive [one][two]
+ \TestSix [one]{two}
+
+\else
+ \input{luatex-preprocessor.tex}
+ \inputpreprocessed{luatex-preprocessor-test.tex}
+ \expandafter \end
+\fi
diff --git a/tex/generic/context/luatex-preprocessor.lua b/tex/generic/context/luatex-preprocessor.lua
new file mode 100644
index 000000000..8faa0b47e
--- /dev/null
+++ b/tex/generic/context/luatex-preprocessor.lua
@@ -0,0 +1,163 @@
+if not modules then modules = { } end modules ['luatex-preprocessor'] = {
+ version = 1.001,
+ comment = "companion to luatex-preprocessor.tex",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx
+<p>This is a stripped down version of the preprocessor. In
+<l n='context'/> we have a bit more, use a different logger, and
+use a few optimizations. A few examples are shown at the end.</p>
+--ldx]]
+
+local rep, sub, gmatch = string.rep, string.sub, string.gmatch
+local insert, remove = table.insert, table.remove
+local setmetatable = setmetatable
+
+local stack, top, n, hashes = { }, nil, 0, { }
+
+local function set(s)
+ if top then
+ n = n + 1
+ if n > 9 then
+ texio.write_nl("number of arguments > 9, ignoring: " .. s)
+ else
+ local ns = #stack
+ local h = hashes[ns]
+ if not h then
+ h = rep("#",ns)
+ hashes[ns] = h
+ end
+ m = h .. n
+ top[s] = m
+ return m
+ end
+ end
+end
+
+local function get(s)
+ local m = top and top[s] or s
+ return m
+end
+
+local function push()
+ top = { }
+ n = 0
+ local s = stack[#stack]
+ if s then
+ setmetatable(top,{ __index = s })
+ end
+ insert(stack,top)
+end
+
+local function pop()
+ top = remove(stack)
+end
+
+local leftbrace = lpeg.P("{")
+local rightbrace = lpeg.P("}")
+local escape = lpeg.P("\\")
+
+local space = lpeg.P(" ")
+local spaces = space^1
+local newline = lpeg.S("\r\n")
+local nobrace = 1 - leftbrace - rightbrace
+
+local name = lpeg.R("AZ","az")^1
+local longname = (leftbrace/"") * (nobrace^1) * (rightbrace/"")
+local variable = lpeg.P("#") * lpeg.Cs(name + longname)
+local escapedname = escape * name
+local definer = escape * (lpeg.P("def") + lpeg.P("egdx") * lpeg.P("def"))
+local anything = lpeg.P(1)
+local always = lpeg.P(true)
+
+local pushlocal = always / push
+local poplocal = always / pop
+local declaration = variable / set
+local identifier = variable / get
+
+local function matcherror(str,pos)
+ texio.write_nl("runaway definition at: " .. sub(str,pos-30,pos))
+end
+
+local parser = lpeg.Cs { "converter",
+ definition = pushlocal
+ * definer
+ * escapedname
+ * (declaration + (1-leftbrace))^0
+ * lpeg.V("braced")
+ * poplocal,
+ braced = leftbrace
+ * ( lpeg.V("definition")
+ + identifier
+ + lpeg.V("braced")
+ + nobrace
+ )^0
+ * (rightbrace + lpeg.Cmt(always,matcherror)),
+ converter = (lpeg.V("definition") + anything)^1,
+}
+
+--[[ldx
+<p>We provide a few commands.</p>
+--ldx]]
+
+-- local texkpse
+
+local function find_file(...)
+ -- texkpse = texkpse or kpse.new("luatex","tex")
+ -- return texkpse:find_file(...) or ""
+ return kpse.find_file(...) or ""
+end
+
+commands = commands or { }
+
+function commands.preprocessed(str)
+ return lpeg.match(parser,str)
+end
+
+function commands.inputpreprocessed(name)
+ local name = find_file(name) or ""
+ if name ~= "" then
+ -- we could use io.loaddata as it's loaded in luatex-plain
+ local f = io.open(name,'rb')
+ if f then
+ texio.write("("..name)
+ local d = commands.preprocessed(f:read("*a"))
+ if d and d ~= "" then
+ texio.write("processed: " .. name)
+ for s in gmatch(d,"[^\n\r]+") do
+ tex.print(s) -- we do a dumb feedback
+ end
+ end
+ f:close()
+ texio.write(")")
+ else
+ tex.error("preprocessor error, invalid file: " .. name)
+ end
+ else
+ tex.error("preprocessor error, unknown file: " .. name)
+ end
+end
+
+function commands.preprocessfile(oldfile,newfile) -- no checking
+ if oldfile and oldfile ~= newfile then
+ local f = io.open(oldfile,'rb')
+ if f then
+ local g = io.open(newfile,'wb')
+ if g then
+ g:write(lpeg.match(parser,f:read("*a") or ""))
+ g:close()
+ end
+ f:close()
+ end
+ end
+end
+
+--~ print(preprocessed([[\def\test#oeps{test:#oeps}]]))
+--~ print(preprocessed([[\def\test#oeps{test:#{oeps}}]]))
+--~ print(preprocessed([[\def\test#{oeps:1}{test:#{oeps:1}}]]))
+--~ print(preprocessed([[\def\test#{oeps}{test:#oeps}]]))
+--~ preprocessed([[\def\test#{oeps}{test:#oeps \halign{##\cr #oeps\cr}]])
+--~ print(preprocessed([[\def\test#{oeps}{test:#oeps \halign{##\cr #oeps\cr}}]]))
diff --git a/tex/generic/context/luatex-preprocessor.tex b/tex/generic/context/luatex-preprocessor.tex
new file mode 100644
index 000000000..fe4872d61
--- /dev/null
+++ b/tex/generic/context/luatex-preprocessor.tex
@@ -0,0 +1,14 @@
+%D \module
+%D [ file=luatex-preprocessor,
+%D version=2010.12.02,
+%D title=\LUATEX\ Support Macros,
+%D subtitle=Generic Preprocessor,
+%D author=Hans Hagen,
+%D copyright=public domain]
+
+\directlua{dofile(kpse.find_file('luatex-preprocessor.lua'))}
+
+\def\inputpreprocessed#1%
+ {\directlua{commands.inputpreprocessed("#1")}}
+
+\endinput