~ubuntu-branches/ubuntu/saucy/haskell-hs-bibutils/saucy

« back to all changes in this revision

Viewing changes to bibutils/risout.c

  • Committer: Package Import Robot
  • Author(s): Joachim Breitner
  • Date: 2011-09-26 17:57:15 UTC
  • Revision ID: package-import@ubuntu.com-20110926175715-muzp5giy0rzonss2
Tags: upstream-4.12
ImportĀ upstreamĀ versionĀ 4.12

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * risout.c
 
3
 *
 
4
 * Copyright (c) Chris Putnam 2003-2010
 
5
 *
 
6
 * Program and source code released under the GPL
 
7
 *
 
8
 */
 
9
#include <stdio.h>
 
10
#include <stdlib.h>
 
11
#include <string.h>
 
12
#include <ctype.h>
 
13
#include "utf8.h"
 
14
#include "newstr.h"
 
15
#include "strsearch.h"
 
16
#include "fields.h"
 
17
#include "doi.h"
 
18
#include "risout.h"
 
19
 
 
20
void
 
21
risout_initparams( param *p, const char *progname )
 
22
{
 
23
        p->writeformat      = BIBL_RISOUT;
 
24
        p->format_opts      = 0;
 
25
        p->charsetout       = BIBL_CHARSET_DEFAULT;
 
26
        p->charsetout_src   = BIBL_SRC_DEFAULT;
 
27
        p->latexout         = 0;
 
28
        p->utf8out          = 0;
 
29
        p->utf8bom          = 0;
 
30
        p->xmlout           = 0;
 
31
        p->nosplittitle     = 0;
 
32
        p->verbose          = 0;
 
33
        p->addcount         = 0;
 
34
        p->singlerefperfile = 0;
 
35
 
 
36
        p->headerf = risout_writeheader;
 
37
        p->footerf = NULL;
 
38
        p->writef  = risout_write;
 
39
}
 
40
 
 
41
enum { 
 
42
        TYPE_UNKNOWN,
 
43
        TYPE_STD,                /* standard/generic */
 
44
        TYPE_ABSTRACT,           /* abstract */
 
45
        TYPE_ARTICLE,            /* article */
 
46
        TYPE_BOOK,               /* book */
 
47
        TYPE_CASE,               /* case */
 
48
        TYPE_INBOOK,             /* chapter */
 
49
        TYPE_CONF,               /* conference */
 
50
        TYPE_ELEC,               /* electronic */
 
51
        TYPE_HEAR,               /* hearing */
 
52
        TYPE_MAGARTICLE,         /* magazine article */
 
53
        TYPE_NEWS,               /* newspaper */
 
54
        TYPE_MPCT,               /* mpct */
 
55
        TYPE_PAMP,               /* pamphlet */
 
56
        TYPE_PATENT,             /* patent */
 
57
        TYPE_PCOMM,              /* personal communication */
 
58
        TYPE_PROGRAM,            /* program */
 
59
        TYPE_REPORT,             /* report */
 
60
        TYPE_STATUTE,            /* statute */
 
61
        TYPE_THESIS,             /* thesis */
 
62
        TYPE_MASTERSTHESIS,      /* thesis */
 
63
        TYPE_PHDTHESIS,          /* thesis */
 
64
        TYPE_DIPLOMATHESIS,      /* thesis */
 
65
        TYPE_DOCTORALTHESIS,     /* thesis */
 
66
        TYPE_HABILITATIONTHESIS, /* thesis */
 
67
        TYPE_UNPUBLISHED,        /* unpublished */
 
68
};
 
69
 
 
70
typedef struct match_type {
 
71
        char *name;
 
72
        int type;
 
73
} match_type;
 
74
 
 
75
/* Try to determine type of reference from <genre></genre> 
 
76
 * and <TypeOfResource></TypeOfResource>
 
77
 */
 
78
static int
 
79
get_type_genre( fields *info )
 
