Docstrip Version of XBTXBST.DOC

P. W. Daly

This paper describes file xbtxbst.mbs, version 1.1 from 1994 July 1

Part I

About This File

1 Introduction

When I got the idea of using Frank Mittelbach’s docstrip program to make up generic, or master, bibliographic style files for BibTEX, I took the standard .bst file plain plus apalike (also from Patashnik) and merged them as my model. I wanted to add various options using docstrip alternative coding, as explained in the next sections. However, in order to find out what bibliographic features were being used by others, I copied every .bst file I could find in order to compare the results. In this way I discovered xbtxbst.doc, a modified version of btxbst.doc that includes ISBN and ISSN numbers, as well as a periodical type. The .bst styles produced from it are normally prefixed with is- to distinguish them from the original four.

The original file btxbst.doc is Patashnik’s master file for producing the four standard .bst files, and it works exactly as I visualized using docstrip, but with a C-preprocessor. It contains only 6 options. It was no great problem to convert the preprocessor commands to docstrip equivalents.

However, what is even more interesting is the extensive comments from Patashnik that fill the coding. These are simply ascii comments, but I decided to try to convert them to L^{A}TEX format in order to produce a true internally documented file in the manner of Mittelbach’s doc.sty system. For anyone struggling through BibTEX formatting language, this will be a great relief.

I provide this file in such a manner that when it is L^{A}TEXed, it only produces my introductory text, describing master files and makebst, as well as the menus for running makebst and docstrip. To obtain the whole BibTEX coding, with Patashnik’s comments, you must remove the line % \OnlyDescription near the beginning. Removal is done not by adding a % sign (they have been turned off!) but by physical deletion, or better, by

adding ^^A, as % ^^A\OnlyDescription. This is a speciality of doc.sty,

and not of normal L^{A}TEX.

2 About Master Bibliographic Style Files

2.1 The docstrip Options

This master file is a BibTEX bibliographic style file containing alternative coding depending on docstrip options. The options are selected when docstrip is run, either interactively or through a batch job.

Suppose that one of the options is called xyz. Then the following alternatives are possible:

%<xyz> one line of coding

includes the single line of coding;

%<!xyz> one line of coding

excludes the single line;

     %<*xyz>

several lines of coding

     %</xyz>

includes all the bracketted lines;

     %<*!xyz>

several lines of coding

     %</!xyz>

excludes all the bracketted lines.

Options may be logically combined: the symbol | is a logical or, & a logical and, ! a logical not; parentheses ( and ) may be used to group options.

2.2 The docstrip Batch Job

In order to generate a true BibTEX style file with selected options from this master file, it is necessary to run a docstrip batch job. Suppose that the master file is named master.mbs, and the resulting BibTEX style file is to be silly.bst, and the batch job file itself is called silly.drv. To produce this with options, say, xyz and abc, the batch job would look something like:

      \def\batchfile{silly.drv}
      \input docstrip
      \preamble
      This is for Journal of Silly Results
      \endpreamble
      \postamble
      End of customized bst file
      \endpostamble
      \keepsilent
      \generateFile{silly.bst}{f}{\from{master.mbs}{xyz,abc}}

A preamble is not necessary, although it is advisable to include some statement about the application of the bibliographic style. A postamble is vital, otherwise the default will add \endinput at the end of the file, something that BibTEX will not understand. The \keepsilent is optional and just suppresses docstrip output during processing.

2.3 The makebst Program

The program makebst simplifies the creation of the batch job file. To do that, it needs information on the available options. This information must be stored in a special format, either in the master file itself, or in a file with the same root name but extension .opt. The form of this format is described in the documentation on makebst.

In the master file, this information must be enclosed within docstrip options

%<*options> . . . %</options> and must include an \endoptions command.

It may also include any number of comments.

A sample menu in the master file to select one or none of options xyz or zyx would look thus:

      %<*options>
      \mes{Select one of these}
      \optdef{f}{xyz}{Option forword}{to do forward stuff}
      \optdef{r}{zyx}{Option reverse}{to do reverse stuff}
      \optdef{*}{}{None of the above}{}
      \getans

      \endoptions
      %</options>
      %<*!options>
      . . . . . .
      %</!options>

An explanation of these commands is to be found in the documentation on

makebst.

The menu information may be extracted from the master file by means of docstrip and stored in a file with extension .opt. If this file is missing, the program tries to read it from the master file.

3 The Options

The original file xbtxbst.doc contains only 6 options for the C-prepro-cessor, which I have easily changed to 6 corresponding docstrip options. (By comparison, my own master bibliographic style file offers about 30.)

These six options are:

lab-alph an alphabetic label is produced instead of a running number;

sorted the references are listed alphabetically by author(s); if this is option is not given, then they appear in the list in the same order as they are cited in the text;

name-full first names of authors and editors are written out (provided they have been given in the entry); if this option is missing, then the first names are initialized;

atit-lower words in the titles of non-books (i.e., articles) are converted to lowercase, other than the first word, and any words enclosed in braces; if not given, such titles are reproduced as they are in the entry;

month-full the names of months are written out in full; otherwise they are abbreviated;

jour-full the names of the pre-defined journals are written out in full; otherwise they are abbreviated.

The following table shows the values of these options for the four standard bibliographic styles (+ means active, − means not active):

               Option  plain  unsrt  abbrv  alph
              lab-alph  −  −  −  +
               sorted  +  −  +  +
             name-full  +  +  −  +
             atit-lower  +  +  +  +
             month-full  +  +  −  +
             jour-full  +  +  −  +

To this I have now added a seventh option:

nfss to use NFSS font commands instead of the older L^{A}TEX 2.09 ones.

This means that \emph{text} is used in place of {\em text}. Such a .bst file can only be used with L^{A}TEX 2ε. This allows an easy way to update the standard four .bst files to the new L^{A}TEX.

4 The Menu Information

Here I describe the options and menu information for this particular master file for use with makebst.

All this menu information is nested between docstrip guard options %<*options> … %</options>, and the last command is \endoptions. The rest of the file is nested between %<*!options> … %</!options> in order to exclude it if docstrip is used to extract only the menu information.

First the menu identifies itself.

1 ⟨∗options⟩

 2 \mes{^^JThis is XBTXBST.DOC, hacked to work with DOCSTRIP instead}
 3 \mes{\space\space of with a C Preprocessor}
 4 \mes{\space\space It is the Master File for the (extended) standard BibTeX}
 5 \mes{\space\space styles plain, unsrt, abbrv, and alpha}
 6 \mes{\space\space (Extended means ISBN and ISSN are included as fields)}

Now the inquisition begins. Note that the default answers produce the plain (more properly the is-plain) bibliographic style. This illustrates how the menu defaults may be different from the docstrip ones. The ^^J forces a new line within the output message.

 7 \mes{^^JSelect your options:^^JStyle of label:}
 8 \optdef{*}{}{Numerical}{for plain, unsrt, abbrv}
 9 \optdef{a}{lab-alph}{Alphabetical}{for alpha}
10 \getans

11

12 \mes{^^JOrdering:}
13 \optdef{*}{sorted}{Sorted}{for plain, abbrv, alpha}

4 THE MENU INFORMATION 6

14 \optdef{u}{}{Unsorted}{for unsrt}
15 \getans

16

17 \mes{^^JAuthor names:}
18 \optdef{*}{name-full}{Names fully written}{for plain, unsrt, alpha}
19 \optdef{a}{}{Names abbreviated}{for abbrv}
20 \getans

21

22 \mes{^^JNon-book titles:}
23 \optdef{*}{atit-lower}{Converted to l.c.}{for plain, unsrt, abbrv, alpha}
24 \optdef{u}{}{As in entry}{for none}
25 \getans

26

27 \mes{^^JMonth names:}
28 \optdef{*}{month-full}{Full}{for plain, unsrt, alpha}
29 \optdef{a}{}{Abbreviated}{for abbrv}
30 \getans

31

32 \mes{^^JJournal names:}
33 \optdef{*}{jour-full}{Full}{for plain, unsrt, alpha}
34 \optdef{a}{}{Abbreviated}{for abbrv}
35 \getans

36

37 \mes{^^JNEW FONT SELECTION SCHEME:}
38 \optdef{*}{}{No NFSS}{use 2.09 font commands}
39 \optdef{n}{nfss}{NFSS}{use \string\textbf, \string\emph, not \string\bf,
40  \string\em}
41 \getans
42 \endoptions

43 ⟨/options⟩

Part II

The Bibliographic Coding

The remaining text is that found in xbtxbst.doc, which is almost the same as that in btxbst.doc. I have only modified it to work as L^{A}TEX input, adding \tt where necessary, and changing "text" to ``text'', adding environments, and sectioning commands, and so on.

The original also contains several “comment versions” of the coding. These are a simplified copy of the function in question. I have kept them, as verbatim text. They are part of the comments themselves, and not of the coding.

For more information about how the BibTEX stack language works, see Patashnik’s article btxhak.tex that should be part of the standard L^{A}TEX package.

The initial copyright and explanatory text has been moved from the beginning to here; it is output into every .bst file produced.

44 ⟨∗!options⟩

