/***************************************************************************\ * M A K E B I B "Make Bibliography" * * * * AUTHOR: Jim Arvo, California Institute of Technology * * * * This utility creates a LaTeX bibliography from a list of ".bib" files. * * That is, it creates a LaTeX file consisting of nothing but a * * bibliography with selected citations from one or more bibliography files * * in "bibtex" format. The resulting document provides a readable listing * * of the contents of a bibliographic database for easy reference. Command * * line options allow you to choose which types of items are cited, such * * as articles, theses, and books. * * * * USAGE: makebib {[-abtlpn] } > * * where "bibfile" is a BibTex file and "bibliography" is the generated * * LaTeX file. Options are * * a = articles * * b = books * * t = thesies * * l = generate list of names in addition to the bibliography * * p = preserve original order * * n = dot not generate list of names (default) * * * * EXAMPLE: makebib Abbrev -ba Math General -t Graphics > Mybib.tex * * * * The above line creates a file called "Mybib.tex" that consists of a * * bibliography containing all books and articles in "Math.bib" and * * "General.bib" and all theses in "Graphics.bib". The file "Abbrev.bib" * * is read in at the start with default flags, which are all on. This is * * useful for including files of abbreviations, for example. Once complete, * * run latex and bibtex on "Mybib" multiple times (three times suffices). * * * * * * Changes: * * * * 05/15/96 arvo Accept file names with or without ".bib" suffix. * * 09/11/92 arvo Initial implementation. * * * \***************************************************************************/ #include #include #include #define NullChar '\0' #define NewLine '\n' #define TAB '\t' #define DASH '-' #define ATSIGN '@' #define LBRACK '{' #define RBRACK '}' #define COMMA ',' #define BLANK ' ' #define GETC( c ) ( c = getc( fp ) ) #define PUSH( c ) ungetc( c, fp ) #define WHITE( c ) ( c == BLANK || c == NewLine || c == TAB ) #define DELIM( c ) ( c == COMMA || c == LBRACK || c == RBRACK ) #define DIGIT( c ) ( '0' <= c && c <= '9' ) #define MATCH(s,t) ( strcmp(s,t) == 0 ) #define UPPER( c ) ( ( 'a' <= c && c <= 'z' ) ? c + 'A' - 'a' : c ) FILE *fp; int include_article = 0; int include_book = 0; int include_thesis = 0; int list_names = 0; int preserve_order = 0; int entries = 0; static void print_how_to_use() { fprintf( stderr, "Usage: makebib {[-abtlpn] } > \n" ); fprintf( stderr, "where \"bibfile\" is a BibTex file and \"bibliography\" is the " ); fprintf( stderr, "generated LaTeX file. Options are\n" ); fprintf( stderr, " a = articles\n" ); fprintf( stderr, " b = books \n" ); fprintf( stderr, " t = thesies \n" ); fprintf( stderr, " l = generate list of names \n" ); fprintf( stderr, " p = preserve original order \n" ); fprintf( stderr, " n = dot not generate list of names (default) \n" ); exit(1); } static int include_this( char *token ) { if( include_article ) { if( MATCH( token, "ARTICLE" ) ) return 1; if( MATCH( token, "INCOLLECTION" ) ) return 1; if( MATCH( token, "INBOOK" ) ) return 1; if( MATCH( token, "INPROCEEDINGS" ) ) return 1; if( MATCH( token, "MISC" ) ) return 1; if( MATCH( token, "TECHREPORT" ) ) return 1; if( MATCH( token, "UNPUBLISHED" ) ) return 1; } if( include_book ) { if( MATCH( token, "BOOK" ) ) return 1; if( MATCH( token, "BOOKLET" ) ) return 1; if( MATCH( token, "MANUAL" ) ) return 1; if( MATCH( token, "PROCEEDINGS" ) ) return 1; } if( include_thesis ) { if( MATCH( token, "MASTERSTHESIS" ) ) return 1; if( MATCH( token, "PHDTHESIS" ) ) return 1; } return(0); } static void set_search_items( char *arg ) { char c; include_article = 0; include_book = 0; include_thesis = 0; while( (c = *(++arg)) != NullChar ) { switch( c ) { case 'a' : include_article = 1; break; case 'b' : include_book = 1; break; case 't' : include_thesis = 1; break; case 'l' : list_names = 1; break; case 'n' : list_names = 0; break; case 'p' : preserve_order = 1; break; default : fprintf( stderr, "(makebib): Unrecognized option [%c]\n", c ); } } } static void skip_white( ) { char c; do { GETC(c); } while( WHITE(c) ); PUSH(c); } static void skip_to( char target ) { int c; do { GETC(c); } while( c != EOF && c != target ); if( c == EOF ) PUSH(c); } static void get_token( char *s ) { int c; skip_white(); while( GETC(c) != EOF ) { if( WHITE(c) || DELIM(c) ) break; *s++ = c; } PUSH(c); *s = NullChar; } static void get_token_ucase( char *s ) { int c; skip_white(); while( GETC(c) != EOF ) { if( WHITE(c) || DELIM(c) ) break; *s++ = UPPER( c ); } PUSH(c); *s = NullChar; } static void section_header( char *file ) { if( list_names ) printf( "\n\\section{References from %s.bib}\n", file ); } static void citation( char *name ) { if( list_names ) { int i; for( i = 0; i < strlen(name); i++ ) if( DIGIT(name[i]) ) break; printf( "%.*s ", i, name ); } printf( " \\nocite{%s}\n", name ); } static void output_preamble() { printf( "\n" ); printf( "\\documentstyle[11pt]{article} \n" ); printf( "\n" ); printf( "\\setlength{\\textwidth}{6.5in} \n" ); printf( "\\setlength{\\oddsidemargin}{0in} \n" ); printf( "\\setlength{\\evensidemargin}{0in} \n" ); printf( "\\setlength{\\textheight}{8.8in} \n" ); printf( "\\setlength{\\headsep}{.5in} \n" ); printf( "\\setlength{\\topmargin}{-0.5in} \n" ); printf( "\n" ); printf( "\\begin{document} \n" ); } static void output_trailer( int argc, char *argv[] ) { int first = 1; printf( "\\newpage\n" ); printf( "\\bibliography{" ); for( int i = 1; i < argc; i++ ) { char *arg = argv[i]; if( arg[0] == DASH ) continue; if( first ) printf( "%s" , arg ); else printf( ",%s" , arg ); first = 0; } printf( "}\n" ); if( preserve_order ) printf( "\\bibliographystyle{unsrt}\n" ); else printf( "\\bibliographystyle{plain}\n" ); printf( "\\end{document}\n\n" ); } void main( int argc, char *argv[] ) { int c; char name[128]; char fname[128]; char ref_type[128]; if( argc < 2 ) print_how_to_use(); // By default, search for all types of items. set_search_items( "-abt" ); output_preamble(); for( int i = 1; i < argc; i++ ) { int first_in_sec = 1; char *arg = argv[i]; if( arg[0] == DASH ) { set_search_items( arg ); continue; } // First try opening file as it appears on the command line. If that // fails, try appending ".bib". Once open, strip off the suffix if // it has one -- this is for printing later. strcpy( fname, arg ); fp = fopen( fname, "r" ); if( fp == NULL ) { strcat( fname, ".bib" ); // Try appending ".bib" to the name. fp = fopen( fname, "r" ); if( fp == NULL ) { fprintf( stderr, "(makebib): Could not access %s or %s.\n", arg, fname ); exit(1); } } // See if the file name, as originally given, actually ends in ".bib". // If so, strip it off so that it can be printed in the \bibliography{...} // command at the end of the ".tex" file being generated. int m = strlen( arg ) - 4; char *s = arg + m; // Pointer to beginning of the suffix? if( m >= 0 && strcmp( s, ".bib" ) == 0 ) *s = NullChar; // Now parse the file, picking out the abbreviations associated with // each of the entries. Generate citations for the entry types that // were requested for this file. while( GETC(c) != EOF ) { if( c == ATSIGN ) { name[0] = NullChar; get_token_ucase( ref_type ); if( include_this( ref_type ) ) // Generate the citation. { skip_to( LBRACK ); get_token( name ); entries++; if( first_in_sec ) section_header( arg ); citation( name ); first_in_sec = 0; } } } fclose( fp ); } output_trailer( argc, argv ); fprintf( stderr, "---------------------\n" ); fprintf( stderr, "done. Entries = %d \n", entries ); fprintf( stderr, "---------------------\n" ); exit(0); }