80
{
 
81
        match_type match_genres[] = {
 
82
                { "academic journal",          TYPE_ARTICLE },
 
83
                { "magazine",                  TYPE_MAGARTICLE },
 
84
                { "conference publication",    TYPE_CONF },
 
85
                { "newspaper",                 TYPE_NEWS },
 
86
                { "legislation",               TYPE_STATUTE },
 
87
                { "communication",             TYPE_PCOMM },
 
88
                { "hearing",                   TYPE_HEAR },
 
89
                { "electronic",                TYPE_ELEC },
 
90
                { "legal case and case notes", TYPE_CASE },
 
91
                { "Ph.D. thesis",              TYPE_PHDTHESIS },
 
92
                { "Masters thesis",            TYPE_MASTERSTHESIS },
 
93
                { "Diploma thesis",            TYPE_DIPLOMATHESIS },
 
94
                { "Doctoral thesis",           TYPE_DOCTORALTHESIS },
 
95
                { "Habilitation thesis",       TYPE_HABILITATIONTHESIS },
 
96
                { "report",                    TYPE_REPORT },
 
97
                { "abstract or summary",       TYPE_ABSTRACT },
 
98
                { "patent",                    TYPE_PATENT },
 
99
                { "unpublished",               TYPE_UNPUBLISHED },
 
100
        };
 
101
        int nmatch_genres = sizeof( match_genres ) / sizeof( match_genres[0] );
 
102
        match_type match_res[] = {
 
103
                { "software, multimedia",      TYPE_PROGRAM },
 
104
        };
 
105
        int nmatch_res = sizeof( match_res ) / sizeof( match_res[0] );
 
106
        char *tag, *data;
 
107
        int type = TYPE_UNKNOWN, i, j;
 
108
        for ( i=0; i<info->nfields; ++i ) {
 
109
                tag = info->tag[i].data;
 
110
                if ( strcasecmp( tag, "GENRE" ) &&
 
111
                     strcasecmp( tag, "NGENRE") ) continue;
 
112
                data = info->data[i].data;
 
113
                for ( j=0; j<nmatch_genres; ++j ) {
 
114
                        if ( !strcasecmp( data, match_genres[j].name ) )
 
115
                                type = match_genres[j].type;
 
116
                }
 
117
                if ( type==TYPE_UNKNOWN ) {
 
118
                        if ( !strcasecmp( data, "periodical" ) )
 
119
                                type = TYPE_ARTICLE;
 
120
                        else if ( !strcasecmp( data, "thesis" ) )
 
121
                                type = TYPE_THESIS;
 
122
                        else if ( !strcasecmp( data, "book" ) ) {
 
123
                                if ( info->level[i]==0 ) type=TYPE_BOOK;
 
124
                                else type=TYPE_INBOOK;
 
125
                        }
 
126
                        else if ( !strcasecmp( data, "collection" ) ) {
 
127
                                if ( info->level[i]==0 ) type=TYPE_BOOK;
 
128
                                else type=TYPE_INBOOK;
 
129
                        }
 
130
                }
 
131
        }
 
132
        if ( type==TYPE_UNKNOWN ) {
 
133
                for ( i=0; i<info->nfields; ++i ) {
 
134
                        tag = info->tag[i].data;
 
135
                        if ( strcasecmp( tag, "RESOURCE" ) ) continue;
 
136
                        data = info->data[i].data;
 
137
 
 
138
                        for ( j=0; j<nmatch_res; ++j ) {
 
139
                                if ( !strcasecmp( data, match_res[j].name ) )
 
140
                                        type = match_res[j].type;
 
141
                        }
 
142
                }
 
143
        }
 
144
        return type;
 
145
}
 
146
 
 
147
/* Try to determine type of reference from <issuance></issuance> and */
 
148
/* <typeOfReference></typeOfReference> */
 
149
static int
 
150
get_type_issuance( fields *info )
 
151
{
 
152
        int type = TYPE_UNKNOWN;
 
153
        int i, monographic = 0, text = 0, monographic_level = 0;
 
154
        for ( i=0; i<info->nfields; ++i ) {
 
155
                if ( !strcasecmp( info->tag[i].data, "issuance" ) &&
 
156
                     !strcasecmp( info->data[i].data, "MONOGRAPHIC" ) ){
 
157
                        monographic = 1;
 
158
                        monographic_level = info->level[i];
 
159
                }
 
160
                if ( !strcasecmp( info->tag[i].data, "typeOfResource" ) &&
 
161
                     !strcasecmp( info->data[i].data,"text") ) {
 
162
                        text = 1;
 
163
                }
 
164
        }
 
165
        if ( monographic && text ) {
 
166
                if ( monographic_level==0 ) type=TYPE_BOOK;
 
167
                else if ( monographic_level>0 ) type=TYPE_INBOOK;
 
168
        }
 
169
        return type;
 
170
}
 
