Date: Tue 6 Jan 87 17:39:42-PST
From: Eric Muller <EM@Score.Stanford.EDU>
To: texhax@Score.Stanford.EDU
Subject: How to cite all the keys of a bibtex database.


I have made a simple modification to Bibtex so that it can behave as
if all the entries of a (set of) bibliography file had been cited.
Namely, I have added a ".aux" file command, "\citeall{}" which is
equivalent to the list all "\citation{xxx}" commands where xxx is
replaced by the cite-key of each entry.

In conjunction with a bst-format that produces "\nocite{xxx}" as the
bibliographic entry, where xxx is the cite-key of the entry (instead
of the normal LaTeX commands to format the entry) and a ".aux" file of
the form :

\relax 
\bibdata{cs}		% the name of the .bib file
\citeall{}		% to get all the entries of it
\bibstyle{cite-all}	% to produce a \nocite for each entry

what you get after processing by Bibtex is a list of all the "\nocite"
commands in the ".bbl" file, which you can then \input where you want.

I also have a "author-index.bst" format that will produce a list of
"\index" commands, one for each author in each entry, the text of the
index entry being the author name and the "page number" replaced by
the cite-key of the entry. 

You can also use a standard format in the "\bibstyle". The reason for
the two step process (with the cite-all format) is linked to the
memory allocation scheme of Bibtex I did not want to change too much.
That is, if the format you want to use utilizes less than a certain number
of fields in the entries (if think it is 20) then everything is fine;
otherwise use the two step process.

The rest of this message is the files mentioned above, starting with
the change file for bibtex (I am running the modified version on a
Tops-20 system, so that these may have to be merged with changes for
your system), and the two format files. Files are separated by
"@@@@@@@ <file name>" line. If you need any help, just send me mail.

There may be a bug in these modifications : the last entry in the
database may no appear; just add a dummy entry at the end (or find the
bug !).

Last detail : the modified bibtex will do whatever the old one does,
it just has one additional command; the code for the modification is
not really clean (especially on the Web side); you can forward this to
anyone interested.

Good luck,
Eric Muller					 (em@score.stanford.edu)


@@@@@@@ bibtex.ch
@x
@d n_aux_bibdata = 0	{\.{\\bibdata}}
@d n_aux_bibstyle = 1	{\.{\\bibstyle}}
@d n_aux_citation = 2	{\.{\\citation}}
@d n_aux_input = 3	{\.{\\@@input}}
@y
@d n_aux_bibdata = 0	{\.{\\bibdata}}
@d n_aux_bibstyle = 1	{\.{\\bibstyle}}
@d n_aux_citation = 2	{\.{\\citation}}
@d n_aux_input = 3	{\.{\\@@input}}
@d n_aux_citeall = 4	{\.{\\citeall}}
@z

@x
@<Pre-define certain strings@>=
pre_define('\citation   ',9,aux_command_ilk);
ilk_info[pre_def_loc] := n_aux_citation;
pre_define('\bibdata    ',8,aux_command_ilk);
ilk_info[pre_def_loc] := n_aux_bibdata;
pre_define('\bibstyle   ',9,aux_command_ilk);
ilk_info[pre_def_loc] := n_aux_bibstyle;
pre_define('\@@input     ',7,aux_command_ilk);
ilk_info[pre_def_loc] := n_aux_input;
@y
@<Pre-define certain strings@>=
pre_define('\citation   ',9,aux_command_ilk);
ilk_info[pre_def_loc] := n_aux_citation;
pre_define('\bibdata    ',8,aux_command_ilk);
ilk_info[pre_def_loc] := n_aux_bibdata;
pre_define('\bibstyle   ',9,aux_command_ilk);
ilk_info[pre_def_loc] := n_aux_bibstyle;
pre_define('\@@input     ',7,aux_command_ilk);
ilk_info[pre_def_loc] := n_aux_input;
pre_define('\citeall    ',8,aux_command_ilk);
ilk_info[pre_def_loc] := n_aux_citeall;
@z

@x
    case command_num of
	n_aux_bibdata : aux_bib_data_command;
	n_aux_bibstyle : aux_bib_style_command;
	n_aux_citation : aux_citation_command;
	n_aux_input : aux_input_command;
