[Tex/LaTex] Role of swap$ in bibinfo.check function in makebst created bst file

bibtexcustom-bib

I try to understand a makebst-created .bst file.
It has a function called bibinfo.check. The function is defined as:

FUNCTION {bibinfo.check}
{ swap$
  duplicate$ missing$
    {
      pop$ pop$
          ""
    }
    { duplicate$ empty$
        {
          swap$ pop$
        }
        { swap$
          pop$
        }
      if$
    }
  if$
} 

I don't understand the role of the starting swap$ internal function. I know what it does but I don't understand why it is necessary here.

The bibinfo.check function is called by the format.names function, which is called by the format authors function as:

FUNCTION {format.authors}
{ author "author" format.names
}

This is the format.names function:

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$
}

If I understand correctly, in the format.names function "author" is assigned to bibinfo string and the whole content of the author-field (all authors) is assigned to s string.

bibinfo.check is called in format.names function like this:

      format.name$
      remove.dots
      bibinfo bibinfo.check

That is, when bibitem.check is called, the stack looks like:

"formatted name string" "author"

with "author" string at the top of the stack.

bibitem.check swaps these two and then checks if the top item (that is the "formatted name string" is missing).

I don't understand why the swap$ is necessary if we want to check whether the author field is missing. In its current form the function checks if the "formatted name string" is missing or empty, not if the author field is missing. I don't understand the logic. Or do I misunderstand something or misinterpret the code?

Could someone please explain it?

Best Answer

You're almost right in your analysis. When bibinfo.check is called by format.names, the stack contains

<formatted names> "author"

where <formatted names> is what we need to check and "author" is that string literal, not the field author. If the code omitted swap$ it would check that the literal string was there, not the formatted content. As bibinfo.check will always be called with a string literal (to be used in any resulting error message) the final entry on the stack will always be present and non-empty: it's the penultimate one that needs to be checked.

(It would of course be possible to put the string literal onto the stack before doing any formatting, but overall that would be more effort and more confusing than adding it at the end with a quick swap$.)

Related Question