summaryrefslogtreecommitdiff
path: root/support/texlab/crates/bibutils_sys/src/mycvout.c
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/crates/bibutils_sys/src/mycvout.c')
-rw-r--r--support/texlab/crates/bibutils_sys/src/mycvout.c614
1 files changed, 614 insertions, 0 deletions
diff --git a/support/texlab/crates/bibutils_sys/src/mycvout.c b/support/texlab/crates/bibutils_sys/src/mycvout.c
new file mode 100644
index 0000000000..d42e2b0a4c
--- /dev/null
+++ b/support/texlab/crates/bibutils_sys/src/mycvout.c
@@ -0,0 +1,614 @@
+/*
+ * mycvout.c
+ *
+ * Copyright (c) Chris Putnam 2003-2019
+ *
+ * Source code released under the GPL version 2
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "str.h"
+#include "strsearch.h"
+#include "utf8.h"
+#include "xml.h"
+#include "fields.h"
+#include "bibl.h"
+#include "doi.h"
+#include "bibutils.h"
+
+void
+bibtexout_initparams( param *pm, const char *progname )
+{
+ pm->writeformat = BIBL_BIBTEXOUT;
+ pm->format_opts = 0;
+ pm->charsetout = BIBL_CHARSET_DEFAULT;
+ pm->charsetout_src = BIBL_SRC_DEFAULT;
+ pm->latexout = 1;
+ pm->utf8out = 0;
+ pm->utf8bom = 0;
+ pm->xmlout = BIBL_XMLOUT_FALSE;
+ pm->nosplittitle = 0;
+ p->verbose = 0;
+ pm->addcount = 0;
+ pm->singlerefperfile = 0;
+
+ pm->headerf = bibtexout_writeheader;
+ pm->footerf = NULL;
+ pm->writef = bibtexout_write;
+
+ if ( !p->progname && progname )
+ p->progname = strdup( progname );
+}
+
+enum {
+ TYPE_UNKNOWN = 0,
+ TYPE_ARTICLE,
+ TYPE_INBOOK,
+ TYPE_INPROCEEDINGS,
+ TYPE_PROCEEDINGS,
+ TYPE_INCOLLECTION,
+ TYPE_COLLECTION,
+ TYPE_BOOK,
+ TYPE_PHDTHESIS,
+ TYPE_MASTERSTHESIS,
+ TYPE_REPORT,
+ TYPE_MANUAL,
+ TYPE_UNPUBLISHED,
+ TYPE_ELECTRONIC,
+ TYPE_MISC
+};
+
+static void
+output_citekey( FILE *fp, fields *info, unsigned long refnum, int format_opts )
+{
+ int n = fields_find( info, "REFNUM", -1 );
+ char *p;
+ if ( n!=-1 ) {
+ p = info->data[n].data;
+ while ( p && *p && *p!='|' ) {
+ if ( format_opts & BIBL_FORMAT_BIBOUT_STRICTKEY ) {
+ if ( isdigit((unsigned char)*p) || (*p>='A' && *p<='Z') ||
+ (*p>='a' && *p<='z' ) )
+ fprintf( fp, "%c", *p );
+ }
+ else {
+ if ( *p!=' ' && *p!='\t' ) {
+ fprintf( fp, "%c", *p );
+ }
+ }
+ p++;
+ }
+ }
+}
+
+static int
+bibtexout_type( fields *info, char *filename, int refnum, param *p )
+{
+ char *genre;
+ int type = TYPE_UNKNOWN, i, maxlevel, n, level;
+
+ /* determine bibliography type */
+ for ( i=0; i<info->n; ++i ) {
+ if ( strcasecmp( info->tag[i].data, "GENRE:MARC" ) &&
+ strcasecmp( info->tag[i].data, "GENRE:BIBUTILS" ) ) continue;
+ genre = info->data[i].data;
+ level = info->level[i];
+ if ( !strcasecmp( genre, "periodical" ) ||
+ !strcasecmp( genre, "academic journal" ) ||
+ !strcasecmp( genre, "magazine" ) ||
+ !strcasecmp( genre, "newspaper" ) ||
+ !strcasecmp( genre, "article" ) )
+ type = TYPE_ARTICLE;
+ else if ( !strcasecmp( genre, "instruction" ) )
+ type = TYPE_MANUAL;
+ else if ( !strcasecmp( genre, "unpublished" ) )
+ type = TYPE_UNPUBLISHED;
+ else if ( !strcasecmp( genre, "conference publication" ) ) {
+ if ( level==0 ) type=TYPE_PROCEEDINGS;
+ else type = TYPE_INPROCEEDINGS;
+ } else if ( !strcasecmp( genre, "collection" ) ) {
+ if ( level==0 ) type=TYPE_COLLECTION;
+ else type = TYPE_INCOLLECTION;
+ } else if ( !strcasecmp( genre, "technical report" ) )
+ type = TYPE_REPORT;
+ else if ( !strcasecmp( genre, "book" ) ) {
+ if ( level==0 ) type=TYPE_BOOK;
+ else type=TYPE_INBOOK;
+ } else if ( !strcasecmp( genre, "thesis" ) ) {
+ if ( type==TYPE_UNKNOWN ) type=TYPE_PHDTHESIS;
+ } else if ( !strcasecmp( genre, "Ph.D. thesis" ) )
+ type = TYPE_PHDTHESIS;
+ else if ( !strcasecmp( genre, "Masters thesis" ) )
+ type = TYPE_MASTERSTHESIS;
+ else if ( !strcasecmp( genre, "electronic" ) )
+ type = TYPE_ELECTRONIC;
+ }
+ if ( type==TYPE_UNKNOWN ) {
+ for ( i=0; i<info->n; ++i ) {
+ if ( strcasecmp( info->tag[i].data, "ISSUANCE" ) ) continue;
+ if ( !strcasecmp( info->data[i].data, "monographic" ) ) {
+ if ( info->level[i]==0 ) type = TYPE_BOOK;
+ else if ( info->level[i]==1 ) type=TYPE_INBOOK;
+ }
+ }
+ }
+
+ /* default to BOOK type */
+ if ( type==TYPE_UNKNOWN ) {
+ maxlevel = fields_maxlevel( info );
+ if ( maxlevel > 0 ) type = TYPE_INBOOK;
+ else {
+ if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
+ fprintf( stderr, "Cannot identify TYPE "
+ "in reference %d ", refnum+1 );
+ n = fields_find( info, "REFNUM", -1 );
+ if ( n!=-1 )
+ fprintf( stderr, " %s", info->data[n].data);
+ fprintf( stderr, " (defaulting to @Misc)\n" );
+ type = TYPE_MISC;
+ }
+ }
+ return type;
+}
+
+static void
+output_type( FILE *fp, int type, int format_opts )
+{
+ typedef struct {
+ int bib_type;
+ char *type_name;
+ } typenames;
+
+ typenames types[] = {
+ { TYPE_ARTICLE, "Article" },
+ { TYPE_INBOOK, "Inbook" },
+ { TYPE_PROCEEDINGS, "Proceedings" },
+ { TYPE_INPROCEEDINGS, "InProceedings" },
+ { TYPE_BOOK, "Book" },
+ { TYPE_PHDTHESIS, "PhdThesis" },
+ { TYPE_MASTERSTHESIS, "MastersThesis" },
+ { TYPE_REPORT, "TechReport" },
+ { TYPE_MANUAL, "Manual" },
+ { TYPE_COLLECTION, "Collection" },
+ { TYPE_INCOLLECTION, "InCollection" },
+ { TYPE_UNPUBLISHED, "Unpublished" },
+ { TYPE_ELECTRONIC, "Electronic" },
+ { TYPE_MISC, "Misc" } };
+ int i, len, ntypes = sizeof( types ) / sizeof( types[0] );
+ char *s = NULL;
+ for ( i=0; i<ntypes; ++i ) {
+ if ( types[i].bib_type == type ) {
+ s = types[i].type_name;
+ break;
+ }
+ }
+ if ( !s ) s = types[ntypes-1].type_name; /* default to TYPE_MISC */
+ if ( !(format_opts & BIBL_FORMAT_BIBOUT_UPPERCASE ) ) fprintf( fp, "@%s{", s );
+ else {
+ len = strlen( s );
+ fprintf( fp, "@" );
+ for ( i=0; i<len; ++i )
+ fprintf( fp, "%c", toupper((unsigned char)s[i]) );
+ fprintf( fp, "{" );
+ }
+}
+
+static void
+output_element( FILE *fp, char *tag, char *data, int format_opts )
+{
+ int i, len, nquotes = 0;
+ char ch;
+ fprintf( fp, ",\n" );
+ if ( format_opts & BIBL_FORMAT_BIBOUT_WHITESPACE ) fprintf( fp, " " );
+ if ( !(format_opts & BIBL_FORMAT_BIBOUT_UPPERCASE ) ) fprintf( fp, "%s", tag );
+ else {
+ len = strlen( tag );
+ for ( i=0; i<len; ++i )
+ fprintf( fp, "%c", toupper((unsigned char)tag[i]) );
+ }
+ if ( format_opts & BIBL_FORMAT_BIBOUT_WHITESPACE ) fprintf( fp, " = \t" );
+ else fprintf( fp, "=" );
+
+ if ( format_opts & BIBL_FORMAT_BIBOUT_BRACKETS ) fprintf( fp, "{" );
+ else fprintf( fp, "\"" );
+
+ len = strlen( data );
+ for ( i=0; i<len; ++i ) {
+ ch = data[i];
+ if ( ch!='\"' ) fprintf( fp, "%c", ch );
+ else {
+ if ( format_opts & BIBL_FORMAT_BIBOUT_BRACKETS ||
+ ( i>0 && data[i-1]=='\\' ) )
+ fprintf( fp, "\"" );
+ else {
+ if ( nquotes % 2 == 0 )
+ fprintf( fp, "``" );
+ else fprintf( fp, "\'\'" );
+ nquotes++;
+ }
+ }
+ }
+
+ if ( format_opts & BIBL_FORMAT_BIBOUT_BRACKETS ) fprintf( fp, "}" );
+ else fprintf( fp, "\"" );
+}
+
+static void
+output_and_use( FILE *fp, fields *info, int n, char *outtag, int format_opts )
+{
+ output_element( fp, outtag, info->data[n].data, format_opts );
+ fields_setused( info, n );
+}
+
+static void
+output_simple( FILE *fp, fields *info, char *intag, char *outtag,
+ int format_opts )
+{
+ int n = fields_find( info, intag, -1 );
+ if ( n!=-1 ) {
+ output_and_use( fp, info, n, outtag, format_opts );
+ }
+}
+
+static void
+output_simpleall( FILE *fp, fields *info, char *intag, char *outtag,
+ int format_opts )
+{
+ int i;
+ for ( i=0; i<info->n; ++i ) {
+ if ( strcasecmp( info->tag[i].data, intag ) ) continue;
+ output_and_use( fp, info, i, outtag, format_opts );
+ }
+}
+
+static void
+output_fileattach( FILE *fp, fields *info, int format_opts )
+{
+ str data;
+ int i;
+ str_init( &data );
+ for ( i=0; i<info->n; ++i ) {
+ if ( strcasecmp( info->tag[i].data, "FILEATTACH" ) ) continue;
+ str_strcpy( &data, ":" );
+ str_strcatc( &data, &(info->data[i]) );
+ if ( strsearch( info->data[i].data, ".pdf" ) )
+ str_strcatc( &data, ":PDF" );
+ else if ( strsearch( info->data[i].data, ".html" ) )
+ str_strcatc( &data, ":HTML" );
+ else str_strcatc( &data, ":TYPE" );
+ output_element( fp, "file", data.data, format_opts );
+ fields_setused( info, i );
+ str_empty( &data );
+ }
+ str_free( &data );
+}
+
+static void
+add_person( str *s, char *p )
+{
+ int nseps = 0, nch;
+ while ( *p ) {
+ nch = 0;
+ if ( nseps==1 ) str_addchar( s, ',' );
+ if ( nseps ) str_addchar( s, ' ' );
+ while ( *p && *p!='|' ) {
+ str_addchar( s, *p++ );
+ nch++;
+ }
+ if ( *p=='|' ) p++;
+ if ( nseps!=0 && nch==1 ) str_addchar( s, '.' );
+ nseps++;
+ }
+}
+
+static void
+output_people( FILE *fp, fields *info, unsigned long refnum, char *tag,
+ char *ctag, char *atag, char *bibtag, int level,
+ int format_opts )
+{
+ str allpeople;
+ int i, npeople, person, corp, asis;
+
+ /* primary citation authors */
+ npeople = 0;
+ for ( i=0; i<info->n; ++i ) {
+ if ( level!=-1 && info->level[i]!=level ) continue;
+ person = ( strcasecmp( info->tag[i].data, tag ) == 0 );
+ corp = ( strcasecmp( info->tag[i].data, ctag ) == 0 );
+ asis = ( strcasecmp( info->tag[i].data, atag ) == 0 );
+ if ( person || corp || asis ) {
+ if ( npeople==0 ) str_init( &allpeople );
+ else {
+ if ( format_opts & BIBL_FORMAT_BIBOUT_WHITESPACE )
+ str_strcatc(&allpeople,"\n\t\tand ");
+ else str_strcatc( &allpeople, "\nand " );
+ }
+ if ( corp ) {
+ str_addchar( &allpeople, '{' );
+ str_strcatc( &allpeople, info->data[i].data );
+ str_addchar( &allpeople, '}' );
+ } else if ( asis ) {
+ str_addchar( &allpeople, '{' );
+ str_strcatc( &allpeople, info->data[i].data );
+ str_addchar( &allpeople, '}' );
+ } else add_person( &allpeople, info->data[i].data );
+ fields_setused( info, i );
+ npeople++;
+ }
+ }
+ if ( npeople ) {
+ output_element( fp, bibtag, allpeople.data, format_opts );
+ str_free( &allpeople );
+ }
+}
+
+static void
+output_title( FILE *fp, fields *info, unsigned long refnum, char *bibtag, int level, int format_opts )
+{
+ str title;
+ int n1 = -1, n2 = -1;
+ /* Option is for short titles of journals */
+ if ( ( format_opts & BIBL_FORMAT_BIBOUT_SHORTTITLE ) && level==1 ) {
+ n1 = fields_find( info, "SHORTTITLE", level );
+ n2 = fields_find( info, "SHORTSUBTITLE", level );
+ }
+ if ( n1==-1 ) {
+ n1 = fields_find( info, "TITLE", level );
+ n2 = fields_find( info, "SUBTITLE", level );
+ }
+ if ( n1!=-1 ) {
+ str_init( &title );
+ str_strcpy( &title, &(info->data[n1]) );
+ fields_setused( info, n1 );
+ if ( n2!=-1 ) {
+ if ( info->data[n1].data[info->data[n1].len]!='?' )
+ str_strcatc( &title, ": " );
+ else str_addchar( &title, ' ' );
+ str_strcatc( &title, info->data[n2].data );
+ fields_setused( info, n2 );
+ }
+ output_element( fp, bibtag, title.data, format_opts );
+ str_free( &title );
+ }
+}
+
+static void
+output_date( FILE *fp, fields *info, unsigned long refnum, int format_opts )
+{
+ char *months[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+ int n, month;
+ n = fields_find( info, "DATE:YEAR", -1 );
+ if ( n==-1 ) n = fields_find( info, "PARTDATE:YEAR", -1 );
+ if ( n!=-1 ) {
+ output_element( fp, "year", info->data[n].data, format_opts );
+ fields_setused( info, n );
+ }
+ n = fields_find( info, "DATE:MONTH", -1 );
+ if ( n==-1 ) n = fields_find( info, "PARTDATE:MONTH", -1 );
+ if ( n!=-1 ) {
+ month = atoi( info->data[n].data );
+ if ( month>0 && month<13 )
+ output_element( fp, "month", months[month-1], format_opts );
+ else
+ output_element( fp, "month", info->data[n].data, format_opts );
+ fields_setused( info, n );
+ }
+ n = fields_find( info, "DATE:DAY", -1 );
+ if ( n==-1 ) n = fields_find( info, "PARTDATE:DAY", -1 );
+ if ( n!=-1 ) {
+ output_element( fp, "day", info->data[n].data, format_opts );
+ fields_setused( info, n );
+ }
+}
+
+
+/* output article number as pages if true pages aren't found */
+static void
+output_articlenumber( FILE *fp, fields *info, unsigned long refnum,
+ int format_opts )
+{
+ int ar = fields_find( info, "ARTICLENUMBER", -1 );
+ if ( ar!=-1 ) {
+ str pages;
+ str_init( &pages );
+ str_strcatc( &pages, info->data[ar].data );
+ output_element( fp, "pages", pages.data, format_opts );
+ fields_setused( info, ar );
+ str_free( &pages );
+ }
+}
+
+static void
+output_arxiv( FILE *fp, fields *info, int format_opts )
+{
+ int ar = fields_find( info, "ARXIV", -1 );
+ if ( ar!=-1 ) {
+ str arxiv;
+ str_init( &arxiv );
+ arxiv_to_url( info, ar, "URL", &arxiv );
+ if ( arxiv.len )
+ output_element( fp, "url", arxiv.data, format_opts );
+ str_free( &arxiv );
+ }
+}
+
+static void
+output_pmid( FILE *fp, fields *info, int format_opts )
+{
+ int pm = fields_find( info, "PMID", -1 );
+ if ( pm!=-1 ) {
+ str pmid;
+ str_init( &pmid );
+ pmid_to_url( info, pm, "URL", &pmid );
+ if ( pmid.len )
+ output_element( fp, "url", pmid.data, format_opts );
+ str_free( &pmid );
+ }
+}
+
+static void
+output_jstor( FILE *fp, fields *info, int format_opts )
+{
+ int js = fields_find( info, "JSTOR", -1 );
+ if ( js!=-1 ) {
+ str jstor;
+ str_init( &jstor );
+ jstor_to_url( info, js, "URL", &jstor );
+ if ( jstor.len )
+ output_element( fp, "url", jstor.data, format_opts );
+ str_free( &jstor );
+ }
+}
+
+static void
+output_pages( FILE *fp, fields *info, unsigned long refnum, int format_opts )
+{
+ str pages;
+ int sn, en;
+ sn = fields_find( info, "PAGES:START", -1 );
+ en = fields_find( info, "PAGES:STOP", -1 );
+ if ( sn==-1 && en==-1 ) {
+ output_articlenumber( fp, info, refnum, format_opts );
+ return;
+ }
+ str_init( &pages );
+ if ( sn!=-1 ) {
+ str_strcat( &pages, info->data[sn].data );
+ fields_setused( info, sn );
+ }
+ if ( sn!=-1 && en!=-1 ) {
+ if ( format_opts & BIBL_FORMAT_BIBOUT_SINGLEDASH )
+ str_strcat( &pages, "-" );
+ else
+ str_strcat( &pages, "--" );
+ }
+ if ( en!=-1 ) {
+ str_strcat( &pages, info->data[en].data );
+ fields_setused( info, en );
+ }
+ output_element( fp, "pages", pages.data, format_opts );
+ str_free( &pages );
+}
+
+/*
+ * from Tim Hicks:
+ * I'm no expert on bibtex, but those who know more than I on our mailing
+ * list suggest that 'issue' isn't a recognised key for bibtex and
+ * therefore that bibutils should be aliasing IS to number at some point in
+ * the conversion.
+ *
+ * Therefore prefer outputting issue/number as number and only keep
+ * a distinction if both issue and number are present for a particular
+ * reference.
+ */
+
+static void
+output_issue_number( FILE *fp, fields *info, int format_opts )
+{
+ int nissue = fields_find( info, "ISSUE", -1 );
+ int nnumber = fields_find( info, "NUMBER", -1 );
+ if ( nissue!=-1 && nnumber!=-1 ) {
+ output_and_use( fp, info, nissue, "issue", format_opts );
+ output_and_use( fp, info, nnumber, "number", format_opts );
+/* output_element( fp, "issue", info->data[nissue].data,
+ format_opts );
+ fields_setused( info, nissue );
+ output_element( fp, "number", info->data[nnumber].data,
+ format_opts );
+ fields_setused( info, nnumber );*/
+ } else if ( nissue!=-1 ) {
+ output_and_use( fp, info, nissue, "number", format_opts );
+/*
+ output_element( fp, "number", info->data[nissue].data,
+ format_opts );
+ fields_setused( info, nissue );*/
+ } else if ( nnumber!=-1 ) {
+ output_and_use( fp, info, nnumber, "number", format_opts );
+/*
+ output_element( fp, "number", info->data[nnumber].data,
+ format_opts );
+ fields_setused( info, nnumber );
+*/
+ }
+}
+
+void
+bibtexout_write( fields *info, FILE *fp, param *p, unsigned long refnum )
+{
+ int type;
+ fields_clearused( info );
+ type = bibtexout_type( info, "", refnum, p );
+ output_type( fp, type, p->format_opts );
+ if ( !( p->format_opts & BIBL_FORMAT_BIBOUT_DROPKEY ) )
+ output_citekey( fp, info, refnum, p->format_opts );
+ output_people( fp, info, refnum, "AUTHOR", "AUTHOR:CORP", "AUTHOR:ASIS", "author", 0,
+ p->format_opts );
+ output_people( fp, info, refnum, "EDITOR", "EDITOR:CORP", "EDITOR:ASIS", "editor", -1,
+ p->format_opts );
+ output_people( fp, info, refnum, "TRANSLATOR", "TRANSLATOR:CORP", "TRANSLATOR:ASIS", "translator", -1, p->format_opts );
+
+ /* item=main level title */
+ if ( type==TYPE_INBOOK )
+ output_title( fp, info, refnum, "chapter", 0, p->format_opts );
+ else
+ output_title( fp, info, refnum, "title", 0, p->format_opts );
+
+ /* item=host level title */
+ if ( type==TYPE_ARTICLE )
+ output_title( fp, info, refnum, "journal", 1, p->format_opts );
+ else if ( type==TYPE_INBOOK ) {
+ output_title( fp, info, refnum, "title", 1, p->format_opts );
+ output_title( fp, info, refnum, "series", 2, p->format_opts );
+ }
+ else if ( type==TYPE_INPROCEEDINGS || type==TYPE_INCOLLECTION ) {
+ output_title( fp, info, refnum, "booktitle", 1, p->format_opts );
+ output_title( fp, info, refnum, "series", 2, p->format_opts );
+ }
+ else if ( type==TYPE_PHDTHESIS || type==TYPE_MASTERSTHESIS ) {
+ output_title( fp, info, refnum, "series", 1, p->format_opts );
+ }
+ else if ( type==TYPE_BOOK || type==TYPE_COLLECTION || type==TYPE_PROCEEDINGS )
+ output_title( fp, info, refnum, "series", 1, p->format_opts );
+
+ output_date( fp, info, refnum, p->format_opts );
+ output_simple( fp, info, "EDITION", "edition", p->format_opts );
+ output_simple( fp, info, "PUBLISHER", "publisher", p->format_opts );
+ output_simple( fp, info, "ADDRESS", "address", p->format_opts );
+ output_simple( fp, info, "VOLUME", "volume", p->format_opts );
+ output_issue_number( fp, info, p->format_opts );
+/* output_simple( fp, info, "ISSUE", "issue", p->format_opts );
+ output_simple( fp, info, "NUMBER", "number", p->format_opts );s*/
+ output_pages( fp, info, refnum, p->format_opts );
+ output_simpleall( fp, info, "KEYWORD", "keywords", p->format_opts );
+ output_simple( fp, info, "CONTENTS", "contents", p->format_opts );
+ output_simple( fp, info, "ABSTRACT", "abstract", p->format_opts );
+ output_simple( fp, info, "LOCATION", "location", p->format_opts );
+ output_simple( fp, info, "DEGREEGRANTOR", "school", p->format_opts );
+ output_simple( fp, info, "DEGREEGRANTOR:ASIS", "school", p->format_opts );
+ output_simple( fp, info, "DEGREEGRANTOR:CORP", "school", p->format_opts );
+ output_simpleall( fp, info, "NOTES", "note", p->format_opts );
+ output_simpleall( fp, info, "ANNOTE", "annote", p->format_opts );
+ output_simple( fp, info, "ISBN", "isbn", p->format_opts );
+ output_simple( fp, info, "ISSN", "issn", p->format_opts );
+ output_simple( fp, info, "DOI", "doi", p->format_opts );
+ output_simpleall( fp, info, "URL", "url", p->format_opts );
+ output_fileattach( fp, info, p->format_opts );
+ output_arxiv( fp, info, p->format_opts );
+ output_pmid( fp, info, p->format_opts );
+ output_jstor( fp, info, p->format_opts );
+ output_simple( fp, info, "LANGUAGE", "language", p->format_opts );
+ if ( p->format_opts & BIBL_FORMAT_BIBOUT_FINALCOMMA ) fprintf( fp, "," );
+ fprintf( fp, "\n}\n\n" );
+ fflush( fp );
+}
+
+void
+bibtexout_writeheader( FILE *outptr, param *p )
+{
+ if ( p->utf8bom ) utf8_writebom( outptr );
+}
+