[latex3-commits] [git/LaTeX3-latex3-lualibs] v2.68-20191029: imported context (cf30fd6)

Ulrike Fischer fischer at troubleshooting-tex.de
Tue Oct 29 16:50:00 CET 2019


Repository : https://github.com/latex3/lualibs
On branch  : v2.68-20191029
Link       : https://github.com/latex3/lualibs/commit/cf30fd606d6a7ed38a7ffc1cbee0ecce4761cacd

>---------------------------------------------------------------

commit cf30fd606d6a7ed38a7ffc1cbee0ecce4761cacd
Author: Ulrike Fischer <fischer at troubleshooting-tex.de>
Date:   Tue Oct 29 16:50:00 2019 +0100

    imported context


>---------------------------------------------------------------

cf30fd606d6a7ed38a7ffc1cbee0ecce4761cacd
 CTANREADME.md               |   4 +-
 NEWS                        |   3 +
 README.md                   |   6 +-
 build.lua                   |   4 +-
 lualibs-basic-merged.lua    | 205 ++++++++++++++++++++++++++++----------------
 lualibs-extended-merged.lua |  66 +++++++++++---
 lualibs-gzip.lua            | 135 +++++++++++++++++++++--------
 lualibs-lpeg.lua            |   2 +-
 lualibs-lua.lua             |   6 ++
 lualibs-table.lua           |  31 +++++++
 lualibs-unicode.lua         |  84 +++++++++---------
 lualibs-util-lua.lua        |  10 ++-
 lualibs-util-str.lua        |  35 ++++++--
 lualibs-util-tab.lua        |  20 ++++-
 lualibs-util-tpl.lua        |  66 ++++++++------
 lualibs.dtx                 |  18 ++--
 16 files changed, 479 insertions(+), 216 deletions(-)

diff --git a/CTANREADME.md b/CTANREADME.md
index b89ca40..e6455b1 100644
--- a/CTANREADME.md
+++ b/CTANREADME.md
@@ -1,8 +1,8 @@
 # The Lualibs Package
 
-VERSION: 2.67
+VERSION: 2.68
 
-DATE: 2019-08-11
+DATE: 2019-10-29
 
 Lualibs is a collection of Lua modules useful for general programming.
 
diff --git a/NEWS b/NEWS
index 66ee05e..73e5961 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,7 @@
                         History of the lualibs package
+2019/10/29 v2.68/
+    * sync with Context current as of 2019/10/29
+                        
 2019/08/11 v2.67/
     * sync with Context current as of 2019/08/11
                         
diff --git a/README.md b/README.md
index 0e6b111..9aff4b0 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 # The Lualibs Package
 
