summaryrefslogtreecommitdiff
path: root/macros/luatex/generic/minim/minim-alloc.lua
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2022-03-04 03:01:04 +0000
committerNorbert Preining <norbert@preining.info>2022-03-04 03:01:04 +0000
commit575ab7d0e7534edd510bbc89a2ef4b04582af591 (patch)
tree9fc4cf55b7ca8b168bdfd747be21de4c9ef2b30e /macros/luatex/generic/minim/minim-alloc.lua
parent6b9ed20cb01cb52c7aaf2a48202f5d8aa588ff79 (diff)
CTAN sync 202203040301
Diffstat (limited to 'macros/luatex/generic/minim/minim-alloc.lua')
-rw-r--r--macros/luatex/generic/minim/minim-alloc.lua183
1 files changed, 163 insertions, 20 deletions
diff --git a/macros/luatex/generic/minim/minim-alloc.lua b/macros/luatex/generic/minim/minim-alloc.lua
index c99ca2c73d..8f6a69ed0d 100644
--- a/macros/luatex/generic/minim/minim-alloc.lua
+++ b/macros/luatex/generic/minim/minim-alloc.lua
@@ -27,6 +27,131 @@ function M.err (...)
tex.error(string.format(...))
end
+-- 1 pdf helpers
+
+local function insert_formatted(t, ...)
+ table.insert(t, string.format(...))
+end
+
+local function hexify(c)
+ return string.format('#%02x', c:byte())
+end
+function M.pdf_name(n)
+ return '/'..n
+ :gsub('[][(){}<>#%%/\\]', hexify)
+ :gsub('%G', hexify)
+end
+
+-- re-encode to utf-16
+local function pdf_hex_string(text)
+ local str = { [1] = '<feff' }
+ for i in text:utfvalues() do
+ if i <= 0xffff then
+ insert_formatted(str, '%04x', i)
+ else
+ i = i - 0x10000
+ m = math.floor(i/0x400) + 0xd800
+ n = ( i % 0x400 ) + 0xdc00
+ insert_formatted(str, '%04x%04x', m, n)
+ end
+ end
+ table.insert(str, '>')
+ return table.concat(str,'')
+end
+local function octify(c)
+ return string.format('\\%03o', c:byte())
+end
+function M.pdf_string(text)
+ -- do note that \ddd is decimal in lua, octal in pdf
+ if text:match('[^%g\009\010\13 ]') then
+ return pdf_hex_string(text)
+ else
+ return string.format('(%s)', text
+ :gsub('[()\\]','\\%0')
+ :gsub('%c', octify))
+ end
+end
+
+-- try and produce a date of the format (D:YYYYMMDD)
+function M.pdf_date(text)
+ local y, m, d = string.match(text, '^([12][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)$')
+ if not y then d, m, y = string.match(text, '^([0-9][0-9]?)-([0-9][0-9]?)-([12][0-9][0-9][0-9])$') end
+ if y then
+ return string.format('(D:%4d%02d%02d)', y, m, d)
+ else
+ return string.format('(D:%s)', text)
+ end
+end
+
+-- 1 scanning helpers
+
+local function make_scanner(fn)
+ return function(this, name, multiple)
+ this.scanners[name] = multiple and function()
+ this.res[name] = this.res[name] or { }
+ table.insert(this.res[name], fn())
+ end or function()
+ this.scanners[name] = nil
+ this.res[name] = fn()
+ end
+ return this
+ end
+end
+
+function M.options_scanner()
+ return { scanners = { }, res = { },
+ int = make_scanner(token.scan_int),
+ glue = make_scanner(token.scan_glue),
+ dimen = make_scanner(token.scan_dimen),
+ string = make_scanner(token.scan_string),
+ argument = make_scanner(token.scan_argument),
+ word = make_scanner(token.scan_word),
+ list = make_scanner(token.scan_list),
+ keyword = function(this, name, opposite)
+ this.scanners[name] = function()
+ this.res[name] = true
+ if opposite then this.res[opposite] = false end
+ end
+ if opposite then
+ this.scanners[opposite] = function()
+ this.res[name] = false
+ this.res[opposite] = true
+ end
+ end
+ return this
+ end,
+ table = function(this, name)
+ this.scanners[name] = function()
+ this.res[name] = this.res[name] or { }
+ this.res[name][token.scan_string()] = token.scan_string()
+ end
+ return this
+ end,
+ subtable = function(this, name)
+ this.scanners[name] = function()
+ this.res[name] = this.res[name] or { }
+ local sub = token.scan_string();
+ this.res[name][sub] = this.res[name][sub] or { }
+ this.res[name][sub][token.scan_string()] = token.scan_string()
+ end
+ return this
+ end,
+ scan = function(this, defaults)
+ this.res = defaults or this.res
+ repeat
+ local matched = false
+ for name, scanner in pairs(this.scanners) do
+ if token.scan_keyword(name) then
+ matched = true
+ scanner()
+ end
+ end
+ until not matched
+ return this.res
+ end
+ }
+end
+
-- 1 saving modules and tables
local tables = package.loaded['minim-saved-tables']
@@ -70,7 +195,7 @@ function M.table_to_text (tbl)
return '{ ' .. table.concat (r,', ') .. ' }'
end
-require('minim-callbacks')
+local cb = require('minim-callbacks')
M.remember('minim-callbacks')
M.remember('minim-alloc')
@@ -79,11 +204,23 @@ M.remember('minim-alloc')
-- like \unset
M.unset = -0x7FFFFFFF
-local allocations = M.saved_table ('minim:allocations')
+-- works for both \chardef and the likes of \countdef
+function M.registernumber(csname)
+ if token.is_defined(csname) then
+ return token.create(csname).index
+ else
+ return -- would return 0 otherwise
+ end
+end
+
+-- we need remember lua-made allocations in the format file, since otherwise,
+-- a different register will be reserved when the lua code is seen again in the
+-- actual run.
+local allocations = M.saved_table('minim lua-side allocations')
-local function make_alloc_new (fname, globcount)
+local function make_alloc_new(fname, globcount)
allocations[fname] = allocations[fname] or { }
- M['new_'..fname] = function (id)
+ M['new_'..fname] = function(id)
local nr
if id and allocations[fname][id] then
nr = allocations[fname][id]
@@ -108,7 +245,7 @@ make_alloc_new ('userrule' , 'e@alloc@rule@count' )
-- We need different allocation functions for the older registers, because
-- etex’s global allocation macros are off-by-one w.r.t. all other.
--
-local function make_alloc_old (fname, globcount, loccount)
+local function make_alloc_old(fname, globcount)
allocations[fname] = allocations[fname] or { }
M['new_'..fname] = function (id)
local nr
@@ -122,21 +259,16 @@ local function make_alloc_old (fname, globcount, loccount)
end
return nr
end
- M['local_'..fname] = function ()
- local nr = tex.count[loccount] - 1
- tex.setcount(loccount, nr)
- return nr
- end
end
-- existing allocation counters
-make_alloc_old ('count', 260, 270 )
-make_alloc_old ('dimen', 261, 271 )
-make_alloc_old ('skip', 262, 272 )
-make_alloc_old ('muskip', 263, 273 )
-make_alloc_old ('box', 264, 274 )
-make_alloc_old ('toks', 265, 275 )
-make_alloc_old ('marks', 266, 276 )
+make_alloc_old ('count', 260 )
+make_alloc_old ('dimen', 261 )
+make_alloc_old ('skip', 262 )
+make_alloc_old ('muskip', 263 )
+make_alloc_old ('box', 264 )
+make_alloc_old ('toks', 265 )
+make_alloc_old ('marks', 266 )
function M.luadef (csname, fn, ...)
local nr = M.new_function(csname)
@@ -144,8 +276,19 @@ function M.luadef (csname, fn, ...)
token.set_lua(csname, nr, ...)
end
-M.luadef ('minim:rememberalloc', function()
- allocations[token.scan_string()][token.scan_string()] = tex.count['allocationnumber']
+-- the current file
+M.luadef('minim:currentfile', function()
+ tex.sprint((status.filename:gsub('^.*/', '')))
+end)
+
+-- make pdf_string() available as \pdfstring{...}
+M.luadef('pdfstring', function() M.pdf_string(token.scan_string()) end)
+
+-- uselanguage hook callback
+cb.new_callback('uselanguage', 'simple')
+M.luadef('minim:uselanguagecallback', function()
+ local langname = token.scan_string()
+ cb.call_callback('uselanguage', langname)
end)
-- 1 dumping information to the format file
@@ -188,7 +331,7 @@ local function dump_saved_tables()
lua.bytecode[saved_tables_bytecode] = load(saved_tables)
end
-callback.register ('pre_dump', dump_saved_tables)
+cb.register ('pre_dump', dump_saved_tables)
--