collberg@dna.lth.se (Christian S. Collberg) (03/08/91)
Some time ago I asked for a bibliographic cross reference generator to produce bibliographies along the line of what is found in "Concrete Mathematics". Someone pointed out the gkpmac.tex style file used by Knuth et. al. in the production of the book, but it was not immediatedly obvious to me how to use gkpmac with bibtex. I finally decided to write my own generator from scratch. Please try it out, improve it, and send me the changes! I'd be especially greatful if someone with more knowledge of TeX than myself would come up with a better way of positioning the cross references than using marginpars. This is a gross hack. Use it at your own risk. Christian S. Collberg Christian.Collberg@dna.lth.se #!/bin/sh # This is a shell archive. Remove anything before the "#!/bin/sh" line # then unpack it by saving it in a file and typing "sh file" # (Files unpacked will be owned by you and have original permissions). # This archive contains the following files: # ./README # ./bibfix # ./cross.sty # echo "writing ./README" sed 's/^X//' > ./README << '\End\of\File\' X X bibfix X ====== X X Bibliographic cross reference generator for LaTeX X X X Copyright (c) 1991 by Christian S. Collberg X Permission to copy all or part of this work is granted, including X distribution for resale, provided that authorship is acknowledged X and that the copyright notice and this notice are retained. X X Bug reports, comments, and modifications may be sent to X Christian.Collberg@dna.lth.se X X XBibfix is a bibliographic cross reference generator to be used with XLaTeX and BibTeX. It modifies the .bbl file created by BibTeX by Xincluding for each bibliographic entry the page numbers in the document Xon which that entry was referenced. For an example see the bibliography Xin Graham, Knuth, and Patashnik's "Concrete Mathematics". X XTo include cross referencing information in the document doc.tex Xinsert "cross" in the documentstyle header: X X \documentstyle[...,cross,...]{...} X Xand run the following commands: X X > latex doc X > bibtex doc X > bibfix doc X > latex doc X XFeatures: X + Page ranges (more than 2 consecutive pages containing X references to the same article) are recognized. For X example, if a certain bibliographic entry is referenced X on pages 1,2,5,6, and 7 the cross referencing information X will come out as 1, 2, 5--7. X + Roman numbering is handled if it occurs at the beginning X of a document. X + The commands \crossbib, \crossnr, and \crossrange in X cross.sty can be modified to control the layout of X the cross references. X XBugs: X + Unix specific. Uses sort, awk, *and* nawk. X + Uses marginpar for positioning the cross references. X According to the LaTeX book more than 5 marginpar's X per page is dangerous. I have also run into marginpars X which come out in the wrong margin when they occur X at the top of a page. X + If there are 10 initial roman numbered pages, followed X by pages using arabic numbering, and a certain article X is referenced on pages ix, x, 1, 2, 3 then the cross X references will be ix, x, 1--3, rather than ix--3. This X may be construed as a feature. X + I have not tested what happens in the presence of X include-files, includeonly, etc. X + This being a gross hack, there are undoubtedly many more. \End\of\File\ chmod 640 ./README if [ `wc -c ./README | awk '{printf $1}'` -ne 2379 ] then echo `wc -c ./README | awk '{print "Got " $1 ", Expected " 2379}'` fi echo "writing ./bibfix" sed 's/^X//' > ./bibfix << '\End\of\File\' X#!/bin/csh X# bibfix X# ====== X# X# Bibliographic cross reference generator for LaTeX X# X# X# Copyright (c) 1991 by Christian S. Collberg X# Permission to copy all or part of this work is granted, including X# distribution for resale, provided that authorship is acknowledged X# and that the copyright notice and this notice are retained. X# X# Bug reports, comments, and modifications may be sent to X# Christian.Collberg@dna.lth.se X Xset first = /tmp/$$.$1.1 Xset second = /tmp/$$.$1.2 Xset third = /tmp/$$.$1.3 Xset fourth = /tmp/$$.$1.4 Xset fifth = /tmp/$$.$1.5 Xset sixth = /tmp/$$.$1.6 Xset seventh = /tmp/$$.$1.7 X X# Extract \crosscite from .aux file. Subtract 10000 from roman numerals. X# PRE: \crosscite{Kieburtz78,Rudmik82,Barringer79}{5}{v} X# \crosscite{Fraser82}{1}{1} X# POST: Kieburtz78,Rudmik82,Barringer79 -9995 X# Fraser82 1 Xawk -F"{" \ X '/\crosscite/ {x=substr($2,1,length($2)-1);\ X y=substr($3,1,length($3)-1);\ X z=substr($4,1,length($4)-1);\ X if (y==z) {print x,",",y} else {print x,",",y-10000}}'\ X $1.aux >! $first X X# Separate multiple cites. X# PRE: Kieburtz78,Rudmik82,Barringer79 -9995 X# POST: Kieburtz78 -9995 X# Rudmik82 -9995 X# Barringer79 -9995 Xawk -F"," '{for(i=1;i<=(NF-1);i++){print $i,$NF}}' $first >! $second X X# Sort on label, then page number. Roman numerals are negative and X# come first. Duplicate entries (more than one \cite to the same article X# on the same page) are removed. X# PRE: Kieburtz78 10 X# Kieburtz78 -9995 X# Fraser82 11 X# Fraser82 12 X# Fraser82 10 X# Fraser82 11 X# POST: Fraser82 10 X# Fraser82 11 X# Fraser82 12 X# Kieburtz78 -9995 X# Kieburtz78 10 Xsort +0 -1 +1n -u $second >! $third X X# Merge references. X# PRE: Fraser82 10 X# Fraser82 11 X# Fraser82 12 X# Kieburtz78 -9995 X# Kieburtz78 10 X# POST: Fraser82 10 11 12 X# Kieburtz78 -9995 10 Xawk '{if (id==$1) \ X {printf "%s", " " $2} \ X else {\ X if (id != "") print ""; \ X printf "%s", $0}; \ X id=$1}\ X END {print ""}' $third >! $fourth X X# Merge sequences. X# PRE: Fraser82 10 11 12 X# Kieburtz78 -9995 10 X# Celentano80 8 9 11 X# POST: Fraser82 \crossrange{10}{12} X# Kieburtz78 \crossnr{\romannumeral 5}, \crossnr{10} X# Celentano80 \crossnr{8} \crossnr{9}, \crossnr{11} Xawk '{printf "%s",$1 " "; i=2; \ X while (i<=NF){\ X if (i != 2) {printf "%s",", "}; \ X j=i+1; k=i+2;\ X if (($i==$j-1) && ($i==$k-2)) {\ X x=$i; \ X while ((i<=NF) && ($i == $j-1)) {i++; j=i+1}; \ X y=$i; \ X if (x<0) {x="\\\\romannumeral " x+10000}; \ X if (y<0) {y="\\\\romannumeral " y+10000}; \ X printf "%s","\\\\crossrange{" x "}{" y "}" } \ X else {\ X x=$i; \ X if (x<0) {x="\\\\romannumeral " x+10000}; \ X printf "%s", "\\\\crossnr{" x "}" }; \ X i++};\ X print ""}' $fourth >! $fifth X X# Create awk-script to insert cross references in the .bbl file. X# PRE: Fraser82 \crossrange{10}{12} X# POST: /bibitem{Fraser82}/ {print $0; P="\crossbib{\crossrange{10}{12}}"; next} X# {print $0; if (P != "") {print P; P=""}} Xawk '{printf "%s", "/bibitem{"$1"}/ {print $0; P=\"\\\\crossbib{"; \ X for (i=2;i<=NF;i++){printf "%s", $i " "}; \ X print "}\"; next}"} \ X END {print "{print $0; if (P != \"\") {print P; P=\"\"}}"}' $fifth >! $sixth X X# Insert cross references in .bbl file. 'awk' can not be used here since it X# allows only short literal strings. X# PRE: \bibitem{Fraser82} X# Christopher~W. Fraser and David~R. Hansson. X# \newblock A machine-independent linker. X# \newblock {\em Software---Practice and Experience}, 12:351--366, 1982. X# POST: \bibitem{Fraser82} X# Christopher~W. Fraser and David~R. Hansson. X# \crossbib{\crossrange{10}{12}} X# \newblock A machine-independent linker. X# \newblock {\em Software---Practice and Experience}, 12:351--366, 1982. Xnawk -f $sixth $1.bbl >! $seventh X X# Clean up Xmv -f $seventh $1.bbl X/bin/rm $first $second $third $fourth $fifth $sixth X X \End\of\File\ chmod 750 ./bibfix if [ `wc -c ./bibfix | awk '{printf $1}'` -ne 4261 ] then echo `wc -c ./bibfix | awk '{print "Got " $1 ", Expected " 4261}'` fi echo "writing ./cross.sty" sed 's/^X//' > ./cross.sty << '\End\of\File\' X% From latex.tex X\def\@citex[#1]#2{\if@filesw\immediate\write\@auxout{\string\citation{#2}}\fi X \if@filesw\immediate\write\@auxout{\string\crosscite{#2}{\the\c@page}{\thepage}}\fi X \def\@citea{}\@cite{\@for\@citeb:=#2\do X {\@citea\def\@citea{,\penalty\@m\ }\@ifundefined X {b@\@citeb}{{\bf ?}\@warning X {Citation `\@citeb' on page \thepage \space undefined}}% X\hbox{\csname b@\@citeb\endcsname}}}{#1}} X X\newcommand{\crosscite}[3]{} X\newcommand{\crossbib}[1]{\marginpar{\scriptsize #1}} X\newcommand{\crossnr}[1]{#1} X\newcommand{\crossrange}[2]{\crossnr{#1}--\crossnr{#2}} \End\of\File\ chmod 640 ./cross.sty if [ `wc -c ./cross.sty | awk '{printf $1}'` -ne 587 ] then echo `wc -c ./cross.sty | awk '{print "Got " $1 ", Expected " 587}'` fi echo "Finished archive 1 of 1" # if you want to concatenate archives, remove anything after this line exit -- -------------------------------------------------------------------- Christian.Collberg@dna.lu.se