From 575ab7d0e7534edd510bbc89a2ef4b04582af591 Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Fri, 4 Mar 2022 03:01:04 +0000 Subject: CTAN sync 202203040301 --- macros/luatex/generic/minim/minim-alloc.lua | 183 +++++++++++++++++++++++++--- 1 file changed, 163 insertions(+), 20 deletions(-) (limited to 'macros/luatex/generic/minim/minim-alloc.lua') 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] = '') + 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) -- -- cgit v1.2.3