171
 
 
172
static int
 
173
get_type( fields *info )
 
174
{
 
175
        int type;
 
176
        type = get_type_genre( info );
 
177
        if ( type==TYPE_UNKNOWN ) type = get_type_issuance( info );
 
178
        if ( type==TYPE_UNKNOWN ) type = TYPE_STD;
 
179
        return type;
 
180
}
 
181
 
 
182
static void
 
183
output_type( FILE *fp, int type, param *p )
 
184
{
 
185
        match_type tyout[] = {
 
186
                { "STD",  TYPE_STD },
 
187
                { "ABST", TYPE_ABSTRACT },
 
188
                { "JOUR", TYPE_ARTICLE },
 
189
                { "BOOK", TYPE_BOOK },
 
190
                { "CASE", TYPE_CASE },
 
191
                { "CHAP", TYPE_INBOOK },
 
192
                { "CONF", TYPE_CONF },
 
193
                { "ELEC", TYPE_ELEC },
 
194
                { "HEAR", TYPE_HEAR },
 
195
                { "MGZN", TYPE_MAGARTICLE },
 
196
                { "NEWS", TYPE_NEWS },
 
197
                { "MPCT", TYPE_MPCT },
 
198
                { "PAMP", TYPE_PAMP },
 
199
                { "PAT",  TYPE_PATENT },
 
200
                { "PCOMM",TYPE_PCOMM },
 
201
                { "COMP", TYPE_PROGRAM },
 
202
                { "RPRT", TYPE_REPORT },
 
203
                { "STAT", TYPE_STATUTE },
 
204
                { "THES", TYPE_THESIS },
 
205
                { "THES", TYPE_MASTERSTHESIS },
 
206
                { "THES", TYPE_PHDTHESIS },
 
207
                { "THES", TYPE_DIPLOMATHESIS },
 
208
                { "THES", TYPE_DOCTORALTHESIS },
 
209
                { "THES", TYPE_HABILITATIONTHESIS },
 
210
                { "UNPB", TYPE_UNPUBLISHED }
 
211
        };
 
212
        int ntyout = sizeof( tyout ) / sizeof( tyout[0] );
 
213
        int i, found;
 
214
 
 
215
        fprintf( fp, "TY  - " );
 
216
        found = 0;
 
217
        for ( i=0; i<ntyout && !found ; ++i ) {
 
218
                if ( tyout[i].type == type ) {
 
219
                        fprintf( fp, "%s", tyout[i].name );
 
220
                        found = 1;
 
221
                }
 
222
        }
 
223
        if ( !found ) {
 
224
                if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
 
225
                fprintf( stderr, "Internal Error: Cannot identify type %d\n",
 
226
                        type );
 
227
        }
 
228
        fprintf( fp, "\n" );
 
229
}
 
230
 
 
231
static void
 
232
output_person ( FILE *fp, char *p )
 
233
{
 
234
        int nseps = 0, nch;
 
235
        while ( *p ) {
 
236
                nch = 0;
 
237
                if ( nseps==1 ) fprintf( fp, "," );
 
238
                if ( nseps ) fprintf( fp, " " );
 
239
                while ( *p && *p!='|' ) {
 
240
                        fprintf( fp, "%c", *p++ );
 
241
                        nch++;
 
242
                }
 
243
                if ( *p=='|' ) p++;
 
244
                if ( nseps!=0 && nch==1 ) fprintf( fp, "." ); 
 
245
                nseps++;
 
246
        }
 
247
}
 
248
 
 
249
static void
 
250
output_people( FILE *fp, fields *info, long refnum, char *tag, 
 
251
                char *ristag, int level )
 
