/* * risout.c * * Copyright (c) Chris Putnam 2003-2018 * * Source code released under the GPL version 2 * */ #include #include #include #include #include "utf8.h" #include "str.h" #include "strsearch.h" #include "fields.h" #include "name.h" #include "title.h" #include "url.h" #include "bibformats.h" static int risout_write( fields *info, FILE *fp, param *p, unsigned long refnum ); static void risout_writeheader( FILE *outptr, param *p ); void risout_initparams( param *p, const char *progname ) { p->writeformat = BIBL_RISOUT; p->format_opts = 0; p->charsetout = BIBL_CHARSET_DEFAULT; p->charsetout_src = BIBL_SRC_DEFAULT; p->latexout = 0; p->utf8out = BIBL_CHARSET_UTF8_DEFAULT; p->utf8bom = BIBL_CHARSET_BOM_DEFAULT; p->xmlout = BIBL_XMLOUT_FALSE; 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 = risout_writeheader; p->footerf = NULL; p->writef = risout_write; } enum { TYPE_UNKNOWN = 0, TYPE_STD, /* standard/generic */ TYPE_ABSTRACT, /* abstract */ TYPE_ARTICLE, /* article */ TYPE_BOOK, /* book */ TYPE_CASE, /* case */ TYPE_INBOOK, /* chapter */ TYPE_CONF, /* conference */ TYPE_ELEC, /* electronic */ TYPE_HEAR, /* hearing */ TYPE_MAGARTICLE, /* magazine article */ TYPE_NEWSPAPER, /* newspaper */ TYPE_MPCT, /* mpct */ TYPE_PAMPHLET, /* pamphlet */ TYPE_PATENT, /* patent */ TYPE_PCOMM, /* personal communication */ TYPE_PROGRAM, /* program */ TYPE_REPORT, /* report */ TYPE_STATUTE, /* statute */ TYPE_THESIS, /* thesis */ TYPE_LICENTIATETHESIS, /* thesis */ TYPE_MASTERSTHESIS, /* thesis */ TYPE_PHDTHESIS, /* thesis */ TYPE_DIPLOMATHESIS, /* thesis */ TYPE_DOCTORALTHESIS, /* thesis */ TYPE_HABILITATIONTHESIS, /* thesis */ TYPE_MAP, /* map, cartographic data */ TYPE_UNPUBLISHED, /* unpublished */ NUM_TYPES }; static int type_is_element[ NUM_TYPES ] = { [ 0 ... NUM_TYPES-1 ] = 0, [ TYPE_ARTICLE ] = 1, [ TYPE_INBOOK ] = 1, [ TYPE_MAGARTICLE ] = 1, [ TYPE_NEWSPAPER ] = 1, [ TYPE_ABSTRACT ] = 1, [ TYPE_CONF ] = 1, }; static int type_uses_journal[ NUM_TYPES ] = { [ 0 ... NUM_TYPES-1 ] = 0, [ TYPE_ARTICLE ] = 1, [ TYPE_MAGARTICLE ] = 1, }; static void write_type( FILE *fp, int type ) { const char *typenames[ NUM_TYPES ] = { [ TYPE_UNKNOWN ] = "TYPE_UNKNOWN", [ TYPE_STD ] = "TYPE_STD", [ TYPE_ABSTRACT ] = "TYPE_ABSTRACT", [ TYPE_ARTICLE ] = "TYPE_ARTICLE", [ TYPE_BOOK ] = "TYPE_BOOK", [ TYPE_CASE ] = "TYPE_CASE", [ TYPE_INBOOK ] = "TYPE_INBOOK", [ TYPE_CONF ] = "TYPE_CONF", [ TYPE_ELEC ] = "TYPE_ELEC", [ TYPE_HEAR ] = "TYPE_HEAR", [ TYPE_MAGARTICLE ] = "TYPE_MAGARTICLE", [ TYPE_NEWSPAPER ] = "TYPE_NEWSPAPER", [ TYPE_MPCT ] = "TYPE_MPCT", [ TYPE_PAMPHLET ] = "TYPE_PAMPHLET", [ TYPE_PATENT ] = "TYPE_PATENT", [ TYPE_PCOMM ] = "TYPE_PCOMM", [ TYPE_PROGRAM ] = "TYPE_PROGRAM", [ TYPE_REPORT ] = "TYPE_REPORT", [ TYPE_STATUTE ] = "TYPE_STATUTE", [ TYPE_THESIS ] = "TYPE_THESIS", [ TYPE_LICENTIATETHESIS ] = "TYPE_LICENTIATETHESIS", [ TYPE_MASTERSTHESIS ] = "TYPE_MASTERSTHESIS", [ TYPE_PHDTHESIS ] = "TYPE_PHDTHESIS", [ TYPE_DIPLOMATHESIS ] = "TYPE_DIPLOMATHESIS", [ TYPE_DOCTORALTHESIS ] = "TYPE_DOCTORALTHESIS", [ TYPE_HABILITATIONTHESIS ] = "TYPE_HABILITATIONTHESIS", [ TYPE_MAP ] = "TYPE_MAP", [ TYPE_UNPUBLISHED ] = "TYPE_UNPUBLISHED", }; if ( type < 0 || type >= NUM_TYPES ) fprintf( fp, "Error - type not in enum" ); else fprintf( fp, "%s", typenames[ type ] ); } static void verbose_type_identified( char *element_type, param *p, int type ) { if ( p->progname ) fprintf( stderr, "%s: ", p->progname ); fprintf( stderr, "Type from %s element: ", element_type ); write_type( stderr, type ); fprintf( stderr, "\n" ); } static void verbose_type_assignment( char *tag, char *value, param *p, int type ) { if ( p->progname ) fprintf( stderr, "%s: ", p->progname ); fprintf( stderr, "Type from tag '%s' data '%s': ", tag, value ); write_type( stderr, type ); fprintf( stderr, "\n" ); } typedef struct match_type { char *name; int type; } match_type; /* Try to determine type of reference from * */ static int get_type_genre( fields *f, param *p ) { match_type match_genres[] = { { "academic journal", TYPE_ARTICLE }, { "article", TYPE_ARTICLE }, { "journal article", TYPE_ARTICLE }, { "magazine", TYPE_MAGARTICLE }, { "conference publication", TYPE_CONF }, { "newspaper", TYPE_NEWSPAPER }, { "legislation", TYPE_STATUTE }, { "communication", TYPE_PCOMM }, { "hearing", TYPE_HEAR }, { "electronic", TYPE_ELEC }, { "legal case and case notes", TYPE_CASE }, { "book chapter", TYPE_INBOOK }, { "Ph.D. thesis", TYPE_PHDTHESIS }, { "Licentiate thesis", TYPE_LICENTIATETHESIS }, { "Masters thesis", TYPE_MASTERSTHESIS }, { "Diploma thesis", TYPE_DIPLOMATHESIS }, { "Doctoral thesis", TYPE_DOCTORALTHESIS }, { "Habilitation thesis", TYPE_HABILITATIONTHESIS }, { "report", TYPE_REPORT }, { "technical report", TYPE_REPORT }, { "abstract or summary", TYPE_ABSTRACT }, { "patent", TYPE_PATENT }, { "unpublished", TYPE_UNPUBLISHED }, { "manuscript", TYPE_UNPUBLISHED }, { "map", TYPE_MAP }, }; int nmatch_genres = sizeof( match_genres ) / sizeof( match_genres[0] ); char *tag, *value; int type, i, j; type = TYPE_UNKNOWN; for ( i=0; iverbose ) verbose_type_assignment( tag, value, p, type ); if ( type==TYPE_UNKNOWN ) { if ( !strcasecmp( value, "periodical" ) ) type = TYPE_ARTICLE; else if ( !strcasecmp( value, "thesis" ) ) type = TYPE_THESIS; else if ( !strcasecmp( value, "book" ) ) { if ( fields_level( f, i )==0 ) type=TYPE_BOOK; else type=TYPE_INBOOK; } else if ( !strcasecmp( value, "collection" ) ) { if ( fields_level( f, i )==0 ) type=TYPE_BOOK; else type=TYPE_INBOOK; } } } if ( p->verbose ) verbose_type_identified( "genre", p, type ); return type; } /* Try to determine type of reference from * */ static int get_type_resource( fields *f, param *p ) { match_type match_res[] = { { "software, multimedia", TYPE_PROGRAM }, { "cartographic", TYPE_MAP }, }; int nmatch_res = sizeof( match_res ) / sizeof( match_res[0] ); vplist_index i; int type, j; char *value; vplist a; type = TYPE_UNKNOWN; vplist_init( &a ); fields_findv_each( f, LEVEL_ANY, FIELDS_CHRP, &a, "RESOURCE" ); for ( i=0; iverbose ) verbose_type_assignment( "RESOURCE", value, p, type ); } if ( p->verbose ) verbose_type_identified( "resource", p, type ); vplist_free( &a ); return type; } /* Try to determine type of reference from and */ /* */ static int get_type_issuance( fields *f, param *p ) { int type = TYPE_UNKNOWN; int i, monographic = 0, monographic_level = 0; // int text = 0; for ( i=0; in; ++i ) { if ( !strcasecmp( (char *) fields_tag( f, i, FIELDS_CHRP_NOUSE ), "issuance" ) && !strcasecmp( (char *) fields_value( f, i, FIELDS_CHRP_NOUSE ), "MONOGRAPHIC" ) ){ monographic = 1; monographic_level = f->level[i]; } // if ( !strcasecmp( (char *) fields_tag( f, i, FIELDS_CHRP_NOUSE ), "typeOfResource" ) && // !strcasecmp( (char *) fields_value( f, i, FIELDS_CHRP_NOUSE ), "text" ) ) { // text = 1; // } } // if ( monographic && text ) { if ( monographic ) { if ( monographic_level==0 ) type=TYPE_BOOK; else if ( monographic_level>0 ) type=TYPE_INBOOK; } if ( p->verbose ) { if ( p->progname ) fprintf( stderr, "%s: ", p->progname ); fprintf( stderr, "Type from issuance/typeOfReference elements: " ); write_type( stderr, type ); fprintf( stderr, "\n" ); } return type; } static int get_type( fields *f, param *p ) { int type; type = get_type_genre( f, p ); if ( type==TYPE_UNKNOWN ) type = get_type_resource( f, p ); if ( type==TYPE_UNKNOWN ) type = get_type_issuance( f, p ); if ( type==TYPE_UNKNOWN ) { if ( fields_maxlevel( f ) > 0 ) type = TYPE_INBOOK; else type = TYPE_STD; } if ( p->verbose ) { if ( p->progname ) fprintf( stderr, "%s: ", p->progname ); fprintf( stderr, "Final type: " ); write_type( stderr, type ); fprintf( stderr, "\n" ); } return type; } static void append_type( int type, param *p, fields *out, int *status ) { char *typenames[ NUM_TYPES ] = { [ TYPE_STD ] = "STD", [ TYPE_ABSTRACT ] = "ABST", [ TYPE_ARTICLE ] = "JOUR", [ TYPE_BOOK ] = "BOOK", [ TYPE_CASE ] = "CASE", [ TYPE_INBOOK ] = "CHAP", [ TYPE_CONF ] = "CONF", [ TYPE_ELEC ] = "ELEC", [ TYPE_HEAR ] = "HEAR", [ TYPE_MAGARTICLE ] = "MGZN", [ TYPE_NEWSPAPER ] = "NEWS", [ TYPE_MPCT ] = "MPCT", [ TYPE_PAMPHLET ] = "PAMP", [ TYPE_PATENT ] = "PAT", [ TYPE_PCOMM ] = "PCOMM", [ TYPE_PROGRAM ] = "COMP", [ TYPE_REPORT ] = "RPRT", [ TYPE_STATUTE ] = "STAT", [ TYPE_THESIS ] = "THES", [ TYPE_MASTERSTHESIS ] = "THES", [ TYPE_PHDTHESIS ] = "THES", [ TYPE_DIPLOMATHESIS ] = "THES", [ TYPE_DOCTORALTHESIS ] = "THES", [ TYPE_HABILITATIONTHESIS ] = "THES", [ TYPE_MAP ] = "MAP", [ TYPE_UNPUBLISHED ] = "UNPB", }; int fstatus; if ( type < 0 || type >= NUM_TYPES ) { if ( p->progname ) fprintf( stderr, "%s: ", p->progname ); fprintf( stderr, "Internal error: Cannot recognize type %d, switching to TYPE_STD %d\n", type, TYPE_STD ); type = TYPE_STD; } fstatus = fields_add( out, "TY", typenames[ type ], LEVEL_MAIN ); if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR; } static void append_people( fields *f, char *tag, char *ristag, int level, fields *out, int *status ) { vplist_index i; str oneperson; vplist people; int fstatus; str_init( &oneperson ); vplist_init( &people ); fields_findv_each( f, level, FIELDS_CHRP, &people, tag ); for ( i=0; in; ++i ) { tag = fields_tag( out, i, FIELDS_CHRP ); value = fields_value( out, i, FIELDS_CHRP ); fprintf( fp, "%s - %s\n", tag, value ); } fprintf( fp, "ER - \n" ); fflush( fp ); } static int append_data( fields *in, param *p, fields *out ) { int type, status = BIBL_OK; type = get_type( in, p ); append_type ( type, p, out, &status ); append_allpeople ( in, type, out, &status ); append_date ( in, out, &status ); append_alltitles ( in, type, out, &status ); append_pages ( in, out, &status ); append_easy ( in, "VOLUME", "VL", LEVEL_ANY, out, &status ); append_easy ( in, "ISSUE", "IS", LEVEL_ANY, out, &status ); append_easy ( in, "NUMBER", "IS", LEVEL_ANY, out, &status ); append_easy ( in, "EDITION", "ET", LEVEL_ANY, out, &status ); append_easy ( in, "NUMVOLUMES", "NV", LEVEL_ANY, out, &status ); append_easy ( in, "AUTHORADDRESS", "AD", LEVEL_ANY, out, &status ); append_easy ( in, "PUBLISHER", "PB", LEVEL_ANY, out, &status ); append_easy ( in, "DEGREEGRANTOR", "PB", LEVEL_ANY, out, &status ); append_easy ( in, "DEGREEGRANTOR:ASIS", "PB", LEVEL_ANY, out, &status ); append_easy ( in, "DEGREEGRANTOR:CORP", "PB", LEVEL_ANY, out, &status ); append_easy ( in, "ADDRESS", "CY", LEVEL_ANY, out, &status ); append_keywords ( in, out, &status ); append_easy ( in, "ABSTRACT", "AB", LEVEL_ANY, out, &status ); append_easy ( in, "CALLNUMBER", "CN", LEVEL_ANY, out, &status ); append_easy ( in, "ISSN", "SN", LEVEL_ANY, out, &status ); append_easy ( in, "ISBN", "SN", LEVEL_ANY, out, &status ); append_file ( in, "FILEATTACH", "L1", LEVEL_ANY, out, &status ); append_file ( in, "FIGATTACH", "L4", LEVEL_ANY, out, &status ); append_easy ( in, "CAPTION", "CA", LEVEL_ANY, out, &status ); append_urls ( in, out, &status ); append_easyall ( in, "DOI", "DO", LEVEL_ANY, out, &status ); append_easy ( in, "LANGUAGE", "LA", LEVEL_ANY, out, &status ); append_easy ( in, "NOTES", "N1", LEVEL_ANY, out, &status ); append_easy ( in, "REFNUM", "ID", LEVEL_ANY, out, &status ); append_thesishint( type, out, &status ); return status; } static int risout_write( fields *in, FILE *fp, param *p, unsigned long refnum ) { int status; fields out; fields_init( &out ); status = append_data( in, p, &out ); if ( status==BIBL_OK ) output( fp, &out ); fields_free( &out ); return status; } static void risout_writeheader( FILE *outptr, param *p ) { if ( p->utf8bom ) utf8_writebom( outptr ); }