我尝试理解makebst
创建的.bst
文件。它有一个名为的函数bibinfo.check
。该函数定义如下:
FUNCTION {bibinfo.check}
{ swap$
duplicate$ missing$
{
pop$ pop$
""
}
{ duplicate$ empty$
{
swap$ pop$
}
{ swap$
pop$
}
if$
}
if$
}
我不明白启动swap$
内部函数的作用。我知道它做什么,但我不明白为什么这里需要它。
该bibinfo.check
函数由函数调用format.names
,该函数由格式作者函数调用,如下所示:
FUNCTION {format.authors}
{ author "author" format.names
}
这是format.names
函数:
FUNCTION {format.names}
{ 'bibinfo :=
duplicate$ empty$ 'skip$ {
's :=
"" 't :=
#1 'nameptr :=
s num.names$ 'numnames :=
numnames 'namesleft :=
{ namesleft #0 > }
{ s nameptr
"{vv~}{ll}{ f{}}{ jj}"
format.name$
remove.dots
bibinfo bibinfo.check
't :=
nameptr #1 >
{
nameptr #6
#1 + =
numnames #6
> and
{ "others" 't :=
#1 'namesleft := }
'skip$
if$
namesleft #1 >
{ ", " * t * }
{
s nameptr "{ll}" format.name$ duplicate$ "others" =
{ 't := }
{ pop$ }
if$
"," *
t "others" =
{
" " * bbl.etal *
}
{ " " * t * }
if$
}
if$
}
't
if$
nameptr #1 + 'nameptr :=
namesleft #1 - 'namesleft :=
}
while$
} if$
}
如果我理解正确的话,在format.names
函数中将"author"
其分配给bibinfo
字符串,并且作者字段(所有作者)的全部内容都分配给s
字符串。
bibinfo.check
在函数中被调用format.names
如下:
format.name$
remove.dots
bibinfo bibinfo.check
也就是说,当调用bibitem.check时,堆栈如下所示:
"formatted name string" "author"
字符串"author"
位于堆栈顶部。
bibitem.check
交换这两个,然后检查顶部项目(即“格式化的名称字符串”)是否丢失。
我不明白为什么swap$
如果我们想检查author
字段是否缺失,那么这个是必要的。在当前形式下,该函数检查“格式化名称字符串”是否缺失或为空,而不是作者字段是否缺失。我不明白其中的逻辑。还是我误解了什么或误解了代码?
有人可以解释一下吗?
答案1
你的分析几乎是对的。当bibinfo.check
被调用时format.names
,堆栈包含
<formatted names> "author"
<formatted names>
我们需要检查"author"
的是那个字符串文字,而不是字段author
。如果省略代码,swap$
它将检查文字字符串是否存在,而不是格式化的内容。由于bibinfo.check
始终会使用字符串文字进行调用(用于任何生成的错误消息),因此堆栈上的最后一个条目将始终存在且非空:它是需要检查的倒数第二个条目。
(当然,可以在进行任何格式化之前将字符串文字放入堆栈,但总的来说,这会比在最后快速添加它更加费力且更令人困惑swap$
。)