diff options
-rw-r--r-- | scripts/mkimport | 135 | ||||
-rw-r--r-- | src/fontloader/misc/fontloader-l-lpeg.lua | 40 | ||||
-rw-r--r-- | src/fontloader/misc/fontloader-util-str.lua | 28 | ||||
-rw-r--r-- | src/fontloader/runtime/fontloader-fontloader.lua | 50 |
4 files changed, 211 insertions, 42 deletions
diff --git a/scripts/mkimport b/scripts/mkimport index 2f64d62..a430587 100644 --- a/scripts/mkimport +++ b/scripts/mkimport @@ -20,6 +20,8 @@ --- ------------------------------------------------------------------------------- +local debug = false + kpse.set_program_name "luatex" local lfs = require "lfs" @@ -27,10 +29,17 @@ local md5 = require "md5" require "lualibs" -local ioloaddata = io.loaddata -local iowrite = io.write -local md5sumhexa = md5.sumhexa -local stringformat = string.format +local fileiswritable = file.is_writable +local ioloaddata = io.loaddata +local iopopen = io.popen +local iowrite = io.write +local lfschdir = lfs.chdir +local lfsisdir = lfs.isdir +local lfsisfile = lfs.isfile +local md5sumhexa = md5.sumhexa +local osgettimeofday = os.gettimeofday +local stringformat = string.format +local tableconcat = table.concat ------------------------------------------------------------------------------- -- config @@ -212,7 +221,7 @@ local imports = { } --[[ [imports] ]] local hash_file = function (fname) - if not lfs.isfile (fname) then + if not lfsisfile (fname) then die ("cannot find %s.", fname) end local raw = ioloaddata (fname) @@ -225,7 +234,7 @@ end local derive_category_path = function (cat) local subpath = origin_paths[cat] or die ("category " .. cat .. " unknown") local location = file.join (context_root, subpath) - if not lfs.isdir (location) then + if not lfsisdir (location) then die ("invalid base path defined for category " .. cat .. " at " .. location) end @@ -331,7 +340,7 @@ local news = function () status.missing[#status.missing + 1] = ourname else --- Source file exists and is readable. - if not lfs.isdir (fontloader_subdir) then + if not lfsisdir (fontloader_subdir) then die ("path for fontloader tree (" .. fontloader_subdir .. ") is not a directory") end @@ -428,12 +437,12 @@ local import_file = function (name, kind, def, cat) local ourpath = file.join (fontloader_subdir, subdir) local src = file.join (srcdir, fullname) local dst = file.join (ourpath, ourname) - local new = not lfs.isfile (dst) + local new = not lfsisfile (dst) if not new and hash_file (src) == hash_file (dst) then status ("file %s is unchanged, skipping", fullname) return import_skipped end - if not (lfs.isdir (ourpath) or not lfs.mkdirs (ourpath)) then + if not (lfsisdir (ourpath) or not lfs.mkdirs (ourpath)) then die ("failed to create directory %s for file %s", ourpath, ourname) end @@ -475,7 +484,7 @@ end --[[ [local import = function (arg)] ]] local find_in_path = function (root, subdir, target) local file = file.join (root, subdir, target) - if lfs.isfile (file) then + if lfsisfile (file) then return file end end @@ -554,7 +563,7 @@ end local search = function (target) local look_for --- pick a file - if lfs.isfile (target) then --- absolute path given + if lfsisfile (target) then --- absolute path given look_for = target goto found else @@ -632,6 +641,100 @@ local tell = function (arg) return describe (target, location) end +--[[doc-- + + Packaging works as follows: + + * Files are looked up the usual way, allowing us to override the + distribution-supplied scripts with our own alternatives in the + local path. + + * The merged package is written to the same directory as the + packaging script (not ``$PWD``). + + There is some room for improvements: Instead of reading a file with + fixed content from disk, the merge script could be composed + on-the-fly from a list of files and then written to memory (not sure + though if we can access shm_open or memfd and the likes from Lua). + +--doc]]-- + +local package = function (args) + local t0 = osgettimeofday () + local orig_dir = lfs.currentdir () + local base_dir = orig_dir .. "/src/fontloader/" + local merge_name = base_dir .. "luaotfload-package.lua" + --- output name is fixed so we have to deal with it but maybe we can + --- get a patch to mtx-package upstreamed in the future + local output_name = base_dir .. "luaotfload-package-merged.lua" + local target_name = stringformat ("fontloader-%s.lua", + os.date ("%F")) + status ("assuming fontloader source in %s", base_dir) + status ("reading merge instructions from %s", merge_name) + status ("writing output to %s", target_name) + + --- check preconditions + + if not lfsisdir (base_dir) then die ("directory %s does not exist", emphasis (base_dir )) end + if not lfsisfile (merge_name) then die ("missing merge file at %s", emphasis (merge_name )) end + if not fileiswritable (output_name) then die ("cannot write to %s", emphasis (output_name)) end + if not fileiswritable (target_name) then die ("cannot write to %s", emphasis (target_name)) end + if not lfschdir (base_dir) then die ("failed to cd into %s", emphasis (base_dir )) end + + if lfsisfile (output_name) then + status ("output file already exists at “%s”, unlinking", output_name) + local ret, err = os.remove (output_name) + if ret == nil then + if not lfschdir (orig_dir) then + status ("warning: failed to cd retour into %s", emphasis (orig_dir)) + end + die ("failed to remove existing merge package") + end + end + --die ("missing merge file at %s", emphasis (merge_name )) end + + --- perform merge + + local cmd = { "mtxrun", "--script", "package", "--merge", merge_name } + local shl = tableconcat (cmd, " ") + + status ("invoking %s as “%s”", emphasis "mtx-package", shl) + + local fh = iopopen (shl, "r") + + if not fh then + if not lfschdir (orig_dir) then + status ("warning: failed to cd retour into %s", emphasis (orig_dir)) + end + die ("merge failed; failed to invoke mtxrun") + end + + local junk = fh.read (fh, "*all") + if not junk then + status ("warning: received no output from mtxrun; this is strange") + end + + fh.close (fh) + + if debug then print (junk) end + + --- clean up + + if not lfschdir (orig_dir) then + status ("warning: failed to cd retour into %s", emphasis (orig_dir)) + end + + --- check postconditions + + if not lfsisfile (output_name) then die ("merge failed; package not found at " .. output_name) end + + --- at this point we know that mtxrun was invoked correctly and the + --- result file has been created + + status ("merge complete; operation finished in %.0f ms", + (osgettimeofday() - t0) * 1000) +end + local help = function () iowrite "usage: mkimport <command> [<args>]\n" iowrite "\n" @@ -640,14 +743,16 @@ local help = function () iowrite " tell Display information about a file’s integration\n" iowrite " news Check Context for updated files\n" iowrite " import Update with files from Context\n" + iowrite " package Invoke mtx-package on the current fontloader\n" iowrite "\n" end local job_kind = table.mirrored { - news = news, - import = import, - tell = tell, - help = help, + help = help, + import = import, + news = news, + package = package, + tell = tell, } ------------------------------------------------------------------------------- diff --git a/src/fontloader/misc/fontloader-l-lpeg.lua b/src/fontloader/misc/fontloader-l-lpeg.lua index 4aadadb..55a0d89 100644 --- a/src/fontloader/misc/fontloader-l-lpeg.lua +++ b/src/fontloader/misc/fontloader-l-lpeg.lua @@ -10,6 +10,8 @@ if not modules then modules = { } end modules ['l-lpeg'] = { -- if i can use new features like capture / 2 and .B (at first sight the xml -- parser is some 5% slower) +-- lpeg.P("abc") is faster than lpeg.P("a") * lpeg.P("b") * lpeg.P("c") + -- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1) -- move utf -> l-unicode @@ -19,7 +21,7 @@ lpeg = require("lpeg") -- The latest lpeg doesn't have print any more, and even the new ones are not -- available by default (only when debug mode is enabled), which is a pitty as --- as it helps nailign down bottlenecks. Performance seems comparable: some 10% +-- as it helps nailing down bottlenecks. Performance seems comparable: some 10% -- slower pattern compilation, same parsing speed, although, -- -- local p = lpeg.C(lpeg.P(1)^0 * lpeg.P(-1)) @@ -841,7 +843,6 @@ local function make(t) local function making(t) local p = p_false local keys = sortedkeys(t) --- local okay = t[""] for i=1,#keys do local k = keys[i] if k ~= "" then @@ -850,8 +851,6 @@ local function make(t) p = p + P(k) * p_true elseif v == false then -- can't happen --- elseif okay then --- p = p + P(k) * (making(v) + p_true) else p = p + P(k) * making(v) end @@ -872,8 +871,6 @@ local function make(t) p = p + P(k) * p_true elseif v == false then -- can't happen --- elseif v[""] then --- p = p + P(k) * (making(v) + p_true) else p = p + P(k) * making(v) end @@ -882,6 +879,33 @@ local function make(t) return p end +local function collapse(t,x) + if type(t) ~= "table" then + return t, x + else + local n = next(t) + if n == nil then + return t, x + elseif next(t,n) == nil then + -- one entry + local k = n + local v = t[k] + if type(v) == "table" then + return collapse(v,x..k) + else + return v, x .. k + end + else + local tt = { } + for k, v in next, t do + local vv, kk = collapse(v,k) + tt[kk] = vv + end + return tt, x + end + end +end + function lpeg.utfchartabletopattern(list) -- goes to util-lpg local tree = { } local n = #list @@ -955,10 +979,14 @@ function lpeg.utfchartabletopattern(list) -- goes to util-lpg end end end +-- collapse(tree,"") -- needs testing, maybe optional, slightly faster because P("x")*P("X") seems slower than P"(xX") (why) -- inspect(tree) return make(tree) end +-- local t = { "start", "stoep", "staart", "paard" } +-- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/string.upper + 1)^1) + -- local t = { "a", "abc", "ac", "abe", "abxyz", "xy", "bef","aa" } -- local p = lpeg.Cs((lpeg.utfchartabletopattern(t)/string.upper + 1)^1) diff --git a/src/fontloader/misc/fontloader-util-str.lua b/src/fontloader/misc/fontloader-util-str.lua index a677a82..de4a87e 100644 --- a/src/fontloader/misc/fontloader-util-str.lua +++ b/src/fontloader/misc/fontloader-util-str.lua @@ -44,7 +44,12 @@ end if not number then number = { } end -- temp hack for luatex-fonts -local stripper = patterns.stripzeros +local stripper = patterns.stripzeros +local newline = patterns.newline +local endofstring = patterns.endofstring +local whitespace = patterns.whitespace +local spacer = patterns.spacer +local spaceortab = patterns.spaceortab local function points(n) n = tonumber(n) @@ -62,12 +67,12 @@ number.basepoints = basepoints -- str = " \n \ntest \n test\ntest " -- print("["..string.gsub(string.collapsecrlf(str),"\n","+").."]") -local rubish = patterns.spaceortab^0 * patterns.newline -local anyrubish = patterns.spaceortab + patterns.newline +local rubish = spaceortab^0 * newline +local anyrubish = spaceortab + newline local anything = patterns.anything -local stripped = (patterns.spaceortab^1 / "") * patterns.newline +local stripped = (spaceortab^1 / "") * newline local leading = rubish^0 / "" -local trailing = (anyrubish^1 * patterns.endofstring) / "" +local trailing = (anyrubish^1 * endofstring) / "" local redundant = rubish^3 / "\n" local pattern = Cs(leading * (trailing + redundant + stripped + anything)^0) @@ -129,7 +134,7 @@ local pattern = return "" end end - + patterns.newline * Cp() / function(position) + + newline * Cp() / function(position) extra, start = 0, position end + patterns.anything @@ -162,11 +167,6 @@ end -- return str -- end -local newline = patterns.newline -local endofstring = patterns.endofstring -local whitespace = patterns.whitespace -local spacer = patterns.spacer - local space = spacer^0 local nospace = space/"" local endofline = nospace * newline @@ -1117,3 +1117,9 @@ local pattern = function string.optionalquoted(str) return lpegmatch(pattern,str) or str end + +local pattern = Cs((newline / os.newline + 1)^0) + +function string.replacenewlines(str) + return lpegmatch(pattern,str) +end diff --git a/src/fontloader/runtime/fontloader-fontloader.lua b/src/fontloader/runtime/fontloader-fontloader.lua index 1d6509a..c46c168 100644 --- a/src/fontloader/runtime/fontloader-fontloader.lua +++ b/src/fontloader/runtime/fontloader-fontloader.lua @@ -1,6 +1,6 @@ -- merged file : luatex-fonts-merged.lua -- parent file : luatex-fonts.lua --- merge date : 04/18/15 14:41:50 +-- merge date : 05/04/15 19:00:43 do -- begin closure to overcome local limits and interference @@ -699,6 +699,31 @@ local function make(t) end return p end +local function collapse(t,x) + if type(t)~="table" then + return t,x + else + local n=next(t) + if n==nil then + return t,x + elseif next(t,n)==nil then + local k=n + local v=t[k] + if type(v)=="table" then + return collapse(v,x..k) + else + return v,x..k + end + else + local tt={} + for k,v in next,t do + local vv,kk=collapse(v,k) + tt[kk]=vv + end + return tt,x + end + end +end function lpeg.utfchartabletopattern(list) local tree={} local n=#list @@ -2773,6 +2798,11 @@ else end if not number then number={} end local stripper=patterns.stripzeros +local newline=patterns.newline +local endofstring=patterns.endofstring +local whitespace=patterns.whitespace +local spacer=patterns.spacer +local spaceortab=patterns.spaceortab local function points(n) n=tonumber(n) return (not n or n==0) and "0pt" or lpegmatch(stripper,format("%.5fpt",n/65536)) @@ -2783,12 +2813,12 @@ local function basepoints(n) end number.points=points number.basepoints=basepoints -local rubish=patterns.spaceortab^0*patterns.newline -local anyrubish=patterns.spaceortab+patterns.newline +local rubish=spaceortab^0*newline +local anyrubish=spaceortab+newline local anything=patterns.anything -local stripped=(patterns.spaceortab^1/"")*patterns.newline +local stripped=(spaceortab^1/"")*newline local leading=rubish^0/"" -local trailing=(anyrubish^1*patterns.endofstring)/"" +local trailing=(anyrubish^1*endofstring)/"" local redundant=rubish^3/"\n" local pattern=Cs(leading*(trailing+redundant+stripped+anything)^0) function strings.collapsecrlf(str) @@ -2834,17 +2864,13 @@ local pattern=Carg(1)/function(t) else return "" end - end+patterns.newline*Cp()/function(position) + end+newline*Cp()/function(position) extra,start=0,position end+patterns.anything )^1) function strings.tabtospace(str,tab) return lpegmatch(pattern,str,1,tab or 7) end -local newline=patterns.newline -local endofstring=patterns.endofstring -local whitespace=patterns.whitespace -local spacer=patterns.spacer local space=spacer^0 local nospace=space/"" local endofline=nospace*newline @@ -3413,6 +3439,10 @@ local pattern=Cs(dquote*(equote-P(-2))^0*dquote) function string.optionalquoted(str) return lpegmatch(pattern,str) or str end +local pattern=Cs((newline/os.newline+1)^0) +function string.replacenewlines(str) + return lpegmatch(pattern,str) +end end -- closure |