hs-bibutils-4.14: bibutils/adsout.c
/*
* adsout.c
*
* Copyright (c) Richard Mathar 2007-2012
* Copyright (c) Chris Putnam 2007-2012
*
* Program and source code released under the GPL
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <ctype.h>
#include "utf8.h"
#include "newstr.h"
#include "strsearch.h"
#include "fields.h"
#include "adsout.h"
void
adsout_initparams( param *p, const char *progname )
{
p->writeformat = BIBL_ADSABSOUT;
p->format_opts = 0;
p->charsetout = BIBL_CHARSET_DEFAULT;
p->charsetout_src = BIBL_SRC_DEFAULT;
p->latexout = 0;
p->utf8out = 0;
p->utf8bom = 0;
p->xmlout = 0;
p->nosplittitle = 0;
p->verbose = 0;
p->addcount = 0;
p->singlerefperfile = 0;
if ( p->charsetout == BIBL_CHARSET_UNICODE ) {
p->utf8out = p->utf8bom = 1;
}
p->headerf = adsout_writeheader;
p->footerf = NULL;
p->writef = adsout_write;
}
enum {
TYPE_UNKNOWN = 0,
TYPE_GENERIC,
TYPE_ARTICLE,
TYPE_MAGARTICLE,
TYPE_BOOK,
TYPE_INBOOK,
TYPE_INPROCEEDINGS,
TYPE_HEARING,
TYPE_BILL,
TYPE_CASE,
TYPE_NEWSPAPER,
TYPE_COMMUNICATION,
TYPE_BROADCAST,
TYPE_MANUSCRIPT,
TYPE_REPORT,
TYPE_THESIS,
TYPE_MASTERSTHESIS,
TYPE_PHDTHESIS,
TYPE_DIPLOMATHESIS,
TYPE_DOCTORALTHESIS,
TYPE_HABILITATIONTHESIS,
TYPE_PATENT,
TYPE_PROGRAM
};
typedef struct match_type {
char *name;
int type;
} match_type;
static int
get_type( fields *info )
{
match_type match_genres[] = {
{ "academic journal", TYPE_ARTICLE },
{ "magazine", TYPE_MAGARTICLE },
{ "conference publication", TYPE_INPROCEEDINGS },
{ "hearing", TYPE_HEARING },
{ "Ph.D. thesis", TYPE_PHDTHESIS },
{ "Masters thesis", TYPE_MASTERSTHESIS },
{ "Diploma thesis", TYPE_DIPLOMATHESIS },
{ "Doctoral thesis", TYPE_DOCTORALTHESIS },
{ "Habilitation thesis", TYPE_HABILITATIONTHESIS },
{ "legislation", TYPE_BILL },
{ "newspaper", TYPE_NEWSPAPER },
{ "communication", TYPE_COMMUNICATION },
{ "manuscript", TYPE_MANUSCRIPT },
{ "report", TYPE_REPORT },
{ "legal case and case notes", TYPE_CASE },
{ "patent", TYPE_PATENT },
};
int nmatch_genres = sizeof( match_genres ) / sizeof( match_genres[0] );
char *tag, *data;
int i, j, type = TYPE_UNKNOWN;
for ( i=0; i<info->n; ++i ) {
tag = info->tag[i].data;
if ( strcasecmp( tag, "GENRE" )!=0 &&
strcasecmp( tag, "NGENRE" )!=0 ) continue;
data = info->data[i].data;
for ( j=0; j<nmatch_genres; ++j ) {
if ( !strcasecmp( data, match_genres[j].name ) ) {
type = match_genres[j].type;
fields_setused( info, i );
}
}
if ( type==TYPE_UNKNOWN ) {
if ( !strcasecmp( data, "periodical" ) )
type = TYPE_ARTICLE;
else if ( !strcasecmp( data, "thesis" ) )
type = TYPE_THESIS;
else if ( !strcasecmp( data, "book" ) ) {
if ( info->level[i]==0 ) type = TYPE_BOOK;
else type = TYPE_INBOOK;
}
else if ( !strcasecmp( data, "collection" ) ) {
if ( info->level[i]==0 ) type = TYPE_BOOK;
else type = TYPE_INBOOK;
}
if ( type!=TYPE_UNKNOWN ) fields_setused( info, i );
}
}
if ( type==TYPE_UNKNOWN ) {
for ( i=0; i<info->n; ++i ) {
if ( strcasecmp( info->tag[i].data, "RESOURCE" ) )
continue;
data = info->data[i].data;
if ( !strcasecmp( data, "moving image" ) )
type = TYPE_BROADCAST;
else if ( !strcasecmp( data, "software, multimedia" ) )
type = TYPE_PROGRAM;
if ( type!=TYPE_UNKNOWN ) fields_setused( info, i );
}
}
/* default to generic */
if ( type==TYPE_UNKNOWN ) type = TYPE_GENERIC;
return type;
}
static void
output_title( FILE *fp, fields *f, char *full, char *sub, char *adstag, int level )
{
newstr *fulltitle, *subtitle, *vol, *iss, *sn, *en, *ar;
fulltitle = fields_findv( f, level, FIELDS_STRP, full );
subtitle = fields_findv( f, level, FIELDS_STRP, sub );
if ( fulltitle && fulltitle->len ) {
fprintf( fp, "%s %s", adstag, fulltitle->data );
if ( subtitle && subtitle->len ) {
if ( fulltitle->data[ fulltitle->len - 1 ] != '?' )
fprintf( fp, ": " );
else fprintf( fp, " " );
fprintf( fp, "%s", subtitle->data );
}
vol = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "VOLUME" );
if ( vol && vol->len ) fprintf( fp, ", vol. %s", vol->data );
iss = fields_findv_firstof( f, LEVEL_ANY, FIELDS_STRP, "ISSUE",
"NUMBER", NULL );
if ( iss && iss->len ) fprintf( fp, ", no. %s", iss->data );
sn = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "PAGESTART" );
en = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "PAGEEND" );
ar = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "ARTICLENUMBER" );
if ( sn && sn->len ) {
if ( en && en->len )
fprintf( fp, ", pp." );
else
fprintf( fp, ", p." );
fprintf( fp, " %s", sn->data );
} else if ( ar && ar->len ) {
fprintf( fp, ", p. %s", ar->data );
}
if ( en && en->len ) {
fprintf( fp, "-%s", en->data );
}
fprintf( fp, "\n" );
}
}
static void
output_person( FILE *fp, char *p )
{
int nseps = 0, nch;
while ( *p ) {
nch = 0;
if ( nseps==1 ) fprintf( fp, "," );
if ( nseps ) fprintf( fp, " " );
while ( *p && *p!='|' ) {
fprintf( fp, "%c", *p++ );
nch++;
}
if ( *p=='|' ) p++;
if ( nseps!=0 && nch==1 ) fprintf( fp, "." );
nseps++;
}
}
static void
output_people( FILE *fp, fields *f, char *tag1, char *tag2, char *tag3, char *adstag, int level )
{
vplist a;
int i;
vplist_init( &a );
fields_findv_eachof( f, level, FIELDS_CHRP, &a, tag1, tag2, tag3, NULL );
extern void fields_findv_eachof( fields *f, int level, int mode, vplist *a, ... );
for ( i=0; i<a.n; ++i ) {
if ( i==0 ) fprintf( fp, "%s ", adstag );
else fprintf( fp, "; " );
output_person( fp, (char *) vplist_get( &a, i) );
}
if ( a.n ) fprintf( fp, "\n" );
vplist_free( &a );
}
static void
output_pages( FILE *fp, fields *f )
{
newstr *sn = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "PAGESTART" );
newstr *en = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "PAGEEND" );
newstr *ar = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "ARTICLENUMBER" );
if ( sn && sn->len!=0 ) fprintf( fp, "%%P %s\n", sn->data );
else if ( ar && ar->len!=0 ) fprintf( fp, "%%P %s\n", ar->data );
if ( en && en->len!=0 ) fprintf( fp, "%%L %s\n", en->data );
}
static int
mont2mont( const char *m )
{
static char *monNames[]= { "jan", "feb", "mar", "apr", "may",
"jun", "jul", "aug", "sep", "oct", "nov", "dec" };
int i;
if ( isdigit( m[0] ) ) return atoi( m );
else {
for ( i=0; i<12; i++ ) {
if ( !strncasecmp( m, monNames[i], 3 ) ) return i+1;
}
}
return 0;
}
static int
get_month( fields *f, int level )
{
newstr *month = fields_findv_firstof( f, level, FIELDS_STRP,
"MONTH", "PARTMONTH", NULL );
if ( month && month->len ) return mont2mont( month->data );
else return 0;
}
static void
output_date( FILE *fp, fields *f, char *adstag, int level )
{
newstr *year = fields_findv_firstof( f, level, FIELDS_STRP,
"YEAR", "PARTYEAR", NULL );
int month;
if ( year && year->len ) {
month = get_month( f, level );
fprintf( fp, "%s %02d/%s\n", adstag, month, year->data );
}
}
#include "adsout_journals.c"
static void
output_4digit_value( char *pos, long long n )
{
char buf[6];
n = n % 10000; /* truncate to 0->9999, will fit in buf[6] */
sprintf( buf, "%lld", n );
if ( n < 10 ) strncpy( pos+3, buf, 1 );
else if ( n < 100 ) strncpy( pos+2, buf, 2 );
else if ( n < 1000 ) strncpy( pos+1, buf, 3 );
else strncpy( pos, buf, 4 );
}
static char
get_firstinitial( fields *f )
{
char *name;
int n;
n = fields_find( f, "AUTHOR", LEVEL_MAIN );
if ( n==-1 ) n = fields_find( f, "AUTHOR", LEVEL_ANY );
if ( n!=-1 ) {
name = fields_value( f, n, FIELDS_CHRP );
return name[0];
} else return '\0';
}
static int
min( int a, int b )
{
if ( a < b ) return a;
else return b;
}
static int
get_journalabbr( fields *f )
{
char *jrnl;
int ljrnl, ltmp, len, n, j;
n = fields_find( f, "TITLE", LEVEL_HOST );
if ( n!=-1 ) {
jrnl = fields_value( f, n, FIELDS_CHRP );
ljrnl = strlen( jrnl );
for ( j=0; j<njournals; j++ ) {
ltmp = strlen( journals[j]+6 );
len = min( ljrnl, ltmp );
if ( !strncasecmp( jrnl, journals[j]+6, len ) )
return j;
}
}
return -1;
}
static void
output_Rtag( FILE *fp, fields *f, char *adstag, int type )
{
char out[20], ch;
int n;
long long page;
strcpy( out, "..................." );
/** YYYY */
n = fields_find( f, "YEAR", LEVEL_ANY );
if ( n==-1 ) n = fields_find( f, "PARTYEAR", LEVEL_ANY );
if ( n!=-1 ) output_4digit_value( out, atoi( fields_value( f, n, FIELDS_CHRP ) ) );
/** JJJJ */
n = get_journalabbr( f );
if ( n!=-1 ) strncpy( out+4, journals[n], 5 );
/** VVVV */
n = fields_find( f, "VOLUME", LEVEL_ANY );
if ( n!=-1 ) output_4digit_value( out+9, atoi( fields_value( f, n, FIELDS_CHRP ) ) );
/** MPPPP */
n = fields_find( f, "PAGESTART", LEVEL_ANY );
if ( n==-1 ) n = fields_find( f, "ARTICLENUMBER", LEVEL_ANY );
if ( n!=-1 ) {
page = atoll( fields_value( f, n, FIELDS_CHRP ) );
output_4digit_value( out+14, page );
if ( page>=10000 ) {
ch = 'a' + (page/10000);
out[13] = ch;
}
}
/** A */
ch = toupper( get_firstinitial( f ) );
if ( ch!='\0' ) out[18] = ch;
fprintf( fp, "%s %s\n", adstag, out );
}
static void
output_easyall( FILE *fp, fields *f, char *tag, char *adstag, int level )
{
vplist a;
int i;
vplist_init( &a );
fields_findv_each( f, level, FIELDS_CHRP, &a, tag );
for ( i=0; i<a.n; ++i )
fprintf( fp, "%s %s\n", adstag, (char *) vplist_get( &a, i ) );
vplist_free( &a );
}
static void
output_easy( FILE *fp, fields *f, char *tag, char *adstag, int level )
{
char *value = fields_findv( f, level, FIELDS_CHRP, tag );
if ( value && value[0]!='\0' ) fprintf( fp, "%s %s\n", adstag, value );
}
static void
output_keys( FILE *fp, fields *f, char *tag, char *adstag, int level )
{
vplist a;
int i;
vplist_init( &a );
fields_findv_each( f, level, FIELDS_CHRP, &a, tag );
for ( i=0; i<a.n; ++i ) {
if ( i==0 ) fprintf( fp, "%s ", adstag );
else fprintf( fp, ", " );
fprintf( fp, "%s", (char *) vplist_get( &a, i ) );
}
if ( a.n ) fprintf( fp, "\n" );
vplist_free( &a );
}
void
adsout_write( fields *f, FILE *fp, param *p, unsigned long refnum )
{
int type;
fields_clearused( f );
type = get_type( f );
output_people( fp, f, "AUTHOR", "AUTHOR:ASIS", "AUTHOR:CORP", "%A", LEVEL_MAIN );
output_people( fp, f, "EDITOR", "EDITOR:ASIS", "EDITOR:CORP", "%E", LEVEL_ANY );
output_easy( fp, f, "TITLE", "%T", LEVEL_ANY );
if ( type==TYPE_ARTICLE || type==TYPE_MAGARTICLE )
output_title( fp, f, "TITLE", "SUBTITLE", "%J", LEVEL_HOST );
output_date( fp, f, "%D", LEVEL_ANY );
output_easy( fp, f, "VOLUME", "%V", LEVEL_ANY );
output_easy( fp, f, "ISSUE", "%N", LEVEL_ANY );
output_easy( fp, f, "NUMBER", "%N", LEVEL_ANY );
output_easy( fp, f, "LANGUAGE", "%M", LEVEL_ANY );
output_easyall( fp, f, "NOTES", "%X", LEVEL_ANY );
output_easy( fp, f, "ABSTRACT", "%B", LEVEL_ANY );
output_keys( fp, f, "KEYWORD", "%K", LEVEL_ANY );
output_easyall( fp, f, "URL", "%U", LEVEL_ANY );
output_easyall( fp, f, "FILEATTACH", "%U", LEVEL_ANY );
output_easyall( fp, f, "FIGATTACH", "%U", LEVEL_ANY );
output_pages( fp, f );
output_easyall( fp, f, "DOI", "%Y", LEVEL_ANY );
fprintf( fp, "%%W PHY\n%%G AUTHOR\n" );
output_Rtag( fp, f, "%R", type );
fprintf( fp, "\n" );
fflush( fp );
}
void
adsout_writeheader( FILE *outptr, param *p )
{
if ( p->utf8bom ) utf8_writebom( outptr );
}