@y
    case command_num of
	n_aux_bibdata : aux_bib_data_command;
	n_aux_bibstyle : aux_bib_style_command;
	n_aux_citation : aux_citation_command;
	n_aux_input : aux_input_command;
	n_aux_citeall : aux_citeall_command;
@z

@x
procedure aux_citation_command;
label exit;
begin
@y
procedure aux_citation_command;
label exit;
begin
if citeall_seen then aux_err ('illegal, \citation after a \citeall');
@z

@x
That's it for processing \.{.aux} commands, except for finishing the
procedural gymnastics.

@<Procedures and functions for the reading and processing of input files@>=
@<Scan for and process an \.{.aux} command@>
@y
That's it for processing \.{.aux} commands, except for finishing the
procedural gymnastics.

@<Procedures and functions for the reading and processing of input files@>=
@<Procedure for processing the citeall command@>
@<Scan for and process an \.{.aux} command@>
@z

@x
num_cites := cite_ptr;		{record the number of distinct cite keys}
num_bib_files := bib_ptr;	{and the number of \.{.bib} files}
if (not citation_seen) then
    aux_end_err ('I found no \citation commands')
  else if (num_cites = 0) then
    aux_end_err ('I found no \cite keys');
@y
if citeall_seen then num_cites := max_cites else num_cites := cite_ptr;
num_bib_files := bib_ptr;	{and the number of \.{.bib} files}
if (not citeall_seen) and (not citation_seen) then
  aux_end_err ('I found no \citeall nor \citation commands')
else if (citation_seen) and (num_cites = 0) then
    aux_end_err ('I found no \cite keys');
@z

@x
  trace_pr_ln ('finished reading the database file(s)');
  ecart@/
@<Check for missing entries@>;
@y
  trace_pr_ln ('finished reading the database file(s)');
  ecart@/
if citeall_seen then 
  num_cites := real_num_cites
else begin
  @<Check for missing entries@>; end;
@z

@x
@<Check for a database key of interest@>=
  trace
  trace_pr_token;
  trace_pr_ln (' is a database key');
  ecart@/
tmp_ptr := buf_ptr1;
while (tmp_ptr < buf_ptr2) do
    begin
    sv_buf2[tmp_ptr] := buffer[tmp_ptr];
    incr(tmp_ptr);
    end;
