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
|
% This is used by OpTeX packages minim-mp, minim-pdf, see http://petr.olsak.net/optex
% minim.opm, Michal Vlasák <lahcim8@gmail.com>, 2022
% see also https://github.com/vlasakm/optex-minim
\_def\_optexminim_version{0.1}
\_codedecl \optexminim_loaded {Minim compatibility for \OpTeX/ (v\_optexminim_version)}
\_doc
When we want to use minim with \OpTeX/, we need to accomodate for their
differences. Particularly in allocations. Because of Esger Renkema's
graciousness, minim has been modified in ways that make it easier to
integrate with \OpTeX/. So even when the two formats normally disagree on a
lot of core things (allocations, callbacks) they can end up working together.
\OpTeX/ defines most allocation macros in `alloc.opm` and some Lua
allocation functions in `optex.lua`. Minim \"packages" are not standalone,
they all depend on core routines defined in `minim-alloc.tex` and
`minim-alloc.lua` respectively. Minim as a format preloads a stripped
version of `etex.src` so the Lua code makes some assumptions about that
(i.e. expects local allocators).
Both \OpTeX/ and minim want to make it possible to register more functions
for a single callback, by chaining their calls and `callback.register()`ing
only a proxy function. While minim stays close to the `callback` interface
from \LuaTeX/, \OpTeX/ is a subset of the \LaTeX/ `luatexbase` interface.
But minim now can work on top of ltluatex by using its functions instead of
`callback.register()`, so we don't have to do anything to support it in
\OpTeX/!
Firstly, because we only change what is defined by others, we actually need
a dummy macro for `\_codedecl`, to prevent loading this file more than once.
\_cod
\_catcode`\@=11
% dummy macro to signalize that we are loaded
\_let\optexminim_loaded=\empty
\_doc
In general, there are four allocator types expected by minim:
\begitems
* Knuth allocators from `plain.tex` (like `\newcount`). These are already
defined by \OpTeX/. Although minim itself sets the old `\allocationnumber`
counter, which is not even defined in \OpTeX/.
* Global allocators from `etex.src` (like `\globcount`). These are not
defined by \OpTeX/, since they no longer make sense (\LuaTeX/ doesn't use
sparse arrays for registers). Minim defines them to be the classic Knuth
allocators if it doesn't find them on the TeX side, but expects them from
the Lua side.
* Local allocators from `etex.src` (like `\loccount`). Concept of local
allocators is completely missing in \OpTeX/. The semantics of local
allocation in Lua is weird too, so we try to avoid these, since minim also
doesn't define their Lua variants.
* \LuaTeX/ allocators from `ltluatex.tex` (like `\newattribute`). Subset of
these is in \OpTeX/ (only atributes, which are also allocatable in Lua, and
catcode tables). But minim tries to be compatible with \LaTeX/ and patches
its routines if it detects them.
\enditems
For defining \TeX/ commands implemented in Lua, \OpTeX/ has
`define_lua_command`, which actually does the allocation and definition at
the same time, and allows to do so only from Lua end.
Historically (in my opinion unfortunately) \LaTeX/ made the allocations of
these functions available from \TeX/ end, and the \"lua define" operation is
thus a two step process which involves synchronization with \TeX/.
`minim-alloc` actually defines a `luadef` function which is like
`define_lua_command`, but is backed by the minim allocator. To make this
work, we just need to set the \LaTeX/ register to the index of last
allocated function, since it allocates at counter plus one. Then minim will
start where \OpTeX/ stopped, and we will later define `define_lua_command`
to be just minim's `luadef`.
We tell the number of allocated function by going through the table of
actually used functions. This is not that robust, because while
`define_lua_command` allocates sequentially, the provided functions may be
`nil`, which breaks the code below.
\_cod
\_newcount\allocationnumber
% for synchronisation of allocated Lua functions
\_ea\_newcount\_csname e@alloc@luafunction@count\_endcsname
\directlua{
local function_table = lua.get_functions_table()
% minim allocates at count + 1 for "new" allocators, so this works
tex.setcount("global", "e@alloc@luafunction@count", \csstring\#function_table)
}
\_doc
Both \LaTeX/ and the minim inspired catcode table allocators initialize the
catcode tables with `\initcatcodetable` (i.e. ini\TeX/ catcodes). \OpTeX/
merely allocates the registers. \LuaTeX/ doesn't allow to activate
unitialized catcode table, therefore activation with either
`\initcatcodetable` or `\savecatcodetable` is necessary before use. To
ensure compatibility with foreign macros, we also issue `\initcatcodetable`
on allocation in the public version of `\newcatcodetable`.
\_cod
\_def\newcatcodetable#1{\_newcatcodetable#1\_initcatcodetable#1}
\_doc
We also get PDF resources out of the way now. Minim is ready to use \OpTeX's
PDF resource management, but also has compatibility layer for PGF, which is
not needed in \OpTeX/. We prevent loading the problematic \TeX/ file.
\_cod
\_let\minimpdfresourcesloaded=\_empty
\_doc
The preparations are over. We load `minim-alloc.tex`.
\_cod
\input minim-alloc
\_doc
By now, the Knuthian allocators are dealt with. \eTeX/ global and local
allocators are undefined, but the global ones are expected in minim's Lua
code with their hardcoded counter register numbers. This is unacceptable,
since in this range (`\count260` to `\count266`) \OpTeX/ has already made
allocations. Thus we need to replace these Lua functions with similar
definitions. For some, \OpTeX/ also has a different idea whether the counter
represent the last or next allocated register number, so we correct that as
well.
We also don't forget to actually set `define_lua_command` to be minim's
`luadef`.
\_cod
\directlua{
local minimalloc = require("minim-alloc")
define_lua_command = minimalloc.luadef
% these are allocators already defined in OpTeX that we need to repair
local toreplace = {
"count",
"dimen",
"skip",
"muskip",
"box",
"toks",
"marks",
"attribute",
"catcodetable",
}
for _, alloc in ipairs(toreplace) do
local cache = {}
local countername = string.format("_\_pcent salloc", alloc)
minimalloc["new_"..alloc] = function(id)
local n = cache[id]
if not n then
n = tex.getcount(countername) + 1
tex.setcount("global", countername, n)
if id then
cache[id] = n
end
minimalloc.log(
"\_nbb\_pcent s\_pcent d : \_pcent s", alloc, n, id or "<unnamed>")
end
return n
end
end
}
\_doc
We also need to do something about `minim-hooks.tex`, which hooks into
`\shipout`, but the default \OpTeX/ output routine (and perhaps also the
user ones) use `\_shipout`.
Minim also adds to `\everypar`, but that is fine.
\_cod
\_let\shipout\_shipout
\input minim-hooks
\_catcode`\:=11
\_let\_shipout\minim:shipout:new
% catcodes changes don't propage, since this file is loaded with \opinput
\_endcode
|