252
{
 
253
        int i;
 
254
        for ( i=0; i<info->nfields; ++i ) {
 
255
                if ( level!=-1 && info->level[i]!=level ) continue;
 
256
                if ( !strcasecmp( info->tag[i].data, tag ) ) {
 
257
                        fprintf( fp, "%s  - ", ristag );
 
258
                        output_person ( fp, info->data[i].data );
 
259
                        fprintf( fp, "\n" );
 
260
                }
 
261
        }
 
262
}
 
263
 
 
264
static void
 
265
output_date( FILE *fp, fields *info, long refnum )
 
266
{
 
267
        int year = fields_find( info, "YEAR", -1 );
 
268
        int month = fields_find( info, "MONTH", -1 );
 
269
        int day = fields_find( info, "DAY", -1 );
 
270
        if ( year==-1 ) year = fields_find( info, "PARTYEAR", -1 );
 
271
        if ( month==-1 ) month = fields_find( info, "PARTMONTH", -1 );
 
272
        if ( day==-1 ) day = fields_find( info, "PARTDAY", -1 );
 
273
        if ( year==-1 && month==-1 && day==-1 ) return;
 
274
        fprintf( fp, "PY  - " );
 
275
        if ( year!=-1 ) fprintf( fp, "%s", info->data[year].data );
 
276
        fprintf( fp, "/" );
 
277
        if ( month!=-1 ) fprintf( fp, "%s", info->data[month].data );
 
278
        fprintf( fp, "/" );
 
279
        if ( day!=-1 ) fprintf( fp, "%s", info->data[day].data );
 
280
        fprintf( fp, "\n" );
 
281
}
 
282
 
 
283
static void
 
284
output_title( FILE *fp, fields *info, char *ristag, int level )
 
285
{
 
286
        int n1 = fields_find( info, "TITLE", level );
 
287
        int n2 = fields_find( info, "SUBTITLE", level );
 
288
        if ( n1!=-1 ) {
 
289
                fprintf( fp, "%s  - %s", ristag, info->data[n1].data );
 
290
                if ( n2!=-1 ) {
 
291
                        if ( info->data[n1].data[info->data[n1].len]!='?' )
 
292
                                fprintf( fp, ": " );
 
293
                        else fprintf( fp, " " );
 
294
                        fprintf( fp, "%s", info->data[n2].data );
 
295
                }
 
296
                fprintf( fp, "\n" );
 
297
        }
 
298
}
 
299
 
 
300
static void
 
301
output_abbrtitle( FILE *fp, fields *info, char *ristag, int level )
 
302
{
 
303
        int n1 = fields_find( info, "SHORTTITLE", level );
 
304
        int n2 = fields_find( info, "SHORTSUBTITLE", level );
 
305
        if ( n1!=-1 ) {
 
306
                fprintf( fp, "%s  - %s", ristag, info->data[n1].data );
 
307
                if ( n2!=-1 ){
 
308
                        if ( info->data[n1].data[info->data[n1].len]!='?' )
 
309
                                fprintf( fp, ": " );
 
310
                        else fprintf( fp, " " );
 
311
                        fprintf( fp, "%s", info->data[n2].data );
 
312
                }
 
313
                fprintf( fp, "\n" );
 
314
        }
 
315
}
 
316
 
 
317
static void
 
318
output_pages( FILE *fp, fields *info, long refnum )
 
319
{
 
320
        int sn = fields_find( info, "PAGESTART", -1 );
 
321
        int en = fields_find( info, "PAGEEND", -1 );
 
322
        int ar = fields_find( info, "ARTICLENUMBER", -1 );
 
323
        if ( sn!=-1 || en!=-1 ) {
 
324
                if ( sn!=-1 ) 
 
325
                        fprintf( fp, "SP  - %s\n", info->data[sn].data );
 
326
                if ( en!=-1 ) 
 
327
                        fprintf( fp, "EP  - %s\n", info->data[en].data );
 
328
        } else if ( ar!=-1 ) {
 
329
                fprintf( fp, "SP  - %s\n", info->data[ar].data );
 
330
        }
 
331
}
 
332
 
 
333
static void
 
334
output_keywords( FILE *fp, fields *info )
 
335
{
 
336
        int i;
 
337
        for ( i=0; i<info->nfields; ++i ) {
 
338
                if ( !strcmp( info->tag[i].data, "KEYWORD" ) )
 
339
                        fprintf( fp, "KW  - %s\n", info->data[i].data );
 
340
        }
 
341
}
 