lower_case (sv_buf2, buf_ptr1, token_len);	{convert to `canonical' form}
lc_cite_loc := str_lookup(sv_buf2,buf_ptr1,token_len,lc_cite_ilk,dont_insert);
if (not hash_found) then
    store_entry := false	{no such cite key read on |cite_list|}
  else
    begin
    store_entry := true;
    @<Make sure this entry is ok before proceeding@>;
    end;
@y
@<Check for a database key of interest@>=
  trace
  trace_pr_token;
  trace_pr_ln (' is a database key');
  ecart@/
tmp_ptr := buf_ptr1;
while (tmp_ptr < buf_ptr2) do
    begin
    sv_buf2[tmp_ptr] := buffer[tmp_ptr];
    incr(tmp_ptr);
    end;
lower_case (sv_buf2, buf_ptr1, token_len);	{convert to `canonical' form}
lc_cite_loc := str_lookup(sv_buf2,buf_ptr1,token_len,lc_cite_ilk,dont_insert);

if citeall_seen then begin
  if not hash_found then begin
    lc_cite_loc := str_lookup(sv_buf2,buf_ptr1,
			      token_len,lc_cite_ilk,do_insert);
    trace
    trace_pr_newline;
    ecart@/
    if (real_num_cites = max_cites) then
       overflow('number of \cite keys ',max_cites);
    cite_loc := str_lookup(buffer,buf_ptr1,token_len,cite_ilk,do_insert);
    if (hash_found) then
      aux_err ('this can''t happen---cite hash error');
    cite_list[real_num_cites] := hash_text[cite_loc];
    ilk_info[cite_loc] := real_num_cites;
    ilk_info[lc_cite_loc] := real_num_cites;
    incr(real_num_cites); end;
  store_entry := true;
  @<Make sure this entry is ok before proceeding@>; end

else
  if (not hash_found) then
    store_entry := false	{no such cite key read on |cite_list|}
  else begin
    store_entry := true;
    @<Make sure this entry is ok before proceeding@>; end;
@z

@x
@* System-dependent changes.
@^system dependencies@>
This section should be replaced, if necessary, by changes to the program
that are necessary to make \BibTeX\ work at a particular installation.
It is usually best to design your change file so that all changes to
previous sections preserve the section numbering; then everybody's version
will be consistent with the printed program. More extensive changes,
which introduce new sections, can be inserted here; then only the index
itself will get a new section number.
@y
@ Here are the new modules for the citation of all entries.
We need a global variable to remember that we must cite all entries, 
and another to count the real number of entries :

@<Globals in the outer block@>=
citeall_seen : boolean;
real_num_cites : cite_number;

@ Of course, this needs some initialization.

@<Set initial values of key variables@>=
citeall_seen := false;
real_num_cites := 0;

@ Currently, we do not process arguments of the \.{\\citeall} command, but
skip over them. However, the \.{\{} and \.{\}} must be there.

@<Procedure for processing the citeall command@>=
procedure aux_citeall_command;
label exit;
begin
if citeall_seen then aux_err ('illegal, another \citeall command');
if citation_seen then aux_err ('illegal, \citall command after some \citation command');

citeall_seen := true;
incr(buf_ptr2);
if (not scan1 (right_brace)) then
  aux_err ('no "',xchr[right_brace],'" for \citeall command');
if (last > buf_ptr2 + 1) then
  aux_err ('stuff after "', xchr[right_brace], '" for \citeall command');
exit: end;


@* System-dependent changes.
@^system dependencies@>
This section should be replaced, if necessary, by changes to the program
that are necessary to make \BibTeX\ work at a particular installation.
It is usually best to design your change file so that all changes to
previous sections preserve the section numbering; then everybody's version
will be consistent with the printed program. More extensive changes,
which introduce new sections, can be inserted here; then only the index
itself will get a new section number.
@z

@@@@@@@ cite-all.bst
ENTRY
  {none}
  {}
  {}

FUNCTION {default.type}
{ newline$
  "\nocite{" write$
  cite$ write$
  "}" write$
}

FUNCTION {article} { default.type }
FUNCTION {book} { default.type }
FUNCTION {booklet} { default.type }
FUNCTION {inbook} { default.type }
FUNCTION {incollection} { default.type }
FUNCTION {inproceedings} { default.type }
FUNCTION {conference} { default.type }
FUNCTION {manual} { default.type }
FUNCTION {mastersthesis} { default.type }
FUNCTION {misc} { default.type }
FUNCTION {phdthesis} { default.type }
FUNCTION {proceedings} { default.type }
FUNCTION {techreport} { default.type }
FUNCTION {unpublished} { default.type }

READ

ITERATE {call.type$}

@@@@@@@ author-index.bst
ENTRY
  { author
    editor
  }
  {}
  {label}


STRINGS { s t }

INTEGERS { nameptr namesleft numnames }


FUNCTION {format.names}
{ 's swap$ :=
  'nameptr #1 :=
  'numnames s num.names$ :=
  'namesleft numnames :=
    { namesleft #0 > }
    {
      "\index{" write$
      s nameptr "{vv~}{ll}{ jj}{, ff}" format.name$ write$
      "}{\cite{" write$ cite$ write$ "}}" write$ newline$
      'nameptr nameptr #1 + :=
      'namesleft namesleft #1 - :=
    }
  while$
}

FUNCTION {default.type}
  { author missing$
    { editor missing$
      { skip$ }
      { editor format.names }
      if$ }
    { author format.names }
    if$ }

FUNCTION {article} { default.type }
FUNCTION {book} { default.type }
FUNCTION {booklet} { default.type }
FUNCTION {inbook} { default.type }
FUNCTION {incollection} { default.type }
FUNCTION {inproceedings} { default.type }
FUNCTION {conference} { default.type }
FUNCTION {manual} { default.type }
FUNCTION {mastersthesis} { default.type }
FUNCTION {misc} { default.type }
FUNCTION {phdthesis} { default.type }
FUNCTION {proceedings} { default.type }
FUNCTION {techreport} { default.type }
FUNCTION {unpublished} { default.type }

READ

ITERATE {call.type$}

-------