45 %% BibTeX `plain' family
46 %%       version 0.99b for BibTeX versions 0.99a or later, LaTeX version 2.09.
47 %%       Copyright (C) 1985, all rights reserved.
48 %%       Copying of this file is authorized only if either
49 %%       (1) you make absolutely no changes to your copy, including name, or
50 %%       (2) if you do make changes, you name it something other than
51 %%       btxbst.doc, plain.bst, unsrt.bst, alpha.bst, and abbrv.bst.
52 %%       This restriction helps ensure that all standard styles are identical.
53 %%       The file btxbst.doc has the documentation for this style.
54 %%

From here on, it is Oren Patashnik’s original text. Any other comments that I may have will be entered in slanted typeface as here.

PWD

5 Background

Entry formatting: Similar to that recommended by Mary-Claire van Leunen in “A Handbook for Scholars”. Book-like titles are italicized (emphasized) and non-book titles are converted to sentence capitalization (and not enclosed in quotes). This file outputs a \newblock between major blocks of an entry (the name \newblock is analogous to the names \newline and \newpage) so that the user can obtain an “open” format, which has a line break before each block and lines after the first are indented within blocks, 5 BACKGROUND 8

by giving the optional \documentstyle argument openbib; the default is the “closed” format—blocks runs together. Citation alphabetic label format:

[Knu73] for single author (or editor or key)

[AHU83] (first letters of last names) for multiple authors Citation label numberic format:

     [number]

Reference list ordering for sorted, alphabetic lables:

alphabetical by citation label, then by author(s) or whatever passes for author in the absence of one, then by year, then title.

Reference list ordering for sorted, numeric lables:

alphabetical by author(s) or whatever passes for author in the absence of one, then by year, then title.

Reference list ordering for unsorted:

by the order cited in the text. History: 12/16/84 (HWT) Original plain version, by Howard Trickey.

12/23/84 (LL) Some comments made by Leslie Lamport.

2/16/85 (OP) Changes based on LL’s comments, Oren Patashnik. 2/17/85 (HWT) Template file and other standard styles made.

3/28/85 (OP) First release, version 0.98b for BibTEX 0.98f.

5/09/85 (OP) Version 0.98c for BibTEX 0.98i:

fixed Theoretical Computer Science macro name;

                  fixed the format.vol.num.pages function.

1/24/88 (OP) Version 0.99a for BibTEX 0.99a, main changes: assignment operator (:=) arguments reversed; the preamble$ function outputs the database PREAMBLE; entry.max$ and global.max$ (built-in) variables re-

place entry.string.max and global.string.max func-

tions; alphabetizing by year then title, not just title; many unnecessary ties removed;

\em ⇒ \em;

the alpha style uses a superscripted ‘+’ instead of a ‘*’ for unnamed names in constructing the label; the abbrv style now uses “Mar.” and “Sept.”; the functions calc.label and presort now look at just the fields they’re supposed to;

BOOKLET, MASTERSTHESIS, TECHREPORT use nonbook

titles; INBOOK and INCOLLECTION take an optional type (e.g. type = “Section”), overriding the default “chapter”;

BOOK, INBOOK, INCOLLECTION, and PROCEEDINGS now

allow either volume or number, not just volume; INCOLLECTION now allows an edition and series field;

PROCEEDINGS and INPROCEEDINGS now use the ad-

dress field to tell where a conference was held;

INPROCEEDINGS and PROCEEDINGS now allow either

volume or number, and also a series field;

MASTERSTHESIS and PHDTHESIS accept types other

than “Master’s thesis” and “PhD thesis”; UNPUBLISHED now outputs, in one block, note then date; MANUAL now prints out the organization in the first block if the author field is empty; MISC can’t be empty—it requires some optional field.

3/23/88 (OP) Version 0.99b for BibTEX 0.99c—changed the three erroneous occurrences of cite to cite$; this change didn’t affect the four standard styles, so the 0.99a versions of those styles are still current.

6 Preliminaries

6.1 The ENTRY declaration

Like Scribe’s (according to pages 231-2 of the April ’84 edition), but no fullauthor or editors fields because BibTEX does name handling. The annote field is commented out here because this family doesn’t include an annotated bibliography style. And in addition to the fields listed here, BibTEX has a built-in crossref field, explained later.

55 ENTRY

Fields:

56 { address

Usually the address of a publisher or other type of organization. Put information in this field only if it helps the reader find the thing—for example you should omit the address of a major publisher entirely. For a PROCEEDINGS or an INPROCEEDINGS, however, it’s the address of the conference; for those two entry types, include the publisher’s or organization’s address, if necessary, in the publisher or organization field.

57 %    annote

Long annotation—for annotated bibliographies (begins sentence).

58  author

Name(s) of author(s), in BibTEX name format.

59  booktitle

Book title when the thing being referenced isn’t the whole book. For book entries, the title field should be used instead.

60  chapter

Chapter (or section or whatever) number.

61  edition

Edition of a book—should be an ordinal (e.g., “Second”).

62  editor

Name(s) of editor(s), in BibTEX name format. If there is also an author field, then the editor field should be for the book or collection that the work appears in.

63  howpublished

How something strange has been published (begins sentence).

64  institution

Sponsoring institution of a technical report.

65  isbn

ISBN book number (a 10-digit number with optional embedded spaces or hyphens, where a ‘digit’ is one of 0123456789X).

66  issn

ISSN serial publication number (an 8-digit number with optional embedded spaces or hyphens, where a ‘digit’ is one of 0123456789X).

67  journal

Journal name (macros are provided for many).

68  key

Alphabetizing, labeling, and cross-referencing key (needed when an entry

has no author or editor).
69  month

Month (macros are provided).

70  note

To help the reader find a reference (begins sentence).

71  number

Number of a journal or technical report, or of a work in a series.

72  organization

Organization sponsoring a conference (or publishing a manual); if the editor (or author) is empty, and if the organization produces an awkward label or cross reference, you should put appropriately condensed organization information in the key field as well.

73  pages

Page number or numbers (use -- to separate a range, use + to indicate pages following that don’t form a simple range).

74  publisher

Publisher name.

75  school

School name (for theses).

76  series

The name of a series or set of books. An individual book will also have it’s own title.

77  title

The title of the thing you’re referring to.

78  type

Type of a Techreport (e.g., “Research Note”) to be used instead of the default “Technical Report”; or, similarly, the type of a thesis; or of a part of a book.

79  volume

The volume number of a journal or multivolume work.

80  year

The year should contain only numerals (technically, it should end with four numerals, after purification; doesn’t a begin sentence).

81 }

There are no integer entry variables

82 {}

These string entry variables are used to form the citation label. In a storage pinch, sort.label can be easily computed on the fly. 83 ⟨∗lab − alph⟩

84 ⟨sorted⟩ { label extra.label sort.label }

It doesn’t seem like a good idea to use an order-of-citation reference list when using alphabetic labels, but when this happens we do things a little differently

85 ⟨!sorted⟩ { label }

86 ⟨/lab − alph⟩

87 ⟨!lab − alph⟩ { label }

88

6.2 Description of the Processing

Each entry function starts by calling output.bibitem, to write the \bibitem and its arguments to the .bbl file. Then the various fields are formatted and printed by output or output.check. Those functions handle the writing of separators (commas, periods, \newblock’s), taking care not to do so when they are passed a null string. Finally, fin.entry is called to add the final period and finish the entry.

A bibliographic reference is formatted into a number of ‘blocks’: in the open format, a block begins on a new line and subsequent lines of the block are indented. A block may contain more than one sentence (well, not a grammatical sentence, but something to be ended with a sentence ending period). The entry functions should call new.block whenever a block other than the first is about to be started. They should call new.sentence whenever a new sentence is to be started. The output functions will ensure that if two new.sentence’s occur without any non-null string being output between them then there won’t be two periods output. Similarly for two successive

new.block’s.

The output routines don’t write their argument immediately. Instead, by convention, that argument is saved on the stack to be output next time (when we’ll know what separator needs to come after it). Meanwhile, the output routine has to pop the pending output off the stack, append any needed separator, and write it.

6.2.1 The Output States

To tell which separator is needed, we maintain an output.state. It will be one of these values:

before.all just after the \bibitem

mid.sentence in the middle of a sentence: comma needed if more sentence is output

after.sentence just after a sentence: period needed

after.block just after a block (and sentence): period and \newblock needed.

Note: These styles don’t use after.sentence.

VAR: output.state : INTEGER – state variable for output

6.2.2 The Output Functions

The output.nonnull function saves its argument (assumed to be nonnull) on the stack, and writes the old saved value followed by any needed separator. The ordering of the tests is decreasing frequency of occurrence.

6 PRELIMINARIES 14

output.nonnull(s) ==
BEGIN
s := argument on stack
if output.state = mid.sentence then
    write$(pop() * ", ")
          -- "pop" isn't a function: just use stack top
else
    if output.state = after.block then
        write$(add.period$(pop()))
        newline$
        write$("\newblock ")
    else
        if output.state = before.all then
            write$(pop())
        else        -- output.state should be after.sentence
            write$(add.period$(pop()) * " ")
        fi
    fi
    output.state := mid.sentence
fi
push s on stack
END

The output function calls output.nonnull if its argument is non-empty; its argument may be a missing field (thus, not necessarily a string)

output(s) ==
BEGIN
if not empty$(s) then output.nonnull(s)
fi
END

The output.check function is the same as the output function except that, if necessary, output.check warns the user that the t field shouldn’t be empty (this is because it probably won’t be a good reference without the field; the entry functions try to make the formatting look reasonable even when such fields are empty).

output.check(s,t) ==
BEGIN
if empty$(s) then
    warning$("empty " * t * " in " * cite$)
else output.nonnull(s)
fi
END

The output.bibitem function writes the \bibitem for the current entry (the label should already have been set up), and sets up the separator state for the output functions. And, it leaves a string on the stack as per the output convention.

 output.bibitem ==
  BEGIN
       newline$
       write$("\bibitem[")     % for alphabetic labels,
       write$(label)           % these three lines
       write$("]{")            % are used
       write$("\bibitem{")             % this line for numeric labels
       write$(cite$)
       write$("}")
       push "" on stack
       output.state := before.all
  END

The fin.entry function finishes off an entry by adding a period to the string remaining on the stack. If the state is still before.all then nothing was produced for this entry, so the result will look bad, but the user deserves it. (We don’t omit the whole entry because the entry was cited, and a \bibitem is needed to define the citation label.)

 fin.entry ==
  BEGIN
       write$(add.period$(pop()))
       newline$
  END

The new.block function prepares for a new block to be output, and new.sentence prepares for a new sentence.

 new.block ==
  BEGIN
       if output.state <> before.all then
           output.state := after.block
       fi
  END
 new.sentence ==
  BEGIN
       if output.state <> after.block then
           if output.state <> before.all then
               output.state :=  after.sentence

            fi
        fi
   END

6.3 Coding of Output Functions

89

 90 INTEGERS { output.state before.all mid.sentence after.sentence after.block }

91

 92 FUNCTION {init.state.consts}
 93 { #0 'before.all :=
 94 #1 'mid.sentence :=
 95 #2 'after.sentence :=
 96 #3 'after.block :=

97 }

98

The variables s and t are temporary string holders.

99

100 STRINGS { s t }

101

102 FUNCTION {output.nonnull}
103 { 's :=
104 output.state mid.sentence =
105  { ", " * write$ }
106  { output.state after.block =
107  { add.period$ write$
108  newline$
109  "\newblock " write$

110 }

111  { output.state before.all =
112  'write$
113  { add.period$ " " * write$ }
114  if$

115 }

116  if$
117  mid.sentence 'output.state :=

118 }

119 if$

120 s 121 }

122

123 FUNCTION {output}
124 { duplicate$ empty$
125  'pop$
126  'output.nonnull
127 if$

128 }

129

130 FUNCTION {output.check}
131 { 't :=
132 duplicate$ empty$
133  { pop$ "empty " t * " in " * cite$ * warning$ }
134  'output.nonnull
135 if$

136 }

137

138 FUNCTION {output.bibitem}
139 { newline$

140 ⟨∗lab − alph⟩

141 "\bibitem[" write$
142 label write$
143 "]{" write$

144 ⟨/lab − alph⟩ 145 ⟨∗!lab − alph⟩

146 "\bibitem{" write$

147 ⟨/!lab − alph⟩

148 cite$ write$
149 "}" write$
150 newline$

151 ""

152 before.all 'output.state :=

153 }

154

This function finishes all entries.

155 FUNCTION {fin.entry}
156 { add.period$
157 write$
158 newline$

159 }

160

161 FUNCTION {new.block}
162 { output.state before.all =
163  'skip$
164  { after.block 'output.state := }
165 if$

166 }

167

168 FUNCTION {new.sentence}
169 { output.state after.block =
170  'skip$
171  { output.state before.all =
172  'skip$
173  { after.sentence 'output.state := }
174  if$

175 }

176 if$

177 }

178

6.4 Some Auxiliary Functions

These three functions pop one or two (integer) arguments from the stack and push a single one, either 0 or 1. The skip$ in the and and or functions are used because the corresponding if$ would be idempotent.

179 FUNCTION {not}
180 {   { #0 }
181  { #1 }
182 if$

183 }

184

185 FUNCTION {and}
186 {   'skip$
187  { pop$ #0 }
188 if$

189 }

190

191 FUNCTION {or}
192 {   { pop$ #1 }
193  'skip$
194 if$

195 }

196

Sometimes we begin a new block only if the block will be big enough. The new.block.checka function issues a new.block if its argument is nonempty; new.block.checkb does the same if either of its two arguments is nonempty.

197 FUNCTION {new.block.checka}
198 { empty$
199  'skip$
200  'new.block
201 if$

202 }

203

204 FUNCTION {new.block.checkb}
205 { empty$
206 swap$ empty$
207 and
208  'skip$
209  'new.block
210 if$

212

The new.sentence.check functions are analogous.

213 FUNCTION {new.sentence.checka}
214 { empty$
215  'skip$
216  'new.sentence
217 if$

218 }

219

220 FUNCTION {new.sentence.checkb}
221 { empty$
222 swap$ empty$
223 and
224  'skip$
225  'new.sentence
226 if$

227 }

228

7 Formatting Functions

7.1 Formatting Names

Here are some functions for formatting chunks of an entry. By convention they either produce a string that can be followed by a comma or period (using add.period$, so it is OK to end in a period), or they produce the null string.

A useful utility is the field.or.null function, which checks if the argument is the result of pushing a ‘missing’ field (one for which no assignment was made when the current entry was read in from the database) or the result of pushing a string having no non-white-space characters. It returns the null string if so, otherwise it returns the field string. Its main (but not only) purpose is to guarantee that what’s left on the stack is a string rather than a missing field.

 field.or.null(s) ==
  BEGIN
       if empty$(s) then return ""
       else return s
  END

7 FORMATTING FUNCTIONS 20

Another helper function is emphasize, which returns the argument emphasized, if that is non-empty, otherwise it returns the null string. Italic corrections aren’t used, so this function should be used when punctation will follow the result.

emphasize(s) ==
BEGIN
if empty$(s) then return ""
else return "{\em " * s * "}"

The format.names function formats the argument (which should be in BibTEX name format) into “First Von Last, Junior”, separated by commas and with an “and” before the last (but ending with “et al.” if the last of multiple authors is “others”). This function’s argument should always contain at least one name.

VAR: nameptr, namesleft, numnames: INTEGER

pseudoVAR: nameresult: STRING (it’s what’s accumulated on the stack)

format.names(s) ==
BEGIN
nameptr := 1
numnames := num.names$(s)
namesleft := numnames
while namesleft > 0
  do
                        % for full names:
    t := format.name$(s, nameptr, "{ff~}{vv~}{ll}{, jj}")
                        % for abbreviated first names:
    t := format.name$(s, nameptr, "{f.~}{vv~}{ll}{, jj}")
    if nameptr > 1 then
        if namesleft > 1 then nameresult := nameresult * ", " * t
        else if numnames > 2
               then nameresult := nameresult * ","
             fi
             if t = "others"
               then nameresult := nameresult * " et~al."
               else nameresult := nameresult * " and " * t
             fi
        fi
    else nameresult := t
    fi
    nameptr := nameptr + 1
    namesleft := namesleft - 1
  od
return nameresult
END

 The format.authors function returns the result of format.names(author)

if the author is present, or else it returns the null string.

  format.authors ==
   BEGIN
        if empty$(author) then return ""
        else return format.names(author)
        fi
   END

 Format.editors is like format.authors, but it uses the editor field, and

appends “, editor” or “, editors”.

  format.editors ==
   BEGIN
        if empty$(editor) then return ""
        else
            if num.names$(editor) > 1 then
                return format.names(editor) * ", editors"
            else
                return format.names(editor) * ", editor"
            fi
        fi
   END

Other formatting functions are similar, so no “comment version” will be given for them.

7.2 Coding the Names Format Functions

The pop$ in this function gets rid of the duplicate ‘empty’ value and the skip$ returns the duplicate field value.

229 FUNCTION {field.or.null}
230 { duplicate$ empty$
231  { pop$ "" }
232  'skip$
233 if$

234 }

235

236 FUNCTION {emphasize}
237 { duplicate$ empty$
238  { pop$ "" }
239 ⟨!nfss⟩  { "{\em " swap$ * "}" * }
240 ⟨nfss⟩  { "\emph{" swap$ * "}" * }

241 if$

242 }

243

244 INTEGERS { nameptr namesleft numnames }

245

246 FUNCTION {format.names}
247 { 's :=
248 #1 'nameptr :=
249 s num.names$ 'numnames :=
250 numnames 'namesleft :=
251  { namesleft #0 > }
252 ⟨name − full⟩  { s nameptr "{ff~}{vv~}{ll}{, jj}" format.name$ 't :=
253 ⟨!name − full⟩  { s nameptr "{f.~}{vv~}{ll}{, jj}" format.name$ 't :=
254  nameptr #1 >
255  { namesleft #1 >
256  { ", " * t * }
257  { numnames #2 >
258  { "," * }
259  'skip$
260  if$
261  t "others" =
262  { " et~al." * }
263  { " and " * t * }
264  if$

265 }

266  if$

267 } 268 't

269  if$
270  nameptr #1 + 'nameptr :=
271  namesleft #1 - 'namesleft :=

272 }

273 while$

274 }

275

276 FUNCTION {format.authors}
277 { author empty$
278  { "" }
279  { author format.names }
280 if$

281 }

282

283 FUNCTION {format.editors}
284 { editor empty$
285  { "" }
286  { editor format.names
287  editor num.names$ #1 >
288  { ", editors" * }
289  { ", editor" * }

290  if$

291 }

292 if$

293 }

294

295 FUNCTION {format.isbn}
296 { isbn empty$
297  { "" }
298  { new.block "ISBN " isbn * }
299 if$

300 }

301

302 FUNCTION {format.issn}
303 { issn empty$
304  { "" }
305  { new.block "ISSN " issn * }
306 if$

307 }

308

7.3 Title and Date Format Functions

The format.title function is used for non-book-like titles. For most styles we convert to lowercase (except for the very first letter, and except for the first one after a colon (followed by whitespace)), and hope the user has bracesurrounded words that need to stay capitalized; for some styles, however, we leave it as it is in the database.

309 FUNCTION {format.title}
310 { title empty$
311  { "" }
312 ⟨atit − lower⟩  { title "t" change.case$ }

313 ⟨!atit − lower⟩ 'title

314 if$

315 }

316

By default, BibTEX sets the global integer variable global.max$ to the BibTEX constant glob_str_size, the maximum length of a global string variable. Analogously, BibTEX sets the global integer variable entry.max$ to ent_str_size, the maximum length of an entry string variable. The style designer may change these if necessary (but this is unlikely).

The n.dashify function makes each single - in a string a double -- if it’s not already.

pseudoVAR: pageresult: STRING (it’s what’s accumulated on the stack)

  n.dashify(s) ==
   BEGIN
        t := s
        pageresult := ""
        while (not empty$(t))
          do
            if (first character of t = "-")
              then
                if (next character isn't)
                  then
                    pageresult := pageresult * "--"
                    t := t with the "-" removed
                  else
                    while (first character of t = "-")
                      do
                        pageresult := pageresult * "-"
                        t := t with the "-" removed
                      od
                fi
              else
                pageresult := pageresult * the first character
                t := t with the first character removed
            fi
          od
        return pageresult
   END

317 FUNCTION {n.dashify}
318 { 't :=

319 ""

320  { t empty$ not }
321  { t #1 #1 substring$ "-" =
322  { t #1 #2 substring$ "--" = not
323  { "--" *
324  t #2 global.max$ substring$ 't :=

325 }

326  {   { t #1 #1 substring$ "-" = }
327  { "-" *
328  t #2 global.max$ substring$ 't :=

329 }

330  while$

331 }

332  if$

333 }

334  { t #1 #1 substring$ *
335  t #2 global.max$ substring$ 't :=

336 }

337  if$

339 while$

340 }

341

The format.date function is for the month and year, but we give a warning if there’s an empty year but the month is there, and we return the empty string if they’re both empty.

342 FUNCTION {format.date}
343 { year empty$
344  { month empty$
345  { "" }
346  { "there's a month but no year in " cite$ * warning$
347  month

348 }

349  if$

350 }

351  { month empty$
352  'year
353  { month " " * year * }
354  if$

355 }

356 if$

357 }

358

The format.btitle is for formatting the title field when it is a book-like entry—the style used here keeps it in uppers-and-lowers and emphasizes it.

359 FUNCTION {format.btitle}
360 { title emphasize

361 }

362

For several functions we’ll need to connect two strings with a tie (~) if the second one isn’t very long (fewer than 3 characters). The tie.or.space.connect function does that. It concatenates the two strings on top of the stack, along with either a tie or space between them, and puts this concatenation back onto the stack:

 tie.or.space.connect(str1,str2) ==
    BEGIN
       if text.length$(str2) < 3
         then return the concatenation of str1, "~", and str2
         else return the concatenation of str1, " ", and str2
    END

363 FUNCTION {tie.or.space.connect}
364 { duplicate$ text.length$ #3 <

365  { "~" }
366  { " " }
367 if$
368 swap$ * *

369 }

370

The either.or.check function complains if both fields or an either-or pair are nonempty.

  either.or.check(t,s) ==
   BEGIN
        if empty$(s) then
            warning$(can't use both " * t * " fields in " * cite$)
        fi
   END

371 FUNCTION {either.or.check}
372 { empty$
373  'pop$
374  { "can't use both " swap$ * " fields in " * cite$ * warning$ }
375 if$

376 }

377

The format.bvolume function is for formatting the volume and perhaps series name of a multivolume work. If both a volume and a series field are there, we assume the series field is the title of the whole multivolume work (the title field should be the title of the thing being referred to), and we add an “of series”. This function is called in mid-sentence.

378 FUNCTION {format.bvolume}
379 { volume empty$
380  { "" }
381  { "volume" volume tie.or.space.connect
382  series empty$
383  'skip$
384  { " of " * series emphasize * }
385  if$
386  "volume and number" number either.or.check

387 }

388 if$

389 }

7.4 Formats for Special Fields

The format.number.series function is for formatting the series name and perhaps number of a work in a series. This function is similar to format.bvolume, although for this one the series must exist (and the volume must not exist). If the number field is empty we output either the series field unchanged if it exists or else the null string. If both the number and series fields are there we assume the series field gives the name of the whole series (the title field should be the title of the work being one referred to), and we add an “in series”. We capitalize “Number” when this function is used at the beginning of a block.

391 FUNCTION {format.number.series}
392 { volume empty$
393  { number empty$
394  { series field.or.null }
395  { output.state mid.sentence =
396  { "number" }
397  { "Number" }
398  if$
399  number tie.or.space.connect
400  series empty$
401  { "there's a number but no series in " cite$ * warning$ }
402  { " in " * series * }
403  if$

404 }

405  if$

406 }

407  { "" }
408 if$

409 }

410

The format.edition function appends “edition” to the edition, if present. We lowercase the edition (it should be something like “Third”), because this doesn’t start a sentence.

411 FUNCTION {format.edition}
412 { edition empty$
413  { "" }
414  { output.state mid.sentence =
415  { edition "l" change.case$ " edition" * }
416  { edition "t" change.case$ " edition" * }
417  if$

418 }

419 if$

420 }

The format.pages function is used for formatting a page range in a book (and in rare circumstances, an article).

The multi.page.check function examines the pages field for a - or , or + so that format.pages can use “page” instead of “pages” if none exists. Note: global.max$ here means “take the rest of the string”.

VAR: multiresult: INTEGER (actually, a boolean)

  multi.page.check(s) ==
   BEGIN
        t := s
        multiresult := false
        while ((not multiresult) and (not empty$(t)))
          do
            if (first character of t = "-" or "," or "+")
              then multiresult := true
              else t := t with the first character removed
            fi
          od
        return multiresult
   END

422

423 INTEGERS { multiresult }

424

425 FUNCTION {multi.page.check}
426 { 't :=
427 #0 'multiresult :=
428  { multiresult not
429  t empty$ not
430  and

431 }

432  { t #1 #1 substring$
433  duplicate$ "-" =
434  swap$ duplicate$ "," =
435  swap$ "+" =
436  or or
437  { #1 'multiresult := }
438  { t #2 global.max$ substring$ 't := }
439  if$

440 }

441 while$
442 multiresult

443 }

This function doesn’t begin a sentence so “pages” isn’t capitalized. Other functions that use this should keep that in mind.

445 FUNCTION {format.pages}
446 { pages empty$
447  { "" }
448  { pages multi.page.check
449  { "pages" pages n.dashify tie.or.space.connect }
450  { "page" pages tie.or.space.connect }
451  if$

452 }

453 if$

454 }

455

The format.vol.num.pages function is for the volume, number, and page range of a journal article. We use the format: vol(number):pages, with some variations for empty fields. This doesn’t begin a sentence.

456 FUNCTION {format.vol.num.pages}
457 { volume field.or.null
458 number empty$
459  'skip$
460  { "\penalty0 (" number * ")" * *
461  volume empty$
462  { "there's a number but no volume in " cite$ * warning$ }
463  'skip$
464  if$

465 }

466 if$
467 pages empty$
468  'skip$
469  { duplicate$ empty$
470  { pop$ format.pages }
471  { ":\penalty0 " * pages n.dashify * }
472  if$

473 }

474 if$

475 }

476

The format.chapter.pages, if the chapter is present, puts whatever is in the type field (or else “chapter” if type is empty) in front of a chapter number. It then appends the pages, if present. This doesn’t begin a sentence.

477 FUNCTION {format.chapter.pages}
478 { chapter empty$
479  'format.pages
480  { type empty$
481  { "chapter" }
482  { type "l" change.case$ }

483  if$
484  chapter tie.or.space.connect
485  pages empty$
486  'skip$
487  { ", " * format.pages * }
488  if$

489 }

490 if$

491 }

492

The format.in.ed.booktitle function is used for starting out a sentence that begins “In booktitle”, putting an editor before the title if one exists.

493 FUNCTION {format.in.ed.booktitle}
494 { booktitle empty$
495  { "" }
496  { editor empty$
497  { "In " booktitle emphasize * }
498  { "In " format.editors * ", " * booktitle emphasize * }
499  if$

500 }

501 if$

502 }

503

The function empty.misc.check complains if all six fields are empty, and if there’s been no sorting or alphabetic-label complaint.

504 FUNCTION {empty.misc.check}
505 { author empty$ title empty$ howpublished empty$
506 month empty$ year empty$ note empty$
507 and and and and and
508 ⟨sorted⟩ key empty$ not and

509 ⟨!sorted & lab − alph⟩ key empty$ not and

510  { "all relevant fields are empty in " cite$ * warning$ }
511  'skip$
512 if$

513 }

514

The function format.thesis.type returns either the (case-changed) type field, if it is defined, or else the default string already on the stack (like “Master’s thesis” or “PhD thesis”).

515 FUNCTION {format.thesis.type}
516 { type empty$
517  'skip$
518  { pop$
519  type "t" change.case$

521 if$

522 }

523

The function format.tr.number makes a string starting with “Technical Report” (or type, if that field is defined), followed by the number if there is one; it returns the starting part (with a case change) even if there is no number. This is used at the beginning of a sentence.

524 FUNCTION {format.tr.number}
525 { type empty$
526  { "Technical Report" }
527  'type
528 if$
529 number empty$
530  { "t" change.case$ }
531  { number tie.or.space.connect }
532 if$

533 }

534

7.5 Cross-Reference Format Functions

Now come the cross-referencing functions (these are invoked because one entry in the database file(s) cross-references another, by giving the other entry’s database key in a crossref field). This feature allows one or more titled things that are part of a larger titled thing to cross-reference the larger thing. These styles allow for five posibilities:

1. an ARTICLE may cross-reference an ARTICLE;

  2. a BOOK,
  3. INBOOK, or

4. INCOLLECTION may cross-reference a BOOK; or

  5. an INPROCEEDINGS may cross-reference a PROCEEDINGS.

Each of these is explained in more detail later.

An ARTICLE entry type may cross reference another ARTICLE (this is intended for when an entire journal is devoted to a single topic—but since there is no JOURNAL entry type, the journal, too, should be classified as an ARTICLE but without the author and title fields). This will result in two warning messages for the journal’s entry if it’s included in the reference list, but such is life.

  format.article.crossref ==
   BEGIN
        if empty$(key) then
            if empty$(journal) then
                warning$("need key or journal for " * cite$ *
                                                " to crossref " * crossref)
                return(" \cite{" * crossref * "}")
            else
                return("In " * emphasize.correct (journal) *
                                                " \cite{" * crossref * "}")
                fi
        else
            return("In " * key * " \cite{" * crossref * "}")
        fi
   END

The other cross-referencing functions are similar, so no “comment version” will be given for them.

535 FUNCTION {format.article.crossref}
536 { key empty$
537  { journal empty$
538  { "need key or journal for " cite$ * " to crossref " * crossref *
539  warning$

540 "" 541 }

542 ⟨!nfss⟩  { "In {\em " journal * "\/}" * }
543 ⟨nfss⟩  { "In \emph{" journal * "}" * }
544  if$

545 }

546  { "In " key * }
547 if$
548 " \cite{" * crossref * "}" *

549 }

550

We use just the last names of editors for a cross reference: either “editor”, or “editor1 and editor2”, or “editor1 et al.” depending on whether there are one, or two, or more than two editors.

551 FUNCTION {format.crossref.editor}
552 { editor #1 "{vv~}{ll}" format.name$
553 editor num.names$ duplicate$
554 #2 >
555  { pop$ " et~al." * }
556  { #2 <
557  'skip$
558  { editor #2 "{ff }{vv }{ll}{ jj}" format.name$ "others" =
559  { " et~al." * }

560  { " and " * editor #2 "{vv~}{ll}" format.name$ * }
561  if$

562 }

563  if$

564 }

565 if$

566 }

567

A BOOK (or INBOOK) entry type (assumed to be for a single volume in a multivolume work) may cross reference another BOOK (the entire multivolume). Usually there will be an editor, in which case we use that to construct the cross reference; otherwise we use a nonempty key field or else the series field (since the series gives the title of the multivolume work).

568 FUNCTION {format.book.crossref}
569 { volume empty$
570  { "empty volume in " cite$ * "'s crossref of " * crossref * warning$
571  "In "

572 }

573  { "Volume" volume tie.or.space.connect
574  " of " *

575 }

576 if$
577 editor empty$
578 editor field.or.null author field.or.null =

579 or

580  { key empty$
581  { series empty$
582  { "need editor, key, or series for " cite$ * " to crossref " *
583  crossref * warning$
584  "" *

585 }

586 ⟨!nfss⟩  { "{\em " * series * "\/}" * }
587 ⟨nfss⟩  { "\emph{" * series * "}" * }
588  if$

589 }

590  { key * }
591  if$

592 }

593  { format.crossref.editor * }
594 if$
595 " \cite{" * crossref * "}" *

596 }

597

An INCOLLECTION entry type may cross reference a BOOK (assumed to be the collection), or an INPROCEEDINGS may cross reference a PROCEEDINGS. Often there will be an editor, in which case we use that to construct the cross reference; otherwise we use a nonempty key field or else the booktitle field (which gives the cross-referenced work’s title).

598 FUNCTION {format.incoll.inproc.crossref}
599 { editor empty$
600 editor field.or.null author field.or.null =

601 or

602  { key empty$
603  { booktitle empty$
604  { "need editor, key, or booktitle for " cite$ * " to crossref " *
605  crossref * warning$

606 "" 607 }

608 ⟨!nfss⟩  { "In {\em " booktitle * "\/}" * }
609 ⟨nfss⟩  { "In \emph{" booktitle * "}" * }
610  if$

611 }

612  { "In " key * }
613  if$

614 }

615  { "In " format.crossref.editor * }
616 if$
617 " \cite{" * crossref * "}" *

618 }

619

8 The Entry Type Functions

Now we define the type functions for all entry types that may appear in the .bib file—e.g., functions like article and book. These are the routines that actually generate the .bbl-file output for the entry. These must all precede the READ command. In addition, the style designer should have a function default.type for unknown types. Note: The fields (within each list) are listed in order of appearance, except as described for an inbook or

a proceedings.

8.1 The article Function

The article function is for an article in a journal. An article may CROSSREF another article.

 Required fields: author, title, journal, year
 Optional fields: volume, number, pages, month, note
 article ==

8 THE ENTRY TYPE FUNCTIONS 35

BEGIN
output.bibitem
output.check(format.authors,"author")
new.block
output.check(format.title,"title")
new.block
if missing$(crossref) then
    output.check(emphasize(journal),"journal")
    output(format.vol.num.pages)
    output.check(format.date,"year")
else
    output.nonnull(format.article.crossref)
    output(format.pages)
fi
new.block
output(note)
fin.entry
END

8.2 The book Function

The book function is for a whole book. A book may CROSSREF another book.

Required fields: author or editor, title, publisher, year
Optional fields: volume or number, series, address, edition, month,
note
book ==
BEGIN
if empty$(author) then output.check(format.editors,"author and editor")
else    output.check(format.authors,"author")
        if missing$(crossref) then
            either.or.check("author and editor",editor)
        fi
fi
new.block
output.check(format.btitle,"title")
if missing$(crossref) then
    output(format.bvolume)
    new.block
    output(format.number.series)
    new.sentence
    output.check(publisher,"publisher")
    output(address)
else
    new.block

            output.nonnull(format.book.crossref)
        fi
        output(format.edition)
        output.check(format.date,"year")
        new.block
        output(note)
        fin.entry
   END

The other entry functions are all quite similar, so no “comment version” will be given for them.

620 FUNCTION {article}
621 { output.bibitem
622 format.authors "author" output.check
623 new.block
624 format.title "title" output.check
625 new.block
626 crossref missing$
627  { journal emphasize "journal" output.check
628  format.vol.num.pages output
629  format.date "year" output.check

630 }

631  { format.article.crossref output.nonnull
632  format.pages output

633 }

634 if$
635 new.block
636 note output
637 fin.entry

638 }

639

640 FUNCTION {book}
641 { output.bibitem
642 author empty$
643  { format.editors "author and editor" output.check }
644  { format.authors output.nonnull
645  crossref missing$
646  { "author and editor" editor either.or.check }
647  'skip$
648  if$

649 }

650 if$
651 new.block
652 format.btitle "title" output.check
653 crossref missing$
654  { format.bvolume output
655  new.block

656  format.number.series output
657  new.sentence
658  publisher "publisher" output.check
659  address output

660 }

661  { new.block
662  format.book.crossref output.nonnull

663 }

664 if$
665 format.edition output
666 format.date "year" output.check
667 format.isbn output
668 new.block
669 note output
670 fin.entry

671 }

672

8.3 The booklet Function

A booklet is a bound thing without a publisher or sponsoring institution.

Required: title

  Optional: author, howpublished, address, month, year, note
673 FUNCTION {booklet}
674 { output.bibitem
675 format.authors output
676 new.block
677 format.title "title" output.check
678 howpublished address new.block.checkb
679 howpublished output
680 address output
681 format.date output
682 format.isbn output
683 new.block
684 note output
685 fin.entry

686 }

687

8.4 The inbook Function

For the conference entry type, see inproceedings.

An inbook is a piece of a book: either a chapter and/or a page range. It may CROSSREF a book. If there’s no volume field, the type field will come before number and series.

  Required: author or editor, title, chapter and/or pages, publisher,
     year
  Optional: volume or number, series, type, address, edition, month,
     note
688 FUNCTION {inbook}
689 { output.bibitem
690 author empty$
691  { format.editors "author and editor" output.check }
692  { format.authors output.nonnull
693  crossref missing$
694  { "author and editor" editor either.or.check }
695  'skip$
696  if$

697 }

698 if$
699 new.block
700 format.btitle "title" output.check
701 crossref missing$
702  { format.bvolume output
703  format.chapter.pages "chapter and pages" output.check
704  new.block
705  format.number.series output
706  new.sentence
707  publisher "publisher" output.check
708  address output

709 }

710  { format.chapter.pages "chapter and pages" output.check
711  new.block
712  format.book.crossref output.nonnull

713 }

714 if$
715 format.edition output
716 format.date "year" output.check
717 format.isbn output
718 new.block
719 note output
720 fin.entry

721 }

722

8.5 The incollection Function

An incollection is like inbook, but where there is a separate title for the referenced thing (and perhaps an editor for the whole). An incollection may CROSSREF a book.

  Required: author, title, booktitle, publisher, year
  Optional: editor, volume or number, series, type, chapter, pages,
     address, edition, month, note
723 FUNCTION {incollection}
724 { output.bibitem
725 format.authors "author" output.check
726 new.block
727 format.title "title" output.check
728 new.block
729 crossref missing$
730  { format.in.ed.booktitle "booktitle" output.check
731  format.bvolume output
732  format.number.series output
733  format.chapter.pages output
734  new.sentence
735  publisher "publisher" output.check
736  address output
737  format.edition output
738  format.date "year" output.check

739 }

740  { format.incoll.inproc.crossref output.nonnull
741  format.chapter.pages output

742 }

743 if$
744 format.isbn output
745 new.block
746 note output
747 fin.entry

748 }

749

8.6 The inproceedings Function

An inproceedings is an article in a conference proceedings, and it may CROSSREF a proceedings. If there’s no address field, the month (and year) will appear just before note.

  Required: author, title, booktitle, year
  Optional: editor, volume or number, series, pages, address, month,
     organization, publisher, note
750 FUNCTION {inproceedings}
751 { output.bibitem
752 format.authors "author" output.check
753 new.block

754 format.title "title" output.check
755 new.block
756 crossref missing$
757  { format.in.ed.booktitle "booktitle" output.check
758  format.bvolume output
759  format.number.series output
760  format.pages output
761  address empty$
762  { organization publisher new.sentence.checkb
763  organization output
764  publisher output
765  format.date "year" output.check

766 }

767  { address output.nonnull
768  format.date "year" output.check
769  new.sentence
770  organization output
771  publisher output

772 }

773  if$

774 }

775  { format.incoll.inproc.crossref output.nonnull
776  format.pages output

777 }

778 if$
779 format.isbn output
780 new.block
781 note output
782 fin.entry

783 }

784

The conference function is included for Scribe compatibility.

785 FUNCTION {conference} { inproceedings }

786

8.7 The manual Function

A manual is technical documentation.

Required: title

  Optional: author, organization, address, edition, month, year, note
787 FUNCTION {manual}
788 { output.bibitem
789 author empty$
790  { organization empty$

791  'skip$
792  { organization output.nonnull
793  address output

794 }

795  if$

796 }

797  { format.authors output.nonnull }
798 if$
799 new.block
800 format.btitle "title" output.check
801 author empty$
802  { organization empty$
803  { address new.block.checka
804  address output

805 }

806  'skip$
807  if$

808 }

809  { organization address new.block.checkb
810  organization output
811  address output

812 }

813 if$
814 format.edition output
815 format.date output
816 new.block
817 note output
818 fin.entry

819 } 820 %

8.8 The mastersthesis Function

A mastersthesis is a Master’s thesis.

  Required: author, title, school, year
  Optional: type, address, month, note
821 FUNCTION {mastersthesis}
822 { output.bibitem
823 format.authors "author" output.check
824 new.block
825 format.title "title" output.check
826 new.block
827 "Master's thesis" format.thesis.type output.nonnull
828 school "school" output.check
829 address output
830 format.date "year" output.check

831 new.block
832 note output
833 fin.entry

834 }

835

8.9 The misc Function

A misc is something that doesn’t fit elsewhere.

Required: at least one of the ‘optional’ fields

  Optional: author, title, howpublished, month, year, note
836 FUNCTION {misc}
837 { output.bibitem
838 format.authors output
839 title howpublished new.block.checkb
840 format.title output
841 howpublished new.block.checka
842 howpublished output
843 format.date output
844 format.issn output
845 new.block
846 note output
847 fin.entry
848 empty.misc.check

849 }

850

8.10 The phdthesis Function

A phdthesis is like a mastersthesis.

  Required: author, title, school, year
  Optional: type, address, month, note
851 FUNCTION {phdthesis}
852 { output.bibitem
853 format.authors "author" output.check
854 new.block
855 format.btitle "title" output.check
856 new.block
857 "PhD thesis" format.thesis.type output.nonnull
858 school "school" output.check
859 address output
860 format.date "year" output.check

861 new.block
862 note output
863 fin.entry

864 }

865

8.11 The periodical Function

(This is not part of the standard styles, but is an addition in xbtxbst.doc. —PWD)

A periodical is a publication that appears at regular intervals. This includes journals, magazines, and newspapers. If there is an organization but no editor field, the organization will appear as the first optional field (we try to make the first block nonempty); if there’s no address field, the month (and year) will appear just before note.

Required: title, key

 Optional: editor, volume, number, series, address, month, year,
     organization, publisher, note, issn, howpublished
866 FUNCTION {periodical}
867 { output.bibitem
868 editor empty$
869  { organization output }
870  { format.editors output.nonnull }
871 if$
872 new.block
873 title emphasize "title" output.check
874 %  format.bvolume output
875 %  format.number.series output
876 format.vol.num.pages output
877 format.date output
878 format.issn output
879 new.sentence
880 publisher output
881 address output
882 howpublished new.block.checka
883 howpublished output
884 new.block
885 note output
886 fin.entry

887 }

8.12 The proceedings Function

A proceedings is a conference proceedings. If there is an organization but no editor field, the organization will appear as the first optional field (we try to make the first block nonempty); if there’s no address field, the month (and year) will appear just before note.

Required: title, year

  Optional: editor, volume or number, series, address, month, organization,
     publisher, note
889 FUNCTION {proceedings}
890 { output.bibitem
891 editor empty$
892  { organization output }
893  { format.editors output.nonnull }
894 if$
895 new.block
896 format.btitle "title" output.check
897 format.bvolume output
898 format.number.series output
899 address empty$
900  { editor empty$
901  { publisher new.sentence.checka }
902  { organization publisher new.sentence.checkb
903  organization output

904 }

905  if$
906  publisher output
907  format.date "year" output.check

908 }

909  { address output.nonnull
910  format.date "year" output.check
911  new.sentence
912  editor empty$
913  'skip$
914  { organization output }
915  if$
916  publisher output

917 }

918 if$
919 format.isbn output
920 new.block
921 note output
922 fin.entry

923 }

8.13 The techreport Function

A techreport is a technical report.

  Required: author, title, institution, year
  Optional: type, number, address, month, note
925 FUNCTION {techreport}
926 { output.bibitem
927 format.authors "author" output.check
928 new.block
929 format.title "title" output.check
930 new.block
931 format.tr.number output.nonnull
932 institution "institution" output.check
933 address output
934 format.date "year" output.check
935 new.block
936 note output
937 fin.entry

938 }

939

8.14 The unpublished Function

An unpublished is something that hasn’t been published.

  Required: author, title, note

Optional: month, year

940 FUNCTION {unpublished}
941 { output.bibitem
942 format.authors "author" output.check
943 new.block
944 format.title "title" output.check
945 new.block
946 note "note" output.check
947 format.date output
948 fin.entry

949 }

950

8.15 The default.type Function

We use entry type misc for an unknown type; BibTEX gives a warning.

9 COMMON FEATURES 46

951 FUNCTION {default.type} { misc }

952

9 Common Features

Here are macros for common things that may vary from style to style. Users are encouraged to use these macros.

9.1 The Months

Months are either written out in full or abbreviated

953 ⟨∗month − full⟩

954

955 MACRO {jan} {"January"}

956

957 MACRO {feb} {"February"}

958

959 MACRO {mar} {"March"}

960

961 MACRO {apr} {"April"}

962

963 MACRO {may} {"May"}

964

965 MACRO {jun} {"June"}

966

967 MACRO {jul} {"July"}

968

969 MACRO {aug} {"August"}

970

971 MACRO {sep} {"September"}

972

973 MACRO {oct} {"October"}

974

975 MACRO {nov} {"November"}

976

977 MACRO {dec} {"December"}

978

979 ⟨/month − full⟩ 980 ⟨∗!month − full⟩

981

982 MACRO {jan} {"Jan."}

983

984 MACRO {feb} {"Feb."}

985

986 MACRO {mar} {"Mar."}

 988 MACRO {apr} {"Apr."}

989

 990 MACRO {may} {"May"}

991

 992 MACRO {jun} {"June"}

993

 994 MACRO {jul} {"July"}

995

 996 MACRO {aug} {"Aug."}

997

 998 MACRO {sep} {"Sept."}

999

1000 MACRO {oct} {"Oct."}

1001

1002 MACRO {nov} {"Nov."}

1003

1004 MACRO {dec} {"Dec."}

1005

1006 ⟨/!month − full⟩

1007

9.2 Journal Names

Journals are either written out in full or abbreviated; the abbreviations are like those found in ACM publications.

To get a completely different set of abbreviations, it may be best to make a separate .bib file with nothing but those abbreviations; users could then include that file name as the first argument to the \bibliography command.

1008 ⟨∗jour − full⟩

1009

1010 MACRO {acmcs} {"ACM Computing Surveys"}

1011

1012 MACRO {acta} {"Acta Informatica"}

1013

1014 MACRO {cacm} {"Communications of the ACM"}

1015

1016 MACRO {ibmjrd} {"IBM Journal of Research and Development"}

1017

1018 MACRO {ibmsj} {"IBM Systems Journal"}

1019

1020 MACRO {ieeese} {"IEEE Transactions on Software Engineering"}

1021

1022 MACRO {ieeetc} {"IEEE Transactions on Computers"}

1023

1024 MACRO {ieeetcad}
1025 {"IEEE Transactions on Computer-Aided Design of Integrated Circuits"}

1027 MACRO {ipl} {"Information Processing Letters"}

1028

1029 MACRO {jacm} {"Journal of the ACM"}

1030

1031 MACRO {jcss} {"Journal of Computer and System Sciences"}

1032

1033 MACRO {scp} {"Science of Computer Programming"}

1034

1035 MACRO {sicomp} {"SIAM Journal on Computing"}

1036

1037 MACRO {tocs} {"ACM Transactions on Computer Systems"}

1038

1039 MACRO {tods} {"ACM Transactions on Database Systems"}

1040

1041 MACRO {tog} {"ACM Transactions on Graphics"}

1042

1043 MACRO {toms} {"ACM Transactions on Mathematical Software"}

1044

1045 MACRO {toois} {"ACM Transactions on Office Information Systems"}

1046

1047 MACRO {toplas} {"ACM Transactions on Programming Languages and Systems"}

1048

1049 MACRO {tcs} {"Theoretical Computer Science"}

1050

1051 ⟨/jour − full⟩ 1052 ⟨∗!jour − full⟩

1053

1054 MACRO {acmcs} {"ACM Comput. Surv."}

1055

1056 MACRO {acta} {"Acta Inf."}

1057

1058 MACRO {cacm} {"Commun. ACM"}

1059

1060 MACRO {ibmjrd} {"IBM J. Res. Dev."}

1061

1062 MACRO {ibmsj} {"IBM Syst.~J."}

1063

1064 MACRO {ieeese} {"IEEE Trans. Softw. Eng."}

1065

1066 MACRO {ieeetc} {"IEEE Trans. Comput."}

1067

1068 MACRO {ieeetcad}
1069 {"IEEE Trans. Comput.-Aided Design Integrated Circuits"}

1070

1071 MACRO {ipl} {"Inf. Process. Lett."}

1072

1073 MACRO {jacm} {"J.~ACM"}

1074

1075 MACRO {jcss} {"J.~Comput. Syst. Sci."}

10 PROCESSING 49

1076

1077 MACRO {scp} {"Sci. Comput. Programming"}

1078

1079 MACRO {sicomp} {"SIAM J. Comput."}

1080

1081 MACRO {tocs} {"ACM Trans. Comput. Syst."}

1082

1083 MACRO {tods} {"ACM Trans. Database Syst."}

1084

1085 MACRO {tog} {"ACM Trans. Gr."}

1086

1087 MACRO {toms} {"ACM Trans. Math. Softw."}

1088

1089 MACRO {toois} {"ACM Trans. Office Inf. Syst."}

1090

1091 MACRO {toplas} {"ACM Trans. Prog. Lang. Syst."}

1092

1093 MACRO {tcs} {"Theoretical Comput. Sci."}

1094

1095 ⟨/!jour − full⟩

1096

10 Processing

10.1 Input the Entries

Now we read in the .bib entries.

1097 READ

1098

10.2 Auxiliary Functions for Labels

The sortify function converts to lower case after purify$ing; it’s used in sorting and in computing alphabetic labels after sorting.

The chop.word(w,len,s) function returns either s or, if the first len letters of s equals w (this comparison is done in the third line of the function’s definition), it returns that part of s after w.

1099 ⟨∗sorted⟩

1100

1101 FUNCTION {sortify}
1102 { purify$
1103 "l" change.case$

1104 }

1106 INTEGERS { len }

1107

1108 FUNCTION {chop.word}
1109 { 's :=
1110 'len :=
1111 s #1 len substring$ =
1112  { s len #1 + global.max$ substring$ }

1113 's 1114 if$ 1115 }

1116

1117 ⟨/sorted⟩ 1118 ⟨∗lab − alph&!sorted⟩

1119

We need the chop.word stuff for the dubious unsorted-list-with-labels case.

1120 INTEGERS { len }

1121

1122 FUNCTION {chop.word}
1123 { 's :=
1124 'len :=
1125 s #1 len substring$ =
1126  { s len #1 + global.max$ substring$ }

1127 's 1128 if$ 1129 }

1130

1131 ⟨/lab − alph&!sorted⟩

1132

10.3 Making Labels

This long comment applies only to alphabetic labels.

The format.lab.names function makes a short label by using the initials of the von and Last parts of the names (but if there are more than four names, (i.e., people) it truncates after three and adds a superscripted +; it also adds such a + if the last of multiple authors is “others”). If there is only one name, and its von and Last parts combined have just a single name-token (“Knuth” has a single token, “Brinch Hansen” has two), we take the first three letters of the last name. The boolean et.al.char.used tells whether we’ve used a superscripted +, so that we know whether to include a L^{A}TEX macro for it.

 format.lab.names(s) ==
  BEGIN
       numnames := num.names$(s)

       if numnames > 1 then
           if numnames > 4 then
               namesleft := 3
           else
               namesleft := numnames
           nameptr := 1
           nameresult := ""
           while namesleft > 0
             do
               if (name_ptr = numnames) and
                    format.name$(s, nameptr, "{ff }{vv }{ll}{ jj}") = "others"
                  then nameresult := nameresult * "{\etalchar{+}}"
                       et.al.char.used := true
                  else nameresult := nameresult *
                               format.name$(s, nameptr, "{v{}}{l{}}")
               nameptr := nameptr + 1
               namesleft := namesleft - 1
             od
           if numnames > 4 then
               nameresult := nameresult * "{\etalchar{+}}"
               et.al.char.used := true
       else
           t := format.name$(s, 1, "{v{}}{l{}}")
           if text.length$(t) < 2 then % there's just one name-token
               nameresult := text.prefix$(format.name$(s,1,"{ll}"),3)
           else
               nameresult := t
           fi
       fi
       return nameresult
  END

Exactly what fields we look at in constructing the primary part of the label depends on the entry type; this selectivity (as opposed to, say, always looking at author, then editor, then key) helps ensure that “ignored” fields, as described in the L^{A}TEX book, really are ignored. Note that MISC is part of the deepest ‘else’ clause in the nested part of calc.label; thus, any unrecognized entry type in the database is handled correctly.

There is one auxiliary function for each of the four different sequences of fields we use. The first of these functions looks at the author field, and then, if necessary, the key field. The other three functions, which might look at two fields and the key field, are similar, except that the key field takes precedence over the organization field (for labels—not for sorting).

The calc.label function calculates the preliminary label of an entry, which is formed by taking three letters of information from the author or editor or key or organization field (depending on the entry type and on what’s empty, but ignoring a leading “The ” in the organization), and appending the last two characters (digits) of the year. It is an error if the appropriate fields among author, editor, organization, and key are missing, and we use the first three letters of the cite$ in desperation when this happens. The resulting label has the year part, but not the name part, purify$ed (purify$ing the year allows some sorting shenanigans by the user).

This function also calculates the version of the label to be used in sorting.

The final label may need a trailing ‘a’, ‘b’, etc., to distinguish it from otherwise identical labels, but we can’t calculated those extra.labels until after sorting.

   calc.label ==
    BEGIN
         if type$ = "book" or "inbook" then
             author.editor.key.label
         else if type$ = "proceedings" then
             editor.key.organization.label
         else if type$ = "manual" then
             author.key.organization.label
         else
             author.key.label
         fi fi fi
         label := label * substring$(purify$(field.or.null(year)), -1, 2)
                 % assuming we will also sort, we calculate a sort.label
         sort.label := sortify(label), but use the last four, not two, digits
    END

1133 ⟨∗lab − alph⟩

1134

1135 INTEGERS { et.al.char.used }

1136

1137 FUNCTION {initialize.et.al.char.used}
1138 { #0 'et.al.char.used :=

1139 }

1140

1141 EXECUTE {initialize.et.al.char.used}

1142

1143 FUNCTION {format.lab.names}
1144 { 's :=
1145 s num.names$ 'numnames :=
1146 numnames #1 >
1147  { numnames #4 >
1148  { #3 'namesleft := }
1149  { numnames 'namesleft := }

1150 if$

1151  #1 'nameptr :=

1152 ""

1153  { namesleft #0 > }
1154  { nameptr numnames =
1155  { s nameptr "{ff }{vv }{ll}{ jj}" format.name$ "others" =
1156  { "{\etalchar{+}}" *
1157  #1 'et.al.char.used :=

1158 }

1159  { s nameptr "{v{}}{l{}}" format.name$ * }

1160 if$ 1161 }

1162  { s nameptr "{v{}}{l{}}" format.name$ * }

1163 if$

1164  nameptr #1 + 'nameptr :=
1165  namesleft #1 - 'namesleft :=

1166 }

1167  while$
1168  numnames #4 >
1169  { "{\etalchar{+}}" *
1170  #1 'et.al.char.used :=

1171 }

1172  'skip$

1173 if$ 1174 }

1175  { s #1 "{v{}}{l{}}" format.name$
1176  duplicate$ text.length$ #2 <
1177  { pop$ s #1 "{ll}" format.name$ #3 text.prefix$ }
1178  'skip$

1179 if$ 1180 } 1181 if$ 1182 }

1183

1184 FUNCTION {author.key.label}
1185 { author empty$
1186  { key empty$
1187 ⟨sorted⟩  { cite$ #1 #3 substring$ }

1188 ⟨∗!sorted⟩

We need a warning here because we won’t give it later

1189  { "for label, need author or key in " cite$ * warning$
1190  cite$ #1 #3 substring$

1191 }

1192 ⟨/!sorted⟩

1193  { key #3 text.prefix$ }

1194 if$ 1195 }

1196  { author format.lab.names }

1197 if$

1199

1200 FUNCTION {author.editor.key.label}
1201 { author empty$
1202  { editor empty$
1203  { key empty$
1204 ⟨sorted⟩  { cite$ #1 #3 substring$ }

1205 ⟨∗!sorted⟩

1206  { "for label, need author, editor, or key in " cite$ * warning$
1207  cite$ #1 #3 substring$

1208 }

1209 ⟨/!sorted⟩

1210  { key #3 text.prefix$ }

1211 if$ 1212 }

1213  { editor format.lab.names }

1214 if$ 1215 }

1216  { author format.lab.names }

1217 if$ 1218 }

1219

1220 FUNCTION {author.key.organization.label}
1221 { author empty$
1222  { key empty$
1223  { organization empty$
1224 ⟨sorted⟩  { cite$ #1 #3 substring$ }

1225 ⟨∗!sorted⟩

1226  { "for label, need author, key, or organization in " cite$ *
1227  warning$
1228  cite$ #1 #3 substring$

1229 }

1230 ⟨/!sorted⟩

1231  { "The " #4 organization chop.word #3 text.prefix$ }

1232 if$ 1233 }

1234  { key #3 text.prefix$ }

1235 if$ 1236 }

1237  { author format.lab.names }

1238 if$ 1239 }

1240

1241 FUNCTION {editor.key.organization.label}
1242 { editor empty$
1243  { key empty$
1244  { organization empty$
1245 ⟨sorted⟩  { cite$ #1 #3 substring$ }

1246 ⟨∗!sorted⟩

1247  { "for label, need editor, key, or organization in " cite$ *

1248  warning$
1249  cite$ #1 #3 substring$

1250 }

1251 ⟨/!sorted⟩

1252  { "The " #4 organization chop.word #3 text.prefix$ }

1253 if$ 1254 }

1255  { key #3 text.prefix$ }

1256 if$ 1257 }

1258  { editor format.lab.names }

1259 if$ 1260 }

1261

1262 FUNCTION {calc.label}
1263 { type$ "book" =
1264 type$ "inbook" =

1265 or

1266  'author.editor.key.label
1267  { type$ "proceedings" =
1268  'editor.key.organization.label
1269  { type$ "manual" =
1270  'author.key.organization.label
1271  'author.key.label

1272 if$ 1273 } 1274 if$ 1275 } 1276 if$

1277 duplicate$
1278 year field.or.null purify$ #-1 #2 substring$

1279 *

1280 'label :=
1281 year field.or.null purify$ #-1 #4 substring$

1282 *

1283 sortify 'sort.label :=

1284 }

1285

10.4 Sorting

It doesn’t seem like a particularly good idea to use an order-of-citation reference list when using alphabetic labels, but we need to have a special pass to calculate labels when this happens.

1286 ⟨!sorted⟩ITERATE {calc.label}

1287

1288 ⟨/lab − alph⟩ When sorting, we compute the sortkey by executing presort on each entry. The presort key contains a number of sortifyed strings, concatenated with multiple blanks between them. This makes things like “brinch per” come before “brinch hansen per”.

The fields used here are: the sort.label for alphabetic labels (as set by calc.label), followed by the author names (or editor names or organization (with a leading “The ” removed) or key field, depending on entry type and on what’s empty), followed by year, followed by the first bit of the title (chopping off a leading “The ”, “A ”, or “An ”). Names are formatted: Von Last First Junior. The names within a part will be separated by a single blank (such as “brinch hansen”), two will separate the name parts themselves (except the von and last), three will separate the names, four will separate the names from year (and from label, if alphabetic), and four will separate year from title.

The sort.format.names function takes an argument that should be in BibTEX name format, and returns a string containing “␣␣␣”-separated names in the format described above. The function is almost the same

as format.names.

1290 ⟨∗sorted⟩

1291

1292 FUNCTION {sort.format.names}
1293 { 's :=
1294 #1 'nameptr :=

1295 ""

1296 s num.names$ 'numnames :=
1297 numnames 'namesleft :=
1298  { namesleft #0 > }
1299  { nameptr #1 >
1300  { "   " * }
1301  'skip$

1302 if$

1303 ⟨name − full⟩  s nameptr "{vv{ } }{ll{ }}{  ff{ }}{  jj{ }}" format.name$ 't :=
1304 ⟨!name − full⟩  s nameptr "{vv{ } }{ll{ }}{  f{ }}{  jj{ }}" format.name$ 't :=
1305  nameptr numnames = t "others" = and
1306  { "et al" * }
1307  { t sortify * }

1308 if$

1309  nameptr #1 + 'nameptr :=
1310  namesleft #1 - 'namesleft :=

1311 }

1312 while$

1313 }

1314

The sort.format.title function returns the argument, but first any leading “A ” ’s, “An ” ’s, or “The ” ’s are removed. The chop.word function uses s, so we need another string variable, t.

1315 FUNCTION {sort.format.title}
1316 { 't :=
1317 "A " #2
1318  "An " #3
1319  "The " #4 t chop.word
1320  chop.word
1321 chop.word
1322 sortify
1323 #1 global.max$ substring$

1324 }

1325

The auxiliary functions here, for the presort function, are analogous to the ones for calc.label; the same comments apply, except that the organization field takes precedence here over the key field. For sorting purposes, we still remove a leading “The ” from the organization field.

1326 FUNCTION {author.sort}
1327 { author empty$
1328  { key empty$
1329  { "to sort, need author or key in " cite$ * warning$

1330 "" 1331 }

1332  { key sortify }

1333 if$ 1334 }

1335  { author sort.format.names }

1336 if$ 1337 }

1338

1339 FUNCTION {author.editor.sort}
1340 { author empty$
1341  { editor empty$
1342  { key empty$
1343  { "to sort, need author, editor, or key in " cite$ * warning$

1344 "" 1345 }

1346  { key sortify }

1347 if$ 1348 }

1349  { editor sort.format.names }

1350 if$ 1351 }

1352  { author sort.format.names }

1353 if$ 1354 }

1355

1356 FUNCTION {author.organization.sort}

1357 { author empty$
1358  { organization empty$
1359  { key empty$
1360  { "to sort, need author, organization, or key in " cite$ * warning$

1361 "" 1362 }

1363  { key sortify }

1364 if$ 1365 }

1366  { "The " #4 organization chop.word sortify }

1367 if$ 1368 }

1369  { author sort.format.names }

1370 if$ 1371 }

1372

1373 FUNCTION {editor.organization.sort}
1374 { editor empty$
1375  { organization empty$
1376  { key empty$
1377  { "to sort, need editor, organization, or key in " cite$ * warning$

1378 "" 1379 }

1380  { key sortify }

1381 if$ 1382 }

1383  { "The " #4 organization chop.word sortify }

1384 if$ 1385 }

1386  { editor sort.format.names }

1387 if$ 1388 }

1389

There is a limit, entry.max$, on the length of an entry string variable (which is what its sort.key$ is), so we take at most that many characters of the constructed key, and hope there aren’t many references that match to that many characters!

1390 FUNCTION {presort}

1391 ⟨∗lab − alph⟩

1392 { calc.label
1393 sort.label

1394 " " 1395 *

1396 type$ "book" =

1397 ⟨/lab − alph⟩

1398 ⟨!lab − alph⟩{ type$ "book" =

1399 type$ "inbook" =

1400 or

1401  'author.editor.sort
1402  { type$ "proceedings" =
1403  'editor.organization.sort
1404  { type$ "manual" =
1405  'author.organization.sort
1406  'author.sort

1407 if$ 1408 } 1409 if$ 1410 } 1411 if$

1412 ⟨lab − alph⟩ *

1413 " " 1414 *

1415 year field.or.null sortify

1416 * 1417 " " 1418 *

1419 title field.or.null
1420 sort.format.title

1421 *

1422 #1 entry.max$ substring$
1423 'sort.key$ :=

1424 }

1425

1426 ITERATE {presort}

1427

And now we can sort.

1428 SORT

1429

1430 ⟨/sorted⟩

1431

10.5 Sorted Alphabetic Labels

This long comment applies only to alphabetic labels, when sorted.

Now comes the final computation for alphabetic labels, putting in the ‘a’s and ‘b’s and so forth if required. This involves two passes: a forward pass to put in the ‘b’s, ‘c’s and so on, and a backwards pass to put in the ‘a’s (we don’t want to put in ‘a’s unless we know there are ‘b’s). We have to keep track of the longest (in width$ terms) label, for use by the thebibliography environment.

     VAR: longest.label, last.sort.label, next.extra: string
     longest.label.width, last.extra.num: integer

initialize.longest.label ==
BEGIN
longest.label := ""
last.sort.label := int.to.chr$(0)
next.extra := ""
longest.label.width := 0
last.extra.num := 0
END
forward.pass ==
BEGIN
if last.sort.label = sort.label then
    last.extra.num := last.extra.num + 1
    extra.label := int.to.chr$(last.extra.num)
else
    last.extra.num := chr.to.int$("a")
    extra.label := ""
    last.sort.label := sort.label
fi
END
reverse.pass ==
BEGIN
if next.extra = "b" then
    extra.label := "a"
fi
label := label * extra.label
if width$(label) > longest.label.width then
    longest.label := label
    longest.label.width := width$(label)
fi
next.extra := extra.label
END

1432 ⟨∗lab − alph⟩ 1433 ⟨∗sorted⟩

1434

1435 STRINGS { longest.label last.sort.label next.extra }

1436

1437 INTEGERS { longest.label.width last.extra.num }

1438

1439 FUNCTION {initialize.longest.label}
1440 { "" 'longest.label :=
1441 #0 int.to.chr$ 'last.sort.label :=
1442 "" 'next.extra :=
1443 #0 'longest.label.width :=
1444 #0 'last.extra.num :=

1446

1447 FUNCTION {forward.pass}
1448 { last.sort.label sort.label =
1449  { last.extra.num #1 + 'last.extra.num :=
1450  last.extra.num int.to.chr$ 'extra.label :=

1451 }

1452  { "a" chr.to.int$ 'last.extra.num :=
1453  "" 'extra.label :=
1454  sort.label 'last.sort.label :=

1455 } 1456 if$ 1457 }

1458

1459 FUNCTION {reverse.pass}
1460 { next.extra "b" =
1461  { "a" 'extra.label := }
1462  'skip$

1463 if$

1464 label extra.label * 'label :=
1465 label width$ longest.label.width >
1466  { label 'longest.label :=
1467  label width$ 'longest.label.width :=

1468 }

1469  'skip$

1470 if$

1471 extra.label 'next.extra :=

1472 }

1473

1474 EXECUTE {initialize.longest.label}

1475

1476 ITERATE {forward.pass}

1477

1478 REVERSE {reverse.pass}

1479

1480 ⟨/sorted⟩ 1481 ⟨∗!sorted⟩

1482

It still doesn’t seem like a good idea to use an order-of-citation reference list when using alphabetic labels, but when this happens we must compute the longest label

1483 STRINGS { longest.label }

1484

1485 INTEGERS { longest.label.width }

1486

1487 FUNCTION {initialize.longest.label}
1488 { "" 'longest.label :=
1489 #0 'longest.label.width :=

1491

1492 FUNCTION {longest.label.pass}
1493 { label width$ longest.label.width >
1494  { label 'longest.label :=
1495  label width$ 'longest.label.width :=

1496 }

1497  'skip$

1498 if$ 1499 }

1500

1501 EXECUTE {initialize.longest.label}

1502

1503 ITERATE {longest.label.pass}

1504

1505 ⟨/!sorted⟩ 1506 ⟨/lab − alph⟩ 1507 ⟨∗!lab − alph⟩

1508

10.6 Numeric Labels

Now comes the computation for numeric labels. We use either the sorted order or original order. We still have to keep track of the longest (in width$ terms) label, for use by the thebibliography environment.

1509 STRINGS { longest.label }

1510

1511 INTEGERS { number.label longest.label.width }

1512

1513 FUNCTION {initialize.longest.label}
1514 { "" 'longest.label :=
1515 #1 'number.label :=
1516 #0 'longest.label.width :=

1517 }

1518

1519 FUNCTION {longest.label.pass}
1520 { number.label int.to.str$ 'label :=
1521 number.label #1 + 'number.label :=
1522 label width$ longest.label.width >
1523  { label 'longest.label :=
1524  label width$ 'longest.label.width :=

1525 }

1526  'skip$

1527 if$ 1528 }

1529

1530 EXECUTE {initialize.longest.label}

1531

1532 ITERATE {longest.label.pass}

1533

1534 ⟨/!lab − alph⟩

1535

10.7 Writing the .bbl File

Now we’re ready to start writing the .bbl file. We begin, if necessary, with a L^{A}TEX macro for unnamed names in an alphabetic label; next comes stuff from the preamble command in the database files. Then we give an incantation containing the command

         \begin{thebibliography}{...}

where the ... is the longest label.

We also call init.state.consts, for use by the output routines.

1536 FUNCTION {begin.bib}

1537 ⟨∗lab − alph⟩

1538 { et.al.char.used
1539  { "\newcommand{\etalchar}[1]{$^{#1}$}" write$ newline$ }
1540  'skip$

1541 if$

1542 preamble$ empty$

1543 ⟨/lab − alph⟩

1544 ⟨!lab − alph⟩{ preamble$ empty$
1545  'skip$
1546  { preamble$ write$ newline$ }

1547 if$

1548 "\begin{thebibliography}{"  longest.label  * "}" * write$ newline$

1549 }

1550

1551 EXECUTE {begin.bib}

1552

1553 EXECUTE {init.state.consts}

1554

Now we produce the output for all the entries.

1555 ITERATE {call.type$}

1556

Finally, we finish up by writing the ‘\end{thebibliography}’ command.

1557 FUNCTION {end.bib}
1558 { newline$
1559 "\end{thebibliography}" write$ newline$

1560 }

1561

1562 EXECUTE {end.bib}

10 PROCESSING 64 1563 ⟨/!options⟩