[Tex/LaTex] In bst file, check if variable contains string

bibtex

I have a bst file that handles a "collaboration" field in a bib entry as follows:

@article{test,
      author         = "Smith, J.",
      title          = "The Foo Title",
      collaboration  = "BAR",
      journal        = "Stack",
      volume         = 0,
      pages          = "1-10",
      year           = 2013
}

Yields:

J. Smith (BAR Collaboration), The Foo Title, Stack 0, 1–10 (2013).

This is fine, except for entries in which the "collaboration" field already contains the word collaboration.

My question is, is there a simple way in which to modify the function below such that the "Collaboration" or "Collaborations" string is only added when required?

The modified function would need to be case insensitive and also insensitive to singular/plural.

Here is the current function:

FUNCTION {format.collaboration}
{ collaboration empty$
    { "" }
    { collaboration num.names$ #1 >
        {" (" collaboration * " Collaborations)" * }
        {" (" collaboration * " Collaboration)" * }
    if$
    }
  if$
}

Unfortunately, the reverse polish format of bibtex makes the learning curve so steep that the Tame the BeaST document and its examples are not really helping me.

By the time I figure out a fix, I could have just changed all of my bib entries to be compliant. But going forward, it would be nice to have a function so I don't have to worry about it.

Thanks!

Best Answer

We use the string.length function from Tame the Beast, the or function should be contained in your bst file already. Then we define a simple search function that tests whether a string is contained in another string. Using this, we can test for "collaboration" and "Collaboration" in the collaboration field. Note that we do not need to test for the plural forms, as searching for the singular form will find those plurals, too.

INTEGERS{ l }
FUNCTION{ string.length }
{
  #1 'l :=
  {duplicate$ duplicate$ #1 l substring$ = not}
    { l #1 + 'l :=}
  while$
  pop$ l
}

INTEGERS {find.length search.start search.end done}
STRINGS {find.string find.pattern}
FUNCTION {contains}
{
  'find.pattern :=
  'find.string :=
  find.pattern string.length 'find.length :=
  #1 'search.start :=
  find.string string.length find.length - #2 + 'search.end :=
  #0 'done :=
  { search.start search.end < }
  {
    find.string search.start find.length substring$ find.pattern =
      { 
        #1 'done :=
        search.end 'search.start :=%% stop searching
      }
      { #1 search.start + 'search.start := }
    if$
  }
  while$
  done
}

FUNCTION {format.collaboration}
{ collaboration empty$
    { "" }
    { collaboration num.names$ #1 >
        { " (" collaboration *
          collaboration "collaboration" contains
          collaboration "Collaboration" contains or
            { ")" * }
            { " Collaborations)" * }
          if$
        }
        { " (" collaboration *
          collaboration "collaboration" contains
          collaboration "Collaboration" contains or
            { ")" * }
            { " Collaboration)" * }
          if$
        }
    if$
    }
  if$
}

As a final note I would advice against those hacks, and change the bib file instead. BibTeX is meant to just format the bibliography, not to alter the content. If you would like to use another style, or switch to biblatex, those inconsistent BibTeX entries come back to bite you, again.