Blame bibutils/risout.c

Packit 89ede9
/*
Packit 89ede9
 * risout.c
Packit 89ede9
 *
Packit 89ede9
 * Copyright (c) Chris Putnam 2003-2018
Packit 89ede9
 *
Packit 89ede9
 * Source code released under the GPL version 2
Packit 89ede9
 *
Packit 89ede9
 */
Packit 89ede9
#include <stdio.h>
Packit 89ede9
#include <stdlib.h>
Packit 89ede9
#include <string.h>
Packit 89ede9
#include <ctype.h>
Packit 89ede9
#include "utf8.h"
Packit 89ede9
#include "str.h"
Packit 89ede9
#include "strsearch.h"
Packit 89ede9
#include "fields.h"
Packit 89ede9
#include "name.h"
Packit 89ede9
#include "title.h"
Packit 89ede9
#include "url.h"
Packit 89ede9
#include "bibformats.h"
Packit 89ede9
Packit 89ede9
static int  risout_write( fields *info, FILE *fp, param *p, unsigned long refnum );
Packit 89ede9
static void risout_writeheader( FILE *outptr, param *p );
Packit 89ede9
Packit 89ede9
Packit 89ede9
void
Packit 89ede9
risout_initparams( param *p, const char *progname )
Packit 89ede9
{
Packit 89ede9
	p->writeformat      = BIBL_RISOUT;
Packit 89ede9
	p->format_opts      = 0;
Packit 89ede9
	p->charsetout       = BIBL_CHARSET_DEFAULT;
Packit 89ede9
	p->charsetout_src   = BIBL_SRC_DEFAULT;
Packit 89ede9
	p->latexout         = 0;
Packit 89ede9
	p->utf8out          = BIBL_CHARSET_UTF8_DEFAULT;
Packit 89ede9
	p->utf8bom          = BIBL_CHARSET_BOM_DEFAULT;
Packit 89ede9
	p->xmlout           = BIBL_XMLOUT_FALSE;
Packit 89ede9
	p->nosplittitle     = 0;
Packit 89ede9
	p->verbose          = 0;
Packit 89ede9
	p->addcount         = 0;
Packit 89ede9
	p->singlerefperfile = 0;
Packit 89ede9
Packit 89ede9
	if ( p->charsetout == BIBL_CHARSET_UNICODE ) {
Packit 89ede9
		p->utf8out = p->utf8bom = 1;
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	p->headerf = risout_writeheader;
Packit 89ede9
	p->footerf = NULL;
Packit 89ede9
	p->writef  = risout_write;
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
enum { 
Packit 89ede9
	TYPE_UNKNOWN = 0,
Packit 89ede9
	TYPE_STD,                /* standard/generic */
Packit 89ede9
	TYPE_ABSTRACT,           /* abstract */
Packit 89ede9
	TYPE_ARTICLE,            /* article */
Packit 89ede9
	TYPE_BOOK,               /* book */
Packit 89ede9
	TYPE_CASE,               /* case */
Packit 89ede9
	TYPE_INBOOK,             /* chapter */
Packit 89ede9
	TYPE_CONF,               /* conference */
Packit 89ede9
	TYPE_ELEC,               /* electronic */
Packit 89ede9
	TYPE_HEAR,               /* hearing */
Packit 89ede9
	TYPE_MAGARTICLE,         /* magazine article */
Packit 89ede9
	TYPE_NEWSPAPER,          /* newspaper */
Packit 89ede9
	TYPE_MPCT,               /* mpct */
Packit 89ede9
	TYPE_PAMPHLET,           /* pamphlet */
Packit 89ede9
	TYPE_PATENT,             /* patent */
Packit 89ede9
	TYPE_PCOMM,              /* personal communication */
Packit 89ede9
	TYPE_PROGRAM,            /* program */
Packit 89ede9
	TYPE_REPORT,             /* report */
Packit 89ede9
	TYPE_STATUTE,            /* statute */
Packit 89ede9
	TYPE_THESIS,             /* thesis */
Packit 89ede9
	TYPE_LICENTIATETHESIS,   /* thesis */
Packit 89ede9
	TYPE_MASTERSTHESIS,      /* thesis */
Packit 89ede9
	TYPE_PHDTHESIS,          /* thesis */
Packit 89ede9
	TYPE_DIPLOMATHESIS,      /* thesis */
Packit 89ede9
	TYPE_DOCTORALTHESIS,     /* thesis */
Packit 89ede9
	TYPE_HABILITATIONTHESIS, /* thesis */
Packit 89ede9
	TYPE_MAP,                /* map, cartographic data */
Packit 89ede9
	TYPE_UNPUBLISHED,        /* unpublished */
Packit 89ede9
	NUM_TYPES
Packit 89ede9
};
Packit 89ede9
Packit 89ede9
static int type_is_element[ NUM_TYPES ] = {
Packit 89ede9
	[ 0 ... NUM_TYPES-1 ] = 0,
Packit 89ede9
	[ TYPE_ARTICLE      ] = 1,
Packit 89ede9
	[ TYPE_INBOOK       ] = 1,
Packit 89ede9
	[ TYPE_MAGARTICLE   ] = 1,
Packit 89ede9
	[ TYPE_NEWSPAPER    ] = 1,
Packit 89ede9
	[ TYPE_ABSTRACT     ] = 1,
Packit 89ede9
	[ TYPE_CONF         ] = 1,
Packit 89ede9
};
Packit 89ede9
Packit 89ede9
static int type_uses_journal[ NUM_TYPES ] = {
Packit 89ede9
	[ 0 ... NUM_TYPES-1 ] = 0,
Packit 89ede9
	[ TYPE_ARTICLE      ] = 1,
Packit 89ede9
	[ TYPE_MAGARTICLE   ] = 1,
Packit 89ede9
};
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
write_type( FILE *fp, int type )
Packit 89ede9
{
Packit 89ede9
	const char *typenames[ NUM_TYPES ] = {
Packit 89ede9
		[ TYPE_UNKNOWN            ] = "TYPE_UNKNOWN",
Packit 89ede9
		[ TYPE_STD                ] = "TYPE_STD",
Packit 89ede9
		[ TYPE_ABSTRACT           ] = "TYPE_ABSTRACT",
Packit 89ede9
		[ TYPE_ARTICLE            ] = "TYPE_ARTICLE",
Packit 89ede9
		[ TYPE_BOOK               ] = "TYPE_BOOK",
Packit 89ede9
		[ TYPE_CASE               ] = "TYPE_CASE",
Packit 89ede9
		[ TYPE_INBOOK             ] = "TYPE_INBOOK",
Packit 89ede9
		[ TYPE_CONF               ] = "TYPE_CONF",
Packit 89ede9
		[ TYPE_ELEC               ] = "TYPE_ELEC",
Packit 89ede9
		[ TYPE_HEAR               ] = "TYPE_HEAR",
Packit 89ede9
		[ TYPE_MAGARTICLE         ] = "TYPE_MAGARTICLE",
Packit 89ede9
		[ TYPE_NEWSPAPER          ] = "TYPE_NEWSPAPER",
Packit 89ede9
		[ TYPE_MPCT               ] = "TYPE_MPCT",
Packit 89ede9
		[ TYPE_PAMPHLET           ] = "TYPE_PAMPHLET",
Packit 89ede9
		[ TYPE_PATENT             ] = "TYPE_PATENT",
Packit 89ede9
		[ TYPE_PCOMM              ] = "TYPE_PCOMM",
Packit 89ede9
		[ TYPE_PROGRAM            ] = "TYPE_PROGRAM",
Packit 89ede9
		[ TYPE_REPORT             ] = "TYPE_REPORT",
Packit 89ede9
		[ TYPE_STATUTE            ] = "TYPE_STATUTE",
Packit 89ede9
		[ TYPE_THESIS             ] = "TYPE_THESIS",
Packit 89ede9
		[ TYPE_LICENTIATETHESIS   ] = "TYPE_LICENTIATETHESIS",
Packit 89ede9
		[ TYPE_MASTERSTHESIS      ] = "TYPE_MASTERSTHESIS",
Packit 89ede9
		[ TYPE_PHDTHESIS          ] = "TYPE_PHDTHESIS",
Packit 89ede9
		[ TYPE_DIPLOMATHESIS      ] = "TYPE_DIPLOMATHESIS",
Packit 89ede9
		[ TYPE_DOCTORALTHESIS     ] = "TYPE_DOCTORALTHESIS",
Packit 89ede9
		[ TYPE_HABILITATIONTHESIS ] = "TYPE_HABILITATIONTHESIS",
Packit 89ede9
		[ TYPE_MAP                ] = "TYPE_MAP",
Packit 89ede9
		[ TYPE_UNPUBLISHED        ] = "TYPE_UNPUBLISHED",
Packit 89ede9
	};
Packit 89ede9
Packit 89ede9
	if ( type < 0 || type >= NUM_TYPES ) fprintf( fp, "Error - type not in enum" );
Packit 89ede9
	else fprintf( fp, "%s", typenames[ type ] );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
verbose_type_identified( char *element_type, param *p, int type )
Packit 89ede9
{
Packit 89ede9
	if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
Packit 89ede9
	fprintf( stderr, "Type from %s element: ", element_type );
Packit 89ede9
	write_type( stderr, type );
Packit 89ede9
	fprintf( stderr, "\n" );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
verbose_type_assignment( char *tag, char *value, param *p, int type )
Packit 89ede9
{
Packit 89ede9
	if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
Packit 89ede9
	fprintf( stderr, "Type from tag '%s' data '%s': ", tag, value );
Packit 89ede9
	write_type( stderr, type );
Packit 89ede9
	fprintf( stderr, "\n" );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
typedef struct match_type {
Packit 89ede9
	char *name;
Packit 89ede9
	int type;
Packit 89ede9
} match_type;
Packit 89ede9
Packit 89ede9
/* Try to determine type of reference from
Packit 89ede9
 * <genre></genre>
Packit 89ede9
 */
Packit 89ede9
static int
Packit 89ede9
get_type_genre( fields *f, param *p )
Packit 89ede9
{
Packit 89ede9
	match_type match_genres[] = {
Packit 89ede9
		{ "academic journal",          TYPE_ARTICLE },
Packit 89ede9
		{ "article",                   TYPE_ARTICLE },
Packit 89ede9
		{ "journal article",           TYPE_ARTICLE },
Packit 89ede9
		{ "magazine",                  TYPE_MAGARTICLE },
Packit 89ede9
		{ "conference publication",    TYPE_CONF },
Packit 89ede9
		{ "newspaper",                 TYPE_NEWSPAPER },
Packit 89ede9
		{ "legislation",               TYPE_STATUTE },
Packit 89ede9
		{ "communication",             TYPE_PCOMM },
Packit 89ede9
		{ "hearing",                   TYPE_HEAR },
Packit 89ede9
		{ "electronic",                TYPE_ELEC },
Packit 89ede9
		{ "legal case and case notes", TYPE_CASE },
Packit 89ede9
		{ "book chapter",              TYPE_INBOOK },
Packit 89ede9
		{ "Ph.D. thesis",              TYPE_PHDTHESIS },
Packit 89ede9
		{ "Licentiate thesis",         TYPE_LICENTIATETHESIS },
Packit 89ede9
		{ "Masters thesis",            TYPE_MASTERSTHESIS },
Packit 89ede9
		{ "Diploma thesis",            TYPE_DIPLOMATHESIS },
Packit 89ede9
		{ "Doctoral thesis",           TYPE_DOCTORALTHESIS },
Packit 89ede9
		{ "Habilitation thesis",       TYPE_HABILITATIONTHESIS },
Packit 89ede9
		{ "report",                    TYPE_REPORT },
Packit 89ede9
		{ "technical report",          TYPE_REPORT },
Packit 89ede9
		{ "abstract or summary",       TYPE_ABSTRACT },
Packit 89ede9
		{ "patent",                    TYPE_PATENT },
Packit 89ede9
		{ "unpublished",               TYPE_UNPUBLISHED },
Packit 89ede9
		{ "manuscript",                TYPE_UNPUBLISHED },
Packit 89ede9
		{ "map",                       TYPE_MAP },
Packit 89ede9
	};
Packit 89ede9
	int nmatch_genres = sizeof( match_genres ) / sizeof( match_genres[0] );
Packit 89ede9
	char *tag, *value;
Packit 89ede9
	int type, i, j;
Packit 89ede9
Packit 89ede9
	type = TYPE_UNKNOWN;
Packit 89ede9
Packit 89ede9
	for ( i=0; i
Packit 89ede9
		tag = ( char * ) fields_tag( f, i, FIELDS_CHRP );
Packit 89ede9
		if ( strcmp( tag, "GENRE:MARC" ) && strcmp( tag, "GENRE:BIBUTILS" ) && strcmp( tag, "GENRE:UNKNOWN") ) continue;
Packit 89ede9
		value = ( char * ) fields_value( f, i, FIELDS_CHRP );
Packit 89ede9
		for ( j=0; j
Packit 89ede9
			if ( !strcasecmp( match_genres[j].name, value ) )
Packit 89ede9
				type = match_genres[j].type;
Packit 89ede9
		if ( p->verbose ) verbose_type_assignment( tag, value, p, type );
Packit 89ede9
		if ( type==TYPE_UNKNOWN ) {
Packit 89ede9
			if ( !strcasecmp( value, "periodical" ) )
Packit 89ede9
				type = TYPE_ARTICLE;
Packit 89ede9
			else if ( !strcasecmp( value, "thesis" ) )
Packit 89ede9
				type = TYPE_THESIS;
Packit 89ede9
			else if ( !strcasecmp( value, "book" ) ) {
Packit 89ede9
				if ( fields_level( f, i )==0 ) type=TYPE_BOOK;
Packit 89ede9
				else type=TYPE_INBOOK;
Packit 89ede9
			}
Packit 89ede9
			else if ( !strcasecmp( value, "collection" ) ) {
Packit 89ede9
				if ( fields_level( f, i )==0 ) type=TYPE_BOOK;
Packit 89ede9
				else type=TYPE_INBOOK;
Packit 89ede9
			}
Packit 89ede9
		}
Packit 89ede9
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	if ( p->verbose ) verbose_type_identified( "genre", p, type );
Packit 89ede9
Packit 89ede9
	return type;
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
/* Try to determine type of reference from
Packit 89ede9
 * <TypeOfResource></TypeOfResource>
Packit 89ede9
 */
Packit 89ede9
static int
Packit 89ede9
get_type_resource( fields *f, param *p )
Packit 89ede9
{
Packit 89ede9
	match_type match_res[] = {
Packit 89ede9
		{ "software, multimedia",      TYPE_PROGRAM },
Packit 89ede9
		{ "cartographic",              TYPE_MAP     },
Packit 89ede9
	};
Packit 89ede9
	int nmatch_res = sizeof( match_res ) / sizeof( match_res[0] );
Packit 89ede9
	vplist_index i;
Packit 89ede9
	int type, j;
Packit 89ede9
	char *value;
Packit 89ede9
	vplist a;
Packit 89ede9
Packit 89ede9
	type = TYPE_UNKNOWN;
Packit 89ede9
Packit 89ede9
	vplist_init( &a );
Packit 89ede9
	fields_findv_each( f, LEVEL_ANY, FIELDS_CHRP, &a, "RESOURCE" );
Packit 89ede9
Packit 89ede9
	for ( i=0; i
Packit 89ede9
		value = ( char * ) vplist_get( &a, i );
Packit 89ede9
		for ( j=0; j
Packit 89ede9
			if ( !strcasecmp( value, match_res[j].name ) )
Packit 89ede9
				type = match_res[j].type;
Packit 89ede9
		}
Packit 89ede9
		if ( p->verbose ) verbose_type_assignment( "RESOURCE", value, p, type );
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	if ( p->verbose ) verbose_type_identified( "resource", p, type );
Packit 89ede9
Packit 89ede9
	vplist_free( &a );
Packit 89ede9
	return type;
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
/* Try to determine type of reference from <issuance></issuance> and */
Packit 89ede9
/* <typeOfReference></typeOfReference> */
Packit 89ede9
static int
Packit 89ede9
get_type_issuance( fields *f, param *p )
Packit 89ede9
{
Packit 89ede9
	int type = TYPE_UNKNOWN;
Packit 89ede9
	int i, monographic = 0, monographic_level = 0;
Packit 89ede9
//	int text = 0;
Packit 89ede9
	for ( i=0; i<f->n; ++i ) {
Packit 89ede9
		if ( !strcasecmp( (char *) fields_tag( f, i, FIELDS_CHRP_NOUSE ), "issuance" ) &&
Packit 89ede9
		     !strcasecmp( (char *) fields_value( f, i, FIELDS_CHRP_NOUSE ), "MONOGRAPHIC" ) ){
Packit 89ede9
			monographic = 1;
Packit 89ede9
			monographic_level = f->level[i];
Packit 89ede9
		}
Packit 89ede9
//		if ( !strcasecmp( (char *) fields_tag( f, i, FIELDS_CHRP_NOUSE ), "typeOfResource" ) &&
Packit 89ede9
//		     !strcasecmp( (char *) fields_value( f, i, FIELDS_CHRP_NOUSE ), "text" ) ) {
Packit 89ede9
//			text = 1;
Packit 89ede9
//		}
Packit 89ede9
	}
Packit 89ede9
//	if ( monographic && text ) {
Packit 89ede9
	if ( monographic ) {
Packit 89ede9
		if ( monographic_level==0 ) type=TYPE_BOOK;
Packit 89ede9
		else if ( monographic_level>0 ) type=TYPE_INBOOK;
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	if ( p->verbose ) {
Packit 89ede9
		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
Packit 89ede9
		fprintf( stderr, "Type from issuance/typeOfReference elements: " );
Packit 89ede9
		write_type( stderr, type );
Packit 89ede9
		fprintf( stderr, "\n" );
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	return type;
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static int
Packit 89ede9
get_type( fields *f, param *p )
Packit 89ede9
{
Packit 89ede9
	int type;
Packit 89ede9
	type = get_type_genre( f, p );
Packit 89ede9
	if ( type==TYPE_UNKNOWN ) type = get_type_resource( f, p );
Packit 89ede9
	if ( type==TYPE_UNKNOWN ) type = get_type_issuance( f, p );
Packit 89ede9
	if ( type==TYPE_UNKNOWN ) {
Packit 89ede9
		if ( fields_maxlevel( f ) > 0 ) type = TYPE_INBOOK;
Packit 89ede9
		else type = TYPE_STD;
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	if ( p->verbose ) {
Packit 89ede9
		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
Packit 89ede9
		fprintf( stderr, "Final type: " );
Packit 89ede9
		write_type( stderr, type );
Packit 89ede9
		fprintf( stderr, "\n" );
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
Packit 89ede9
	return type;
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
append_type( int type, param *p, fields *out, int *status )
Packit 89ede9
{
Packit 89ede9
	char *typenames[ NUM_TYPES ] = {
Packit 89ede9
		[ TYPE_STD                ] = "STD",
Packit 89ede9
		[ TYPE_ABSTRACT           ] = "ABST",
Packit 89ede9
		[ TYPE_ARTICLE            ] = "JOUR",
Packit 89ede9
		[ TYPE_BOOK               ] = "BOOK",
Packit 89ede9
		[ TYPE_CASE               ] = "CASE",
Packit 89ede9
		[ TYPE_INBOOK             ] = "CHAP",
Packit 89ede9
		[ TYPE_CONF               ] = "CONF",
Packit 89ede9
		[ TYPE_ELEC               ] = "ELEC",
Packit 89ede9
		[ TYPE_HEAR               ] = "HEAR",
Packit 89ede9
		[ TYPE_MAGARTICLE         ] = "MGZN",
Packit 89ede9
		[ TYPE_NEWSPAPER          ] = "NEWS",
Packit 89ede9
		[ TYPE_MPCT               ] = "MPCT",
Packit 89ede9
		[ TYPE_PAMPHLET           ] = "PAMP",
Packit 89ede9
		[ TYPE_PATENT             ] = "PAT",
Packit 89ede9
		[ TYPE_PCOMM              ] = "PCOMM",
Packit 89ede9
		[ TYPE_PROGRAM            ] = "COMP",
Packit 89ede9
		[ TYPE_REPORT             ] = "RPRT",
Packit 89ede9
		[ TYPE_STATUTE            ] = "STAT",
Packit 89ede9
		[ TYPE_THESIS             ] = "THES",
Packit 89ede9
		[ TYPE_MASTERSTHESIS      ] = "THES",
Packit 89ede9
		[ TYPE_PHDTHESIS          ] = "THES",
Packit 89ede9
		[ TYPE_DIPLOMATHESIS      ] = "THES",
Packit 89ede9
		[ TYPE_DOCTORALTHESIS     ] = "THES",
Packit 89ede9
		[ TYPE_HABILITATIONTHESIS ] = "THES",
Packit 89ede9
		[ TYPE_MAP                ] = "MAP",
Packit 89ede9
		[ TYPE_UNPUBLISHED        ] = "UNPB",
Packit 89ede9
	};
Packit 89ede9
	int fstatus;
Packit 89ede9
Packit 89ede9
	if ( type < 0 || type >= NUM_TYPES ) {
Packit 89ede9
		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
Packit 89ede9
		fprintf( stderr, "Internal error: Cannot recognize type %d, switching to TYPE_STD %d\n", type, TYPE_STD );
Packit 89ede9
		type = TYPE_STD;
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	fstatus = fields_add( out, "TY", typenames[ type ], LEVEL_MAIN );
Packit 89ede9
	if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
append_people( fields *f, char *tag, char *ristag, int level, fields *out, int *status )
Packit 89ede9
{
Packit 89ede9
	vplist_index i;
Packit 89ede9
	str oneperson;
Packit 89ede9
	vplist people;
Packit 89ede9
	int fstatus;
Packit 89ede9
Packit 89ede9
	str_init( &oneperson );
Packit 89ede9
	vplist_init( &people );
Packit 89ede9
	fields_findv_each( f, level, FIELDS_CHRP, &people, tag );
Packit 89ede9
	for ( i=0; i
Packit 89ede9
		name_build_withcomma( &oneperson, ( char * ) vplist_get( &people, i ) );
Packit 89ede9
		if ( str_memerr( &oneperson ) ) { *status = BIBL_ERR_MEMERR; goto out; }
Packit 89ede9
		fstatus = fields_add_can_dup( out, ristag, str_cstr( &oneperson ), LEVEL_MAIN );
Packit 89ede9
		if ( fstatus!=FIELDS_OK ) { *status = BIBL_ERR_MEMERR; goto out; }
Packit 89ede9
	}
Packit 89ede9
out:
Packit 89ede9
	vplist_free( &people );
Packit 89ede9
	str_free( &oneperson );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
append_date( fields *in, fields *out, int *status )
Packit 89ede9
{
Packit 89ede9
	char *year, *month, *day;
Packit 89ede9
	str date;
Packit 89ede9
	int fstatus;
Packit 89ede9
Packit 89ede9
	year  = fields_findv_firstof( in, LEVEL_ANY, FIELDS_CHRP, "DATE:YEAR",  "PARTDATE:YEAR",  NULL );
Packit 89ede9
	month = fields_findv_firstof( in, LEVEL_ANY, FIELDS_CHRP, "DATE:MONTH", "PARTDATE:MONTH", NULL );
Packit 89ede9
	day   = fields_findv_firstof( in, LEVEL_ANY, FIELDS_CHRP, "DATE:DAY",   "PARTDATE:DAY",   NULL );
Packit 89ede9
Packit 89ede9
	if ( year ) {
Packit 89ede9
		fstatus = fields_add( out, "PY", year, LEVEL_MAIN );
Packit 89ede9
		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	if ( year || month || day ) {
Packit 89ede9
		str_init( &date );
Packit 89ede9
Packit 89ede9
		if ( year ) str_strcatc( &date, year );
Packit 89ede9
		str_addchar( &date, '/' );
Packit 89ede9
		if ( month ) str_strcatc( &date, month );
Packit 89ede9
		str_addchar( &date, '/' );
Packit 89ede9
		if ( day ) str_strcatc( &date, day );
Packit 89ede9
Packit 89ede9
		if ( str_memerr( &date ) ) { *status = BIBL_ERR_MEMERR; str_free( &date ); return; }
Packit 89ede9
Packit 89ede9
		fstatus = fields_add( out, "DA", str_cstr( &date ), LEVEL_MAIN );
Packit 89ede9
		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
Packit 89ede9
Packit 89ede9
		str_free( &date );
Packit 89ede9
	}
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
append_titlecore( fields *in, char *ristag, int level, char *maintag, char *subtag, fields *out, int *status )
Packit 89ede9
{
Packit 89ede9
	str *mainttl = fields_findv( in, level, FIELDS_STRP, maintag );
Packit 89ede9
	str *subttl  = fields_findv( in, level, FIELDS_STRP, subtag );
Packit 89ede9
	str fullttl;
Packit 89ede9
	int fstatus;
Packit 89ede9
Packit 89ede9
	str_init( &fullttl );
Packit 89ede9
Packit 89ede9
	title_combine( &fullttl, mainttl, subttl );
Packit 89ede9
Packit 89ede9
	if ( str_memerr( &fullttl ) ) {
Packit 89ede9
		*status = BIBL_ERR_MEMERR;
Packit 89ede9
		goto out;
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	if ( str_has_value( &fullttl ) ) {
Packit 89ede9
		fstatus = fields_add( out, ristag, str_cstr( &fullttl ), LEVEL_MAIN );
Packit 89ede9
		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
out:
Packit 89ede9
	str_free( &fullttl );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
append_alltitles( fields *in, int type, fields *out, int *status )
Packit 89ede9
{
Packit 89ede9
	append_titlecore( in, "TI", 0, "TITLE", "SUBTITLE", out, status );
Packit 89ede9
	append_titlecore( in, "T2", -1, "SHORTTITLE", "SHORTSUBTITLE", out, status );
Packit 89ede9
	if ( type_is_element[ type ] ) {
Packit 89ede9
		if ( type_uses_journal[ type ] )
Packit 89ede9
			append_titlecore( in, "JO", 1, "TITLE", "SUBTITLE", out, status );
Packit 89ede9
		else append_titlecore( in, "BT", 1, "TITLE", "SUBTITLE", out, status );
Packit 89ede9
		append_titlecore( in, "T3", 2, "TITLE", "SUBTITLE", out, status );
Packit 89ede9
	} else {
Packit 89ede9
		append_titlecore( in, "T3", 1, "TITLE", "SUBTITLE", out, status );
Packit 89ede9
	}
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
append_pages( fields *in, fields *out, int *status )
Packit 89ede9
{
Packit 89ede9
	char *sn, *en, *ar;
Packit 89ede9
	int fstatus;
Packit 89ede9
Packit 89ede9
	sn = fields_findv( in, LEVEL_ANY, FIELDS_CHRP, "PAGES:START" );
Packit 89ede9
	en = fields_findv( in, LEVEL_ANY, FIELDS_CHRP, "PAGES:STOP" );
Packit 89ede9
Packit 89ede9
	if ( sn || en ) {
Packit 89ede9
		if ( sn ) {
Packit 89ede9
			fstatus = fields_add( out, "SP", sn, LEVEL_MAIN );
Packit 89ede9
			if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
Packit 89ede9
		}
Packit 89ede9
		if ( en ) {
Packit 89ede9
			fstatus = fields_add( out, "EP", en, LEVEL_MAIN );
Packit 89ede9
			if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
Packit 89ede9
		}
Packit 89ede9
	} else {
Packit 89ede9
		ar = fields_findv( in, LEVEL_ANY, FIELDS_CHRP, "ARTICLENUMBER" );
Packit 89ede9
		if ( ar ) {
Packit 89ede9
			fstatus = fields_add( out, "SP", ar, LEVEL_MAIN );
Packit 89ede9
			if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
Packit 89ede9
		}
Packit 89ede9
	}
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
append_keywords( fields *in, fields *out, int *status )
Packit 89ede9
{
Packit 89ede9
	vplist_index i;
Packit 89ede9
	int fstatus;
Packit 89ede9
	vplist vpl;
Packit 89ede9
Packit 89ede9
	vplist_init( &vpl );
Packit 89ede9
	fields_findv_each( in, LEVEL_ANY, FIELDS_CHRP, &vpl, "KEYWORD" );
Packit 89ede9
	for ( i=0; i
Packit 89ede9
		fstatus = fields_add( out, "KW", ( char * ) vplist_get( &vpl, i ), LEVEL_MAIN );
Packit 89ede9
		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
Packit 89ede9
	}
Packit 89ede9
	vplist_free( &vpl );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
append_urls( fields *in, fields *out, int *status )
Packit 89ede9
{
Packit 89ede9
	int lstatus;
Packit 89ede9
	slist types;
Packit 89ede9
Packit 89ede9
	lstatus = slist_init_valuesc( &types, "URL", "DOI", "PMID", "PMC", "ARXIV", "JSTOR", "MRNUMBER", NULL );
Packit 89ede9
	if ( lstatus!=SLIST_OK ) {
Packit 89ede9
		*status = BIBL_ERR_MEMERR;
Packit 89ede9
		return;
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	*status = urls_merge_and_add( in, LEVEL_ANY, out, "UR", LEVEL_MAIN, &types );
Packit 89ede9
Packit 89ede9
	slist_free( &types );
Packit 89ede9
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
append_thesishint( int type, fields *out, int *status )
Packit 89ede9
{
Packit 89ede9
	int fstatus;
Packit 89ede9
Packit 89ede9
	if ( type==TYPE_MASTERSTHESIS ) {
Packit 89ede9
		fstatus = fields_add( out, "U1", "Masters thesis", LEVEL_MAIN );
Packit 89ede9
		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	else if ( type==TYPE_PHDTHESIS ) {
Packit 89ede9
		fstatus = fields_add( out, "U1", "Ph.D. thesis", LEVEL_MAIN );
Packit 89ede9
		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	else if ( type==TYPE_DIPLOMATHESIS ) {
Packit 89ede9
		fstatus = fields_add( out, "U1", "Diploma thesis", LEVEL_MAIN );
Packit 89ede9
		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	else if ( type==TYPE_DOCTORALTHESIS ) {
Packit 89ede9
		fstatus = fields_add( out, "U1", "Doctoral thesis", LEVEL_MAIN );
Packit 89ede9
		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	else if ( type==TYPE_HABILITATIONTHESIS ) {
Packit 89ede9
		fstatus = fields_add( out, "U1", "Habilitation thesis", LEVEL_MAIN );
Packit 89ede9
		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	else if ( type==TYPE_LICENTIATETHESIS ) {
Packit 89ede9
		fstatus = fields_add( out, "U1", "Licentiate thesis", LEVEL_MAIN );
Packit 89ede9
		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
Packit 89ede9
	}
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static int
Packit 89ede9
is_uri_scheme( char *p )
Packit 89ede9
{
Packit 89ede9
	char *scheme[] = { "http:", "https:", "file:", "ftp:", "git:", "gopher:" };
Packit 89ede9
	int i, len, nschemes = sizeof( scheme ) / sizeof( scheme[0] );
Packit 89ede9
	for ( i=0; i
Packit 89ede9
		len = strlen( scheme[i] );
Packit 89ede9
		if ( !strncmp( p, scheme[i], len ) ) return len;
Packit 89ede9
	}
Packit 89ede9
	return 0;
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
append_file( fields *in, char *tag, char *ristag, int level, fields *out, int *status )
Packit 89ede9
{
Packit 89ede9
	vplist_index i;
Packit 89ede9
	str filename;
Packit 89ede9
	int fstatus;
Packit 89ede9
	vplist a;
Packit 89ede9
	char *fl;
Packit 89ede9
Packit 89ede9
	str_init( &filename );
Packit 89ede9
	vplist_init( &a );
Packit 89ede9
	fields_findv_each( in, level, FIELDS_CHRP, &a, tag );
Packit 89ede9
	for ( i=0; i
Packit 89ede9
		fl = ( char * ) vplist_get( &a, i );
Packit 89ede9
		str_empty( &filename );
Packit 89ede9
		if ( !is_uri_scheme( fl ) ) str_strcatc( &filename, "file:" );
Packit 89ede9
		str_strcatc( &filename, fl );
Packit 89ede9
		if ( str_memerr( &filename ) ) { *status = BIBL_ERR_MEMERR; goto out; }
Packit 89ede9
		fstatus = fields_add( out, ristag, str_cstr( &filename ), LEVEL_MAIN );
Packit 89ede9
		if ( fstatus!=FIELDS_OK ) { *status = BIBL_ERR_MEMERR; goto out; }
Packit 89ede9
	}
Packit 89ede9
out:
Packit 89ede9
	vplist_free( &a );
Packit 89ede9
	str_free( &filename );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
append_easy( fields *in, char *tag, char *ristag, int level, fields *out, int *status )
Packit 89ede9
{
Packit 89ede9
	char *value;
Packit 89ede9
	int fstatus;
Packit 89ede9
Packit 89ede9
	value = fields_findv( in, level, FIELDS_CHRP, tag );
Packit 89ede9
	if ( value ) {
Packit 89ede9
		fstatus = fields_add( out, ristag, value, LEVEL_MAIN );
Packit 89ede9
		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
Packit 89ede9
	}
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
append_easyall( fields *in, char *tag, char *ristag, int level, fields *out, int *status )
Packit 89ede9
{
Packit 89ede9
	vplist_index i;
Packit 89ede9
	int fstatus;
Packit 89ede9
	vplist a;
Packit 89ede9
Packit 89ede9
	vplist_init( &a );
Packit 89ede9
	fields_findv_each( in, level, FIELDS_CHRP, &a, tag );
Packit 89ede9
	for ( i=0; i
Packit 89ede9
		fstatus = fields_add( out, ristag, (char *) vplist_get( &a, i ), LEVEL_MAIN );
Packit 89ede9
		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
Packit 89ede9
	}
Packit 89ede9
	vplist_free( &a );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
append_allpeople( fields *in, int type, fields *out, int *status )
Packit 89ede9
{
Packit 89ede9
	append_people ( in, "AUTHOR",      "AU", LEVEL_MAIN,   out, status );
Packit 89ede9
	append_easyall( in, "AUTHOR:CORP", "AU", LEVEL_MAIN,   out, status );
Packit 89ede9
	append_easyall( in, "AUTHOR:ASIS", "AU", LEVEL_MAIN,   out, status );
Packit 89ede9
	append_people ( in, "AUTHOR",      "A2", LEVEL_HOST,   out, status );
Packit 89ede9
	append_easyall( in, "AUTHOR:CORP", "A2", LEVEL_HOST,   out, status );
Packit 89ede9
	append_easyall( in, "AUTHOR:ASIS", "A2", LEVEL_HOST,   out, status );
Packit 89ede9
	append_people ( in, "AUTHOR",      "A3", LEVEL_SERIES, out, status );
Packit 89ede9
	append_easyall( in, "AUTHOR:CORP", "A3", LEVEL_SERIES, out, status );
Packit 89ede9
	append_easyall( in, "AUTHOR:ASIS", "A3", LEVEL_SERIES, out, status );
Packit 89ede9
	append_people ( in, "EDITOR",      "ED", LEVEL_MAIN,   out, status );
Packit 89ede9
	append_easyall( in, "EDITOR:CORP", "ED", LEVEL_MAIN,   out, status );
Packit 89ede9
	append_easyall( in, "EDITOR:ASIS", "ED", LEVEL_MAIN,   out, status );
Packit 89ede9
	if ( type_is_element[ type ] ) {
Packit 89ede9
		append_people ( in, "EDITOR",      "ED", LEVEL_HOST, out, status );
Packit 89ede9
		append_easyall( in, "EDITOR:CORP", "ED", LEVEL_HOST, out, status );
Packit 89ede9
		append_easyall( in, "EDITOR:ASIS", "ED", LEVEL_HOST, out, status );
Packit 89ede9
	} else {
Packit 89ede9
		append_people ( in, "EDITOR",      "A3", LEVEL_HOST, out, status );
Packit 89ede9
		append_easyall( in, "EDITOR:CORP", "A3", LEVEL_HOST, out, status );
Packit 89ede9
		append_easyall( in, "EDITOR:ASIS", "A3", LEVEL_HOST, out, status );
Packit 89ede9
	}
Packit 89ede9
	append_people ( in, "EDITOR",      "A3", LEVEL_SERIES, out, status );
Packit 89ede9
	append_easyall( in, "EDITOR:CORP", "A3", LEVEL_SERIES, out, status );
Packit 89ede9
	append_easyall( in, "EDITOR:ASIS", "A3", LEVEL_SERIES, out, status );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
output( FILE *fp, fields *out )
Packit 89ede9
{
Packit 89ede9
	char *tag, *value;
Packit 89ede9
	int i;
Packit 89ede9
Packit 89ede9
	for ( i=0; i<out->n; ++i ) {
Packit 89ede9
		tag   = fields_tag( out, i, FIELDS_CHRP );
Packit 89ede9
		value = fields_value( out, i, FIELDS_CHRP );
Packit 89ede9
		fprintf( fp, "%s  - %s\n", tag, value );
Packit 89ede9
	}
Packit 89ede9
Packit 89ede9
	fprintf( fp, "ER  - \n" );
Packit 89ede9
	fflush( fp );
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static int
Packit 89ede9
append_data( fields *in, param *p, fields *out )
Packit 89ede9
{
Packit 89ede9
	int type, status = BIBL_OK;
Packit 89ede9
Packit 89ede9
	type = get_type( in, p );
Packit 89ede9
Packit 89ede9
	append_type      ( type, p, out, &status );
Packit 89ede9
	append_allpeople ( in, type, out, &status );
Packit 89ede9
	append_date      ( in, out, &status );
Packit 89ede9
	append_alltitles ( in, type, out, &status );
Packit 89ede9
	append_pages     ( in, out, &status );
Packit 89ede9
	append_easy      ( in, "VOLUME",             "VL", LEVEL_ANY, out, &status );
Packit 89ede9
	append_easy      ( in, "ISSUE",              "IS", LEVEL_ANY, out, &status );
Packit 89ede9
	append_easy      ( in, "NUMBER",             "IS", LEVEL_ANY, out, &status );
Packit 89ede9
	append_easy      ( in, "EDITION",            "ET", LEVEL_ANY, out, &status );
Packit 89ede9
	append_easy      ( in, "NUMVOLUMES",         "NV", LEVEL_ANY, out, &status );
Packit 89ede9
	append_easy      ( in, "AUTHORADDRESS",      "AD", LEVEL_ANY, out, &status );
Packit 89ede9
	append_easy      ( in, "PUBLISHER",          "PB", LEVEL_ANY, out, &status );
Packit 89ede9
	append_easy      ( in, "DEGREEGRANTOR",      "PB", LEVEL_ANY, out, &status );
Packit 89ede9
	append_easy      ( in, "DEGREEGRANTOR:ASIS", "PB", LEVEL_ANY, out, &status );
Packit 89ede9
	append_easy      ( in, "DEGREEGRANTOR:CORP", "PB", LEVEL_ANY, out, &status );
Packit 89ede9
	append_easy      ( in, "ADDRESS",            "CY", LEVEL_ANY, out, &status );
Packit 89ede9
	append_keywords  ( in, out, &status );
Packit 89ede9
	append_easy      ( in, "ABSTRACT",           "AB", LEVEL_ANY, out, &status );
Packit 89ede9
	append_easy      ( in, "CALLNUMBER",         "CN", LEVEL_ANY, out, &status );
Packit 89ede9
	append_easy      ( in, "ISSN",               "SN", LEVEL_ANY, out, &status );
Packit 89ede9
	append_easy      ( in, "ISBN",               "SN", LEVEL_ANY, out, &status );
Packit 89ede9
	append_file      ( in, "FILEATTACH",         "L1", LEVEL_ANY, out, &status );
Packit 89ede9
	append_file      ( in, "FIGATTACH",          "L4", LEVEL_ANY, out, &status );
Packit 89ede9
	append_easy      ( in, "CAPTION",            "CA", LEVEL_ANY, out, &status );
Packit 89ede9
	append_urls      ( in, out, &status );
Packit 89ede9
	append_easyall   ( in, "DOI",                "DO", LEVEL_ANY, out, &status );
Packit 89ede9
	append_easy      ( in, "LANGUAGE",           "LA", LEVEL_ANY, out, &status );
Packit 89ede9
	append_easy      ( in, "NOTES",              "N1", LEVEL_ANY, out, &status );
Packit 89ede9
	append_easy      ( in, "REFNUM",             "ID", LEVEL_ANY, out, &status );
Packit 89ede9
	append_thesishint( type, out, &status );
Packit 89ede9
Packit 89ede9
	return status;
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static int
Packit 89ede9
risout_write( fields *in, FILE *fp, param *p, unsigned long refnum )
Packit 89ede9
{
Packit 89ede9
	int status;
Packit 89ede9
	fields out;
Packit 89ede9
Packit 89ede9
	fields_init( &out );
Packit 89ede9
Packit 89ede9
	status = append_data( in, p, &out );
Packit 89ede9
	if ( status==BIBL_OK ) output( fp, &out );
Packit 89ede9
Packit 89ede9
	fields_free( &out );
Packit 89ede9
Packit 89ede9
	return status;
Packit 89ede9
}
Packit 89ede9
Packit 89ede9
static void
Packit 89ede9
risout_writeheader( FILE *outptr, param *p )
Packit 89ede9
{
Packit 89ede9
	if ( p->utf8bom ) utf8_writebom( outptr );
Packit 89ede9
}