1 /*
2 * endout.c
3 *
4 * Copyright (c) Chris Putnam 2004-2020
5 *
6 * Program and source code released under the GPL version 2
7 *
8 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ctype.h>
13 #include "utf8.h"
14 #include "str.h"
15 #include "strsearch.h"
16 #include "fields.h"
17 #include "generic.h"
18 #include "name.h"
19 #include "title.h"
20 #include "type.h"
21 #include "url.h"
22 #include "bibformats.h"
23
24 /*****************************************************
25 PUBLIC: int endout_initparams()
26 *****************************************************/
27
28 static int endout_write( fields *in, FILE *fp, param *p, unsigned long refnum );
29 static int endout_assemble( fields *in, fields *out, param *pm, unsigned long refnum );
30
31 int
endout_initparams(param * pm,const char * progname)32 endout_initparams( param *pm, const char *progname )
33 {
34 pm->writeformat = BIBL_ENDNOTEOUT;
35 pm->format_opts = 0;
36 pm->charsetout = BIBL_CHARSET_DEFAULT;
37 pm->charsetout_src = BIBL_SRC_DEFAULT;
38 pm->latexout = 0;
39 pm->utf8out = BIBL_CHARSET_UTF8_DEFAULT;
40 pm->utf8bom = BIBL_CHARSET_BOM_DEFAULT;
41 pm->xmlout = BIBL_XMLOUT_FALSE;
42 pm->nosplittitle = 0;
43 pm->verbose = 0;
44 pm->addcount = 0;
45 pm->singlerefperfile = 0;
46
47 if ( pm->charsetout == BIBL_CHARSET_UNICODE ) {
48 pm->utf8out = pm->utf8bom = 1;
49 }
50
51 pm->headerf = generic_writeheader;
52 pm->footerf = NULL;
53 pm->assemblef = endout_assemble;
54 pm->writef = endout_write;
55
56 if ( !pm->progname ) {
57 if ( !progname ) pm->progname = NULL;
58 else {
59 pm->progname = strdup( progname );
60 if ( !pm->progname ) return BIBL_ERR_MEMERR;
61 }
62 }
63
64 return BIBL_OK;
65 }
66
67 /*****************************************************
68 PUBLIC: int endout_assemble()
69 *****************************************************/
70
71 enum {
72 TYPE_UNKNOWN = 0,
73 TYPE_GENERIC, /* Generic */
74 TYPE_ARTWORK, /* Artwork */
75 TYPE_AUDIOVISUAL, /* Audiovisual Material */
76 TYPE_BILL, /* Bill */
77 TYPE_BOOK, /* Book */
78 TYPE_INBOOK, /* Book Section */
79 TYPE_CASE, /* Case */
80 TYPE_CHARTTABLE, /* Chart or Table */
81 TYPE_CLASSICALWORK, /* Classical Work */
82 TYPE_PROGRAM, /* Computer Program */
83 TYPE_INPROCEEDINGS, /* Conference Paper */
84 TYPE_PROCEEDINGS, /* Conference Proceedings */
85 TYPE_EDITEDBOOK, /* Edited Book */
86 TYPE_EQUATION, /* Equation */
87 TYPE_ELECTRONICARTICLE, /* Electronic Article */
88 TYPE_ELECTRONICBOOK, /* Electronic Book */
89 TYPE_ELECTRONIC, /* Electronic Source */
90 TYPE_FIGURE, /* Figure */
91 TYPE_FILMBROADCAST, /* Film or Broadcast */
92 TYPE_GOVERNMENT, /* Government Document */
93 TYPE_HEARING, /* Hearing */
94 TYPE_ARTICLE, /* Journal Article */
95 TYPE_LEGALRULE, /* Legal Rule/Regulation */
96 TYPE_MAGARTICLE, /* Magazine Article */
97 TYPE_MANUSCRIPT, /* Manuscript */
98 TYPE_MAP, /* Map */
99 TYPE_NEWSARTICLE, /* Newspaper Article */
100 TYPE_ONLINEDATABASE, /* Online Database */
101 TYPE_ONLINEMULTIMEDIA, /* Online Multimedia */
102 TYPE_PATENT, /* Patent */
103 TYPE_COMMUNICATION, /* Personal Communication */
104 TYPE_REPORT, /* Report */
105 TYPE_STATUTE, /* Statute */
106 TYPE_THESIS, /* Thesis */
107 TYPE_MASTERSTHESIS, /* Thesis */
108 TYPE_PHDTHESIS, /* Thesis */
109 TYPE_DIPLOMATHESIS, /* Thesis */
110 TYPE_DOCTORALTHESIS, /* Thesis */
111 TYPE_HABILITATIONTHESIS, /* Thesis */
112 TYPE_LICENTIATETHESIS, /* Thesis */
113 TYPE_UNPUBLISHED, /* Unpublished Work */
114 };
115
116 static void
write_type(FILE * fp,int type)117 write_type( FILE *fp, int type )
118 {
119 switch( type ) {
120 case TYPE_UNKNOWN: fprintf( fp, "TYPE_UNKNOWN" ); break;
121 case TYPE_GENERIC: fprintf( fp, "TYPE_GENERIC" ); break;
122 case TYPE_ARTWORK: fprintf( fp, "TYPE_ARTWORK" ); break;
123 case TYPE_AUDIOVISUAL: fprintf( fp, "TYPE_AUDIOVISUAL" ); break;
124 case TYPE_BILL: fprintf( fp, "TYPE_BILL" ); break;
125 case TYPE_BOOK: fprintf( fp, "TYPE_BOOK" ); break;
126 case TYPE_INBOOK: fprintf( fp, "TYPE_INBOOK" ); break;
127 case TYPE_CASE: fprintf( fp, "TYPE_CASE" ); break;
128 case TYPE_CHARTTABLE: fprintf( fp, "TYPE_CHARITABLE" ); break;
129 case TYPE_CLASSICALWORK: fprintf( fp, "TYPE_CLASSICALWORK" ); break;
130 case TYPE_PROGRAM: fprintf( fp, "TYPE_PROGRAM" ); break;
131 case TYPE_INPROCEEDINGS: fprintf( fp, "TYPE_INPROCEEDINGS" ); break;
132 case TYPE_PROCEEDINGS: fprintf( fp, "TYPE_PROCEEDINGS" ); break;
133 case TYPE_EDITEDBOOK: fprintf( fp, "TYPE_EDITEDBOOK" ); break;
134 case TYPE_EQUATION: fprintf( fp, "TYPE_EQUATION" ); break;
135 case TYPE_ELECTRONICARTICLE: fprintf( fp, "TYPE_ELECTRONICARTICLE" ); break;
136 case TYPE_ELECTRONICBOOK: fprintf( fp, "TYPE_ELECTRONICBOOK" ); break;
137 case TYPE_ELECTRONIC: fprintf( fp, "TYPE_ELECTRONIC" ); break;
138 case TYPE_FIGURE: fprintf( fp, "TYPE_FIGURE" ); break;
139 case TYPE_FILMBROADCAST: fprintf( fp, "TYPE_FILMBROADCAST" ); break;
140 case TYPE_GOVERNMENT: fprintf( fp, "TYPE_GOVERNMENT" ); break;
141 case TYPE_HEARING: fprintf( fp, "TYPE_HEARING" ); break;
142 case TYPE_ARTICLE: fprintf( fp, "TYPE_ARTICLE" ); break;
143 case TYPE_LEGALRULE: fprintf( fp, "TYPE_LEGALRULE" ); break;
144 case TYPE_MAGARTICLE: fprintf( fp, "TYPE_MAGARTICLE" ); break;
145 case TYPE_MANUSCRIPT: fprintf( fp, "TYPE_MANUSCRIPT" ); break;
146 case TYPE_MAP: fprintf( fp, "TYPE_MAP" ); break;
147 case TYPE_NEWSARTICLE: fprintf( fp, "TYPE_NEWSARTICLE" ); break;
148 case TYPE_ONLINEDATABASE: fprintf( fp, "TYPE_ONLINEDATABASE" ); break;
149 case TYPE_ONLINEMULTIMEDIA: fprintf( fp, "TYPE_ONLINEMULTIMEDIA" ); break;
150 case TYPE_PATENT: fprintf( fp, "TYPE_PATENT" ); break;
151 case TYPE_COMMUNICATION: fprintf( fp, "TYPE_COMMUNICATION" ); break;
152 case TYPE_REPORT: fprintf( fp, "TYPE_REPORT" ); break;
153 case TYPE_STATUTE: fprintf( fp, "TYPE_STATUTE" ); break;
154 case TYPE_THESIS: fprintf( fp, "TYPE_THESIS" ); break;
155 case TYPE_MASTERSTHESIS: fprintf( fp, "TYPE_MASTERSTHESIS" ); break;
156 case TYPE_PHDTHESIS: fprintf( fp, "TYPE_PHDTHESIS" ); break;
157 case TYPE_DIPLOMATHESIS: fprintf( fp, "TYPE_DIPLOMATHESIS" ); break;
158 case TYPE_DOCTORALTHESIS: fprintf( fp, "TYPE_DOCTORALTHESIS" ); break;
159 case TYPE_HABILITATIONTHESIS:fprintf( fp, "TYPE_HABILITATIONTHESIS" ); break;
160 case TYPE_UNPUBLISHED: fprintf( fp, "TYPE_UNPUBLISHED" ); break;
161 default: fprintf( fp, "Error - type not in enum" );break;
162 }
163 }
164
165 static void
type_report_progress(param * p,const char * element_type,int type,unsigned long refnum)166 type_report_progress( param *p, const char *element_type, int type, unsigned long refnum )
167 {
168 // Patch: Disable output logging
169 }
170
171 static int
type_from_default(fields * in,param * p,unsigned long refnum)172 type_from_default( fields *in, param *p, unsigned long refnum )
173 {
174 int n, type;
175
176 /* default to chapter if host terms */
177 if ( fields_maxlevel( in ) > 0 ) type = TYPE_INBOOK;
178
179 /* default to generic if no host terms */
180 else type = TYPE_GENERIC;
181
182 // Patch: Disable output logging
183 n = fields_find( in, "REFNUM", LEVEL_ANY );
184 return type;
185 }
186
187 static int
get_type(fields * in,param * p,unsigned long refnum)188 get_type( fields *in, param *p, unsigned long refnum )
189 {
190 /* Comment out TYPE_GENERIC entries as that is default, but
191 * keep in source as record of mapping decision. */
192 match_type genre_matches[] = {
193 /* MARC Authority elements */
194 { "art original", TYPE_ARTWORK, LEVEL_ANY },
195 { "art reproduction", TYPE_ARTWORK, LEVEL_ANY },
196 { "article", TYPE_ARTICLE, LEVEL_ANY },
197 { "atlas", TYPE_MAP, LEVEL_ANY },
198 { "autobiography", TYPE_BOOK, LEVEL_ANY },
199 /* { "bibliography", TYPE_GENERIC, LEVEL_ANY },*/
200 { "biography", TYPE_BOOK, LEVEL_ANY },
201 { "book", TYPE_BOOK, LEVEL_MAIN },
202 { "book", TYPE_INBOOK, LEVEL_ANY },
203 /* { "calendar", TYPE_GENERIC, LEVEL_ANY },*/
204 /* { "catalog", TYPE_GENERIC, LEVEL_ANY },*/
205 { "chart", TYPE_CHARTTABLE, LEVEL_ANY },
206 /* { "comic or graphic novel", TYPE_GENERIC, LEVEL_ANY },*/
207 /* { "comic strip", TYPE_GENERIC, LEVEL_ANY },*/
208 { "conference publication", TYPE_PROCEEDINGS, LEVEL_ANY },
209 { "database", TYPE_ONLINEDATABASE, LEVEL_ANY },
210 /* { "dictionary", TYPE_GENERIC, LEVEL_ANY },*/
211 { "diorama", TYPE_ARTWORK, LEVEL_ANY },
212 /* { "directory", TYPE_GENERIC, LEVEL_ANY },*/
213 { "discography", TYPE_AUDIOVISUAL, LEVEL_ANY },
214 /* { "drama", TYPE_GENERIC, LEVEL_ANY },*/
215 { "encyclopedia", TYPE_BOOK, LEVEL_ANY },
216 /* { "essay", TYPE_GENERIC, LEVEL_ANY }, */
217 { "festschrift", TYPE_BOOK, LEVEL_MAIN },
218 { "festschrift", TYPE_INBOOK, LEVEL_ANY },
219 { "fiction", TYPE_BOOK, LEVEL_ANY },
220 { "filmography", TYPE_FILMBROADCAST, LEVEL_ANY },
221 { "filmstrip", TYPE_FILMBROADCAST, LEVEL_ANY },
222 /* { "finding aid", TYPE_GENERIC, LEVEL_ANY },*/
223 /* { "flash card", TYPE_GENERIC, LEVEL_ANY },*/
224 { "folktale", TYPE_CLASSICALWORK, LEVEL_ANY },
225 { "font", TYPE_ELECTRONIC, LEVEL_ANY },
226 /* { "game", TYPE_GENERIC, LEVEL_ANY },*/
227 { "government publication", TYPE_GOVERNMENT, LEVEL_ANY },
228 { "graphic", TYPE_FIGURE, LEVEL_ANY },
229 { "globe", TYPE_MAP, LEVEL_ANY },
230 /* { "handbook", TYPE_GENERIC, LEVEL_ANY },*/
231 { "history", TYPE_BOOK, LEVEL_ANY },
232 { "hymnal", TYPE_BOOK, LEVEL_MAIN },
233 { "hymnal", TYPE_INBOOK, LEVEL_ANY },
234 /* { "humor, satire", TYPE_GENERIC, LEVEL_ANY },*/
235 /* { "index", TYPE_GENERIC, LEVEL_ANY },*/
236 /* { "instruction", TYPE_GENERIC, LEVEL_ANY },*/
237 /* { "interview", TYPE_GENERIC, LEVEL_ANY },*/
238 { "issue", TYPE_ARTICLE, LEVEL_ANY },
239 { "journal", TYPE_ARTICLE, LEVEL_ANY },
240 /* { "kit", TYPE_GENERIC, LEVEL_ANY },*/
241 /* { "language instruction", TYPE_GENERIC, LEVEL_ANY },*/
242 /* { "law report or digest", TYPE_GENERIC, LEVEL_ANY },*/
243 /* { "legal article", TYPE_GENERIC, LEVEL_ANY },*/
244 { "legal case and case notes", TYPE_CASE, LEVEL_ANY },
245 { "legislation", TYPE_BILL, LEVEL_ANY },
246 { "letter", TYPE_COMMUNICATION, LEVEL_ANY },
247 { "loose-leaf", TYPE_GENERIC, LEVEL_ANY },
248 { "map", TYPE_MAP, LEVEL_ANY },
249 /* { "memoir", TYPE_GENERIC, LEVEL_ANY },*/
250 /* { "microscope slide", TYPE_GENERIC, LEVEL_ANY },*/
251 /* { "model", TYPE_GENERIC, LEVEL_ANY },*/
252 { "motion picture", TYPE_AUDIOVISUAL, LEVEL_ANY },
253 { "multivolume monograph", TYPE_BOOK, LEVEL_ANY },
254 { "newspaper", TYPE_NEWSARTICLE, LEVEL_ANY },
255 { "novel", TYPE_BOOK, LEVEL_ANY },
256 /* { "numeric data", TYPE_GENERIC, LEVEL_ANY },*/
257 /* { "offprint", TYPE_GENERIC, LEVEL_ANY },*/
258 { "online system or service", TYPE_ELECTRONIC, LEVEL_ANY },
259 { "patent", TYPE_PATENT, LEVEL_ANY },
260 { "picture", TYPE_ARTWORK, LEVEL_ANY },
261 /* { "poetry", TYPE_GENERIC, LEVEL_ANY },*/
262 { "programmed text", TYPE_PROGRAM, LEVEL_ANY },
263 /* { "realia", TYPE_GENERIC, LEVEL_ANY },*/
264 { "rehearsal", TYPE_AUDIOVISUAL, LEVEL_ANY },
265 /* { "remote sensing image", TYPE_GENERIC, LEVEL_ANY },*/
266 /* { "reporting", TYPE_GENERIC, LEVEL_ANY },*/
267 { "report", TYPE_REPORT, LEVEL_ANY },
268 /* { "review", TYPE_GENERIC, LEVEL_ANY },*/
269 /* { "script", TYPE_GENERIC, LEVEL_ANY },*/
270 /* { "series", TYPE_GENERIC, LEVEL_ANY },*/
271 /* { "short story", TYPE_GENERIC, LEVEL_ANY },*/
272 /* { "slide", TYPE_GENERIC, LEVEL_ANY },*/
273 { "sound", TYPE_AUDIOVISUAL, LEVEL_ANY },
274 /* { "speech", TYPE_GENERIC, LEVEL_ANY },*/
275 /* { "standard or specification", TYPE_GENERIC, LEVEL_ANY },*/
276 /* { "statistics", TYPE_GENERIC, LEVEL_ANY },*/
277 /* { "survey of literature", TYPE_GENERIC, LEVEL_ANY },*/
278 { "technical drawing", TYPE_ARTWORK, LEVEL_ANY },
279 { "technical report", TYPE_REPORT, LEVEL_ANY },
280 /* { "toy", TYPE_GENERIC, LEVEL_ANY },*/
281 /* { "transparency", TYPE_GENERIC, LEVEL_ANY },*/
282 /* { "treaty", TYPE_GENERIC, LEVEL_ANY },*/
283 { "videorecording", TYPE_AUDIOVISUAL, LEVEL_ANY },
284 { "web site", TYPE_ELECTRONIC, LEVEL_ANY },
285 /* Non-MARC Authority elements */
286 { "academic journal", TYPE_ARTICLE, LEVEL_ANY },
287 { "collection", TYPE_BOOK, LEVEL_MAIN },
288 { "collection", TYPE_INBOOK, LEVEL_ANY },
289 { "magazine", TYPE_MAGARTICLE, LEVEL_ANY },
290 { "hearing", TYPE_HEARING, LEVEL_ANY },
291 { "Ph.D. thesis", TYPE_PHDTHESIS, LEVEL_ANY },
292 { "Masters thesis", TYPE_MASTERSTHESIS, LEVEL_ANY },
293 { "Diploma thesis", TYPE_DIPLOMATHESIS, LEVEL_ANY },
294 { "Doctoral thesis", TYPE_DOCTORALTHESIS, LEVEL_ANY },
295 { "Habilitation thesis", TYPE_HABILITATIONTHESIS, LEVEL_ANY },
296 { "Licentiate thesis", TYPE_LICENTIATETHESIS, LEVEL_ANY },
297 { "communication", TYPE_COMMUNICATION, LEVEL_ANY },
298 { "manuscript", TYPE_MANUSCRIPT, LEVEL_ANY },
299 { "unpublished", TYPE_UNPUBLISHED, LEVEL_ANY },
300 /* Delayed MARC Authority elements */
301 { "thesis", TYPE_THESIS, LEVEL_ANY },
302 { "periodical", TYPE_MAGARTICLE, LEVEL_ANY },
303 };
304 int ngenre_matches = sizeof( genre_matches ) / sizeof( genre_matches[0] );
305
306 match_type resource_matches[] = {
307 { "moving image", TYPE_FILMBROADCAST, LEVEL_ANY },
308 { "software, multimedia", TYPE_PROGRAM, LEVEL_ANY },
309 };
310 int nresource_matches = sizeof( resource_matches ) / sizeof( resource_matches[0] );
311
312 match_type issuance_matches[] = {
313 { "monographic", TYPE_BOOK, LEVEL_MAIN },
314 { "monographic", TYPE_INBOOK, LEVEL_ANY },
315 };
316 int nissuance_matches = sizeof( issuance_matches ) / sizeof( issuance_matches[0] );
317
318 int type;
319
320 type = type_from_mods_hints( in, TYPE_FROM_GENRE, genre_matches, ngenre_matches, TYPE_UNKNOWN );
321 type_report_progress( p, "genre", type, refnum );
322 if ( type!=TYPE_UNKNOWN ) return type;
323
324 type = type_from_mods_hints( in, TYPE_FROM_RESOURCE, resource_matches, nresource_matches, TYPE_UNKNOWN );
325 type_report_progress( p, "resource", type, refnum );
326 if ( type!=TYPE_UNKNOWN ) return type;
327
328 type = type_from_mods_hints( in, TYPE_FROM_ISSUANCE, issuance_matches, nissuance_matches, TYPE_UNKNOWN );
329 type_report_progress( p, "issuance", type, refnum );
330 if ( type!=TYPE_UNKNOWN ) return type;
331
332 return type_from_default( in, p, refnum );
333 }
334
335 static void
append_type(int type,fields * out,param * p,int * status)336 append_type( int type, fields *out, param *p, int *status )
337 {
338 /* These are restricted to Endnote-defined types */
339 match_type genrenames[] = {
340 { "Generic", TYPE_GENERIC },
341 { "Artwork", TYPE_ARTWORK },
342 { "Audiovisual Material", TYPE_AUDIOVISUAL },
343 { "Bill", TYPE_BILL },
344 { "Book", TYPE_BOOK },
345 { "Book Section", TYPE_INBOOK },
346 { "Case", TYPE_CASE },
347 { "Chart or Table", TYPE_CHARTTABLE },
348 { "Classical Work", TYPE_CLASSICALWORK },
349 { "Computer Program", TYPE_PROGRAM },
350 { "Conference Paper", TYPE_INPROCEEDINGS },
351 { "Conference Proceedings", TYPE_PROCEEDINGS },
352 { "Edited Book", TYPE_EDITEDBOOK },
353 { "Equation", TYPE_EQUATION },
354 { "Electronic Article", TYPE_ELECTRONICARTICLE },
355 { "Electronic Book", TYPE_ELECTRONICBOOK },
356 { "Electronic Source", TYPE_ELECTRONIC },
357 { "Figure", TYPE_FIGURE },
358 { "Film or Broadcast", TYPE_FILMBROADCAST },
359 { "Government Document", TYPE_GOVERNMENT },
360 { "Hearing", TYPE_HEARING },
361 { "Journal Article", TYPE_ARTICLE },
362 { "Legal Rule/Regulation", TYPE_LEGALRULE },
363 { "Magazine Article", TYPE_MAGARTICLE },
364 { "Manuscript", TYPE_MANUSCRIPT },
365 { "Map", TYPE_MAP },
366 { "Newspaper Article", TYPE_NEWSARTICLE },
367 { "Online Database", TYPE_ONLINEDATABASE },
368 { "Online Multimedia", TYPE_ONLINEMULTIMEDIA },
369 { "Patent", TYPE_PATENT },
370 { "Personal Communication", TYPE_COMMUNICATION },
371 { "Report", TYPE_REPORT },
372 { "Statute", TYPE_STATUTE },
373 { "Thesis", TYPE_THESIS },
374 { "Thesis", TYPE_PHDTHESIS },
375 { "Thesis", TYPE_MASTERSTHESIS },
376 { "Thesis", TYPE_DIPLOMATHESIS },
377 { "Thesis", TYPE_DOCTORALTHESIS },
378 { "Thesis", TYPE_HABILITATIONTHESIS },
379 { "Unpublished Work", TYPE_UNPUBLISHED },
380 };
381 int ngenrenames = sizeof( genrenames ) / sizeof( genrenames[0] );
382 int i, fstatus, found = 0;
383 for ( i=0; i<ngenrenames && !found; ++i ) {
384 if ( genrenames[i].type == type ) {
385 fstatus = fields_add( out, "%0", genrenames[i].name, LEVEL_MAIN );
386 if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
387 found = 1;
388 }
389 }
390 if ( !found ) {
391 fstatus = fields_add( out, "%0", "Generic", LEVEL_MAIN );
392 if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
393 // Patch: Disable output logging
394 }
395 }
396
397 static int
append_title(fields * in,char * full,char * sub,char * endtag,int level,fields * out,int * status)398 append_title( fields *in, char *full, char *sub, char *endtag,
399 int level, fields *out, int *status )
400 {
401 str *mainttl = fields_findv( in, level, FIELDS_STRP, full );
402 str *subttl = fields_findv( in, level, FIELDS_STRP, sub );
403 str fullttl;
404 int fstatus;
405
406 str_init( &fullttl );
407 title_combine( &fullttl, mainttl, subttl );
408
409 if ( str_memerr( &fullttl ) ) {
410 *status = BIBL_ERR_MEMERR;
411 goto out;
412 }
413
414 if ( str_has_value( &fullttl ) ) {
415 fstatus = fields_add( out, endtag, str_cstr( &fullttl ), LEVEL_MAIN );
416 if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
417 }
418 out:
419 str_free( &fullttl );
420 return 1;
421 }
422
423 static void
append_people(fields * in,char * tag,char * entag,int level,fields * out,int * status)424 append_people( fields *in, char *tag, char *entag, int level, fields *out, int *status )
425 {
426 int i, n, flvl, fstatus;
427 str oneperson;
428 char *ftag;
429
430 str_init( &oneperson );
431 n = fields_num( in );
432 for ( i=0; i<n; ++i ) {
433 flvl = fields_level( in, i );
434 if ( level!=LEVEL_ANY && flvl!=level ) continue;
435 ftag = fields_tag( in, i, FIELDS_CHRP );
436 if ( !strcasecmp( ftag, tag ) ) {
437 name_build_withcomma( &oneperson, fields_value( in, i, FIELDS_CHRP ) );
438 fstatus = fields_add_can_dup( out, entag, str_cstr( &oneperson ), LEVEL_MAIN );
439 if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
440 }
441 }
442 str_free( &oneperson );
443 }
444
445 static void
append_pages(fields * in,fields * out,int * status)446 append_pages( fields *in, fields *out, int *status )
447 {
448 str *sn, *en;
449 int fstatus;
450 str pages;
451 char *ar;
452
453 sn = fields_findv( in, LEVEL_ANY, FIELDS_STRP, "PAGES:START" );
454 en = fields_findv( in, LEVEL_ANY, FIELDS_STRP, "PAGES:STOP" );
455 if ( sn || en ) {
456 str_init( &pages );
457 if ( sn ) str_strcpy( &pages, sn );
458 if ( sn && en ) str_strcatc( &pages, "-" );
459 if ( en ) str_strcat( &pages, en );
460 if ( str_memerr( &pages ) ) { *status = BIBL_ERR_MEMERR; str_free( &pages ); return; }
461 fstatus = fields_add( out, "%P", str_cstr( &pages ), LEVEL_MAIN );
462 if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
463 str_free( &pages );
464 } else {
465 ar = fields_findv( in, LEVEL_ANY, FIELDS_CHRP, "ARTICLENUMBER" );
466 if ( ar ) {
467 fstatus = fields_add( out, "%P", ar, LEVEL_MAIN );
468 if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
469 }
470 }
471 }
472
473 static void
append_urls(fields * in,fields * out,int * status)474 append_urls( fields *in, fields *out, int *status )
475 {
476 int lstatus;
477 slist types;
478
479 lstatus = slist_init_valuesc( &types, "URL", "DOI", "PMID", "PMC", "ARXIV", "JSTOR", "MRNUMBER", NULL );
480 if ( lstatus!=SLIST_OK ) {
481 *status = BIBL_ERR_MEMERR;
482 return;
483 }
484
485 *status = urls_merge_and_add( in, LEVEL_ANY, out, "%U", LEVEL_MAIN, &types );
486
487 slist_free( &types );
488 }
489
490 static void
append_year(fields * in,fields * out,int * status)491 append_year( fields *in, fields *out, int *status )
492 {
493 int fstatus;
494 char *year;
495
496 year = fields_findv_firstof( in, LEVEL_ANY, FIELDS_CHRP, "DATE:YEAR", "PARTDATE:YEAR", NULL );
497 if ( year ) {
498 fstatus = fields_add( out, "%D", year, LEVEL_MAIN );
499 if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
500 }
501 }
502
503 static void
append_monthday(fields * in,fields * out,int * status)504 append_monthday( fields *in, fields *out, int *status )
505 {
506 char *months[12] = { "January", "February", "March", "April",
507 "May", "June", "July", "August", "September", "October",
508 "November", "December" };
509 char *month, *day;
510 int m, fstatus;
511 str monday;
512
513 str_init( &monday );
514 month = fields_findv_firstof( in, LEVEL_ANY, FIELDS_CHRP, "DATE:MONTH", "PARTDATE:MONTH", NULL );
515 day = fields_findv_firstof( in, LEVEL_ANY, FIELDS_CHRP, "DATE:DAY", "PARTDATE:DAY", NULL );
516 if ( month || day ) {
517 if ( month ) {
518 m = atoi( month );
519 if ( m>0 && m<13 ) str_strcpyc( &monday, months[m-1] );
520 else str_strcpyc( &monday, month );
521 }
522 if ( month && day ) str_strcatc( &monday, " " );
523 if ( day ) str_strcatc( &monday, day );
524 fstatus = fields_add( out, "%8", str_cstr( &monday ), LEVEL_MAIN );
525 if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
526 }
527 str_free( &monday );
528 }
529
530 static void
append_genrehint(int type,fields * out,vplist * a,int * status)531 append_genrehint( int type, fields *out, vplist *a, int *status )
532 {
533 vplist_index i;
534 int fstatus;
535 char *g;
536
537 for ( i=0; i<a->n; ++i ) {
538 g = ( char * ) vplist_get( a, i );
539 if ( !strcmp( g, "journal article" ) && type==TYPE_ARTICLE ) continue;
540 if ( !strcmp( g, "academic journal" ) && type==TYPE_ARTICLE ) continue;
541 if ( !strcmp( g, "collection" ) && type==TYPE_INBOOK ) continue;
542 if ( !strcmp( g, "television broadcast" ) && type==TYPE_FILMBROADCAST ) continue;
543 if ( !strcmp( g, "electronic" ) && type==TYPE_PROGRAM ) continue;
544 if ( !strcmp( g, "magazine" ) && type==TYPE_MAGARTICLE ) continue;
545 if ( !strcmp( g, "miscellaneous" ) && type==TYPE_GENERIC ) continue;
546 if ( !strcmp( g, "hearing" ) && type==TYPE_HEARING ) continue;
547 if ( !strcmp( g, "communication" ) && type==TYPE_COMMUNICATION ) continue;
548 if ( !strcmp( g, "report" ) && type==TYPE_REPORT ) continue;
549 if ( !strcmp( g, "book chapter" ) && type==TYPE_INBOOK ) continue;
550 fstatus = fields_add( out, "%9", g, LEVEL_MAIN );
551 if ( fstatus!=FIELDS_OK ) {
552 *status = BIBL_ERR_MEMERR;
553 return;
554 }
555 }
556 }
557
558 static void
append_all_genrehint(int type,fields * in,fields * out,int * status)559 append_all_genrehint( int type, fields *in, fields *out, int *status )
560 {
561 vplist a;
562
563 vplist_init( &a );
564
565 fields_findv_each( in, LEVEL_ANY, FIELDS_CHRP, &a, "GENRE:BIBUTILS" );
566 append_genrehint( type, out, &a, status );
567
568 vplist_empty( &a );
569
570 fields_findv_each( in, LEVEL_ANY, FIELDS_CHRP, &a, "GENRE:UNKNOWN" );
571 append_genrehint( type, out, &a, status );
572
573 vplist_free( &a );
574 }
575
576 static void
append_thesishint(int type,fields * out,int * status)577 append_thesishint( int type, fields *out, int *status )
578 {
579 int fstatus;
580
581 if ( type==TYPE_MASTERSTHESIS ) {
582 fstatus = fields_add( out, "%9", "Masters thesis", LEVEL_MAIN );
583 if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
584 }
585 else if ( type==TYPE_PHDTHESIS ) {
586 fstatus = fields_add( out, "%9", "Ph.D. thesis", LEVEL_MAIN );
587 if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
588 }
589 else if ( type==TYPE_DIPLOMATHESIS ) {
590 fstatus = fields_add( out, "%9", "Diploma thesis", LEVEL_MAIN );
591 if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
592 }
593 else if ( type==TYPE_DOCTORALTHESIS ) {
594 fstatus = fields_add( out, "%9", "Doctoral thesis", LEVEL_MAIN );
595 if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
596 }
597 else if ( type==TYPE_HABILITATIONTHESIS ) {
598 fstatus = fields_add( out, "%9", "Habilitation thesis", LEVEL_MAIN );
599 if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
600 }
601 else if ( type==TYPE_LICENTIATETHESIS ) {
602 fstatus = fields_add( out, "%9", "Licentiate thesis", LEVEL_MAIN );
603 if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
604 }
605 }
606
607 static void
append_easyall(fields * in,char * tag,char * entag,int level,fields * out,int * status)608 append_easyall( fields *in, char *tag, char *entag, int level, fields *out, int *status )
609 {
610 vplist_index i;
611 int fstatus;
612 vplist a;
613 vplist_init( &a );
614 fields_findv_each( in, level, FIELDS_CHRP, &a, tag );
615 for ( i=0; i<a.n; ++i ) {
616 fstatus = fields_add( out, entag, (char *) vplist_get( &a, i ), LEVEL_MAIN );
617 if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
618 }
619 vplist_free( &a );
620 }
621
622 static void
append_easy(fields * in,char * tag,char * entag,int level,fields * out,int * status)623 append_easy( fields *in, char *tag, char *entag, int level, fields *out, int *status )
624 {
625 char *value;
626 int fstatus;
627
628 value = fields_findv( in, level, FIELDS_CHRP, tag );
629 if ( value ) {
630 fstatus = fields_add( out, entag, value, LEVEL_MAIN );
631 if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
632 }
633 }
634
635 static int
endout_assemble(fields * in,fields * out,param * pm,unsigned long refnum)636 endout_assemble( fields *in, fields *out, param *pm, unsigned long refnum )
637 {
638 int added, type, status = BIBL_OK;
639
640 fields_clear_used( in );
641
642 type = get_type( in, pm, refnum );
643
644 append_type( type, out, pm, &status );
645
646 added = append_title( in, "TITLE", "SUBTITLE", "%T", LEVEL_MAIN, out, &status );
647 if ( added==0 ) append_title( in, "SHORTTITLE", "SHORTSUBTITLE", "%T", LEVEL_MAIN, out, &status );
648 else append_title( in, "SHORTTITLE", "SHORTSUBTITLE", "%!", LEVEL_MAIN, out, &status );
649
650 append_people( in, "AUTHOR", "%A", LEVEL_MAIN, out, &status );
651 append_people( in, "EDITOR", "%E", LEVEL_MAIN, out, &status );
652 if ( type==TYPE_ARTICLE || type==TYPE_MAGARTICLE || type==TYPE_ELECTRONICARTICLE || type==TYPE_NEWSARTICLE )
653 append_people( in, "EDITOR", "%E", LEVEL_HOST, out, &status );
654 else if ( type==TYPE_INBOOK || type==TYPE_INPROCEEDINGS ) {
655 append_people( in, "EDITOR", "%E", LEVEL_HOST, out, &status );
656 } else {
657 append_people( in, "EDITOR", "%Y", LEVEL_HOST, out, &status );
658 }
659 append_people( in, "TRANSLATOR", "%H", LEVEL_ANY, out, &status );
660
661 append_people( in, "AUTHOR", "%Y", LEVEL_SERIES, out, &status );
662 append_people( in, "EDITOR", "%Y", LEVEL_SERIES, out, &status );
663
664 if ( type==TYPE_CASE ) {
665 append_easy( in, "AUTHOR:CORP", "%I", LEVEL_MAIN, out, &status );
666 append_easy( in, "AUTHOR:ASIS", "%I", LEVEL_MAIN, out, &status );
667 }
668 else if ( type==TYPE_HEARING ) {
669 append_easyall( in, "AUTHOR:CORP", "%S", LEVEL_MAIN, out, &status );
670 append_easyall( in, "AUTHOR:ASIS", "%S", LEVEL_MAIN, out, &status );
671 }
672 else if ( type==TYPE_NEWSARTICLE ) {
673 append_people( in, "REPORTER", "%A", LEVEL_MAIN, out, &status );
674 append_people( in, "REPORTER:CORP", "%A", LEVEL_MAIN, out, &status );
675 append_people( in, "REPORTER:ASIS", "%A", LEVEL_MAIN, out, &status );
676 }
677 else if ( type==TYPE_COMMUNICATION ) {
678 append_people( in, "ADDRESSEE", "%E", LEVEL_ANY, out, &status );
679 append_people( in, "ADDRESSEE:CORP", "%E", LEVEL_ANY, out, &status );
680 append_people( in, "ADDRESSEE:ASIS", "%E", LEVEL_ANY, out, &status );
681 }
682 else {
683 append_easyall( in, "AUTHOR:CORP", "%A", LEVEL_MAIN, out, &status );
684 append_easyall( in, "AUTHOR:ASIS", "%A", LEVEL_MAIN, out, &status );
685 append_easyall( in, "EDITOR:CORP", "%E", LEVEL_ANY, out, &status );
686 append_easyall( in, "EDITOR:ASIS", "%E", LEVEL_ANY, out, &status );
687 append_easyall( in, "TRANSLATOR:CORP", "%H", LEVEL_ANY, out, &status );
688 append_easyall( in, "TRANSLATOR:ASIS", "%H", LEVEL_ANY, out, &status );
689 }
690
691 if ( type==TYPE_ARTICLE || type==TYPE_MAGARTICLE || type==TYPE_ELECTRONICARTICLE || type==TYPE_NEWSARTICLE ) {
692 added = append_title( in, "TITLE", "SUBTITLE", "%J", LEVEL_HOST, out, &status );
693 if ( added==0 ) append_title( in, "SHORTTITLE", "SHORTSUBTITLE", "%J", LEVEL_HOST, out, &status );
694 }
695
696 else if ( type==TYPE_INBOOK || type==TYPE_INPROCEEDINGS ) {
697 added = append_title( in, "TITLE", "SUBTITLE", "%B", LEVEL_HOST, out, &status );
698 if ( added==0 ) append_title( in, "SHORTTITLE", "SHORTSUBTITLE", "%B", LEVEL_HOST, out, &status );
699 }
700
701 else {
702 added = append_title( in, "TITLE", "SUBTITLE", "%S", LEVEL_HOST, out, &status );
703 if ( added==0 ) append_title( in, "SHORTTITLE", "SHORTSUBTITLE", "%S", LEVEL_HOST, out, &status );
704 }
705
706 if ( type!=TYPE_CASE && type!=TYPE_HEARING ) {
707 append_title( in, "TITLE", "SUBTITLE", "%S", LEVEL_SERIES, out, &status );
708 }
709
710 append_year ( in, out, &status );
711 append_monthday( in, out, &status );
712
713 append_easy ( in, "VOLUME", "%V", LEVEL_ANY, out, &status );
714 append_easy ( in, "ISSUE", "%N", LEVEL_ANY, out, &status );
715 append_easy ( in, "NUMBER", "%N", LEVEL_ANY, out, &status );
716 append_easy ( in, "EDITION", "%7", LEVEL_ANY, out, &status );
717 append_easy ( in, "PUBLISHER", "%I", LEVEL_ANY, out, &status );
718 append_easy ( in, "ADDRESS", "%C", LEVEL_ANY, out, &status );
719 append_easy ( in, "DEGREEGRANTOR", "%C", LEVEL_ANY, out, &status );
720 append_easy ( in, "DEGREEGRANTOR:CORP", "%C", LEVEL_ANY, out, &status );
721 append_easy ( in, "DEGREEGRANTOR:ASIS", "%C", LEVEL_ANY, out, &status );
722 append_easy ( in, "SERIALNUMBER", "%@", LEVEL_ANY, out, &status );
723 append_easy ( in, "ISSN", "%@", LEVEL_ANY, out, &status );
724 append_easy ( in, "ISBN", "%@", LEVEL_ANY, out, &status );
725 append_easy ( in, "LANGUAGE", "%G", LEVEL_ANY, out, &status );
726 append_easy ( in, "REFNUM", "%F", LEVEL_ANY, out, &status );
727 append_easyall ( in, "NOTES", "%O", LEVEL_ANY, out, &status );
728 append_easy ( in, "ABSTRACT", "%X", LEVEL_ANY, out, &status );
729 append_easy ( in, "CLASSIFICATION" , "%L", LEVEL_ANY, out, &status );
730 append_easyall ( in, "KEYWORD", "%K", LEVEL_ANY, out, &status );
731 append_all_genrehint( type, in, out, &status );
732 append_thesishint( type, out, &status );
733 append_easyall ( in, "DOI", "%R", LEVEL_ANY, out, &status );
734 append_easyall ( in, "URL", "%U", LEVEL_ANY, out, &status );
735 append_easyall ( in, "FILEATTACH", "%U", LEVEL_ANY, out, &status );
736 append_urls ( in, out, &status );
737 append_pages ( in, out, &status );
738
739 return status;
740 }
741
742 /*****************************************************
743 PUBLIC: int endout_write()
744 *****************************************************/
745
746 static int
endout_write(fields * out,FILE * fp,param * pm,unsigned long refnum)747 endout_write( fields *out, FILE *fp, param *pm, unsigned long refnum )
748 {
749 int i;
750
751 for ( i=0; i<out->n; ++i ) {
752 fprintf( fp, "%s %s\n",
753 (char*) fields_tag( out, i, FIELDS_CHRP ),
754 (char*) fields_value( out, i, FIELDS_CHRP )
755 );
756 }
757
758 fprintf( fp, "\n" );
759 fflush( fp );
760 return BIBL_OK;
761 }
762