From ad537519dede600d6d0a0542d07c64fbc1e82de3 Mon Sep 17 00:00:00 2001
From: Philipp Gesang <phg42.2a@gmail.com>
Date: Tue, 30 Apr 2013 12:54:32 +0200
Subject: [doc] fix typos in attr.dtx

---
 luatexbase-attr.dtx | 29 +++++++++++++++--------------
 1 file changed, 15 insertions(+), 14 deletions(-)

(limited to 'luatexbase-attr.dtx')

diff --git a/luatexbase-attr.dtx b/luatexbase-attr.dtx
index ded08b3..1a0df61 100644
--- a/luatexbase-attr.dtx
+++ b/luatexbase-attr.dtx
@@ -116,7 +116,7 @@ See the aforementioned source file(s) for copyright and licensing information.
 % \begin{abstract}
 % In addition to the registers existing in \tex and \etex, \luatex introduces
 % a new concept: attributes. This package takes care of attribute allocation
-% just like Plain TeX and LaTeX do for other registers, and also provides a
+% just like Plain \tex and \latex do for other registers, and also provides a
 % Lua interface.
 % \end{abstract}
 %
@@ -283,7 +283,7 @@ See the aforementioned source file(s) for copyright and licensing information.
 %    \subsubsection{Load supporting Lua module}
 %
 %    First load \pk{luatexbase-loader} (hence \pk{luatexbase-compat}), then
-%    the supporting Lua module. We make sure luatex.sty is loaded.
+%    the supporting Lua module. We make sure \verb|luatex.sty| is loaded.
 %
 %    \begin{macrocode}
 \begingroup\expandafter\expandafter\expandafter\endgroup
@@ -299,7 +299,7 @@ See the aforementioned source file(s) for copyright and licensing information.
 %
 %    \subsection{User macros}
 %
-%    The allocaton macro is merely a wrapper around the Lua function, but
+%    The allocation macro is merely a wrapper around the Lua function, but
 %    handles error and logging in \tex, for consistency with other allocation
 %    macros.
 %
@@ -353,13 +353,14 @@ module('luatexbase', package.seeall)
 attributes = {}
 %    \end{macrocode}
 %
-%    There are currently two functions that create a new attribute.One is in
-%    |oberdiek| bundle, the other is this one. We will hack a little in order
-%    to make them compatible. The other function uses |LuT@AllocAttribute| as
-%    attribute counter, we will keep it in sync with ours. A possible problem
-%    might also appear: the other function starts attribute allocation at 0,
-%    which might break luaotfload. We output an error if a new attribute has
-%    already been allocated with number 0.
+%    In the \luatex ecosystem there are currently two functions that create a
+%    new attribute.
+%    One is in |oberdiek| bundle, the other is this one. We will hack a little
+%    in order to make them compatible. The other function uses
+%    |LuT@AllocAttribute| as attribute counter, we will keep it in sync with
+%    ours. A possible problem might also appear: the other function starts
+%    attribute allocation at 0, which will break luaotfload. We output an
+%    error if a new attribute has already been allocated with number 0.
 %
 %    \begin{macrocode}
 local luatex_sty_counter = 'LuT@AllocAttribute'
@@ -374,10 +375,10 @@ if tex.count[luatex_sty_counter] then
 end
 %    \end{macrocode}
 %
-%    The allocaton function. Unlike other registers, allocate starting from 1.
-%    Some code (eg, font handling coming from Con\tex{}t) behaves strangely
-%    with \verb+\attribute0+ and since there is plenty of room here, it
-%    doesn't seem bad to ``loose'' one item in order to avoid this problem.
+%    The allocation function. Unlike other registers, allocate starting from 1.
+%    Some code (e.~g., font handling coming from Con\tex{}t) behaves strangely
+%    with \verb+\attribute0+ set, and since there is plenty of room here, it
+%    doesn't seem bad to ``lose'' one item in order to avoid this problem.
 %
 %    \begin{macrocode}
 local last_alloc = 0
-- 
cgit v1.2.3


