假设有
\newcount\c@mycountera
\newcount\c@mycounterb
\newcount\c@mycounterc
每个都\newcount
使用\alloc@
并且 具有\wlog{\string#5=\string#2\the\allocationnumber}
。因此,为了确定哪个寄存器mycountera
使用,我可以查看.log
文件中的 (例如) \c@mycountera=\count123
。
但是我如何才能自动确定 LaTeX 内部使用的寄存器的数量?(类似于\registernumber{\c@mycountera}
扩展为123
。)之后\newcount\c@mycountera
是\the\allocationnumber
,但是当在和我需要信息的时间之间创建了未知数量的计数时,\newcount\c@mycountera
这无济于事。(我不能\xdef\myallocationnumber{\the\allocationnumber}
立即使用\newcount\c@mycountera
,因为它是在包内定义的。)
(我怀疑答案也可以与 \dimen、\box 等一起使用。)
答案1
您可以使用以下事实\meaning
来打印类似\countXXX
寄存器的内容:
\def\registernumber#1{%
\expandafter\registernumberauxi\meaning#1\halt\stop
}
\def\registernumberauxi#1#2\stop{%
\ifx\halt#1%
\expandafter\gobbletwo
\else
\expandafter\registernumberauxii
\fi
{#1}{#2}%
}
\def\registernumberauxii#1#2{%
\ifnum`#1<48\else\ifnum`#1>57\else#1\fi\fi
\registernumberauxi#2\stop
}
\def\gobbletwo#1#2{}
\def\halt{\halt}
\newcount\mycount
\registernumber\mycount
\bye
我在这里使用了一个简单的循环来从数字前面删除寄存器的类型。也许有更好的方法可以做到这一点,但如果证明了原理。循环利用了事实,即\char48
是 0 并且\char57
是 9,因此超出此范围的任何东西都不是数字。
答案2
这是一个也适用于盒子寄存器的方法:
\makeatletter
\def\showregister#1{\expandafter\extract@number\meaning#1\showregister}
\def\extract@number#1{%
\ifx#1\showregister
\expandafter\@gobbletwo
\else
\if\string"#1#1%
\expandafter\expandafter\expandafter\@firstoftwo
\else
\ifnum`#1<`0 \else \ifnum`#1>`9 \else #1\fi\fi
\expandafter\expandafter\expandafter\@secondoftwo
\fi
\fi
\extract@rest\extract@number}
\def\extract@rest#1\showregister{#1}
\def\showcounter#1{\expandafter\showregister\csname c@#1\endcsname}
\makeatother
\newcount\AAA
\showregister\AAA
\newdimen\AAB
\showregister\AAB
\newlength\AAC
\showregister\AAC
\newsavebox\AAD
\showregister\AAD
\newcount{AAE}
\showcounter{AAE} % or \expandafter\showregister\csname c@AAE\endcsname
盒子寄存器编号将采用十六进制形式,前面带有"
输出应该是(如果启动时没有任何包)
7910241 “
1A80
这是 LaTeX3 版本:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\showcounter} { m }
{ \exp_args:Nc \showregister { c@#1 } }
\DeclareExpandableDocumentCommand{\showregister} { m }
{
\tl_map_function:fN { \cs_meaning:N #1 } \showreg_scan:n
}
\cs_generate_variant:Nn \tl_map_function:nN { f }
\cs_new:Npn \showreg_scan:n #1
{
\bool_if:nT
{
( \int_compare_p:n { `#1 >= `0 } && \int_compare_p:n { `#1 <= `9 } )
||
\int_compare_p:n { `#1 = `" }
||
( \int_compare_p:n { `#1 >= `A } && \int_compare_p:n { `#1 <= `F } )
}
{ #1 }
}
\ExplSyntaxOff
\def\test#1{\edef\x{\showregister#1}\message{\x\space = \meaning#1}}
\test\fboxsep
\newbox\mybox
\test\mybox
终端上的输出将是
36 = \dimen36
"23 = \char"23
答案3
这段评论太长了。根据 OP,计数器数字用于检查加载的包的顺序。这不太可能成为一种完整的证明技术。
LaTeX2e
,将所有分配的计数器存储在\@elt
名为的列表 中\cl@@ckpt
。
以下 MWE 将显示所有已分配的计数器及其名称,即 之后的部分c@
。正如您在运行示例时所观察到的,像 Heiko 这样的 hyperTexies 会摆弄系统。不过,它主要会预测加载顺序:
% See all the counters in LaTeX2e
% and their allocation numbers
\documentclass{book}
\usepackage{graphicx}
\usepackage{longtable}
\usepackage{verse}
\usepackage{hyperref}
\usepackage{caption}
\newcounter{ZZZ}
\begin{document}
\makeatletter
\def\Z{%
\def\@elt##1{%
\expandafter\meaning
\csname c@##1\endcsname
\space = ##1,\par
}%
\cl@@ckpt%
}
All counter in article class plus one!
Expand list.
\Z
\section{Test}
\ifcsname c@section@level\endcsname
hyperef package has been loaded
\else
not loaded
\fi
%\expandafter\let\csname c@section@level\endcsname\undefined
\the\count118
\the\c@section@level
\end{document}
检查文件顺序的更好方法是检查@filelist
。
\documentclass{book}
\usepackage{graphicx}
\usepackage{longtable}
\usepackage{verse}
\usepackage{hyperref}
\usepackage{caption}
\newcounter{ctr}
\makeatletter
\let\afilelist\@filelist
\begin{document}
% Just to see files
\@for\next:=\afilelist\do{%
\next, \par
}
% Command factory
\stepcounter{ctr}
\@for\next:=\afilelist\do{%
\expandafter\edef\csname @\next\endcsname{\thectr}
\stepcounter{ctr}
}
% Define macro to check order
\def\checkpkgorder#1#2{%
\edef\X{\csname @#1\endcsname}
\edef\Y{\csname @#2\endcsname}
\expandafter\ifnum\X\expandafter<\Y
Yes loaded earlier \X, \Y
\else
No loaded later \X, \Y
\fi
}
\checkpkgorder{book.cls}{ifxetex.sty}
\end{document}