1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
|
--
-- This is file `attr.lua',
-- generated with the docstrip utility.
--
-- The original source files were:
--
-- luatexbase-attr.dtx (with options: `luamodule')
--
-- See the aforementioned source file(s) for copyright and licensing information.
--
--- locals
local copynode = node.copy
local newnode = node.new
local nodesubtype = node.subtype
local nodetype = node.id
local stringfind = string.find
local stringformat = string.format
local tableunpack = unpack or table.unpack
local texiowrite_nl = texio.write_nl
local texiowrite = texio.write
--- luatex internal types
local whatsit_t = nodetype"whatsit"
local user_defined_t = nodesubtype"user_defined"
local unassociated = "__unassociated"
luatexbase = luatexbase or { }
local luatexbase = luatexbase
local err, warning, info, log = luatexbase.provides_module({
name = "luatexbase-attr",
version = 0.6,
date = "2013/05/11",
description = "Attributes allocation for LuaTeX",
author = "Elie Roux, Manuel Pegourie-Gonnard and Philipp Gesang",
copyright = "Elie Roux, Manuel Pegourie-Gonnard and Philipp Gesang",
license = "CC0",
})
luatexbase.attributes = luatexbase.attributes or { }
local attributes = luatexbase.attributes
local new_attribute
local unset_attribute
local luatex_sty_counter = 'LuT@AllocAttribute'
if tex.count[luatex_sty_counter] then
if tex.count[luatex_sty_counter] > -1 then
error("luatexbase error: attribute 0 has already been set by \newattribute"
.."macro from luatex.sty, not belonging to this package, this makes"
.."luaotfload unusable. Please report to the maintainer of luatex.sty")
else
tex.count[luatex_sty_counter] = 0
end
end
local last_alloc = 0
function new_attribute(name, silent)
if last_alloc >= 65535 then
if silent then
return -1
else
error("No room for a new \\attribute", 1)
end
end
local lsc = tex.count[luatex_sty_counter]
if lsc and lsc > last_alloc then
last_alloc = lsc
end
last_alloc = last_alloc + 1
if lsc then
tex.setcount('global', luatex_sty_counter, last_alloc)
end
attributes[name] = last_alloc
unset_attribute(name)
if not silent then
log('luatexbase.attributes[%q] = %d', name, last_alloc)
end
return last_alloc
end
luatexbase.new_attribute = new_attribute
local unset_value = (luatexbase.luatexversion < 37) and -1 or -2147483647
function unset_attribute(name)
tex.setattribute(attributes[name], unset_value)
end
luatexbase.unset_attribute = unset_attribute
luatexbase.get_unset_value = function () return unset_value end
--- cf. luatexref-t.pdf, sect. 8.1.4.25
local user_whatsits = { --- (package, (name, id hash)) hash
__unassociated = { }, --- those without package name
}
local whatsit_ids = { } --- (id, (name * package)) hash
local whatsit_cap = 2^53 --- Lua numbers are doubles
local current_whatsit = 0
local anonymous_whatsits = 0
local anonymous_prefix = "anon"
--- string -> string -> int
local new_user_whatsit_id = function (name, package)
if name then
if not package then
package = unassociated
end
else -- anonymous
anonymous_whatsits = anonymous_whatsits + 1
warning("defining anonymous user whatsit no. %d", anonymous_whatsits)
warning("dear package authors, please name your whatsits!")
package = unassociated
name = anonymous_prefix .. tostring(anonymous_whatsits)
end
local whatsitdata = user_whatsits[package]
if not whatsitdata then
whatsitdata = { }
user_whatsits[package] = whatsitdata
end
local id = whatsitdata[name]
if id then --- warning
warning("replacing whatsit %s:%s (%d)", package, name, id)
else --- new id
current_whatsit = current_whatsit + 1
if current_whatsit >= whatsit_cap then
warning("maximum of %d integral user whatsit ids reached",
whatsit_cap)
warning("further whatsit allocation may be inconsistent")
end
id = current_whatsit
whatsitdata[name] = id
whatsit_ids[id] = { name, package }
end
log("new user-defined whatsit %d (%s:%s)", id, package, name)
return id
end
luatexbase.new_user_whatsit_id = new_user_whatsit_id
--- (string | node_t) -> string -> ((unit -> node_t) * int)
local new_user_whatsit = function (req, package)
local id, whatsit
if type(req) == "string" then
id = new_user_whatsit_id(req, package)
whatsit = newnode(whatsit_t, user_defined_t)
whatsit.user_id = id
elseif req.id == whatsit_t and req.subtype == user_defined_t then
id = req.user_id
whatsit = copynode(req)
if not whatsit_ids[id] then
warning("whatsit id %d unregistered; "
.. "inconsistencies may arise", id)
end
end
return function () return copynode(whatsit) end, id
end
luatexbase.new_user_whatsit = new_user_whatsit
--- string -> string -> int
local get_user_whatsit_id = function (name, package)
if not package then
package = unassociated
end
return user_whatsits[package][name]
end
luatexbase.get_user_whatsit_id = get_user_whatsit_id
--- int | fun | node -> (string, string)
local get_user_whatsit_name = function (asked)
local id
if type(asked) == "number" then
id = asked
elseif type(asked) == "function" then
--- node generator
local n = asked()
id = n.user_id
else --- node
id = asked.user_id
end
local metadata = whatsit_ids[id]
if not metadata then -- unknown
warning("whatsit id %d unregistered; inconsistencies may arise", id)
return "", ""
end
return tableunpack(metadata)
end
luatexbase.get_user_whatsit_name = get_user_whatsit_name
--- string -> unit
local dump_registered_whatsits = function (asked_package)
local whatsit_list = { }
if asked_package then
local whatsitdata = user_whatsits[asked_package]
if not whatsitdata then
error("(no user whatsits registered for package %s)",
asked_package)
return
end
texiowrite_nl("(user whatsit allocation stats for " .. asked_package)
for name, id in next, whatsitdata do
whatsit_list[#whatsit_list+1] =
stringformat("(%s:%s %d)", asked_package, name, id)
end
else
texiowrite_nl("(user whatsit allocation stats")
texiowrite_nl(stringformat(" ((total %d)\n (anonymous %d))",
current_whatsit, anonymous_whatsits))
for package, whatsitdata in next, user_whatsits do
for name, id in next, whatsitdata do
whatsit_list[#whatsit_list+1] =
stringformat("(%s:%s %d)", package, name, id)
end
end
end
texiowrite_nl" ("
--- in an attempt to be clever the texio.write* functions
--- mess up line breaking, so concatenation is unusable ...
local first = true
for i=1, #whatsit_list do
if first then
first = false
else -- indent
texiowrite_nl" "
end
texiowrite(whatsit_list[i])
end
texiowrite"))\n"
end
luatexbase.dump_registered_whatsits = dump_registered_whatsits
luatexbase.newattribute = new_attribute
luatexbase.newuserwhatsit = new_user_whatsit
luatexbase.newuserwhatsitid = new_user_whatsit_id
luatexbase.getuserwhatsitid = get_user_whatsit_id
luatexbase.getuserwhatsitname = get_user_whatsit_name
luatexbase.dumpregisteredwhatsits = dump_registered_whatsits
--
-- End of File `attr.lua'.
|