From 3f94f09e4111c64e6a4e3495db8ce3ebd195a1c4 Mon Sep 17 00:00:00 2001
From: Philipp Gesang <phg42.2a@gmail.com>
Date: Tue, 30 Apr 2013 16:50:58 +0200
Subject: draft user whatsit allocator

---
 luatexbase-attr.dtx | 152 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 150 insertions(+), 2 deletions(-)

(limited to 'luatexbase-attr.dtx')

diff --git a/luatexbase-attr.dtx b/luatexbase-attr.dtx
index 1a0df61..977ea12 100644
--- a/luatexbase-attr.dtx
+++ b/luatexbase-attr.dtx
@@ -344,7 +344,21 @@ See the aforementioned source file(s) for copyright and licensing information.
 %
 %    \begin{macrocode}
 %<*luamodule>
+--- locals
+local nodenew           = node.new
+local nodesubtype       = node.subtype
+local nodetype          = node.id
+local stringfind        = string.find
+local stringformat      = string.format
+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"
+--- module declaration (deprecated in 5.2)
 module('luatexbase', package.seeall)
+luatexbase       = luatexbase or { }
+local luatexbase = luatexbase
 %    \end{macrocode}
 %
 %    This table holds the values of the allocated attributes, indexed by name.
@@ -368,7 +382,7 @@ 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 unuseable. Please report to the maintainer of luatex.sty")
+        .."luaotfload unusable. Please report to the maintainer of luatex.sty")
   else
     tex.count[luatex_sty_counter] = 0
   end
@@ -401,7 +415,7 @@ function new_attribute(name, silent)
     attributes[name] = last_alloc
     unset_attribute(name)
     if not silent then
