6

In a custom .bst file I want to define a string that can be modified from the .bib file. As far as I can tell the way to do this is defining a

MACRO {mystring} {"Original"} 

in the .bst and if necessary redefining it using

@string{mystring = "Modified"}

in the .bib.

However, in the .bst file I need to access the value of the string. Specifically, I want to write an if statement that checks whether the string was replaced by the .bib file or not. The code I thought would make sense for this was along these lines:

mystring "Original" =
{}
{"mystring changed" warning$}
if$

However, this leads to the error

mystring is an unknown function

as it is apparently no possible to push the content of a MACRO on the stack.

Interestingly it works if I define it as

FUNCTION {mystring} {"Original"} 

but in that case it's no longer possible to modify the value from the bib file.

So my question is, is it somehow possible to push the content of a MACRO to the stack, or is there some other mechanism by which I could pass global information from the .bib file to the .bst file that does not belong to any individual entry.

Here's an (non-working) example as minimal as I could make it:

\documentclass{article}
\usepackage{filecontents}
\begin{filecontents}{my.bib}
@string{mystring = "Modified"}
@Misc{AAA,
  title = "The best title"
}
\end{filecontents}
\begin{filecontents}{my.bst}
ENTRY
  { 
    title
  }
  {}
  { label }
INTEGERS { output.state before.all mid.sentence after.sentence after.block }
FUNCTION {init.state.consts}
{ #0 'before.all :=
  #1 'mid.sentence :=
  #2 'after.sentence :=
  #3 'after.block :=
}
STRINGS { s t}
FUNCTION {output.nonnull}
{ 's :=
  output.state mid.sentence =
    { ", " * write$ }
    { output.state after.block =
        { add.period$ write$
          newline$
          "\newblock " write$
        }
        { output.state before.all =
            'write$
            { add.period$ " " * write$ }
          if$
        }
      if$
      mid.sentence 'output.state :=
    }
  if$
  s
}
FUNCTION {output}
{ duplicate$ empty$
    'pop$
    'output.nonnull
  if$
}

FUNCTION {fin.entry}
{ add.period$
  write$
  newline$
}

INTEGERS { nameptr namesleft numnames }


FUNCTION {format.title}
{ title
  duplicate$ empty$ 'skip$
    { "t" change.case$ }
  if$
}
FUNCTION {output.bibitem}
{ newline$
  "\bibitem{" write$
  cite$ write$
  "}" write$
  newline$
  ""
  before.all 'output.state :=
}

MACRO {mystring}{"Original"}

FUNCTION {misc}
{ output.bibitem
  format.title output
  mystring "Original" =
  {}
  {"mystring changed" warning$}
  if$
  fin.entry
}

READ
SORT
FUNCTION {begin.bib}
{ preamble$ empty$
    'skip$
    { preamble$ write$ newline$ }
  if$
  "\begin{thebibliography}{}"
  write$ newline$
  "\expandafter\ifx\csname urlstyle\endcsname\relax"
  write$ newline$
  "  \providecommand{\doi}[1]{doi:\discretionary{}{}{}#1}\else"
  write$ newline$
  "  \providecommand{\doi}{doi:\discretionary{}{}{}\begingroup \urlstyle{rm}\Url}\fi"
  write$ newline$
}
EXECUTE {begin.bib}
EXECUTE {init.state.consts}
ITERATE {call.type$}
FUNCTION {end.bib}
{ newline$
  "\end{thebibliography}" write$ newline$
}
EXECUTE {end.bib}
\end{filecontents}
\begin{document}
  \cite{AAA}

  \bibliographystyle{my}
  \bibliography{my}
\end{document}
5

No, it's not possible. The macro/string mechanism in BibTeX is there as a 'convenience': the substitution takes place very early, before the fields are passed to the .bst code for formatting. So from the point of view of what is programmatically accessible, these substitutions 'don't exist': the value of the fields has already changed.

If you want something flexible, you'll want to have a TeX macro or perhaps a marker value that you can search-and-replace. Alternatively, you might consider the mechanism used by for example achemso or biblatex to pass data: using a special citation with dedicated data fields.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.