Skip to content

Commit 74c0e05

Browse files
authored
Allocate (#2460)
* allocateRegister avoids allocating a \count... slot that is already used; NewCounter avoids redefining a counter that already was defined; uses internal arabic macro for \the<ctr> * Define \lx@alloc@ as safe version of plain's \alloc@, latex's \e@alloc; defines internal \lx@counter@arabic * Use new \lx@alloc@ for plain's \alloc@, latex's \e@alloc
1 parent 1301850 commit 74c0e05

File tree

4 files changed

+46
-16
lines changed

4 files changed

+46
-16
lines changed

lib/LaTeXML/Engine/LaTeX.pool.ltxml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ Let('\magnification', '\@undefined');
3636
Let('\@empty', '\lx@empty');
3737
Let('\@ifundefined', '\lx@ifundefined');
3838

39+
# Use Package's register allocation to avoid allocating same slot twice; and ALWAYS have room!
40+
DefMacro('\e@alloc{}{}{}{}{}{}', '\lx@alloc@{#1}{#3}{#2}{#6}', locked => 1);
41+
DefMacro('\e@ch@ck{}{}{}{}', '', locked => 1);
42+
3943
#**********************************************************************
4044
# Basic \documentclass & \documentstyle
4145

@@ -771,6 +775,7 @@ sub beginAppendices {
771775
else {
772776
NewCounter($counter, 'document', idprefix => 'A');
773777
DefMacroI('\the' . $counter, undef, '\Alph{' . $counter . '}', scope => 'global'); }
778+
SetCounter($counter => Number(0)); # In case register was already defined
774779
AssignMapping('counter_for_type', appendix => $counter);
775780
Let(T_CS('\\' . $counter), T_CS('\@@appendix'), 'global');
776781
Let(T_CS('\@appendix'), T_CS('\relax'), 'global');

lib/LaTeXML/Engine/TeX_Registers.pool.ltxml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,28 @@ DefPrimitive('\muskipdef SkipSpaces Token SkipSpaces SkipMatch:=', sub {
7070
DefPrimitive('\toksdef SkipSpaces Token SkipSpaces SkipMatch:=', sub {
7171
shorthandDef($_[0], $_[1], '\toks', Tokens()); });
7272

73+
# Candidate for use defining plain's \alloc@ and latex's \e@alloc
74+
our %stored_registers = (
75+
'\countdef' => 1, '\dimendef' => 1, '\skipdef' => 1, '\muskipdef' => 1, '\toksdef' => 1);
76+
DefMacro('\lx@alloc@ DefToken {} {} DefToken', sub {
77+
my ($gullet, $type, $tracker, $allocator, $cs) = @_;
78+
$type = ToString($type);
79+
$tracker = ToString($tracker);
80+
my $next;
81+
if ($stored_registers{ ToString($allocator) }) {
82+
$next = LaTeXML::Package::allocateRegister($type);
83+
$next =~ s/^\Q$type\E//; }
84+
else {
85+
my $xnext = $STATE->lookupValue($tracker) || Number(0);
86+
$next = $xnext->valueOf + 1; }
87+
$STATE->assignValue($tracker => Number($next), 'global');
88+
return Tokens(T_CS('\allocationnumber'), Explode($next), T_CS('\relax'),
89+
T_CS('\global'), $allocator, $cs, T_OTHER('='), T_CS('\allocationnumber')); });
90+
91+
# Out of place, but utility for LaTeX-style \the<ctr>; used by Package's NewCounter
92+
DefMacro('\lx@counter@arabic{}', sub {
93+
ExplodeText(CounterValue(ToString(Expand($_[1])))->valueOf); });
94+
7395
#======================================================================
7496
# Numeric Registers
7597
#----------------------------------------------------------------------

lib/LaTeXML/Engine/plain.pool.ltxml

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,10 @@ DefPrimitive('\wlog{}', sub {
196196
NoteLog(ToString(Expand($_[1])));
197197
return; },
198198
locked => 1);
199+
200+
# Use Package's register allocation to avoid allocating same slot twice; and ALWAYS have room!
201+
DefMacro('\alloc@{}{}{}{}{}', '\lx@alloc@{#2}{\count1#1}{#3}{#5}', locked => 1);
202+
DefMacro('\ch@ck{}{}{}', '', locked => 1);
199203
# From plain.tex
200204
RawTeX(<<'EoTeX');
201205
\outer\def\newcount{\alloc@0\count\countdef\insc@unt}
@@ -211,18 +215,9 @@ RawTeX(<<'EoTeX');
211215
\outer\def\newfam{\alloc@8\fam\chardef\sixt@@n}
212216
\outer\def\newlanguage{\alloc@9\language\chardef\@cclvi}
213217
EoTeX
214-
DefMacro('\e@alloc{}{}{}{}{}{}',
215-
'\global\advance#3\@ne
216-
% \e@ch@ck{#3}{#4}{#5}#1%
217-
\allocationnumber#3\relax
218-
\global#2#6\allocationnumber
219-
% \wlog{\string#6=\string#1\the\allocationnumber}
220-
');
221-
DefMacro('\alloc@{}{}{}{}', '\e@alloc#2#3{\count1#1}#4\float@count');
222218

223219
# This implementation is quite wrong
224220
DefPrimitive('\newinsert Token', sub { DefRegisterI($_[1], undef, Number(0)); });
225-
# \alloc@, \ch@ck
226221

227222
# TeX plain uses \newdimen, etc. for these.
228223
# Is there any advantage to that?

lib/LaTeXML/Package.pm

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -597,9 +597,12 @@ sub allocateRegister {
597597
if (my $addr = $allocations{$type}) { # $addr is a Register but MUST be stored as \count<#>
598598
if (my $n = $STATE->lookupValue($addr)) {
599599
my $next = $n->valueOf + 1;
600+
my $loc = $type . $next;
601+
while ($STATE->isValueBound($loc)) {
602+
$next++; $loc = $type . $next; }
600603
$STATE->assignValue($addr => Number($next), 'global');
601-
return $type . $next; }
602-
else { # If allocations not set up, punt to unallocated register
604+
return $loc; }
605+
else { # If allocations not set up, punt to unallocated register
603606
return; } }
604607
else {
605608
Error('misdefined', $type, undef, "Type $type is not an allocated register type");
@@ -634,8 +637,15 @@ sub NewCounter {
634637
my $unctr = "UN$ctr"; # UNctr is counter for generating ID's for UN-numbered items.
635638
if ($within && ($within ne 'document') && !LookupDefinition(T_CS("\\c\@$within"))) {
636639
NewCounter($within); }
637-
my $cs = T_CS("\\c\@$ctr");
638-
DefRegisterI($cs, undef, Number(0), allocate => '\count');
640+
my $cs = T_CS("\\c\@$ctr");
641+
my $prevdefn = $STATE->lookupMeaning($cs);
642+
if ($prevdefn && ((ref $prevdefn) eq 'LaTeXML::Core::Definition::Register')
643+
&& (($$prevdefn{address} || '') =~ /^\\count/)) {
644+
Info('unexpected', $cs, undef, "Counter $ctr was already allocated, skipping"); }
645+
else {
646+
Warn('unexpected', $cs, undef,
647+
"Counter " . ToString($cs) . " was already defined as $prevdefn; redefining") if $prevdefn;
648+
DefRegisterI($cs, undef, Number(0), allocate => '\count'); }
639649
AfterAssignment();
640650
AssignValue("\\cl\@$ctr" => Tokens(), 'global') unless LookupValue("\\cl\@$ctr");
641651
DefRegisterI(T_CS("\\c\@$unctr"), undef, Number(0));
@@ -649,9 +659,7 @@ sub NewCounter {
649659
'global') if $within;
650660
AssignValue('nested_counters_' . $ctr => $options{nested}, 'global') if $options{nested};
651661
# default is equivalent to \arabic{ctr}, but w/o using the LaTeX macro!
652-
DefMacroI(T_CS("\\the$ctr"), undef, sub {
653-
ExplodeText(CounterValue($ctr)->valueOf); },
654-
scope => 'global');
662+
DefMacroI(T_CS("\\the$ctr"), undef, "\\lx\@counter\@arabic{$ctr}", scope => 'global');
655663
if (!LookupDefinition(T_CS("\\p\@$ctr"))) {
656664
DefMacroI(T_CS("\\p\@$ctr"), undef, Tokens(), scope => 'global'); }
657665
my $prefix = $options{idprefix};

0 commit comments

Comments
 (0)