-        texio.write_nl('log', string.format(
+        texiowrite_nl('log', string.format(
             'luatexbase.attributes[%q] = %d', name, last_alloc))
     end
     return last_alloc
@@ -417,6 +431,140 @@ function unset_attribute(name)
 end
 %    \end{macrocode}
 %
+%    User whatsit allocation (experimental).
+%
+%    \begin{macrocode}
+--- cf. luatexref-t.pdf, sect. 8.1.4.25
+local prefixsep           = "-"  --- make this @ for latex junkies?
+local user_whatsits       = { }  --- name -> id
+local whatsit_ids         = { }  --- id   -> name
+local current_whatsit     = 0
+local anonymous_whatsits  = 0
+local anonymous_prefix    = "anon"
+%    \end{macrocode}
+%
+%    The whatsit allocation is split into two functions:
+%    \verb|new_user_whatsit_id| registers a new id (an integer)
+%    and returns it. It is up to the user what he actually does
+%    with the return value.
+%
+%    Registering whatsits without a name, though supported, is
+%    not exactly good style. In these cases we generate a name
+%    from a counter.
+%
+%    In addition to the whatsit name, it is possible and even
+%    encouraged to specify the name of the package that will be
+%    using the whatsit as the second argument.
+%
+%    \begin{macrocode}
+--- string -> string -> int
+new_user_whatsit_id = function (name, package)
+    if name then
+        if package then name = package .. prefixsep .. name end
+    else -- anonymous
+        anonymous_whatsits = anonymous_whatsits + 1
+        name = anonymous_prefix
+            .. prefixsep
+            .. tostring(anonymous_whatsits)
+    end
+    local id = user_whatsits[name]
+    if id then --- what to do now?
+      texiowrite_nl(stringformat(
+        "replacing whatsit %s (%d)", name, id))
+    else --- new id
+      current_whatsit     = current_whatsit + 1
+      id                  = current_whatsit
+    end
+    user_whatsits[name] = id
+    whatsit_ids[id]     = name
+    texiowrite_nl(stringformat(
+        "new user-defined whatsit %d (%s)", id, name))
+    return id
+end
+luatexbase.new_user_whatsit_id = new_user_whatsit_id
+%    \end{macrocode}
+%
+%    \verb|new_user_whatsit| first registers a new id and
+%    then also creates the corresponding whatsit of subtype “user defined”.
+%    Return values are said node and its id.
+%
+%    \begin{macrocode}
+--- string -> string -> (node_t -> int)
+new_user_whatsit = function (name, package)
+    local id    = new_user_whatsit_id(name, package)
+    local wi    = nodenew(whatsit_t, user_defined_t)
+    wi.user_id = id
+    return wi, id
+end
+luatexbase.new_user_whatsit = new_user_whatsit
+%    \end{macrocode}
+%
+%    If one knows the name of a whatsit, its corresponding id
+%    can be retrieved by means of \verb|get_user_whatsit_id|.
+%
+%    \begin{macrocode}
+--- string -> string -> int
+get_user_whatsit_id = function (name, package)
+    if package then name = package .. prefixsep .. name end
+    return user_whatsits[name]
+end
+luatexbase.get_user_whatsit_id = get_user_whatsit_id
+%    \end{macrocode}
+%
+%    The inverse lookup is also possible via \verb|get_user_whatsit_name|.
+%    Here it finally becomes obvious why it is beneficial to supply a package
+%    name -- it adds information about who created and might be relying on the
+%    whatsit in question.
+%
+%    \begin{macrocode}
+--- string -> string -> int
+get_user_whatsit_name = function (id)
+    return whatsit_ids[id]
+end
+luatexbase.get_user_whatsit_name = get_user_whatsit_name
+%    \end{macrocode}
+%
+%    For the curious as well as the cautious who are interesting in
+%    what they are dealing with, we add a function that outputs the
+%    current allocation status to the terminal.
+%
+%    \begin{macrocode}
+--- string -> unit
+dump_registered_whatsits = function (package)
+    if package then
+        texiowrite_nl("(user whatsit allocation stats for " .. package)
+    else
+        texiowrite_nl("(user whatsit allocation stats")
+    end
+    texiowrite_nl(stringformat(
+        " ((total %d)\n  (anonymous %d))",
+        current_whatsit, anonymous_whatsits))
+    texio.write_nl" ("
+    local whatsit_list = { }
+    for name, val in next, user_whatsits do
+        if package then --- restrict to matching prefix
+            if stringfind(name, "^"..package.."%"..prefixsep) then
+              whatsit_list[#whatsit_list+1] = stringformat("(%s %d)", name, val)
+            end
+        else
+            whatsit_list[#whatsit_list+1] = stringformat("(%s %d)", name, val)
+        end
+    end
+    texiowrite(table.concat(whatsit_list, "\n  "))
+    texiowrite"))"
+end
+luatexbase.dump_registered_whatsits = dump_registered_whatsits
+%    \end{macrocode}
+%    Lastly, we define a couple synonyms for convenience.
+%    \begin{macrocode}
+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{macrocode}
+%
 %    \begin{macrocode}
 %</luamodule>
 %    \end{macrocode}
-- 
cgit v1.2.3


From ec9d2665e95c90f27f2529072a0616f7156ea13f Mon Sep 17 00:00:00 2001
From: Philipp Gesang <phg42.2a@gmail.com>
Date: Thu, 2 May 2013 14:46:54 +0200
Subject: drop calls to deprecated `module()`

---
 luatexbase-attr.dtx | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

(limited to 'luatexbase-attr.dtx')

diff --git a/luatexbase-attr.dtx b/luatexbase-attr.dtx
index 977ea12..859803e 100644
--- a/luatexbase-attr.dtx
+++ b/luatexbase-attr.dtx
@@ -355,10 +355,10 @@ local texiowrite        = texio.write
 --- luatex internal types
 local whatsit_t         = nodetype"whatsit"
 local user_defined_t    = nodesubtype"user_defined"
---- module declaration (deprecated in 5.2)
-module('luatexbase', package.seeall)
+
 luatexbase       = luatexbase or { }
 local luatexbase = luatexbase
+
 %    \end{macrocode}
 %
 %    This table holds the values of the allocated attributes, indexed by name.
@@ -396,7 +396,7 @@ end
 %
 %    \begin{macrocode}
 local last_alloc = 0
-function new_attribute(name, silent)
+local function new_attribute(name, silent)
     if last_alloc >= 65535 then
         if silent then
             return -1
@@ -420,15 +420,17 @@ function new_attribute(name, silent)
     end
     return last_alloc
 end
+luatexbase.new_attribute = new_attribute
 %    \end{macrocode}
 %
 %    Unset an attribute the correct way depending on \luatex's version.
 %
 %    \begin{macrocode}
 local unset_value = (luatexbase.luatexversion < 37) and -1 or -2147483647
-function unset_attribute(name)
+local function unset_attribute(name)
     tex.setattribute(attributes[name], unset_value)
 end
+luatexbase.unset_attribute = unset_attribute
 %    \end{macrocode}
 %
 %    User whatsit allocation (experimental).
@@ -458,7 +460,7 @@ local anonymous_prefix    = "anon"
 %
 %    \begin{macrocode}
 --- string -> string -> int
-new_user_whatsit_id = function (name, package)
+local new_user_whatsit_id = function (name, package)
     if name then
         if package then name = package .. prefixsep .. name end
     else -- anonymous
@@ -490,7 +492,7 @@ luatexbase.new_user_whatsit_id = new_user_whatsit_id
 %
 %    \begin{macrocode}
 --- string -> string -> (node_t -> int)
-new_user_whatsit = function (name, package)
+local new_user_whatsit = function (name, package)
     local id    = new_user_whatsit_id(name, package)
     local wi    = nodenew(whatsit_t, user_defined_t)
     wi.user_id = id
@@ -504,7 +506,7 @@ luatexbase.new_user_whatsit = new_user_whatsit
 %
 %    \begin{macrocode}
 --- string -> string -> int
-get_user_whatsit_id = function (name, package)
+local get_user_whatsit_id = function (name, package)
     if package then name = package .. prefixsep .. name end
     return user_whatsits[name]
 end
@@ -518,7 +520,7 @@ luatexbase.get_user_whatsit_id = get_user_whatsit_id
 %
 %    \begin{macrocode}
 --- string -> string -> int
-get_user_whatsit_name = function (id)
+local get_user_whatsit_name = function (id)
     return whatsit_ids[id]
 end
 luatexbase.get_user_whatsit_name = get_user_whatsit_name
@@ -530,7 +532,7 @@ luatexbase.get_user_whatsit_name = get_user_whatsit_name
 %
 %    \begin{macrocode}
 --- string -> unit
-dump_registered_whatsits = function (package)
+local dump_registered_whatsits = function (package)
     if package then
         texiowrite_nl("(user whatsit allocation stats for " .. package)
     else
-- 
cgit v1.2.3


From d17162ae3da3b7bbf5272322061d9c824eccf782 Mon Sep 17 00:00:00 2001
From: Philipp Gesang <phg42.2a@gmail.com>
Date: Thu, 2 May 2013 16:39:24 +0200
Subject: avoid shadowing locals

---
 luatexbase-attr.dtx | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

(limited to 'luatexbase-attr.dtx')

diff --git a/luatexbase-attr.dtx b/luatexbase-attr.dtx
index 859803e..209ffd6 100644
--- a/luatexbase-attr.dtx
+++ b/luatexbase-attr.dtx
@@ -356,15 +356,23 @@ local texiowrite        = texio.write
 local whatsit_t         = nodetype"whatsit"
 local user_defined_t    = nodesubtype"user_defined"
 
-luatexbase       = luatexbase or { }
-local luatexbase = luatexbase
+luatexbase              = luatexbase or { }
+local luatexbase        = luatexbase
 
 %    \end{macrocode}
 %
 %    This table holds the values of the allocated attributes, indexed by name.
 %
 %    \begin{macrocode}
-attributes = {}
+luatexbase.attributes   = luatexbase.attributes or { }
+local attributes        = luatexbase.attributes
+%    \end{macrocode}
+%
+%    Scoping: we use locals for the attribute functions.
+%
+%    \begin{macrocode}
+local new_attribute
+local unset_attribute
 %    \end{macrocode}
 %
 %    In the \luatex ecosystem there are currently two functions that create a
@@ -396,7 +404,7 @@ end
 %
 %    \begin{macrocode}
 local last_alloc = 0
-local function new_attribute(name, silent)
+function new_attribute(name, silent)
     if last_alloc >= 65535 then
         if silent then
             return -1
@@ -427,7 +435,7 @@ luatexbase.new_attribute = new_attribute
 %
 %    \begin{macrocode}
 local unset_value = (luatexbase.luatexversion < 37) and -1 or -2147483647
-local function unset_attribute(name)
+function unset_attribute(name)
     tex.setattribute(attributes[name], unset_value)
 end
 luatexbase.unset_attribute = unset_attribute
-- 
cgit v1.2.3


From 2596b53e7577696440c84c1209a9f548cd6037ca Mon Sep 17 00:00:00 2001
From: Philipp Gesang <phg42.2a@gmail.com>
Date: Thu, 2 May 2013 20:56:29 +0200
Subject: store user whatsits by package

---
 luatexbase-attr.dtx | 116 +++++++++++++++++++++++++++++++++-------------------
 1 file changed, 74 insertions(+), 42 deletions(-)

(limited to 'luatexbase-attr.dtx')

diff --git a/luatexbase-attr.dtx b/luatexbase-attr.dtx
index 209ffd6..f1a0f7a 100644
--- a/luatexbase-attr.dtx
+++ b/luatexbase-attr.dtx
@@ -350,15 +350,32 @@ 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
-
+%    \end{macrocode}
+%
+%    We improvise a basic logging facility.
+%
+%    \begin{macrocode}
+local reporter = function (log, category, ...)
+    if log == true then
+        texiowrite_nl("log", "("..category..") ")
+        texiowrite("log", stringformat(...))
+    else
+        texiowrite_nl("("..category..") ")
+        texiowrite(stringformat(...))
+    end
+end
+local warning = function (...) reporter (false, "warning", ...) end
+----- info    = function (...) reporter (false, "info",    ...) end
+local log     = function (...) reporter (true,  "log",     ...) end
 %    \end{macrocode}
 %
 %    This table holds the values of the allocated attributes, indexed by name.
@@ -423,8 +440,7 @@ function new_attribute(name, silent)
     attributes[name] = last_alloc
     unset_attribute(name)
     if not silent then
-        texiowrite_nl('log', string.format(
-            'luatexbase.attributes[%q] = %d', name, last_alloc))
+        log('luatexbase.attributes[%q] = %d', name, last_alloc)
     end
     return last_alloc
 end
@@ -445,9 +461,10 @@ luatexbase.unset_attribute = unset_attribute
 %
 %    \begin{macrocode}
 --- cf. luatexref-t.pdf, sect. 8.1.4.25
-local prefixsep           = "-"  --- make this @ for latex junkies?
-local user_whatsits       = { }  --- name -> id
-local whatsit_ids         = { }  --- id   -> name
+local user_whatsits       = {    --- (package, (name, id hash)) hash
+    __unassociated = { },        --- those without package name
+}
+local whatsit_ids         = { }  --- (id, (name * package)) hash
 local current_whatsit     = 0
 local anonymous_whatsits  = 0
 local anonymous_prefix    = "anon"
@@ -470,25 +487,31 @@ local anonymous_prefix    = "anon"
 --- string -> string -> int
 local new_user_whatsit_id = function (name, package)
     if name then
-        if package then name = package .. prefixsep .. name end
+        if not package then
+            package = unassociated
+        end
     else -- anonymous
         anonymous_whatsits = anonymous_whatsits + 1
-        name = anonymous_prefix
-            .. prefixsep
-            .. tostring(anonymous_whatsits)
+        package = unassociated
+        name    = anonymous_prefix .. tostring(anonymous_whatsits)
     end
-    local id = user_whatsits[name]
-    if id then --- what to do now?
-      texiowrite_nl(stringformat(
-        "replacing whatsit %s (%d)", name, id))
+
+    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
-      id                  = current_whatsit
+        current_whatsit     = current_whatsit + 1
+        id                  = current_whatsit
+        whatsitdata[name]   = id
+        whatsit_ids[id]     = { name, package }
     end
-    user_whatsits[name] = id
-    whatsit_ids[id]     = name
-    texiowrite_nl(stringformat(
-        "new user-defined whatsit %d (%s)", id, name))
+    log("new user-defined whatsit %d (%s:%s)", id, package, name)
     return id
 end
 luatexbase.new_user_whatsit_id = new_user_whatsit_id
@@ -503,7 +526,7 @@ luatexbase.new_user_whatsit_id = new_user_whatsit_id
 local new_user_whatsit = function (name, package)
     local id    = new_user_whatsit_id(name, package)
     local wi    = nodenew(whatsit_t, user_defined_t)
-    wi.user_id = id
+    wi.user_id  = id
     return wi, id
 end
 luatexbase.new_user_whatsit = new_user_whatsit
@@ -515,8 +538,10 @@ luatexbase.new_user_whatsit = new_user_whatsit
 %    \begin{macrocode}
 --- string -> string -> int
 local get_user_whatsit_id = function (name, package)
-    if package then name = package .. prefixsep .. name end
-    return user_whatsits[name]
+    if not package then
+        package = unassociated
+    end
+    return user_whatsits[package][name]
 end
 luatexbase.get_user_whatsit_id = get_user_whatsit_id
 %    \end{macrocode}
@@ -524,12 +549,13 @@ luatexbase.get_user_whatsit_id = get_user_whatsit_id
 %    The inverse lookup is also possible via \verb|get_user_whatsit_name|.
 %    Here it finally becomes obvious why it is beneficial to supply a package
 %    name -- it adds information about who created and might be relying on the
-%    whatsit in question.
+%    whatsit in question. First return value is the whatsit name, the second
+%    the package identifier it was registered with.
 %
 %    \begin{macrocode}
---- string -> string -> int
+--- int -> (string, string)
 local get_user_whatsit_name = function (id)
-    return whatsit_ids[id]
+    return tableunpack(whatsit_ids[id])
 end
 luatexbase.get_user_whatsit_name = get_user_whatsit_name
 %    \end{macrocode}
@@ -540,26 +566,32 @@ luatexbase.get_user_whatsit_name = get_user_whatsit_name
 %
 %    \begin{macrocode}
 --- string -> unit
-local dump_registered_whatsits = function (package)
-    if package then
-        texiowrite_nl("(user whatsit allocation stats for " .. package)
+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")
-    end
-    texiowrite_nl(stringformat(
-        " ((total %d)\n  (anonymous %d))",
-        current_whatsit, anonymous_whatsits))
-    texio.write_nl" ("
-    local whatsit_list = { }
-    for name, val in next, user_whatsits do
-        if package then --- restrict to matching prefix
-            if stringfind(name, "^"..package.."%"..prefixsep) then
-              whatsit_list[#whatsit_list+1] = stringformat("(%s %d)", name, val)
+        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
-        else
-            whatsit_list[#whatsit_list+1] = stringformat("(%s %d)", name, val)
         end
     end
+    texiowrite_nl" ("
     texiowrite(table.concat(whatsit_list, "\n  "))
     texiowrite"))"
 end
-- 
cgit v1.2.3


From d95b4e16d9985c89c75b798c72acb795fd4813f0 Mon Sep 17 00:00:00 2001
From: Philipp Gesang <phg42.2a@gmail.com>
Date: Thu, 2 May 2013 21:05:33 +0200
Subject: emit warning when defining anonymous whatsits

---
 luatexbase-attr.dtx | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'luatexbase-attr.dtx')

diff --git a/luatexbase-attr.dtx b/luatexbase-attr.dtx
index f1a0f7a..5a4960c 100644
--- a/luatexbase-attr.dtx
+++ b/luatexbase-attr.dtx
@@ -492,6 +492,8 @@ local new_user_whatsit_id = function (name, package)
         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
-- 
cgit v1.2.3


From 00ba44f1939220af84ad885d1ba2f1f974bd7eb7 Mon Sep 17 00:00:00 2001
From: Philipp Gesang <phg42.2a@gmail.com>
Date: Thu, 2 May 2013 21:45:14 +0200
Subject: emit warning after 2^53 user whatsits

---
 luatexbase-attr.dtx | 6 ++++++
 1 file changed, 6 insertions(+)

(limited to 'luatexbase-attr.dtx')

diff --git a/luatexbase-attr.dtx b/luatexbase-attr.dtx
index 5a4960c..7c8f5b9 100644
--- a/luatexbase-attr.dtx
+++ b/luatexbase-attr.dtx
@@ -465,6 +465,7 @@ 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"
@@ -509,6 +510,11 @@ local new_user_whatsit_id = function (name, package)
         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 }
-- 
cgit v1.2.3


From 9bc0be2978b9c87eaf111d93339378a9e3b5bbc9 Mon Sep 17 00:00:00 2001
From: Philipp Gesang <phg42.2a@gmail.com>
Date: Thu, 2 May 2013 22:05:22 +0200
Subject: accept node as argument for function ``get_user_whatsit_name``

---
 luatexbase-attr.dtx | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

(limited to 'luatexbase-attr.dtx')

diff --git a/luatexbase-attr.dtx b/luatexbase-attr.dtx
index 7c8f5b9..54c26f7 100644
--- a/luatexbase-attr.dtx
+++ b/luatexbase-attr.dtx
@@ -561,8 +561,14 @@ luatexbase.get_user_whatsit_id = get_user_whatsit_id
 %    the package identifier it was registered with.
 %
 %    \begin{macrocode}
---- int -> (string, string)
-local get_user_whatsit_name = function (id)
+--- int | node -> (string, string)
+local get_user_whatsit_name = function (asked)
+    local id
+    if type(asked) == "number" then
+        id = asked
+    else --- node
+        id = asked.user_id
+    end
     return tableunpack(whatsit_ids[id])
 end
 luatexbase.get_user_whatsit_name = get_user_whatsit_name
-- 
cgit v1.2.3


From c5837a5e38f2324ce7960840b609c290337ff160 Mon Sep 17 00:00:00 2001
From: Philipp Gesang <phg42.2a@gmail.com>
Date: Thu, 2 May 2013 22:15:35 +0200
Subject: add warning if ``get_user_whatsit_name`` is called with unknown id
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

another of Stephan Hennig’s suggestions
---
 luatexbase-attr.dtx | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

(limited to 'luatexbase-attr.dtx')

diff --git a/luatexbase-attr.dtx b/luatexbase-attr.dtx
index 54c26f7..60ca026 100644
--- a/luatexbase-attr.dtx
+++ b/luatexbase-attr.dtx
@@ -560,6 +560,9 @@ luatexbase.get_user_whatsit_id = get_user_whatsit_id
 %    whatsit in question. First return value is the whatsit name, the second
 %    the package identifier it was registered with.
 %
+%    We issue a warning and return empty strings in case the asked whatsit is
+%    unregistered.
+%
 %    \begin{macrocode}
 --- int | node -> (string, string)
 local get_user_whatsit_name = function (asked)
@@ -569,7 +572,12 @@ local get_user_whatsit_name = function (asked)
     else --- node
         id = asked.user_id
     end
-    return tableunpack(whatsit_ids[id])
+    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
 %    \end{macrocode}
-- 
cgit v1.2.3


From f7103fd0390b98c9ad4e74d8624376ee5b402a2b Mon Sep 17 00:00:00 2001
From: Philipp Gesang <phg42.2a@gmail.com>
Date: Sat, 4 May 2013 01:22:25 +0200
Subject: have ``new_user_whatsit`` return a generating function

---
 luatexbase-attr.dtx | 45 ++++++++++++++++++++++++++++++++-------------
 1 file changed, 32 insertions(+), 13 deletions(-)

(limited to 'luatexbase-attr.dtx')

diff --git a/luatexbase-attr.dtx b/luatexbase-attr.dtx
index 60ca026..faa0261 100644
--- a/luatexbase-attr.dtx
+++ b/luatexbase-attr.dtx
@@ -345,7 +345,8 @@ See the aforementioned source file(s) for copyright and licensing information.
 %    \begin{macrocode}
 %<*luamodule>
 --- locals
-local nodenew           = node.new
+local copynode          = node.copy
+local newnode           = node.new
 local nodesubtype       = node.subtype
 local nodetype          = node.id
 local stringfind        = string.find
@@ -525,19 +526,21 @@ end
 luatexbase.new_user_whatsit_id = new_user_whatsit_id
 %    \end{macrocode}
 %
-%    \verb|new_user_whatsit| first registers a new id and
-%    then also creates the corresponding whatsit of subtype “user defined”.
-%    Return values are said node and its id.
+%    \verb|new_user_whatsit| first registers a new id and then also
+%    creates the corresponding whatsit of subtype “user defined”.
+%    We return a nullary function that delivers copies of the whatsit.
 %
 %    \begin{macrocode}
---- string -> string -> (node_t -> int)
+--- string -> string -> (unit -> node_t, int)
 local new_user_whatsit = function (name, package)
-    local id    = new_user_whatsit_id(name, package)
-    local wi    = nodenew(whatsit_t, user_defined_t)
-    wi.user_id  = id
-    return wi, id
+    local id         = new_user_whatsit_id(name, package)
+    local whatsit    = newnode(whatsit_t, user_defined_t)
+    whatsit.user_id  = id
+    --- unit -> node_t
+    return function ( ) return copynode(whatsit) end, id
 end
-luatexbase.new_user_whatsit = new_user_whatsit
+luatexbase.new_user_whatsit         = new_user_whatsit
+luatexbase.new_user_whatsit_factory = new_user_whatsit --- for Stephan
 %    \end{macrocode}
 %
 %    If one knows the name of a whatsit, its corresponding id
@@ -564,11 +567,15 @@ luatexbase.get_user_whatsit_id = get_user_whatsit_id
 %    unregistered.
 %
 %    \begin{macrocode}
---- int | node -> (string, string)
+--- 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.id
     else --- node
         id = asked.user_id
     end
@@ -613,9 +620,20 @@ local dump_registered_whatsits = function (asked_package)
             end
         end
     end
+
     texiowrite_nl" ("
-    texiowrite(table.concat(whatsit_list, "\n  "))
-    texiowrite"))"
+    --- 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
 %    \end{macrocode}
@@ -623,6 +641,7 @@ luatexbase.dump_registered_whatsits = dump_registered_whatsits
 %    \begin{macrocode}
 luatexbase.newattribute            = new_attribute
 luatexbase.newuserwhatsit          = new_user_whatsit
+luatexbase.newuserwhatsitfactory   = new_user_whatsit_factory
 luatexbase.newuserwhatsitid        = new_user_whatsit_id
 luatexbase.getuserwhatsitid        = get_user_whatsit_id
 luatexbase.getuserwhatsitname      = get_user_whatsit_name
-- 
cgit v1.2.3


From 94fd32b7dd09f9c3caca57a24ca7519be66b012e Mon Sep 17 00:00:00 2001
From: Philipp Gesang <phg42.2a@gmail.com>
Date: Sat, 4 May 2013 01:25:40 +0200
Subject: fix ``get_user_whatsit_name``

---
 luatexbase-attr.dtx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'luatexbase-attr.dtx')

diff --git a/luatexbase-attr.dtx b/luatexbase-attr.dtx
index faa0261..aa5e987 100644
--- a/luatexbase-attr.dtx
+++ b/luatexbase-attr.dtx
@@ -575,7 +575,7 @@ local get_user_whatsit_name = function (asked)
     elseif type(asked) == "function" then
         --- node generator
         local n = asked()
-        id = n.id
+        id = n.user_id
     else --- node
         id = asked.user_id
     end
-- 
cgit v1.2.3