342
 
 
343
static void
 
344
output_doi( FILE *fp, fields *info )
 
345
{
 
346
        newstr doi_url;
 
347
        int i;
 
348
        newstr_init( &doi_url );
 
349
        for ( i=0; i<info->nfields; ++i ) {
 
350
                if ( strcmp( info->tag[i].data, "DOI" ) ) continue;
 
351
                doi_to_url( info, i, "URL", &doi_url );
 
352
                if ( doi_url.len )
 
353
                        fprintf( fp, "UR  - %s\n", doi_url.data );
 
354
        }
 
355
        newstr_free( &doi_url );
 
356
}
 
357
 
 
358
static void
 
359
output_pmid( FILE *fp, fields *info )
 
360
{
 
361
        newstr pmid_url;
 
362
        int i;
 
363
        newstr_init( &pmid_url );
 
364
        for ( i=0; i<info->nfields; ++i ) {
 
365
                if ( strcmp( info->tag[i].data, "PMID" ) ) continue;
 
366
                pmid_to_url( info, i, "URL", &pmid_url );
 
367
                if ( pmid_url.len )
 
368
                        fprintf( fp, "UR  - %s\n", pmid_url.data );
 
369
        }
 
370
        newstr_free( &pmid_url );
 
371
}
 
372
 
 
373
static void
 
374
output_arxiv( FILE *fp, fields *info )
 
375
{
 
376
        newstr arxiv_url;
 
377
        int i;
 
378
        newstr_init( &arxiv_url );
 
379
        for ( i=0; i<info->nfields; ++i ) {
 
380
                if ( strcmp( info->tag[i].data, "ARXIV" ) ) continue;
 
381
                arxiv_to_url( info, i, "URL", &arxiv_url );
 
382
                if ( arxiv_url.len )
 
383
                        fprintf( fp, "UR  - %s\n", arxiv_url.data );
 
384
        }
 
385
        newstr_free( &arxiv_url );
 
386
}
 
387
 
 
388
static void
 
389
output_jstor( FILE *fp, fields *info )
 
390
{
 
391
        newstr jstor_url;
 
392
        int i;
 
393
        newstr_init( &jstor_url );
 
394
        for ( i=0; i<info->nfields; ++i ) {
 
395
                if ( strcmp( info->tag[i].data, "JSTOR" ) ) continue;
 
396
                jstor_to_url( info, i, "URL", &jstor_url );
 
397
                if ( jstor_url.len )
 
398
                        fprintf( fp, "UR  - %s\n", jstor_url.data );
 
399
        }
 
400
        newstr_free( &jstor_url );
 
401
}
 
402
 
 
403
static void
 
404
output_thesishint( FILE *fp, int type )
 
405
{
 
406
        if ( type==TYPE_MASTERSTHESIS )
 
407
                fprintf( fp, "%s  - %s\n", "U1", "Masters thesis" );
 
408
        else if ( type==TYPE_PHDTHESIS )
 
409
                fprintf( fp, "%s  - %s\n", "U1", "Ph.D. thesis" );
 
410
        else if ( type==TYPE_DIPLOMATHESIS )
 
411
                fprintf( fp, "%s  - %s\n", "U1", "Diploma thesis" );
 
412
        else if ( type==TYPE_DOCTORALTHESIS )
 
413
                fprintf( fp, "%s  - %s\n", "U1", "Doctoral thesis" );
 
414
        else if ( type==TYPE_HABILITATIONTHESIS )
 
415
                fprintf( fp, "%s  - %s\n", "U1", "Habilitation thesis" );
 
416
}
 
417
 
 
418
static void
 
419
output_easy( FILE *fp, fields *info, long refnum, char *tag, char *ristag, int level )
 
420
{
 
421
        int n = fields_find( info, tag, level );
 
422
        if ( n!=-1 ) {
 
423
                fprintf( fp, "%s  - %s\n", ristag, info->data[n].data );
 
424
        }
 
425
}
 
426
 
 
427
static void
 
428
output_easyall( FILE *fp, fields *info, long refnum, char *tag, char *ristag, int level )
 