-![Version: 2.67](https://img.shields.io/badge/current_version-2.67-blue.svg?style=flat-square)
-![Date: 2019-08-11](https://img.shields.io/badge/date-2019--08--11-blue.svg?style=flat-square)
+![Version: 2.68](https://img.shields.io/badge/current_version-2.68-blue.svg?style=flat-square)
+![Date: 2019-10-29](https://img.shields.io/badge/date-2019--10--29-blue.svg?style=flat-square)
 [![License: GNU GPLv2](https://img.shields.io/badge/license-GNU_GPLv2-blue.svg?style=flat-square)](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html)
 
 
@@ -15,7 +15,7 @@ This package has been developed by the LuaLaTeX development team on
 <http://github.com/lualatex/lualibs>. 
 
 The current version has been build by Ulrike Fischer on
-<https://github.com/u-fischer/lualibs> from context 2019-08-11. 
+<https://github.com/u-fischer/lualibs> from context 2019-10-29. 
 
 Please see the documentation lualibs.pdf for more information.
 
diff --git a/build.lua b/build.lua
index afcb6fe..068b81d 100644
--- a/build.lua
+++ b/build.lua
@@ -1,6 +1,6 @@
 -- Build script for lualibs
-packageversion= "2.67"
-packagedate= "2019-08-11"
+packageversion= "2.68"
+packagedate= "2019-10-29"
 
 module   = "lualibs"
 ctanpkg  = "lualibs"
diff --git a/lualibs-basic-merged.lua b/lualibs-basic-merged.lua
index 0cb07ce..bee6c7d 100644
--- a/lualibs-basic-merged.lua
+++ b/lualibs-basic-merged.lua
@@ -1,6 +1,6 @@
 -- merged file : lualibs-basic-merged.lua
 -- parent file : lualibs-basic.lua
--- merge date  : Tue Aug 13 20:13:08 2019
+-- merge date  : Tue Oct 29 16:47:31 2019
 
 do -- begin closure to overcome local limits and interference
 
@@ -20,6 +20,9 @@ if LUAVERSION<5.2 and jit then
  MINORVERSION=2
  LUAVERSION=5.2
 end
+if lua and lua.openfile then
+ io.open=lua.openfile
+end
 if not lpeg then
  lpeg=require("lpeg")
 end
@@ -613,7 +616,7 @@ patterns.propername=(uppercase+lowercase+underscore)*(uppercase+lowercase+unders
 patterns.somecontent=(anything-newline-space)^1 
 patterns.beginline=#(1-newline)
 patterns.longtostring=Cs(whitespace^0/""*((patterns.quoted+nonwhitespace^1+whitespace^1/""*(endofstring+Cc(" ")))^0))
-function anywhere(pattern) 
+local function anywhere(pattern) 
  return (1-P(pattern))^0*P(pattern)
 end
 lpeg.anywhere=anywhere
@@ -3954,43 +3957,98 @@ if not modules then modules={} end modules ['l-gzip']={
  copyright="PRAGMA ADE / ConTeXt Development Team",
  license="see context related readme files"
 }
-if not gzip then
- return
-end
-local suffix,suffixes=file.suffix,file.suffixes
-function gzip.load(filename)
- local f=io.open(filename,"rb")
- if not f then
- elseif suffix(filename)=="gz" then
-  f:close()
-  local g=gzip.open(filename,"rb")
-  if g then
-   local str=g:read("*all")
-   g:close()
+if gzip then
+ local suffix,suffixes=file.suffix,file.suffixes
+ function gzip.load(filename)
+  local f=io.open(filename,"rb")
+  if not f then
+  elseif suffix(filename)=="gz" then
+   f:close()
+   local g=gzip.open(filename,"rb")
+   if g then
+    local str=g:read("*all")
+    g:close()
+    return str
+   end
+  else
+   local str=f:read("*all")
+   f:close()
    return str
   end
- else
-  local str=f:read("*all")
-  f:close()
-  return str
  end
-end
-function gzip.save(filename,data)
- if suffix(filename)~="gz" then
-  filename=filename..".gz"
+ function gzip.save(filename,data)
+  if suffix(filename)~="gz" then
+   filename=filename..".gz"
+  end
+  local f=io.open(filename,"wb")
+  if f then
+   local s=zlib.compress(data or "",9,nil,15+16)
+   f:write(s)
+   f:close()
+   return #s
+  end
  end
- local f=io.open(filename,"wb")
- if f then
-  local s=zlib.compress(data or "",9,nil,15+16)
-  f:write(s)
-  f:close()
-  return #s
+ function gzip.suffix(filename)
+  local suffix,extra=suffixes(filename)
+  local gzipped=extra=="gz"
+  return suffix,gzipped
  end
+else
 end
-function gzip.suffix(filename)
- local suffix,extra=suffixes(filename)
- local gzipped=extra=="gz"
- return suffix,gzipped
+if flate then
+ local type=type
+ local find=string.find
+ local compress=flate.gz_compress
+ local decompress=flate.gz_decompress
+ local absmax=128*1024*1024
+ local initial=64*1024
+ local identifier="^\x1F\x8B\x08"
+ function gzip.compressed(s)
+  return s and find(s,identifier)
+ end
+ function gzip.compress(s,level)
+  if s and not find(s,identifier) then 
+   if not level then
+    level=3
+   elseif level<=0 then
+    return s
+   elseif level>9 then
+    level=9
+   end
+   return compress(s,level) or s
+  end
+ end
+ function gzip.decompress(s,size,iterate)
+  if s and find(s,identifier) then
+   if type(size)~="number" then
+    size=initial
+   end
+   if size>absmax then
+    size=absmax
+   end
+   if type(iterate)=="number" then
+    max=size*iterate
+   elseif iterate==nil or iterate==true then
+    iterate=true
+    max=absmax
+   end
+   if max>absmax then
+    max=absmax
+   end
+   while true do
+    local d=decompress(s,size)
+    if d then
+     return d
+    end
+    size=2*size
+    if not iterate or size>max then
+     return false
+    end
+   end
+  else
+   return s
+  end
+ end
 end
 
 end -- closure
@@ -5097,49 +5155,52 @@ end
 function utf.utf32_to_utf8_t(t,endian)
  return endian and utf32_to_utf8_be_t(t) or utf32_to_utf8_le_t(t) or t
 end
-local function little(b)
- if b<0x10000 then
-  return char(b%256,rshift(b,8))
- else
-  b=b-0x10000
-  local b1=rshift(b,10)+0xD800
-  local b2=b%1024+0xDC00
-  return char(b1%256,rshift(b1,8),b2%256,rshift(b2,8))
+if bit32 then
+ local rshift=bit32.rshift
+ local function little(b)
+  if b<0x10000 then
+   return char(b%256,rshift(b,8))
+  else
+   b=b-0x10000
+   local b1=rshift(b,10)+0xD800
+   local b2=b%1024+0xDC00
+   return char(b1%256,rshift(b1,8),b2%256,rshift(b2,8))
+  end
  end
-end
-local function big(b)
- if b<0x10000 then
-  return char(rshift(b,8),b%256)
- else
-  b=b-0x10000
-  local b1=rshift(b,10)+0xD800
-  local b2=b%1024+0xDC00
-  return char(rshift(b1,8),b1%256,rshift(b2,8),b2%256)
+ local function big(b)
+  if b<0x10000 then
+   return char(rshift(b,8),b%256)
+  else
+   b=b-0x10000
+   local b1=rshift(b,10)+0xD800
+   local b2=b%1024+0xDC00
+   return char(rshift(b1,8),b1%256,rshift(b2,8),b2%256)
+  end
  end
-end
-local l_remap=Cs((p_utf8byte/little+P(1)/"")^0)
-local b_remap=Cs((p_utf8byte/big+P(1)/"")^0)
-local function utf8_to_utf16_be(str,nobom)
- if nobom then
-  return lpegmatch(b_remap,str)
- else
-  return char(254,255)..lpegmatch(b_remap,str)
+ local l_remap=Cs((p_utf8byte/little+P(1)/"")^0)
+ local b_remap=Cs((p_utf8byte/big+P(1)/"")^0)
+ local function utf8_to_utf16_be(str,nobom)
+  if nobom then
+   return lpegmatch(b_remap,str)
+  else
+   return char(254,255)..lpegmatch(b_remap,str)
+  end
  end
-end
-local function utf8_to_utf16_le(str,nobom)
- if nobom then
-  return lpegmatch(l_remap,str)
- else
-  return char(255,254)..lpegmatch(l_remap,str)
+ local function utf8_to_utf16_le(str,nobom)
+  if nobom then
+   return lpegmatch(l_remap,str)
+  else
+   return char(255,254)..lpegmatch(l_remap,str)
+  end
  end
-end
-utf.utf8_to_utf16_be=utf8_to_utf16_be
-utf.utf8_to_utf16_le=utf8_to_utf16_le
-function utf.utf8_to_utf16(str,littleendian,nobom)
- if littleendian then
-  return utf8_to_utf16_le(str,nobom)
- else
-  return utf8_to_utf16_be(str,nobom)
+ utf.utf8_to_utf16_be=utf8_to_utf16_be
+ utf.utf8_to_utf16_le=utf8_to_utf16_le
+ function utf.utf8_to_utf16(str,littleendian,nobom)
+  if littleendian then
+   return utf8_to_utf16_le(str,nobom)
+  else
+   return utf8_to_utf16_be(str,nobom)
+  end
  end
 end
 local pattern=Cs (
diff --git a/lualibs-extended-merged.lua b/lualibs-extended-merged.lua
index b3fecf2..c250240 100644
--- a/lualibs-extended-merged.lua
+++ b/lualibs-extended-merged.lua
@@ -1,6 +1,6 @@
 -- merged file : lualibs-extended-merged.lua
 -- parent file : lualibs-extended.lua
--- merge date  : Tue Aug 13 20:12:59 2019
+-- merge date  : Tue Oct 29 16:47:22 2019
 
 do -- begin closure to overcome local limits and interference
 
@@ -366,7 +366,7 @@ local environment={
  stripzero=patterns.stripzero,
  stripzeros=patterns.stripzeros,
  escapedquotes=string.escapedquotes,
- FORMAT=string.f9,
+ FORMAT=string.f6,
 }
 local arguments={ "a1" } 
 setmetatable(arguments,{ __index=function(t,k)
@@ -574,12 +574,25 @@ local format_n=function()
  n=n+1
  return format("((a%s %% 1 == 0) and format('%%i',a%s) or tostring(a%s))",n,n,n)
 end
-local format_N=function(f) 
- n=n+1
- if not f or f=="" then
-  f=".9"
+local format_N  if environment.FORMAT then
+ format_N=function(f)
+  n=n+1
+  if not f or f=="" then
+   return format("FORMAT(a%s,'%%.9f')",n)
+  elseif f==".6" then
+   return format("FORMAT(a%s)",n)
+  else
+   return format("FORMAT(a%s,'%%%sf')",n,f)
+  end
+ end
+else
+ format_N=function(f) 
+  n=n+1
+  if not f or f=="" then
+   f=".9"
+  end 
+  return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n)
  end
- return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n)
 end
 local format_a=function(f)
  n=n+1
@@ -1416,7 +1429,21 @@ function table.fastserialize(t,prefix)
   m=m+1
   r[m]="{"
   if n>0 then
-   for i=0,n do
+   local v=t[0]
+   if v then
+    local tv=type(v)
+    if tv=="string" then
+     m=m+1 r[m]=f_indexed_string(0,v)
+    elseif tv=="number" then
+     m=m+1 r[m]=f_indexed_number(0,v)
+    elseif tv=="table" then
+     m=m+1 r[m]=f_indexed_table(0)
+     fastserialize(v)
+    elseif tv=="boolean" then
+     m=m+1 r[m]=f_indexed_boolean(0,v)
+    end
+   end
+   for i=1,n do
     local v=t[i]
     local tv=type(v)
     if tv=="string" then
@@ -3377,6 +3404,11 @@ luautilities.nofstrippedchunks=0
 luautilities.nofstrippedbytes=0
 local strippedchunks={} 
 luautilities.strippedchunks=strippedchunks
+if not LUATEXENGINE then
+ LUATEXENGINE=status.luatex_engine and string.lower(status.luatex_engine)
+ JITSUPPORTED=LUATEXENGINE=="luajittex" or jit
+ CONTEXTLMTXMODE=CONTEXTLMTXMODE or (LUATEXENGINE=="luametatex" and 1) or 0
+end
 luautilities.suffixes={
  tma="tma",
  tmc=(CONTEXTLMTXMODE and CONTEXTLMTXMODE>0 and "tmd") or (jit and "tmb") or "tmc",
@@ -3386,7 +3418,7 @@ luautilities.suffixes={
  luv="luv",
  luj="luj",
  tua="tua",
- tuc="tuc",
+ tuc=(CONTEXTLMTXMODE and CONTEXTLMTXMODE>0 and "tud") or (jit and "tub") or "tuc",
 }
 local function register(name) 
  if tracestripping then
@@ -3833,6 +3865,7 @@ local report_template=logs.reporter("template")
 local tostring,next=tostring,next
 local format,sub,byte=string.format,string.sub,string.byte
 local P,C,R,Cs,Cc,Carg,lpegmatch,lpegpatterns=lpeg.P,lpeg.C,lpeg.R,lpeg.Cs,lpeg.Cc,lpeg.Carg,lpeg.match,lpeg.patterns
+local formatters=string.formatters
 local replacer
 local function replacekey(k,t,how,recursive)
  local v=t[k]
@@ -3901,6 +3934,10 @@ local function replaceoptional(l,m,r,t,how,recurse)
  local v=t[l]
  return v and v~="" and lpegmatch(replacer,r,1,t,how or "lua",recurse or false) or ""
 end
+local function replaceformatted(l,m,r,t,how,recurse)
+ local v=t[r]
+ return v and formatters[l](v)
+end
 local single=P("%")  
 local double=P("%%") 
 local lquoted=P("%[") 
@@ -3914,16 +3951,19 @@ local nolquoted=lquoted/''
 local norquoted=rquoted/''
 local nolquotedq=lquotedq/''
 local norquotedq=rquotedq/''
+local nolformatted=P(":")/"%%"
+local norformatted=P(":")/""
 local noloptional=P("%?")/''
 local noroptional=P("?%")/''
 local nomoptional=P(":")/''
 local args=Carg(1)*Carg(2)*Carg(3)
-local key=nosingle*((C((1-nosingle   )^1)*args)/replacekey  )*nosingle
-local quoted=nolquotedq*((C((1-norquotedq )^1)*args)/replacekeyquoted  )*norquotedq
-local unquoted=nolquoted*((C((1-norquoted  )^1)*args)/replacekeyunquoted)*norquoted
+local key=nosingle*((C((1-nosingle)^1)*args)/replacekey)*nosingle
+local quoted=nolquotedq*((C((1-norquotedq)^1)*args)/replacekeyquoted)*norquotedq
+local unquoted=nolquoted*((C((1-norquoted)^1)*args)/replacekeyunquoted)*norquoted
 local optional=noloptional*((C((1-nomoptional)^1)*nomoptional*C((1-noroptional)^1)*args)/replaceoptional)*noroptional
+local formatted=nosingle*((Cs(nolformatted*(1-norformatted )^1)*norformatted*C((1-nosingle)^1)*args)/replaceformatted)*nosingle
 local any=P(1)
-   replacer=Cs((unquoted+quoted+escape+optional+key+any)^0)
+   replacer=Cs((unquoted+quoted+formatted+escape+optional+key+any)^0)
 local function replace(str,mapping,how,recurse)
  if mapping and str then
   return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str
diff --git a/lualibs-gzip.lua b/lualibs-gzip.lua
index 5100e47..31466bd 100644
--- a/lualibs-gzip.lua
+++ b/lualibs-gzip.lua
@@ -5,50 +5,113 @@ if not modules then modules = { } end modules ['l-gzip'] = {
     license   = "see context related readme files"
 }
 
-if not gzip then
+if gzip then
 
-    -- no fallback yet
+    local suffix, suffixes = file.suffix, file.suffixes
 
-    return
-
-end
-
-local suffix, suffixes = file.suffix, file.suffixes
-
-function gzip.load(filename)
-    local f = io.open(filename,"rb")
-    if not f then
-        -- invalid file
-    elseif suffix(filename) == "gz" then
-        f:close()
-        local g = gzip.open(filename,"rb")
-        if g then
-            local str = g:read("*all")
-            g:close()
+    function gzip.load(filename)
+        local f = io.open(filename,"rb")
+        if not f then
+            -- invalid file
+        elseif suffix(filename) == "gz" then
+            f:close()
+            local g = gzip.open(filename,"rb")
+            if g then
+                local str = g:read("*all")
+                g:close()
+                return str
+            end
+        else
+            local str = f:read("*all")
+            f:close()
             return str
         end
-    else
-        local str = f:read("*all")
-        f:close()
-        return str
     end
-end
 
-function gzip.save(filename,data)
-    if suffix(filename) ~= "gz" then
-        filename = filename .. ".gz"
+    function gzip.save(filename,data)
+        if suffix(filename) ~= "gz" then
+            filename = filename .. ".gz"
+        end
+        local f = io.open(filename,"wb")
+        if f then
+            local s = zlib.compress(data or "",9,nil,15+16)
+            f:write(s)
+            f:close()
+            return #s
+        end
     end
-    local f = io.open(filename,"wb")
-    if f then
-        local s = zlib.compress(data or "",9,nil,15+16)
-        f:write(s)
-        f:close()
-        return #s
+
+    function gzip.suffix(filename)
+        local suffix, extra = suffixes(filename)
+        local gzipped = extra == "gz"
+        return suffix, gzipped
     end
+
+else
+
+    -- todo: fallback on flate
+
 end
 
-function gzip.suffix(filename)
-    local suffix, extra = suffixes(filename)
-    local gzipped = extra == "gz"
-    return suffix, gzipped
+if flate then
+
+    local type = type
+    local find = string.find
+
+    local compress   = flate.gz_compress
+    local decompress = flate.gz_decompress
+
+    local absmax     = 128*1024*1024
+    local initial    =       64*1024
+    local identifier = "^\x1F\x8B\x08"
+
+    function gzip.compressed(s)
+        return s and find(s,identifier)
+    end
+
+    function gzip.compress(s,level)
+        if s and not find(s,identifier) then -- the find check might go away
+            if not level then
+                level = 3
+            elseif level <= 0 then
+                return s
+            elseif level > 9 then
+                level = 9
+            end
+            return compress(s,level) or s
+        end
+    end
+
+    function gzip.decompress(s,size,iterate)
+        if s and find(s,identifier) then
+            if type(size) ~= "number" then
+                size = initial
+            end
+            if size > absmax then
+                size = absmax
+            end
+            if type(iterate) == "number" then
+                max = size * iterate
+            elseif iterate == nil or iterate == true then
+                iterate = true
+                max     = absmax
+            end
+            if max > absmax then
+                max = absmax
+            end
+            while true do
+                local d = decompress(s,size)
+                if d then
+                    return d
+                end
+                size = 2 * size
+                if not iterate or size > max then
+                    return false
+                end
+            end
+        else
+            return s
+        end
+    end
+
 end
diff --git a/lualibs-lpeg.lua b/lualibs-lpeg.lua
index 51bc1d3..7979a40 100644
--- a/lualibs-lpeg.lua
+++ b/lualibs-lpeg.lua
@@ -295,7 +295,7 @@ patterns.longtostring  = Cs(whitespace^0/"" * ((patterns.quoted + nonwhitespace^
 --     return P { P(pattern) + 1 * V(1) }
 -- end
 
-function anywhere(pattern) -- faster
+local function anywhere(pattern) -- faster
     return (1-P(pattern))^0 * P(pattern)
 end
 
diff --git a/lualibs-lua.lua b/lualibs-lua.lua
index 6e9606e..5139921 100644
--- a/lualibs-lua.lua
+++ b/lualibs-lua.lua
@@ -35,6 +35,12 @@ if LUAVERSION < 5.2 and jit then
     LUAVERSION   = 5.2
 end
 
+-- this is lmtx only:
+
+if lua and lua.openfile then
+    io.open = lua.openfile
+end
+
 -- lpeg
 
 if not lpeg then
diff --git a/lualibs-table.lua b/lualibs-table.lua
index cffdcc2..e828203 100644
--- a/lualibs-table.lua
+++ b/lualibs-table.lua
@@ -287,6 +287,37 @@ local function sortedhash(t,cmp)
     return nothing
 end
 
+-- local function iterate(t,i)
+--     local i = i + 1
+--     if i <= t.n then
+--         local k = t[i]
+--         return i, k, t.t[k]
+--     end
+-- end
+--
+-- local function indexedhash(t,cmp)
+--     if t then
+--         local s
+--         if cmp then
+--             -- it would be nice if the sort function would accept a third argument (or nicer, an optional first)
+--             s = sortedhashkeys(t,function(a,b) return cmp(t,a,b) end)
+--         else
+--             s = sortedkeys(t) -- the robust one
+--         end
+--         local m = #s
+--         if m == 1 then
+--             return next, t
+--         elseif m > 0 then
+--             s.n = m
+--             s.t = t
+--             return iterate, s, 0
+--         end
+--     end
+--     return nothing
+-- end
+--
+-- -- for i, k, v in indexedhash(t) do print(k,v,s) end
+
 table.sortedhash  = sortedhash
 table.sortedpairs = sortedhash -- obsolete
 
diff --git a/lualibs-unicode.lua b/lualibs-unicode.lua
index 73d1eb7..2708d14 100644
--- a/lualibs-unicode.lua
+++ b/lualibs-unicode.lua
@@ -1081,56 +1081,62 @@ function utf.utf32_to_utf8_t(t,endian)
     return endian and utf32_to_utf8_be_t(t) or utf32_to_utf8_le_t(t) or t
 end
 
-local function little(b)
-    if b < 0x10000 then
-        return char(b%256,rshift(b,8))
-    else
-        b = b - 0x10000
-        local b1 = rshift(b,10) + 0xD800
-        local b2 = b%1024 + 0xDC00
-        return char(b1%256,rshift(b1,8),b2%256,rshift(b2,8))
+if bit32 then
+
+    local rshift  = bit32.rshift
+
+    local function little(b)
+        if b < 0x10000 then
+            return char(b%256,rshift(b,8))
+        else
+            b = b - 0x10000
+            local b1 = rshift(b,10) + 0xD800
+            local b2 = b%1024 + 0xDC00
+            return char(b1%256,rshift(b1,8),b2%256,rshift(b2,8))
+        end
     end
-end
 
-local function big(b)
-    if b < 0x10000 then
-        return char(rshift(b,8),b%256)
-    else
-        b = b - 0x10000
-        local b1 = rshift(b,10) + 0xD800
-        local b2 = b%1024 + 0xDC00
-        return char(rshift(b1,8),b1%256,rshift(b2,8),b2%256)
+    local function big(b)
+        if b < 0x10000 then
+            return char(rshift(b,8),b%256)
+        else
+            b = b - 0x10000
+            local b1 = rshift(b,10) + 0xD800
+            local b2 = b%1024 + 0xDC00
+            return char(rshift(b1,8),b1%256,rshift(b2,8),b2%256)
+        end
     end
-end
 
-local l_remap = Cs((p_utf8byte/little+P(1)/"")^0)
-local b_remap = Cs((p_utf8byte/big   +P(1)/"")^0)
+    local l_remap = Cs((p_utf8byte/little+P(1)/"")^0)
+    local b_remap = Cs((p_utf8byte/big   +P(1)/"")^0)
 
-local function utf8_to_utf16_be(str,nobom)
-    if nobom then
-        return lpegmatch(b_remap,str)
-    else
-        return char(254,255) .. lpegmatch(b_remap,str)
+    local function utf8_to_utf16_be(str,nobom)
+        if nobom then
+            return lpegmatch(b_remap,str)
+        else
+            return char(254,255) .. lpegmatch(b_remap,str)
+        end
     end
-end
 
-local function utf8_to_utf16_le(str,nobom)
-    if nobom then
-        return lpegmatch(l_remap,str)
-    else
-        return char(255,254) .. lpegmatch(l_remap,str)
+    local function utf8_to_utf16_le(str,nobom)
+        if nobom then
+            return lpegmatch(l_remap,str)
+        else
+            return char(255,254) .. lpegmatch(l_remap,str)
+        end
     end
-end
 
-utf.utf8_to_utf16_be = utf8_to_utf16_be
-utf.utf8_to_utf16_le = utf8_to_utf16_le
+    utf.utf8_to_utf16_be = utf8_to_utf16_be
+    utf.utf8_to_utf16_le = utf8_to_utf16_le
 
-function utf.utf8_to_utf16(str,littleendian,nobom)
-    if littleendian then
-        return utf8_to_utf16_le(str,nobom)
-    else
-        return utf8_to_utf16_be(str,nobom)
+    function utf.utf8_to_utf16(str,littleendian,nobom)
+        if littleendian then
+            return utf8_to_utf16_le(str,nobom)
+        else
+            return utf8_to_utf16_be(str,nobom)
+        end
     end
+
 end
 
 local pattern = Cs (
diff --git a/lualibs-util-lua.lua b/lualibs-util-lua.lua
index f7e6e4f..fb4088e 100644
--- a/lualibs-util-lua.lua
+++ b/lualibs-util-lua.lua
@@ -28,6 +28,13 @@ luautilities.nofstrippedbytes  = 0
 local strippedchunks           = { } -- allocate()
 luautilities.strippedchunks    = strippedchunks
 
+if not LUATEXENGINE then
+    --- probably mtxrun ...
+    LUATEXENGINE    = status.luatex_engine and string.lower(status.luatex_engine)
+    JITSUPPORTED    = LUATEXENGINE == "luajittex" or jit
+    CONTEXTLMTXMODE = CONTEXTLMTXMODE or (LUATEXENGINE == "luametatex" and 1) or 0
+end
+
 luautilities.suffixes = {
     tma = "tma",
     tmc = (CONTEXTLMTXMODE and CONTEXTLMTXMODE > 0 and "tmd") or (jit and "tmb") or "tmc",
@@ -37,7 +44,8 @@ luautilities.suffixes = {
     luv = "luv",
     luj = "luj",
     tua = "tua",
-    tuc = "tuc",
+ -- tuc = "tuc",
+    tuc = (CONTEXTLMTXMODE and CONTEXTLMTXMODE > 0 and "tud") or (jit and "tub") or "tuc",
 }
 
 -- environment.loadpreprocessedfile can be set to a preprocessor
diff --git a/lualibs-util-str.lua b/lualibs-util-str.lua
index ad22302..432b39e 100644
--- a/lualibs-util-str.lua
+++ b/lualibs-util-str.lua
@@ -633,7 +633,7 @@ local environment = {
     stripzeros      = patterns.stripzeros,
     escapedquotes   = string.escapedquotes,
 
-    FORMAT          = string.f9,
+    FORMAT          = string.f6,
 }
 
 -- -- --
@@ -908,7 +908,7 @@ local format_L = function()
     return format("(a%s and 'TRUE' or 'FALSE')",n)
 end
 
-local format_n = function() -- strips leading and trailing zeros and removes .0
+local format_n = function() -- strips leading and trailing zeros and removes .0, beware: can produce e notation
     n = n + 1
     return format("((a%s %% 1 == 0) and format('%%i',a%s) or tostring(a%s))",n,n,n)
 end
@@ -938,13 +938,30 @@ end
 --     end
 -- end
 
-local format_N = function(f) -- strips leading and trailing zeros
-    n = n + 1
-    -- stripzero (singular) as we only have a number
-    if not f or f == "" then
-        f = ".9"
-    end -- always a leading number !
-    return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n)
+local format_N  if environment.FORMAT then
+
+    format_N = function(f)
+        n = n + 1
+        if not f or f == "" then
+            return format("FORMAT(a%s,'%%.9f')",n)
+        elseif f == ".6" then
+            return format("FORMAT(a%s)",n)
+        else
+            return format("FORMAT(a%s,'%%%sf')",n,f)
+        end
+    end
+
+else
+
+    format_N = function(f) -- strips leading and trailing zeros
+        n = n + 1
+        -- stripzero (singular) as we only have a number
+        if not f or f == "" then
+            f = ".9"
+        end -- always a leading number !
+        return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n)
+    end
+
 end
 
 local format_a = function(f)
diff --git a/lualibs-util-tab.lua b/lualibs-util-tab.lua
index f970d8a..410292c 100644
--- a/lualibs-util-tab.lua
+++ b/lualibs-util-tab.lua
@@ -341,7 +341,21 @@ function table.fastserialize(t,prefix) -- todo, move local function out
         m = m + 1
         r[m] = "{"
         if n > 0 then
-            for i=0,n do
+            local v = t[0]
+            if v then
+                local tv = type(v)
+                if tv == "string" then
+                    m = m + 1 r[m] = f_indexed_string(0,v)
+                elseif tv == "number" then
+                    m = m + 1 r[m] = f_indexed_number(0,v)
+                elseif tv == "table" then
+                    m = m + 1 r[m] = f_indexed_table(0)
+                    fastserialize(v)
+                elseif tv == "boolean" then
+                    m = m + 1 r[m] = f_indexed_boolean(0,v)
+                end
+            end
+            for i=1,n do
                 local v  = t[i]
                 local tv = type(v)
                 if tv == "string" then
@@ -355,6 +369,8 @@ function table.fastserialize(t,prefix) -- todo, move local function out
                 end
             end
         end
+        -- hm, can't we avoid this ... lua should have a way to check if there
+        -- is a hash part
         for k, v in next, t do
             local tk = type(k)
             if tk == "number" then
@@ -411,7 +427,7 @@ function table.deserialize(str)
     return code
 end
 
--- inspect(table.fastserialize { a = 1, b = { 4, { 5, 6 } }, c = { d = 7, e = 'f"g\nh' } })
+-- inspect(table.fastserialize { a = 1, b = { [0]=4, { 5, 6 } }, c = { d = 7, e = 'f"g\nh' } })
 
 function table.load(filename,loader)
     if filename then
diff --git a/lualibs-util-tpl.lua b/lualibs-util-tpl.lua
index 57d7df3..318f2ef 100644
--- a/lualibs-util-tpl.lua
+++ b/lualibs-util-tpl.lua
@@ -20,6 +20,8 @@ local tostring, next = tostring, next
 local format, sub, byte = string.format, string.sub, string.byte
 local P, C, R, Cs, Cc, Carg, lpegmatch, lpegpatterns = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs, lpeg.Cc, lpeg.Carg, lpeg.match, lpeg.patterns
 
+local formatters = string.formatters
+
 -- todo: make installable template.new
 
 local replacer
@@ -133,34 +135,42 @@ local function replaceoptional(l,m,r,t,how,recurse)
     return v and v ~= "" and lpegmatch(replacer,r,1,t,how or "lua",recurse or false) or ""
 end
 
-local single      = P("%")  -- test %test% test     : resolves test
-local double      = P("%%") -- test 10%% test       : %% becomes %
-local lquoted     = P("%[") -- test '%[test]%' test : resolves to test with escaped "'s
-local rquoted     = P("]%") --
-local lquotedq    = P("%(") -- test %(test)% test   : resolves to 'test' with escaped "'s
-local rquotedq    = P(")%") --
-
-local escape      = double   / '%%'
-local nosingle    = single   / ''
-local nodouble    = double   / ''
-local nolquoted   = lquoted  / ''
-local norquoted   = rquoted  / ''
-local nolquotedq  = lquotedq / ''
-local norquotedq  = rquotedq / ''
-
-local noloptional = P("%?") / ''
-local noroptional = P("?%") / ''
-local nomoptional = P(":")  / ''
-
-
-local args        = Carg(1) * Carg(2) * Carg(3)
-local key         = nosingle    * ((C((1-nosingle   )^1) * args) / replacekey        ) * nosingle
-local quoted      = nolquotedq  * ((C((1-norquotedq )^1) * args) / replacekeyquoted  ) * norquotedq
-local unquoted    = nolquoted   * ((C((1-norquoted  )^1) * args) / replacekeyunquoted) * norquoted
-local optional    = noloptional * ((C((1-nomoptional)^1) * nomoptional * C((1-noroptional)^1) * args) / replaceoptional) *  noroptional
-local any         = P(1)
+local function replaceformatted(l,m,r,t,how,recurse)
+    local v = t[r]
+    return v and formatters[l](v)
+end
 
-      replacer    = Cs((unquoted + quoted + escape + optional + key + any)^0)
+local single       = P("%")  -- test %test% test     : resolves test
+local double       = P("%%") -- test 10%% test       : %% becomes %
+local lquoted      = P("%[") -- test '%[test]%' test : resolves to test with escaped "'s
+local rquoted      = P("]%") --
+local lquotedq     = P("%(") -- test %(test)% test   : resolves to 'test' with escaped "'s
+local rquotedq     = P(")%") --
+
+local escape       = double   / '%%'
+local nosingle     = single   / ''
+local nodouble     = double   / ''
+local nolquoted    = lquoted  / ''
+local norquoted    = rquoted  / ''
+local nolquotedq   = lquotedq / ''
+local norquotedq   = rquotedq / ''
+
+local nolformatted = P(":") / "%%"
+local norformatted = P(":") / ""
+
+local noloptional  = P("%?") / ''
+local noroptional  = P("?%") / ''
+local nomoptional  = P(":")  / ''
+
+local args         = Carg(1) * Carg(2) * Carg(3)
+local key          = nosingle * ((C((1-nosingle)^1) * args) / replacekey) * nosingle
+local quoted       = nolquotedq * ((C((1-norquotedq)^1) * args) / replacekeyquoted) * norquotedq
+local unquoted     = nolquoted * ((C((1-norquoted)^1) * args) / replacekeyunquoted) * norquoted
+local optional     = noloptional * ((C((1-nomoptional)^1) * nomoptional * C((1-noroptional)^1) * args) / replaceoptional) *  noroptional
+local formatted    = nosingle * ((Cs(nolformatted * (1-norformatted )^1) * norformatted * C((1-nosingle)^1) * args) / replaceformatted) * nosingle
+local any          = P(1)
+
+      replacer     = Cs((unquoted + quoted + formatted + escape + optional + key + any)^0)
 
 local function replace(str,mapping,how,recurse)
     if mapping and str then
@@ -179,6 +189,8 @@ end
 -- print(replace([[test %[x]% test]],{ x = [[a "x"  a]]}))
 -- print(replace([[test %(x)% test]],{ x = [[a "x"  a]]}))
 -- print(replace([[convert %?x: -x "%x%" ?% %?y: -y "%y%" ?%]],{ x = "yes" }))
+-- print(replace("test %:0.3N:x% test",{ x = 123.45 }))
+-- print(replace("test %:0.3N:x% test",{ x = 12345 }))
 
 templates.replace = replace
 
diff --git a/lualibs.dtx b/lualibs.dtx
index 8c30240..7dc0e4b 100644
--- a/lualibs.dtx
+++ b/lualibs.dtx
@@ -37,7 +37,7 @@
 \input docstrip.tex
 \Msg{************************************************************************}
 \Msg{* Installation}
-\Msg{* Package: lualibs 2019-08-11 v2.67 Lua additional functions.}
+\Msg{* Package: lualibs 2019-10-29 v2.68 Lua additional functions.}
 \Msg{************************************************************************}
 
 \keepsilent
@@ -107,7 +107,7 @@ and lualibs-extended.lua.
 %<*driver>
 \NeedsTeXFormat{LaTeX2e}
 \ProvidesFile{lualibs.drv}
-  [2019/08/11 v2.67 Lua Libraries.]
+  [2019/10/29 v2.68 Lua Libraries.]
 \documentclass{ltxdoc}
 \usepackage{fancyvrb,xspace}
 \usepackage[x11names]{xcolor}
@@ -208,7 +208,7 @@ and lualibs-extended.lua.
 % \GetFileInfo{lualibs.drv}
 %
 % \title{The \identifier{lualibs} package}
-% \date{2019/08/11 v2.67}
+% \date{2019/10/29 v2.68}
 % \author{Élie Roux      · \email{elie.roux at telecom-bretagne.eu}\\
 %         Philipp Gesang · \email{phg at phi-gamma.net}\\
 %         Ulrike Fischer · \email{fischer at troubleshooting-tex.de}\\
@@ -429,8 +429,8 @@ lualibs = lualibs or { }
 
 lualibs.module_info = {
   name          = "lualibs",
-  version       = "2.67",       --TAGVERSION
-    date        = "2019-08-11", --TAGDATE
+  version       = "2.68",       --TAGVERSION
+    date        = "2019-10-29", --TAGDATE
   description   = "ConTeXt Lua standard libraries.",
   author        = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang",
   copyright     = "PRAGMA ADE / ConTeXt Development Team",
@@ -583,8 +583,8 @@ local loadmodule        = lualibs.loadmodule
 
 local lualibs_basic_module = {
   name          = "lualibs-basic",
-  version       = "2.67",       --TAGVERSION
-  date          = "2019-08-11", --TAGDATE
+  version       = "2.68",       --TAGVERSION
+  date          = "2019-10-29", --TAGDATE
   description   = "ConTeXt Lua libraries -- basic collection.",
   author        = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang",
   copyright     = "PRAGMA ADE / ConTeXt Development Team",
@@ -665,8 +665,8 @@ lualibs = lualibs or { }
 
 local lualibs_extended_module = {
   name          = "lualibs-extended",
-  version       = "2.67",       --TAGVERSION
-  date          = "2019-08-11", --TAGDATE
+  version       = "2.68",       --TAGVERSION
+  date          = "2019-10-29", --TAGDATE
   description   = "ConTeXt Lua libraries -- extended collection.",
   author        = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang",
   copyright     = "PRAGMA ADE / ConTeXt Development Team",





More information about the latex3-commits mailing list