429
{
 
430
        int i;
 
431
        for ( i=0; i<info->nfields; ++i ) {
 
432
                if ( level!=-1 && level!=info->level[i] ) continue;
 
433
                if ( !strcmp( info->tag[i].data, tag ) )
 
434
                        fprintf( fp, "%s  - %s\n", ristag, info->data[i].data );
 
435
        }
 
436
}
 
437
 
 
438
void
 
439
risout_write( fields *info, FILE *fp, param *p, unsigned long refnum )
 
440
{
 
441
        int type;
 
442
        type = get_type( info );
 
443
        output_type( fp, type, p );
 
444
        output_people( fp, info, refnum, "AUTHOR", "AU", 0 );
 
445
        output_easyall( fp, info, refnum, "AUTHOR:CORP", "AU", 0 );
 
446
        output_easyall( fp, info, refnum, "AUTHOR:ASIS", "AU", 0 );
 
447
        output_people( fp, info, refnum, "AUTHOR", "A2", 1 );
 
448
        output_easyall( fp, info, refnum, "AUTHOR:CORP", "A2", 1 );
 
449
        output_easyall( fp, info, refnum, "AUTHOR:ASIS", "A2", 1 );
 
450
        output_people( fp, info, refnum, "AUTHOR", "A3", 2 );
 
451
        output_easyall( fp, info, refnum, "AUTHOR:CORP", "A3", 2 );
 
452
        output_easyall( fp, info, refnum, "AUTHOR:ASIS", "A3", 2 );
 
453
        output_people( fp, info, refnum, "EDITOR", "ED", -1 );
 
454
        output_easyall( fp, info, refnum, "EDITOR:CORP", "ED", -1 );
 
455
        output_easyall( fp, info, refnum, "EDITOR:ASIS", "ED", -1 );
 
456
        output_date( fp, info, refnum );
 
457
        output_title( fp, info, "TI", 0 );
 
458
        output_abbrtitle( fp, info, "T2", -1 );
 
459
        if ( type==TYPE_ARTICLE || type==TYPE_MAGARTICLE ) {
 
460
                output_title( fp, info, "JO", 1 );
 
461
        }
 
462
        else output_title( fp, info, "BT", 1 );
 
463
        output_title( fp, info, "T3", 2 );
 
464
        output_pages( fp, info, refnum );
 
465
        output_easy( fp, info, refnum, "VOLUME", "VL", -1 );
 
466
        output_easy( fp, info, refnum, "ISSUE", "IS", -1 );
 
467
        output_easy( fp, info, refnum, "NUMBER", "IS", -1 );
 
468
        /* output article number as pages */
 
469
        output_easy( fp, info, refnum, "PUBLISHER", "PB", -1 );
 
470
        output_easy( fp, info, refnum, "DEGREEGRANTOR", "PB", -1 );
 
471
        output_easy( fp, info, refnum, "DEGREEGRANTOR:ASIS", "PB", -1 );
 
472
        output_easy( fp, info, refnum, "DEGREEGRANTOR:CORP", "PB", -1 );
 
473
        output_easy( fp, info, refnum, "ADDRESS", "CY", -1 );
 
474
        output_keywords( fp, info );
 
475
        output_easy( fp, info, refnum, "ABSTRACT", "N2", -1 );
 
476
        output_easy( fp, info, refnum, "ISSN", "SN", -1 );
 
477
        output_easy( fp, info, refnum, "ISBN", "SN", -1 );
 
478
        output_easyall( fp, info, refnum, "URL", "UR", -1 );
 
479
        output_easyall( fp, info, refnum, "FILEATTACH", "L1", -1 );
 
480
        output_doi( fp, info );
 
481
        output_pmid( fp, info );
 
482
        output_arxiv( fp, info );
 
483
        output_jstor( fp, info );
 
484
        output_easy( fp, info, refnum, "NOTES", "N1", -1 );
 
485
        output_easy( fp, info, refnum, "REFNUM", "ID", -1 );
 
486
        output_thesishint( fp, type );
 
487
        fprintf( fp, "ER  - \n" );
 
488
        fflush( fp );
 
489
}
 
490
 
 
491
void
 
492
risout_writeheader( FILE *outptr, param *p )
 
493
{
 
494
        if ( p->utf8bom ) utf8_writebom( outptr );
 
495
}
 
496