packages feed

hs-bibutils 5.5 → 6.2

raw patch · 114 files changed

+12753/−10402 lines, 114 filesnew-uploaderPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Text.Bibutils: addcount :: Param -> CInt
- Text.Bibutils: charsetin :: Param -> CInt
- Text.Bibutils: charsetin_src :: Param -> CUChar
- Text.Bibutils: charsetout :: Param -> CInt
- Text.Bibutils: charsetout_src :: Param -> CUChar
- Text.Bibutils: format_opts :: Param -> CInt
- Text.Bibutils: instance Eq BiblioIn
- Text.Bibutils: instance Eq BiblioOut
- Text.Bibutils: instance Eq Charset
- Text.Bibutils: instance Eq Status
- Text.Bibutils: instance Show Param
- Text.Bibutils: instance Show Status
- Text.Bibutils: instance Storable Bibl
- Text.Bibutils: instance Storable Param
- Text.Bibutils: latexin :: Param -> CUChar
- Text.Bibutils: latexout :: Param -> CUChar
- Text.Bibutils: nosplittitle :: Param -> CUChar
- Text.Bibutils: output_raw :: Param -> CUChar
- Text.Bibutils: redaformat :: Param -> CInt
- Text.Bibutils: singlerefperfile :: Param -> CUChar
- Text.Bibutils: utf8bom :: Param -> CUChar
- Text.Bibutils: utf8in :: Param -> CUChar
- Text.Bibutils: utf8out :: Param -> CUChar
- Text.Bibutils: verbose :: Param -> CUChar
- Text.Bibutils: wordout_dropkey :: FormatOpt
- Text.Bibutils: writeformat :: Param -> CInt
- Text.Bibutils: xmlin :: Param -> CUChar
- Text.Bibutils: xmlout :: Param -> CUChar
+ Text.Bibutils: [addcount] :: Param -> CInt
+ Text.Bibutils: [charsetin] :: Param -> CInt
+ Text.Bibutils: [charsetin_src] :: Param -> CUChar
+ Text.Bibutils: [charsetout] :: Param -> CInt
+ Text.Bibutils: [charsetout_src] :: Param -> CUChar
+ Text.Bibutils: [format_opts] :: Param -> CInt
+ Text.Bibutils: [latexin] :: Param -> CUChar
+ Text.Bibutils: [latexout] :: Param -> CUChar
+ Text.Bibutils: [nosplittitle] :: Param -> CUChar
+ Text.Bibutils: [output_raw] :: Param -> CUChar
+ Text.Bibutils: [redaformat] :: Param -> CInt
+ Text.Bibutils: [singlerefperfile] :: Param -> CUChar
+ Text.Bibutils: [utf8bom] :: Param -> CUChar
+ Text.Bibutils: [utf8in] :: Param -> CUChar
+ Text.Bibutils: [utf8out] :: Param -> CUChar
+ Text.Bibutils: [verbose] :: Param -> CUChar
+ Text.Bibutils: [writeformat] :: Param -> CInt
+ Text.Bibutils: [xmlin] :: Param -> CUChar
+ Text.Bibutils: [xmlout] :: Param -> CUChar
+ Text.Bibutils: instance Foreign.Storable.Storable Text.Bibutils.Bibl
+ Text.Bibutils: instance Foreign.Storable.Storable Text.Bibutils.Param
+ Text.Bibutils: instance GHC.Classes.Eq Text.Bibutils.BiblioIn
+ Text.Bibutils: instance GHC.Classes.Eq Text.Bibutils.BiblioOut
+ Text.Bibutils: instance GHC.Classes.Eq Text.Bibutils.Charset
+ Text.Bibutils: instance GHC.Classes.Eq Text.Bibutils.Status
+ Text.Bibutils: instance GHC.Show.Show Text.Bibutils.Param
+ Text.Bibutils: instance GHC.Show.Show Text.Bibutils.Status

Files

+ ChangeLog.md view
@@ -0,0 +1,4 @@+# 6.2++  - This release has removed `wordout_dropkey` because the corresponding+    constant in Bibutils has also been removed.
− README
@@ -1,125 +0,0 @@-% Haskell Bindings to Bibutils, the Bibliography Conversion Utilities-% Andrea Rossato--About--------[hs-bibutils] is library with Haskell bindings to Chris Putnam's-[bibutils], a library that interconverts between various bibliography-formats using a common MODS-format XML intermediate.--[hs-bibutils] can be used with [citeproc-hs] and [pandoc] to read and-use various bibliographic database formats for processing and-automatically formatting citations and references according to a [CSL]-style.--[citeproc-hs] adds to [pandoc], the famous [Haskell] text processing-tool, a Bibtex like citation and bibliographic formatting and-generation facility.--[CSL] is an XML language for specifying citation and bibliographic-formatting, similar in principle to BibTeX `.bst` files or the binary-style files in commercial products like Endnote or Reference Manager.--Download-----------[hs-bibutils] can be downloaded from [Hackage]:--<http://hackage.haskell.org/cgi-bin/hackage-scripts/package/hs-bibutils>--To get the darcs source run:--        darcs get http://code.haskell.org/hs-bibutils/--Installation---------------[hs-bibutils] does not require [bibutils] to be installed, since it-ships with its one version of the library. To build and install-[hs-bibutils] unpack the tar archive, in the source directory run:--        runhaskell Setup.lhs configure-        runhaskell Setup.lhs build-        runhaskell Setup.lhs install--This last step requires `root` privileges.--If you don't have `root` privileges you can install [hs-bibutils]-locally with these commands:--        runhaskell Setup.lhs configure --user --prefix=$HOME-        runhaskell Setup.lhs build-        runhaskell Setup.lhs install --user--[hs-bibutils] should be compatible with cabal-install.--Documentation----------------The [Haddock] generated documentation is available here:--<http://code.haskell.org/hs-bibutils/docs/>--The original API documentation is available here:--<http://www.scripps.edu/~cdputnam/software/bibutils/library_specs.html>--Bug Reports--------------To submit bug reports you can use the [citeproc-hs] bug tracking-system available at the following address:--<http://code.google.com/p/citeproc-hs/issues>--Credits----------Thanks to [Chris Putnam] for his help.--Author---------Andrea Rossato--`andrea.rossato at unitn.it`--Links to Related Projects-------------------Bibutils-:    <http://www.scripps.edu/~cdputnam/software/bibutils/>--Pandoc-:    <http://johnmacfarlane.net/pandoc/>--Citeproc-hs:-:    <http://code.haskell.org/citeproc-hs/>--CSL-:    <http://xbiblio.sourceforge.net/csl/>--Legal--------This software is released under the GNU GPL. See LICENSE for more-details.--This is an early, "alpha" release. It carries no warranties of any kind.--Copyright &copy; 2008 - 2010 Andrea Rossato--[hs-bibutils]: http://code.haskell.org/hs-bibutils-[bibutils]: http://www.scripps.edu/~cdputnam/software/bibutils/-[Hackage]: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/hs-bibutils-[citeproc-hs]: http://code.haskell.org/citeproc-hs-[CSL]: http://citationstyles.org/-[pandoc]: http://johnmacfarlane.net/pandoc/-[Zotero]: http://www.zotero.org-[MODS]: http://www.loc.gov/mods/-[Bruce D'Arcus]: http://community.muohio.edu/blogs/darcusb/-[John MacFarlane]: http://johnmacfarlane.net/-[Chris Putnam]: http://www.scripps.edu/~cdputnam/-[Haskell]:  http://www.haskell.org/-[Haddock]:  http://www.haskell.org/haddock/
+ README.md view
@@ -0,0 +1,95 @@+About+-----++[hs-bibutils] is library with Haskell bindings to Chris Putnam's+[bibutils], a library that interconverts between various bibliography+formats using a common MODS-format XML intermediate.++[hs-bibutils] can be used with [pandoc-citeproc] to read and use various+bibliographic database formats for processing and automatically formatting+citations and references according to a [CSL] style.++[pandoc-citeproc] adds to [pandoc], the famous [Haskell] text processing+tool, a Bibtex like citation and bibliographic formatting and generation+facility.++[CSL] is an XML language for specifying citation and bibliographic+formatting, similar in principle to BibTeX `.bst` files or the binary+style files in commercial products like Endnote or Reference Manager.++Documentation+-------------++The [Haddock] generated documentation is available here:++<https://hackage.haskell.org/package/hs-bibutils/docs/Text-Bibutils.html>++Bug Reports+-----------++To submit bug reports you can use the [hs-bibutils] bug tracking+system available at the following address:++<https://github.com/wilx/hs-bibutils/issues>++Credits+-------++Thanks to [Chris Putnam] for his help.++Author+------++Andrea Rossato++`andrea.rossato at unitn dot it`++Maintainer+----------++Václav Haisman++`vhaisman at gmail dot com`++Links to Related Projects+----------------++Bibutils+:    <https://sourceforge.net/p/bibutils/home/Bibutils/>++Pandoc+:    <https://pandoc.org/>++Pandoc-Citeproc+:    <https://github.com/jgm/pandoc-citeproc>++Citeproc-hs:+:    <http://istitutocolli.org/repos/citeproc-hs/>++CSL+:    <http://xbiblio.sourceforge.net/csl/>++Legal+-----++This software is released under the GNU GPL. See LICENSE for more+details.++This is an early, "alpha" release. It carries no warranties of any kind.++Copyright © 2008 – 2010 Andrea Rossato++[hs-bibutils]: https://github.com/wilx/hs-bibutils+[bibutils]: https://sourceforge.net/p/bibutils/home/Bibutils/+[Hackage]: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/hs-bibutils+[citeproc-hs]: http://istitutocolli.org/repos/citeproc-hs/+[CSL]: http://citationstyles.org/+[pandoc]: http://pandoc.org/+[pandoc-citeproc]: https://github.com/jgm/pandoc-citeproc+[Zotero]: http://www.zotero.org+[MODS]: http://www.loc.gov/mods/+[Bruce D'Arcus]: http://community.muohio.edu/blogs/darcusb/+[John MacFarlane]: http://johnmacfarlane.net/+[Chris Putnam]: http://www.scripps.edu/~cdputnam/+[Haskell]:  http://www.haskell.org/+[Haddock]:  http://www.haskell.org/haddock/
bibutils/adsout.c view
@@ -1,8 +1,8 @@ /*  * adsout.c  *- * Copyright (c) Richard Mathar 2007-2014- * Copyright (c) Chris Putnam 2007-2014+ * Copyright (c) Richard Mathar 2007-2017+ * Copyright (c) Chris Putnam 2007-2017  *  * Program and source code released under the GPL version 2  *@@ -13,12 +13,17 @@ #include <string.h> #include <ctype.h> #include "utf8.h"-#include "newstr.h"+#include "str.h" #include "strsearch.h" #include "fields.h" #include "name.h"-#include "adsout.h"+#include "title.h"+#include "url.h"+#include "bibformats.h" +static int  adsout_write( fields *in, FILE *fp, param *p, unsigned long refnum );+static void adsout_writeheader( FILE *outptr, param *p );+ void adsout_initparams( param *p, const char *progname ) {@@ -76,7 +81,7 @@ } match_type;  static int-get_type( fields *info )+get_type( fields *in ) { 	match_type match_genres[] = { 		{ "academic journal",          TYPE_ARTICLE },@@ -101,15 +106,15 @@ 	char *tag, *data; 	int i, j, type = TYPE_UNKNOWN; -	for ( i=0; i<info->n; ++i ) {-		tag = info->tag[i].data;+	for ( i=0; i<in->n; ++i ) {+		tag = in->tag[i].data; 		if ( strcasecmp( tag, "GENRE" )!=0 && 		     strcasecmp( tag, "NGENRE" )!=0 ) continue;-		data = info->data[i].data;+		data = in->data[i].data; 		for ( j=0; j<nmatch_genres; ++j ) { 			if ( !strcasecmp( data, match_genres[j].name ) ) { 				type = match_genres[j].type;-				fields_setused( info, i );+				fields_setused( in, i ); 			} 		} 		if ( type==TYPE_UNKNOWN ) {@@ -118,26 +123,26 @@ 			else if ( !strcasecmp( data, "thesis" ) ) 				type = TYPE_THESIS; 			else if ( !strcasecmp( data, "book" ) ) {-				if ( info->level[i]==0 ) type = TYPE_BOOK;+				if ( in->level[i]==0 ) type = TYPE_BOOK; 				else type = TYPE_INBOOK; 			} 			else if ( !strcasecmp( data, "collection" ) ) {-				if ( info->level[i]==0 ) type = TYPE_BOOK;+				if ( in->level[i]==0 ) type = TYPE_BOOK; 				else type = TYPE_INBOOK; 			}-			if ( type!=TYPE_UNKNOWN ) fields_setused( info, i );+			if ( type!=TYPE_UNKNOWN ) fields_setused( in, i ); 		} 	} 	if ( type==TYPE_UNKNOWN ) {-		for ( i=0; i<info->n; ++i ) {-			if ( strcasecmp( info->tag[i].data, "RESOURCE" ) )+		for ( i=0; i<in->n; ++i ) {+			if ( strcasecmp( in->tag[i].data, "RESOURCE" ) ) 				continue;-			data = info->data[i].data;+			data = in->data[i].data; 			if ( !strcasecmp( data, "moving image" ) ) 				type = TYPE_BROADCAST; 			else if ( !strcasecmp( data, "software, multimedia" ) ) 				type = TYPE_PROGRAM;-			if ( type!=TYPE_UNKNOWN ) fields_setused( info, i );+			if ( type!=TYPE_UNKNOWN ) fields_setused( in, i ); 		} 	} @@ -147,81 +152,144 @@ 	return type; } -static void-output_title( FILE *fp, fields *f, char *full, char *sub, char *adstag, int level )+static int+append_title( fields *in, char *ttl, char *sub, char *adstag, int level, fields *out, int *status ) {-	newstr *fulltitle, *subtitle, *vol, *iss, *sn, *en, *ar;+	str fulltitle, *title, *subtitle, *vol, *iss, *sn, *en, *ar;+	int fstatus, output = 0; -	fulltitle = fields_findv( f, level, FIELDS_STRP, full );-	subtitle  = fields_findv( f, level, FIELDS_STRP, sub );+	str_init( &fulltitle ); -	if ( fulltitle && fulltitle->len ) {+	title     = fields_findv( in, level, FIELDS_STRP, ttl );+	subtitle  = fields_findv( in, level, FIELDS_STRP, sub ); -		fprintf( fp, "%s %s", adstag, fulltitle->data );-		if ( subtitle && subtitle->len ) {-			if ( fulltitle->data[ fulltitle->len - 1 ] != '?' )-				fprintf( fp, ": " );-			else fprintf( fp, " " );-			fprintf( fp, "%s", subtitle->data );-		}+	if ( str_has_value( title ) ) { -		vol = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "VOLUME" );-		if ( vol && vol->len ) fprintf( fp, ", vol. %s", vol->data );+		output = 1; -		iss = fields_findv_firstof( f, LEVEL_ANY, FIELDS_STRP, "ISSUE",+		title_combine( &fulltitle, title, subtitle );++		vol = fields_findv( in, LEVEL_ANY, FIELDS_STRP, "VOLUME" );+		if ( str_has_value( vol ) ) {+			str_strcatc( &fulltitle, ", vol. " );+			str_strcat( &fulltitle, vol );+		}++		iss = fields_findv_firstof( in, LEVEL_ANY, FIELDS_STRP, "ISSUE", 			"NUMBER", NULL );-		if ( iss && iss->len ) fprintf( fp, ", no. %s", iss->data );+		if ( str_has_value( iss ) ) {+			str_strcatc( &fulltitle, ", no. " );+			str_strcat( &fulltitle, iss );+		} -		sn = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "PAGESTART" );-		en = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "PAGEEND" );-		ar = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "ARTICLENUMBER" );-		if ( sn && sn->len ) {-			if ( en && en->len )-				fprintf( fp, ", pp." );-			else-				fprintf( fp, ", p." );-			fprintf( fp, " %s", sn->data );-		} else if ( ar && ar->len ) {-			fprintf( fp, ", p. %s", ar->data );+		sn = fields_findv( in, LEVEL_ANY, FIELDS_STRP, "PAGES:START" );+		en = fields_findv( in, LEVEL_ANY, FIELDS_STRP, "PAGES:STOP" );+		ar = fields_findv( in, LEVEL_ANY, FIELDS_STRP, "ARTICLENUMBER" );++		if ( str_has_value( sn ) ) {+			if ( str_has_value( en ) ) {+				str_strcatc( &fulltitle, ", pp. " );+			} else {+				str_strcatc( &fulltitle, ", p. " );+			}+			str_strcat( &fulltitle, sn );+		} else if ( str_has_value( ar ) ) {+			str_strcatc( &fulltitle, ", p. " );+			str_strcat( &fulltitle, ar ); 		}-		if ( en && en->len ) {-			fprintf( fp, "-%s", en->data );+		if ( str_has_value( en ) ) {+			str_addchar( &fulltitle, '-' );+			str_strcat( &fulltitle, en ); 		} -		fprintf( fp, "\n" );+		if ( str_memerr( &fulltitle ) ) {+			*status = BIBL_ERR_MEMERR;+			goto out;+		}++		fstatus = fields_add( out, adstag, str_cstr( &fulltitle ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+ 	}++out:+	str_free( &fulltitle );++	return output; }  static void-output_people( FILE *fp, fields *f, char *tag1, char *tag2, char *tag3, char *adstag, int level )+append_titles( fields *in, int type, fields *out, int *status ) {-	newstr oneperson;+	int added;+	if ( type==TYPE_ARTICLE || type==TYPE_MAGARTICLE ) {+		added = append_title( in, "TITLE", "SUBTITLE", "%J", LEVEL_HOST, out, status );+		if ( added==0 )+			(void) append_title( in, "SHORTTITLE", "SHORTSUBTITLE", "%J", LEVEL_HOST, out, status );+	}+}++static void+append_people( fields *in, char *tag1, char *tag2, char *tag3, char *adstag, int level, fields *out, int *status )+{+	str oneperson, allpeople;+	vplist_index i;+	int fstatus; 	vplist a;-	int i;-	newstr_init( &oneperson );++	str_init( &oneperson );+	str_init( &allpeople ); 	vplist_init( &a );-	fields_findv_eachof( f, level, FIELDS_CHRP, &a, tag1, tag2, tag3, NULL );-	extern void  fields_findv_eachof( fields *f, int level, int mode, vplist *a, ... );-	for ( i=0; i<a.n; ++i ) {-		if ( i==0 ) fprintf( fp, "%s ", adstag );-		else fprintf( fp, "; " );-		name_build_withcomma( &oneperson, (char *) vplist_get( &a, i) );-		fprintf( fp, "%s", oneperson.data );++	fields_findv_eachof( in, level, FIELDS_CHRP, &a, tag1, tag2, tag3, NULL );+	if ( a.n ) {+		for ( i=0; i<a.n; ++i ) {+			if ( i!=0 ) str_strcatc( &allpeople, "; " );+			name_build_withcomma( &oneperson, (char *) vplist_get( &a, i) );+			str_strcat( &allpeople, &oneperson );+		}+		fstatus = fields_add( out, adstag, str_cstr( &allpeople ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR; 	}-	if ( a.n ) fprintf( fp, "\n" );+ 	vplist_free( &a );-	newstr_free( &oneperson );+	str_free( &oneperson );+	str_free( &allpeople ); }  static void-output_pages( FILE *fp, fields *f )+append_pages( fields *in, fields *out, int *status ) {-	newstr *sn = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "PAGESTART" );-	newstr *en = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "PAGEEND" );-	newstr *ar = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "ARTICLENUMBER" );-	if ( sn && sn->len!=0 ) fprintf( fp, "%%P %s\n", sn->data );-	else if ( ar && ar->len!=0 ) fprintf( fp, "%%P %s\n", ar->data );-	if ( en && en->len!=0 ) fprintf( fp, "%%L %s\n", en->data );+	str *sn, *en, *ar;+	int fstatus;++	sn = fields_findv( in, LEVEL_ANY, FIELDS_STRP, "PAGES:START" );+	en = fields_findv( in, LEVEL_ANY, FIELDS_STRP, "PAGES:STOP" );+	ar = fields_findv( in, LEVEL_ANY, FIELDS_STRP, "ARTICLENUMBER" );++	if ( str_has_value( sn ) ) {+		fstatus = fields_add( out, "%P", str_cstr( sn ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) {+			*status = BIBL_ERR_MEMERR;+			return;+		}+	}++	else if ( str_has_value( ar ) ) {+		fstatus = fields_add( out, "%P", str_cstr( ar ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) {+			*status = BIBL_ERR_MEMERR;+			return;+		}+	}++	if ( str_has_value( en ) ) {+		fstatus = fields_add( out, "%L", str_cstr( en ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) {+			*status = BIBL_ERR_MEMERR;+			return;+		}+	} }  static int@@ -240,23 +308,28 @@ }  static int-get_month( fields *f, int level )+get_month( fields *in, int level ) {-	newstr *month = fields_findv_firstof( f, level, FIELDS_STRP,-			"MONTH", "PARTMONTH", NULL );-	if ( month && month->len ) return mont2mont( month->data );+	str *month;++	month = fields_findv_firstof( in, level, FIELDS_STRP, "DATE:MONTH", "PARTDATE:MONTH", NULL );+	if ( str_has_value( month ) ) return mont2mont( month->data ); 	else return 0; }  static void-output_date( FILE *fp, fields *f, char *adstag, int level )+append_date( fields *in, char *adstag, int level, fields *out, int *status ) {-	newstr *year = fields_findv_firstof( f, level, FIELDS_STRP,-		"YEAR", "PARTYEAR", NULL );-	int month;-	if ( year && year->len ) {-		month = get_month( f, level );-		fprintf( fp, "%s %02d/%s\n", adstag, month, year->data );+	int month, fstatus;+	char outstr[1000];+	str *year;++	year = fields_findv_firstof( in, level, FIELDS_STRP, "DATE:YEAR", "PARTDATE:YEAR", NULL );+	if ( str_has_value( year ) ) {+		month = get_month( in, level );+		sprintf( outstr, "%02d/%s", month, str_cstr( year ) );+		fstatus = fields_add( out, adstag, outstr, LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR; 	} } @@ -279,29 +352,29 @@ }  static char-get_firstinitial( fields *f )+get_firstinitial( fields *in ) { 	char *name; 	int n; -	n = fields_find( f, "AUTHOR", LEVEL_MAIN );-	if ( n==-1 ) n = fields_find( f, "AUTHOR", LEVEL_ANY );+	n = fields_find( in, "AUTHOR", LEVEL_MAIN );+	if ( n==-1 ) n = fields_find( in, "AUTHOR", LEVEL_ANY );  	if ( n!=-1 ) {-		name = fields_value( f, n, FIELDS_CHRP );+		name = fields_value( in, n, FIELDS_CHRP ); 		return name[0]; 	} else return '\0'; }  static int-get_journalabbr( fields *f )+get_journalabbr( fields *in ) { 	char *jrnl; 	int n, j; -	n = fields_find( f, "TITLE", LEVEL_HOST );+	n = fields_find( in, "TITLE", LEVEL_HOST ); 	if ( n!=-1 ) {-		jrnl = fields_value( f, n, FIELDS_CHRP );+		jrnl = fields_value( in, n, FIELDS_CHRP ); 		for ( j=0; j<njournals; j++ ) { 			if ( !strcasecmp( jrnl, journals[j]+6 ) ) 				return j;@@ -311,121 +384,211 @@ }  static void-output_Rtag( FILE *fp, fields *f, char *adstag, int type )+append_Rtag( fields *in, char *adstag, int type, fields *out, int *status ) {-	char out[20], ch;-	int n, i;+	char outstr[20], ch;+	int n, i, fstatus; 	long long page; -	strcpy( out, "..................." );+	strcpy( outstr, "..................." );  	/** YYYY */-	n = fields_find( f, "YEAR", LEVEL_ANY );-	if ( n==-1 ) n = fields_find( f, "PARTYEAR", LEVEL_ANY );-	if ( n!=-1 ) output_4digit_value( out, atoi( fields_value( f, n, FIELDS_CHRP ) ) );+	n = fields_find( in, "DATE:YEAR", LEVEL_ANY );+	if ( n==-1 ) n = fields_find( in, "PARTDATE:YEAR", LEVEL_ANY );+	if ( n!=-1 ) output_4digit_value( outstr, atoi( fields_value( in, n, FIELDS_CHRP ) ) );  	/** JJJJ */-	n = get_journalabbr( f );+	n = get_journalabbr( in ); 	if ( n!=-1 ) { 		i = 0; 		while ( i<5 && journals[n][i]!=' ' && journals[n][i]!='\t' ) {-			out[4+i] = journals[n][i];+			outstr[4+i] = journals[n][i]; 			i++; 		} 	}  	/** VVVV */-	n = fields_find( f, "VOLUME", LEVEL_ANY );-	if ( n!=-1 ) output_4digit_value( out+9, atoi( fields_value( f, n, FIELDS_CHRP ) ) );+	n = fields_find( in, "VOLUME", LEVEL_ANY );+	if ( n!=-1 ) output_4digit_value( outstr+9, atoi( fields_value( in, n, FIELDS_CHRP ) ) );  	/** MPPPP */-	n = fields_find( f, "PAGESTART", LEVEL_ANY );-	if ( n==-1 ) n = fields_find( f, "ARTICLENUMBER", LEVEL_ANY );+	n = fields_find( in, "PAGES:START", LEVEL_ANY );+	if ( n==-1 ) n = fields_find( in, "ARTICLENUMBER", LEVEL_ANY ); 	if ( n!=-1 ) {-		page = atoll( fields_value( f, n, FIELDS_CHRP ) );-		output_4digit_value( out+14, page );+		page = atoll( fields_value( in, n, FIELDS_CHRP ) );+		output_4digit_value( outstr+14, page ); 		if ( page>=10000 ) { 			ch = 'a' + (page/10000);-			out[13] = ch;+			outstr[13] = ch; 		} 	}  	/** A */-        ch = toupper( (unsigned char) get_firstinitial( f ) );-	if ( ch!='\0' ) out[18] = ch;+        ch = toupper( (unsigned char) get_firstinitial( in ) );+	if ( ch!='\0' ) outstr[18] = ch; -	fprintf( fp, "%s %s\n", adstag, out );+	fstatus = fields_add( out, adstag, outstr, LEVEL_MAIN );+	if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR; }  static void-output_easyall( FILE *fp, fields *f, char *tag, char *adstag, int level )+append_easyall( fields *in, char *tag, char *adstag, int level, fields *out, int *status ) {+	vplist_index i;+	int fstatus; 	vplist a;-	int i;+ 	vplist_init( &a );-	fields_findv_each( f, level, FIELDS_CHRP, &a, tag );-	for ( i=0; i<a.n; ++i )-		fprintf( fp, "%s %s\n", adstag, (char *) vplist_get( &a, i ) );++	fields_findv_each( in, level, FIELDS_CHRP, &a, tag );++	for ( i=0; i<a.n; ++i ) {+		fstatus = fields_add( out, adstag, (char*) vplist_get( &a, i ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) {+			*status = BIBL_ERR_MEMERR;+			goto out;+		}+	}+out: 	vplist_free( &a ); }  static void-output_easy( FILE *fp, fields *f, char *tag, char *adstag, int level )+append_easy( fields *in, char *tag, char *adstag, int level, fields *out, int *status ) {-	char *value = fields_findv( f, level, FIELDS_CHRP, tag );-	if ( value && value[0]!='\0' ) fprintf( fp, "%s %s\n", adstag, value );+	char *value;+	int fstatus;++	value = fields_findv( in, level, FIELDS_CHRP, tag );+	if ( value && value[0]!='\0' ) {+		fstatus = fields_add( out, adstag, value, LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	} }  static void-output_keys( FILE *fp, fields *f, char *tag, char *adstag, int level )+append_keys( fields *in, char *tag, char *adstag, int level, fields *out, int *status ) {+	vplist_index i;+	str allkeys;+	int fstatus; 	vplist a;-	int i;++	str_init( &allkeys ); 	vplist_init( &a );-	fields_findv_each( f, level, FIELDS_CHRP, &a, tag );-	for ( i=0; i<a.n; ++i ) {-		if ( i==0 ) fprintf( fp, "%s ", adstag );-		else fprintf( fp, ", " );-		fprintf( fp, "%s", (char *) vplist_get( &a, i ) );++	fields_findv_each( in, level, FIELDS_CHRP, &a, tag );++	if ( a.n ) {+		for ( i=0; i<a.n; ++i ) {+			if ( i>0 ) str_strcatc( &allkeys, ", " );+			str_strcatc( &allkeys, (char *) vplist_get( &a, i ) );+		}+		fstatus = fields_add( out, adstag, str_cstr( &allkeys ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR; 	}-	if ( a.n ) fprintf( fp, "\n" );++	str_free( &allkeys ); 	vplist_free( &a ); } -void-adsout_write( fields *f, FILE *fp, param *p, unsigned long refnum )+static void+append_urls( fields *in, fields *out, int *status ) {-	int type;-	fields_clearused( f );-	type = get_type( f );+	int lstatus;+	slist types; -	output_people(  fp, f, "AUTHOR", "AUTHOR:ASIS", "AUTHOR:CORP", "%A", LEVEL_MAIN );-	output_people(  fp, f, "EDITOR", "EDITOR:ASIS", "EDITOR:CORP", "%E", LEVEL_ANY );-	output_easy(    fp, f, "TITLE",       "%T", LEVEL_ANY );+	lstatus = slist_init_valuesc( &types, "URL", "DOI", "PMID", "PMC", "ARXIV", "JSTOR", "MRNUMBER", "FILEATTACH", "FIGATTACH", NULL );+	if ( lstatus!=SLIST_OK ) {+		*status = BIBL_ERR_MEMERR;+		return;+	} -	if ( type==TYPE_ARTICLE || type==TYPE_MAGARTICLE )-		output_title( fp, f, "TITLE", "SUBTITLE", "%J", LEVEL_HOST );+	*status = urls_merge_and_add( in, LEVEL_ANY, out, "%U", LEVEL_MAIN, &types ); -	output_date(    fp, f,               "%D", LEVEL_ANY );-	output_easy(    fp, f, "VOLUME",     "%V", LEVEL_ANY );-	output_easy(    fp, f, "ISSUE",      "%N", LEVEL_ANY );-	output_easy(    fp, f, "NUMBER",     "%N", LEVEL_ANY );-	output_easy(    fp, f, "LANGUAGE",   "%M", LEVEL_ANY );-	output_easyall( fp, f, "NOTES",      "%X", LEVEL_ANY );-	output_easy(    fp, f, "ABSTRACT",   "%B", LEVEL_ANY );-	output_keys(    fp, f, "KEYWORD",    "%K", LEVEL_ANY );-	output_easyall( fp, f, "URL",        "%U", LEVEL_ANY ); -	output_easyall( fp, f, "FILEATTACH", "%U", LEVEL_ANY ); -	output_easyall( fp, f, "FIGATTACH",  "%U", LEVEL_ANY ); -	output_pages( fp, f );-	output_easyall( fp, f, "DOI",        "%Y", LEVEL_ANY );-        fprintf( fp, "%%W PHY\n%%G AUTHOR\n" );-	output_Rtag( fp, f, "%R", type );+	slist_free( &types );+}++static void+append_trailer( fields *out, int *status )+{+	int fstatus;++	fstatus = fields_add( out, "%W", "PHY", LEVEL_MAIN );+	if ( fstatus!=FIELDS_OK ) {+		*status = BIBL_ERR_MEMERR;+		return;+	}++	fstatus = fields_add( out, "%G", "AUTHOR", LEVEL_MAIN );+	if ( fstatus!=FIELDS_OK ) {+		*status = BIBL_ERR_MEMERR;+		return;+	}+}++static void+output( FILE *fp, fields *out )+{+	char *tag, *value;+	int i;++	for ( i=0; i<out->n; ++i ) {+		tag   = fields_tag( out, i, FIELDS_CHRP );+		value = fields_value( out, i, FIELDS_CHRP );+		fprintf( fp, "%s %s\n", tag, value );+	}+ 	fprintf( fp, "\n" ); 	fflush( fp ); } -void+static int+append_data( fields *in, fields *out )+{+	int type, status = BIBL_OK;++	fields_clearused( in );+	type = get_type( in );++	append_people ( in, "AUTHOR", "AUTHOR:ASIS", "AUTHOR:CORP", "%A", LEVEL_MAIN, out, &status );+	append_people ( in, "EDITOR", "EDITOR:ASIS", "EDITOR:CORP", "%E", LEVEL_ANY,  out, &status );+	append_easy   ( in, "TITLE",       "%T", LEVEL_ANY, out, &status );+	append_titles ( in, type, out, &status );+	append_date   ( in,               "%D", LEVEL_ANY, out, &status );+	append_easy   ( in, "VOLUME",     "%V", LEVEL_ANY, out, &status );+	append_easy   ( in, "ISSUE",      "%N", LEVEL_ANY, out, &status );+	append_easy   ( in, "NUMBER",     "%N", LEVEL_ANY, out, &status );+	append_easy   ( in, "LANGUAGE",   "%M", LEVEL_ANY, out, &status );+	append_easyall( in, "NOTES",      "%X", LEVEL_ANY, out, &status );+	append_easy   ( in, "ABSTRACT",   "%B", LEVEL_ANY, out, &status );+	append_keys   ( in, "KEYWORD",    "%K", LEVEL_ANY, out, &status );+	append_urls   ( in, out, &status );+	append_pages  ( in, out, &status );+	append_easyall( in, "DOI",        "%Y", LEVEL_ANY, out, &status );+	append_trailer( out, &status );+	append_Rtag   ( in, "%R", type, out, &status );++	return status;+}++static int+adsout_write( fields *in, FILE *fp, param *p, unsigned long refnum )+{+	int status;+	fields out;++	fields_init( &out );++	status = append_data( in, &out );+	if ( status==BIBL_OK ) output( fp, &out );++	fields_free( &out );++	return status;+}++static void adsout_writeheader( FILE *outptr, param *p ) { 	if ( p->utf8bom ) utf8_writebom( outptr );
− bibutils/adsout.h
@@ -1,22 +0,0 @@-/*- * adsout.h- *- * Copyright (c) Richard Mathar 2007-2013- * Copyright (c) Chris Putnam 2007-2013- *- * Source code released under the GPL version 2- *- */-#ifndef ADSOUT_H-#define ADSOUT_H--#include <stdio.h>-#include "bibutils.h"--extern void adsout_write( fields *info, FILE *fp, param *p,-		unsigned long refnum );-extern void adsout_writeheader( FILE *outptr, param *p );--extern void adsout_initparams( param *p, const char *progname );--#endif
bibutils/bibcore.c view
@@ -1,7 +1,7 @@ /*  * bibcore.c  *- * Copyright (c) Chris Putnam 2005-2014+ * Copyright (c) Chris Putnam 2005-2017  *  * Source code released under the GPL version 2  *@@ -13,7 +13,7 @@ /* internal includes */ #include "reftypes.h" #include "charsets.h"-#include "newstr_conv.h"+#include "str_conv.h" #include "is_ws.h"  /* illegal modes to pass in, but use internally for consistency */@@ -95,13 +95,13 @@ static int bibl_duplicateparams( param *np, param *op ) {-	int ok;-	list_init( &(np->asis) );-	list_init( &(np->corps) );-	ok = list_copy( &(np->asis), &(op->asis ) );-	if ( !ok ) return BIBL_ERR_MEMERR;-	ok = list_copy( &(np->corps), &(op->corps ) );-	if ( !ok ) return BIBL_ERR_MEMERR;+	int status;+	slist_init( &(np->asis) );+	slist_init( &(np->corps) );+	status = slist_copy( &(np->asis), &(op->asis ) );+	if ( status!=SLIST_OK ) return BIBL_ERR_MEMERR;+	status = slist_copy( &(np->corps), &(op->corps ) );+	if ( status!=SLIST_OK ) return BIBL_ERR_MEMERR; 	 	if ( !op->progname ) np->progname = NULL; 	else {@@ -190,8 +190,8 @@ bibl_freeparams( param *p ) { 	if ( p ) {-		list_free( &(p->asis) );-		list_free( &(p->corps) );+		slist_free( &(p->asis) );+		slist_free( &(p->corps) ); 		if ( p->progname ) free( p->progname ); 	} }@@ -204,10 +204,10 @@ 	if ( !p ) return BIBL_ERR_BADINPUT; 	if ( !f ) return BIBL_ERR_BADINPUT; -	status = list_fill( &(p->asis), f, 1 );+	status = slist_fill( &(p->asis), f, 1 ); -	if ( status == LIST_ERR_CANNOTOPEN ) return BIBL_ERR_CANTOPEN;-	else if ( status == 0 ) return BIBL_ERR_MEMERR;+	if ( status == SLIST_ERR_CANTOPEN ) return BIBL_ERR_CANTOPEN;+	else if ( status == SLIST_ERR_MEMERR ) return BIBL_ERR_MEMERR; 	return BIBL_OK; } @@ -219,9 +219,9 @@ 	if ( !p ) return BIBL_ERR_BADINPUT; 	if ( !f ) return BIBL_ERR_BADINPUT; -	status = list_fill( &(p->corps), f, 1 );+	status = slist_fill( &(p->corps), f, 1 ); -	if ( status == LIST_ERR_CANNOTOPEN ) return BIBL_ERR_CANTOPEN;+	if ( status == SLIST_ERR_CANTOPEN ) return BIBL_ERR_CANTOPEN; 	else if ( status == 0 ) return BIBL_ERR_MEMERR; 	return BIBL_OK; }@@ -233,12 +233,12 @@ int bibl_addtoasis( param *p, char *d ) {-	newstr *s;+	str *s;  	if ( !p ) return BIBL_ERR_BADINPUT; 	if ( !d ) return BIBL_ERR_BADINPUT; -	s = list_addc( &(p->asis), d );+	s = slist_addc( &(p->asis), d );  	return ( s==NULL )? BIBL_ERR_MEMERR : BIBL_OK; }@@ -250,12 +250,12 @@ int bibl_addtocorps( param *p, char *d ) {-	newstr *s;+	str *s;  	if ( !p ) return BIBL_ERR_BADINPUT; 	if ( !d ) return BIBL_ERR_BADINPUT; -	s = list_addc( &(p->corps), d );+	s = slist_addc( &(p->corps), d );  	return ( s==NULL )? BIBL_ERR_MEMERR : BIBL_OK; }@@ -343,23 +343,23 @@  * value = "Masters thesis"  */ static int-extract_tag_value( newstr *tag, newstr *value, char *p )+extract_tag_value( str *tag, str *value, char *p ) {-	newstr_empty( tag );+	str_empty( tag ); 	while ( p && *p && *p!='|' ) {-		newstr_addchar( tag, *p );+		str_addchar( tag, *p ); 		p++; 	}-	if ( newstr_memerr( tag ) ) return BIBL_ERR_MEMERR;+	if ( str_memerr( tag ) ) return BIBL_ERR_MEMERR;  	if ( p && *p=='|' ) p++; -	newstr_empty( value );+	str_empty( value ); 	while ( p && *p ) {-		newstr_addchar( value, *p );+		str_addchar( value, *p ); 		p++; 	}-	if ( newstr_memerr( tag ) ) return BIBL_ERR_MEMERR;+	if ( str_memerr( tag ) ) return BIBL_ERR_MEMERR;  	return BIBL_OK; }@@ -374,10 +374,10 @@ process_defaultadd( fields *f, int reftype, param *r ) { 	int i, n, process, level, status, ret = BIBL_OK;-	newstr tag, value;+	str tag, value; 	char *p; -	newstrs_init( &tag, &value, NULL );+	strs_init( &tag, &value, NULL );  	for ( i=0; i<r->all[reftype].ntags; ++i ) { @@ -404,7 +404,7 @@  	} out:-	newstrs_free( &tag, &value, NULL );+	strs_free( &tag, &value, NULL );  	return ret; }@@ -419,10 +419,10 @@ process_alwaysadd( fields *f, int reftype, param *r ) { 	int i, process, level, status, ret = BIBL_OK;-	newstr tag, value;+	str tag, value; 	char *p; -	newstrs_init( &tag, &value, NULL );+	strs_init( &tag, &value, NULL );  	for ( i=0; i<r->all[reftype].ntags; ++i ) { @@ -446,7 +446,7 @@ 	}  out:-	newstrs_free( &tag, &value, NULL );+	strs_free( &tag, &value, NULL );  	return ret; }@@ -455,11 +455,11 @@ read_ref( FILE *fp, bibl *bin, char *filename, param *p ) { 	int nrefs = 0, bufpos = 0, ok, ret=BIBL_OK, fcharset;/* = CHARSET_UNKNOWN;*/-	newstr reference, line;+	str reference, line; 	char buf[256]=""; 	fields *ref;-	newstr_init( &reference );-	newstr_init( &line );+	str_init( &reference );+	str_init( &line ); 	while ( p->readf( fp, buf, sizeof(buf), &bufpos, &line, &reference, &fcharset ) ) { 		if ( reference.len==0 ) continue; 		ref = fields_new();@@ -468,7 +468,7 @@ 			bibl_free( bin ); 			goto out; 		}-		if ( p->processf( ref, reference.data, filename, nrefs+1 )){+		if ( p->processf( ref, reference.data, filename, nrefs+1, p )){ 			ok = bibl_addref( bin, ref ); 			if ( !ok ) { 				ret = BIBL_ERR_MEMERR;@@ -481,7 +481,7 @@ 			fields_free( ref ); 			free( ref ); 		}-		newstr_empty( &reference );+		str_empty( &reference ); 		if ( fcharset!=CHARSET_UNKNOWN ) { 			/* charset from file takes priority over default, but 			 * not user-specified */@@ -494,8 +494,8 @@ 	} 	if ( p->charsetin==CHARSET_UNICODE ) p->utf8in = 1; out:-	newstr_free( &line );-	newstr_free( &reference );+	str_free( &line );+	str_free( &reference ); 	return ret; } @@ -517,7 +517,7 @@ static int bibl_fixcharsetdata( fields *ref, param *p ) {-	newstr *data;+	str *data; 	char *tag; 	long i, n; 	int ok;@@ -530,11 +530,11 @@ 		data = fields_value( ref, i, FIELDS_STRP_NOUSE );  		if ( bibl_notexify( tag ) ) {-			ok = newstr_convert( data,+			ok = str_convert( data, 				p->charsetin,  0, p->utf8in,  p->xmlin, 				p->charsetout, 0, p->utf8out, p->xmlout ); 		} else {-			ok = newstr_convert( data,+			ok = str_convert( data, 				p->charsetin,  p->latexin,  p->utf8in,  p->xmlin, 				p->charsetout, p->latexout, p->utf8out, p->xmlout ); 		}@@ -564,16 +564,16 @@ { 	char *year, *author, *p, num[512]; 	int status, ret = BIBL_OK;-	newstr refnum;+	str refnum;  	*n = -1; -	newstr_init( &refnum );+	str_init( &refnum ); -	year = fields_findv( f, LEVEL_MAIN, FIELDS_CHRP_NOUSE, "YEAR" );+	year = fields_findv( f, LEVEL_MAIN, FIELDS_CHRP_NOUSE, "DATE:YEAR" ); 	if ( !year ) 		year = fields_findv_firstof( f, LEVEL_ANY, FIELDS_CHRP_NOUSE,-			"YEAR", "PARTYEAR", NULL );+			"DATE:YEAR", "PARTDATE:YEAR", NULL );  	author = fields_findv( f, LEVEL_MAIN, FIELDS_CHRP_NOUSE, "AUTHOR" ); 	if ( !author )@@ -583,15 +583,15 @@ 	if ( year && author ) { 		p = author; 		while ( *p && *p!='|' )-			newstr_addchar( &refnum, *p++ );+			str_addchar( &refnum, *p++ ); 		p = year; 		while ( *p && *p!=' ' && *p!='\t' )-			newstr_addchar( &refnum, *p++ );+			str_addchar( &refnum, *p++ ); 	} else { 		sprintf( num, "%ld", nrefs );-		newstr_mergestrs( &refnum, "ref", num, NULL );+		str_mergestrs( &refnum, "ref", num, NULL ); 	}-	if ( newstr_memerr( &refnum ) ) {+	if ( str_memerr( &refnum ) ) { 		ret = BIBL_ERR_MEMERR; 		goto out; 	}@@ -601,7 +601,7 @@ 	else *n = fields_find( f, "REFNUM", 0 );  out:-	newstr_free( &refnum );+	str_free( &refnum );  	return ret; }@@ -623,8 +623,8 @@ 		} 		if ( p->addcount ) { 			sprintf( buf, "_%ld", i+1 );-			newstr_strcat( &(ref->data[n]), buf );-			if ( newstr_memerr( &(ref->data[n]) ) )+			str_strcatc( &(ref->data[n]), buf );+			if ( str_memerr( &(ref->data[n]) ) ) 				return BIBL_ERR_MEMERR; 		} 	}@@ -637,28 +637,28 @@ { 	int n1, n2, status, ret; 	char *p, buf[100];-	newstr citekey;+	str citekey; -	newstr_init( &citekey );+	str_init( &citekey );  	n1 = fields_find( f, "AUTHOR", 0 ); 	if ( n1==-1 ) n1 = fields_find( f, "AUTHOR", -1 );-	n2 = fields_find( f, "YEAR", 0 );-	if ( n2==-1 ) n2 = fields_find( f, "YEAR", -1 );-	if ( n2==-1 ) n2 = fields_find( f, "PARTYEAR", 0 );-	if ( n2==-1 ) n2 = fields_find( f, "PARTYEAR", -1 );+	n2 = fields_find( f, "DATE:YEAR", 0 );+	if ( n2==-1 ) n2 = fields_find( f, "DATE:YEAR", -1 );+	if ( n2==-1 ) n2 = fields_find( f, "PARTDATE:YEAR", 0 );+	if ( n2==-1 ) n2 = fields_find( f, "PARTDATE:YEAR", -1 ); 	if ( n1!=-1 && n2!=-1 ) { 		p = f->data[n1].data; 		while ( p && *p && *p!='|' ) {-			if ( !is_ws( *p ) ) newstr_addchar( &citekey, *p ); +			if ( !is_ws( *p ) ) str_addchar( &citekey, *p );  			p++; 		} 		p = f->data[n2].data; 		while ( p && *p ) {-			if ( !is_ws( *p ) ) newstr_addchar( &citekey, *p );+			if ( !is_ws( *p ) ) str_addchar( &citekey, *p ); 			p++; 		}-		if ( newstr_memerr( &citekey ) ) {+		if ( str_memerr( &citekey ) ) { 			ret = -1; 			goto out; 		}@@ -669,41 +669,41 @@ 		} 	} else { 		sprintf( buf, "ref%d\n", nref );-		newstr_strcpy( &citekey, buf );+		str_strcpyc( &citekey, buf ); 	} 	ret = fields_find( f, "REFNUM", -1 ); out:-	newstr_free( &citekey );+	str_free( &citekey ); 	return ret; }  static int-resolve_citekeys( bibl *b, list *citekeys, int *dup )+resolve_citekeys( bibl *b, slist *citekeys, int *dup ) { 	const char abc[]="abcdefghijklmnopqrstuvwxyz"; 	int nsame, ntmp, n, i, j, status = BIBL_OK;-	newstr tmp;+	str tmp; -	newstr_init( &tmp );+	str_init( &tmp );  	for ( i=0; i<citekeys->n; ++i ) { 		if ( dup[i]==-1 ) continue; 		nsame = 0; 		for ( j=i; j<citekeys->n; ++j ) { 			if ( dup[j]!=i ) continue;-			newstr_newstrcpy( &tmp, &(citekeys->str[j]) );-			if ( newstr_memerr( &tmp ) ) {+			str_strcpy( &tmp, slist_str( citekeys, j ) );+			if ( str_memerr( &tmp ) ) { 				status = BIBL_ERR_MEMERR; 				goto out; 			} 			ntmp = nsame; 			while ( ntmp >= 26 ) {-				newstr_addchar( &tmp, 'a' );+				str_addchar( &tmp, 'a' ); 					ntmp -= 26; 			} 			if ( ntmp<26 && ntmp>=0 )-			newstr_addchar( &tmp, abc[ntmp] );-			if ( newstr_memerr( &tmp ) ) {+			str_addchar( &tmp, abc[ntmp] );+			if ( str_memerr( &tmp ) ) { 				status = BIBL_ERR_MEMERR; 				goto out; 			}@@ -711,8 +711,8 @@ 			dup[j] = -1; 			n = fields_find( b->ref[j], "REFNUM", -1 ); 			if ( n!=-1 ) {-				newstr_newstrcpy(&((b->ref[j])->data[n]),&tmp);-				if ( newstr_memerr( &((b->ref[j])->data[n]) ) ) {+				str_strcpy(&((b->ref[j])->data[n]),&tmp);+				if ( str_memerr( &((b->ref[j])->data[n]) ) ) { 					status = BIBL_ERR_MEMERR; 					goto out; 				}@@ -720,25 +720,25 @@ 		} 	} out:-	newstr_free( &tmp );+	str_free( &tmp ); 	return status; }  static int-get_citekeys( bibl *b, list *citekeys )+get_citekeys( bibl *b, slist *citekeys ) {-	newstr *s; 	fields *f; 	int i, n;+	str *s; 	for ( i=0; i<b->nrefs; ++i ) { 		f = b->ref[i]; 		n = fields_find( f, "REFNUM", -1 ); 		if ( n==-1 ) n = generate_citekey( f, i ); 		if ( n!=-1 && f->data[n].data ) {-			s = list_add( citekeys, &(f->data[n]) );+			s = slist_add( citekeys, &(f->data[n]) ); 			if ( !s ) return BIBL_ERR_MEMERR; 		} else {-			s = list_addc( citekeys, "" );+			s = slist_addc( citekeys, "" ); 			if ( !s ) return BIBL_ERR_MEMERR; 		} 	}@@ -746,7 +746,7 @@ }  static int -dup_citekeys( bibl *b, list *citekeys )+dup_citekeys( bibl *b, slist *citekeys ) { 	int i, j, status = BIBL_OK, *dup, ndup=0; @@ -757,8 +757,8 @@ 	for ( i=0; i<citekeys->n-1; ++i ) { 		if ( dup[i]!=-1 ) continue; 		for ( j=i+1; j<citekeys->n; ++j ) {-			if ( !strcmp( citekeys->str[i].data, -				citekeys->str[j].data ) ) {+			if ( !strcmp( slist_cstr( citekeys, i ),+			              slist_cstr( citekeys, j ) ) ) { 					dup[i] = i; 					dup[j] = i; 					ndup++;@@ -773,14 +773,14 @@ static int uniqueify_citekeys( bibl *b ) {-	list citekeys;+	slist citekeys; 	int status;-	list_init( &citekeys );+	slist_init( &citekeys ); 	status = get_citekeys( b, &citekeys ); 	if ( status!=BIBL_OK ) goto out; 	status = dup_citekeys( b, &citekeys ); out:-	list_free( &citekeys );+	slist_free( &citekeys ); 	return status; } @@ -803,8 +803,8 @@ 		rout = fields_new(); 		if ( !rout ) return BIBL_ERR_MEMERR; 		if ( p->typef ) -			reftype = p->typef( rin, fname, i+1, p, p->all, p->nall );-		status = p->convertf( rin, rout, reftype, p, p->all, p->nall );+			reftype = p->typef( rin, fname, i+1, p );+		status = p->convertf( rin, rout, reftype, p ); 		if ( status!=BIBL_OK ) return status; 		if ( p->all ) { 			status = process_alwaysadd( rout, reftype, p );@@ -815,6 +815,13 @@ 		ok = bibl_addref( bout, rout ); 		if ( !ok ) return BIBL_ERR_MEMERR; 	}+	if ( debug_set( p ) ) {+		fflush( stdout );+		fprintf( stderr, "-------------------start for convert_ref\n");+		bibl_verbose0( bout );+		fprintf( stderr, "-------------------end for convert_ref\n" );+		fflush( stderr );+	} 	status = uniqueify_citekeys( bout ); 	return status; }@@ -838,7 +845,10 @@ 	bibl_init( &bin );  	status = read_ref( fp, &bin, filename, &lp );-	if ( status!=BIBL_OK ) return status;+	if ( status!=BIBL_OK ) {+		bibl_freeparams( &lp );+		return status;+	}  	if ( debug_set( p ) ) { 		fflush( stdout );@@ -884,13 +894,18 @@ 			fflush( stderr ); 		} 		ok = bibl_copy( b, &bin );-		if ( !ok ) return BIBL_ERR_MEMERR;+		if ( !ok ) {+			bibl_freeparams( &lp );+			return BIBL_ERR_MEMERR;+		} 	} 	if ( !lp.output_raw || ( lp.output_raw & BIBL_RAW_WITHMAKEREFID ) ) 		bibl_checkrefid( b, &lp );  	bibl_free( &bin ); +	bibl_freeparams( &lp );+ 	return BIBL_OK; } @@ -932,14 +947,16 @@ static int bibl_writeeachfp( FILE *fp, bibl *b, param *p ) {+	int status; 	long i; 	for ( i=0; i<b->nrefs; ++i ) { 		fp = singlerefname( b->ref[i], i, p->writeformat ); 		if ( !fp ) return BIBL_ERR_CANTOPEN; 		if ( p->headerf ) p->headerf( fp, p );-		p->writef( b->ref[i], fp, p, i );+		status = p->writef( b->ref[i], fp, p, i ); 		if ( p->footerf ) p->footerf( fp ); 		fclose( fp );+		if ( status!=BIBL_OK ) return status; 	} 	return BIBL_OK; }@@ -947,12 +964,15 @@ static int bibl_writefp( FILE *fp, bibl *b, param *p ) {+	int status = BIBL_OK; 	long i; 	if ( p->headerf ) p->headerf( fp, p );-	for ( i=0; i<b->nrefs; ++i )-		p->writef( b->ref[i], fp, p, i );+	for ( i=0; i<b->nrefs; ++i ) {+		status = p->writef( b->ref[i], fp, p, i );+		if ( status!=BIBL_OK ) break;+	} 	if ( p->footerf ) p->footerf( fp );-	return BIBL_OK;+	return status; }  int@@ -972,10 +992,19 @@ 	status = bibl_fixcharsets( b, &lp ); 	if ( status!=BIBL_OK ) return status; -	if ( debug_set( p ) ) report_params( stderr, "bibl_write", &lp );+	if ( debug_set( p ) ) {+		report_params( stderr, "bibl_write", &lp );+		fflush( stdout );+		fprintf( stderr, "-------------------start for bibl_write\n");+		bibl_verbose0( b );+		fprintf( stderr, "-------------------end for bibl_write\n" );+		fflush( stderr );+	}  	if ( p->singlerefperfile ) status = bibl_writeeachfp( fp, b, &lp ); 	else status = bibl_writefp( fp, b, &lp );++	bibl_freeparams( &lp );  	return status; }
+ bibutils/bibformats.h view
@@ -0,0 +1,35 @@+/*+ * bibformats.h+ *+ * Copyright (c) Chris Putnam 2007-2017+ *+ * Source code released under the GPL version 2+ *+ */+#ifndef BIBFORMATS_H+#define BIBFORMATS_H++#include "bibutils.h"++void adsout_initparams(     param *p, const char *progname );+void biblatexin_initparams( param *p, const char *progname );+void bibtexin_initparams(   param *p, const char *progname );+void bibtexout_initparams(  param *p, const char *progname );+void copacin_initparams(    param *p, const char *progname );+void ebiin_initparams(      param *p, const char *progname );+void endin_initparams(      param *p, const char *progname );+void endout_initparams(     param *p, const char *progname );+void endxmlin_initparams(   param *p, const char *progname );+void isiin_initparams(      param *p, const char *progname );+void isiout_initparams(     param *p, const char *progname );+void medin_initparams(      param *p, const char *progname );+void modsin_initparams(     param *p, const char *progname );+void modsout_initparams(    param *p, const char *progname );+void nbibin_initparams(      param *p, const char *progname );+void risin_initparams(      param *p, const char *progname );+void risout_initparams(     param *p, const char *progname );+void wordin_initparams(     param *p, const char *progname );+void wordout_initparams(    param *p, const char *progname );++#endif+
bibutils/bibl.c view
@@ -1,7 +1,7 @@ /*  * bibl.c  *- * Copyright (c) Chris Putnam 2005-2014+ * Copyright (c) Chris Putnam 2005-2017  *  * Source code released under the GPL version 2  *@@ -92,7 +92,7 @@ 			value = fields_value( refin, j, FIELDS_CHRP ); 			level = fields_level( refin, j ); 			if ( tag && value ) {-				status = fields_add( refout, tag, value, level );+				status = fields_add_can_dup( refout, tag, value, level ); 				if ( status!=FIELDS_OK ) return 0; 			} 		}
bibutils/bibl.h view
@@ -1,7 +1,7 @@ /*  * bibl.h  *- * Copyright (c) Chris Putnam 2005-2014+ * Copyright (c) Chris Putnam 2005-2017  *  * Source code released under the GPL version 2  *@@ -10,7 +10,7 @@ #define BIBL_H  #include <stdio.h>-#include "newstr.h"+#include "str.h" #include "fields.h" #include "reftypes.h" 
bibutils/biblatexin.c view
@@ -1,1412 +1,1300 @@ /*  * biblatexin.c  *- * Copyright (c) Chris Putnam 2008-2014- * Copyright (c) Johannes Wilm 2010-2014- *- * Program and source code released under the GPL version 2- *- */-#include <stdio.h>-#include <stdlib.h>-#include <string.h>-#include <ctype.h>-#include "is_ws.h"-#include "strsearch.h"-#include "newstr.h"-#include "newstr_conv.h"-#include "fields.h"-#include "list.h"-#include "name.h"-#include "reftypes.h"-#include "biblatexin.h"--extern const char progname[];--static list find    = { 0, 0, NULL, 0 };-static list replace = { 0, 0, NULL, 0 };--/*****************************************************- PUBLIC: void biblatexin_initparams()-*****************************************************/--void-biblatexin_initparams( param *p, const char *progname )-{-	p->readformat       = BIBL_BIBLATEXIN;-	p->charsetin        = BIBL_CHARSET_DEFAULT;-	p->charsetin_src    = BIBL_SRC_DEFAULT;-	p->latexin          = 1;-	p->xmlin            = 0;-	p->utf8in           = 0;-	p->nosplittitle     = 0;-	p->verbose          = 0;-	p->addcount         = 0;-	p->output_raw       = 0;--	p->readf    = biblatexin_readf;-	p->processf = biblatexin_processf;-	p->cleanf   = biblatexin_cleanf;-	p->typef    = biblatexin_typef;-	p->convertf = biblatexin_convertf;-	p->all      = biblatex_all;-	p->nall     = biblatex_nall;--	list_init( &(p->asis) );-	list_init( &(p->corps) );--	if ( !progname ) p->progname = NULL;-	else p->progname = strdup( progname );-}--/*****************************************************- PUBLIC: int biblatexin_readf()-*****************************************************/--/*- * readf can "read too far", so we store this information in line, thus- * the next new text is in line, either from having read too far or- * from the next chunk obtained via newstr_fget()- *- * return 1 on success, 0 on error/end-of-file- *- */-static int-readmore( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line )-{-	if ( line->len ) return 1;-	else return newstr_fget( fp, buf, bufsize, bufpos, line );-}--/*- * readf()- *- * returns zero if cannot get reference and hit end of-file- * returns 1 if last reference in file, 2 if reference within file- */-int-biblatexin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset )-{-	int haveref = 0;-	char *p;-	while ( haveref!=2 && readmore( fp, buf, bufsize, bufpos, line ) ) {-		if ( line->len == 0 ) continue; /* blank line */-		p = &(line->data[0]);-		p = skip_ws( p );-		if ( *p == '%' ) { /* commented out line */-			newstr_empty( line );-			continue;-		}-		if ( *p == '@' ) haveref++;-		if ( haveref && haveref<2 ) {-			newstr_strcat( reference, p );-			newstr_addchar( reference, '\n' );-			newstr_empty( line );-		} else if ( !haveref ) newstr_empty( line );-	-	}-	*fcharset = CHARSET_UNKNOWN;-	return haveref;-}--/*****************************************************- PUBLIC: int biblatexin_processf()-*****************************************************/--static char *-process_biblatextype( char *p, newstr *type )-{-	newstr tmp;-	newstr_init( &tmp );--	if ( *p=='@' ) p++;-	p = newstr_cpytodelim( &tmp, p, "{( \t\r\n", 0 );-	p = skip_ws( p );-	if ( *p=='{' || *p=='(' ) p++;-	p = skip_ws( p );--	if ( tmp.len ) newstr_strcpy( type, tmp.data );-	else newstr_empty( type );--	newstr_free( &tmp );-	return p;-}--static char *-process_biblatexid( char *p, newstr *id )-{-	char *start_p = p;-	newstr tmp;--	newstr_init( &tmp );-	p = newstr_cpytodelim( &tmp, p, ",", 1 );--	if ( tmp.len ) {-		if ( strchr( tmp.data, '=' ) ) {-			/* Endnote writes biblatex files w/o fields, try to-			 * distinguish via presence of an equal sign.... if-			 * it's there, assume that it's a tag/data pair instead-			 * and roll back.-			 */-			p = start_p;-			newstr_empty( id );-		} else {-			newstr_strcpy( id, tmp.data );-		}-	} else {-		newstr_empty( id );-	}--	newstr_free( &tmp );-	return skip_ws( p );-}--static char *-biblatex_tag( char *p, newstr *tag )-{-	p = newstr_cpytodelim( tag, skip_ws( p ), "= \t\r\n", 0 );-	return skip_ws( p );-}--static char *-biblatex_data( char *p, fields *bibin, list *tokens )-{-	unsigned int nbracket = 0, nquotes = 0;-	char *startp = p;-	newstr tok, *s;--	newstr_init( &tok );-	while ( p && *p ) {-		if ( !nquotes && !nbracket ) {-			if ( *p==',' || *p=='=' || *p=='}' || *p==')' )-				goto out;-		}-		if ( *p=='\"' && nbracket==0 && ( p==startp || *(p-1)!='\\' ) ) {-			nquotes = !nquotes;-			newstr_addchar( &tok, *p );-			if ( !nquotes ) {-				s = list_add( tokens, &tok );-				if ( !s ) { p = NULL; goto outerr; }-				newstr_empty( &tok );-			}-		} else if ( *p=='#' && !nquotes && !nbracket ) {-			if ( tok.len ) {-				s = list_add( tokens, &tok );-				if ( !s ) { p = NULL; goto outerr; }-			}-			newstr_strcpy( &tok, "#" );-			s = list_add( tokens, &tok );-			if ( !s ) { p = NULL; goto outerr; }-			newstr_empty( &tok );-		} else if ( *p=='{' && !nquotes && ( p==startp || *(p-1)!='\\' ) ) {-			nbracket++;-			newstr_addchar( &tok, *p );-		} else if ( *p=='}' && !nquotes && ( p==startp || *(p-1)!='\\' ) ) {-			nbracket--;-			newstr_addchar( &tok, *p );-			if ( nbracket==0 ) {-				s = list_add( tokens, &tok );-				if ( !s ) { p = NULL; goto outerr; }-				newstr_empty( &tok );-			}-		} else if ( !is_ws( *p ) || nquotes || nbracket ) {-			if ( !is_ws( *p ) ) newstr_addchar( &tok, *p );-			else {-				if ( tok.len!=0 && *p!='\n' && *p!='\r' )-					newstr_addchar( &tok, *p );-				else if ( tok.len!=0 && (*p=='\n' || *p=='\r')) {-					newstr_addchar( &tok, ' ' );-					while ( is_ws( *(p+1) ) ) p++;-				}-			}-		} else if ( is_ws( *p ) ) {-			if ( tok.len ) {-				s = list_add( tokens, &tok );-				if ( !s ) { p = NULL; goto outerr; }-				newstr_empty( &tok );-			}-		}-		p++;-	}-out:-	if ( nbracket!=0 ) {-		fprintf( stderr, "%s: Mismatch in number of brackets in reference.\n", progname );-	}-	if ( nquotes!=0 ) {-		fprintf( stderr, "%s: Mismatch in number of quotes in reference.\n", progname );-	}-	if ( tok.len ) {-		s = list_add( tokens, &tok );-		if ( !s ) p = NULL;-	}-outerr:-	newstr_free( &tok );-	return p;-}--/* replace_strings()- *- * do string replacement -- only if unprotected by quotation marks or curly brackets- */-static void-replace_strings( list *tokens, fields *bibin )-{-	int i, n, ok;-	newstr *s;-	char *q;-	i = 0;-	while ( i < tokens->n ) {-		s = list_get( tokens, i );-		if ( !strcmp( s->data, "#" ) ) {-		} else if ( s->data[0]!='\"' && s->data[0]!='{' ) {-			n = list_find( &find, s->data );-			if ( n!=-1 ) {-				newstr_newstrcpy( s, list_get( &replace, n ) );-			} else {-				q = s->data;-				ok = 1;-				while ( *q && ok ) {-					if ( !isdigit( *q ) ) ok = 0;-					q++;-				}-				if ( !ok ) {-					fprintf( stderr, "%s: Warning: Non-numeric "-					   "BibTeX elements should be in quotations or "-					   "curly brackets in reference.\n", progname );-				}-			}-		}-		i++;-	}-}--static int-string_concatenate( list *tokens, fields *bibin )-{-	int i, status;-	newstr *s, *t;-	i = 0;-	while ( i < tokens->n ) {-		s = list_get( tokens, i );-		if ( !strcmp( s->data, "#" ) ) {-			if ( i==0 || i==tokens->n-1 ) {-				fprintf( stderr, "%s: Warning: Stray string concatenation "-					"('#' character) in reference\n", progname );-				status = list_remove( tokens, i );-				if ( status!=LIST_OK ) return BIBL_ERR_MEMERR;-				continue;-			}-			s = list_get( tokens, i-1 );-			if ( s->data[0]!='\"' && s->data[s->len-1]!='\"' )-				fprintf( stderr, "%s: Warning: String concentation should "-					"be used in context of quotations marks.\n", progname );-			t = list_get( tokens, i+1 );-			if ( t->data[0]!='\"' && t->data[s->len-1]!='\"' )-				fprintf( stderr, "%s: Warning: String concentation should "-					"be used in context of quotations marks.\n", progname );-			if ( ( s->data[s->len-1]=='\"' && t->data[0]=='\"') || (s->data[s->len-1]=='}' && t->data[0]=='{') ) {-				newstr_trimend( s, 1 );-				newstr_trimbegin( t, 1 );-				newstr_newstrcat( s, t );-			} else {-				newstr_newstrcat( s, t );-			}-			status = list_remove( tokens, i );-			if ( status!=LIST_OK ) return BIBL_ERR_MEMERR;-			status = list_remove( tokens, i );-			if ( status!=LIST_OK ) return BIBL_ERR_MEMERR;-		} else i++;-	}-	return BIBL_OK;-}--static char *-process_biblatexline( char *p, newstr *tag, newstr *data, uchar stripquotes )-{-	int i, status;-	list tokens;-	newstr *s;--	newstr_empty( data );--	p = biblatex_tag( p, tag );-	if ( tag->len==0 ) return p;--	list_init( &tokens );--	if ( *p=='=' ) p = biblatex_data( p+1, NULL, &tokens );--	replace_strings( &tokens, NULL );--	status = string_concatenate( &tokens, NULL );-	if ( status!=BIBL_OK ) {-		p = NULL;-		goto out;-	}--	for ( i=0; i<tokens.n; i++ ) {-		s = list_get( &tokens, i );-		if ( ( stripquotes && s->data[0]=='\"' && s->data[s->len-1]=='\"' ) ||-		     ( s->data[0]=='{' && s->data[s->len-1]=='}' ) ) {-			newstr_trimbegin( s, 1 );-			newstr_trimend( s, 1 );-		}-		newstr_newstrcat( data, list_get( &tokens, i ) );-	}-out:-	list_free( &tokens );-	return p;-}--static int-process_cite( fields *bibin, char *p, char *filename, long nref )-{-	int fstatus, status = BIBL_OK;-	newstr tag, data;-	newstrs_init( &tag, &data, NULL );-	p = process_biblatextype( p, &data );-	if ( data.len ) {-		fstatus = fields_add( bibin, "INTERNAL_TYPE", data.data, 0 );-		if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }-	}-	p = process_biblatexid ( p, &data );-	if ( data.len ) {-		fstatus = fields_add( bibin, "REFNUM", data.data, 0 );-		if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }-	}-	while ( *p ) {-		p = process_biblatexline( p, &tag, &data, 1 );-		if ( !p ) { status = BIBL_ERR_MEMERR; goto out; }-		/* no anonymous or empty fields allowed */-		if ( tag.len && data.len ) {-			fstatus = fields_add( bibin, tag.data, data.data, 0 );-			if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }-		}-		newstrs_empty( &tag, &data, NULL );-	}-out:-	newstrs_free( &tag, &data, NULL );-	return status;-}--/* process_string()- *- * Handle lines like:- *- * '@STRING{TL = {Tetrahedron Lett.}}'- *- * p should point to just after '@STRING'- *- * In BibTeX, if a string is defined several times, the last one is kept.- *- */-static int-process_string( char *p )-{-	int n, status = BIBL_OK;-	newstr s1, s2, *s;-	newstrs_init( &s1, &s2, NULL );-	while ( *p && *p!='{' && *p!='(' ) p++;-	if ( *p=='{' || *p=='(' ) p++;-	p = process_biblatexline( skip_ws( p ), &s1, &s2, 0 );-	if ( s2.data ) {-		newstr_findreplace( &s2, "\\ ", " " );-		if ( newstr_memerr( &s2 ) ) { status = BIBL_ERR_MEMERR; goto out; }-	}-	if ( s1.data ) {-		n = list_find( &find, s1.data );-		if ( n==-1 ) {-			s = list_add( &find, &s1 );-			if ( s==NULL ) { status = BIBL_ERR_MEMERR; goto out; }-			if ( s2.data ) s = list_add( &replace, &s2 );-			else s = list_addc( &replace, "" );-			if ( s==NULL ) { status = BIBL_ERR_MEMERR; goto out; }-		} else {-			if ( s2.data ) s = list_set( &replace, n, &s2 );-			else s = list_setc( &replace, n, "" );-			if ( s==NULL ) { status = BIBL_ERR_MEMERR; goto out; }-		}-	}-out:-	newstrs_free( &s1, &s2, NULL );-	return status;-}--int-biblatexin_processf( fields *bibin, char *data, char *filename, long nref )-{-	if ( !strncasecmp( data, "@STRING", 7 ) ) {-		process_string( data+7 );-		return 0;-        } else {-		process_cite( bibin, data, filename, nref );-		return 1;-	}-}--/*****************************************************- PUBLIC: void biblatexin_cleanf()-*****************************************************/--static void-biblatex_process_tilde( newstr *s )-{-	char *p, *q;-	int n = 0;--	p = q = s->data;-	if ( !p ) return;-	while ( *p ) {-		if ( *p=='~' ) {-			*q = ' ';-		} else if ( *p=='\\' && *(p+1)=='~' ) {-			n++;-			p++;-			*q = '~';-		} else {-			*q = *p;-		}-		p++;-		q++;-	}-	*q = '\0';-	s->len -= n;-}--static void-biblatex_process_bracket( newstr *s )-{-	char *p, *q;-	int n = 0;--	p = q = s->data;-	if ( !p ) return;-	while ( *p ) {-		if ( *p=='\\' && ( *(p+1)=='{' || *(p+1)=='}' ) ) {-			n++;-			p++;-			*q = *p;-			q++;-		} else if ( *p=='{' || *p=='}' ) {-			n++;-		} else {-			*q = *p;-			q++;-		}-		p++;-	}-	*q = '\0';-	s->len -= n;-}--static int-biblatex_cleantoken( newstr *s )-{-	/* 'textcomp' annotations */-	newstr_findreplace( s, "\\textit", "" );-	newstr_findreplace( s, "\\textbf", "" );-	newstr_findreplace( s, "\\textsl", "" );-	newstr_findreplace( s, "\\textsc", "" );-	newstr_findreplace( s, "\\textsf", "" );-	newstr_findreplace( s, "\\texttt", "" );-	newstr_findreplace( s, "\\textsubscript", "" );-	newstr_findreplace( s, "\\textsuperscript", "" );-	newstr_findreplace( s, "\\emph", "" );-	newstr_findreplace( s, "\\url", "" );--	/* Other text annotations */-	newstr_findreplace( s, "\\it ", "" );-	newstr_findreplace( s, "\\em ", "" );--	newstr_findreplace( s, "\\%", "%" );-	newstr_findreplace( s, "\\$", "$" );-	while ( newstr_findreplace( s, "  ", " " ) ) {}--	/* 'textcomp' annotations that we don't want to substitute on output*/-	newstr_findreplace( s, "\\textdollar", "$" );-	newstr_findreplace( s, "\\textunderscore", "_" );--	biblatex_process_bracket( s );-	biblatex_process_tilde( s );--	if ( !newstr_memerr( s ) ) return BIBL_OK;-	else return BIBL_ERR_MEMERR;-}--static int-biblatex_split( list *tokens, newstr *s )-{-	int i, n = s->len, nbrackets = 0, status = BIBL_OK;-	newstr tok, *t;--	newstr_init( &tok );--	for ( i=0; i<n; ++i ) {-		if ( s->data[i]=='{' && ( i==0 || s->data[i-1]!='\\' ) ) {-			nbrackets++;-			newstr_addchar( &tok, '{' );-		} else if ( s->data[i]=='}' && ( i==0 || s->data[i-1]!='\\' ) ) {-			nbrackets--;-			newstr_addchar( &tok, '}' );-		} else if ( !is_ws( s->data[i] ) || nbrackets ) {-			newstr_addchar( &tok, s->data[i] );-		} else if ( is_ws( s->data[i] ) ) {-			if ( newstr_memerr( &tok ) ) { status = BIBL_ERR_MEMERR; goto out; }-			if ( tok.len ) {-				t = list_add( tokens, &tok );-				if ( !t ) { status = BIBL_ERR_MEMERR; goto out; }-			}-			newstr_empty( &tok );-		}-	}-	if ( tok.len ) {-		if ( newstr_memerr( &tok ) ) { status = BIBL_ERR_MEMERR; goto out; }-		t = list_add( tokens, &tok );-		if ( !t ) { status = BIBL_ERR_MEMERR; goto out; }-	}--	for ( i=0; i<tokens->n; ++i ) {-		t = list_get( tokens, i );-		newstr_trimstartingws( t );-		newstr_trimendingws( t );-		if ( newstr_memerr( t ) ) { status = BIBL_ERR_MEMERR; goto out; }-	}-out:-	newstr_free( &tok );-	return status;-}--static int-biblatexin_addtitleurl( fields *info, newstr *in )-{-	int fstatus, status = BIBL_OK;-	newstr s;-	char *p;--	newstr_init( &s );-	/* skip past "\href{" */-	p = newstr_cpytodelim( &s, in->data + 6, "}", 1 );-	if ( newstr_memerr( &s ) ) {-		status = BIBL_ERR_MEMERR;-		goto out;-	}-	fstatus = fields_add( info, "URL", s.data, 0 );-	if ( fstatus!=FIELDS_OK ) {-		status = BIBL_ERR_MEMERR;-		goto out;-	}--	p = newstr_cpytodelim( &s, p, "", 0 );-	if ( newstr_memerr( &s ) ) {-		status = BIBL_ERR_MEMERR;-		goto out;-	}-	newstr_swapstrings( &s, in );-out:-	newstr_free( &s );-	return status;-}--static int-is_name_tag( newstr *tag )-{-	if ( tag->len ) {-		if ( !strcasecmp( tag->data, "author" ) ) return 1;-		if ( !strcasecmp( tag->data, "editor" ) ) return 1;-		if ( !strcasecmp( tag->data, "editorb" ) ) return 1;-		if ( !strcasecmp( tag->data, "editorc" ) ) return 1;-		if ( !strcasecmp( tag->data, "director" ) ) return 1;-		if ( !strcasecmp( tag->data, "producer" ) ) return 1;-		if ( !strcasecmp( tag->data, "execproducer" ) ) return 1;-		if ( !strcasecmp( tag->data, "writer" ) ) return 1;-		if ( !strcasecmp( tag->data, "redactor" ) ) return 1;-		if ( !strcasecmp( tag->data, "annotator" ) ) return 1;-		if ( !strcasecmp( tag->data, "commentator" ) ) return 1;-		if ( !strcasecmp( tag->data, "translator" ) ) return 1;-		if ( !strcasecmp( tag->data, "foreword" ) ) return 1;-		if ( !strcasecmp( tag->data, "afterword" ) ) return 1;-		if ( !strcasecmp( tag->data, "introduction" ) ) return 1;-	}-	return 0;-}--static int-is_url_tag( newstr *tag )-{-	if ( tag->len ) {-		if ( !strcasecmp( tag->data, "url" ) ) return 1;-	}-	return 0;-}--static int-biblatexin_cleandata( newstr *tag, newstr *s, fields *info, param *p )-{-	list tokens;-	newstr *tok;-	int i, status = BIBL_OK;-	if ( !s->len ) return status;-	/* protect url from undergoing any parsing */-	if ( is_url_tag( tag ) ) return status;-	list_init( &tokens );-	biblatex_split( &tokens, s );-	for ( i=0; i<tokens.n; ++i ) {-		if (!strncasecmp(tokens.str[i].data,"\\href{", 6)) {-			status = biblatexin_addtitleurl( info, &(tokens.str[i]) );-			if ( status!=BIBL_OK ) goto out;-		}-		if ( p && p->latexin && !is_name_tag( tag ) ) {-			status = biblatex_cleantoken( &(tokens.str[i]) );-			if ( status!=BIBL_OK ) goto out;-		}-	}-	newstr_empty( s );-	for ( i=0; i<tokens.n; ++i ) {-		tok = list_get( &tokens, i );-		if ( i>0 ) newstr_addchar( s, ' ' );-		newstr_newstrcat( s, tok );-	}-out:-	list_free( &tokens );-	return status;-}--static long-biblatexin_findref( bibl *bin, char *citekey )-{-	int n;-	long i;-	for ( i=0; i<bin->nrefs; ++i ) {-		n = fields_find( bin->ref[i], "refnum", -1 );-		if ( n==-1 ) continue;-		if ( !strcmp( bin->ref[i]->data[n].data, citekey ) ) return i;-	}-	return -1;-}--static void-biblatexin_nocrossref( bibl *bin, long i, int n, param *p )-{-	int n1 = fields_find( bin->ref[i], "REFNUM", -1 );-	if ( p->progname ) fprintf( stderr, "%s: ", p->progname );-	fprintf( stderr, "Cannot find cross-reference '%s'", -			bin->ref[i]->data[n].data);-	if ( n1!=-1 )-		fprintf( stderr, " for reference '%s'\n", -				bin->ref[i]->data[n1].data );-	fprintf( stderr, "\n" );-}--static int-biblatexin_crossref_oneref( fields *ref, fields *cross )-{-	int j, nl, ntype, fstatus;-	char *type, *nt, *nd;-	ntype = fields_find( ref, "INTERNAL_TYPE", -1 );-	type = ( char * ) fields_value( ref, ntype, FIELDS_CHRP_NOUSE );-	for ( j=0; j<cross->n; ++j ) {-		nt = ( char * ) fields_tag( cross, j, FIELDS_CHRP_NOUSE );-		if ( !strcasecmp( nt, "INTERNAL_TYPE" ) ) continue;-		if ( !strcasecmp( nt, "REFNUM" ) ) continue;-		if ( !strcasecmp( nt, "TITLE" ) ) {-			if ( !strcasecmp( type, "Inproceedings" ) ||-			     !strcasecmp( type, "Incollection" ) )-				nt = "booktitle";-		}-		nd = ( char * ) fields_value( cross, j, FIELDS_CHRP_NOUSE );-		nl = fields_level( cross, j ) + 1;-		fstatus = fields_add( ref, nt, nd, nl );-		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;-	}-	return BIBL_OK;-}--static int-biblatexin_crossref( bibl *bin, param *p )-{-	int n, ncross, status = BIBL_OK;-	fields *ref, *cross;-	long i;-        for ( i=0; i<bin->nrefs; ++i ) {-		ref = bin->ref[i];-		n = fields_find( ref, "CROSSREF", -1 );-		if ( n==-1 ) continue;-		fields_setused( ref, n );-		ncross = biblatexin_findref(bin, (char*)fields_value(ref,n, FIELDS_CHRP_NOUSE));-		if ( ncross==-1 ) {-			biblatexin_nocrossref( bin, i, n, p );-			continue;-		}-		cross = bin->ref[ncross];-		status = biblatexin_crossref_oneref( ref, cross );-		if ( status!=BIBL_OK ) return status;-	}-	return status;-}--static int-biblatexin_cleanref( fields *bibin, param *p )-{-	int i, n, status;-	newstr *t, *d;-	n = fields_num( bibin );-	for ( i=0; i<n; ++i ) {-		t = fields_tag( bibin, i, FIELDS_STRP_NOUSE );-		d = fields_value( bibin, i, FIELDS_STRP_NOUSE );-		status = biblatexin_cleandata( t, d, bibin, p );-		if ( status!=BIBL_OK ) return status;-		if ( !strsearch( t->data, "AUTHORS" ) ) {-			newstr_findreplace( d, "\n", " " );-			newstr_findreplace( d, "\r", " " );-		}-		else if ( !strsearch( t->data, "ABSTRACT" ) ||-		     !strsearch( t->data, "SUMMARY" ) || -		     !strsearch( t->data, "NOTE" ) ) {-			newstr_findreplace( d, "\n", "" );-			newstr_findreplace( d, "\r", "" );-		}-	}-	return BIBL_OK;-}--int-biblatexin_cleanf( bibl *bin, param *p )-{-	int status;-	long i;-        for ( i=0; i<bin->nrefs; ++i ) {-		status = biblatexin_cleanref( bin->ref[i], p );-		if ( status!=BIBL_OK ) return status;-	}-	status = biblatexin_crossref( bin, p );-	return status;-}--/*****************************************************- PUBLIC: void biblatexin_typef()-*****************************************************/--int-biblatexin_typef( fields *bibin, char *filename, int nrefs, param *p,-                variants *all, int nall )-{-        char *refnum = "";-        int reftype, n, nrefnum;-        n = fields_find( bibin, "INTERNAL_TYPE", 0 );-        nrefnum = fields_find( bibin, "REFNUM", 0 );-        if ( nrefnum!=-1 ) refnum = (bibin->data[nrefnum]).data;-        if ( n!=-1 )-                /* figure out type */-                reftype = get_reftype( (bibin->data[n]).data, nrefs,-                        p->progname, all, nall, refnum );-        else-                /* no type info, go for default */-                reftype = get_reftype( "", nrefs, p->progname, all, nall, refnum );-        return reftype;-}--/*****************************************************- PUBLIC: int biblatexin_convertf(), returns BIBL_OK or BIBL_ERR_MEMERR-*****************************************************/--/* is_utf8_emdash()- *- * Internally pages="A---B" will convert --- to a UTF8- * emdash = 0xE2 (-30) 0x80 (-128) 0x94 (-108)- */-static int-is_utf8_emdash( char *p )-{-	static char emdash[3] = { -30, -128, -108 };-	if ( strncmp( p, emdash, 3 ) ) return 0;-	return 1;-}-/* is_utf8_endash()- *- * Internally pages="A--B" will convert -- to a UTF8- * endash = 0xE2 (-30) 0x80 (-128) 0x93 (-109)- */-static int-is_utf8_endash( char *p )-{-	static char endash[3] = { -30, -128, -109 };-	if ( strncmp( p, endash, 3 ) ) return 0;-	return 1;-}--static int-process_pages( fields *info, newstr *s, int level )-{-	int fstatus, status = BIBL_OK;-	newstr page;-	char *p;--	newstr_findreplace( s, " ", "" );-	if ( s->len==0 ) return status;--	newstr_init( &page );-	p = skip_ws( s->data );-	while ( *p && !is_ws(*p) && *p!='-' && *p!=-30 )-		newstr_addchar( &page, *p++ );-	if ( page.len>0 ) {-		fstatus = fields_add( info, "PAGESTART", page.data, level );-		if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }-	}--	while ( *p && (is_ws(*p) || *p=='-' ) ) p++;-	if ( *p && is_utf8_emdash( p ) ) p+=3;-	if ( *p && is_utf8_endash( p ) ) p+=3;--	newstr_empty( &page );-	while ( *p && !is_ws(*p) && *p!='-' && *p!=-30 )-		newstr_addchar( &page, *p++ );-	if ( page.len>0 ) {-		fstatus = fields_add( info, "PAGEEND", page.data, level );-		if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }-	}-out:-	newstr_free( &page );-	return status;-}--static int-process_url( fields *info, char *p, int level )-{-	int fstatus;-	if ( !strncasecmp( p, "\\urllink", 8 ) )-		fstatus = fields_add( info, "URL", p+8, level );-	else if ( !strncasecmp( p, "\\url", 4 ) )-		fstatus = fields_add( info, "URL", p+4, level );-	else if ( !strncasecmp( p, "arXiv:", 6 ) )-		fstatus = fields_add( info, "ARXIV", p+6, level ); -	else if ( !strncasecmp( p, "http://arxiv.org/abs/", 21 ) )-		fstatus = fields_add( info, "ARXIV", p+21, level );-	else if ( !strncasecmp( p, "http:", 5 ) )-		fstatus = fields_add( info, "URL", p, level );-	else -		fstatus = fields_add( info, "URL", p, level );-	if ( fstatus==FIELDS_OK ) return BIBL_OK;-	else return BIBL_ERR_MEMERR;-}---/* process_howpublished()- *- *    howpublished={},- *- * Normally indicates the manner in which something was- * published in lieu of a formal publisher, so typically- * 'howpublished' and 'publisher' will never be in the- * same reference.- *- * Occasionally, people put Diploma thesis information- * into this field, so check for that first.- */-static int-process_howpublished( fields *info, char *p, int level )-{-	int fstatus;-        if ( !strncasecmp( p, "Diplom", 6 ) )-                fstatus = fields_replace_or_add( info, "NGENRE", "Diploma thesis", level );-        else if ( !strncasecmp( p, "Habilitation", 13 ) )-                fstatus = fields_replace_or_add( info, "NGENRE", "Habilitation thesis", level );-        else-		fstatus = fields_add( info, "PUBLISHER", p, level );-	if ( fstatus==FIELDS_OK ) return BIBL_OK;-	else return BIBL_ERR_MEMERR;-}--static int-process_thesistype( fields *info, char *p, int level )-{-	int fstatus;-	/* type in the @thesis is used to distinguish Ph.D. and Master's thesis */-	if ( !strncasecmp( p, "phdthesis", 9 ) ) {-		fstatus = fields_replace_or_add( info, "NGENRE", "Ph.D. thesis", level );-	} else if ( !strncasecmp( p, "mastersthesis", 13 ) || !strncasecmp( p, "masterthesis", 12 ) ) {-		fstatus = fields_replace_or_add( info, "NGENRE", "Masters thesis", level );-	} else if ( !strncasecmp( p, "mathesis", 8 ) ) {-		fstatus = fields_replace_or_add( info, "NGENRE", "Masters thesis", level );-	} else if ( !strncasecmp( p, "diploma", 7 ) ) {-		fstatus = fields_replace_or_add( info, "NGENRE", "Diploma thesis", level );-	} else if ( !strncasecmp( p, "habilitation", 12 ) ) {-		fstatus = fields_replace_or_add( info, "NGENRE", "Habilitation thesis", level );-	}-	if ( fstatus==FIELDS_OK ) return BIBL_OK;-	else return BIBL_ERR_MEMERR;-}--/* biblatex drops school field if institution is present */-static int-process_school( fields *bibin, fields *info, char *tag, char *value, int level )-{-	int fstatus;-	if ( fields_find( bibin, "institution", LEVEL_ANY ) != -1 )-		return BIBL_OK;-	else {-		fstatus = fields_add( info, tag, value, level );-		if ( fstatus==FIELDS_OK ) return BIBL_OK;-		else return BIBL_ERR_MEMERR;-	}-}--/* biblatex drops school field if institution is present */-static int-process_subtype( fields *bibin, fields *info, char *tag, char *value, int level )-{-	int fstatus;-	if ( !strcasecmp( value, "magazine" ) ) {-		fstatus = fields_add( info, "NGENRE", "magazine article", LEVEL_MAIN );-		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;-		fstatus = fields_add( info, "NGENRE", "magazine", LEVEL_HOST );-		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;-	} else if ( !strcasecmp( value, "newspaper" ) ) {-		fstatus = fields_add( info, "NGENRE", "newspaper article", LEVEL_MAIN );-		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;-		fstatus = fields_add( info, "GENRE", "newspaper", LEVEL_HOST );-		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;-	}-	return BIBL_OK;-}--static int-process_eprint( fields *bibin, fields *info, int level )-{-	int neprint, netype, fstatus;-	char *eprint = NULL, *etype = NULL;-	neprint = fields_find( bibin, "eprint", -1 );-	netype  = fields_find( bibin, "eprinttype", -1 );-	if ( neprint!=-1 ) eprint = bibin->data[neprint].data;-	if ( netype!=-1 ) etype = bibin->data[netype].data;-	if ( eprint && etype ) {-		if ( !strncasecmp( etype, "arxiv", 5 ) ) {-			fstatus = fields_add( info, "ARXIV", eprint, level );-			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;-		} else if ( !strncasecmp( etype, "jstor", 5 ) ) {-			fstatus = fields_add( info, "JSTOR", eprint, level );-			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;-		} else if ( !strncasecmp( etype, "pubmed", 6 ) ) {-			fstatus = fields_add( info, "PMID", eprint, level );-			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;-		} else if ( !strncasecmp( etype, "medline", 7 ) ) {-			fstatus = fields_add( info, "MEDLINE", eprint, level );-			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;-		} else {-			fstatus = fields_add( info, "EPRINT", eprint, level );-			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;-			fstatus = fields_add( info, "EPRINTTYPE", etype, level );-			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;-		}-		fields_setused( bibin, neprint );-		fields_setused( bibin, netype );-	} else if ( eprint ) {-		fstatus = fields_add( info, "EPRINT", eprint, level );-		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;-		fields_setused( bibin, neprint );-	} else if ( etype ) {-		fstatus = fields_add( info, "EPRINTTYPE", etype, level );-		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;-		fields_setused( bibin, netype );-	}-	return BIBL_OK;-}--static void-report( fields *f )-{-	int i, n;-	n = fields_num( f );-	for ( i=0; i<n; ++i )-		fprintf(stderr, "%d '%s' = '%s'\n",-			fields_level( f, i ),-			(char*)fields_tag( f, i, FIELDS_CHRP_NOUSE ),-			(char*)fields_value( f, i, FIELDS_CHRP_NOUSE ) );-}--static void-biblatexin_notag( param *p, char *tag )-{-	if ( p->verbose && strcmp( tag, "INTERNAL_TYPE" ) ) {-		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );-		fprintf( stderr, " Cannot find tag '%s'\n", tag );-	}-}--/* get_title_elements()- *- * find all of the biblatex title elements for the current level- *    internal "TITLE"      -> "title", "booktitle", "maintitle"- *    internal "SUBTITLE"   -> "subtitle", "booksubtitle", "mainsubtitle"- *    internal "TITLEADDON" -> "titleaddon", "booktitleaddon", "maintitleaddon"- *- * place in ttl, subttl, and ttladdon strings- *- * return 1 if an element is found, 0 if not- */-static int-get_title_elements( fields *bibin, int currlevel, int reftype, variants *all, int nall,-	newstr *ttl, newstr *subttl, newstr *ttladdon )-{-	int nfields, process, level, i, n;-	newstr *t, *d;-	char *newtag;--	newstrs_empty( ttl, subttl, ttladdon, NULL );--	nfields = fields_num( bibin );--	for ( i=0; i<nfields; ++i ) {--		/* ...skip already used titles */-		if ( fields_used( bibin, i ) ) continue;--		/* ...skip empty elements */-		t = fields_tag  ( bibin, i, FIELDS_STRP_NOUSE );-		d = fields_value( bibin, i, FIELDS_STRP_NOUSE );-		if ( d->len == 0 ) continue;--		n = translate_oldtag( t->data, reftype, all, nall, &process, &level, &newtag );-		if ( n==-1 ) continue;-		if ( process != TITLE ) continue;-		if ( level != currlevel ) continue;--		fields_setused( bibin, i );--		if ( !strcasecmp( newtag, "TITLE" ) ) {-			if ( ttl->len ) newstr_addchar( ttl, ' ' );-			newstr_newstrcat( ttl, d );-		} else if ( !strcasecmp( newtag, "SUBTITLE" ) ) {-			if ( subttl->len ) newstr_addchar( subttl, ' ' );-			newstr_newstrcat( subttl, d );-		} else if ( !strcasecmp( newtag, "TITLEADDON" ) ) {-			if ( ttladdon->len ) newstr_addchar( ttladdon, ' ' );-			newstr_newstrcat( ttladdon, d );-		}-	}--	return ( ttl->len>0 || subttl->len > 0 || ttladdon->len > 0 );-}--/* attach_addon()- *- * Add titleaddon to the title.- */-static void-attach_addon( newstr *title, newstr *addon )-{-	if ( title->len ) {-		if ( title->data[title->len-1]!='.' )-			newstr_addchar( title, '.' );-		newstr_addchar( title, ' ' );-	}-	newstr_newstrcat( title, addon );-}--static int-process_combined_title( fields *info, newstr *ttl, newstr *subttl, newstr *ttladdon, int currlevel )-{-	int fstatus, status = BIBL_OK;-	newstr combined;--	newstr_init( &combined );-	newstr_newstrcpy( &combined, ttl );-	if ( subttl->len ) {-		if ( combined.len && combined.data[combined.len-1]!=':' && combined.data[combined.len-1]!='?' )-			newstr_addchar( &combined, ':' );-		newstr_addchar( &combined, ' ' );-		newstr_newstrcat( &combined, subttl );-	}-	if ( ttladdon->len ) attach_addon( &combined, ttladdon );-	if ( newstr_memerr( &combined ) ) { status = BIBL_ERR_MEMERR; goto out; }-	fstatus = fields_add( info, "TITLE", combined.data, currlevel );-	if ( fstatus==FIELDS_OK ) status = BIBL_ERR_MEMERR;-out:-	newstr_free( &combined );-	return status;-}--static int-process_separated_title( fields *info, newstr *ttl, newstr *subttl, newstr *ttladdon, int currlevel )-{-	int fstatus;-	if ( ttladdon->len ) {-		if ( subttl->len ) attach_addon( subttl, ttladdon );-		else attach_addon( ttl, ttladdon );-	}-	if ( ttl->len ) {-		fstatus = fields_add( info, "TITLE", ttl->data, currlevel );-		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;-	}-	if ( subttl->len ) {-		fstatus = fields_add( info, "SUBTITLE", subttl->data, currlevel );-		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;-	}-	return BIBL_OK;-}--static int-process_title_all( fields *bibin, fields *info, int reftype, param *p,-	variants *all, int nall )-{-	int currlevel, found, status = BIBL_OK;-	newstr ttl, subttl, ttladdon;-	newstrs_init( &ttl, &subttl, &ttladdon, NULL );-	for ( currlevel = 0; currlevel<LEVEL_SERIES+2; currlevel++ ) {-		found = get_title_elements( bibin, currlevel, reftype, all, nall,-				&ttl, &subttl, &ttladdon );-		if ( !found ) continue;-		if ( p->nosplittitle )-			status = process_combined_title( info, &ttl, &subttl, &ttladdon, currlevel );-		else-			status = process_separated_title( info, &ttl, &subttl, &ttladdon, currlevel );-		if ( status!=BIBL_OK ) goto out;-	}-out:-	newstrs_free( &ttl, &subttl, &ttladdon, NULL );-	return status;-}---static int-biblatex_matches_list( fields *info, char *tag, char *suffix, newstr *data, int level,-                list *names, int *match )-{-	int i, fstatus, status = BIBL_OK;-	newstr newtag;--	*match = 0;-	if ( names->n==0 ) return status;--	newstr_init( &newtag );--	for ( i=0; i<names->n; ++i ) {-		if ( strcmp( data->data, list_getc( names, i ) ) ) continue;-		newstr_initstr( &newtag, tag );-		newstr_strcat( &newtag, suffix );-		fstatus = fields_add( info, newtag.data, data->data, level );-		if ( fstatus!=FIELDS_OK ) {-			status = BIBL_ERR_MEMERR;-			goto out;-		}-		*match = 1;-		goto out;-	}--out:-	newstr_free( &newtag );-	return status;-}--static int-biblatex_names( fields *info, char *tag, newstr *data, int level, list *asis, list *corps )-{-	int begin, end, ok, n, etal, i, match, status = BIBL_OK;-	list tokens;--	/* If we match the asis or corps list add and bail. */-	status = biblatex_matches_list( info, tag, ":ASIS", data, level, asis, &match );-	if ( match==1 || status!=BIBL_OK ) return status;-	status = biblatex_matches_list( info, tag, ":CORP", data, level, corps, &match );-	if ( match==1 || status!=BIBL_OK ) return status;--	list_init( &tokens );--	biblatex_split( &tokens, data );-	for ( i=0; i<tokens.n; ++i )-		biblatex_cleantoken( list_get( &tokens, i ) );--	etal = name_findetal( &tokens );--	begin = 0;-	n = tokens.n - etal;-	while ( begin < n ) {--		end = begin + 1;--		while ( end < n && strcasecmp( list_getc( &tokens, end ), "and" ) )-			end++;--		if ( end - begin == 1 ) {-			ok = name_addsingleelement( info, tag, list_getc( &tokens, begin ), level, 0 );-			if ( !ok ) { status = BIBL_ERR_MEMERR; goto out; }-		} else {-			ok = name_addmultielement( info, tag, &tokens, begin, end, level );-			if ( !ok ) { status = BIBL_ERR_MEMERR; goto out; }-		}--		begin = end + 1;--		/* Handle repeated 'and' errors */-		while ( begin < n && !strcasecmp( list_getc( &tokens, begin ), "and" ) )-			begin++;--	}--	if ( etal ) {-		ok = name_addsingleelement( info, tag, "et al.", level, 0 );-		if ( !ok ) status = BIBL_ERR_MEMERR;-	}--out:-	list_free( &tokens );-	return status;-}--/*- * biblatex has multiple editor fields "editor", "editora", "editorb", "editorc",- * each of which can be modified from a type of "EDITOR" via "editortype",- * "editoratype", "editorbtype", "editorctype".- *- * Defined types:- *     "editor"- *     "collaborator"- *     "compiler"- *     "redactor"- *- *     "reviser" ?- *     "founder" ?- *     "continuator" ?- *- *  bibtex-chicago- *- *     "director"- *     "producer"- *     "conductor"- *     "none" (for performer)- */-static int-process_editor( fields *bibin, fields *info, newstr *tag, newstr *value, int level, list *asis, list *corps )-{-	char *editor_fields[] = { "editor", "editora", "editorb", "editorc" };-	char *editor_types[]  = { "editortype", "editoratype", "editorbtype", "editorctype" };-	int i, n = 0, ntype, neditors = sizeof( editor_fields ) / sizeof( editor_fields[0] );-	char *type, *outtag = "EDITOR";-	for ( i=1; i<neditors; ++i )-		if ( !strcasecmp( tag->data, editor_fields[i] ) ) n = i;-	ntype = fields_find( bibin, editor_types[n], LEVEL_ANY );-	if ( ntype!=-1 ) {-		type = fields_value( bibin, ntype, FIELDS_CHRP_NOUSE );-		if ( !strcasecmp( type, "collaborator" ) )  outtag = "COLLABORATOR";-		else if ( !strcasecmp( type, "compiler" ) ) outtag = "COMPILER";-		else if ( !strcasecmp( type, "redactor" ) ) outtag = "REDACTOR";-		else if ( !strcasecmp( type, "director" ) ) outtag = "DIRECTOR";-		else if ( !strcasecmp( type, "producer" ) ) outtag = "PRODUCER";-		else if ( !strcasecmp( type, "none" ) )     outtag = "PERFORMER";-	}-	return biblatex_names( info, outtag, value, level, asis, corps );-}--static int-biblatexin_simple( fields *f, char *tag, char *value, int level )-{-	int fstatus = fields_add( f, tag, value, level );-	if ( fstatus==FIELDS_OK ) return BIBL_OK;-	else return BIBL_ERR_MEMERR;-}--int-biblatexin_convertf( fields *bibin, fields *info, int reftype, param *p,-		variants *all, int nall )-{-	int process, level, i, n, nfields, status = BIBL_OK;-	newstr *t, *d;-	char *newtag;--	nfields = fields_num( bibin );-	for ( i=0; i<nfields; ++i ) {--               /* skip ones already "used" such as successful crossref */-                if ( fields_used( bibin, i ) ) continue;--		/* skip ones with no data or no tags (e.g. don't match ALWAYS/DEFAULT entries) */-		t = fields_tag  ( bibin, i, FIELDS_STRP_NOUSE );-		d = fields_value( bibin, i, FIELDS_STRP_NOUSE );-		if ( t->len == 0 || d->len == 0 ) continue;--		n = translate_oldtag( t->data, reftype, all, nall, &process, &level, &newtag );-		if ( n==-1 ) {-			biblatexin_notag( p, t->data );-			continue;-		}--		switch ( process ) {--		case SIMPLE:-			status = biblatexin_simple( info, newtag, d->data, level );-			fields_setused( bibin, i );-			break;--		case PERSON:-			status = biblatex_names( info, newtag, d, level, &(p->asis), &(p->corps) );-			fields_setused( bibin, i );-			break;--		case BLT_EDITOR:-			status = process_editor( bibin, info, t, d, level, &(p->asis), &(p->corps) );-			fields_setused( bibin, i );-			break;--		case PAGES:-			status = process_pages( info, d, level);-			fields_setused( bibin, i );-			break;--		case HOWPUBLISHED:-			status = process_howpublished( info, d->data, level );-			fields_setused( bibin, i );-			break;--		case BT_URL:-			status = process_url( info, d->data, level );-			fields_setused( bibin, i );-			break;--		case BT_GENRE:-			status = biblatexin_simple( info, "NGENRE", d->data, level );-			fields_setused( bibin, i );-			break;--		case BT_EPRINT:-			status = process_eprint( bibin, info, level );-			fields_setused( bibin, i );-			break;--		case BLT_THESIS_TYPE:-			status = process_thesistype( info, d->data, level );-			fields_setused( bibin, i );-			break;--		case BLT_SCHOOL:-			status = process_school( bibin, info, newtag, d->data, level );-			fields_setused( bibin, i );-			break;--		case BLT_SUBTYPE:-			status = process_subtype( bibin, info, newtag, d->data, level );-			fields_setused( bibin, i );-			break;--		case BLT_SKIP:-			status = BIBL_OK;-			fields_setused( bibin, i );-			break;--		case TITLE:-			status = BIBL_OK; /* delay title processing until later */-			break;--		default:-			status = BIBL_OK;-			break;--		}-		if ( status!=BIBL_OK ) return status;--	}--	status = process_title_all( bibin, info, reftype, p, all, nall );--	if ( status==BIBL_OK && p->verbose ) report( info );+ * Copyright (c) Chris Putnam 2008-2017+ * Copyright (c) Johannes Wilm 2010-2017+ *+ * Program and source code released under the GPL version 2+ *+ */+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <ctype.h>+#include "is_ws.h"+#include "strsearch.h"+#include "str.h"+#include "utf8.h"+#include "str_conv.h"+#include "fields.h"+#include "slist.h"+#include "name.h"+#include "reftypes.h"+#include "bibformats.h"+#include "generic.h"++extern variants biblatex_all[];+extern int biblatex_nall;++static slist find    = { 0, 0, 0, NULL };+static slist replace = { 0, 0, 0, NULL };++/*****************************************************+ PUBLIC: void biblatexin_initparams()+*****************************************************/++static int  biblatexin_convertf( fields *bibin, fields *info, int reftype, param *p );+static int  biblatexin_processf( fields *bibin, char *data, char *filename, long nref, param *p );+static int  biblatexin_cleanf( bibl *bin, param *p );+static int  biblatexin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset );+static int  biblatexin_typef( fields *bibin, char *filename, int nrefs, param *p );++void+biblatexin_initparams( param *p, const char *progname )+{+	p->readformat       = BIBL_BIBLATEXIN;+	p->charsetin        = BIBL_CHARSET_DEFAULT;+	p->charsetin_src    = BIBL_SRC_DEFAULT;+	p->latexin          = 1;+	p->xmlin            = 0;+	p->utf8in           = 0;+	p->nosplittitle     = 0;+	p->verbose          = 0;+	p->addcount         = 0;+	p->output_raw       = 0;++	p->readf    = biblatexin_readf;+	p->processf = biblatexin_processf;+	p->cleanf   = biblatexin_cleanf;+	p->typef    = biblatexin_typef;+	p->convertf = biblatexin_convertf;+	p->all      = biblatex_all;+	p->nall     = biblatex_nall;++	slist_init( &(p->asis) );+	slist_init( &(p->corps) );++	if ( !progname ) p->progname = NULL;+	else p->progname = strdup( progname );+}++/*****************************************************+ PUBLIC: int biblatexin_readf()+*****************************************************/++/*+ * readf can "read too far", so we store this information in line, thus+ * the next new text is in line, either from having read too far or+ * from the next chunk obtained via str_fget()+ *+ * return 1 on success, 0 on error/end-of-file+ *+ */+static int+readmore( FILE *fp, char *buf, int bufsize, int *bufpos, str *line )+{+	if ( line->len ) return 1;+	else return str_fget( fp, buf, bufsize, bufpos, line );+}++/*+ * readf()+ *+ * returns zero if cannot get reference and hit end of-file+ * returns 1 if last reference in file, 2 if reference within file+ */+static int+biblatexin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset )+{+	int haveref = 0;+	char *p;+	while ( haveref!=2 && readmore( fp, buf, bufsize, bufpos, line ) ) {+		if ( line->len == 0 ) continue; /* blank line */+		p = &(line->data[0]);+		p = skip_ws( p );+		if ( *p == '%' ) { /* commented out line */+			str_empty( line );+			continue;+		}+		if ( *p == '@' ) haveref++;+		if ( haveref && haveref<2 ) {+			str_strcatc( reference, p );+			str_addchar( reference, '\n' );+			str_empty( line );+		} else if ( !haveref ) str_empty( line );+	+	}+	*fcharset = CHARSET_UNKNOWN;+	return haveref;+}++/*****************************************************+ PUBLIC: int biblatexin_processf()+*****************************************************/++static char *+process_biblatextype( char *p, str *type )+{+	str tmp;+	str_init( &tmp );++	if ( *p=='@' ) p++;+	p = str_cpytodelim( &tmp, p, "{( \t\r\n", 0 );+	p = skip_ws( p );+	if ( *p=='{' || *p=='(' ) p++;+	p = skip_ws( p );++	if ( str_has_value( &tmp ) ) str_strcpy( type, &tmp );+	else str_empty( type );++	str_free( &tmp );+	return p;+}++static char *+process_biblatexid( char *p, str *id )+{+	char *start_p = p;+	str tmp;++	str_init( &tmp );+	p = str_cpytodelim( &tmp, p, ",", 1 );++	if ( str_has_value( &tmp ) ) {+		if ( strchr( tmp.data, '=' ) ) {+			/* Endnote writes biblatex files w/o fields, try to+			 * distinguish via presence of an equal sign.... if+			 * it's there, assume that it's a tag/data pair instead+			 * and roll back.+			 */+			p = start_p;+			str_empty( id );+		} else {+			str_strcpy( id, &tmp );+		}+	} else {+		str_empty( id );+	}++	str_free( &tmp );+	return skip_ws( p );+}++static char *+biblatex_tag( char *p, str *tag )+{+	p = str_cpytodelim( tag, skip_ws( p ), "= \t\r\n", 0 );+	return skip_ws( p );+}++static char *+biblatex_data( char *p, fields *bibin, slist *tokens, long nref, param *pm )+{+	unsigned int nbracket = 0, nquotes = 0;+	char *startp = p;+	str tok, *s;++	str_init( &tok );+	while ( p && *p ) {+		if ( !nquotes && !nbracket ) {+			if ( *p==',' || *p=='=' || *p=='}' || *p==')' )+				goto out;+		}+		if ( *p=='\"' && nbracket==0 && ( p==startp || *(p-1)!='\\' ) ) {+			nquotes = !nquotes;+			str_addchar( &tok, *p );+			if ( !nquotes ) {+				s = slist_add( tokens, &tok );+				if ( !s ) { p = NULL; goto outerr; }+				str_empty( &tok );+			}+		} else if ( *p=='#' && !nquotes && !nbracket ) {+			if ( str_has_value( &tok ) ) {+				s = slist_add( tokens, &tok );+				if ( !s ) { p = NULL; goto outerr; }+			}+			str_strcpyc( &tok, "#" );+			s = slist_add( tokens, &tok );+			if ( !s ) { p = NULL; goto outerr; }+			str_empty( &tok );+		} else if ( *p=='{' && !nquotes && ( p==startp || *(p-1)!='\\' ) ) {+			nbracket++;+			str_addchar( &tok, *p );+		} else if ( *p=='}' && !nquotes && ( p==startp || *(p-1)!='\\' ) ) {+			nbracket--;+			str_addchar( &tok, *p );+			if ( nbracket==0 ) {+				s = slist_add( tokens, &tok );+				if ( !s ) { p = NULL; goto outerr; }+				str_empty( &tok );+			}+		} else if ( !is_ws( *p ) || nquotes || nbracket ) {+			if ( !is_ws( *p ) ) str_addchar( &tok, *p );+			else {+				if ( tok.len!=0 && *p!='\n' && *p!='\r' )+					str_addchar( &tok, *p );+				else if ( tok.len!=0 && (*p=='\n' || *p=='\r')) {+					str_addchar( &tok, ' ' );+					while ( is_ws( *(p+1) ) ) p++;+				}+			}+		} else if ( is_ws( *p ) ) {+			if ( str_has_value( &tok ) ) {+				s = slist_add( tokens, &tok );+				if ( !s ) { p = NULL; goto outerr; }+				str_empty( &tok );+			}+		}+		p++;+	}+out:+	if ( nbracket!=0 ) {+		fprintf( stderr, "%s: Mismatch in number of brackets in reference %ld\n", pm->progname, nref );+	}+	if ( nquotes!=0 ) {+		fprintf( stderr, "%s: Mismatch in number of quotes in reference %ld\n", pm->progname, nref );+	}+	if ( str_has_value( &tok ) ) {+		s = slist_add( tokens, &tok );+		if ( !s ) p = NULL;+	}+outerr:+	str_free( &tok );+	return p;+}++/* replace_strings()+ *+ * do string replacement -- only if unprotected by quotation marks or curly brackets+ */+static void+replace_strings( slist *tokens, fields *bibin, long nref, param *pm )+{+	int i, n, ok;+	char *q;+	str *s;+	i = 0;+	while ( i < tokens->n ) {+		s = slist_str( tokens, i );+		if ( !strcmp( s->data, "#" ) ) {+		} else if ( s->data[0]!='\"' && s->data[0]!='{' ) {+			n = slist_find( &find, s );+			if ( n!=-1 ) {+				str_strcpy( s, slist_str( &replace, n ) );+			} else {+				q = s->data;+				ok = 1;+				while ( *q && ok ) {+					if ( !isdigit( *q ) ) ok = 0;+					q++;+				}+				if ( !ok ) {+					fprintf( stderr, "%s: Warning: Non-numeric "+					   "BibTeX elements should be in quotations or "+					   "curly brackets in reference %ld\n", pm->progname, nref );+				}+			}+		}+		i++;+	}+}++static int+string_concatenate( slist *tokens, fields *bibin, long nref, param *pm )+{+	int i, status;+	str *s, *t;+	i = 0;+	while ( i < tokens->n ) {+		s = slist_str( tokens, i );+		if ( !strcmp( str_cstr( s ), "#" ) ) {+			if ( i==0 || i==tokens->n-1 ) {+				fprintf( stderr, "%s: Warning: Stray string concatenation "+					"('#' character) in reference %ld\n", pm->progname, nref );+				status = slist_remove( tokens, i );+				if ( status!=SLIST_OK ) return BIBL_ERR_MEMERR;+				continue;+			}+			s = slist_str( tokens, i-1 );+			if ( s->data[0]!='\"' && s->data[s->len-1]!='\"' )+				fprintf( stderr, "%s: Warning: String concentation should "+					"be used in context of quotations marks in reference %ld\n", pm->progname, nref );+			t = slist_str( tokens, i+1 );+			if ( t->data[0]!='\"' && t->data[s->len-1]!='\"' )+				fprintf( stderr, "%s: Warning: String concentation should "+					"be used in context of quotations marks in reference %ld\n", pm->progname, nref );+			if ( ( s->data[s->len-1]=='\"' && t->data[0]=='\"') || (s->data[s->len-1]=='}' && t->data[0]=='{') ) {+				str_trimend( s, 1 );+				str_trimbegin( t, 1 );+				str_strcat( s, t );+			} else {+				str_strcat( s, t );+			}+			status = slist_remove( tokens, i );+			if ( status!=SLIST_OK ) return BIBL_ERR_MEMERR;+			status = slist_remove( tokens, i );+			if ( status!=SLIST_OK ) return BIBL_ERR_MEMERR;+		} else i++;+	}+	return BIBL_OK;+}++static char *+process_biblatexline( char *p, str *tag, str *data, uchar stripquotes, long nref, param *pm )+{+	int i, status;+	slist tokens;+	str *s;++	str_empty( data );++	p = biblatex_tag( p, tag );+	if ( tag->len==0 ) return p;++	slist_init( &tokens );++	if ( *p=='=' ) p = biblatex_data( p+1, NULL, &tokens, nref, pm );++	replace_strings( &tokens, NULL, nref, pm );++	status = string_concatenate( &tokens, NULL, nref, pm );+	if ( status!=BIBL_OK ) {+		p = NULL;+		goto out;+	}++	for ( i=0; i<tokens.n; i++ ) {+		s = slist_str( &tokens, i );+		if ( ( stripquotes && s->data[0]=='\"' && s->data[s->len-1]=='\"' ) ||+		     ( s->data[0]=='{' && s->data[s->len-1]=='}' ) ) {+			str_trimbegin( s, 1 );+			str_trimend( s, 1 );+		}+		str_strcat( data, slist_str( &tokens, i ) );+	}+out:+	slist_free( &tokens );+	return p;+}++static int+process_cite( fields *bibin, char *p, char *filename, long nref, param *pm )+{+	int fstatus, status = BIBL_OK;+	str tag, data;+	strs_init( &tag, &data, NULL );+	p = process_biblatextype( p, &data );+	if ( str_has_value( &data ) ) {+		fstatus = fields_add( bibin, "INTERNAL_TYPE", str_cstr( &data ), 0 );+		if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }+	}+	p = process_biblatexid ( p, &data );+	if ( str_has_value( &data ) ) {+		fstatus = fields_add( bibin, "REFNUM", str_cstr( &data ), 0 );+		if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }+	}+	while ( *p ) {+		p = process_biblatexline( p, &tag, &data, 1, nref, pm );+		if ( !p ) { status = BIBL_ERR_MEMERR; goto out; }+		/* no anonymous or empty fields allowed */+		if ( str_has_value( &tag ) && str_has_value( &data ) ) {+			fstatus = fields_add( bibin, str_cstr( &tag ), str_cstr( &data ), 0 );+			if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }+		}+		strs_empty( &tag, &data, NULL );+	}+out:+	strs_free( &tag, &data, NULL );+	return status;+}++/* process_string()+ *+ * Handle lines like:+ *+ * '@STRING{TL = {Tetrahedron Lett.}}'+ *+ * p should point to just after '@STRING'+ *+ * In BibTeX, if a string is defined several times, the last one is kept.+ *+ */+static int+process_string( char *p, long nref, param *pm )+{+	int n, status = BIBL_OK;+	str s1, s2, *s;+	strs_init( &s1, &s2, NULL );+	while ( *p && *p!='{' && *p!='(' ) p++;+	if ( *p=='{' || *p=='(' ) p++;+	p = process_biblatexline( skip_ws( p ), &s1, &s2, 0, nref, pm );+	if ( str_has_value( &s2 ) ) {+		str_findreplace( &s2, "\\ ", " " );+		if ( str_memerr( &s2 ) ) { status = BIBL_ERR_MEMERR; goto out; }+	}+	if ( str_has_value( &s1 ) ) {+		n = slist_find( &find, &s1 );+		if ( n==-1 ) {+			s = slist_add( &find, &s1 );+			if ( s==NULL ) { status = BIBL_ERR_MEMERR; goto out; }+			if ( str_has_value( &s2 ) ) s = slist_add( &replace, &s2 );+			else s = slist_addc( &replace, "" );+			if ( s==NULL ) { status = BIBL_ERR_MEMERR; goto out; }+		} else {+			if ( str_has_value( &s2 ) ) s = slist_set( &replace, n, &s2 );+			else s = slist_setc( &replace, n, "" );+			if ( s==NULL ) { status = BIBL_ERR_MEMERR; goto out; }+		}+	}+out:+	strs_free( &s1, &s2, NULL );+	return status;+}++static int+biblatexin_processf( fields *bibin, char *data, char *filename, long nref, param *p )+{+	if ( !strncasecmp( data, "@STRING", 7 ) ) {+		process_string( data+7, nref, p );+		return 0;+        } else {+		process_cite( bibin, data, filename, nref, p );+		return 1;+	}+}++/*****************************************************+ PUBLIC: void biblatexin_cleanf()+*****************************************************/++static void+biblatex_process_tilde( str *s )+{+	char *p, *q;+	int n = 0;++	p = q = s->data;+	if ( !p ) return;+	while ( *p ) {+		if ( *p=='~' ) {+			*q = ' ';+		} else if ( *p=='\\' && *(p+1)=='~' ) {+			n++;+			p++;+			*q = '~';+		} else {+			*q = *p;+		}+		p++;+		q++;+	}+	*q = '\0';+	s->len -= n;+}++static void+biblatex_process_bracket( str *s )+{+	char *p, *q;+	int n = 0;++	p = q = s->data;+	if ( !p ) return;+	while ( *p ) {+		if ( *p=='\\' && ( *(p+1)=='{' || *(p+1)=='}' ) ) {+			n++;+			p++;+			*q = *p;+			q++;+		} else if ( *p=='{' || *p=='}' ) {+			n++;+		} else {+			*q = *p;+			q++;+		}+		p++;+	}+	*q = '\0';+	s->len -= n;+}++static int+biblatex_cleantoken( str *s )+{+	/* 'textcomp' annotations */+	str_findreplace( s, "\\textit", "" );+	str_findreplace( s, "\\textbf", "" );+	str_findreplace( s, "\\textsl", "" );+	str_findreplace( s, "\\textsc", "" );+	str_findreplace( s, "\\textsf", "" );+	str_findreplace( s, "\\texttt", "" );+	str_findreplace( s, "\\textsubscript", "" );+	str_findreplace( s, "\\textsuperscript", "" );+	str_findreplace( s, "\\emph", "" );+	str_findreplace( s, "\\url", "" );++	/* Other text annotations */+	str_findreplace( s, "\\it ", "" );+	str_findreplace( s, "\\em ", "" );++	str_findreplace( s, "\\%", "%" );+	str_findreplace( s, "\\$", "$" );+	while ( str_findreplace( s, "  ", " " ) ) {}++	/* 'textcomp' annotations that we don't want to substitute on output*/+	str_findreplace( s, "\\textdollar", "$" );+	str_findreplace( s, "\\textunderscore", "_" );++	biblatex_process_bracket( s );+	biblatex_process_tilde( s );++	if ( !str_memerr( s ) ) return BIBL_OK;+	else return BIBL_ERR_MEMERR;+}++static int+biblatex_split( slist *tokens, str *s )+{+	int i, n = s->len, nbrackets = 0, status = BIBL_OK;+	str tok, *t;++	str_init( &tok );++	for ( i=0; i<n; ++i ) {+		if ( s->data[i]=='{' && ( i==0 || s->data[i-1]!='\\' ) ) {+			nbrackets++;+			str_addchar( &tok, '{' );+		} else if ( s->data[i]=='}' && ( i==0 || s->data[i-1]!='\\' ) ) {+			nbrackets--;+			str_addchar( &tok, '}' );+		} else if ( !is_ws( s->data[i] ) || nbrackets ) {+			str_addchar( &tok, s->data[i] );+		} else if ( is_ws( s->data[i] ) ) {+			if ( str_memerr( &tok ) ) { status = BIBL_ERR_MEMERR; goto out; }+			if ( str_has_value( &tok ) ) {+				t = slist_add( tokens, &tok );+				if ( !t ) { status = BIBL_ERR_MEMERR; goto out; }+			}+			str_empty( &tok );+		}+	}+	if ( str_has_value( &tok ) ) {+		if ( str_memerr( &tok ) ) { status = BIBL_ERR_MEMERR; goto out; }+		t = slist_add( tokens, &tok );+		if ( !t ) { status = BIBL_ERR_MEMERR; goto out; }+	}++	for ( i=0; i<tokens->n; ++i ) {+		t = slist_str( tokens, i );+		str_trimstartingws( t );+		str_trimendingws( t );+		if ( str_memerr( t ) ) { status = BIBL_ERR_MEMERR; goto out; }+	}+out:+	str_free( &tok );+	return status;+}++static int+biblatexin_addtitleurl( fields *info, str *in )+{+	int fstatus, status = BIBL_OK;+	char *p;+	str s;++	str_init( &s );+	/* skip past "\href{" */+	p = str_cpytodelim( &s, in->data + 6, "}", 1 );+	if ( str_memerr( &s ) ) {+		status = BIBL_ERR_MEMERR;+		goto out;+	}+	fstatus = fields_add( info, "URL", s.data, 0 );+	if ( fstatus!=FIELDS_OK ) {+		status = BIBL_ERR_MEMERR;+		goto out;+	}++	p = str_cpytodelim( &s, p, "", 0 );+	if ( str_memerr( &s ) ) {+		status = BIBL_ERR_MEMERR;+		goto out;+	}+	str_swapstrings( &s, in );+out:+	str_free( &s );+	return status;+}++static int+is_name_tag( str *tag )+{+	if ( str_has_value( tag ) ) {+		if ( !strcasecmp( str_cstr( tag ), "author" ) ) return 1;+		if ( !strcasecmp( str_cstr( tag ), "editor" ) ) return 1;+		if ( !strcasecmp( str_cstr( tag ), "editorb" ) ) return 1;+		if ( !strcasecmp( str_cstr( tag ), "editorc" ) ) return 1;+		if ( !strcasecmp( str_cstr( tag ), "director" ) ) return 1;+		if ( !strcasecmp( str_cstr( tag ), "producer" ) ) return 1;+		if ( !strcasecmp( str_cstr( tag ), "execproducer" ) ) return 1;+		if ( !strcasecmp( str_cstr( tag ), "writer" ) ) return 1;+		if ( !strcasecmp( str_cstr( tag ), "redactor" ) ) return 1;+		if ( !strcasecmp( str_cstr( tag ), "annotator" ) ) return 1;+		if ( !strcasecmp( str_cstr( tag ), "commentator" ) ) return 1;+		if ( !strcasecmp( str_cstr( tag ), "translator" ) ) return 1;+		if ( !strcasecmp( str_cstr( tag ), "foreword" ) ) return 1;+		if ( !strcasecmp( str_cstr( tag ), "afterword" ) ) return 1;+		if ( !strcasecmp( str_cstr( tag ), "introduction" ) ) return 1;+	}+	return 0;+}++static int+is_url_tag( str *tag )+{+	if ( str_has_value( tag ) ) {+		if ( !strcasecmp( str_cstr( tag ), "url" ) ) return 1;+	}+	return 0;+}++static int+biblatexin_cleandata( str *tag, str *s, fields *info, param *p )+{+	slist tokens;+	str *tok;+	int i, status = BIBL_OK;+	if ( str_is_empty( s ) ) return status;+	/* protect url from undergoing any parsing */+	if ( is_url_tag( tag ) ) return status;+	slist_init( &tokens );+	biblatex_split( &tokens, s );+	for ( i=0; i<tokens.n; ++i ) {+		if ( !strncasecmp(slist_cstr( &tokens, i ), "\\href{", 6 )) {+			status = biblatexin_addtitleurl( info, slist_str( &tokens, i ) );+			if ( status!=BIBL_OK ) goto out;+		}+		if ( p && p->latexin && !is_name_tag( tag ) ) {+			status = biblatex_cleantoken( slist_str( &tokens, i ) );+			if ( status!=BIBL_OK ) goto out;+		}+	}+	str_empty( s );+	for ( i=0; i<tokens.n; ++i ) {+		tok = slist_str( &tokens, i );+		if ( i>0 ) str_addchar( s, ' ' );+		str_strcat( s, tok );+	}+out:+	slist_free( &tokens );+	return status;+}++static long+biblatexin_findref( bibl *bin, char *citekey )+{+	int n;+	long i;+	for ( i=0; i<bin->nrefs; ++i ) {+		n = fields_find( bin->ref[i], "refnum", -1 );+		if ( n==-1 ) continue;+		if ( !strcmp( bin->ref[i]->data[n].data, citekey ) ) return i;+	}+	return -1;+}++static void+biblatexin_nocrossref( bibl *bin, long i, int n, param *p )+{+	int n1 = fields_find( bin->ref[i], "REFNUM", -1 );+	if ( p->progname ) fprintf( stderr, "%s: ", p->progname );+	fprintf( stderr, "Cannot find cross-reference '%s'", +			bin->ref[i]->data[n].data);+	if ( n1!=-1 )+		fprintf( stderr, " for reference '%s'\n", +				bin->ref[i]->data[n1].data );+	fprintf( stderr, "\n" );+}++static int+biblatexin_crossref_oneref( fields *ref, fields *cross )+{+	int j, nl, ntype, fstatus;+	char *type, *nt, *nd;+	ntype = fields_find( ref, "INTERNAL_TYPE", -1 );+	type = ( char * ) fields_value( ref, ntype, FIELDS_CHRP_NOUSE );+	for ( j=0; j<cross->n; ++j ) {+		nt = ( char * ) fields_tag( cross, j, FIELDS_CHRP_NOUSE );+		if ( !strcasecmp( nt, "INTERNAL_TYPE" ) ) continue;+		if ( !strcasecmp( nt, "REFNUM" ) ) continue;+		if ( !strcasecmp( nt, "TITLE" ) ) {+			if ( !strcasecmp( type, "Inproceedings" ) ||+			     !strcasecmp( type, "Incollection" ) )+				nt = "booktitle";+		}+		nd = ( char * ) fields_value( cross, j, FIELDS_CHRP_NOUSE );+		nl = fields_level( cross, j ) + 1;+		fstatus = fields_add( ref, nt, nd, nl );+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;+	}+	return BIBL_OK;+}++static int+biblatexin_crossref( bibl *bin, param *p )+{+	int n, ncross, status = BIBL_OK;+	fields *ref, *cross;+	long i;+        for ( i=0; i<bin->nrefs; ++i ) {+		ref = bin->ref[i];+		n = fields_find( ref, "CROSSREF", -1 );+		if ( n==-1 ) continue;+		fields_setused( ref, n );+		ncross = biblatexin_findref(bin, (char*)fields_value(ref,n, FIELDS_CHRP_NOUSE));+		if ( ncross==-1 ) {+			biblatexin_nocrossref( bin, i, n, p );+			continue;+		}+		cross = bin->ref[ncross];+		status = biblatexin_crossref_oneref( ref, cross );+		if ( status!=BIBL_OK ) return status;+	}+	return status;+}++static int+biblatexin_cleanref( fields *bibin, param *p )+{+	int i, n, status;+	str *t, *d;+	n = fields_num( bibin );+	for ( i=0; i<n; ++i ) {+		t = fields_tag( bibin, i, FIELDS_STRP_NOUSE );+		d = fields_value( bibin, i, FIELDS_STRP_NOUSE );+		status = biblatexin_cleandata( t, d, bibin, p );+		if ( status!=BIBL_OK ) return status;+		if ( !strsearch( str_cstr( t ), "AUTHORS" ) ) {+			str_findreplace( d, "\n", " " );+			str_findreplace( d, "\r", " " );+		}+		else if ( !strsearch( str_cstr( t ), "ABSTRACT" ) ||+		     !strsearch( str_cstr( t ), "SUMMARY" ) || +		     !strsearch( str_cstr( t ), "NOTE" ) ) {+			str_findreplace( d, "\n", "" );+			str_findreplace( d, "\r", "" );+		}+	}+	return BIBL_OK;+}++static int+biblatexin_cleanf( bibl *bin, param *p )+{+	int status;+	long i;+        for ( i=0; i<bin->nrefs; ++i ) {+		status = biblatexin_cleanref( bin->ref[i], p );+		if ( status!=BIBL_OK ) return status;+	}+	status = biblatexin_crossref( bin, p );+	return status;+}++/*****************************************************+ PUBLIC: void biblatexin_typef()+*****************************************************/++static int+biblatexin_typef( fields *bibin, char *filename, int nrefs, param *p )+{+	int ntypename, nrefname, is_default;+	char *refname = "", *typename="";++	ntypename = fields_find( bibin, "INTERNAL_TYPE", LEVEL_MAIN );+	nrefname  = fields_find( bibin, "REFNUM",        LEVEL_MAIN );+	if ( nrefname!=-1 )  refname  = fields_value( bibin, nrefname,  FIELDS_CHRP_NOUSE );+        if ( ntypename!=-1 ) typename = fields_value( bibin, ntypename, FIELDS_CHRP_NOUSE );++	return get_reftype( typename, nrefs, p->progname, p->all, p->nall, refname, &is_default, REFTYPE_CHATTY );+}++/*****************************************************+ PUBLIC: int biblatexin_convertf(), returns BIBL_OK or BIBL_ERR_MEMERR+*****************************************************/++/* get_title_elements()+ *+ * find all of the biblatex title elements for the current level+ *    internal "TITLE"      -> "title", "booktitle", "maintitle"+ *    internal "SUBTITLE"   -> "subtitle", "booksubtitle", "mainsubtitle"+ *    internal "TITLEADDON" -> "titleaddon", "booktitleaddon", "maintitleaddon"+ *+ * place in ttl, subttl, and ttladdon strings+ *+ * return 1 if an element is found, 0 if not+ */+static int+get_title_elements( fields *bibin, int currlevel, int reftype, variants *all, int nall, str *ttl, str *subttl, str *ttladdon )+{+	int nfields, process, level, i;+	str *t, *d;+	char *newtag;++	strs_empty( ttl, subttl, ttladdon, NULL );++	nfields = fields_num( bibin );++	for ( i=0; i<nfields; ++i ) {++		/* ...skip already used titles */+		if ( fields_used( bibin, i ) ) continue;++		/* ...skip empty elements */+		t = fields_tag  ( bibin, i, FIELDS_STRP_NOUSE );+		d = fields_value( bibin, i, FIELDS_STRP_NOUSE );+		if ( d->len == 0 ) continue;++		if ( !translate_oldtag( t->data, reftype, all, nall, &process, &level, &newtag ) )+			continue;+		if ( process != TITLE ) continue;+		if ( level != currlevel ) continue;++		fields_setused( bibin, i );++		if ( !strcasecmp( newtag, "TITLE" ) ) {+			if ( str_has_value( ttl ) ) str_addchar( ttl, ' ' );+			str_strcat( ttl, d );+		} else if ( !strcasecmp( newtag, "SUBTITLE" ) ) {+			if ( str_has_value( subttl ) ) str_addchar( subttl, ' ' );+			str_strcat( subttl, d );+		} else if ( !strcasecmp( newtag, "TITLEADDON" ) ) {+			if ( str_has_value( ttladdon ) ) str_addchar( ttladdon, ' ' );+			str_strcat( ttladdon, d );+		}+	}++	return ( ttl->len>0 || subttl->len > 0 || ttladdon->len > 0 );+}++/* attach_subtitle()+ *+ * Add subtitle (if exists) to the title+ */+static void+attach_subtitle( str *title, str *subtitle )+{+	if ( str_has_value( subtitle ) ) {+		if ( str_has_value( title ) ) {+			if ( title->data[title->len-1]!=':' && title->data[title->len-1]!='?' )+				str_addchar( title, ':' );+			str_addchar( title, ' ' );+		}+		str_strcat( title, subtitle );+	}+}++/* attach_addon()+ *+ * Add titleaddon (if exists) to the title.+ */+static void+attach_addon( str *title, str *addon )+{+	if ( str_has_value( addon ) ) {+		if ( str_has_value( title ) ) {+			if ( title->data[title->len-1]!='.' )+				str_addchar( title, '.' );+			str_addchar( title, ' ' );+		}+		str_strcat( title, addon );+	}+}++static int+process_combined_title( fields *info, str *ttl, str *subttl, str *ttladdon, int currlevel )+{+	int fstatus, status = BIBL_OK;+	str combined;++	str_init( &combined );++	str_strcpy( &combined, ttl );+	attach_subtitle( &combined, subttl );+	attach_addon( &combined, ttladdon );++	if ( str_memerr( &combined ) ) {+		status = BIBL_ERR_MEMERR;+		goto out;+	}++	fstatus = fields_add( info, "TITLE", combined.data, currlevel );+	if ( fstatus==FIELDS_OK ) status = BIBL_ERR_MEMERR;+out:+	str_free( &combined );+	return status;+}++static int+process_separated_title( fields *info, str *ttl, str *subttl, str *ttladdon, int currlevel )+{+	int fstatus;+	if ( str_has_value( ttladdon ) ) {+		if ( subttl->len ) attach_addon( subttl, ttladdon );+		else attach_addon( ttl, ttladdon );+	}+	if ( str_has_value( ttl ) ) {+		fstatus = fields_add( info, "TITLE", str_cstr( ttl ), currlevel );+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;+	}+	if ( str_has_value( subttl ) ) {+		fstatus = fields_add( info, "SUBTITLE", str_cstr( subttl ), currlevel );+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;+	}+	return BIBL_OK;+}++static int+process_title_all( fields *bibin, fields *info, int reftype, param *p )+{+	int currlevel, found, status = BIBL_OK;+	str ttl, subttl, ttladdon;+	strs_init( &ttl, &subttl, &ttladdon, NULL );+	for ( currlevel = 0; currlevel<LEVEL_SERIES+2; currlevel++ ) {+		found = get_title_elements( bibin, currlevel, reftype, p->all, p->nall, &ttl, &subttl, &ttladdon );+		if ( !found ) continue;+		if ( p->nosplittitle )+			status = process_combined_title( info, &ttl, &subttl, &ttladdon, currlevel );+		else+			status = process_separated_title( info, &ttl, &subttl, &ttladdon, currlevel );+		if ( status!=BIBL_OK ) goto out;+	}+out:+	strs_free( &ttl, &subttl, &ttladdon, NULL );+	return status;+}+++static int+biblatex_matches_list( fields *info, char *tag, char *suffix, str *data, int level, slist *names, int *match )+{+	int i, fstatus, status = BIBL_OK;+	str newtag;++	*match = 0;+	if ( names->n==0 ) return status;++	str_init( &newtag );++	for ( i=0; i<names->n; ++i ) {+		if ( strcmp( str_cstr( data ), slist_cstr( names, i ) ) ) continue;+		str_initstrc( &newtag, tag );+		str_strcatc( &newtag, suffix );+		fstatus = fields_add( info, str_cstr( &newtag ), str_cstr( data ), level );+		if ( fstatus!=FIELDS_OK ) {+			status = BIBL_ERR_MEMERR;+			goto out;+		}+		*match = 1;+		goto out;+	}++out:+	str_free( &newtag );+	return status;+}++static int+biblatex_names( fields *info, char *tag, str *data, int level, slist *asis, slist *corps )+{+	int begin, end, ok, n, etal, i, match, status = BIBL_OK;+	slist tokens;++	/* If we match the asis or corps list add and bail. */+	status = biblatex_matches_list( info, tag, ":ASIS", data, level, asis, &match );+	if ( match==1 || status!=BIBL_OK ) return status;+	status = biblatex_matches_list( info, tag, ":CORP", data, level, corps, &match );+	if ( match==1 || status!=BIBL_OK ) return status;++	slist_init( &tokens );++	biblatex_split( &tokens, data );+	for ( i=0; i<tokens.n; ++i )+		biblatex_cleantoken( slist_str( &tokens, i ) );++	etal = name_findetal( &tokens );++	begin = 0;+	n = tokens.n - etal;+	while ( begin < n ) {++		end = begin + 1;++		while ( end < n && strcasecmp( slist_cstr( &tokens, end ), "and" ) )+			end++;++		if ( end - begin == 1 ) {+			ok = name_addsingleelement( info, tag, slist_cstr( &tokens, begin ), level, 0 );+			if ( !ok ) { status = BIBL_ERR_MEMERR; goto out; }+		} else {+			ok = name_addmultielement( info, tag, &tokens, begin, end, level );+			if ( !ok ) { status = BIBL_ERR_MEMERR; goto out; }+		}++		begin = end + 1;++		/* Handle repeated 'and' errors */+		while ( begin < n && !strcasecmp( slist_cstr( &tokens, begin ), "and" ) )+			begin++;++	}++	if ( etal ) {+		ok = name_addsingleelement( info, tag, "et al.", level, 0 );+		if ( !ok ) status = BIBL_ERR_MEMERR;+	}++out:+	slist_free( &tokens );+	return status;+}++static int+biblatexin_bltsubtype( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	int fstatus1, fstatus2;++	if ( !strcasecmp( str_cstr( invalue ), "magazine" ) ) {+		fstatus1 = fields_add( bibout, "NGENRE", "magazine article", LEVEL_MAIN );+		fstatus2 = fields_add( bibout, "NGENRE", "magazine",         LEVEL_HOST );+		if ( fstatus1!=FIELDS_OK || fstatus2!=FIELDS_OK ) return BIBL_ERR_MEMERR;+	}++	else if ( !strcasecmp( str_cstr( invalue ), "newspaper" ) ) {+		fstatus1 = fields_add( bibout, "NGENRE", "newspaper article", LEVEL_MAIN );+		fstatus2 = fields_add( bibout, "GENRE",  "newspaper",         LEVEL_HOST );+		if ( fstatus1!=FIELDS_OK || fstatus2!=FIELDS_OK ) return BIBL_ERR_MEMERR;+	}++	return BIBL_OK;+}++/* biblatex drops school field if institution is present */+static int+biblatexin_bltschool( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	int fstatus;+	if ( fields_find( bibin, "institution", LEVEL_ANY ) != -1 )+		return BIBL_OK;+	else {+		fstatus = fields_add( bibout, outtag, str_cstr( invalue ), level );+		if ( fstatus==FIELDS_OK ) return BIBL_OK;+		else return BIBL_ERR_MEMERR;+	}+}++static int+biblatexin_bltthesistype( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	char *p = invalue->data;+	int fstatus = FIELDS_OK;+	/* type in the @thesis is used to distinguish Ph.D. and Master's thesis */+	if ( !strncasecmp( p, "phdthesis", 9 ) ) {+		fstatus = fields_replace_or_add( bibout, "NGENRE", "Ph.D. thesis", level );+	} else if ( !strncasecmp( p, "mastersthesis", 13 ) || !strncasecmp( p, "masterthesis", 12 ) ) {+		fstatus = fields_replace_or_add( bibout, "NGENRE", "Masters thesis", level );+	} else if ( !strncasecmp( p, "mathesis", 8 ) ) {+		fstatus = fields_replace_or_add( bibout, "NGENRE", "Masters thesis", level );+	} else if ( !strncasecmp( p, "diploma", 7 ) ) {+		fstatus = fields_replace_or_add( bibout, "NGENRE", "Diploma thesis", level );+	} else if ( !strncasecmp( p, "habilitation", 12 ) ) {+		fstatus = fields_replace_or_add( bibout, "NGENRE", "Habilitation thesis", level );+	}+	if ( fstatus==FIELDS_OK ) return BIBL_OK;+	else return BIBL_ERR_MEMERR;+}++static int+biblatexin_bteprint( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	int neprint, netype, fstatus;+	char *eprint = NULL, *etype = NULL;++	neprint = fields_find( bibin, "eprint", -1 );+	netype  = fields_find( bibin, "eprinttype", -1 );++	if ( neprint!=-1 ) eprint = bibin->data[neprint].data;+	if ( netype!=-1 )  etype =  bibin->data[netype].data;++	if ( eprint && etype ) {+		if ( !strncasecmp( etype, "arxiv", 5 ) ) {+			fstatus = fields_add( bibout, "ARXIV", eprint, level );+			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;+		} else if ( !strncasecmp( etype, "jstor", 5 ) ) {+			fstatus = fields_add( bibout, "JSTOR", eprint, level );+			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;+		} else if ( !strncasecmp( etype, "pubmed", 6 ) ) {+			fstatus = fields_add( bibout, "PMID", eprint, level );+			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;+		} else if ( !strncasecmp( etype, "medline", 7 ) ) {+			fstatus = fields_add( bibout, "MEDLINE", eprint, level );+			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;+		} else {+			fstatus = fields_add( bibout, "EPRINT", eprint, level );+			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;+			fstatus = fields_add( bibout, "EPRINTTYPE", etype, level );+			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;+		}+		fields_setused( bibin, neprint );+		fields_setused( bibin, netype );+	} else if ( eprint ) {+		fstatus = fields_add( bibout, "EPRINT", eprint, level );+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;+		fields_setused( bibin, neprint );+	} else if ( etype ) {+		fstatus = fields_add( bibout, "EPRINTTYPE", etype, level );+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;+		fields_setused( bibin, netype );+	}+	return BIBL_OK;+}++static int+biblatexin_btgenre( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	if ( fields_add( bibout, "NGENRE", str_cstr( invalue ), level ) == FIELDS_OK ) return BIBL_OK;+	else return BIBL_ERR_MEMERR;+}++/* biblatexin_howpublished()+ *+ *    howpublished={},+ *+ * Normally indicates the manner in which something was+ * published in lieu of a formal publisher, so typically+ * 'howpublished' and 'publisher' will never be in the+ * same reference.+ *+ * Occasionally, people put Diploma thesis information+ * into this field, so check for that first.+ */+static int+biblatexin_howpublished( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	int fstatus;++        if ( !strncasecmp( str_cstr( invalue ), "Diplom", 6 ) )+                fstatus = fields_replace_or_add( bibout, "NGENRE", "Diploma thesis", level );+        else if ( !strncasecmp( str_cstr( invalue ), "Habilitation", 13 ) )+                fstatus = fields_replace_or_add( bibout, "NGENRE", "Habilitation thesis", level );+        else+		fstatus = fields_add( bibout, "PUBLISHER", str_cstr( invalue ), level );++	if ( fstatus==FIELDS_OK ) return BIBL_OK;+	else return BIBL_ERR_MEMERR;+}++/*+ * biblatex has multiple editor fields "editor", "editora", "editorb", "editorc",+ * each of which can be modified from a type of "EDITOR" via "editortype",+ * "editoratype", "editorbtype", "editorctype".+ *+ * Defined types:+ *     "editor"+ *     "collaborator"+ *     "compiler"+ *     "redactor"+ *+ *     "reviser" ?+ *     "founder" ?+ *     "continuator" ?+ *+ *  bibtex-chicago+ *+ *     "director"+ *     "producer"+ *     "conductor"+ *     "none" (for performer)+ */+static int+biblatexin_blteditor( fields *bibin, int m, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	char *editor_fields[] = { "editor", "editora", "editorb", "editorc" };+	char *editor_types[]  = { "editortype", "editoratype", "editorbtype", "editorctype" };+	int i, n = 0, ntype, neditors = sizeof( editor_fields ) / sizeof( editor_fields[0] );+	char *type, *usetag = "EDITOR";+	for ( i=1; i<neditors; ++i )+		if ( !strcasecmp( intag->data, editor_fields[i] ) ) n = i;+	ntype = fields_find( bibin, editor_types[n], LEVEL_ANY );+	if ( ntype!=-1 ) {+		type = fields_value( bibin, ntype, FIELDS_CHRP_NOUSE );+		if ( !strcasecmp( type, "collaborator" ) )  usetag = "COLLABORATOR";+		else if ( !strcasecmp( type, "compiler" ) ) usetag = "COMPILER";+		else if ( !strcasecmp( type, "redactor" ) ) usetag = "REDACTOR";+		else if ( !strcasecmp( type, "director" ) ) usetag = "DIRECTOR";+		else if ( !strcasecmp( type, "producer" ) ) usetag = "PRODUCER";+		else if ( !strcasecmp( type, "none" ) )     usetag = "PERFORMER";+	}+	return biblatex_names( bibout, usetag, invalue, level, &(pm->asis), &(pm->corps) );+}++static int+biblatexin_person( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	return biblatex_names( bibout, outtag, invalue, level, &(pm->asis), &(pm->corps) );+}++static void+biblatexin_notag( param *p, char *tag )+{+	if ( p->verbose && strcmp( tag, "INTERNAL_TYPE" ) ) {+		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );+		fprintf( stderr, " Cannot find tag '%s'\n", tag );+	}+}++static int+biblatexin_convertf( fields *bibin, fields *bibout, int reftype, param *p )+{+	static int (*convertfns[NUM_REFTYPES])(fields *, int, str *, str *, int, param *, char *, fields *) = {+		[ 0 ... NUM_REFTYPES-1 ] = generic_null,+		[ SIMPLE          ] = generic_simple,+		[ PAGES           ] = generic_pages,+		[ NOTES           ] = generic_notes,+		[ PERSON          ] = biblatexin_person,+		[ BLT_EDITOR      ] = biblatexin_blteditor,+		[ HOWPUBLISHED    ] = biblatexin_howpublished,+		[ URL             ] = generic_url,+		[ BT_GENRE        ] = biblatexin_btgenre,+		[ BT_EPRINT       ] = biblatexin_bteprint,+		[ BLT_THESIS_TYPE ] = biblatexin_bltthesistype,+		[ BLT_SCHOOL      ] = biblatexin_bltschool,+		[ BLT_SUBTYPE     ] = biblatexin_bltsubtype,+		[ BLT_SKIP        ] = generic_skip,+		[ TITLE           ] = generic_null,    /* delay processing until later */+	};++	int process, level, i, nfields, status = BIBL_OK;+	str *intag, *invalue;+	char *outtag;++	nfields = fields_num( bibin );+	for ( i=0; i<nfields; ++i ) {++               /* skip ones already "used" such as successful crossref */+                if ( fields_used( bibin, i ) ) continue;++		/* skip ones with no data or no tags (e.g. don't match ALWAYS/DEFAULT entries) */+		intag   = fields_tag  ( bibin, i, FIELDS_STRP_NOUSE );+		invalue = fields_value( bibin, i, FIELDS_STRP_NOUSE );+		if ( str_is_empty( intag ) || str_is_empty( invalue ) ) continue;++		if ( !translate_oldtag( intag->data, reftype, p->all, p->nall, &process, &level, &outtag ) ) {+			biblatexin_notag( p, intag->data );+			continue;+		}++		status = convertfns[ process ]( bibin, i, intag, invalue, level, p, outtag, bibout );+		if ( status!=BIBL_OK ) return status;++		if ( convertfns[ process ] != generic_null )+			fields_setused( bibin, i );++	}++	status = process_title_all( bibin, bibout, reftype, p );++	if ( status==BIBL_OK && p->verbose ) fields_report( bibout, stdout );  	return status; }
− bibutils/biblatexin.h
@@ -1,33 +0,0 @@-/*- * biblatexin.h- *- * Copyright (c) Chris Putnam 2008-2014- *- * Source code released under the GPL version 2- *- */-#ifndef BIBLATEXIN_H-#define BIBLATEXIN_H--#include "newstr.h"-#include "list.h"-#include "fields.h"-#include "bibl.h"-#include "bibutils.h"-#include "reftypes.h"--extern int  biblatexin_convertf( fields *bibin, fields *info, int reftype, param *p, variants *all, int nall );-extern int  biblatexin_processf( fields *bibin, char *data, char *filename, long nref );-extern int  biblatexin_cleanf( bibl *bin, param *p );-extern int  biblatexin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );-extern int  biblatexin_typef( fields *bibin, char *filename, int nrefs,-        param *p, variants *all, int nall );--extern void biblatexin_initparams( param *p, const char *progname );--extern variants biblatex_all[];-extern int biblatex_nall;---#endif-
bibutils/bibtexin.c view
@@ -1,1375 +1,1325 @@ /*  * bibtexin.c  *- * Copyright (c) Chris Putnam 2003-2014- *- * Program and source code released under the GPL version 2- *- */-#include <stdio.h>-#include <stdlib.h>-#include <string.h>-#include <ctype.h>-#include "is_ws.h"-#include "strsearch.h"-#include "newstr.h"-#include "newstr_conv.h"-#include "fields.h"-#include "list.h"-#include "name.h"-#include "title.h"-#include "reftypes.h"-#include "bibtexin.h"--static list find    = { 0, 0, NULL, 0 };-static list replace = { 0, 0, NULL, 0 };--extern const char progname[];--/*****************************************************- PUBLIC: void bibtexin_initparams()-*****************************************************/-void-bibtexin_initparams( param *p, const char *progname )-{-	p->readformat       = BIBL_BIBTEXIN;-	p->charsetin        = BIBL_CHARSET_DEFAULT;-	p->charsetin_src    = BIBL_SRC_DEFAULT;-	p->latexin          = 1;-	p->xmlin            = 0;-	p->utf8in           = 0;-	p->nosplittitle     = 0;-	p->verbose          = 0;-	p->addcount         = 0;-	p->output_raw       = 0;--	p->readf    = bibtexin_readf;-	p->processf = bibtexin_processf;-	p->cleanf   = bibtexin_cleanf;-	p->typef    = bibtexin_typef;-	p->convertf = bibtexin_convertf;-	p->all      = bibtex_all;-	p->nall     = bibtex_nall;--	list_init( &(p->asis) );-	list_init( &(p->corps) );--	if ( !progname ) p->progname = NULL;-	else p->progname = strdup( progname );-}--/*****************************************************- PUBLIC: int bibtexin_readf()-*****************************************************/--/*- * readf can "read too far", so we store this information in line, thus- * the next new text is in line, either from having read too far or- * from the next chunk obtained via newstr_fget()- *- * return 1 on success, 0 on error/end-of-file- *- */-static int-readmore( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line )-{-	if ( line->len ) return 1;-	else return newstr_fget( fp, buf, bufsize, bufpos, line );-}--/*- * readf()- *- * returns zero if cannot get reference and hit end of-file- * returns 1 if last reference in file, 2 if reference within file- */-int-bibtexin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset )-{-	int haveref = 0;-	char *p;-	*fcharset = CHARSET_UNKNOWN;-	while ( haveref!=2 && readmore( fp, buf, bufsize, bufpos, line ) ) {-		if ( line->len == 0 ) continue; /* blank line */-		p = &(line->data[0]);-		/* Recognize UTF8 BOM */-		if ( line->len > 2 && -				(unsigned char)(p[0])==0xEF &&-				(unsigned char)(p[1])==0xBB &&-				(unsigned char)(p[2])==0xBF ) {-			*fcharset = CHARSET_UNICODE;-			p += 3;-		}-		p = skip_ws( p );-		if ( *p == '%' ) { /* commented out line */-			newstr_empty( line );-			continue;-		}-		if ( *p == '@' ) haveref++;-		if ( haveref && haveref<2 ) {-			newstr_strcat( reference, p );-			newstr_addchar( reference, '\n' );-			newstr_empty( line );-		} else if ( !haveref ) newstr_empty( line );-	-	}-	return haveref;-}--/*****************************************************- PUBLIC: int bibtexin_processf()-*****************************************************/--static char*-process_bibtextype( char *p, newstr *type )-{-	newstr tmp;-	newstr_init( &tmp );--	if ( *p=='@' ) p++;-	p = newstr_cpytodelim( &tmp, p, "{( \t\r\n", 0 );-	p = skip_ws( p );-	if ( *p=='{' || *p=='(' ) p++;-	p = skip_ws( p );--	if ( tmp.len ) newstr_strcpy( type, tmp.data );-	else newstr_empty( type );--	newstr_free( &tmp );-	return p;-}--static char*-process_bibtexid( char *p, newstr *id )-{-	char *start_p = p;-	newstr tmp;--	newstr_init( &tmp );-	p = newstr_cpytodelim( &tmp, p, ",", 1 );--	if ( tmp.len ) {-		if ( strchr( tmp.data, '=' ) ) {-			/* Endnote writes bibtex files w/o fields, try to-			 * distinguish via presence of an equal sign.... if-			 * it's there, assume that it's a tag/data pair instead-			 * and roll back.-			 */-			p = start_p;-			newstr_empty( id );-		} else {-			newstr_strcpy( id, tmp.data );-		}-	} else {-		newstr_empty( id );-	}--	newstr_free( &tmp );-	return skip_ws( p );-}--static char *-bibtex_tag( char *p, newstr *tag )-{-	p = newstr_cpytodelim( tag, skip_ws( p ), "= \t\r\n", 0 );-	if ( newstr_memerr( tag ) ) return NULL;-	return skip_ws( p );-}--static char *-bibtex_data( char *p, fields *bibin, list *tokens )-{-	unsigned int nbracket = 0, nquotes = 0;-	char *startp = p;-	newstr tok, *t;--	newstr_init( &tok );-	while ( p && *p ) {-		if ( !nquotes && !nbracket ) {-			if ( *p==',' || *p=='=' || *p=='}' || *p==')' )-				goto out;-		}-		if ( *p=='\"' && nbracket==0 && ( p==startp || *(p-1)!='\\' ) ) {-			nquotes = !nquotes;-			newstr_addchar( &tok, *p );-			if ( !nquotes ) {-				if ( newstr_memerr( &tok ) ) { p=NULL; goto out; }-				t = list_add( tokens, &tok );-				if ( !t ) { p=NULL; goto out0; }-				newstr_empty( &tok );-			}-		} else if ( *p=='#' && !nquotes && !nbracket ) {-			if ( tok.len ) {-				if ( newstr_memerr( &tok ) ) { p=NULL; goto out; }-				t = list_add( tokens, &tok );-				if ( !t ) { p=NULL; goto out0; }-			}-			newstr_strcpy( &tok, "#" );-			t = list_add( tokens, &tok );-			if ( !t ) { p=NULL; goto out0; }-			newstr_empty( &tok );-		} else if ( *p=='{' && !nquotes && ( p==startp || *(p-1)!='\\' ) ) {-			nbracket++;-			newstr_addchar( &tok, *p );-		} else if ( *p=='}' && !nquotes && ( p==startp || *(p-1)!='\\' ) ) {-			nbracket--;-			newstr_addchar( &tok, *p );-			if ( nbracket==0 ) {-				if ( newstr_memerr( &tok ) ) { p=NULL; goto out; }-				t = list_add( tokens, &tok );-				if ( !t ) { p=NULL; goto out; }-				newstr_empty( &tok );-			}-		} else if ( !is_ws( *p ) || nquotes || nbracket ) {-			if ( !is_ws( *p ) ) newstr_addchar( &tok, *p );-			else {-				if ( tok.len!=0 && *p!='\n' && *p!='\r' )-					newstr_addchar( &tok, *p );-				else if ( tok.len!=0 && (*p=='\n' || *p=='\r')) {-					newstr_addchar( &tok, ' ' );-					while ( is_ws( *(p+1) ) ) p++;-				}-			}-		} else if ( is_ws( *p ) ) {-			if ( tok.len ) {-				if ( newstr_memerr( &tok ) ) { p=NULL; goto out; }-				t = list_add( tokens, &tok );-				if ( !t ) { p=NULL; goto out; }-				newstr_empty( &tok );-			}-		}-		p++;-	}-out:-	if ( nbracket!=0 ) {-		fprintf( stderr, "%s: Mismatch in number of brackets in reference.\n", progname );-	}-	if ( nquotes!=0 ) {-		fprintf( stderr, "%s: Mismatch in number of quotes in reference.\n", progname );-	}-	if ( tok.len ) {-		if ( newstr_memerr( &tok ) ) { p = NULL; goto out; }-		t = list_add( tokens, &tok );-		if ( !t ) p = NULL;-	}-out0:-	newstr_free( &tok );-	return p;-}--/* replace_strings()- *- * do string replacement -- only if unprotected by quotation marks or curly brackets- */-static void-replace_strings( list *tokens, fields *bibin )-{-	int i, n, ok;-	newstr *s;-	char *q;-	i = 0;-	while ( i < tokens->n ) {-		s = list_get( tokens, i );-		if ( !strcmp( s->data, "#" ) ) {-		} else if ( s->data[0]!='\"' && s->data[0]!='{' ) {-			n = list_find( &find, s->data );-			if ( n!=-1 ) {-				newstr_newstrcpy( s, list_get( &replace, n ) );-			} else {-				q = s->data;-				ok = 1;-				while ( *q && ok ) {-					if ( !isdigit( *q ) ) ok = 0;-					q++;-				}-				if ( !ok ) {-					fprintf( stderr, "%s: Warning: Non-numeric "-					   "BibTeX elements should be in quotations or "-					   "curly brackets in reference.\n", progname );-				}-			}-		}-		i++;-	}-}--static int-string_concatenate( list *tokens, fields *bibin )-{-	newstr *s, *t;-	int i, status;-	i = 0;-	while ( i < tokens->n ) {-		s = list_get( tokens, i );-		if ( !strcmp( s->data, "#" ) ) {-			if ( i==0 || i==tokens->n-1 ) {-				fprintf( stderr, "%s: Warning: Stray string concatenation "-					"('#' character) in reference\n", progname );-				status = list_remove( tokens, i );-				if ( status!=LIST_OK ) return BIBL_ERR_MEMERR;-				continue;-			}-			s = list_get( tokens, i-1 );-			if ( s->data[0]!='\"' && s->data[s->len-1]!='\"' )-				fprintf( stderr, "%s: Warning: String concentation should "-					"be used in context of quotations marks.\n", progname );-			t = list_get( tokens, i+1 );-			if ( t->data[0]!='\"' && t->data[s->len-1]!='\"' )-				fprintf( stderr, "%s: Warning: String concentation should "-					"be used in context of quotations marks.\n", progname );-			if ( ( s->data[s->len-1]=='\"' && t->data[0]=='\"') || (s->data[s->len-1]=='}' && t->data[0]=='{') ) {-				newstr_trimend( s, 1 );-				newstr_trimbegin( t, 1 );-				newstr_newstrcat( s, t );-			} else {-				newstr_newstrcat( s, t );-			}-			status = list_remove( tokens, i );-			if ( status!=LIST_OK ) return BIBL_ERR_MEMERR;-			status = list_remove( tokens, i );-			if ( status!=LIST_OK ) return BIBL_ERR_MEMERR;-		} else i++;-	}-	return BIBL_OK;-}--/* return NULL on memory error */-static char *-process_bibtexline( char *p, newstr *tag, newstr *data, uchar stripquotes, fields *bibin )-{-	int i, status;-	list tokens;-	newstr *s;--	newstr_empty( data );--	p = bibtex_tag( p, tag );-	if ( p==NULL || tag->len==0 ) return p;--	list_init( &tokens );--	if ( *p=='=' ) {-		p = bibtex_data( p+1, bibin, &tokens );-		if ( p==NULL ) goto out;-	}--	replace_strings( &tokens, bibin );--	status = string_concatenate( &tokens, bibin );-	if ( status!=BIBL_OK ) {-		p = NULL;-		goto out;-	}--	for ( i=0; i<tokens.n; i++ ) {-		s = list_get( &tokens, i );-		if ( ( stripquotes && s->data[0]=='\"' && s->data[s->len-1]=='\"' ) ||-		     ( s->data[0]=='{' && s->data[s->len-1]=='}' ) ) {-			newstr_trimbegin( s, 1 );-			newstr_trimend( s, 1 );-		}-		newstr_newstrcat( data, list_get( &tokens, i ) );-	}-out:-	list_free( &tokens );-	return p;-}--/* process_cite()- *- */-static int-process_cite( fields *bibin, char *p, char *filename, long nref )-{-	int fstatus, status = BIBL_OK;-	newstr tag, data;--	newstrs_init( &tag, &data, NULL );--	p = process_bibtextype( p, &data );-	if ( data.len ) {-		fstatus = fields_add( bibin, "INTERNAL_TYPE", data.data, 0 );-		if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }-	}--	p = process_bibtexid( p, &data );-	if ( data.len ) {-		fstatus = fields_add( bibin, "REFNUM", data.data, 0 );-		if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }-	}--	while ( *p ) {-		p = process_bibtexline( p, &tag, &data, 1, bibin );-		if ( p==NULL ) { status = BIBL_ERR_MEMERR; goto out; }-		/* no anonymous or empty fields allowed */-		if ( tag.len && data.len ) {-			fstatus = fields_add( bibin, tag.data, data.data, 0 );-			if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }-		}-		newstrs_empty( &tag, &data, NULL );-	}-out:-	newstrs_free( &tag, &data, NULL );-	return status;-}--/* process_string()- *- * Handle lines like:- *- * '@STRING{TL = {Tetrahedron Lett.}}'- *- * p should point to just after '@STRING'- *- * In BibTeX, if a string is defined several times, the last one is kept.- *- */-static int-process_string( char *p )-{-	int n, status = BIBL_OK;-	newstr s1, s2, *t;-	newstrs_init( &s1, &s2, NULL );-	while ( *p && *p!='{' && *p!='(' ) p++;-	if ( *p=='{' || *p=='(' ) p++;-	p = process_bibtexline( skip_ws( p ), &s1, &s2, 0, NULL );-	if ( p==NULL ) { status = BIBL_ERR_MEMERR; goto out; }-	if ( s2.data ) {-		newstr_findreplace( &s2, "\\ ", " " );-	}-	if ( s1.data ) {-		n = list_find( &find, s1.data );-		if ( n==-1 ) {-			t = list_add( &find, &s1 );-			if ( t==NULL ) { status = BIBL_ERR_MEMERR; goto out; }-			if ( s2.data ) t = list_add( &replace, &s2 );-			else t = list_addc( &replace, "" );-			if ( t==NULL ) { status = BIBL_ERR_MEMERR; goto out; }-		} else {-			if ( s2.data ) t = list_set( &replace, n, &s2 );-			else t = list_setc( &replace, n, "" );-			if ( t==NULL ) { status = BIBL_ERR_MEMERR; goto out; }-		}-	}-out:-	newstrs_free( &s1, &s2, NULL );-	return status;-}--/* bibtexin_processf()- *- * Handle '@STRING', '@reftype', and ignore '@COMMENT'- */-int-bibtexin_processf( fields *bibin, char *data, char *filename, long nref )-{-	if ( !strncasecmp( data, "@STRING", 7 ) ) {-		process_string( data+7 );-		return 0;-	} else if ( !strncasecmp( data, "@COMMENT", 8 ) ) {-		/* Not sure if these are real Bibtex, but not references */-		return 0;-	} else {-		process_cite( bibin, data, filename, nref );-		return 1;-	}-}--/*****************************************************- PUBLIC: void bibtexin_cleanf()-*****************************************************/--static int-bibtex_protected( newstr *data )-{-	if ( data->data[0]=='{' && data->data[data->len-1]=='}' ) return 1;-	if ( data->data[0]=='\"' && data->data[data->len-1]=='\"' ) return 1;-	return 0;-}--static int-bibtex_split( list *tokens, newstr *s )-{-	int i, n = s->len, nbrackets = 0, status = BIBL_OK;-	newstr tok, *t;--	newstr_init( &tok );--	for ( i=0; i<n; ++i ) {-		if ( s->data[i]=='{' && ( i==0 || s->data[i-1]!='\\' ) ) {-			nbrackets++;-			newstr_addchar( &tok, '{' );-		} else if ( s->data[i]=='}' && ( i==0 || s->data[i-1]!='\\' ) ) {-			nbrackets--;-			newstr_addchar( &tok, '}' );-		} else if ( !is_ws( s->data[i] ) || nbrackets ) {-			newstr_addchar( &tok, s->data[i] );-		} else if ( is_ws( s->data[i] ) ) {-			if ( tok.len ) {-				t = list_add( tokens, &tok );-				if ( !t ) {-					status = BIBL_ERR_MEMERR;-					goto out;-				}-			}-			newstr_empty( &tok );-		}-	}-	if ( tok.len ) {-		t = list_add( tokens, &tok );-		if ( !t ) {-			status = BIBL_ERR_MEMERR;-			goto out;-		}-	}--	for ( i=0; i<tokens->n; ++i ) {-		newstr_trimstartingws( list_get( tokens, i ) );-		newstr_trimendingws( list_get( tokens, i ) );-	}-out:-	newstr_free( &tok );-	return status;-}--static int-bibtex_addtitleurl( fields *info, newstr *in )-{-	int fstatus, status = BIBL_OK;-	newstr s;-	char *p;--	newstr_init( &s );--	/* ...skip past "\href{" and copy to "}" */-	p = newstr_cpytodelim( &s, in->data + 6, "}", 1 );-	if ( newstr_memerr( &s ) ) { status = BIBL_ERR_MEMERR; goto out; }--	/* ...add to URL */-	fstatus = fields_add( info, "URL", s.data, 0 );-	if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }--	/* ...return deleted fragment to newstr in */-	p = newstr_cpytodelim( &s, p, "", 0 );-	if ( newstr_memerr( &s ) ) { status = BIBL_ERR_MEMERR; goto out; }-	newstr_swapstrings( &s, in );--out:-	newstr_free( &s );-	return status;-}--static int-is_url_tag( newstr *tag )-{-	if ( tag->len ) {-		if ( !strcasecmp( tag->data, "url" ) ) return 1;-	}-	return 0;-}--static int-is_name_tag( newstr *tag )-{-	if ( tag->len ) {-		if ( !strcasecmp( tag->data, "author" ) ) return 1;-		if ( !strcasecmp( tag->data, "editor" ) ) return 1;-	}-	return 0;-}--static void-bibtex_process_tilde( newstr *s )-{-	char *p, *q;-	int n = 0;--	p = q = s->data;-	if ( !p ) return;-	while ( *p ) {-		if ( *p=='~' ) {-			*q = ' ';-		} else if ( *p=='\\' && *(p+1)=='~' ) {-			n++;-			p++;-			*q = '~';-		} else {-			*q = *p;-		}-		p++;-		q++;-	}-	*q = '\0';-	s->len -= n;-}--static void-bibtex_process_bracket( newstr *s )-{-	char *p, *q;-	int n = 0;--	p = q = s->data;-	if ( !p ) return;-	while ( *p ) {-		if ( *p=='\\' && ( *(p+1)=='{' || *(p+1)=='}' ) ) {-			n++;-			p++;-			*q = *p;-			q++;-		} else if ( *p=='{' || *p=='}' ) {-			n++;-		} else {-			*q = *p;-			q++;-		}-		p++;-	}-	*q = '\0';-	s->len -= n;-}--static void-bibtex_cleantoken( newstr *s )-{-	/* 'textcomp' annotations */-	newstr_findreplace( s, "\\textit", "" );-	newstr_findreplace( s, "\\textbf", "" );-	newstr_findreplace( s, "\\textsl", "" );-	newstr_findreplace( s, "\\textsc", "" );-	newstr_findreplace( s, "\\textsf", "" );-	newstr_findreplace( s, "\\texttt", "" );-	newstr_findreplace( s, "\\textsubscript", "" );-	newstr_findreplace( s, "\\textsuperscript", "" );-	newstr_findreplace( s, "\\emph", "" );-	newstr_findreplace( s, "\\url", "" );-	newstr_findreplace( s, "\\mbox", "" );--	/* Other text annotations */-	newstr_findreplace( s, "\\it ", "" );-	newstr_findreplace( s, "\\em ", "" );--	newstr_findreplace( s, "\\%", "%" );-	newstr_findreplace( s, "\\$", "$" );-	while ( newstr_findreplace( s, "  ", " " ) ) {}--	/* 'textcomp' annotations that we don't want to substitute on output*/-	newstr_findreplace( s, "\\textdollar", "$" );-	newstr_findreplace( s, "\\textunderscore", "_" );--	bibtex_process_bracket( s );-	bibtex_process_tilde( s );--}--static int-bibtex_cleandata( newstr *tag, newstr *s, fields *info, param *p )-{-	int i, status;-	list tokens;-	newstr *tok;-	if ( !s->len ) return BIBL_OK;-	/* protect url from undergoing any parsing */-	if ( is_url_tag( tag ) ) return BIBL_OK;-	list_init( &tokens );-	status = bibtex_split( &tokens, s );-	if ( status!=BIBL_OK ) goto out;-	for ( i=0; i<tokens.n; ++i ) {-		tok = list_get( &tokens, i );-		if ( bibtex_protected( tok ) ) {-			if (!strncasecmp(tok->data,"\\href{", 6)) {-				bibtex_addtitleurl( info, tok );-			}-		}-		if ( p->latexin && !is_name_tag( tag ) && !is_url_tag( tag ) )-			bibtex_cleantoken( tok );-	}-	newstr_empty( s );-	for ( i=0; i<tokens.n; ++i ) {-		tok = list_get( &tokens, i );-		if ( i>0 ) newstr_addchar( s, ' ' );-		newstr_newstrcat( s, tok );-	}-out:-	list_free( &tokens );-	return status;-}--static int-bibtexin_cleanref( fields *bibin, param *p )-{-	int i, n, status;-	newstr *t, *d;-	n = fields_num( bibin );-	for ( i=0; i<n; ++i ) {-		t = fields_tag( bibin, i, FIELDS_STRP_NOUSE );-		d = fields_value( bibin, i, FIELDS_STRP_NOUSE );-		status = bibtex_cleandata( t, d, bibin, p );-		if ( status!=BIBL_OK ) return status;-	}-	return BIBL_OK;-}--static long-bibtexin_findref( bibl *bin, char *citekey )-{-	int n;-	long i;-	for ( i=0; i<bin->nrefs; ++i ) {-		n = fields_find( bin->ref[i], "refnum", -1 );-		if ( n==-1 ) continue;-		if ( !strcmp( bin->ref[i]->data[n].data, citekey ) ) return i;-	}-	return -1;-}--static void-bibtexin_nocrossref( bibl *bin, long i, int n, param *p )-{-	int n1 = fields_find( bin->ref[i], "REFNUM", -1 );-	if ( p->progname ) fprintf( stderr, "%s: ", p->progname );-	fprintf( stderr, "Cannot find cross-reference '%s'",-			bin->ref[i]->data[n].data );-	if ( n1!=-1 ) fprintf( stderr, " for reference '%s'\n",-			bin->ref[i]->data[n1].data );-	fprintf( stderr, "\n" );-}--static int-bibtexin_crossref_oneref( fields *bibref, fields *bibcross )-{-	int j, n, nl, ntype, fstatus, status = BIBL_OK;-	char *type, *nt, *nv;--	ntype = fields_find( bibref, "INTERNAL_TYPE", -1 );-	type = ( char * ) fields_value( bibref, ntype, FIELDS_CHRP_NOUSE );--	n = fields_num( bibcross );-	for ( j=0; j<n; ++j ) {-		nt = ( char * ) fields_tag( bibcross, j, FIELDS_CHRP_NOUSE );-		if ( !strcasecmp( nt, "INTERNAL_TYPE" ) ) continue;-		if ( !strcasecmp( nt, "REFNUM" ) ) continue;-		if ( !strcasecmp( nt, "TITLE" ) ) {-			if ( !strcasecmp( type, "Inproceedings" ) ||-			     !strcasecmp( type, "Incollection" ) )-				nt = "booktitle";-		}-		nv = ( char * ) fields_value( bibcross, j, FIELDS_CHRP_NOUSE );-		nl = fields_level( bibcross, j ) + 1;-		fstatus = fields_add( bibref, nt, nv, nl );-		if ( fstatus!=FIELDS_OK ) {-			status = BIBL_ERR_MEMERR;-			goto out;-		}-	}-out:-	return status;-}--static int-bibtexin_crossref( bibl *bin, param *p )-{-	int i, n, ncross, status = BIBL_OK;-	fields *bibref, *bibcross;--	for ( i=0; i<bin->nrefs; ++i ) {-		bibref = bin->ref[i];-		n = fields_find( bibref, "CROSSREF", -1 );-		if ( n==-1 ) continue;-		fields_setused( bibref, n );-		ncross = bibtexin_findref( bin, (char*) fields_value( bibref, n, FIELDS_CHRP ) );-		if ( ncross==-1 ) {-			bibtexin_nocrossref( bin, i, n, p );-			continue;-		}-		bibcross = bin->ref[ncross];-		status = bibtexin_crossref_oneref( bibref, bibcross );-		if ( status!=BIBL_OK ) goto out;-	}-out:-	return status;-}--int-bibtexin_cleanf( bibl *bin, param *p )-{-	int status = BIBL_OK;-	long i;--        for ( i=0; i<bin->nrefs; ++i )-		status = bibtexin_cleanref( bin->ref[i], p );-	bibtexin_crossref( bin, p );-	return status;-}--/*****************************************************- PUBLIC: int bibtexin_typef()-*****************************************************/--int-bibtexin_typef( fields *bibin, char *filename, int nrefs, param *p,-		variants *all, int nall )-{-	char *refnum = "";-	int reftype, n, nrefnum;-	n = fields_find( bibin, "INTERNAL_TYPE", 0 );-	nrefnum = fields_find( bibin, "REFNUM", 0 );-	if ( nrefnum!=-1 ) refnum = (bibin->data[nrefnum]).data;-	if ( n!=-1 )-		/* figure out type */-		reftype = get_reftype( (bibin->data[n]).data, nrefs,-			p->progname, all, nall, refnum );-	else-		/* no type info, go for default */-		reftype = get_reftype( "", nrefs, p->progname, all, nall, refnum );-	return reftype;-}--/*****************************************************- PUBLIC: int bibtexin_convertf(), returns BIBL_OK or BIBL_ERR_MEMERR-*****************************************************/--static int-bibtex_matches_list( fields *info, char *tag, char *suffix, newstr *data, int level,-		list *names, int *match )-{-	int i, fstatus, status = BIBL_OK;-	newstr newtag;--	*match = 0;-	if ( names->n==0 ) return status;--	newstr_init( &newtag );--	for ( i=0; i<names->n; ++i ) {-		if ( strcmp( data->data, list_getc( names, i ) ) ) continue;-		newstr_initstr( &newtag, tag );-		newstr_strcat( &newtag, suffix );-		fstatus = fields_add( info, newtag.data, data->data, level );-		if ( fstatus!=FIELDS_OK ) {-			status = BIBL_ERR_MEMERR;-			goto out;-		}-		*match = 1;-		goto out;-	}--out:-	newstr_free( &newtag );-	return status;-}--/*- * bibtex_names( info, newtag, field, level);- *- * split names in author list separated by and's (use '|' character)- * and add names- *- * returns BIBL_OK on success, BIBL_ERR_MEMERR on memory error- */-static int-bibtex_names( fields *info, char *tag, newstr *data, int level, list *asis,-	list *corps )-{-	int begin, end, ok, n, etal, i, status, match;-	list tokens;--	/* If we match the asis or corps list add and bail. */-	status = bibtex_matches_list( info, tag, ":ASIS", data, level, asis, &match );-	if ( match==1 || status!=BIBL_OK ) return status;-	status = bibtex_matches_list( info, tag, ":CORP", data, level, corps, &match );-	if ( match==1 || status!=BIBL_OK ) return status;--	list_init( &tokens );--	bibtex_split( &tokens, data );-	for ( i=0; i<tokens.n; ++i )-		bibtex_cleantoken( list_get( &tokens, i ) );--	etal = name_findetal( &tokens );--	begin = 0;-	n = tokens.n - etal;-	while ( begin < n ) {--		end = begin + 1;--		while ( end < n && strcasecmp( list_getc( &tokens, end ), "and" ) )-			end++;--		if ( end - begin == 1 ) {-			ok = name_addsingleelement( info, tag, list_getc( &tokens, begin ), level, 0 );-			if ( !ok ) { status = BIBL_ERR_MEMERR; goto out; }-		} else {-			ok = name_addmultielement( info, tag, &tokens, begin, end, level );-			if ( !ok ) { status = BIBL_ERR_MEMERR; goto out; }-		}--		begin = end + 1;--		/* Handle repeated 'and' errors: authors="G. F. Author and and B. K. Author" */-		while ( begin < n && !strcasecmp( list_getc( &tokens, begin ), "and" ) )-			begin++;-	}--	if ( etal ) {-		ok = name_addsingleelement( info, tag, "et al.", level, 0 );-		if ( !ok ) status = BIBL_ERR_MEMERR;-	}--out:-	list_free( &tokens );-	return status;-}--/* is_utf8_emdash()- *- * Internally pages="A---B" will convert --- to a UTF8- * emdash = 0xE2 (-30) 0x80 (-128) 0x94 (-108)- */-static int-is_utf8_emdash( char *p )-{-	static char emdash[3] = { -30, -128, -108 };-	if ( strncmp( p, emdash, 3 ) ) return 0;-	return 1;-}-/* is_utf8_endash()- *- * Internally pages="A--B" will convert -- to a UTF8- * endash = 0xE2 (-30) 0x80 (-128) 0x93 (-109)- */-static int-is_utf8_endash( char *p )-{-	static char endash[3] = { -30, -128, -109 };-	if ( strncmp( p, endash, 3 ) ) return 0;-	return 1;-}--static int-process_pages( fields *info, newstr *s, int level )-{-	int fstatus, status = BIBL_OK;-	newstr page;-	char *p;--	newstr_findreplace( s, " ", "" );-	if ( s->len==0 ) return 1;--	newstr_init( &page );-	p = skip_ws( s->data );-	while ( *p && !is_ws(*p) && *p!='-' && *p!='\r' && *p!='\n' && *p!=-30 )-		newstr_addchar( &page, *p++ );-	if ( page.len>0 ) {-		fstatus = fields_add( info, "PAGESTART", page.data, level );-		if ( fstatus!=FIELDS_OK ) {-			status = BIBL_ERR_MEMERR;-			goto out;-		}-	}--	while ( *p && (is_ws(*p) || *p=='-' ) ) p++;-	if ( *p && is_utf8_emdash( p ) ) p+=3;-	if ( *p && is_utf8_endash( p ) ) p+=3;--	newstr_empty( &page );-	while ( *p && !is_ws(*p) && *p!='-' && *p!='\r' && *p!='\n' )-		newstr_addchar( &page, *p++ );-	if ( page.len>0 ) {-		fstatus = fields_add( info, "PAGEEND", page.data, level );-		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR; -	}--out:-	newstr_free( &page );-	return status;-}--static int-process_urlcore( fields *info, newstr *d, int level, char *default_tag )-{-	char *p = d->data;-	int fstatus;-	if ( !strncasecmp( p, "\\urllink", 8 ) )-		fstatus = fields_add( info, "URL", p+8, level );-	else if ( !strncasecmp( p, "\\url", 4 ) )-		fstatus = fields_add( info, "URL", p+4, level );-	else if ( !strncasecmp( p, "arXiv:", 6 ) )-		fstatus = fields_add( info, "ARXIV", p+6, level );-	else if ( !strncasecmp( p, "http://arxiv.org/abs/", 21 ) )-		fstatus = fields_add( info, "ARXIV", p+21, level );-	else if ( !strncasecmp( p, "http:", 5 ) )-		fstatus = fields_add( info, "URL", p, level );-	else-		fstatus = fields_add( info, default_tag, p, level );-	if ( fstatus==FIELDS_OK ) return BIBL_OK;-	else return BIBL_ERR_MEMERR;-}--static int-process_url( fields *info, newstr *d, int level )-{-	return process_urlcore( info, d, level, "URL" );-}--/* Split keywords="" with semicolons.- * Commas are also frequently used, but will break- * entries like:- *       keywords="Microscopy, Confocal"- * Returns BIBL_OK or BIBL_ERR_MEMERR- */-static int-process_keywords( fields *info, newstr *d, int level )-{-	int fstatus, status = BIBL_OK;-	newstr keyword;-	char *p;--	if ( !d || d->len==0 ) return BIBL_OK;--	p = d->data;-	newstr_init( &keyword );--	while ( *p ) {-		p = newstr_cpytodelim( &keyword, skip_ws( p ), ";", 1 );-		newstr_trimendingws( &keyword );-		if ( newstr_memerr( &keyword ) ) {-			status = BIBL_ERR_MEMERR;-			goto out;-		}-		if ( keyword.len ) {-			fstatus = fields_add( info, "KEYWORD", keyword.data, level );-			if ( fstatus!=FIELDS_OK ) {-				status = BIBL_ERR_MEMERR;-				goto out;-			}-		}-	}-out:-	newstr_free( &keyword );-	return status;-}--/* proces_howpublished()- *- *    howpublished={},- *- * Normally indicates the manner in which something was- * published in lieu of a formal publisher, so typically- * 'howpublished' and 'publisher' will never be in the- * same reference.- *- * Occassionally, people put Diploma thesis information- * into the field, so check that first.- *- * Returns BIBL_OK or BIBL_ERR_MEMERR- */-static int-process_howpublished( fields *info, newstr *d, int level )-{-	int fstatus, status = BIBL_OK;-	char *p = d->data;-	if ( !strncasecmp( p, "Diplom", 6 ) ) {-		fstatus = fields_replace_or_add( info, "GENRE", "Diploma thesis", level );-		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;-	} else if ( !strncasecmp( p, "Habilitation", 13 ) ) {-		fstatus = fields_replace_or_add( info, "GENRE", "Habilitation thesis", level );-		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;-	} else if ( !strncasecmp( d->data, "http:", 5 ) ) {-		status = process_url( info, d, level );-	} else if ( !strncasecmp( d->data, "arXiv:", 6 ) ) {-		status = process_url( info, d, level );-	} else {-		fstatus = fields_add( info, "PUBLISHER", p, level );-		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;-	}-	return status;-}--/*- * sentelink = {file://localhost/full/path/to/file.pdf,Sente,PDF}- */-static int-process_sente( fields *info, newstr *d, int level )-{-	int fstatus, status = BIBL_OK;-	newstr link;--	newstr_init( &link );-	newstr_cpytodelim( &link, skip_ws( d->data ), ",", 0 );-	newstr_trimendingws( &link );-	if ( newstr_memerr( &link ) ) status = BIBL_ERR_MEMERR;--	if ( status==BIBL_OK && link.len ) {-		fstatus = fields_add( info, "FILEATTACH", link.data, level );-		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;-	}--	newstr_free( &link );-	return status;-}--/*- * BibTeX uses 'organization' in lieu of publisher if that field is missing.- * Otherwise output as- * <name type="corporate">- *    <namePart>The organization</namePart>- *    <role>- *       <roleTerm authority="marcrelator" type="text">organizer of meeting</roleTerm>- *    </role>- * </name>- */-static int-process_organization( fields *bibin, fields *info, newstr *d, int level )-{-	int n, fstatus;-	n = fields_find( bibin, "publisher", LEVEL_ANY );-	if ( n==-1 )-		fstatus = fields_add( info, "PUBLISHER", d->data, level );-	else-		fstatus = fields_add( info, "ORGANIZER:CORP", d->data, level );-	if ( fstatus==FIELDS_OK ) return BIBL_OK;-	else return BIBL_ERR_MEMERR;-}--static int-count_colons( char *p )-{-	int n = 0;-	while ( *p ) {-		if ( *p==':' ) n++;-		p++;-	}-	return n;-}--static int-first_colon( char *p )-{-	int n = 0;-	while ( p[n] && p[n]!=':' ) n++;-	return n;-}--static int-last_colon( char *p )-{-	int n = strlen( p ) - 1;-	while ( n>0 && p[n]!=':' ) n--;-	return n;-}--/*- * file={Description:/full/path/to/file.pdf:PDF}- */-static int-process_file( fields *info, newstr *d, int level )-{-	int fstatus, status = BIBL_OK;-	char *p = d->data;-	int i, n, n1, n2;-	newstr link;--	n = count_colons( p );-	if ( n > 1 ) {-		/* A DOS file can contain a colon ":C:/....pdf:PDF" */-		/* Extract after 1st and up to last colons */-		n1 = first_colon( p ) + 1;-		n2 = last_colon( p );-		newstr_init( &link );-		for ( i=n1; i<n2; ++i ) {-			newstr_addchar( &link, p[i] );-		}-		newstr_trimstartingws( &link );-		newstr_trimendingws( &link );-		if ( newstr_memerr( &link ) ) {-			status = BIBL_ERR_MEMERR;-			goto out;-		}-		if ( link.len ) {-			fstatus = fields_add( info, "FILEATTACH", link.data, level );-			if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;-		}-out:-		newstr_free( &link );-	} else {-		/* This field isn't formatted properly, so just copy directly */-		fstatus = fields_add( info, "FILEATTACH", p, level );-		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;-	}-	return status;-}--static int-process_note( fields *info, newstr *d, int level )-{-	int fstatus, status = BIBL_OK;-	if ( !strncasecmp( d->data, "http:", 5 ) ||-	     !strncasecmp( d->data, "arXiv:", 6 ) ) {-		status = process_url( info, d, level );-	} else {-		fstatus = fields_add( info, "NOTES", d->data, level );-		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;-	}-	return status;-}--static void-bibtexin_notag( param *p, char *tag )-{-	if ( p->verbose && strcmp( tag, "INTERNAL_TYPE" ) ) {-		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );-		fprintf( stderr, "Cannot find tag '%s'\n", tag );-	}-}--/* bibtexin_titleinbook_isbooktitle()- *- * Normally, the title field of inbook refers to the book.  The- * section in a @inbook reference is untitled.  If it's titled,- * the @incollection should be used.  For example, in:- *- * @inbook{- *    title="xxx"- * }- *- * the booktitle is "xxx".- *- * However, @inbook is frequently abused (and treated like- * @incollection) so that title and booktitle are present- * and title is now 'supposed' to refer to the section.  For example:- *- * @inbook{- *     title="yyy",- *     booktitle="xxx"- * }- *- * Therefore report whether or not booktitle is present as well- * as title in @inbook references.  If not, then make 'title'- * correspond to the title of the book, not the section.- *- */-static int-bibtexin_titleinbook_isbooktitle( char *intag, fields *bibin )-{-	int n;--	/* ...look only at 'title="xxx"' elements */-	if ( strcasecmp( intag, "TITLE" ) ) return 0;--	/* ...look only at '@inbook' references */-	n = fields_find( bibin, "INTERNAL_TYPE", -1 );-	if ( n==-1 ) return 0;-	if ( strcasecmp( fields_value( bibin, n, FIELDS_CHRP ), "INBOOK" ) ) return 0;--	/* ...look to see if 'booktitle="yyy"' exists */-	n = fields_find( bibin, "BOOKTITLE", -1 );-	if ( n==-1 ) return 0;-	else return 1;-}-static int-bibtexin_title_process( fields *info, char *outtag, fields *bibin, newstr *t, newstr *d, int level, int nosplittitle )-{-	char *intag = t->data;-	char *indata = d->data;-	int ok;-	if ( bibtexin_titleinbook_isbooktitle( intag, bibin ) ) level=LEVEL_MAIN;-	ok = title_process( info, outtag, indata, level, nosplittitle );-	if ( ok ) return BIBL_OK;-	else return BIBL_ERR_MEMERR;-}--static int-bibtex_simple( fields *info, char *outtag, newstr *d, int level )-{-	int fstatus;-	fstatus = fields_add( info, outtag, d->data, level );-	if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;-	return BIBL_OK;-}--int-bibtexin_convertf( fields *bibin, fields *info, int reftype, param *p,-		variants *all, int nall )-{-	int process, level, i, n, nfields, status;-	newstr *t, *d;-	char *outtag;--	nfields = fields_num( bibin );-	for ( i=0; i<nfields; ++i ) {--		if ( fields_used( bibin, i ) ) continue; /* e.g. successful crossref */-		if ( fields_nodata( bibin, i ) ) continue;--		t = fields_tag( bibin, i, FIELDS_STRP );-		if ( t->len == 0 ) continue; /* Don't consider with null tags */-		n = process_findoldtag( t->data, reftype, all, nall );-		if ( n==-1 ) {-			bibtexin_notag( p, t->data );-			continue;-		}--		d = fields_value( bibin, i, FIELDS_STRP );--		process = ((all[reftype]).tags[n]).processingtype;-		level   = ((all[reftype]).tags[n]).level;-		outtag  = ((all[reftype]).tags[n]).newstr;--		switch( process ) {--		case SIMPLE:-			status = bibtex_simple( info, outtag, d, level );-			break;--		case TITLE:-			status = bibtexin_title_process( info, "TITLE", bibin, t, d, level, p->nosplittitle );-			break;--		case PERSON:-			status = bibtex_names( info, outtag, d, level, &(p->asis), &(p->corps) );-			break;--		case PAGES:-			status = process_pages( info, d, level );-			break;--		case KEYWORD:-			status = process_keywords( info, d, level );-			break;--		case HOWPUBLISHED:-			status = process_howpublished( info, d, level );-			break;--		case LINKEDFILE:-			status = process_file( info, d, level );-			break;--		case BT_NOTE:-			status = process_note( info, d, level );-			break;--		case BT_SENTE:-			status = process_sente( info, d, level );-			break;--		case BT_URL:-			status = process_url( info, d, level );-			break;--		case BT_ORG:-			status = process_organization( bibin, info, d, level );-			break;--		default:-			status = BIBL_OK;-			break;-		}--		if ( status!=BIBL_OK ) return status;-	}-	return status;-}-+ * Copyright (c) Chris Putnam 2003-2017+ *+ * Program and source code released under the GPL version 2+ *+ */+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <ctype.h>+#include "is_ws.h"+#include "str.h"+#include "utf8.h"+#include "str_conv.h"+#include "fields.h"+#include "slist.h"+#include "name.h"+#include "title.h"+#include "url.h"+#include "reftypes.h"+#include "bibformats.h"+#include "generic.h"++static slist find    = { 0, 0, 0, NULL };+static slist replace = { 0, 0, 0, NULL };++extern variants bibtex_all[];+extern int bibtex_nall;++/*****************************************************+ PUBLIC: void bibtexin_initparams()+*****************************************************/++static int  bibtexin_convertf( fields *bibin, fields *info, int reftype, param *p );+static int  bibtexin_processf( fields *bibin, char *data, char *filename, long nref, param *p );+static int  bibtexin_cleanf( bibl *bin, param *p );+static int  bibtexin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset );+static int  bibtexin_typef( fields *bibin, char *filename, int nrefs, param *p );++void+bibtexin_initparams( param *p, const char *progname )+{+	p->readformat       = BIBL_BIBTEXIN;+	p->charsetin        = BIBL_CHARSET_DEFAULT;+	p->charsetin_src    = BIBL_SRC_DEFAULT;+	p->latexin          = 1;+	p->xmlin            = 0;+	p->utf8in           = 0;+	p->nosplittitle     = 0;+	p->verbose          = 0;+	p->addcount         = 0;+	p->output_raw       = 0;++	p->readf    = bibtexin_readf;+	p->processf = bibtexin_processf;+	p->cleanf   = bibtexin_cleanf;+	p->typef    = bibtexin_typef;+	p->convertf = bibtexin_convertf;+	p->all      = bibtex_all;+	p->nall     = bibtex_nall;++	slist_init( &(p->asis) );+	slist_init( &(p->corps) );++	if ( !progname ) p->progname = NULL;+	else p->progname = strdup( progname );+}++/*****************************************************+ PUBLIC: int bibtexin_readf()+*****************************************************/++/*+ * readf can "read too far", so we store this information in line, thus+ * the next new text is in line, either from having read too far or+ * from the next chunk obtained via str_fget()+ *+ * return 1 on success, 0 on error/end-of-file+ *+ */+static int+readmore( FILE *fp, char *buf, int bufsize, int *bufpos, str *line )+{+	if ( line->len ) return 1;+	else return str_fget( fp, buf, bufsize, bufpos, line );+}++/*+ * readf()+ *+ * returns zero if cannot get reference and hit end of-file+ * returns 1 if last reference in file, 2 if reference within file+ */+static int+bibtexin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset )+{+	int haveref = 0;+	char *p;+	*fcharset = CHARSET_UNKNOWN;+	while ( haveref!=2 && readmore( fp, buf, bufsize, bufpos, line ) ) {+		if ( line->len == 0 ) continue; /* blank line */+		p = &(line->data[0]);+		/* Recognize UTF8 BOM */+		if ( line->len > 2 && +				(unsigned char)(p[0])==0xEF &&+				(unsigned char)(p[1])==0xBB &&+				(unsigned char)(p[2])==0xBF ) {+			*fcharset = CHARSET_UNICODE;+			p += 3;+		}+		p = skip_ws( p );+		if ( *p == '%' ) { /* commented out line */+			str_empty( line );+			continue;+		}+		if ( *p == '@' ) haveref++;+		if ( haveref && haveref<2 ) {+			str_strcatc( reference, p );+			str_addchar( reference, '\n' );+			str_empty( line );+		} else if ( !haveref ) str_empty( line );+	+	}+	return haveref;+}++/*****************************************************+ PUBLIC: int bibtexin_processf()+*****************************************************/++static char*+process_bibtextype( char *p, str *type )+{+	str tmp;+	str_init( &tmp );++	if ( *p=='@' ) p++;+	p = str_cpytodelim( &tmp, p, "{( \t\r\n", 0 );+	p = skip_ws( p );+	if ( *p=='{' || *p=='(' ) p++;+	p = skip_ws( p );++	if ( str_has_value( &tmp ) ) str_strcpy( type, &tmp );+	else str_empty( type );++	str_free( &tmp );+	return p;+}++static char*+process_bibtexid( char *p, str *id )+{+	char *start_p = p;+	str tmp;++	str_init( &tmp );+	p = str_cpytodelim( &tmp, p, ",", 1 );++	if ( str_has_value( &tmp ) ) {+		if ( strchr( tmp.data, '=' ) ) {+			/* Endnote writes bibtex files w/o fields, try to+			 * distinguish via presence of an equal sign.... if+			 * it's there, assume that it's a tag/data pair instead+			 * and roll back.+			 */+			p = start_p;+			str_empty( id );+		} else {+			str_strcpy( id, &tmp );+		}+	} else {+		str_empty( id );+	}++	str_free( &tmp );+	return skip_ws( p );+}++static char *+bibtex_tag( char *p, str *tag )+{+	p = str_cpytodelim( tag, skip_ws( p ), "= \t\r\n", 0 );+	if ( str_memerr( tag ) ) return NULL;+	return skip_ws( p );+}++static char *+bibtex_data( char *p, fields *bibin, slist *tokens, long nref, param *pm )+{+	unsigned int nbracket = 0, nquotes = 0;+	char *startp = p;+	str tok, *t;++	str_init( &tok );+	while ( p && *p ) {+		if ( !nquotes && !nbracket ) {+			if ( *p==',' || *p=='=' || *p=='}' || *p==')' )+				goto out;+		}+		if ( *p=='\"' && nbracket==0 && ( p==startp || *(p-1)!='\\' ) ) {+			nquotes = !nquotes;+			str_addchar( &tok, *p );+			if ( !nquotes ) {+				if ( str_memerr( &tok ) ) { p=NULL; goto out; }+				t = slist_add( tokens, &tok );+				if ( !t ) { p=NULL; goto out0; }+				str_empty( &tok );+			}+		} else if ( *p=='#' && !nquotes && !nbracket ) {+			if ( str_has_value( &tok ) ) {+				if ( str_memerr( &tok ) ) { p=NULL; goto out; }+				t = slist_add( tokens, &tok );+				if ( !t ) { p=NULL; goto out0; }+			}+			str_strcpyc( &tok, "#" );+			t = slist_add( tokens, &tok );+			if ( !t ) { p=NULL; goto out0; }+			str_empty( &tok );+		} else if ( *p=='{' && !nquotes && ( p==startp || *(p-1)!='\\' ) ) {+			nbracket++;+			str_addchar( &tok, *p );+		} else if ( *p=='}' && !nquotes && ( p==startp || *(p-1)!='\\' ) ) {+			nbracket--;+			str_addchar( &tok, *p );+			if ( nbracket==0 ) {+				if ( str_memerr( &tok ) ) { p=NULL; goto out; }+				t = slist_add( tokens, &tok );+				if ( !t ) { p=NULL; goto out; }+				str_empty( &tok );+			}+		} else if ( !is_ws( *p ) || nquotes || nbracket ) {+			if ( !is_ws( *p ) ) str_addchar( &tok, *p );+			else {+				if ( tok.len!=0 && *p!='\n' && *p!='\r' )+					str_addchar( &tok, *p );+				else if ( tok.len!=0 && (*p=='\n' || *p=='\r')) {+					str_addchar( &tok, ' ' );+					while ( is_ws( *(p+1) ) ) p++;+				}+			}+		} else if ( is_ws( *p ) ) {+			if ( tok.len ) {+				if ( str_memerr( &tok ) ) { p=NULL; goto out; }+				t = slist_add( tokens, &tok );+				if ( !t ) { p=NULL; goto out; }+				str_empty( &tok );+			}+		}+		p++;+	}+out:+	if ( nbracket!=0 ) {+		fprintf( stderr, "%s: Mismatch in number of brackets in reference %ld.\n", pm->progname, nref );+	}+	if ( nquotes!=0 ) {+		fprintf( stderr, "%s: Mismatch in number of quotes in reference %ld.\n", pm->progname, nref );+	}+	if ( str_has_value( &tok ) ) {+		if ( str_memerr( &tok ) ) { p = NULL; goto out; }+		t = slist_add( tokens, &tok );+		if ( !t ) p = NULL;+	}+out0:+	str_free( &tok );+	return p;+}++/* replace_strings()+ *+ * do string replacement -- only if unprotected by quotation marks or curly brackets+ */+static void+replace_strings( slist *tokens, fields *bibin, param *pm )+{+	int i, n, ok;+	char *q;+	str *s;+	i = 0;+	while ( i < tokens->n ) {+		s = slist_str( tokens, i );+		if ( !strcmp( s->data, "#" ) ) {+		} else if ( s->data[0]!='\"' && s->data[0]!='{' ) {+			n = slist_find( &find, s );+			if ( n!=-1 ) {+				str_strcpy( s, slist_str( &replace, n ) );+			} else {+				q = s->data;+				ok = 1;+				while ( *q && ok ) {+					if ( !isdigit( *q ) ) ok = 0;+					q++;+				}+				if ( !ok ) {+					fprintf( stderr, "%s: Warning: Non-numeric "+					   "BibTeX elements should be in quotations or "+					   "curly brackets in reference.\n", pm->progname );+				}+			}+		}+		i++;+	}+}++static int+string_concatenate( slist *tokens, fields *bibin, long nref, param *pm )+{+	int i, status;+	str *s, *t;+	i = 0;+	while ( i < tokens->n ) {+		s = slist_str( tokens, i );+		if ( !strcmp( s->data, "#" ) ) {+			if ( i==0 || i==tokens->n-1 ) {+				fprintf( stderr, "%s: Warning: Stray string concatenation "+					"('#' character) in reference %ld\n", pm->progname, nref );+				status = slist_remove( tokens, i );+				if ( status!=SLIST_OK ) return BIBL_ERR_MEMERR;+				continue;+			}+			s = slist_str( tokens, i-1 );+			if ( s->data[0]!='\"' && s->data[s->len-1]!='\"' )+				fprintf( stderr, "%s: Warning: String concentation should "+					"be used in context of quotations marks in reference %ld\n", pm->progname, nref );+			t = slist_str( tokens, i+1 );+			if ( t->data[0]!='\"' && t->data[s->len-1]!='\"' )+				fprintf( stderr, "%s: Warning: String concentation should "+					"be used in context of quotations marks in reference %ld\n", pm->progname, nref );+			if ( ( s->data[s->len-1]=='\"' && t->data[0]=='\"') || (s->data[s->len-1]=='}' && t->data[0]=='{') ) {+				str_trimend( s, 1 );+				str_trimbegin( t, 1 );+				str_strcat( s, t );+			} else {+				str_strcat( s, t );+			}+			status = slist_remove( tokens, i );+			if ( status!=SLIST_OK ) return BIBL_ERR_MEMERR;+			status = slist_remove( tokens, i );+			if ( status!=SLIST_OK ) return BIBL_ERR_MEMERR;+		} else i++;+	}+	return BIBL_OK;+}++/* return NULL on memory error */+static char *+process_bibtexline( char *p, str *tag, str *data, uchar stripquotes, fields *bibin, long nref, param *pm )+{+	int i, status;+	slist tokens;+	str *s;++	str_empty( data );++	p = bibtex_tag( p, tag );+	if ( p==NULL || str_is_empty( tag ) ) return p;++	slist_init( &tokens );++	if ( *p=='=' ) {+		p = bibtex_data( p+1, bibin, &tokens, nref, pm );+		if ( p==NULL ) goto out;+	}++	replace_strings( &tokens, bibin, pm );++	status = string_concatenate( &tokens, bibin, nref, pm );+	if ( status!=BIBL_OK ) {+		p = NULL;+		goto out;+	}++	for ( i=0; i<tokens.n; i++ ) {+		s = slist_str( &tokens, i );+		if ( ( stripquotes && s->data[0]=='\"' && s->data[s->len-1]=='\"' ) ||+		     ( s->data[0]=='{' && s->data[s->len-1]=='}' ) ) {+			str_trimbegin( s, 1 );+			str_trimend( s, 1 );+		}+		str_strcat( data, slist_str( &tokens, i ) );+	}+out:+	slist_free( &tokens );+	return p;+}++/* process_cite()+ *+ */+static int+process_cite( fields *bibin, char *p, char *filename, long nref, param *pm )+{+	int fstatus, status = BIBL_OK;+	str tag, data;++	strs_init( &tag, &data, NULL );++	p = process_bibtextype( p, &data );+	if ( str_has_value( &data ) ) {+		fstatus = fields_add( bibin, "INTERNAL_TYPE", str_cstr( &data ), 0 );+		if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }+	}++	p = process_bibtexid( p, &data );+	if ( str_has_value( &data ) ) {+		fstatus = fields_add( bibin, "REFNUM", str_cstr( &data ), 0 );+		if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }+	}++	while ( *p ) {+		p = process_bibtexline( p, &tag, &data, 1, bibin, nref, pm );+		if ( p==NULL ) { status = BIBL_ERR_MEMERR; goto out; }+		/* no anonymous or empty fields allowed */+		if ( str_has_value( &tag ) && str_has_value( &data ) ) {+			fstatus = fields_add( bibin, str_cstr( &tag ), str_cstr( &data ), 0 );+			if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }+		}+		strs_empty( &tag, &data, NULL );+	}+out:+	strs_free( &tag, &data, NULL );+	return status;+}++/* process_string()+ *+ * Handle lines like:+ *+ * '@STRING{TL = {Tetrahedron Lett.}}'+ *+ * p should point to just after '@STRING'+ *+ * In BibTeX, if a string is defined several times, the last one is kept.+ *+ */+static int+process_string( char *p, long nref, param *pm )+{+	int n, status = BIBL_OK;+	str s1, s2, *t;+	strs_init( &s1, &s2, NULL );+	while ( *p && *p!='{' && *p!='(' ) p++;+	if ( *p=='{' || *p=='(' ) p++;+	p = process_bibtexline( skip_ws( p ), &s1, &s2, 0, NULL, nref, pm );+	if ( p==NULL ) { status = BIBL_ERR_MEMERR; goto out; }+	if ( str_has_value( &s2 ) ) {+		str_findreplace( &s2, "\\ ", " " );+	}+	if ( str_has_value( &s1 ) ) {+		n = slist_find( &find, &s1 );+		if ( n==-1 ) {+			t = slist_add( &find, &s1 );+			if ( t==NULL ) { status = BIBL_ERR_MEMERR; goto out; }+			if ( str_has_value( &s2 ) ) t = slist_add( &replace, &s2 );+			else t = slist_addc( &replace, "" );+			if ( t==NULL ) { status = BIBL_ERR_MEMERR; goto out; }+		} else {+			if ( str_has_value( &s2 ) ) t = slist_set( &replace, n, &s2 );+			else t = slist_setc( &replace, n, "" );+			if ( t==NULL ) { status = BIBL_ERR_MEMERR; goto out; }+		}+	}+out:+	strs_free( &s1, &s2, NULL );+	return status;+}++/* bibtexin_processf()+ *+ * Handle '@STRING', '@reftype', and ignore '@COMMENT'+ */+static int+bibtexin_processf( fields *bibin, char *data, char *filename, long nref, param *p )+{+	if ( !strncasecmp( data, "@STRING", 7 ) ) {+		process_string( data+7, nref, p );+		return 0;+	} else if ( !strncasecmp( data, "@COMMENT", 8 ) ) {+		/* Not sure if these are real Bibtex, but not references */+		return 0;+	} else {+		process_cite( bibin, data, filename, nref, p );+		return 1;+	}+}++/*****************************************************+ PUBLIC: void bibtexin_cleanf()+*****************************************************/++static int+bibtex_protected( str *data )+{+	if ( data->data[0]=='{' && data->data[data->len-1]=='}' ) return 1;+	if ( data->data[0]=='\"' && data->data[data->len-1]=='\"' ) return 1;+	return 0;+}++static int+bibtex_split( slist *tokens, str *s )+{+	int i, n = s->len, nbrackets = 0, status = BIBL_OK;+	str tok, *t;++	str_init( &tok );++	for ( i=0; i<n; ++i ) {+		if ( s->data[i]=='{' && ( i==0 || s->data[i-1]!='\\' ) ) {+			nbrackets++;+			str_addchar( &tok, '{' );+		} else if ( s->data[i]=='}' && ( i==0 || s->data[i-1]!='\\' ) ) {+			nbrackets--;+			str_addchar( &tok, '}' );+		} else if ( !is_ws( s->data[i] ) || nbrackets ) {+			str_addchar( &tok, s->data[i] );+		} else if ( is_ws( s->data[i] ) ) {+			if ( str_has_value( &tok ) ) {+				t = slist_add( tokens, &tok );+				if ( !t ) {+					status = BIBL_ERR_MEMERR;+					goto out;+				}+			}+			str_empty( &tok );+		}+	}+	if ( str_has_value( &tok ) ) {+		t = slist_add( tokens, &tok );+		if ( !t ) {+			status = BIBL_ERR_MEMERR;+			goto out;+		}+	}++	for ( i=0; i<tokens->n; ++i ) {+		str_trimstartingws( slist_str( tokens, i ) );+		str_trimendingws( slist_str( tokens, i ) );+	}+out:+	str_free( &tok );+	return status;+}++static int+bibtex_addtitleurl( fields *info, str *in )+{+	int fstatus, status = BIBL_OK;+	str s;+	char *p;++	str_init( &s );++	/* ...skip past "\href{" and copy to "}" */+	p = str_cpytodelim( &s, in->data + 6, "}", 1 );+	if ( str_memerr( &s ) ) { status = BIBL_ERR_MEMERR; goto out; }++	/* ...add to URL */+	fstatus = fields_add( info, "URL", s.data, 0 );+	if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }++	/* ...return deleted fragment to str in */+	p = str_cpytodelim( &s, p, "", 0 );+	if ( str_memerr( &s ) ) { status = BIBL_ERR_MEMERR; goto out; }+	str_swapstrings( &s, in );++out:+	str_free( &s );+	return status;+}++static int+is_url_tag( str *tag )+{+	if ( str_has_value( tag ) ) {+		if ( !strcasecmp( str_cstr( tag ), "url" ) ) return 1;+	}+	return 0;+}++static int+is_name_tag( str *tag )+{+	if ( str_has_value( tag ) ) {+		if ( !strcasecmp( str_cstr( tag ), "author" ) ) return 1;+		if ( !strcasecmp( str_cstr( tag ), "editor" ) ) return 1;+	}+	return 0;+}++static void+bibtex_process_tilde( str *s )+{+	char *p, *q;+	int n = 0;++	p = q = s->data;+	if ( !p ) return;+	while ( *p ) {+		if ( *p=='~' ) {+			*q = ' ';+		} else if ( *p=='\\' && *(p+1)=='~' ) {+			n++;+			p++;+			*q = '~';+		} else {+			*q = *p;+		}+		p++;+		q++;+	}+	*q = '\0';+	s->len -= n;+}++static void+bibtex_process_bracket( str *s )+{+	char *p, *q;+	int n = 0;++	p = q = s->data;+	if ( !p ) return;+	while ( *p ) {+		if ( *p=='\\' && ( *(p+1)=='{' || *(p+1)=='}' ) ) {+			n++;+			p++;+			*q = *p;+			q++;+		} else if ( *p=='{' || *p=='}' ) {+			n++;+		} else {+			*q = *p;+			q++;+		}+		p++;+	}+	*q = '\0';+	s->len -= n;+}++static void+bibtex_cleantoken( str *s )+{+	/* 'textcomp' annotations */+	str_findreplace( s, "\\textit", "" );+	str_findreplace( s, "\\textbf", "" );+	str_findreplace( s, "\\textsl", "" );+	str_findreplace( s, "\\textsc", "" );+	str_findreplace( s, "\\textsf", "" );+	str_findreplace( s, "\\texttt", "" );+	str_findreplace( s, "\\textsubscript", "" );+	str_findreplace( s, "\\textsuperscript", "" );+	str_findreplace( s, "\\emph", "" );+	str_findreplace( s, "\\url", "" );+	str_findreplace( s, "\\mbox", "" );++	/* Other text annotations */+	str_findreplace( s, "\\it ", "" );+	str_findreplace( s, "\\em ", "" );++	str_findreplace( s, "\\%", "%" );+	str_findreplace( s, "\\$", "$" );+	while ( str_findreplace( s, "  ", " " ) ) {}++	/* 'textcomp' annotations that we don't want to substitute on output*/+	str_findreplace( s, "\\textdollar", "$" );+	str_findreplace( s, "\\textunderscore", "_" );++	bibtex_process_bracket( s );+	bibtex_process_tilde( s );++}++static int+bibtex_cleandata( str *tag, str *s, fields *info, param *p )+{+	int i, status;+	slist tokens;+	str *tok;+	if ( str_is_empty( s ) ) return BIBL_OK;+	/* protect url from undergoing any parsing */+	if ( is_url_tag( tag ) ) return BIBL_OK;+	slist_init( &tokens );+	status = bibtex_split( &tokens, s );+	if ( status!=BIBL_OK ) goto out;+	for ( i=0; i<tokens.n; ++i ) {+		tok = slist_str( &tokens, i );+		if ( bibtex_protected( tok ) ) {+			if (!strncasecmp(tok->data,"\\href{", 6)) {+				bibtex_addtitleurl( info, tok );+			}+		}+		if ( p->latexin && !is_name_tag( tag ) && !is_url_tag( tag ) )+			bibtex_cleantoken( tok );+	}+	str_empty( s );+	for ( i=0; i<tokens.n; ++i ) {+		tok = slist_str( &tokens, i );+		if ( i>0 ) str_addchar( s, ' ' );+		str_strcat( s, tok );+	}+out:+	slist_free( &tokens );+	return status;+}++static int+bibtexin_cleanref( fields *bibin, param *p )+{+	int i, n, status;+	str *t, *d;+	n = fields_num( bibin );+	for ( i=0; i<n; ++i ) {+		t = fields_tag( bibin, i, FIELDS_STRP_NOUSE );+		d = fields_value( bibin, i, FIELDS_STRP_NOUSE );+		status = bibtex_cleandata( t, d, bibin, p );+		if ( status!=BIBL_OK ) return status;+	}+	return BIBL_OK;+}++static long+bibtexin_findref( bibl *bin, char *citekey )+{+	int n;+	long i;+	for ( i=0; i<bin->nrefs; ++i ) {+		n = fields_find( bin->ref[i], "refnum", LEVEL_ANY );+		if ( n==-1 ) continue;+		if ( !strcmp( bin->ref[i]->data[n].data, citekey ) ) return i;+	}+	return -1;+}++static void+bibtexin_nocrossref( bibl *bin, long i, int n, param *p )+{+	int n1 = fields_find( bin->ref[i], "REFNUM", LEVEL_ANY );+	if ( p->progname ) fprintf( stderr, "%s: ", p->progname );+	fprintf( stderr, "Cannot find cross-reference '%s'",+			bin->ref[i]->data[n].data );+	if ( n1!=-1 ) fprintf( stderr, " for reference '%s'\n",+			bin->ref[i]->data[n1].data );+	fprintf( stderr, "\n" );+}++static int+bibtexin_crossref_oneref( fields *bibref, fields *bibcross )+{+	int j, n, nl, ntype, fstatus, status = BIBL_OK;+	char *type, *nt, *nv;++	ntype = fields_find( bibref, "INTERNAL_TYPE", LEVEL_ANY );+	type = ( char * ) fields_value( bibref, ntype, FIELDS_CHRP_NOUSE );++	n = fields_num( bibcross );+	for ( j=0; j<n; ++j ) {+		nt = ( char * ) fields_tag( bibcross, j, FIELDS_CHRP_NOUSE );+		if ( !strcasecmp( nt, "INTERNAL_TYPE" ) ) continue;+		if ( !strcasecmp( nt, "REFNUM" ) ) continue;+		if ( !strcasecmp( nt, "TITLE" ) ) {+			if ( !strcasecmp( type, "Inproceedings" ) ||+			     !strcasecmp( type, "Incollection" ) )+				nt = "booktitle";+		}+		nv = ( char * ) fields_value( bibcross, j, FIELDS_CHRP_NOUSE );+		nl = fields_level( bibcross, j ) + 1;+		fstatus = fields_add( bibref, nt, nv, nl );+		if ( fstatus!=FIELDS_OK ) {+			status = BIBL_ERR_MEMERR;+			goto out;+		}+	}+out:+	return status;+}++static int+bibtexin_crossref( bibl *bin, param *p )+{+	int i, n, ncross, status = BIBL_OK;+	fields *bibref, *bibcross;++	for ( i=0; i<bin->nrefs; ++i ) {+		bibref = bin->ref[i];+		n = fields_find( bibref, "CROSSREF", LEVEL_ANY );+		if ( n==-1 ) continue;+		fields_setused( bibref, n );+		ncross = bibtexin_findref( bin, (char*) fields_value( bibref, n, FIELDS_CHRP ) );+		if ( ncross==-1 ) {+			bibtexin_nocrossref( bin, i, n, p );+			continue;+		}+		bibcross = bin->ref[ncross];+		status = bibtexin_crossref_oneref( bibref, bibcross );+		if ( status!=BIBL_OK ) goto out;+	}+out:+	return status;+}++static int+bibtexin_cleanf( bibl *bin, param *p )+{+	int status = BIBL_OK;+	long i;++        for ( i=0; i<bin->nrefs; ++i )+		status = bibtexin_cleanref( bin->ref[i], p );+	bibtexin_crossref( bin, p );+	return status;+}++/*****************************************************+ PUBLIC: int bibtexin_typef()+*****************************************************/++static int+bibtexin_typef( fields *bibin, char *filename, int nrefs, param *p )+{+	int ntypename, nrefname, is_default;+	char *refname = "", *typename = "";++	ntypename = fields_find( bibin, "INTERNAL_TYPE", LEVEL_MAIN );+	nrefname  = fields_find( bibin, "REFNUM",        LEVEL_MAIN );+	if ( nrefname!=-1 )  refname  = fields_value( bibin, nrefname,  FIELDS_CHRP_NOUSE );+	if ( ntypename!=-1 ) typename = fields_value( bibin, ntypename, FIELDS_CHRP_NOUSE );++	return get_reftype( typename, nrefs, p->progname, p->all, p->nall, refname, &is_default, REFTYPE_CHATTY );+}++/*****************************************************+ PUBLIC: int bibtexin_convertf(), returns BIBL_OK or BIBL_ERR_MEMERR+*****************************************************/++static int+bibtex_matches_list( fields *bibout, char *tag, char *suffix, str *data, int level,+		slist *names, int *match )+{+	int i, fstatus, status = BIBL_OK;+	str newtag;++	*match = 0;+	if ( names->n==0 ) return status;++	str_init( &newtag );++	for ( i=0; i<names->n; ++i ) {+		if ( strcmp( str_cstr( data ), slist_cstr( names, i ) ) ) continue;+		str_initstrc( &newtag, tag );+		str_strcatc( &newtag, suffix );+		fstatus = fields_add( bibout, str_cstr( &newtag ), str_cstr( data ), level );+		if ( fstatus!=FIELDS_OK ) {+			status = BIBL_ERR_MEMERR;+			goto out;+		}+		*match = 1;+		goto out;+	}++out:+	str_free( &newtag );+	return status;+}++/**** bibtexin_btorg ****/++/*+ * BibTeX uses 'organization' in lieu of publisher if that field is missing.+ * Otherwise output as+ * <name type="corporate">+ *    <namePart>The organization</namePart>+ *    <role>+ *       <roleTerm authority="marcrelator" type="text">organizer of meeting</roleTerm>+ *    </role>+ * </name>+ */++static int+bibtexin_btorg( fields *bibin, int m, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	int n, fstatus;+	n = fields_find( bibin, "publisher", LEVEL_ANY );+	if ( n==-1 )+		fstatus = fields_add( bibout, "PUBLISHER", str_cstr( invalue ), level );+	else+		fstatus = fields_add( bibout, "ORGANIZER:CORP", str_cstr( invalue ), level );+	if ( fstatus==FIELDS_OK ) return BIBL_OK;+	else return BIBL_ERR_MEMERR;+}++/**** bibtexin_btsente() ****/++/*+ * sentelink = {file://localhost/full/path/to/file.pdf,Sente,PDF}+ *+ * Sente is an academic reference manager for MacOSX and Apple iPad.+ */++static int+bibtexin_btsente( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	int fstatus, status = BIBL_OK;+	str link;++	str_init( &link );+	str_cpytodelim( &link, skip_ws( invalue->data ), ",", 0 );+	str_trimendingws( &link );+	if ( str_memerr( &link ) ) status = BIBL_ERR_MEMERR;++	if ( status==BIBL_OK && link.len ) {+		fstatus = fields_add( bibout, "FILEATTACH", str_cstr( &link ), level );+		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;+	}++	str_free( &link );+	return status;+}++/**** bibtexin_linkedfile() ****/++static int+count_colons( char *p )+{+	int n = 0;+	while ( *p ) {+		if ( *p==':' ) n++;+		p++;+	}+	return n;+}++static int+first_colon( char *p )+{+	int n = 0;+	while ( p[n] && p[n]!=':' ) n++;+	return n;+}++static int+last_colon( char *p )+{+	int n = strlen( p ) - 1;+	while ( n>0 && p[n]!=':' ) n--;+	return n;+}++/*+ * file={Description:/full/path/to/file.pdf:PDF}+ */+static int+bibtexin_linkedfile( fields *bibin, int m, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	int fstatus, status = BIBL_OK;+	char *p = invalue->data;+	int i, n, n1, n2;+	str link;++	n = count_colons( p );+	if ( n > 1 ) {+		/* A DOS file can contain a colon ":C:/....pdf:PDF" */+		/* Extract after 1st and up to last colons */+		n1 = first_colon( p ) + 1;+		n2 = last_colon( p );+		str_init( &link );+		for ( i=n1; i<n2; ++i ) {+			str_addchar( &link, p[i] );+		}+		str_trimstartingws( &link );+		str_trimendingws( &link );+		if ( str_memerr( &link ) ) {+			status = BIBL_ERR_MEMERR;+			goto out;+		}+		if ( link.len ) {+			fstatus = fields_add( bibout, "FILEATTACH", link.data, level );+			if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;+		}+out:+		str_free( &link );+	} else {+		/* This field isn't formatted properly, so just copy directly */+		fstatus = fields_add( bibout, "FILEATTACH", p, level );+		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;+	}+	return status;++}++/**** bibtexin_howpublished() ****/++/*    howpublished={},+ *+ * Normally indicates the manner in which something was+ * published in lieu of a formal publisher, so typically+ * 'howpublished' and 'publisher' will never be in the+ * same reference.+ *+ * Occassionally, people put Diploma thesis information+ * into the field, so check that first.+ *+ * Returns BIBL_OK or BIBL_ERR_MEMERR+ */++static int+bibtexin_howpublished( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	int fstatus, status = BIBL_OK;+	if ( !strncasecmp( str_cstr( invalue ), "Diplom", 6 ) ) {+		fstatus = fields_replace_or_add( bibout, "GENRE", "Diploma thesis", level );+		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;+	} else if ( !strncasecmp( str_cstr( invalue ), "Habilitation", 13 ) ) {+		fstatus = fields_replace_or_add( bibout, "GENRE", "Habilitation thesis", level );+		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;+	} else if ( is_embedded_link( str_cstr( invalue ) ) ) {+		status =  urls_split_and_add( str_cstr( invalue ), bibout, level );+	} else {+		fstatus = fields_add( bibout, "PUBLISHER", str_cstr( invalue ), level );+		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;+	}+	return status;+}++/**** bibtexin_eprint() ****/++/* Try to capture situations like+ *+ * eprint="1605.02026",+ * archivePrefix="arXiv",+ *+ * or+ *+ * eprint="13211131",+ * eprinttype="medline",+ *+ * If we don't know anything, concatenate archivePrefix:eprint+ * and push into URL. (Could be wrong)+ *+ * If no info, just push eprint into URL. (Could be wrong)+ */+static int+process_eprint_with_prefix( fields *bibout, char *prefix, str *value, int level )+{+	int fstatus, status = BIBL_OK;+	str merge;++	if ( !strcmp( prefix, "arXiv" ) ) {+		fstatus = fields_add( bibout, "ARXIV", value->data, level );+		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;+	}++	else if ( !strcmp( prefix, "jstor" ) ) {+		fstatus = fields_add( bibout, "JSTOR", value->data, level );+		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;+	}++	else if ( !strcmp( prefix, "medline" ) ) {+		fstatus = fields_add( bibout, "MEDLINE", value->data, level );+		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;+	}++	else if ( !strcmp( prefix, "pubmed" ) ) {+		fstatus = fields_add( bibout, "PMID", value->data, level );+		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;+	}++	/* ...if this is unknown prefix, merge prefix & eprint */+	else {+		str_init( &merge );+		str_mergestrs( &merge, prefix, ":", value->data, NULL );+		fstatus = fields_add( bibout, "URL", merge.data, level );+		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;+		str_free( &merge );+	}++	return status;+}+static int+process_eprint_without_prefix( fields *bibout, str *value, int level )+{+	int fstatus;++	/* ...no archivePrefix, need to handle just 'eprint' tag */+	fstatus = fields_add( bibout, "URL", value->data, level );++	if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;+	else return BIBL_OK;+}++static int+bibtexin_eprint( fields *bibin, int m, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	char *prefix;+	int n;++	/* ...do we have an archivePrefix too? */+	n = fields_find( bibin, "ARCHIVEPREFIX", level );+	if ( n==-1 ) n = fields_find( bibin, "EPRINTTYPE", level );+	if ( n!=-1 ) {+		prefix = fields_value( bibin, n, FIELDS_CHRP );+		return process_eprint_with_prefix( bibout, prefix, invalue, level );+	}++	/* ...no we don't */+	return process_eprint_without_prefix( bibout, invalue, level );+}++/**** bibtexin_keyword() ****/++/* Split keywords="" with semicolons.+ * Commas are also frequently used, but will break+ * entries like:+ *       keywords="Microscopy, Confocal"+ * Returns BIBL_OK or BIBL_ERR_MEMERR+ */++static int+bibtexin_keyword( fields *bibin, int m, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	int fstatus, status = BIBL_OK;+	str keyword;+	char *p;++	p = invalue->data;+	str_init( &keyword );++	while ( *p ) {+		p = str_cpytodelim( &keyword, skip_ws( p ), ";", 1 );+		str_trimendingws( &keyword );+		if ( str_memerr( &keyword ) ) {+			status = BIBL_ERR_MEMERR;+			goto out;+		}+		if ( keyword.len ) {+			fstatus = fields_add( bibout, "KEYWORD", keyword.data, level );+			if ( fstatus!=FIELDS_OK ) {+				status = BIBL_ERR_MEMERR;+				goto out;+			}+		}+	}+out:+	str_free( &keyword );+	return status;+}++/*+ * bibtex_names( bibout, newtag, field, level);+ *+ * split names in author list separated by and's (use '|' character)+ * and add names+ *+ * returns BIBL_OK on success, BIBL_ERR_MEMERR on memory error+ */++static int+bibtexin_person( fields *bibin, int m, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	int begin, end, ok, n, etal, i, status, match;+	slist tokens;++	/* If we match the asis or corps list add and bail. */+	status = bibtex_matches_list( bibout, outtag, ":ASIS", invalue, level, &(pm->asis), &match );+	if ( match==1 || status!=BIBL_OK ) return status;+	status = bibtex_matches_list( bibout, outtag, ":CORP", invalue, level, &(pm->corps), &match );+	if ( match==1 || status!=BIBL_OK ) return status;++	slist_init( &tokens );++	bibtex_split( &tokens, invalue );+	for ( i=0; i<tokens.n; ++i )+		bibtex_cleantoken( slist_str( &tokens, i ) );++	etal = name_findetal( &tokens );++	begin = 0;+	n = tokens.n - etal;+	while ( begin < n ) {++		end = begin + 1;++		while ( end < n && strcasecmp( slist_cstr( &tokens, end ), "and" ) )+			end++;++		if ( end - begin == 1 ) {+			ok = name_addsingleelement( bibout, outtag, slist_cstr( &tokens, begin ), level, 0 );+			if ( !ok ) { status = BIBL_ERR_MEMERR; goto out; }+		} else {+			ok = name_addmultielement( bibout, outtag, &tokens, begin, end, level );+			if ( !ok ) { status = BIBL_ERR_MEMERR; goto out; }+		}++		begin = end + 1;++		/* Handle repeated 'and' errors: authors="G. F. Author and and B. K. Author" */+		while ( begin < n && !strcasecmp( slist_cstr( &tokens, begin ), "and" ) )+			begin++;+	}++	if ( etal ) {+		ok = name_addsingleelement( bibout, outtag, "et al.", level, 0 );+		if ( !ok ) status = BIBL_ERR_MEMERR;+	}++out:+	slist_free( &tokens );+	return status;++}++/**** bibtexin_title() ****/++/* bibtexin_titleinbook_isbooktitle()+ *+ * Normally, the title field of inbook refers to the book.  The+ * section in a @inbook reference is untitled.  If it's titled,+ * the @incollection should be used.  For example, in:+ *+ * @inbook{+ *    title="xxx"+ * }+ *+ * the booktitle is "xxx".+ *+ * However, @inbook is frequently abused (and treated like+ * @incollection) so that title and booktitle are present+ * and title is now 'supposed' to refer to the section.  For example:+ *+ * @inbook{+ *     title="yyy",+ *     booktitle="xxx"+ * }+ *+ * Therefore report whether or not booktitle is present as well+ * as title in @inbook references.  If not, then make 'title'+ * correspond to the title of the book, not the section.+ *+ */+static int+bibtexin_titleinbook_isbooktitle( fields *bibin, char *intag )+{+	int n;++	/* ...look only at 'title="xxx"' elements */+	if ( strcasecmp( intag, "TITLE" ) ) return 0;++	/* ...look only at '@inbook' references */+	n = fields_find( bibin, "INTERNAL_TYPE", LEVEL_ANY );+	if ( n==-1 ) return 0;+	if ( strcasecmp( fields_value( bibin, n, FIELDS_CHRP ), "INBOOK" ) ) return 0;++	/* ...look to see if 'booktitle="yyy"' exists */+	n = fields_find( bibin, "BOOKTITLE", LEVEL_ANY );+	if ( n==-1 ) return 0;+	else return 1;+}++static int+bibtexin_title( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	int ok;++	if ( bibtexin_titleinbook_isbooktitle( bibin, intag->data ) ) level=LEVEL_MAIN;+	ok = title_process( bibout, "TITLE", invalue->data, level, pm->nosplittitle );+	if ( ok ) return BIBL_OK;+	else return BIBL_ERR_MEMERR;+}++static void+bibtexin_notag( param *p, char *tag )+{+	if ( p->verbose && strcmp( tag, "INTERNAL_TYPE" ) ) {+		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );+		fprintf( stderr, "Cannot find tag '%s'\n", tag );+	}+}++static int+bibtexin_convertf( fields *bibin, fields *bibout, int reftype, param *p )+{+	static int (*convertfns[NUM_REFTYPES])(fields *, int, str *, str *, int, param *, char *, fields *) = {+		[ 0 ... NUM_REFTYPES-1 ] = generic_null,+		[ SIMPLE       ] = generic_simple,+		[ TITLE        ] = bibtexin_title,+		[ PERSON       ] = bibtexin_person,+		[ PAGES        ] = generic_pages,+		[ KEYWORD      ] = bibtexin_keyword,+		[ EPRINT       ] = bibtexin_eprint,+		[ HOWPUBLISHED ] = bibtexin_howpublished,+		[ LINKEDFILE   ] = bibtexin_linkedfile,+		[ NOTES        ] = generic_notes,+		[ BT_SENTE     ] = bibtexin_btsente,+		[ BT_ORG       ] = bibtexin_btorg,+		[ URL          ] = generic_url+	};++	int process, level, i, nfields, status = BIBL_OK;+	str *intag, *invalue;+	char *outtag;++	nfields = fields_num( bibin );+	for ( i=0; i<nfields; ++i ) {++		if ( fields_used( bibin, i ) )   continue; /* e.g. successful crossref */+		if ( fields_notag( bibin, i ) )  continue;+		if ( fields_nodata( bibin, i ) ) continue;++		intag   = fields_tag( bibin, i, FIELDS_STRP );+		invalue = fields_value( bibin, i, FIELDS_STRP );++		if ( !translate_oldtag( str_cstr( intag ), reftype, p->all, p->nall, &process, &level, &outtag ) ) {+			bibtexin_notag( p, str_cstr( intag ) );+			continue;+		}++		status = convertfns[ process ] ( bibin, i, intag, invalue, level, p, outtag, bibout );+		if ( status!=BIBL_OK ) return status;+	}++	if ( status==BIBL_OK && p->verbose ) fields_report( bibout, stderr );++	return status;+}
− bibutils/bibtexin.h
@@ -1,33 +0,0 @@-/*- * bibtexin.h- *- * Copyright (c) Chris Putnam 2003-2014- *- * Source code released under the GPL version 2- *- */-#ifndef BIBTEXIN_H-#define BIBTEXIN_H--#include "newstr.h"-#include "list.h"-#include "fields.h"-#include "bibl.h"-#include "bibutils.h"-#include "reftypes.h"--extern int  bibtexin_convertf( fields *bibin, fields *info, int reftype, param *p, variants *all, int nall );-extern int  bibtexin_processf( fields *bibin, char *data, char *filename, long nref );-extern int  bibtexin_cleanf( bibl *bin, param *p );-extern int  bibtexin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );-extern int  bibtexin_typef( fields *bibin, char *filename, int nrefs,-        param *p, variants *all, int nall );-extern void bibtexin_initparams( param *p, const char *progname );---extern variants bibtex_all[];-extern int bibtex_nall;---#endif-
bibutils/bibtexout.c view
@@ -1,7 +1,7 @@ /*  * bibtexout.c  *- * Copyright (c) Chris Putnam 2003-2014+ * Copyright (c) Chris Putnam 2003-2017  *  * Program and source code released under the GPL version 2  *@@ -10,16 +10,19 @@ #include <stdlib.h> #include <string.h> #include <ctype.h>-#include "newstr.h"+#include "str.h" #include "strsearch.h" #include "utf8.h" #include "xml.h" #include "fields.h" #include "name.h"-#include "bibl.h"-#include "doi.h"-#include "bibtexout.h"+#include "title.h"+#include "url.h"+#include "bibformats.h" +static int  bibtexout_write( fields *in, FILE *fp, param *p, unsigned long refnum );+static void bibtexout_writeheader( FILE *outptr, param *p );+ void bibtexout_initparams( param *p, const char *progname ) {@@ -59,44 +62,22 @@ 	TYPE_MANUAL, 	TYPE_UNPUBLISHED, 	TYPE_ELECTRONIC,-	TYPE_MISC+	TYPE_MISC,+	NUM_TYPES }; -static void-output_citekey( FILE *fp, fields *info, unsigned long refnum, int format_opts )-{-	int n = fields_find( info, "REFNUM", -1 );-	char *p;-	if ( n!=-1 ) {-		p = info->data[n].data;-		while ( p && *p && *p!='|' ) {-			if ( format_opts & BIBOUT_STRICTKEY ) {-				if ( isdigit((unsigned char)*p) || (*p>='A' && *p<='Z') ||-				     (*p>='a' && *p<='z' ) )-					fprintf( fp, "%c", *p );-			}-			else {-				if ( *p!=' ' && *p!='\t' ) {-					fprintf( fp, "%c", *p );-				}-			}-			p++;-		}-	}-}- static int-bibtexout_type( fields *info, char *filename, int refnum, param *p )+bibtexout_type( fields *in, char *filename, int refnum, param *p ) {-	char *genre; 	int type = TYPE_UNKNOWN, i, maxlevel, n, level;+	char *tag, *genre;  	/* determine bibliography type */-	for ( i=0; i<info->n; ++i ) {-		if ( strcasecmp( info->tag[i].data, "GENRE" ) &&-		     strcasecmp( info->tag[i].data, "NGENRE" ) ) continue;-		genre = info->data[i].data;-		level = info->level[i];+	for ( i=0; i<in->n; ++i ) {+		tag = fields_tag( in, i, FIELDS_CHRP );+		if ( strcasecmp( tag, "GENRE" ) && strcasecmp( tag, "NGENRE" ) ) continue;+		genre = fields_value( in, i, FIELDS_CHRP );+		level = in->level[i]; 		if ( !strcasecmp( genre, "periodical" ) || 		     !strcasecmp( genre, "academic journal" ) || 		     !strcasecmp( genre, "magazine" ) ||@@ -115,9 +96,11 @@ 			else type = TYPE_INCOLLECTION; 		} else if ( !strcasecmp( genre, "report" ) ) 			type = TYPE_REPORT;+		else if ( !strcasecmp( genre, "book chapter" ) )+			type = TYPE_INBOOK; 		else if ( !strcasecmp( genre, "book" ) ) {-			if ( level==0 ) type=TYPE_BOOK;-			else type=TYPE_INBOOK;+			if ( level==0 ) type = TYPE_BOOK;+			else type = TYPE_INBOOK; 		} else if ( !strcasecmp( genre, "thesis" ) ) { 			if ( type==TYPE_UNKNOWN ) type=TYPE_PHDTHESIS; 		} else if ( !strcasecmp( genre, "Ph.D. thesis" ) )@@ -128,26 +111,27 @@ 			type = TYPE_ELECTRONIC; 	} 	if ( type==TYPE_UNKNOWN ) {-		for ( i=0; i<info->n; ++i ) {-			if ( strcasecmp( info->tag[i].data, "ISSUANCE" ) ) continue;-			if ( !strcasecmp( info->data[i].data, "monographic" ) ) {-				if ( info->level[i]==0 ) type = TYPE_BOOK;-				else if ( info->level[i]==1 ) type=TYPE_INBOOK;+		for ( i=0; i<in->n; ++i ) {+			tag = fields_tag( in, i, FIELDS_CHRP );+			if ( strcasecmp( tag, "ISSUANCE" ) ) continue;+			genre = fields_value( in, i, FIELDS_CHRP );+			if ( !strcasecmp( genre, "monographic" ) ) {+				if ( in->level[i]==0 ) type = TYPE_BOOK;+				else if ( in->level[i]==1 ) type = TYPE_MISC; 			} 		} 	} -	/* default to BOOK type */+	/* default to TYPE_MISC */ 	if ( type==TYPE_UNKNOWN ) {-		maxlevel = fields_maxlevel( info );-		if ( maxlevel > 0 ) type = TYPE_INBOOK;+		maxlevel = fields_maxlevel( in );+		if ( maxlevel > 0 ) type = TYPE_MISC; 		else { 			if ( p->progname ) fprintf( stderr, "%s: ", p->progname );-			fprintf( stderr, "Cannot identify TYPE "-				"in reference %d ", refnum+1 );-			n = fields_find( info, "REFNUM", -1 );+			fprintf( stderr, "Cannot identify TYPE in reference %d ", refnum+1 );+			n = fields_find( in, "REFNUM", LEVEL_ANY ); 			if ( n!=-1 ) -				fprintf( stderr, " %s", info->data[n].data);+				fprintf( stderr, " %s", (char*) fields_value( in, n, FIELDS_CHRP ) ); 			fprintf( stderr, " (defaulting to @Misc)\n" ); 			type = TYPE_MISC; 		}@@ -156,355 +140,592 @@ }  static void-output_type( FILE *fp, int type, int format_opts )+output( FILE *fp, fields *out, int format_opts ) {-	typedef struct {-		int bib_type;-		char *type_name;-	} typenames;+	int i, j, len, nquotes;+	char *tag, *value, ch; -	typenames types[] = {-		{ TYPE_ARTICLE, "Article" },-		{ TYPE_INBOOK, "Inbook" },-		{ TYPE_PROCEEDINGS, "Proceedings" },-		{ TYPE_INPROCEEDINGS, "InProceedings" },-		{ TYPE_BOOK, "Book" },-		{ TYPE_PHDTHESIS, "PhdThesis" },-		{ TYPE_MASTERSTHESIS, "MastersThesis" },-		{ TYPE_REPORT, "TechReport" },-		{ TYPE_MANUAL, "Manual" },-		{ TYPE_COLLECTION, "Collection" },-		{ TYPE_INCOLLECTION, "InCollection" },-		{ TYPE_UNPUBLISHED, "Unpublished" },-		{ TYPE_ELECTRONIC, "Electronic" },-		{ TYPE_MISC, "Misc" } };-	int i, len, ntypes = sizeof( types ) / sizeof( types[0] );-	char *s = NULL;-	for ( i=0; i<ntypes; ++i ) {-		if ( types[i].bib_type == type ) {-			s = types[i].type_name;-			break;-		}-	}-	if ( !s ) s = types[ntypes-1].type_name; /* default to TYPE_MISC */-	if ( !(format_opts & BIBOUT_UPPERCASE ) ) fprintf( fp, "@%s{", s );+	/* ...output type information "@article{" */+	value = ( char * ) fields_value( out, 0, FIELDS_CHRP );+	if ( !(format_opts & BIBL_FORMAT_BIBOUT_UPPERCASE) ) fprintf( fp, "@%s{", value ); 	else {-		len = strlen( s );+		len = strlen( value ); 		fprintf( fp, "@" ); 		for ( i=0; i<len; ++i )-			fprintf( fp, "%c", toupper((unsigned char)s[i]) );+			fprintf( fp, "%c", toupper((unsigned char)value[i]) ); 		fprintf( fp, "{" ); 	}-} -static void-output_element( FILE *fp, char *tag, char *data, int format_opts )-{-	int i, len, nquotes = 0;-	char ch;-	fprintf( fp, ",\n" );-	if ( format_opts & BIBOUT_WHITESPACE ) fprintf( fp, "  " );-	if ( !(format_opts & BIBOUT_UPPERCASE ) ) fprintf( fp, "%s", tag );-	else {-		len = strlen( tag );-		for ( i=0; i<len; ++i )-			fprintf( fp, "%c", toupper((unsigned char)tag[i]) );-	}-	if ( format_opts & BIBOUT_WHITESPACE ) fprintf( fp, " = \t" );-	else fprintf( fp, "=" );--	if ( format_opts & BIBOUT_BRACKETS ) fprintf( fp, "{" );-	else fprintf( fp, "\"" );+	/* ...output refnum "Smith2001" */+	value = ( char * ) fields_value( out, 1, FIELDS_CHRP );+	fprintf( fp, "%s", value ); -	len = strlen( data );-	for ( i=0; i<len; ++i ) {-		ch = data[i];-		if ( ch!='\"' ) fprintf( fp, "%c", ch );+	/* ...rest of the references */+	for ( j=2; j<out->n; ++j ) {+		nquotes = 0;+		tag   = ( char * ) fields_tag( out, j, FIELDS_CHRP );+		value = ( char * ) fields_value( out, j, FIELDS_CHRP );+		fprintf( fp, ",\n" );+		if ( format_opts & BIBL_FORMAT_BIBOUT_WHITESPACE ) fprintf( fp, "  " );+		if ( !(format_opts & BIBL_FORMAT_BIBOUT_UPPERCASE ) ) fprintf( fp, "%s", tag ); 		else {-			if ( format_opts & BIBOUT_BRACKETS || -			    ( i>0 && data[i-1]=='\\' ) )-				fprintf( fp, "\"" );+			len = strlen( tag );+			for ( i=0; i<len; ++i )+				fprintf( fp, "%c", toupper((unsigned char)tag[i]) );+		}+		if ( format_opts & BIBL_FORMAT_BIBOUT_WHITESPACE ) fprintf( fp, " = \t" );+		else fprintf( fp, "=" );++		if ( format_opts & BIBL_FORMAT_BIBOUT_BRACKETS ) fprintf( fp, "{" );+		else fprintf( fp, "\"" );++		len = strlen( value );+		for ( i=0; i<len; ++i ) {+			ch = value[i];+			if ( ch!='\"' ) fprintf( fp, "%c", ch ); 			else {-				if ( nquotes % 2 == 0 )-					fprintf( fp, "``" );-				else    fprintf( fp, "\'\'" );-				nquotes++;+				if ( format_opts & BIBL_FORMAT_BIBOUT_BRACKETS || ( i>0 && value[i-1]=='\\' ) )+					fprintf( fp, "\"" );+				else {+					if ( nquotes % 2 == 0 )+						fprintf( fp, "``" );+					else    fprintf( fp, "\'\'" );+					nquotes++;+				} 			} 		}++		if ( format_opts & BIBL_FORMAT_BIBOUT_BRACKETS ) fprintf( fp, "}" );+		else fprintf( fp, "\"" ); 	} -	if ( format_opts & BIBOUT_BRACKETS ) fprintf( fp, "}" );-	else fprintf( fp, "\"" );+	/* ...finish reference */+	if ( format_opts & BIBL_FORMAT_BIBOUT_FINALCOMMA ) fprintf( fp, "," );+	fprintf( fp, "\n}\n\n" );++	fflush( fp ); }  static void-output_and_use( FILE *fp, fields *info, int n, char *outtag, int format_opts )+append_type( int type, fields *out, int *status ) {-	output_element( fp, outtag, info->data[n].data, format_opts );-	fields_setused( info, n );+	char *typenames[ NUM_TYPES ] = {+		[ TYPE_ARTICLE       ] = "Article",+		[ TYPE_INBOOK        ] = "Inbook",+		[ TYPE_PROCEEDINGS   ] = "Proceedings",+		[ TYPE_INPROCEEDINGS ] = "InProceedings",+		[ TYPE_BOOK          ] = "Book",+		[ TYPE_PHDTHESIS     ] = "PhdThesis",+		[ TYPE_MASTERSTHESIS ] = "MastersThesis",+		[ TYPE_REPORT        ] = "TechReport",+		[ TYPE_MANUAL        ] = "Manual",+		[ TYPE_COLLECTION    ] = "Collection",+		[ TYPE_INCOLLECTION  ] = "InCollection",+		[ TYPE_UNPUBLISHED   ] = "Unpublished",+		[ TYPE_ELECTRONIC    ] = "Electronic",+		[ TYPE_MISC          ] = "Misc",+	};+	int fstatus;+	char *s;++	if ( type < 0 || type >= NUM_TYPES ) type = TYPE_MISC;+	s = typenames[ type ];++	fstatus = fields_add( out, "TYPE", s, LEVEL_MAIN );+	if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR; }  static void-output_simple( FILE *fp, fields *info, char *intag, char *outtag, -		int format_opts )+append_citekey( fields *in, fields *out, int format_opts, int *status ) {-	int n = fields_find( info, intag, -1 );+	int n, fstatus;+	str s;+	char *p;++	n = fields_find( in, "REFNUM", LEVEL_ANY );+	if ( ( format_opts & BIBL_FORMAT_BIBOUT_DROPKEY ) || n==-1 ) {+		fstatus = fields_add( out, "REFNUM", "", LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	}++	else {+		str_init( &s );+		p = fields_value( in, n, FIELDS_CHRP );+		while ( p && *p && *p!='|' ) {+			if ( format_opts & BIBL_FORMAT_BIBOUT_STRICTKEY ) {+				if ( isdigit((unsigned char)*p) || (*p>='A' && *p<='Z') ||+				     (*p>='a' && *p<='z' ) ) {+					str_addchar( &s, *p );+				}+			}+			else {+				if ( *p!=' ' && *p!='\t' ) {+					str_addchar( &s, *p );+				}+			}+			p++;+		}+		if ( str_memerr( &s ) )  { *status = BIBL_ERR_MEMERR; str_free( &s ); return; }+		fstatus = fields_add( out, "REFNUM", str_cstr( &s ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+		str_free( &s );+	}+}++static void+append_simple( fields *in, char *intag, char *outtag, fields *out, int *status )+{+	int n, fstatus;++	n = fields_find( in, intag, LEVEL_ANY ); 	if ( n!=-1 ) {-		output_and_use( fp, info, n, outtag, format_opts );+		fields_setused( in, n );+		fstatus = fields_add( out, outtag, fields_value( in, n, FIELDS_CHRP ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR; 	} }  static void-output_simpleall( FILE *fp, fields *info, char *intag, char *outtag,-		int format_opts )+append_simpleall( fields *in, char *intag, char *outtag, fields *out, int *status ) {-	int i;-	for ( i=0; i<info->n; ++i ) {-		if ( fields_match_tag( info, i, intag ) )-			output_and_use( fp, info, i, outtag, format_opts );+	int i, fstatus;++	for ( i=0; i<in->n; ++i ) {+		if ( fields_match_tag( in, i, intag ) ) {+			fields_setused( in, i );+			fstatus = fields_add( out, outtag, fields_value( in, i, FIELDS_CHRP ), LEVEL_MAIN );+			if ( fstatus!=FIELDS_OK ) {+				*status = BIBL_ERR_MEMERR;+				return;+			}+		} 	} }  static void-output_keywords( FILE *fp, fields *info, int format_opts )+append_keywords( fields *in, fields *out, int *status ) {-	newstr keywords, *word;+	str keywords, *word;+	vplist_index i;+	int fstatus; 	vplist a;-	int i;-	newstr_init( &keywords );++	str_init( &keywords ); 	vplist_init( &a );-	fields_findv_each( info, LEVEL_ANY, FIELDS_STRP, &a, "KEYWORD" );++	fields_findv_each( in, LEVEL_ANY, FIELDS_STRP, &a, "KEYWORD" );+ 	if ( a.n ) {+ 		for ( i=0; i<a.n; ++i ) { 			word = vplist_get( &a, i );-			if ( i>0 ) newstr_strcat( &keywords, "; " );-			newstr_newstrcat( &keywords, word );+			if ( i>0 ) str_strcatc( &keywords, "; " );+			str_strcat( &keywords, word ); 		}-		output_element( fp, "keywords", keywords.data, format_opts ); +		if ( str_memerr( &keywords ) ) { *status = BIBL_ERR_MEMERR; goto out; }++		fstatus = fields_add( out, "keywords", str_cstr( &keywords ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) {+			*status = BIBL_ERR_MEMERR;+			goto out;+		}++ 	}-	newstr_free( &keywords );++out:+	str_free( &keywords ); 	vplist_free( &a ); }  static void-output_fileattach( FILE *fp, fields *info, int format_opts )+append_fileattach( fields *in, fields *out, int *status ) {-	newstr data;-	int i;-	newstr_init( &data );-	for ( i=0; i<info->n; ++i ) {-		if ( strcasecmp( info->tag[i].data, "FILEATTACH" ) ) continue;-		newstr_strcpy( &data, ":" );-		newstr_newstrcat( &data, &(info->data[i]) );-		if ( strsearch( info->data[i].data, ".pdf" ) )-			newstr_strcat( &data, ":PDF" );-		else if ( strsearch( info->data[i].data, ".html" ) )-			newstr_strcat( &data, ":HTML" );-		else newstr_strcat( &data, ":TYPE" );-		output_element( fp, "file", data.data, format_opts );-		fields_setused( info, i );-		newstr_empty( &data );+	char *tag, *value;+	int i, fstatus;+	str data;++	str_init( &data );++	for ( i=0; i<in->n; ++i ) {++		tag = fields_tag( in, i, FIELDS_CHRP );+		if ( strcasecmp( tag, "FILEATTACH" ) ) continue;++		value = fields_value( in, i, FIELDS_CHRP );+		str_strcpyc( &data, ":" );+		str_strcatc( &data, value );+		if ( strsearch( value, ".pdf" ) )+			str_strcatc( &data, ":PDF" );+		else if ( strsearch( value, ".html" ) )+			str_strcatc( &data, ":HTML" );+		else str_strcatc( &data, ":TYPE" );++		if ( str_memerr( &data ) ) {+			*status = BIBL_ERR_MEMERR;+			goto out;+		}++		fields_setused( in, i );+		fstatus = fields_add( out, "file", str_cstr( &data ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) {+			*status = BIBL_ERR_MEMERR;+			goto out;+		}++		str_empty( &data ); 	}-	newstr_free( &data );+out:+	str_free( &data ); }  static void-output_people( FILE *fp, fields *info, unsigned long refnum, char *tag, -		char *ctag, char *atag, char *bibtag, int level, -		int format_opts )+append_people( fields *in, char *tag, char *ctag, char *atag,+		char *bibtag, int level, fields *out, int format_opts ) {-	newstr allpeople, oneperson;+	str allpeople, oneperson; 	int i, npeople, person, corp, asis; -	newstrs_init( &allpeople, &oneperson, NULL );+	strs_init( &allpeople, &oneperson, NULL );  	/* primary citation authors */ 	npeople = 0;-	for ( i=0; i<info->n; ++i ) {-		if ( level!=-1 && info->level[i]!=level ) continue;-		person = ( strcasecmp( info->tag[i].data, tag ) == 0 );-		corp   = ( strcasecmp( info->tag[i].data, ctag ) == 0 );-		asis   = ( strcasecmp( info->tag[i].data, atag ) == 0 );+	for ( i=0; i<in->n; ++i ) {+		if ( level!=LEVEL_ANY && in->level[i]!=level ) continue;+		person = ( strcasecmp( in->tag[i].data, tag ) == 0 );+		corp   = ( strcasecmp( in->tag[i].data, ctag ) == 0 );+		asis   = ( strcasecmp( in->tag[i].data, atag ) == 0 ); 		if ( person || corp || asis ) { 			if ( npeople>0 ) {-				if ( format_opts & BIBOUT_WHITESPACE )-					newstr_strcat(&allpeople,"\n\t\tand ");-				else newstr_strcat( &allpeople, "\nand " );+				if ( format_opts & BIBL_FORMAT_BIBOUT_WHITESPACE )+					str_strcatc( &allpeople, "\n\t\tand " );+				else str_strcatc( &allpeople, "\nand " ); 			} 			if ( corp ) {-				newstr_addchar( &allpeople, '{' );-				newstr_strcat( &allpeople, fields_value( info, i, FIELDS_CHRP ) );-				newstr_addchar( &allpeople, '}' );+				str_addchar( &allpeople, '{' );+				str_strcat( &allpeople, fields_value( in, i, FIELDS_STRP ) );+				str_addchar( &allpeople, '}' ); 			} else if ( asis ) {-				newstr_addchar( &allpeople, '{' );-				newstr_strcat( &allpeople, fields_value( info, i, FIELDS_CHRP ) );-				newstr_addchar( &allpeople, '}' );+				str_addchar( &allpeople, '{' );+				str_strcat( &allpeople, fields_value( in, i, FIELDS_STRP ) );+				str_addchar( &allpeople, '}' ); 			} else {-				name_build_withcomma( &oneperson, fields_value( info, i, FIELDS_CHRP ) );-				newstr_newstrcat( &allpeople, &oneperson );+				name_build_withcomma( &oneperson, fields_value( in, i, FIELDS_CHRP ) );+				str_strcat( &allpeople, &oneperson ); 			} 			npeople++; 		} 	}-	if ( npeople )-		output_element( fp, bibtag, allpeople.data, format_opts );+	if ( npeople ) {+		fields_add( out, bibtag, allpeople.data, LEVEL_MAIN );+	} -	newstrs_free( &allpeople, &oneperson, NULL );+	strs_free( &allpeople, &oneperson, NULL ); } -static void-output_title( FILE *fp, fields *info, unsigned long refnum, char *bibtag, int level, int format_opts )+static int+append_title_chosen( fields *in, char *bibtag, fields *out, int nmainttl, int nsubttl ) {-	newstr title, *mainttl, *subttl;-	int n1 = -1, n2 = -1;-	/* Option is for short titles of journals */-	if ( ( format_opts & BIBOUT_SHORTTITLE ) && level==1 ) {-		n1 = fields_find( info, "SHORTTITLE", level );-		n2 = fields_find( info, "SHORTSUBTITLE", level );+	str fulltitle, *mainttl = NULL, *subttl = NULL;+	int status, ret = BIBL_OK;++	str_init( &fulltitle );++	if ( nmainttl!=-1 ) {+		mainttl = fields_value( in, nmainttl, FIELDS_STRP );+		fields_setused( in, nmainttl ); 	}-	if ( n1==-1 ) {-		n1 = fields_find( info, "TITLE", level );-		n2 = fields_find( info, "SUBTITLE", level );++	if ( nsubttl!=-1 ) {+		subttl = fields_value( in, nsubttl, FIELDS_STRP );+		fields_setused( in, nsubttl ); 	}-	if ( n1!=-1 ) {-		newstr_init( &title );-		mainttl = fields_value( info, n1, FIELDS_STRP );-		newstr_newstrcpy( &title, mainttl );-		fields_setused( info, n1 );-		if ( n2!=-1 ) {-			subttl = fields_value( info, n2, FIELDS_STRP );-			if ( mainttl->len > 0 &&-			     mainttl->data[mainttl->len-1]!='?' )-				newstr_strcat( &title, ": " );-			else newstr_addchar( &title, ' ' );-			newstr_newstrcat( &title, subttl );-			fields_setused( info, n2 );-		}-		output_element( fp, bibtag, title.data, format_opts );-		newstr_free( &title );++	title_combine( &fulltitle, mainttl, subttl );++	if ( str_memerr( &fulltitle ) ) {+		ret = BIBL_ERR_MEMERR;+		goto out; 	}++	if ( str_has_value( &fulltitle ) ) {+		status = fields_add( out, bibtag, str_cstr( &fulltitle ), LEVEL_MAIN );+		if ( status!=FIELDS_OK ) ret = BIBL_ERR_MEMERR;+	}++out:+	str_free( &fulltitle );+	return ret; } +static int+append_title( fields *in, char *bibtag, int level, fields *out, int format_opts )+{+	int title = -1,     short_title = -1;+	int subtitle = -1,  short_subtitle = -1;+	int use_title = -1, use_subtitle = -1;++	title          = fields_find( in, "TITLE",         level );+	short_title    = fields_find( in, "SHORTTITLE",    level );+	subtitle       = fields_find( in, "SUBTITLE",      level );+	short_subtitle = fields_find( in, "SHORTSUBTITLE", level );++	if ( title==-1 || ( ( format_opts & BIBL_FORMAT_BIBOUT_SHORTTITLE ) && level==1 ) ) {+		use_title    = short_title;+		use_subtitle = short_subtitle;+	}++	else {+		use_title    = title;+		use_subtitle = subtitle;+	}++	return append_title_chosen( in, bibtag, out, use_title, use_subtitle );+}+ static void-output_date( FILE *fp, fields *info, unsigned long refnum, int format_opts )+append_titles( fields *in, int type, fields *out, int format_opts, int *status ) {+	/* item=main level title */+	*status = append_title( in, "title", 0, out, format_opts );+	if ( *status!=BIBL_OK ) return;++	switch( type ) {++		case TYPE_ARTICLE:+		*status = append_title( in, "journal", 1, out, format_opts );+		break;++		case TYPE_INBOOK:+		*status = append_title( in, "bookTitle", 1, out, format_opts );+		if ( *status!=BIBL_OK ) return;+		*status = append_title( in, "series",    2, out, format_opts );+		break;++		case TYPE_INCOLLECTION:+		case TYPE_INPROCEEDINGS:+		*status = append_title( in, "booktitle", 1, out, format_opts );+		if ( *status!=BIBL_OK ) return;+		*status = append_title( in, "series",    2, out, format_opts );+		break;++		case TYPE_PHDTHESIS:+		case TYPE_MASTERSTHESIS:+		*status = append_title( in, "series", 1, out, format_opts );+		break;++		case TYPE_BOOK:+		case TYPE_REPORT:+		case TYPE_COLLECTION:+		case TYPE_PROCEEDINGS:+		*status = append_title( in, "series", 1, out, format_opts );+		if ( *status!=BIBL_OK ) return;+		*status = append_title( in, "series", 2, out, format_opts );+		break;++		default:+		/* do nothing */+		break;++	}+}++static int+find_date( fields *in, char *date_element )+{+	char date[100], partdate[100];+	int n;++	sprintf( date, "DATE:%s", date_element );+	n = fields_find( in, date, LEVEL_ANY );++	if ( n==-1 ) {+		sprintf( partdate, "PARTDATE:%s", date_element );+		n = fields_find( in, partdate, LEVEL_ANY );+	}++	return n;+}++static void+append_date( fields *in, fields *out, int *status )+{ 	char *months[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",  		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };-	int n, month;-	n = fields_find( info, "YEAR", -1 );-	if ( n==-1 ) n = fields_find( info, "PARTYEAR", -1 );+	int n, month, fstatus;++	n = find_date( in, "YEAR" ); 	if ( n!=-1 ) {-		output_element( fp, "year", info->data[n].data, format_opts );-		fields_setused( info, n );+		fields_setused( in, n );+		fstatus = fields_add( out, "year", in->data[n].data, LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) {+			*status = BIBL_ERR_MEMERR;+			return;+		} 	}-	n = fields_find( info, "MONTH", -1 );-	if ( n==-1 ) n = fields_find( info, "PARTMONTH", -1 );++	n = find_date( in, "MONTH" ); 	if ( n!=-1 ) {-		month = atoi( info->data[n].data );+		fields_setused( in, n );+		month = atoi( in->data[n].data ); 		if ( month>0 && month<13 )-			output_element( fp, "month", months[month-1], format_opts );+			fstatus = fields_add( out, "month", months[month-1], LEVEL_MAIN ); 		else-			output_element( fp, "month", info->data[n].data, format_opts );-		fields_setused( info, n );+			fstatus = fields_add( out, "month", in->data[n].data, LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) {+			*status = BIBL_ERR_MEMERR;+			return;+		} 	}-	n = fields_find( info, "DAY", -1 );-	if ( n==-1 ) n = fields_find( info, "PARTDAY", -1 );++	n = find_date( in, "DAY" ); 	if ( n!=-1 ) {-		output_element( fp, "day", info->data[n].data, format_opts );-		fields_setused( info, n );+		fields_setused( in, n );+		fstatus = fields_add( out, "day", in->data[n].data, LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) {+			*status = BIBL_ERR_MEMERR;+			return;+		} 	}-} +} -/* output article number as pages if true pages aren't found */ static void-output_articlenumber( FILE *fp, fields *info, unsigned long refnum,-	int format_opts )+append_arxiv( fields *in, fields *out, int *status ) {-	int ar = fields_find( info, "ARTICLENUMBER", -1 );-	if ( ar!=-1 ) {-		newstr pages;-		newstr_init( &pages );-		newstr_strcat( &pages, info->data[ar].data );-		output_element( fp, "pages", pages.data, format_opts );-		fields_setused( info, ar );-		newstr_free( &pages );+	int n, fstatus1, fstatus2;+	str url;++	n = fields_find( in, "ARXIV", LEVEL_ANY );+	if ( n==-1 ) return;++	fields_setused( in, n );++	/* ...write:+	 *     archivePrefix = "arXiv",+	 *     eprint = "#####",+	 * ...for arXiv references+	 */+	fstatus1 = fields_add( out, "archivePrefix", "arXiv", LEVEL_MAIN );+	fstatus2 = fields_add( out, "eprint", fields_value( in, n, FIELDS_CHRP ), LEVEL_MAIN );+	if ( fstatus1!=FIELDS_OK || fstatus2!=FIELDS_OK ) {+		*status = BIBL_ERR_MEMERR;+		return; 	}++	/* ...also write:+	 *     url = "http://arxiv.org/abs/####",+	 * ...to maximize compatibility+	 */+	str_init( &url );+	arxiv_to_url( in, n, "URL", &url );+	if ( str_has_value( &url ) ) {+		fstatus1 = fields_add( out, "url", str_cstr( &url ), LEVEL_MAIN );+		if ( fstatus1!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	}+	str_free( &url ); }  static void-output_arxiv( FILE *fp, fields *info, int format_opts )+append_urls( fields *in, fields *out, int *status ) {-	int ar = fields_find( info, "ARXIV", -1 );-	if ( ar!=-1 ) {-		newstr arxiv;-		newstr_init( &arxiv );-		arxiv_to_url( info, ar, "URL", &arxiv );-		if ( arxiv.len )-			output_element( fp, "url", arxiv.data, format_opts );-		newstr_free( &arxiv );+	int lstatus;+	slist types;++	lstatus = slist_init_valuesc( &types, "URL", "DOI", "PMID", "PMC", "JSTOR", NULL );+	if ( lstatus!=SLIST_OK ) {+		*status = BIBL_ERR_MEMERR;+		return; 	}++	*status = urls_merge_and_add( in, LEVEL_ANY, out, "url", LEVEL_MAIN, &types );++	slist_free( &types ); }  static void-output_pmid( FILE *fp, fields *info, int format_opts )+append_isi( fields *in, fields *out, int *status ) {-	int pm = fields_find( info, "PMID", -1 );-	if ( pm!=-1 ) {-		newstr pmid;-		newstr_init( &pmid );-		pmid_to_url( info, pm, "URL", &pmid );-		if ( pmid.len )-			output_element( fp, "url", pmid.data, format_opts );-		newstr_free( &pmid );+	int n, fstatus;++	n = fields_find( in, "ISIREFNUM", LEVEL_ANY );+	if ( n!=-1 ) {+		fstatus = fields_add( out, "note", fields_value( in, n, FIELDS_CHRP ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR; 	} } -static void-output_jstor( FILE *fp, fields *info, int format_opts )+static int+append_articlenumber( fields *in, fields *out ) {-	int js = fields_find( info, "JSTOR", -1 );-	if ( js!=-1 ) {-		newstr jstor;-		newstr_init( &jstor );-		jstor_to_url( info, js, "URL", &jstor );-		if ( jstor.len )-			output_element( fp, "url", jstor.data, format_opts );-		newstr_free( &jstor );+	int n, fstatus;++	n = fields_find( in, "ARTICLENUMBER", LEVEL_ANY );+	if ( n!=-1 ) {+		fields_setused( in, n );+		fstatus = fields_add( out, "pages", fields_value( in, n, FIELDS_CHRP ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	}+	return BIBL_OK; } -static void-output_pages( FILE *fp, fields *info, unsigned long refnum, int format_opts )+static int+pages_build_pagestr( str *pages, fields *in, int sn, int en, int format_opts ) {-	newstr pages;-	int sn, en;-	sn = fields_find( info, "PAGESTART", -1 );-	en = fields_find( info, "PAGEEND", -1 );-	if ( sn==-1 && en==-1 ) {-		output_articlenumber( fp, info, refnum, format_opts );-		return;-	}-	newstr_init( &pages );+	/* ...append if starting page number is defined */ 	if ( sn!=-1 ) {-		newstr_strcat( &pages, info->data[sn].data );-		fields_setused( info, sn );+		str_strcat( pages, fields_value( in, sn, FIELDS_STRP ) );+		fields_setused( in, sn ); 	}++	/* ...append dashes if both starting and ending page numbers are defined */ 	if ( sn!=-1 && en!=-1 ) {-		if ( format_opts & BIBOUT_SINGLEDASH ) -			newstr_strcat( &pages, "-" );+		if ( format_opts & BIBL_FORMAT_BIBOUT_SINGLEDASH )+			str_strcatc( pages, "-" ); 		else-			newstr_strcat( &pages, "--" );+			str_strcatc( pages, "--" ); 	}++	/* ...append ending page number is defined */ 	if ( en!=-1 ) {-		newstr_strcat( &pages, info->data[en].data );-		fields_setused( info, en );+		str_strcat( pages, fields_value( in, en, FIELDS_STRP ) );+		fields_setused( in, en ); 	}-	output_element( fp, "pages", pages.data, format_opts );-	newstr_free( &pages );++	if ( str_memerr( pages ) ) return BIBL_ERR_MEMERR;+	else return BIBL_OK; } +static int+pages_are_defined( fields *in, int *sn, int *en )+{+	*sn = fields_find( in, "PAGES:START", LEVEL_ANY );+	*en = fields_find( in, "PAGES:STOP",  LEVEL_ANY );+	if ( *sn==-1 && *en==-1 ) return 0;+	else return 1;+}++static void+append_pages( fields *in, fields *out, int format_opts, int *status )+{+	int sn, en, fstatus;+	str pages;++	if ( !pages_are_defined( in, &sn, &en ) ) {+		*status = append_articlenumber( in, out );+		return;+	}++	str_init( &pages );+	*status = pages_build_pagestr( &pages, in, sn, en, format_opts );+	if ( *status==BIBL_OK ) {+		fstatus = fields_add( out, "pages", str_cstr( &pages ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	}+	str_free( &pages );+}+ /*  * from Tim Hicks:  * I'm no expert on bibtex, but those who know more than I on our mailing @@ -518,108 +739,94 @@  */  static void-output_issue_number( FILE *fp, fields *info, int format_opts )+append_issue_number( fields *in, fields *out, int *status ) {-	int nissue  = fields_find( info, "ISSUE", -1 );-	int nnumber = fields_find( info, "NUMBER", -1 );+	int nissue  = fields_find( in, "ISSUE",  LEVEL_ANY );+	int nnumber = fields_find( in, "NUMBER", LEVEL_ANY );+	int fstatus;+ 	if ( nissue!=-1 && nnumber!=-1 ) {-		output_and_use( fp, info, nissue,  "issue",  format_opts );-		output_and_use( fp, info, nnumber, "number", format_opts );-/*		output_element( fp, "issue", info->data[nissue].data, -				format_opts );-		fields_setused( info, nissue );-		output_element( fp, "number", info->data[nnumber].data, -				format_opts );-		fields_setused( info, nnumber );*/+		fields_setused( in, nissue );+		fields_setused( in, nnumber );+		fstatus = fields_add( out, "issue", fields_value( in, nissue, FIELDS_CHRP ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) {+			*status = BIBL_ERR_MEMERR;+			return;+		}+		fstatus = fields_add( out, "number", fields_value( in, nnumber, FIELDS_CHRP ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR; 	} else if ( nissue!=-1 ) {-		output_and_use( fp, info, nissue, "number", format_opts );-/*-		output_element( fp, "number", info->data[nissue].data, -				format_opts );-		fields_setused( info, nissue );*/+		fields_setused( in, nissue );+		fstatus = fields_add( out, "number", fields_value( in, nissue, FIELDS_CHRP ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR; 	} else if ( nnumber!=-1 ) {-		output_and_use( fp, info, nnumber, "number", format_opts );-/*-		output_element( fp, "number", info->data[nnumber].data, -				format_opts );-		fields_setused( info, nnumber );-*/+		fields_setused( in, nnumber );+		fstatus = fields_add( out, "number", fields_value( in, nnumber, FIELDS_CHRP ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR; 	} } -void-bibtexout_write( fields *info, FILE *fp, param *p, unsigned long refnum )+static int+append_data( fields *in, fields *out, param *p, unsigned long refnum ) {-	int type;-	fields_clearused( info );-	type = bibtexout_type( info, "", refnum, p );-	output_type( fp, type, p->format_opts );-	if ( !( p->format_opts & BIBOUT_DROPKEY ) )-		output_citekey( fp, info, refnum, p->format_opts );-	output_people( fp, info, refnum, "AUTHOR", "AUTHOR:CORP", "AUTHOR:ASIS", "author", 0,-		p->format_opts );-	output_people( fp, info, refnum, "EDITOR", "EDITOR:CORP", "EDITOR:ASIS", "editor", -1,-		p->format_opts );-	output_people( fp, info, refnum, "TRANSLATOR", "TRANSLATOR:CORP", "TRANSLATOR:ASIS", "translator", -1, p->format_opts );+	int type, status = BIBL_OK; -	/* item=main level title */-	if ( type==TYPE_INBOOK )-		output_title( fp, info, refnum, "chapter", 0, p->format_opts );-	else-		output_title( fp, info, refnum, "title", 0, p->format_opts );+	type = bibtexout_type( in, "", refnum, p ); -	/* item=host level title */-	if ( type==TYPE_ARTICLE )-		output_title( fp, info, refnum, "journal", 1, p->format_opts );-	else if ( type==TYPE_INBOOK ) {-		output_title( fp, info, refnum, "title", 1, p->format_opts );-		output_title( fp, info, refnum, "series", 2, p->format_opts );-	}-	else if ( type==TYPE_INPROCEEDINGS || type==TYPE_INCOLLECTION ) {-		output_title( fp, info, refnum, "booktitle", 1, p->format_opts );-		output_title( fp, info, refnum, "series", 2, p->format_opts );-	}-	else if ( type==TYPE_PHDTHESIS || type==TYPE_MASTERSTHESIS ) {-		output_title( fp, info, refnum, "series", 1, p->format_opts );-	}-	else if ( type==TYPE_BOOK || type==TYPE_COLLECTION || type==TYPE_PROCEEDINGS || type==TYPE_REPORT ) {-		output_title( fp, info, refnum, "series", 1, p->format_opts );-		output_title( fp, info, refnum, "series", 2, p->format_opts );-	}+	append_type        ( type, out, &status );+	append_citekey     ( in, out, p->format_opts, &status );+	append_people      ( in, "AUTHOR",     "AUTHOR:CORP",     "AUTHOR:ASIS",     "author", 0, out, p->format_opts );+	append_people      ( in, "EDITOR",     "EDITOR:CORP",     "EDITOR:ASIS",     "editor", -1, out, p->format_opts );+	append_people      ( in, "TRANSLATOR", "TRANSLATOR:CORP", "TRANSLATOR:ASIS", "translator", -1, out, p->format_opts );+	append_titles      ( in, type, out, p->format_opts, &status );+	append_date        ( in, out, &status );+	append_simple      ( in, "EDITION",            "edition",   out, &status );+	append_simple      ( in, "PUBLISHER",          "publisher", out, &status );+	append_simple      ( in, "ADDRESS",            "address",   out, &status );+	append_simple      ( in, "VOLUME",             "volume",    out, &status );+	append_issue_number( in, out, &status );+	append_pages       ( in, out, p->format_opts, &status );+	append_keywords    ( in, out, &status );+	append_simple      ( in, "CONTENTS",           "contents",  out, &status );+	append_simple      ( in, "ABSTRACT",           "abstract",  out, &status );+	append_simple      ( in, "LOCATION",           "location",  out, &status );+	append_simple      ( in, "DEGREEGRANTOR",      "school",    out, &status );+	append_simple      ( in, "DEGREEGRANTOR:ASIS", "school",    out, &status );+	append_simple      ( in, "DEGREEGRANTOR:CORP", "school",    out, &status );+	append_simpleall   ( in, "NOTES",              "note",      out, &status );+	append_simpleall   ( in, "ANNOTE",             "annote",    out, &status );+	append_simple      ( in, "ISBN",               "isbn",      out, &status );+	append_simple      ( in, "ISSN",               "issn",      out, &status );+	append_simple      ( in, "MRNUMBER",           "mrnumber",  out, &status );+	append_simple      ( in, "CODEN",              "coden",     out, &status );+	append_simple      ( in, "DOI",                "doi",       out, &status );+	append_urls        ( in, out, &status );+	append_fileattach  ( in, out, &status );+	append_arxiv       ( in, out, &status );+	append_simple      ( in, "EPRINTCLASS",        "primaryClass", out, &status );+	append_isi         ( in, out, &status );+	append_simple      ( in, "LANGUAGE",           "language",  out, &status ); -	output_date( fp, info, refnum, p->format_opts );-	output_simple( fp, info, "EDITION", "edition", p->format_opts );-	output_simple( fp, info, "PUBLISHER", "publisher", p->format_opts );-	output_simple( fp, info, "ADDRESS", "address", p->format_opts );-	output_simple( fp, info, "VOLUME", "volume", p->format_opts );-	output_issue_number( fp, info, p->format_opts );-/*	output_simple( fp, info, "ISSUE", "issue", p->format_opts );-	output_simple( fp, info, "NUMBER", "number", p->format_opts );s*/-	output_pages( fp, info, refnum, p->format_opts );-	output_keywords( fp, info, p->format_opts );-	output_simple( fp, info, "CONTENTS", "contents", p->format_opts );-	output_simple( fp, info, "ABSTRACT", "abstract", p->format_opts );-	output_simple( fp, info, "LOCATION", "location", p->format_opts );-	output_simple( fp, info, "DEGREEGRANTOR", "school", p->format_opts );-	output_simple( fp, info, "DEGREEGRANTOR:ASIS", "school", p->format_opts );-	output_simple( fp, info, "DEGREEGRANTOR:CORP", "school", p->format_opts );-	output_simpleall( fp, info, "NOTES", "note", p->format_opts );-	output_simpleall( fp, info, "ANNOTE", "annote", p->format_opts );-	output_simple( fp, info, "ISBN", "isbn", p->format_opts );-	output_simple( fp, info, "ISSN", "issn", p->format_opts );-	output_simple( fp, info, "DOI", "doi", p->format_opts );-	output_simpleall( fp, info, "URL", "url", p->format_opts );-	output_fileattach( fp, info, p->format_opts );-	output_arxiv( fp, info, p->format_opts );-	output_pmid( fp, info, p->format_opts );-	output_jstor( fp, info, p->format_opts );-	output_simple( fp, info, "LANGUAGE", "language", p->format_opts );-	if ( p->format_opts & BIBOUT_FINALCOMMA ) fprintf( fp, "," );-	fprintf( fp, "\n}\n\n" );-	fflush( fp );+	return status; } -void+static int+bibtexout_write( fields *in, FILE *fp, param *p, unsigned long refnum )+{+	int status;+	fields out;++	fields_init( &out );++	status = append_data( in, &out, p, refnum );+	if ( status==BIBL_OK ) output( fp, &out, p->format_opts );++	fields_free( &out );++	return status;+}++static void bibtexout_writeheader( FILE *outptr, param *p ) { 	if ( p->utf8bom ) utf8_writebom( outptr );
− bibutils/bibtexout.h
@@ -1,31 +0,0 @@-/*- * bibtexout.h- *- * Copyright (c) Chris Putnam 2005-2013- *- * Source code released under GPL version 2- *- */-#ifndef BIBTEXOUT_H-#define BIBTEXOUT_H--#include <stdio.h>-#include "fields.h"-#include "bibutils.h"--/* bibtexout output options */-#define BIBOUT_FINALCOMMA   (2)-#define BIBOUT_SINGLEDASH   (4)-#define BIBOUT_WHITESPACE   (8)-#define BIBOUT_BRACKETS    (16)-#define BIBOUT_UPPERCASE   (32)-#define BIBOUT_STRICTKEY   (64)-#define BIBOUT_SHORTTITLE (128)-#define BIBOUT_DROPKEY    (256)--extern void bibtexout_write( fields *info, FILE *fp, param *p, -		unsigned long refnum );-extern void bibtexout_writeheader( FILE *outptr, param *p );-extern void bibtexout_initparams( param *p, const char *progname );--#endif
bibutils/bibtextypes.c view
@@ -1,7 +1,7 @@ /*  * bibtypes.c  *- * Copyright (c) Chris Putnam 2003-2013+ * Copyright (c) Chris Putnam 2003-2017  *  * Program and source code released under the GPL version 2  *@@ -16,38 +16,44 @@  * Journal Article  */ static lookups article[] = {-	{ "author",       "AUTHOR",    PERSON, LEVEL_MAIN },-	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },-	{ "title",        "TITLE",     TITLE,  LEVEL_MAIN },-	{ "year",         "PARTYEAR",  SIMPLE, LEVEL_MAIN },-	{ "month",        "PARTMONTH", SIMPLE, LEVEL_MAIN },-	{ "day",          "PARTDAY",   SIMPLE, LEVEL_MAIN },-	{ "volume",       "VOLUME",    SIMPLE, LEVEL_MAIN },-	{ "pages",        "PAGES",     PAGES,  LEVEL_MAIN },-	{ "number",       "ISSUE",     SIMPLE, LEVEL_MAIN },-	{ "issue",        "ISSUE",     SIMPLE, LEVEL_MAIN },-	{ "journal",      "TITLE",     TITLE,  LEVEL_HOST },-	{ "publisher",    "PUBLISHER", SIMPLE, LEVEL_HOST },-	{ "address",      "ADDRESS",   SIMPLE, LEVEL_HOST },-	{ "issn",         "ISSN",      SIMPLE, LEVEL_HOST },-	{ "abstract",     "ABSTRACT",  SIMPLE, LEVEL_MAIN },-	{ "contents",     "CONTENTS",  SIMPLE, LEVEL_MAIN },-	{ "language",     "LANGUAGE",  SIMPLE, LEVEL_MAIN },-	{ "note",         "NOTES",     BT_NOTE, LEVEL_MAIN },-	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },-	{ "location",     "LOCATION",  SIMPLE, LEVEL_MAIN },-	{ "ftp",          "",      BT_URL, LEVEL_MAIN },-	{ "url",          "",      BT_URL, LEVEL_MAIN },-	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },-	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },-	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },-	{ "howpublished", "",       HOWPUBLISHED, LEVEL_MAIN },-	{ "doi",          "DOI",       SIMPLE, LEVEL_MAIN },-	{ "key",          "BIBKEY",       SIMPLE, LEVEL_MAIN },-	{ "refnum",       "REFNUM",    SIMPLE, LEVEL_MAIN },-	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },-	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },-	{ "",             "INTERNAL_TYPE|ARTICLE",           ALWAYS, LEVEL_MAIN },+	{ "author",       "AUTHOR",         PERSON,       LEVEL_MAIN },+	{ "translator",   "TRANSLATOR",     PERSON,       LEVEL_MAIN },+	{ "title",        "",               TITLE,        LEVEL_MAIN },+	{ "year",         "PARTDATE:YEAR",  SIMPLE,       LEVEL_MAIN },+	{ "month",        "PARTDATE:MONTH", SIMPLE,       LEVEL_MAIN },+	{ "day",          "PARTDATE:DAY",   SIMPLE,       LEVEL_MAIN },+	{ "volume",       "VOLUME",         SIMPLE,       LEVEL_MAIN },+	{ "pages",        "PAGES",          PAGES,        LEVEL_MAIN },+	{ "number",       "ISSUE",          SIMPLE,       LEVEL_MAIN },+	{ "issue",        "ISSUE",          SIMPLE,       LEVEL_MAIN },+	{ "journal",      "",               TITLE,        LEVEL_HOST },+	{ "publisher",    "PUBLISHER",      SIMPLE,       LEVEL_HOST },+	{ "address",      "ADDRESS",        SIMPLE,       LEVEL_HOST },+	{ "issn",         "ISSN",           SIMPLE,       LEVEL_HOST },+	{ "coden",        "CODEN",          SIMPLE,       LEVEL_HOST },+	{ "abstract",     "ABSTRACT",       SIMPLE,       LEVEL_MAIN },+	{ "contents",     "CONTENTS",       SIMPLE,       LEVEL_MAIN },+	{ "language",     "LANGUAGE",       SIMPLE,       LEVEL_MAIN },+	{ "note",         "NOTES",          NOTES,        LEVEL_MAIN },+	{ "annote",       "ANNOTE",         SIMPLE,       LEVEL_MAIN },+	{ "location",     "LOCATION",       SIMPLE,       LEVEL_MAIN },+	{ "ftp",          "",               URL,          LEVEL_MAIN },+	{ "url",          "",               URL,          LEVEL_MAIN },+	{ "pdf",          "FILEATTACH",     SIMPLE,       LEVEL_MAIN },+	{ "eprint",       "",               EPRINT,       LEVEL_MAIN },+	{ "archivePrefix","ARCHIVEPREFIX",  SIMPLE,       LEVEL_MAIN },+	{ "eprintclass",  "EPRINTCLASS",    SIMPLE,       LEVEL_MAIN },+	{ "primaryClass", "EPRINTCLASS",    SIMPLE,       LEVEL_MAIN },+	{ "sentelink",    "FILEATTACH",     BT_SENTE,     LEVEL_MAIN },+	{ "file",         "FILEATTACH",     LINKEDFILE,   LEVEL_MAIN },+	{ "howpublished", "",               HOWPUBLISHED, LEVEL_MAIN },+	{ "mrnumber",     "MRNUMBER",       SIMPLE,       LEVEL_MAIN },+	{ "doi",          "DOI",            SIMPLE,       LEVEL_MAIN },+	{ "key",          "BIBKEY",         SIMPLE,       LEVEL_MAIN },+	{ "refnum",       "REFNUM",         SIMPLE,       LEVEL_MAIN },+	{ "crossref",     "CROSSREF",       SIMPLE,       LEVEL_MAIN },+	{ "keywords",     "KEYWORD",        KEYWORD,      LEVEL_MAIN },+	{ "",             "INTERNAL_TYPE|ARTICLE",   ALWAYS, LEVEL_MAIN }, 	{ "",             "ISSUANCE|continuing",     ALWAYS, LEVEL_HOST }, 	{ "",             "RESOURCE|text",           ALWAYS, LEVEL_MAIN }, 	{ "",             "NGENRE|journal article",  ALWAYS, LEVEL_MAIN },@@ -58,43 +64,43 @@ /* Book */  static lookups book[] = {-	{ "author",       "AUTHOR",    PERSON, LEVEL_MAIN },-	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },-	{ "title",        "TITLE",     TITLE,  LEVEL_MAIN },-	{ "booktitle",    "TITLE",     TITLE,  LEVEL_MAIN },-	{ "series",       "TITLE",     TITLE,  LEVEL_HOST },-	{ "publisher",    "PUBLISHER", SIMPLE, LEVEL_MAIN },-	{ "organization", "ORGANIZER:CORP", BT_ORG, LEVEL_MAIN },-	{ "address",      "ADDRESS",   SIMPLE, LEVEL_MAIN },-	{ "editor",       "EDITOR",    PERSON, LEVEL_MAIN },-	{ "year",         "YEAR",      SIMPLE, LEVEL_MAIN },-	{ "month",        "MONTH",     SIMPLE, LEVEL_MAIN },-	{ "day",          "DAY",       SIMPLE, LEVEL_MAIN },-	{ "volume",       "VOLUME",    SIMPLE, LEVEL_MAIN },-	{ "number",       "NUMBER",    SIMPLE, LEVEL_MAIN },-	{ "isbn",         "ISBN",      SIMPLE, LEVEL_MAIN },-	{ "lccn",         "LCCN",      SIMPLE, LEVEL_MAIN },-	{ "edition",      "EDITION",   SIMPLE, LEVEL_MAIN },-	{ "abstract",     "ABSTRACT",  SIMPLE, LEVEL_MAIN },-	{ "contents",     "CONTENTS",  SIMPLE, LEVEL_MAIN },-	{ "language",     "LANGUAGE",  SIMPLE, LEVEL_MAIN },-	{ "location",     "LOCATION",  SIMPLE, LEVEL_MAIN },-	{ "note",         "NOTES",     BT_NOTE, LEVEL_MAIN },-	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },-	{ "type",         "GENRE",     SIMPLE, LEVEL_MAIN },-	{ "key",          "BIBKEY",    SIMPLE, LEVEL_MAIN },-	{ "ftp",          "",       BT_URL, LEVEL_MAIN },-	{ "url",          "",       BT_URL, LEVEL_MAIN },-	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },-	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },-	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },-	{ "address",      "ADDRESS",   SIMPLE, LEVEL_MAIN },-	{ "howpublished", "",       HOWPUBLISHED, LEVEL_MAIN },-	{ "doi",          "DOI",       SIMPLE, LEVEL_MAIN },-	{ "refnum",       "REFNUM",    SIMPLE, LEVEL_MAIN },-	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },-	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },-	{ "refnum",       "REFNUM",    SIMPLE, LEVEL_MAIN },+	{ "author",       "AUTHOR",         PERSON,       LEVEL_MAIN },+	{ "translator",   "TRANSLATOR",     PERSON,       LEVEL_MAIN },+	{ "title",        "",               TITLE,        LEVEL_MAIN },+	{ "booktitle",    "",               TITLE,        LEVEL_MAIN },+	{ "series",       "",               TITLE,        LEVEL_HOST },+	{ "publisher",    "PUBLISHER",      SIMPLE,       LEVEL_MAIN },+	{ "organization", "ORGANIZER:CORP", BT_ORG,       LEVEL_MAIN },+	{ "address",      "ADDRESS",        SIMPLE,       LEVEL_MAIN },+	{ "editor",       "EDITOR",         PERSON,       LEVEL_MAIN },+	{ "year",         "DATE:YEAR",      SIMPLE,       LEVEL_MAIN },+	{ "month",        "DATE:MONTH",     SIMPLE,       LEVEL_MAIN },+	{ "day",          "DATE:DAY",       SIMPLE,       LEVEL_MAIN },+	{ "volume",       "VOLUME",         SIMPLE,       LEVEL_MAIN },+	{ "number",       "NUMBER",         SIMPLE,       LEVEL_MAIN },+	{ "isbn",         "ISBN",           SIMPLE,       LEVEL_MAIN },+	{ "lccn",         "LCCN",           SIMPLE,       LEVEL_MAIN },+	{ "edition",      "EDITION",        SIMPLE,       LEVEL_MAIN },+	{ "abstract",     "ABSTRACT",       SIMPLE,       LEVEL_MAIN },+	{ "contents",     "CONTENTS",       SIMPLE,       LEVEL_MAIN },+	{ "language",     "LANGUAGE",       SIMPLE,       LEVEL_MAIN },+	{ "location",     "LOCATION",       SIMPLE,       LEVEL_MAIN },+	{ "note",         "NOTES",          NOTES,        LEVEL_MAIN },+	{ "annote",       "ANNOTE",         SIMPLE,       LEVEL_MAIN },+	{ "type",         "GENRE",          SIMPLE,       LEVEL_MAIN },+	{ "key",          "BIBKEY",         SIMPLE,       LEVEL_MAIN },+	{ "ftp",          "",               URL,          LEVEL_MAIN },+	{ "url",          "",               URL,          LEVEL_MAIN },+	{ "pdf",          "FILEATTACH",     SIMPLE,       LEVEL_MAIN },+	{ "sentelink",    "FILEATTACH",     BT_SENTE,     LEVEL_MAIN },+	{ "file",         "FILEATTACH",     LINKEDFILE,   LEVEL_MAIN },+	{ "address",      "ADDRESS",        SIMPLE,       LEVEL_MAIN },+	{ "howpublished", "",               HOWPUBLISHED, LEVEL_MAIN },+	{ "doi",          "DOI",            SIMPLE,       LEVEL_MAIN },+	{ "refnum",       "REFNUM",         SIMPLE,       LEVEL_MAIN },+	{ "crossref",     "CROSSREF",       SIMPLE,       LEVEL_MAIN },+	{ "keywords",     "KEYWORD",        KEYWORD,      LEVEL_MAIN },+	{ "refnum",       "REFNUM",         SIMPLE,       LEVEL_MAIN }, 	{ "",             "INTERNAL_TYPE|BOOK",   ALWAYS, LEVEL_MAIN }, 	{ "",             "RESOURCE|text",        ALWAYS, LEVEL_MAIN }, 	{ "",             "ISSUANCE|monographic", ALWAYS, LEVEL_MAIN },@@ -104,39 +110,40 @@ /* Technical reports */  static lookups report[] = {-	{ "author",       "AUTHOR",       PERSON, LEVEL_MAIN },-	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },-	{ "title",        "TITLE",        TITLE,  LEVEL_MAIN },-	{ "booktitle",    "TITLE",        TITLE,  LEVEL_MAIN },-	{ "series",       "TITLE",        TITLE,  LEVEL_HOST },-	{ "editor",       "EDITOR",       PERSON, LEVEL_MAIN },-	{ "publisher",    "PUBLISHER",    SIMPLE, LEVEL_MAIN },-	{ "institution",  "PUBLISHER",    SIMPLE, LEVEL_MAIN },-	{ "address",      "ADDRESS",      SIMPLE, LEVEL_MAIN },-	{ "year",         "YEAR",         SIMPLE, LEVEL_MAIN },-	{ "month",        "MONTH",        SIMPLE, LEVEL_MAIN },-	{ "day",          "DAY",          SIMPLE, LEVEL_MAIN },-	{ "number",       "NUMBER",       SIMPLE, LEVEL_MAIN },-	{ "isbn",         "ISBN",         SIMPLE, LEVEL_MAIN },-	{ "lccn",         "LCCN",         SIMPLE, LEVEL_MAIN },-	{ "abstract",     "ABSTRACT",     SIMPLE, LEVEL_MAIN },-	{ "contents",     "CONTENTS",     SIMPLE, LEVEL_MAIN },-	{ "language",     "LANGUAGE",     SIMPLE, LEVEL_MAIN },-	{ "location",     "LOCATION",     SIMPLE, LEVEL_MAIN },-	{ "note",         "NOTES",        BT_NOTE, LEVEL_MAIN },-	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },-	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN },-	{ "doi",          "DOI",          SIMPLE, LEVEL_MAIN },-	{ "ftp",          "",          BT_URL, LEVEL_MAIN },-	{ "url",          "",          BT_URL, LEVEL_MAIN },-	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },-	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },-	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },-	{ "howpublished", "",          HOWPUBLISHED, LEVEL_MAIN },-	{ "refnum",    "REFNUM",          SIMPLE, LEVEL_MAIN },-	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },-	{ "type",      "GENRE",            SIMPLE, LEVEL_MAIN },-	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },+	{ "author",       "AUTHOR",     PERSON,       LEVEL_MAIN },+	{ "translator",   "TRANSLATOR", PERSON,       LEVEL_MAIN },+	{ "title",        "",           TITLE,        LEVEL_MAIN },+	{ "booktitle",    "",           TITLE,        LEVEL_MAIN },+	{ "series",       "",           TITLE,        LEVEL_HOST },+	{ "editor",       "EDITOR",     PERSON,       LEVEL_MAIN },+	{ "publisher",    "PUBLISHER",  SIMPLE,       LEVEL_MAIN },+	{ "institution",  "PUBLISHER",  SIMPLE,       LEVEL_MAIN },+	{ "address",      "ADDRESS",    SIMPLE,       LEVEL_MAIN },+	{ "year",         "DATE:YEAR",  SIMPLE,       LEVEL_MAIN },+	{ "month",        "DATE:MONTH", SIMPLE,       LEVEL_MAIN },+	{ "day",          "DATE:DAY",   SIMPLE,       LEVEL_MAIN },+	{ "number",       "NUMBER",     SIMPLE,       LEVEL_MAIN },+	{ "isbn",         "ISBN",       SIMPLE,       LEVEL_MAIN },+	{ "lccn",         "LCCN",       SIMPLE,       LEVEL_MAIN },+	{ "abstract",     "ABSTRACT",   SIMPLE,       LEVEL_MAIN },+	{ "contents",     "CONTENTS",   SIMPLE,       LEVEL_MAIN },+	{ "language",     "LANGUAGE",   SIMPLE,       LEVEL_MAIN },+	{ "location",     "LOCATION",   SIMPLE,       LEVEL_MAIN },+	{ "note",         "NOTES",      NOTES,        LEVEL_MAIN },+	{ "annote",       "ANNOTE",     SIMPLE,       LEVEL_MAIN },+	{ "key",          "BIBKEY",     SIMPLE,       LEVEL_MAIN },+	{ "doi",          "DOI",        SIMPLE,       LEVEL_MAIN },+	{ "ftp",          "",           URL,          LEVEL_MAIN },+	{ "url",          "",           URL,          LEVEL_MAIN },+	{ "mrnumber",     "MRNUMBER",   SIMPLE,       LEVEL_MAIN },+	{ "pdf",          "FILEATTACH", SIMPLE,       LEVEL_MAIN },+	{ "sentelink",    "FILEATTACH", BT_SENTE,     LEVEL_MAIN },+	{ "file",         "FILEATTACH", LINKEDFILE,   LEVEL_MAIN },+	{ "howpublished", "",           HOWPUBLISHED, LEVEL_MAIN },+	{ "refnum",       "REFNUM",     SIMPLE,       LEVEL_MAIN },+	{ "crossref",     "CROSSREF",   SIMPLE,       LEVEL_MAIN },+	{ "type",         "GENRE",      SIMPLE,       LEVEL_MAIN },+	{ "keywords",     "KEYWORD",    KEYWORD,      LEVEL_MAIN }, 	{ "",         "INTERNAL_TYPE|REPORT", ALWAYS, LEVEL_MAIN }, 	{ "",         "RESOURCE|text",        ALWAYS, LEVEL_MAIN }, 	{ "",         "GENRE|report",         ALWAYS, LEVEL_MAIN }@@ -145,27 +152,27 @@ static lookups manual[] = { 	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN }, 	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },-	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },-	{ "booktitle", "TITLE",     TITLE,  LEVEL_MAIN },+	{ "title",     "",     TITLE,  LEVEL_MAIN },+	{ "booktitle", "",     TITLE,  LEVEL_MAIN }, 	{ "editor",    "EDITOR",    PERSON, LEVEL_MAIN }, 	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_MAIN }, 	{ "organization", "ORGANIZER:CORP", BT_ORG, LEVEL_MAIN }, 	{ "address",   "ADDRESS",   SIMPLE, LEVEL_MAIN },-	{ "year",      "YEAR",      SIMPLE, LEVEL_MAIN },-	{ "month",     "MONTH",     SIMPLE, LEVEL_MAIN },-	{ "day",       "DAY",       SIMPLE, LEVEL_MAIN },+	{ "year",      "DATE:YEAR",      SIMPLE, LEVEL_MAIN },+	{ "month",     "DATE:MONTH",     SIMPLE, LEVEL_MAIN },+	{ "day",       "DATE:DAY",       SIMPLE, LEVEL_MAIN }, 	{ "isbn",      "ISBN",      SIMPLE, LEVEL_MAIN }, 	{ "lccn",      "LCCN",      SIMPLE, LEVEL_MAIN }, 	{ "edition",   "EDITION",   SIMPLE, LEVEL_MAIN }, 	{ "abstract",  "ABSTRACT",  SIMPLE, LEVEL_MAIN }, 	{ "contents",  "CONTENTS",  SIMPLE, LEVEL_MAIN }, 	{ "location",     "LOCATION",     SIMPLE, LEVEL_MAIN },-	{ "note",         "NOTES",        BT_NOTE, LEVEL_MAIN },+	{ "note",         "NOTES",        NOTES,   LEVEL_MAIN }, 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN }, 	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN }, 	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },-	{ "ftp",       "",       BT_URL, LEVEL_MAIN },-	{ "url",       "",       BT_URL, LEVEL_MAIN },+	{ "ftp",       "",       URL,    LEVEL_MAIN },+	{ "url",       "",       URL,    LEVEL_MAIN }, 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN }, 	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN }, 	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },@@ -182,65 +189,65 @@ /* Part of a book (e.g. chapter or section) */  static lookups inbook[] = {-	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN },+	{ "author",       "AUTHOR",    PERSON, LEVEL_MAIN }, 	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },-	{ "editor",    "EDITOR",    PERSON, LEVEL_HOST },-	{ "chapter",   "CHAPTER",   SIMPLE, LEVEL_MAIN },-	{ "title",     "TITLE",     TITLE,  LEVEL_HOST },-	{ "booktitle", "TITLE",     TITLE,  LEVEL_HOST },-	{ "series",    "TITLE",     TITLE,  LEVEL_SERIES },-	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_HOST },-	{ "address",   "ADDRESS",   SIMPLE, LEVEL_HOST },-	{ "year",      "YEAR",      SIMPLE, LEVEL_HOST },-	{ "month",     "MONTH",     SIMPLE, LEVEL_HOST },-	{ "day",       "DAY",       SIMPLE, LEVEL_HOST },-	{ "volume",    "VOLUME",    SIMPLE, LEVEL_SERIES },-	{ "number",    "NUMBER",    SIMPLE, LEVEL_SERIES },-	{ "pages",     "PAGES",     PAGES,  LEVEL_HOST },-	{ "isbn",      "ISBN",      SIMPLE, LEVEL_HOST },-	{ "lccn",      "LCCN",      SIMPLE, LEVEL_HOST },-	{ "edition",   "EDITION",   SIMPLE, LEVEL_HOST },-	{ "abstract",  "ABSTRACT",  SIMPLE, LEVEL_MAIN },-	{ "contents",  "CONTENTS",  SIMPLE, LEVEL_HOST },-	{ "language",     "LANGUAGE",     SIMPLE, LEVEL_MAIN },-	{ "location",     "LOCATION",     SIMPLE, LEVEL_HOST },-	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },-	{ "ftp",       "",       BT_URL, LEVEL_MAIN },-	{ "url",       "",       BT_URL, LEVEL_MAIN },+	{ "editor",       "EDITOR",    PERSON, LEVEL_HOST },+	{ "chapter",      "CHAPTER",   SIMPLE, LEVEL_MAIN },   /* chapter number */+	{ "title",        "",          TITLE,  LEVEL_MAIN },   /* chapter name */+	{ "booktitle",    "",          TITLE,  LEVEL_HOST },+	{ "series",       "",          TITLE,  LEVEL_SERIES },+	{ "publisher",    "PUBLISHER", SIMPLE, LEVEL_HOST },+	{ "address",      "ADDRESS",   SIMPLE, LEVEL_HOST },+	{ "year",         "DATE:YEAR", SIMPLE, LEVEL_HOST },+	{ "month",        "DATE:MONTH",SIMPLE, LEVEL_HOST },+	{ "day",          "DATE:DAY",  SIMPLE, LEVEL_HOST },+	{ "volume",       "VOLUME",    SIMPLE, LEVEL_SERIES },+	{ "number",       "NUMBER",    SIMPLE, LEVEL_SERIES },+	{ "pages",        "PAGES",     PAGES,  LEVEL_HOST },+	{ "isbn",         "ISBN",      SIMPLE, LEVEL_HOST },+	{ "lccn",         "LCCN",      SIMPLE, LEVEL_HOST },+	{ "edition",      "EDITION",   SIMPLE, LEVEL_HOST },+	{ "abstract",     "ABSTRACT",  SIMPLE, LEVEL_MAIN },+	{ "contents",     "CONTENTS",  SIMPLE, LEVEL_HOST },+	{ "language",     "LANGUAGE",  SIMPLE, LEVEL_MAIN },+	{ "location",     "LOCATION",  SIMPLE, LEVEL_HOST },+	{ "doi",          "DOI",       SIMPLE, LEVEL_MAIN },+	{ "ftp",          "",          URL,    LEVEL_MAIN },+	{ "url",          "",          URL,    LEVEL_MAIN }, 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN }, 	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN }, 	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN }, 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },-	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },+	{ "refnum",       "REFNUM",    SIMPLE, LEVEL_MAIN }, 	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },-	{ "type",      "GENRE",      SIMPLE, LEVEL_MAIN },-	{ "note",         "NOTES",        BT_NOTE, LEVEL_MAIN },+	{ "type",         "GENRE",      SIMPLE, LEVEL_MAIN },+	{ "note",         "NOTES",        NOTES,   LEVEL_MAIN }, 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN }, 	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN }, 	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },-	{ "",         "INTERNAL_TYPE|INBOOK", ALWAYS, LEVEL_MAIN },-	{ "",         "RESOURCE|text",        ALWAYS, LEVEL_MAIN },-	{ "",         "ISSUANCE|monographic", ALWAYS, LEVEL_HOST },-	{ "",         "NGENRE|book chapter",  ALWAYS, LEVEL_MAIN },-	{ "",         "GENRE|book",           ALWAYS, LEVEL_HOST }+	{ "",             "INTERNAL_TYPE|INBOOK", ALWAYS, LEVEL_MAIN },+	{ "",             "RESOURCE|text",        ALWAYS, LEVEL_MAIN },+	{ "",             "ISSUANCE|monographic", ALWAYS, LEVEL_HOST },+	{ "",             "NGENRE|book chapter",  ALWAYS, LEVEL_MAIN },+	{ "",             "GENRE|book",           ALWAYS, LEVEL_HOST } };  /* References of papers in conference proceedings */  static lookups inproceedings[] = {-	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN },-	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },-	{ "editor",    "EDITOR",    PERSON, LEVEL_HOST },-	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },-	{ "booktitle", "TITLE",     TITLE,  LEVEL_HOST },-	{ "series",    "TITLE",     TITLE,  LEVEL_SERIES },-	{ "chapter",   "CHAPTER",   SIMPLE, LEVEL_MAIN },-	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_HOST },+	{ "author",     "AUTHOR",     PERSON, LEVEL_MAIN },+	{ "translator", "TRANSLATOR", PERSON, LEVEL_MAIN },+	{ "editor",     "EDITOR",     PERSON, LEVEL_HOST },+	{ "chapter",    "CHAPTER",    SIMPLE, LEVEL_MAIN },   /* chapter number */+	{ "title",      "",           TITLE,  LEVEL_MAIN },   /* chapter name */+	{ "booktitle",  "",           TITLE,  LEVEL_HOST },+	{ "series",     "",           TITLE,  LEVEL_SERIES },+	{ "publisher",  "PUBLISHER",  SIMPLE, LEVEL_HOST }, 	{ "organization", "ORGANIZER:CORP", BT_ORG, LEVEL_HOST }, 	{ "address",   "ADDRESS",   SIMPLE, LEVEL_HOST },-	{ "year",      "PARTYEAR",  SIMPLE, LEVEL_MAIN },-	{ "month",     "PARTMONTH", SIMPLE, LEVEL_MAIN },-	{ "day",       "PARTDAY",   SIMPLE, LEVEL_MAIN },+	{ "year",      "PARTDATE:YEAR",  SIMPLE, LEVEL_MAIN },+	{ "month",     "PARTDATE:MONTH", SIMPLE, LEVEL_MAIN },+	{ "day",       "PARTDATE:DAY",   SIMPLE, LEVEL_MAIN }, 	{ "volume",    "VOLUME",    SIMPLE, LEVEL_MAIN }, 	{ "number",    "NUMBER",    SIMPLE, LEVEL_MAIN }, 	{ "pages",     "PAGES",     PAGES,  LEVEL_MAIN },@@ -252,13 +259,13 @@ 	{ "paper",     "PAPER",     SIMPLE, LEVEL_MAIN }, 	{ "location",     "LOCATION",     SIMPLE, LEVEL_HOST }, 	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },-	{ "ftp",       "",       BT_URL, LEVEL_MAIN },-	{ "url",       "",       BT_URL, LEVEL_MAIN },+	{ "ftp",       "",          URL,    LEVEL_MAIN },+	{ "url",       "",          URL,    LEVEL_MAIN }, 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN }, 	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN }, 	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN }, 	{ "type",      "GENRE",      SIMPLE, LEVEL_MAIN },-	{ "note",         "NOTES",        BT_NOTE, LEVEL_MAIN },+	{ "note",         "NOTES",        NOTES,   LEVEL_MAIN }, 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN }, 	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN }, 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },@@ -273,18 +280,18 @@ /* Used for a section of a book with its own title */  static lookups incollection[] = {-	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN },-	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },-	{ "editor",    "EDITOR",    PERSON, LEVEL_HOST },-	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },-	{ "chapter",   "CHAPTER",   SIMPLE, LEVEL_MAIN },-	{ "booktitle", "TITLE",     TITLE,  LEVEL_HOST },-	{ "series",    "TITLE",     TITLE,  LEVEL_SERIES },-	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_HOST },+	{ "author",     "AUTHOR",     PERSON, LEVEL_MAIN },+	{ "translator", "TRANSLATOR", PERSON, LEVEL_MAIN },+	{ "editor",     "EDITOR",     PERSON, LEVEL_HOST },+	{ "chapter",    "CHAPTER",    SIMPLE, LEVEL_MAIN },   /* chapter number */+	{ "title",      "",           TITLE,  LEVEL_MAIN },   /* chapter name */+	{ "booktitle",  "",           TITLE,  LEVEL_HOST },+	{ "series",     "",           TITLE,  LEVEL_SERIES },+	{ "publisher",  "PUBLISHER",  SIMPLE, LEVEL_HOST }, 	{ "address",   "ADDRESS",   SIMPLE, LEVEL_HOST },-	{ "year",      "YEAR",      SIMPLE, LEVEL_HOST },-	{ "month",     "MONTH",     SIMPLE, LEVEL_HOST },-	{ "day",       "DAY",       SIMPLE, LEVEL_HOST },+	{ "year",      "DATE:YEAR",      SIMPLE, LEVEL_HOST },+	{ "month",     "DATE:MONTH",     SIMPLE, LEVEL_HOST },+	{ "day",       "DATE:DAY",       SIMPLE, LEVEL_HOST }, 	{ "volume",    "VOLUME",    SIMPLE, LEVEL_MAIN }, 	{ "number",    "NUMBER",    SIMPLE, LEVEL_MAIN }, 	{ "pages",     "PAGES",     PAGES,  LEVEL_MAIN },@@ -293,17 +300,17 @@ 	{ "edition",   "EDITION",   SIMPLE, LEVEL_HOST }, 	{ "abstract",  "ABSTRACT",  SIMPLE, LEVEL_MAIN }, 	{ "contents",  "CONTENTS",  SIMPLE, LEVEL_HOST },-	{ "language",     "LANGUAGE",     SIMPLE, LEVEL_MAIN },-	{ "type",      "GENRE",      SIMPLE, LEVEL_MAIN },-	{ "note",         "NOTES",        BT_NOTE, LEVEL_MAIN },-	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },-	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN },+	{ "language",  "LANGUAGE",  SIMPLE, LEVEL_MAIN },+	{ "type",      "GENRE",     SIMPLE, LEVEL_MAIN },+	{ "note",      "NOTES",     NOTES,  LEVEL_MAIN },+	{ "annote",    "ANNOTE",    SIMPLE, LEVEL_MAIN },+	{ "key",       "BIBKEY",    SIMPLE, LEVEL_MAIN }, 	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },-	{ "ftp",       "",       BT_URL, LEVEL_MAIN },-	{ "url",       "",       BT_URL, LEVEL_MAIN },-	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },-	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },-	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },+	{ "ftp",       "",          URL,    LEVEL_MAIN },+	{ "url",       "",          URL,    LEVEL_MAIN },+	{ "pdf",       "FILEATTACH",SIMPLE, LEVEL_MAIN },+	{ "sentelink", "FILEATTACH",BT_SENTE, LEVEL_MAIN },+	{ "file",      "FILEATTACH",LINKEDFILE,   LEVEL_MAIN }, 	{ "location",     "LOCATION",     SIMPLE, LEVEL_HOST }, 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN }, 	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },@@ -321,15 +328,15 @@ 	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN }, 	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "editor",    "EDITOR",    PERSON, LEVEL_MAIN },-	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },-	{ "booktitle", "TITLE",     TITLE,  LEVEL_MAIN },-	{ "series",    "TITLE",     TITLE,  LEVEL_HOST },+	{ "title",     "",     TITLE,  LEVEL_MAIN },+	{ "booktitle", "",     TITLE,  LEVEL_MAIN },+	{ "series",    "",     TITLE,  LEVEL_HOST }, 	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_MAIN }, 	{ "organization", "ORGANIZER:CORP", BT_ORG, LEVEL_MAIN }, 	{ "address",   "ADDRESS",   SIMPLE, LEVEL_MAIN },-	{ "year",      "YEAR",      SIMPLE, LEVEL_MAIN },-	{ "month",     "MONTH",     SIMPLE, LEVEL_MAIN },-	{ "day",       "DAY",       SIMPLE, LEVEL_MAIN },+	{ "year",      "DATE:YEAR",      SIMPLE, LEVEL_MAIN },+	{ "month",     "DATE:MONTH",     SIMPLE, LEVEL_MAIN },+	{ "day",       "DATE:DAY",       SIMPLE, LEVEL_MAIN }, 	{ "volume",    "VOLUME",    SIMPLE, LEVEL_MAIN }, 	{ "number",    "NUMBER",    SIMPLE, LEVEL_MAIN }, 	{ "pages",     "PAGES",     PAGES,  LEVEL_MAIN },@@ -338,15 +345,15 @@ 	{ "abstract",  "ABSTRACT",  SIMPLE, LEVEL_MAIN }, 	{ "contents",  "CONTENTS",  SIMPLE, LEVEL_MAIN }, 	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },-	{ "ftp",       "",       BT_URL, LEVEL_MAIN },-	{ "url",       "",       BT_URL, LEVEL_MAIN },+	{ "ftp",       "",          URL,    LEVEL_MAIN },+	{ "url",       "",          URL,    LEVEL_MAIN }, 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN }, 	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN }, 	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN }, 	{ "language",     "LANGUAGE",     SIMPLE, LEVEL_MAIN }, 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN }, 	{ "location",     "LOCATION",     SIMPLE, LEVEL_MAIN },-	{ "note",         "NOTES",        BT_NOTE, LEVEL_MAIN },+	{ "note",         "NOTES",        NOTES,   LEVEL_MAIN }, 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN }, 	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN }, 	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },@@ -360,24 +367,24 @@ static lookups phds[] = { 	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN }, 	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },-	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },-	{ "year",      "YEAR",      SIMPLE, LEVEL_MAIN },-	{ "month",     "MONTH",     SIMPLE, LEVEL_MAIN },-	{ "day",       "DAY",       SIMPLE, LEVEL_MAIN },+	{ "title",     "",     TITLE,  LEVEL_MAIN },+	{ "year",      "DATE:YEAR",      SIMPLE, LEVEL_MAIN },+	{ "month",     "DATE:MONTH",     SIMPLE, LEVEL_MAIN },+	{ "day",       "DATE:DAY",       SIMPLE, LEVEL_MAIN }, 	{ "school",    "DEGREEGRANTOR:ASIS",SIMPLE, LEVEL_MAIN }, 	{ "address",   "ADDRESS",   SIMPLE, LEVEL_MAIN }, 	{ "abstract",  "ABSTRACT",  SIMPLE, LEVEL_MAIN }, 	{ "contents",  "CONTENTS",  SIMPLE, LEVEL_MAIN }, 	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },-	{ "ftp",       "",       BT_URL, LEVEL_MAIN },-	{ "url",       "",       BT_URL, LEVEL_MAIN },+	{ "ftp",       "",          URL,    LEVEL_MAIN },+	{ "url",       "",          URL,    LEVEL_MAIN }, 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN }, 	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN }, 	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN }, 	{ "howpublished", "" ,   HOWPUBLISHED, LEVEL_MAIN }, 	{ "language",     "LANGUAGE",     SIMPLE, LEVEL_MAIN }, 	{ "location",     "LOCATION",     SIMPLE, LEVEL_MAIN },-	{ "note",         "NOTES",        BT_NOTE, LEVEL_MAIN },+	{ "note",         "NOTES",        NOTES,   LEVEL_MAIN }, 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN }, 	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN }, 	{ "type",         "GENRE",         SIMPLE, LEVEL_MAIN },@@ -393,23 +400,23 @@ static lookups masters[] = { 	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN }, 	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },-	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },-	{ "year",      "YEAR",      SIMPLE, LEVEL_MAIN },-	{ "month",     "MONTH",     SIMPLE, LEVEL_MAIN },-	{ "day",       "DAY",       SIMPLE, LEVEL_MAIN },+	{ "title",     "",     TITLE,  LEVEL_MAIN },+	{ "year",      "DATE:YEAR",      SIMPLE, LEVEL_MAIN },+	{ "month",     "DATE:MONTH",     SIMPLE, LEVEL_MAIN },+	{ "day",       "DATE:DAY",       SIMPLE, LEVEL_MAIN }, 	{ "school",    "DEGREEGRANTOR:ASIS",SIMPLE, LEVEL_MAIN }, 	{ "address",   "ADDRESS",   SIMPLE, LEVEL_MAIN }, 	{ "abstract",  "ABSTRACT",  SIMPLE, LEVEL_MAIN }, 	{ "contents",  "CONTENTS",  SIMPLE, LEVEL_MAIN }, 	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },-	{ "ftp",       "",       BT_URL, LEVEL_MAIN },-	{ "url",       "",       BT_URL, LEVEL_MAIN },+	{ "ftp",       "",          URL,   LEVEL_MAIN },+	{ "url",       "",          URL,   LEVEL_MAIN }, 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN }, 	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN }, 	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN }, 	{ "language",     "LANGUAGE",     SIMPLE, LEVEL_MAIN }, 	{ "location",     "LOCATION",     SIMPLE, LEVEL_MAIN },-	{ "note",         "NOTES",        BT_NOTE, LEVEL_MAIN },+	{ "note",         "NOTES",        NOTES,   LEVEL_MAIN }, 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN }, 	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN }, 	{ "type",         "GENRE",         SIMPLE, LEVEL_MAIN },@@ -428,26 +435,26 @@ static lookups unpublished[] = { 	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN }, 	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },-	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },-	{ "booktitle", "TITLE",     TITLE,  LEVEL_MAIN },+	{ "title",     "",     TITLE,  LEVEL_MAIN },+	{ "booktitle", "",     TITLE,  LEVEL_MAIN }, 	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_MAIN }, 	{ "address",   "ADDRESS",   SIMPLE, LEVEL_MAIN }, 	{ "editor",    "EDITOR",    PERSON, LEVEL_MAIN },-	{ "year",      "YEAR",      SIMPLE, LEVEL_MAIN },-	{ "month",     "MONTH",     SIMPLE, LEVEL_MAIN },-	{ "day",       "DAY",       SIMPLE, LEVEL_MAIN },+	{ "year",      "DATE:YEAR",      SIMPLE, LEVEL_MAIN },+	{ "month",     "DATE:MONTH",     SIMPLE, LEVEL_MAIN },+	{ "day",       "DATE:DAY",       SIMPLE, LEVEL_MAIN }, 	{ "abstract",  "ABSTRACT",  SIMPLE, LEVEL_MAIN }, 	{ "contents",  "CONTENTS",  SIMPLE, LEVEL_MAIN }, 	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },-	{ "ftp",       "",       BT_URL, LEVEL_MAIN },-	{ "url",       "",       BT_URL, LEVEL_MAIN },+	{ "ftp",       "",          URL,    LEVEL_MAIN },+	{ "url",       "",          URL,    LEVEL_MAIN }, 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN }, 	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN }, 	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN }, 	{ "language",     "LANGUAGE",     SIMPLE, LEVEL_MAIN }, 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN }, 	{ "location",     "LOCATION",     SIMPLE, LEVEL_MAIN },-	{ "note",         "NOTES",        BT_NOTE, LEVEL_MAIN },+	{ "note",         "NOTES",        NOTES,   LEVEL_MAIN }, 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN }, 	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN }, 	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },@@ -466,32 +473,32 @@ 	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "organization", "ORGANIZER:CORP", BT_ORG, LEVEL_MAIN }, 	{ "institution", "AUTHOR:CORP", SIMPLE, LEVEL_MAIN },-	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },-	{ "booktitle", "TITLE",     TITLE,  LEVEL_MAIN },-	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_MAIN },-	{ "address",   "ADDRESS",   SIMPLE, LEVEL_MAIN },-	{ "editor",    "EDITOR",    PERSON, LEVEL_MAIN },-	{ "year",      "YEAR",      SIMPLE, LEVEL_MAIN },-	{ "month",     "MONTH",     SIMPLE, LEVEL_MAIN },-	{ "day",       "DAY",       SIMPLE, LEVEL_MAIN },-	{ "isbn",      "ISBN",      SIMPLE, LEVEL_MAIN },-	{ "lccn",      "LCCN",      SIMPLE, LEVEL_MAIN },-	{ "abstract",  "ABSTRACT",  SIMPLE, LEVEL_MAIN },-	{ "contents",  "CONTENTS",  SIMPLE, LEVEL_MAIN },-	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },-	{ "ftp",       "",      BT_URL, LEVEL_MAIN },-	{ "url",       "",      BT_URL, LEVEL_MAIN },-	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },-	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },+	{ "title",     "",           TITLE,    LEVEL_MAIN },+	{ "booktitle", "",           TITLE,    LEVEL_MAIN },+	{ "publisher", "PUBLISHER",  SIMPLE,   LEVEL_MAIN },+	{ "address",   "ADDRESS",    SIMPLE,   LEVEL_MAIN },+	{ "editor",    "EDITOR",     PERSON,   LEVEL_MAIN },+	{ "year",      "DATE:YEAR",  SIMPLE,   LEVEL_MAIN },+	{ "month",     "DATE:MONTH", SIMPLE,   LEVEL_MAIN },+	{ "day",       "DATE:DAY",   SIMPLE,   LEVEL_MAIN },+	{ "isbn",      "ISBN",       SIMPLE,   LEVEL_MAIN },+	{ "lccn",      "LCCN",       SIMPLE,   LEVEL_MAIN },+	{ "abstract",  "ABSTRACT",   SIMPLE,   LEVEL_MAIN },+	{ "contents",  "CONTENTS",   SIMPLE,   LEVEL_MAIN },+	{ "doi",       "DOI",        SIMPLE,   LEVEL_MAIN },+	{ "ftp",       "",           URL,      LEVEL_MAIN },+	{ "url",       "",           URL,      LEVEL_MAIN },+	{ "pdf",       "FILEATTACH", SIMPLE,   LEVEL_MAIN },+	{ "sentelink", "FILEATTACH", BT_SENTE, LEVEL_MAIN }, 	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN }, 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN }, 	{ "language",     "LANGUAGE",     SIMPLE, LEVEL_MAIN }, 	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN }, 	{ "type",      "GENRE",      SIMPLE, LEVEL_MAIN },-	{ "number",    "NUMBER",      TITLE,  LEVEL_MAIN },-	{ "revision",  "REVISION",    TITLE,  LEVEL_MAIN },+	{ "number",    "NUMBER",      SIMPLE,  LEVEL_MAIN },+	{ "revision",  "EDITION",    SIMPLE,  LEVEL_MAIN }, 	{ "location",     "LOCATION",     SIMPLE, LEVEL_MAIN },-	{ "note",         "NOTES",        BT_NOTE, LEVEL_MAIN },+	{ "note",         "NOTES",        NOTES,   LEVEL_MAIN }, 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN }, 	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN }, 	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },@@ -504,30 +511,31 @@  * For Journals and Magazines  */ static lookups periodical[] = {-	{ "title",        "TITLE",       TITLE,  LEVEL_MAIN },-	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },-	{ "series",       "TITLE",       TITLE,  LEVEL_HOST },+	{ "title",        "",            TITLE,  LEVEL_MAIN },+	{ "translator",   "TRANSLATOR",  PERSON, LEVEL_MAIN },+	{ "series",       "",            TITLE,  LEVEL_HOST }, 	{ "publisher",    "PUBLISHER",   SIMPLE, LEVEL_MAIN }, 	{ "address",      "ADDRESS",     SIMPLE, LEVEL_MAIN }, 	{ "editor",       "EDITOR",      PERSON, LEVEL_MAIN },-	{ "year",         "YEAR",        SIMPLE, LEVEL_MAIN },-	{ "month",        "MONTH",       SIMPLE, LEVEL_MAIN },-	{ "day",          "DAY",         SIMPLE, LEVEL_MAIN },+	{ "year",         "DATE:YEAR",   SIMPLE, LEVEL_MAIN },+	{ "month",        "DATE:MONTH",  SIMPLE, LEVEL_MAIN },+	{ "day",          "DATE:DAY",    SIMPLE, LEVEL_MAIN }, 	{ "issn",         "ISSN",        SIMPLE, LEVEL_MAIN },+	{ "coden",        "CODEN",       SIMPLE, LEVEL_MAIN }, 	{ "abstract",     "ABSTRACT",    SIMPLE, LEVEL_MAIN },-	{ "volume",       "VOLUME",      TITLE,  LEVEL_MAIN },-	{ "number",       "NUMBER",      TITLE,  LEVEL_MAIN },+	{ "volume",       "VOLUME",      SIMPLE, LEVEL_MAIN },+	{ "number",       "NUMBER",      SIMPLE, LEVEL_MAIN }, 	{ "contents",     "CONTENTS",    SIMPLE, LEVEL_MAIN }, 	{ "doi",          "DOI",         SIMPLE, LEVEL_MAIN },-	{ "ftp",          "",        BT_URL, LEVEL_MAIN },-	{ "url",          "",        BT_URL, LEVEL_MAIN },-	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },-	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },-	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },-	{ "howpublished", "",         HOWPUBLISHED, LEVEL_MAIN },+	{ "ftp",          "",            URL,    LEVEL_MAIN },+	{ "url",          "",            URL,    LEVEL_MAIN },+	{ "pdf",          "FILEATTACH",  SIMPLE, LEVEL_MAIN },+	{ "sentelink",    "FILEATTACH",  BT_SENTE, LEVEL_MAIN },+	{ "file",         "FILEATTACH",  LINKEDFILE,   LEVEL_MAIN },+	{ "howpublished", "",            HOWPUBLISHED, LEVEL_MAIN }, 	{ "refnum",       "REFNUM",      SIMPLE, LEVEL_MAIN }, 	{ "language",     "LANGUAGE",    SIMPLE, LEVEL_MAIN },-	{ "note",         "NOTES",       BT_NOTE, LEVEL_MAIN },+	{ "note",         "NOTES",       NOTES,   LEVEL_MAIN }, 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN }, 	{ "organization", "ORGANIZER:CORP", BT_ORG, LEVEL_MAIN }, 	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },@@ -540,38 +548,38 @@  * For Patent  */ static lookups patent[] = {-	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN },-	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },-	{ "assignee",  "ASSIGNEE",  PERSON, LEVEL_MAIN },-	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },-	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_MAIN },-	{ "address",   "ADDRESS",   SIMPLE, LEVEL_MAIN },-	{ "editor",    "EDITOR",    PERSON, LEVEL_MAIN },-	{ "year",      "YEAR",      SIMPLE, LEVEL_MAIN }, /* date granted */-	{ "month",     "MONTH",     SIMPLE, LEVEL_MAIN },-	{ "day",       "DAY",       SIMPLE, LEVEL_MAIN },-	{ "yearfiled", "YEAR",      SIMPLE, LEVEL_MAIN }, /* date filed */-	{ "monthfiled","MONTH",     SIMPLE, LEVEL_MAIN },-	{ "dayfiled",  "DAY",       SIMPLE, LEVEL_MAIN },-	{ "abstract",  "ABSTRACT",  SIMPLE, LEVEL_MAIN },-	{ "contents",  "CONTENTS",  SIMPLE, LEVEL_MAIN },-	{ "language",  "LANGUAGE",  SIMPLE, LEVEL_MAIN },-	{ "location",  "LOCATION",  SIMPLE, LEVEL_MAIN },-	{ "nationality", "NATIONALITY", SIMPLE, LEVEL_MAIN },-	{ "note",      "NOTES",     BT_NOTE, LEVEL_MAIN },-	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },-	{ "key",       "BIBKEY",       SIMPLE, LEVEL_MAIN },-	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },-	{ "ftp",       "",      BT_URL, LEVEL_MAIN },-	{ "url",       "",      BT_URL, LEVEL_MAIN },-	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },-	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },-	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },-	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },-	{ "type",       "GENRE",     SIMPLE, LEVEL_MAIN },-	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },-	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },-	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },+	{ "author",       "AUTHOR",      PERSON,       LEVEL_MAIN },+	{ "translator",   "TRANSLATOR",  PERSON,       LEVEL_MAIN },+	{ "assignee",     "ASSIGNEE",    PERSON,       LEVEL_MAIN },+	{ "title",        "",            TITLE,        LEVEL_MAIN },+	{ "publisher",    "PUBLISHER",   SIMPLE,       LEVEL_MAIN },+	{ "address",      "ADDRESS",     SIMPLE,       LEVEL_MAIN },+	{ "editor",       "EDITOR",      PERSON,       LEVEL_MAIN },+	{ "year",         "DATE:YEAR",   SIMPLE,       LEVEL_MAIN }, /* date granted */+	{ "month",        "DATE:MONTH",  SIMPLE,       LEVEL_MAIN },+	{ "day",          "DATE:DAY",    SIMPLE,       LEVEL_MAIN },+	{ "yearfiled",    "DATE:YEAR",   SIMPLE,       LEVEL_MAIN }, /* date filed */+	{ "monthfiled",   "DATE:MONTH",  SIMPLE,       LEVEL_MAIN },+	{ "dayfiled",     "DATE:DAY",    SIMPLE,       LEVEL_MAIN },+	{ "abstract",     "ABSTRACT",    SIMPLE,       LEVEL_MAIN },+	{ "contents",     "CONTENTS",    SIMPLE,       LEVEL_MAIN },+	{ "language",     "LANGUAGE",    SIMPLE,       LEVEL_MAIN },+	{ "location",     "LOCATION",    SIMPLE,       LEVEL_MAIN },+	{ "nationality",  "NATIONALITY", SIMPLE,       LEVEL_MAIN },+	{ "note",         "NOTES",       NOTES,        LEVEL_MAIN },+	{ "annote",       "ANNOTE",      SIMPLE,       LEVEL_MAIN },+	{ "key",          "BIBKEY",      SIMPLE,       LEVEL_MAIN },+	{ "doi",          "DOI",         SIMPLE,       LEVEL_MAIN },+	{ "ftp",          "",            URL,          LEVEL_MAIN },+	{ "url",          "",            URL,          LEVEL_MAIN },+	{ "pdf",          "FILEATTACH",  SIMPLE,       LEVEL_MAIN },+	{ "sentelink",    "FILEATTACH",  BT_SENTE,     LEVEL_MAIN },+	{ "file",         "FILEATTACH",  LINKEDFILE,   LEVEL_MAIN },+	{ "howpublished", "",            HOWPUBLISHED, LEVEL_MAIN },+	{ "type",         "GENRE",       SIMPLE,       LEVEL_MAIN },+	{ "refnum",       "REFNUM",      SIMPLE,       LEVEL_MAIN },+	{ "crossref",     "CROSSREF",    SIMPLE,       LEVEL_MAIN },+	{ "keywords",     "KEYWORD",     KEYWORD,      LEVEL_MAIN }, 	{ "",         "RESOURCE|text",        ALWAYS, LEVEL_MAIN }, 	{ "",         "INTERNAL_TYPE|PATENT", ALWAYS, LEVEL_MAIN }, 	{ "",         "GENRE|patent",         ALWAYS, LEVEL_MAIN },@@ -581,70 +589,70 @@  * Electronic Source  */ static lookups electronic[] = {-	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN },-	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },-	{ "organization", "ORGANIZER:CORP", BT_ORG, LEVEL_MAIN },-	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },-	{ "booktitle", "TITLE",     TITLE,  LEVEL_MAIN },-	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_MAIN },-	{ "address",   "ADDRESS",   SIMPLE, LEVEL_MAIN },-	{ "editor",    "EDITOR",    PERSON, LEVEL_MAIN },-	{ "year",      "YEAR",      SIMPLE, LEVEL_MAIN },-	{ "month",     "MONTH",     SIMPLE, LEVEL_MAIN },-	{ "day",       "DAY",       SIMPLE, LEVEL_MAIN },-	{ "abstract",  "ABSTRACT",  SIMPLE, LEVEL_MAIN },-	{ "volume",    "VOLUME",    SIMPLE, LEVEL_MAIN },-	{ "contents",  "CONTENTS",  SIMPLE, LEVEL_MAIN },-	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },-	{ "ftp",       "",      BT_URL, LEVEL_MAIN },-	{ "url",       "",      BT_URL, LEVEL_MAIN },-	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },-	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },-	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },-	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },-	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },-	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },-	{ "location",  "LOCATION",  SIMPLE, LEVEL_MAIN },-	{ "note",      "NOTES",     BT_NOTE, LEVEL_MAIN },-	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },-	{ "key",       "BIBKEY",       SIMPLE, LEVEL_MAIN },-	{ "language",  "LANGUAGE",  SIMPLE, LEVEL_MAIN },-	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },+	{ "author",       "AUTHOR",         PERSON,       LEVEL_MAIN },+	{ "translator",   "TRANSLATOR",     PERSON,       LEVEL_MAIN },+	{ "organization", "ORGANIZER:CORP", BT_ORG,       LEVEL_MAIN },+	{ "title",        "",               TITLE,        LEVEL_MAIN },+	{ "booktitle",    "",               TITLE,        LEVEL_MAIN },+	{ "publisher",    "PUBLISHER",      SIMPLE,       LEVEL_MAIN },+	{ "address",      "ADDRESS",        SIMPLE,       LEVEL_MAIN },+	{ "editor",       "EDITOR",         PERSON,       LEVEL_MAIN },+	{ "year",         "DATE:YEAR",      SIMPLE,       LEVEL_MAIN },+	{ "month",        "DATE:MONTH",     SIMPLE,       LEVEL_MAIN },+	{ "day",          "DATE:DAY",       SIMPLE,       LEVEL_MAIN },+	{ "abstract",     "ABSTRACT",       SIMPLE,       LEVEL_MAIN },+	{ "volume",       "VOLUME",         SIMPLE,       LEVEL_MAIN },+	{ "contents",     "CONTENTS",       SIMPLE,       LEVEL_MAIN },+	{ "doi",          "DOI",            SIMPLE,       LEVEL_MAIN },+	{ "ftp",          "",               URL,          LEVEL_MAIN },+	{ "url",          "",               URL,          LEVEL_MAIN },+	{ "pdf",          "FILEATTACH",     SIMPLE,       LEVEL_MAIN },+	{ "sentelink",    "FILEATTACH",     BT_SENTE,     LEVEL_MAIN },+	{ "file",         "FILEATTACH",     LINKEDFILE,   LEVEL_MAIN },+	{ "howpublished", "",               HOWPUBLISHED, LEVEL_MAIN },+	{ "refnum",       "REFNUM",         SIMPLE,       LEVEL_MAIN },+	{ "crossref",     "CROSSREF",       SIMPLE,       LEVEL_MAIN },+	{ "location",     "LOCATION",       SIMPLE,       LEVEL_MAIN },+	{ "note",         "NOTES",          NOTES,        LEVEL_MAIN },+	{ "annote",       "ANNOTE",         SIMPLE,       LEVEL_MAIN },+	{ "key",          "BIBKEY",         SIMPLE,       LEVEL_MAIN },+	{ "language",     "LANGUAGE",       SIMPLE,       LEVEL_MAIN },+	{ "keywords",     "KEYWORD",        KEYWORD,      LEVEL_MAIN },         { "",         "RESOURCE|software, multimedia", ALWAYS, LEVEL_MAIN }, 	{ "",         "GENRE|electronic",              ALWAYS, LEVEL_MAIN }, };  static lookups misc[] = {-	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN },-	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },-	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },-	{ "booktitle", "TITLE",     TITLE,  LEVEL_MAIN },-	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_MAIN },-	{ "organization", "ORGANIZER:CORP", BT_ORG, LEVEL_MAIN },-	{ "pages",     "PAGES",     PAGES,  LEVEL_MAIN },-	{ "address",   "ADDRESS",   SIMPLE, LEVEL_MAIN },-	{ "editor",    "EDITOR",    PERSON, LEVEL_MAIN },-	{ "year",      "YEAR",      SIMPLE, LEVEL_MAIN },-	{ "month",     "MONTH",     SIMPLE, LEVEL_MAIN },-	{ "day",       "DAY",       SIMPLE, LEVEL_MAIN },-	{ "abstract",  "ABSTRACT",  SIMPLE, LEVEL_MAIN },-	{ "contents",  "CONTENTS",  SIMPLE, LEVEL_MAIN },-	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },-	{ "ftp",       "",      BT_URL, LEVEL_MAIN },-	{ "url",       "",      BT_URL, LEVEL_MAIN },-	{ "pdf",       "FILEATTACH",   SIMPLE, LEVEL_MAIN },-	{ "sentelink", "FILEATTACH",BT_SENTE, LEVEL_MAIN },-	{ "file",      "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },-	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },-	{ "refnum",    "REFNUM",       SIMPLE, LEVEL_MAIN },-	{ "crossref",  "CROSSREF",     SIMPLE, LEVEL_MAIN },-	{ "location",  "LOCATION",     SIMPLE, LEVEL_MAIN },-	{ "note",      "NOTES",        BT_NOTE, LEVEL_MAIN },-	{ "annote",    "ANNOTE",       SIMPLE, LEVEL_MAIN },-	{ "key",       "BIBKEY",       SIMPLE, LEVEL_MAIN },-	{ "language",  "LANGUAGE",     SIMPLE, LEVEL_MAIN },-	{ "keywords",  "KEYWORD",      KEYWORD, LEVEL_MAIN },-	{ "",          "INTERNAL_TYPE|MISC",       ALWAYS, LEVEL_MAIN },+	{ "author",       "AUTHOR",         PERSON,       LEVEL_MAIN },+	{ "translator",   "TRANSLATOR",     PERSON,       LEVEL_MAIN },+	{ "title",        "",               TITLE,        LEVEL_MAIN },+	{ "booktitle",    "",               TITLE,        LEVEL_MAIN },+	{ "publisher",    "PUBLISHER",      SIMPLE,       LEVEL_MAIN },+	{ "organization", "ORGANIZER:CORP", BT_ORG,       LEVEL_MAIN },+	{ "pages",        "PAGES",          PAGES,        LEVEL_MAIN },+	{ "address",      "ADDRESS",        SIMPLE,       LEVEL_MAIN },+	{ "editor",       "EDITOR",         PERSON,       LEVEL_MAIN },+	{ "year",         "DATE:YEAR",      SIMPLE,       LEVEL_MAIN },+	{ "month",        "DATE:MONTH",     SIMPLE,       LEVEL_MAIN },+	{ "day",          "DATE:DAY",       SIMPLE,       LEVEL_MAIN },+	{ "abstract",     "ABSTRACT",       SIMPLE,       LEVEL_MAIN },+	{ "contents",     "CONTENTS",       SIMPLE,       LEVEL_MAIN },+	{ "doi",          "DOI",            SIMPLE,       LEVEL_MAIN },+	{ "ftp",          "",               URL,          LEVEL_MAIN },+	{ "url",          "",               URL,          LEVEL_MAIN },+	{ "pdf",          "FILEATTACH",     SIMPLE,       LEVEL_MAIN },+	{ "sentelink",    "FILEATTACH",     BT_SENTE,     LEVEL_MAIN },+	{ "file",         "FILEATTACH",     LINKEDFILE,   LEVEL_MAIN },+	{ "howpublished", "",               HOWPUBLISHED, LEVEL_MAIN },+	{ "refnum",       "REFNUM",         SIMPLE,       LEVEL_MAIN },+	{ "crossref",     "CROSSREF",       SIMPLE,       LEVEL_MAIN },+	{ "location",     "LOCATION",       SIMPLE,       LEVEL_MAIN },+	{ "note",         "NOTES",          NOTES,        LEVEL_MAIN },+	{ "annote",       "ANNOTE",         SIMPLE,       LEVEL_MAIN },+	{ "key",          "BIBKEY",         SIMPLE,       LEVEL_MAIN },+	{ "language",     "LANGUAGE",       SIMPLE,       LEVEL_MAIN },+	{ "keywords",     "KEYWORD",        KEYWORD,      LEVEL_MAIN },+	{ "",             "INTERNAL_TYPE|MISC",       ALWAYS, LEVEL_MAIN }, };  #define ORIG(a) ( &(a[0]) )
bibutils/bibutils.c view
@@ -1,7 +1,7 @@ /*  * bibutils.c  *- * Copyright (c) Chris Putnam 2005-2013+ * Copyright (c) Chris Putnam 2005-2017  *  * Source code released under the GPL version 2  *@@ -9,26 +9,7 @@ #include <stdio.h> #include <stdlib.h> #include "bibutils.h"--/* bibl format includes */-#include "adsout.h"-#include "biblatexin.h"-#include "bibtexin.h"-#include "bibtexout.h"-#include "copacin.h"-#include "ebiin.h"-#include "endin.h"-#include "endxmlin.h"-#include "endout.h"-#include "isiin.h"-#include "isiout.h"-#include "medin.h"-#include "modsin.h"-#include "modsout.h"-#include "risin.h"-#include "risout.h"-#include "wordin.h"-#include "wordout.h"+#include "bibformats.h"  void bibl_initparams( param *p, int readmode, int writemode, char *progname )
bibutils/bibutils.h view
@@ -1,7 +1,7 @@ /*  * bibutils.h  *- * Copyright (c) Chris Putnam 2005-2014+ * Copyright (c) Chris Putnam 2005-2017  *  * Source code released under GPL version 2  *@@ -15,9 +15,9 @@  #include <stdio.h> #include "bibl.h"-#include "list.h"+#include "slist.h" #include "charsets.h"-#include "newstr_conv.h"+#include "str_conv.h"  #define BIBL_OK           (0) #define BIBL_ERR_BADINPUT (-1)@@ -36,7 +36,8 @@ #define BIBL_BIBLATEXIN   (BIBL_FIRSTIN+8) #define BIBL_EBIIN        (BIBL_FIRSTIN+9) #define BIBL_WORDIN       (BIBL_FIRSTIN+10)-#define BIBL_LASTIN       (BIBL_FIRSTIN+10)+#define BIBL_NBIBIN       (BIBL_FIRSTIN+11)+#define BIBL_LASTIN       (BIBL_FIRSTIN+11)  #define BIBL_FIRSTOUT     (200) #define BIBL_MODSOUT      (BIBL_FIRSTOUT)@@ -48,7 +49,16 @@ #define BIBL_ADSABSOUT    (BIBL_FIRSTOUT+6) #define BIBL_LASTOUT      (BIBL_FIRSTOUT+6) -#define BIBL_FORMAT_VERBOSE (1)+#define BIBL_FORMAT_VERBOSE             (1)+#define BIBL_FORMAT_BIBOUT_FINALCOMMA   (2)+#define BIBL_FORMAT_BIBOUT_SINGLEDASH   (4)+#define BIBL_FORMAT_BIBOUT_WHITESPACE   (8)+#define BIBL_FORMAT_BIBOUT_BRACKETS    (16)+#define BIBL_FORMAT_BIBOUT_UPPERCASE   (32)+#define BIBL_FORMAT_BIBOUT_STRICTKEY   (64)+#define BIBL_FORMAT_BIBOUT_SHORTTITLE (128)+#define BIBL_FORMAT_BIBOUT_DROPKEY    (256)+#define BIBL_FORMAT_MODSOUT_DROPKEY   (512)  #define BIBL_RAW_WITHCHARCONVERT (4) #define BIBL_RAW_WITHMAKEREFID   (8)@@ -64,9 +74,9 @@ #define BIBL_SRC_FILE    (1)  /* value from file, priority over default */ #define BIBL_SRC_USER    (2)  /* value from user, priority over file, default */ -#define BIBL_XMLOUT_FALSE    NEWSTR_CONV_XMLOUT_FALSE-#define BIBL_XMLOUT_TRUE     NEWSTR_CONV_XMLOUT_TRUE-#define BIBL_XMLOUT_ENTITIES NEWSTR_CONV_XMLOUT_ENTITIES+#define BIBL_XMLOUT_FALSE    STR_CONV_XMLOUT_FALSE+#define BIBL_XMLOUT_TRUE     STR_CONV_XMLOUT_TRUE+#define BIBL_XMLOUT_ENTITIES STR_CONV_XMLOUT_ENTITIES  typedef unsigned char uchar; @@ -95,20 +105,20 @@ 	uchar verbose; 	uchar singlerefperfile; -	list asis;  /* Names that shouldn't be mangled */-	list corps; /* Names that shouldn't be mangled-MODS corporation type */+	slist asis;  /* Names that shouldn't be mangled */+	slist corps; /* Names that shouldn't be mangled-MODS corporation type */  	char *progname;  -        int  (*readf)(FILE*,char*,int,int*,newstr*,newstr*,int*);-        int  (*processf)(fields*,char*,char*,long);+        int  (*readf)(FILE*,char*,int,int*,str*,str*,int*);+        int  (*processf)(fields*,char*,char*,long,struct param*);         int  (*cleanf)(bibl*,struct param*);-        int  (*typef) (fields*,char*,int,struct param*,variants*,int);-        int  (*convertf)(fields*,fields*,int,struct param*,variants*,int);+        int  (*typef) (fields*,char*,int,struct param*);+        int  (*convertf)(fields*,fields*,int,struct param*);         void (*headerf)(FILE*,struct param*);         void (*footerf)(FILE*);-        void (*writef)(fields*,FILE*,struct param*,unsigned long);+        int  (*writef)(fields*,FILE*,struct param*,unsigned long);         variants *all;         int  nall; 
bibutils/bltypes.c view
@@ -1,8 +1,8 @@ /*  * bltypes.c  *- * Copyright (c) Chris Putnam 2008-2013- * Copyright (c) Johannes Wilm 2010-2013+ * Copyright (c) Chris Putnam 2008-2017+ * Copyright (c) Johannes Wilm 2010-2017  *  * Program and source code released under the GPL version 2  *@@ -47,7 +47,7 @@ 	{ "issuesubtitle",   "SUBTITLE",               TITLE,           LEVEL_SERIES }, /*WRONG*/ 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   }, 	{ "origlanguage",    "LANGUAGE",               SIMPLE,          LEVEL_ORIG   },-	{ "origyear",        "YEAR",                   SIMPLE,          LEVEL_ORIG   },+	{ "origyear",        "DATE:YEAR",              SIMPLE,          LEVEL_ORIG   }, 	{ "origdate",        "DATE",                   SIMPLE,          LEVEL_ORIG   }, 	{ "origtitle",       "TITLE",                  SIMPLE,          LEVEL_ORIG   }, 	{ "origlocation",    "ADDRESS",                SIMPLE,          LEVEL_ORIG   },@@ -58,22 +58,23 @@ 	{ "eid",             "EID",                    SIMPLE,          LEVEL_MAIN   }, 	{ "issue",           "ISSUE",                  SIMPLE,          LEVEL_MAIN   }, 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/-	{ "day",             "PARTDAY",                SIMPLE,          LEVEL_MAIN   },-	{ "month",           "PARTMONTH",              SIMPLE,          LEVEL_MAIN   },-	{ "year",            "PARTYEAR",               SIMPLE,          LEVEL_MAIN   },+	{ "day",             "PARTDATE:DAY",           SIMPLE,          LEVEL_MAIN   },+	{ "month",           "PARTDATE:MONTH",         SIMPLE,          LEVEL_MAIN   },+	{ "year",            "PARTDATE:YEAR",          SIMPLE,          LEVEL_MAIN   }, 	{ "pages",           "PAGES",                  PAGES,           LEVEL_MAIN   }, 	{ "version",         "EDITION",                SIMPLE,          LEVEL_MAIN   },-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   }, 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "issn",            "ISSN",                   SIMPLE,          LEVEL_HOST   },+	{ "coden",           "CODEN",                  SIMPLE,          LEVEL_HOST   }, 	{ "abstract",        "ABSTRACT",               SIMPLE,          LEVEL_MAIN   }, 	{ "addendum",        "ADDENDUM",               SIMPLE,          LEVEL_MAIN   }, 	{ "doi",             "DOI",                    SIMPLE,          LEVEL_MAIN   }, 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   }, 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   }, 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },+	{ "url",             "",                       URL,             LEVEL_MAIN   }, 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   }, 	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   }, /* WRONG */ 	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   }, /* WRONG */@@ -120,11 +121,11 @@ 	{ "mainsubtitle",    "SUBTITLE",               TITLE,           LEVEL_HOST   }, 	{ "maintitleaddon",  "TITLEADDON",             TITLE,           LEVEL_HOST   }, 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   }, 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/ 	{ "origlanguage",    "LANGUAGE",               SIMPLE,          LEVEL_ORIG   },-	{ "origyear",        "YEAR",                   SIMPLE,          LEVEL_ORIG   },+	{ "origyear",        "DATE:YEAR",              SIMPLE,          LEVEL_ORIG   }, 	{ "origdate",        "DATE",                   SIMPLE,          LEVEL_ORIG   }, 	{ "origtitle",       "TITLE",                  SIMPLE,          LEVEL_ORIG   }, 	{ "origlocation",    "ADDRESS",                SIMPLE,          LEVEL_ORIG   },@@ -135,7 +136,7 @@ 	{ "volumes",         "NUMVOLUMES",             SIMPLE,          LEVEL_HOST   }, 	{ "series",          "TITLE",                  SIMPLE,          LEVEL_HOST   }, /* WRONG */ 	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   }, 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "publisher",       "PUBLISHER",              SIMPLE,          LEVEL_MAIN   },@@ -143,13 +144,13 @@ 	{ "isbn",            "ISBN",                   SIMPLE,          LEVEL_MAIN   }, 	{ "chapter",         "CHAPTER",                SIMPLE,          LEVEL_MAIN   }, 	{ "pages",           "PAGES",                  PAGES,           LEVEL_MAIN   }, /* WRONG */-	{ "pagetotal",       "TOTALPAGES",             SIMPLE,          LEVEL_MAIN   },+	{ "pagetotal",       "PAGES:TOTAL",            SIMPLE,          LEVEL_MAIN   }, 	{ "addendum",        "ADDENDUM",               SIMPLE,          LEVEL_MAIN   }, 	{ "doi",             "DOI",                    SIMPLE,          LEVEL_MAIN   }, 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   }, 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   }, 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },+	{ "url",             "",                       URL,             LEVEL_MAIN   }, 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   }, 	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   }, 	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   },@@ -184,25 +185,25 @@ 	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   }, 	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   }, 	{ "howpublished",    "",                       HOWPUBLISHED,    LEVEL_MAIN   },-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   }, 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/ 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   }, 	{ "type",            "GENRE",                  BT_GENRE,        LEVEL_MAIN   },-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   }, 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "publisher",       "PUBLISHER",              SIMPLE,          LEVEL_MAIN   }, 	{ "location",        "ADDRESS",                SIMPLE,          LEVEL_MAIN   }, 	{ "chapter",         "CHAPTER",                SIMPLE,          LEVEL_MAIN   }, 	{ "pages",           "PAGES",                  PAGES,           LEVEL_MAIN   },-	{ "pagetotal",       "TOTALPAGES",             SIMPLE,          LEVEL_MAIN   },+	{ "pagetotal",       "PAGES:TOTAL",            SIMPLE,          LEVEL_MAIN   }, 	{ "addendum",        "ADDENDUM",               SIMPLE,          LEVEL_MAIN   }, 	{ "doi",             "DOI",                    SIMPLE,          LEVEL_MAIN   }, 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   }, 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   }, 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },+	{ "url",             "",                       URL,             LEVEL_MAIN   }, 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   }, 	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   }, 	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   },@@ -233,8 +234,8 @@ 	{ "annotator",       "ANNOTATOR",              PERSON,          LEVEL_MAIN   }, 	{ "commentator",     "COMMENTATOR",            PERSON,          LEVEL_MAIN   }, 	{ "translator",      "TRANSLATOR",             PERSON,          LEVEL_MAIN   },-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   }, 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/ 	{ "introduction",    "INTROAUTHOR",            PERSON,          LEVEL_MAIN   }, 	{ "foreword",        "INTROAUTHOR",            PERSON,          LEVEL_MAIN   },@@ -248,7 +249,7 @@ 	{ "maintitleaddon",  "TITLEADDON",             TITLE,           LEVEL_HOST   }, 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   }, 	{ "origlanguage",    "LANGUAGE",               SIMPLE,          LEVEL_ORIG   },-	{ "origyear",        "YEAR",                   SIMPLE,          LEVEL_ORIG   },+	{ "origyear",        "DATE:YEAR",              SIMPLE,          LEVEL_ORIG   }, 	{ "origdate",        "DATE",                   SIMPLE,          LEVEL_ORIG   }, 	{ "origtitle",       "TITLE",                  SIMPLE,          LEVEL_ORIG   }, 	{ "origlocation",    "ADDRESS",                SIMPLE,          LEVEL_ORIG   },@@ -259,7 +260,7 @@ 	{ "volumes",         "NUMVOLUMES",             SIMPLE,          LEVEL_HOST   }, 	{ "series",          "TITLE",                  SIMPLE,          LEVEL_HOST   }, 	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   }, 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "publisher",       "PUBLISHER",              SIMPLE,          LEVEL_MAIN   },@@ -267,13 +268,13 @@ 	{ "isbn",            "ISBN",                   SIMPLE,          LEVEL_MAIN   }, 	{ "chapter",         "CHAPTER",                SIMPLE,          LEVEL_MAIN   }, 	{ "pages",           "PAGES",                  PAGES,           LEVEL_MAIN   },-	{ "pagetotal",       "TOTALPAGES",             SIMPLE,          LEVEL_MAIN   },+	{ "pagetotal",       "PAGES:TOTAL",            SIMPLE,          LEVEL_MAIN   }, 	{ "addendum",        "ADDENDUM",               SIMPLE,          LEVEL_MAIN   }, 	{ "doi",             "DOI",                    SIMPLE,          LEVEL_MAIN   }, 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   }, 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   }, 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },+	{ "url",             "",                       URL,             LEVEL_MAIN   }, 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   }, 	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   }, 	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   },@@ -307,8 +308,8 @@ 	{ "annotator",       "ANNOTATOR",              PERSON,          LEVEL_HOST   }, 	{ "commentator",     "COMMENTATOR",            PERSON,          LEVEL_HOST   }, 	{ "translator",      "TRANSLATOR",             PERSON,          LEVEL_HOST   },-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   }, 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/ 	{ "introduction",    "INTROAUTHOR",            PERSON,          LEVEL_HOST   }, 	{ "foreword",        "INTROAUTHOR",            PERSON,          LEVEL_HOST   },@@ -326,7 +327,7 @@ 	{ "maintitleaddon",  "TITLEADDON",             TITLE,           LEVEL_SERIES }, 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   }, 	{ "origlanguage",    "LANGUAGE",               SIMPLE,          LEVEL_ORIG   },-	{ "origyear",        "YEAR",                   SIMPLE,          LEVEL_ORIG   },+	{ "origyear",        "DATE:YEAR",              SIMPLE,          LEVEL_ORIG   }, 	{ "origdate",        "DATE",                   SIMPLE,          LEVEL_ORIG   }, 	{ "origtitle",       "TITLE",                  SIMPLE,          LEVEL_ORIG   }, 	{ "origlocation",    "ADDRESS",                SIMPLE,          LEVEL_ORIG   },@@ -338,7 +339,7 @@ 	{ "volumes",         "NUMVOLUMES",             SIMPLE,          LEVEL_HOST   }, 	{ "series",          "TITLE",                  SIMPLE,          LEVEL_SERIES+1 }, /* WRONG */ 	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   }, 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "publisher",       "PUBLISHER",              SIMPLE,          LEVEL_MAIN   },@@ -350,7 +351,7 @@ 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   }, 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   }, 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },+	{ "url",             "",                       URL,             LEVEL_MAIN   }, 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   }, 	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   }, 	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   },@@ -369,8 +370,8 @@  static lookups incollection[] = { 	{ "author",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   }, 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/ 	{ "title",           "TITLE",                  TITLE,           LEVEL_MAIN   }, 	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   },@@ -379,7 +380,7 @@ 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   }, 	{ "edition",         "EDITION",                SIMPLE,          LEVEL_MAIN   }, 	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   }, 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "introduction",    "INTROAUTHOR",            PERSON,          LEVEL_HOST   },@@ -416,7 +417,7 @@ 	{ "series",          "TITLE",                  SIMPLE,          LEVEL_SERIES+1 }, /* WRONG */  	{ "origlanguage",    "LANGUAGE",               SIMPLE,          LEVEL_ORIG   },-	{ "origyear",        "YEAR",                   SIMPLE,          LEVEL_ORIG   },+	{ "origyear",        "DATE:YEAR",              SIMPLE,          LEVEL_ORIG   }, 	{ "origdate",        "DATE",                   SIMPLE,          LEVEL_ORIG   }, 	{ "origtitle",       "TITLE",                  SIMPLE,          LEVEL_ORIG   }, 	{ "origlocation",    "ADDRESS",                SIMPLE,          LEVEL_ORIG   },@@ -432,7 +433,7 @@ 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   }, 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   }, 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },+	{ "url",             "",                       URL,             LEVEL_MAIN   }, 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   }, 	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   }, 	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   },@@ -467,8 +468,8 @@ 	{ "commentator",     "COMMENTATOR",            PERSON,          LEVEL_HOST   }, 	{ "translator",      "TRANSLATOR",             PERSON,          LEVEL_HOST   }, 	{ "eventtitle",      "EVENT:CONF",             SIMPLE,          LEVEL_MAIN   },-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   }, 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/ 	{ "introduction",    "INTROAUTHOR",            PERSON,          LEVEL_HOST   }, 	{ "foreword",        "INTROAUTHOR",            PERSON,          LEVEL_HOST   },@@ -493,7 +494,7 @@ 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   }, 	{ "origlanguage",    "LANGUAGE",               SIMPLE,          LEVEL_ORIG   }, 	{ "origdate",        "DATE",                   SIMPLE,          LEVEL_ORIG   },-	{ "origyear",        "YEAR",                   SIMPLE,          LEVEL_ORIG   },+	{ "origyear",        "DATE:YEAR",              SIMPLE,          LEVEL_ORIG   }, 	{ "origtitle",       "TITLE",                  SIMPLE,          LEVEL_ORIG   }, 	{ "origlocation",    "ADDRESS",                SIMPLE,          LEVEL_ORIG   }, 	{ "origpublisher",   "PUBLISHER",              SIMPLE,          LEVEL_ORIG   },@@ -502,7 +503,7 @@ 	{ "edition",         "EDITION",                SIMPLE,          LEVEL_MAIN   }, 	{ "volumes",         "NUMVOLUMES",             SIMPLE,          LEVEL_HOST   }, 	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   }, 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "publisher",       "PUBLISHER",              SIMPLE,          LEVEL_HOST   },@@ -515,7 +516,7 @@ 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   }, 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   }, 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },+	{ "url",             "",                       URL,             LEVEL_MAIN   }, 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   }, 	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   }, 	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   },@@ -547,8 +548,8 @@ 	{ "annotator",       "ANNOTATOR",              PERSON,          LEVEL_MAIN   }, 	{ "commentator",     "COMMENTATOR",            PERSON,          LEVEL_MAIN   }, 	{ "translator",      "TRANSLATOR",             PERSON,          LEVEL_MAIN   },-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   }, 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   }, /*WRONG*/ 	{ "introduction",    "INTROAUTHOR",            PERSON,          LEVEL_MAIN   }, 	{ "foreword",        "INTROAUTHOR",            PERSON,          LEVEL_MAIN   },@@ -563,7 +564,7 @@ 	{ "type",            "GENRE",                  BT_GENRE,        LEVEL_MAIN   }, 	{ "series",          "TITLE",                  SIMPLE,          LEVEL_HOST   }, 	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   }, 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "organization",    "ORGANIZER:CORP",         SIMPLE,          LEVEL_MAIN   },@@ -572,13 +573,13 @@ 	{ "isbn",            "ISBN",                   SIMPLE,          LEVEL_MAIN   }, 	{ "chapter",         "CHAPTER",                SIMPLE,          LEVEL_MAIN   }, 	{ "pages",           "PAGES",                  PAGES,           LEVEL_MAIN   },-	{ "pagetotal",       "TOTALPAGES",             SIMPLE,          LEVEL_MAIN   },+	{ "pagetotal",       "PAGES:TOTAL",            SIMPLE,          LEVEL_MAIN   }, 	{ "addendum",        "ADDENDUM",               SIMPLE,          LEVEL_MAIN   }, 	{ "doi",             "DOI",                    SIMPLE,          LEVEL_MAIN   }, 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   }, 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   }, 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },+	{ "url",             "",                       URL,             LEVEL_MAIN   }, 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   }, 	{ "urlday",          "?????????",              SIMPLE,          LEVEL_MAIN   }, 	{ "urlmonth",        "?????????",              SIMPLE,          LEVEL_MAIN   },@@ -609,15 +610,15 @@ 	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   }, 	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   }, 	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   },-	{ "day",             "DAY",                    SIMPLE,          LEVEL_MAIN   },-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },+	{ "day",             "DATE:DAY",               SIMPLE,          LEVEL_MAIN   },+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   }, 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/ 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   }, 	{ "howpublished",    "",                       HOWPUBLISHED,    LEVEL_MAIN   }, 	{ "version",         "EDITION",                SIMPLE,          LEVEL_MAIN   }, 	{ "type",            "GENRE",                  BT_GENRE,        LEVEL_MAIN   },-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   }, 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "organization",    "ORGANIZER:CORP",         SIMPLE,          LEVEL_MAIN   },@@ -629,7 +630,7 @@ 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   }, 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   }, 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },+	{ "url",             "",                       URL,             LEVEL_MAIN   }, 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   }, 	{ "urlday",          "?????????",              SIMPLE,          LEVEL_MAIN   }, 	{ "urlmonth",        "?????????",              SIMPLE,          LEVEL_MAIN   },@@ -658,13 +659,13 @@ 	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   }, 	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   }, 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },-	{ "day",             "DAY",                    SIMPLE,          LEVEL_MAIN   },-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },+	{ "day",             "DATE:DAY",               SIMPLE,          LEVEL_MAIN   },+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   }, 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   }, 	{ "version",         "EDITION",                SIMPLE,          LEVEL_MAIN   }, 	{ "type",            "GENRE",                  BT_GENRE,        LEVEL_MAIN   },-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   }, 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "organization",    "ORGANIZER:CORP",         SIMPLE,          LEVEL_MAIN   },@@ -675,7 +676,7 @@ 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   }, 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   }, 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },+	{ "url",             "",                       URL,             LEVEL_MAIN   }, 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   }, 	{ "urlday",          "?????????",              SIMPLE,          LEVEL_MAIN   }, 	{ "urlmonth",        "?????????",              SIMPLE,          LEVEL_MAIN   },@@ -695,19 +696,19 @@ 	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   }, 	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   }, 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },-	{ "day",             "DAY",                    SIMPLE,          LEVEL_MAIN   },-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },+	{ "day",             "DATE:DAY",               SIMPLE,          LEVEL_MAIN   },+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   }, 	{ "version",         "EDITION",                SIMPLE,          LEVEL_MAIN   }, 	{ "type",            "GENRE",                  BT_GENRE,        LEVEL_MAIN   },-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   }, 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "organization",    "ORGANIZER:CORP",         SIMPLE,          LEVEL_MAIN   }, 	{ "location",        "ADDRESS",                SIMPLE,          LEVEL_MAIN   }, 	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   }, 	{ "addendum",        "ADDENDUM",               SIMPLE,          LEVEL_MAIN   },-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },+	{ "url",             "",                       URL,             LEVEL_MAIN   }, 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   }, 	{ "urlday",          "?????????",              SIMPLE,          LEVEL_MAIN   }, 	{ "urlmonth",        "?????????",              SIMPLE,          LEVEL_MAIN   },@@ -753,20 +754,21 @@ 	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   }, 	{ "issue",           "ISSUE",                  SIMPLE,          LEVEL_MAIN   }, 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/-	{ "day",             "PARTDAY",                SIMPLE,          LEVEL_MAIN   },-	{ "month",           "PARTMONTH",              SIMPLE,          LEVEL_MAIN   },-	{ "year",            "PARTYEAR",               SIMPLE,          LEVEL_MAIN   },+	{ "day",             "PARTDATE:DAY",           SIMPLE,          LEVEL_MAIN   },+	{ "month",           "PARTDATE:MONTH",         SIMPLE,          LEVEL_MAIN   },+	{ "year",            "PARTDATE:YEAR",          SIMPLE,          LEVEL_MAIN   }, 	{ "pages",           "PAGES",                  PAGES,           LEVEL_MAIN   },-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   }, 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "issn",            "ISSN",                   SIMPLE,          LEVEL_HOST   },+	{ "coden",           "CODEN",                  SIMPLE,          LEVEL_HOST   }, 	{ "addendum",        "ADDENDUM",               SIMPLE,          LEVEL_MAIN   }, 	{ "doi",             "DOI",                    SIMPLE,          LEVEL_MAIN   }, 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   }, 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   }, 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },+	{ "url",             "",                       URL,             LEVEL_MAIN   }, 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   }, 	{ "urlday",          "?????",                  SIMPLE,          LEVEL_MAIN   }, /* WRONG */ 	{ "urlmonth",        "?????",                  SIMPLE,          LEVEL_MAIN   }, /* WRONG */@@ -798,8 +800,8 @@ 	{ "commentator",     "COMMENTATOR",            PERSON,          LEVEL_MAIN   }, 	{ "translator",      "TRANSLATOR",             PERSON,          LEVEL_MAIN   }, 	{ "eventtitle",      "EVENT:CONF",             SIMPLE,          LEVEL_MAIN   },-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   }, 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/ 	{ "introduction",    "INTROAUTHOR",            PERSON,          LEVEL_MAIN   }, 	{ "foreword",        "INTROAUTHOR",            PERSON,          LEVEL_MAIN   },@@ -814,7 +816,7 @@ 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   }, 	{ "origlanguage",    "LANGUAGE",               SIMPLE,          LEVEL_ORIG   }, 	{ "origdate",        "DATE",                   SIMPLE,          LEVEL_ORIG   },-	{ "origyear",        "YEAR",                   SIMPLE,          LEVEL_ORIG   },+	{ "origyear",        "DATE:YEAR",              SIMPLE,          LEVEL_ORIG   }, 	{ "origtitle",       "TITLE",                  SIMPLE,          LEVEL_ORIG   }, 	{ "origlocation",    "ADDRESS",                SIMPLE,          LEVEL_ORIG   }, 	{ "origpublisher",   "PUBLISHER",              SIMPLE,          LEVEL_ORIG   },@@ -824,7 +826,7 @@ 	{ "volumes",         "NUMVOLUMES",             SIMPLE,          LEVEL_HOST   }, 	{ "series",          "TITLE",                  SIMPLE,          LEVEL_SERIES }, 	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   }, 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "organization",    "ORGANIZER:CORP",         SIMPLE,          LEVEL_MAIN   },@@ -833,13 +835,13 @@ 	{ "isbn",            "ISBN",                   SIMPLE,          LEVEL_MAIN   }, 	{ "chapter",         "CHAPTER",                SIMPLE,          LEVEL_MAIN   }, 	{ "pages",           "PAGES",                  SIMPLE,          LEVEL_MAIN   },-	{ "pagetotal",       "TOTALPAGES",             SIMPLE,          LEVEL_MAIN   },+	{ "pagetotal",       "PAGES:TOTAL",            SIMPLE,          LEVEL_MAIN   }, 	{ "addendum",        "ADDENDUM",               SIMPLE,          LEVEL_MAIN   }, 	{ "doi",             "DOI",                    SIMPLE,          LEVEL_MAIN   }, 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   }, 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   }, 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },+	{ "url",             "",                       URL,             LEVEL_MAIN   }, 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   }, 	{ "urlday",          "?????????",              SIMPLE,          LEVEL_MAIN   }, 	{ "urlmonth",        "?????????",              SIMPLE,          LEVEL_MAIN   },@@ -862,12 +864,12 @@ 	{ "series",          "TITLE",                  TITLE,           LEVEL_HOST   }, 	{ "type",            "GENRE",                  BT_GENRE,        LEVEL_MAIN   }, 	{ "institution",     "SPONSOR:ASIS",           SIMPLE,          LEVEL_MAIN   },-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   }, 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/ 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   }, 	{ "number",          "REPORTNUMBER",           SIMPLE,          LEVEL_MAIN   },-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   }, 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "version",         "EDITION",                SIMPLE,          LEVEL_MAIN   },@@ -875,13 +877,13 @@ 	{ "isrn",            "ISRN",                   SIMPLE,          LEVEL_MAIN   }, 	{ "chapter",         "CHAPTER",                SIMPLE,          LEVEL_MAIN   }, 	{ "pages",           "PAGES",                  SIMPLE,          LEVEL_MAIN   },-	{ "pagetotal",       "TOTALPAGES",             SIMPLE,          LEVEL_MAIN   },+	{ "pagetotal",       "PAGES:TOTAL",            SIMPLE,          LEVEL_MAIN   }, 	{ "addendum",        "ADDENDUM",               SIMPLE,          LEVEL_MAIN   }, 	{ "doi",             "DOI",                    SIMPLE,          LEVEL_MAIN   }, 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   }, 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   }, 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },+	{ "url",             "",                       URL,             LEVEL_MAIN   }, 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   }, 	{ "urlday",          "?????????",              SIMPLE,          LEVEL_MAIN   }, 	{ "urlmonth",        "?????????",              SIMPLE,          LEVEL_MAIN   },@@ -902,16 +904,16 @@ 	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   }, 	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   }, 	{ "howpublished",    "",                       HOWPUBLISHED,    LEVEL_MAIN   },-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },-	{ "day",             "DAY",                    SIMPLE,          LEVEL_MAIN   },+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },+	{ "day",             "DATE:DAY",               SIMPLE,          LEVEL_MAIN   }, 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },+	{ "url",             "",                       URL,             LEVEL_MAIN   }, 	{ "urlday",          "?????????",              SIMPLE,          LEVEL_MAIN   }, 	{ "urlmonth",        "?????????",              SIMPLE,          LEVEL_MAIN   }, 	{ "urlyear",         "?????????",              SIMPLE,          LEVEL_MAIN   }, 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   }, 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "addendum",        "ADDENDUM",               SIMPLE,          LEVEL_MAIN   },@@ -930,23 +932,23 @@ 	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   }, 	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   }, 	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   },-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },-	{ "day",             "DAY",                    SIMPLE,          LEVEL_MAIN   },+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },+	{ "day",             "DATE:DAY",               SIMPLE,          LEVEL_MAIN   }, 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/ 	{ "type",            "",                       BLT_THESIS_TYPE, LEVEL_MAIN   }, 	{ "institution",     "DEGREEGRANTOR:ASIS",     SIMPLE,          LEVEL_MAIN   }, 	{ "school",          "DEGREEGRANTOR:ASIS",     BLT_SCHOOL,      LEVEL_MAIN   }, 	{ "doi",             "DOI",                    SIMPLE,          LEVEL_MAIN   }, 	{ "howpublished",    "",                       HOWPUBLISHED,    LEVEL_MAIN   },-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },+	{ "url",             "",                       URL,             LEVEL_MAIN   }, 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   }, 	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   }, 	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   }, 	{ "urlyear",         "?urlyear?",              SIMPLE,          LEVEL_MAIN   }, 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   }, 	{ "location",        "ADDRESS",                SIMPLE,          LEVEL_MAIN   },-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   }, 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },@@ -964,23 +966,23 @@ 	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   }, 	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   }, 	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   },-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },-	{ "day",             "DAY",                    SIMPLE,          LEVEL_MAIN   },+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },+	{ "day",             "DATE:DAY",               SIMPLE,          LEVEL_MAIN   }, 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/ 	{ "type",            "",                       BLT_THESIS_TYPE, LEVEL_MAIN   }, 	{ "institution",     "DEGREEGRANTOR:ASIS",     SIMPLE,          LEVEL_MAIN   }, 	{ "school",          "DEGREEGRANTOR:ASIS",     BLT_SCHOOL,      LEVEL_MAIN   }, 	{ "doi",             "DOI",                    SIMPLE,          LEVEL_MAIN   }, 	{ "howpublished",    "",                       HOWPUBLISHED,    LEVEL_MAIN   },-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },+	{ "url",             "",                       URL,             LEVEL_MAIN   }, 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   }, 	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   }, 	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   }, 	{ "urlyear",         "?urlyear?",              SIMPLE,          LEVEL_MAIN   }, 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   }, 	{ "location",        "ADDRESS",                SIMPLE,          LEVEL_MAIN   },-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   }, 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },@@ -999,23 +1001,23 @@ 	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   }, 	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   }, 	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   },-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },-	{ "day",             "DAY",                    SIMPLE,          LEVEL_MAIN   },+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },+	{ "day",             "DATE:DAY",               SIMPLE,          LEVEL_MAIN   }, 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/ 	{ "type",            "",                       BLT_THESIS_TYPE, LEVEL_MAIN   }, 	{ "institution",     "DEGREEGRANTOR:ASIS",     SIMPLE,          LEVEL_MAIN   }, 	{ "school",          "DEGREEGRANTOR:ASIS",     BLT_SCHOOL,      LEVEL_MAIN   }, 	{ "doi",             "DOI",                    SIMPLE,          LEVEL_MAIN   }, 	{ "howpublished",    "",                       HOWPUBLISHED,    LEVEL_MAIN   },-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },+	{ "url",             "",                       URL,             LEVEL_MAIN   }, 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   }, 	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   }, 	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   }, 	{ "urlyear",         "?urlyear?",              SIMPLE,          LEVEL_MAIN   }, 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   }, 	{ "location",        "ADDRESS",                SIMPLE,          LEVEL_MAIN   },-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   }, 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   }, 	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
bibutils/charsets.c view
@@ -1,7 +1,7 @@ /*  * charsets.c  *- * Copyright (c) Chris Putnam 2003-2013+ * Copyright (c) Chris Putnam 2003-2017  *  * Source code released under the GPL version 2  *
bibutils/charsets.h view
@@ -1,7 +1,7 @@ /*  * charsets.h  *- * Copyright (c) Chris Putnam 2003-2013+ * Copyright (c) Chris Putnam 2003-2017  *  * Source code released under the GPL version 2  *
bibutils/copacin.c view
@@ -1,7 +1,7 @@ /*  * copacin.c  *- * Copyright (c) Chris Putnam 2004-2014+ * Copyright (c) Chris Putnam 2004-2017  *  * Program and source code released under the GPL version 2  *@@ -10,19 +10,26 @@ #include <stdlib.h> #include <string.h> #include "is_ws.h"-#include "newstr.h"-#include "newstr_conv.h"-#include "list.h"+#include "str.h"+#include "str_conv.h"+#include "slist.h" #include "name.h"-#include "title.h" #include "fields.h" #include "reftypes.h"-#include "serialno.h"-#include "copacin.h"+#include "bibformats.h"+#include "generic.h" +extern variants copac_all[];+extern int copac_nall;+ /*****************************************************  PUBLIC: void copacin_initparams() *****************************************************/++static int copacin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset );+static int copacin_processf( fields *bibin, char *p, char *filename, long nref, param *pm );+static int copacin_convertf( fields *bibin, fields *info, int reftype, param *pm );+ void copacin_initparams( param *p, const char *progname ) {@@ -45,8 +52,8 @@ 	p->all      = copac_all; 	p->nall     = copac_nall; -	list_init( &(p->asis) );-	list_init( &(p->corps) );+	slist_init( &(p->asis) );+	slist_init( &(p->corps) );  	if ( !progname ) p->progname = NULL; 	else p->progname = strdup( progname );@@ -74,14 +81,14 @@ 	return 1;  } static int-readmore( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line )+readmore( FILE *fp, char *buf, int bufsize, int *bufpos, str *line ) { 	if ( line->len ) return 1;-	else return newstr_fget( fp, buf, bufsize, bufpos, line );+	else return str_fget( fp, buf, bufsize, bufpos, line ); } -int-copacin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset )+static int+copacin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset ) { 	int haveref = 0, inref=0; 	char *p;@@ -100,22 +107,22 @@ 			p += 3; 		} 		if ( copacin_istag( p ) ) {-			if ( inref ) newstr_addchar( reference, '\n' );-			newstr_strcat( reference, p );-			newstr_empty( line );+			if ( inref ) str_addchar( reference, '\n' );+			str_strcatc( reference, p );+			str_empty( line ); 			inref = 1; 		} else if ( inref ) { 			if ( p ) { 				/* copac puts tag only on 1st line */-				newstr_addchar( reference, ' ' );+				str_addchar( reference, ' ' ); 				if ( *p ) p++; 				if ( *p ) p++; 				if ( *p ) p++;-			   	newstr_strcat( reference, p );+				str_strcatc( reference, p ); 			}-			newstr_empty( line );+			str_empty( line ); 		} else {-			newstr_empty( line );+			str_empty( line ); 		} 	} 	return haveref;@@ -126,20 +133,20 @@ *****************************************************/  static char*-copacin_addtag2( char *p, newstr *tag, newstr *data )+copacin_addtag2( char *p, str *tag, str *data ) { 	int  i; 	i =0; 	while ( i<3 && *p ) {-		newstr_addchar( tag, *p++ );+		str_addchar( tag, *p++ ); 		i++; 	} 	while ( *p==' ' || *p=='\t' ) p++; 	while ( *p && *p!='\r' && *p!='\n' ) {-		newstr_addchar( data, *p );+		str_addchar( data, *p ); 		p++; 	}-	newstr_trimendingws( data );+	str_trimendingws( data ); 	while ( *p=='\n' || *p=='\r' ) p++; 	return p; }@@ -152,29 +159,29 @@ 	return p; } -int-copacin_processf( fields *copacin, char *p, char *filename, long nref )+static int+copacin_processf( fields *copacin, char *p, char *filename, long nref, param *pm ) {-	newstr tag, data;+	str tag, data; 	int status;-	newstr_init( &tag );-	newstr_init( &data );+	str_init( &tag );+	str_init( &data ); 	while ( *p ) { 		p = skip_ws( p ); 		if ( copacin_istag( p ) ) { 			p = copacin_addtag2( p, &tag, &data ); 			/* don't add empty strings */-			if ( tag.len && data.len ) {+			if ( str_has_value( &tag ) && str_has_value( &data ) ) { 				status = fields_add( copacin, tag.data, data.data, 0 ); 				if ( status!=FIELDS_OK ) return 0; 			}-			newstr_empty( &tag );-			newstr_empty( &data );+			str_empty( &tag );+			str_empty( &data ); 		} 		else p = copacin_nextline( p ); 	}-	newstr_free( &tag );-	newstr_free( &data );+	str_free( &tag );+	str_free( &data ); 	return 1; } @@ -188,48 +195,54 @@  * editors seem to be stuck in as authors with the tag "[Editor]" in it  */ static int-copacin_addname( fields *info, char *tag, newstr *name, int level, list *asis,-	list *corps )+copacin_person( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout ) {-	char *usetag = tag, editor[]="EDITOR";-	newstr usename, *s;-	list tokens;-	int comma = 0, i, ok;+	char *usetag = outtag, editor[]="EDITOR";+	int comma = 0, i, ok, status;+	str usename, *s;+	slist tokens; -	if ( list_find( asis, name->data ) !=-1  ||-	     list_find( corps, name->data ) !=-1 ) {-		ok = name_add( info, tag, name->data, level, asis, corps );+	if ( slist_find( &(pm->asis),  invalue ) !=-1  ||+	     slist_find( &(pm->corps), invalue ) !=-1 ) {+		ok = name_add( bibout, outtag, invalue->data, level, &(pm->asis), &(pm->corps) ); 		if ( ok ) return BIBL_OK; 		else return BIBL_ERR_MEMERR; 	} -	list_init( &tokens );-	newstr_init( &usename );+	slist_init( &tokens );+	str_init( &usename ); -	list_tokenize( &tokens, name, " ", 1 );+	status = slist_tokenize( &tokens, invalue, " ", 1 );+	if ( status!=SLIST_OK ) return BIBL_ERR_MEMERR;+ 	for ( i=0; i<tokens.n; ++i ) {-		s = list_get( &tokens, i );-		if ( !strcmp( s->data, "[Editor]" ) ) {+		s = slist_str( &tokens, i );+		if ( !strcmp( str_cstr( s ), "[Editor]" ) ) { 			usetag = editor;-			newstr_strcpy( s, "" );+			str_empty( s ); 		} else if ( s->len && s->data[s->len-1]==',' ) { 			comma++; 		} 	}  	if ( comma==0 && tokens.n ) {-		s = list_get( &tokens, 0 );-		newstr_addchar( s, ',' );+		s = slist_str( &tokens, 0 );+		str_addchar( s, ',' ); 	}  	for ( i=0; i<tokens.n; ++i ) {-		if ( i ) newstr_addchar( &usename, ' ' );-		newstr_newstrcat( &usename, list_get( &tokens, i ) );+		s = slist_str( &tokens, i );+		if ( str_is_empty( s ) ) continue;+		if ( i ) str_addchar( &usename, ' ' );+		str_strcat( &usename, s ); 	} -	list_free( &tokens );+	slist_free( &tokens ); -	ok = name_add( info, usetag, usename.data, level, asis, corps );+	ok = name_add( bibout, usetag, str_cstr( &usename ), level, &(pm->asis), &(pm->corps) );++	str_free( &usename );+ 	if ( ok ) return BIBL_OK; 	else return BIBL_ERR_MEMERR; }@@ -244,66 +257,37 @@ }  static int-copacin_simple( fields *out, char *tag, char *value, int level )+copacin_convertf( fields *bibin, fields *bibout, int reftype, param *p ) {-	int fstatus = fields_add( out, tag, value, level );-	if ( fstatus==FIELDS_OK ) return BIBL_OK;-	else return BIBL_ERR_MEMERR;-}+	static int (*convertfns[NUM_REFTYPES])(fields *, int, str *, str *, int, param *, char *, fields *) = {+		[ 0 ... NUM_REFTYPES-1 ] = generic_null,+		[ SIMPLE       ] = generic_simple,+		[ TITLE        ] = generic_title,+		[ NOTES        ] = generic_notes,+		[ SERIALNO     ] = generic_serialno,+		[ PERSON       ] = copacin_person+	}; -int-copacin_convertf( fields *copacin, fields *out, int reftype, param *p, variants *all, int nall )-{-	int  process, level, i, n, nfields, ok, status = BIBL_OK;-	newstr *tag, *data;-	char *newtag;+	int  process, level, i, nfields, status = BIBL_OK;+	str *intag, *invalue;+	char *outtag; -	nfields = fields_num( copacin );+	nfields = fields_num( bibin ); 	for ( i=0; i<nfields; ++i ) { -		tag = fields_tag( copacin, i, FIELDS_STRP );+		intag = fields_tag( bibin, i, FIELDS_STRP ); -		n = translate_oldtag( tag->data, reftype, all, nall, &process, &level, &newtag );-		if ( n==-1 ) {-			copacin_report_notag( p, tag->data );+		if ( !translate_oldtag( intag->data, reftype, p->all, p->nall, &process, &level, &outtag ) ) {+			copacin_report_notag( p, intag->data ); 			continue; 		}-		if ( process == ALWAYS ) continue; /*add these later*/ -		data = fields_value( copacin, i, FIELDS_STRP );--		switch ( process ) {--		case SIMPLE:-			status = copacin_simple( out, newtag, data->data, level );-			break;--		case TITLE:-			ok = title_process( out, newtag, data->data, level, p->nosplittitle );-			if ( ok ) status = BIBL_OK;-			else status = BIBL_ERR_MEMERR;-			break;--		case PERSON:-			status = copacin_addname( out, newtag, data, level, &(p->asis), &(p->corps) );-			break;--		case SERIALNO:-			ok = addsn( out, data->data, level );-			if ( ok ) status = BIBL_OK;-			else status = BIBL_ERR_MEMERR;-			break;--		default:-			fprintf(stderr,"%s: internal error -- " "illegal process value %d\n", p->progname, process );-			status = BIBL_OK;-			break;-		}+		invalue = fields_value( bibin, i, FIELDS_STRP ); +		status = convertfns[ process ] ( bibin, i, intag, invalue, level, p, outtag, bibout ); 		if ( status!=BIBL_OK ) return status;  	}  	return status; }-
− bibutils/copacin.h
@@ -1,30 +0,0 @@-/*- * copacin.h- *- * Copyright (c) Chris Putnam 2004-2014- *- * Source code released under the GPL- *- */-#ifndef COPACIN_H-#define COPACIN_H--#include "newstr.h"-#include "fields.h"-#include "reftypes.h"-#include "bibutils.h"--extern int copacin_readf( FILE *fp, char *buf, int bufsize, int *bufpos,-		newstr *line, newstr *reference, int *fcharset );-extern int copacin_processf( fields *copacin, char *p, char *filename, -		long nref );-extern int copacin_convertf( fields *copacin, fields *info, int reftype, param *p, variants *all, int nall );--extern void copacin_initparams( param *p, const char *progname );---extern variants copac_all[];-extern int copac_nall;---#endif
bibutils/copactypes.c view
@@ -1,7 +1,7 @@ /*  * copactypes.c  *- * Copyright (c) Chris Putnam 2004-2014+ * Copyright (c) Chris Putnam 2004-2017  *  * Program and source code released under the GPL version 2  *@@ -14,22 +14,22 @@  /* if no specific type can be identified */ static lookups generic[] = {-	{ "TI-", "TITLE" ,    TITLE,  LEVEL_MAIN },-	{ "AU-", "AUTHOR",    PERSON, LEVEL_MAIN },-	{ "MV-", "VOLUME",    SIMPLE, LEVEL_MAIN },-	{ "SE-", "TITLE",     TITLE,  LEVEL_HOST },-	{ "ED-", "EDITION",   SIMPLE, LEVEL_MAIN },-	{ "SC-", "SCALE",     SIMPLE, LEVEL_MAIN }, /* for maps */-	{ "PU-", "PUBLISHER", SIMPLE, LEVEL_MAIN },-	{ "PY-", "YEAR",      SIMPLE, LEVEL_MAIN },-	{ "PD-", "DESCRIPTION",SIMPLE, LEVEL_MAIN }, /* physical description */-	{ "DT-", "TYPE",      SIMPLE, LEVEL_MAIN },-	{ "LA-", "LANGUAGE",  SIMPLE, LEVEL_MAIN },+	{ "TI-", "TITLE" ,       TITLE,  LEVEL_MAIN },+	{ "AU-", "AUTHOR",       PERSON, LEVEL_MAIN },+	{ "MV-", "VOLUME",       SIMPLE, LEVEL_MAIN },+	{ "SE-", "TITLE",        TITLE,  LEVEL_HOST },+	{ "ED-", "EDITION",      SIMPLE, LEVEL_MAIN },+	{ "SC-", "SCALE",        SIMPLE, LEVEL_MAIN }, /* for maps */+	{ "PU-", "PUBLISHER",    SIMPLE, LEVEL_MAIN },+	{ "PY-", "DATE:YEAR",    SIMPLE, LEVEL_MAIN },+	{ "PD-", "DESCRIPTION",  SIMPLE, LEVEL_MAIN }, /* physical description */+	{ "DT-", "TYPE",         SIMPLE, LEVEL_MAIN },+	{ "LA-", "LANGUAGE",     SIMPLE, LEVEL_MAIN }, 	{ "IS-", "SERIALNUMBER", SERIALNO, LEVEL_MAIN },-	{ "NT-", "NOTES",     SIMPLE, LEVEL_MAIN },-	{ "KW-", "KEYWORD",   SIMPLE, LEVEL_MAIN },-	{ "UL-", "URL",       SIMPLE, LEVEL_MAIN },-	{ "HL-", "LOCATION",  SIMPLE, LEVEL_MAIN }+	{ "NT-", "NOTES",        NOTES,  LEVEL_MAIN },+	{ "KW-", "KEYWORD",      SIMPLE, LEVEL_MAIN },+	{ "UL-", "URL",          SIMPLE, LEVEL_MAIN },+	{ "HL-", "LOCATION",     SIMPLE, LEVEL_MAIN } };  /* order is important....."Book" matches "Book" and "Book Section", hence
− bibutils/doi.c
@@ -1,115 +0,0 @@-/*- * doi.c- *- * doi_to_url()- * Handle outputing DOI as a URL (Endnote and RIS formats)- *     1) Append http://dx.doi.org as necessary- *     2) Check for overlap with pre-existing URL for the DOI- *- * is_doi()- * Check for DOI buried in another field.- *- * Copyright (c) Chris Putnam 2008-2013- *- * Source code released under the GPL version 2- *- */-#include <stdio.h>-#include <stdlib.h>-#include <string.h>-#include <ctype.h>-#include "newstr.h"-#include "fields.h"--static void-construct_url( char *prefix, newstr *id, newstr *id_url )-{-	if ( !strncasecmp( id->data, "http:", 5 ) )-		newstr_newstrcpy( id_url, id );-	else {-		newstr_strcpy( id_url, prefix );-		if ( id->data[0]!='/' ) newstr_addchar( id_url, '/' );-		newstr_newstrcat( id_url, id );-	}-}--static int-url_exists( fields *f, char *urltag, newstr *doi_url )-{-	int i, n;-	if ( urltag ) {-		n = fields_num( f );-		for ( i=0; i<n; ++i ) {-			if ( strcmp( fields_tag( f, i, FIELDS_CHRP ), urltag ) ) continue;-			if ( strcmp( fields_value( f, i, FIELDS_CHRP ), doi_url->data ) ) continue;-			return 1;-		}-	}-	return 0;-}--static void-xxx_to_url( fields *f, int n, char *http_prefix, char *urltag, newstr *xxx_url )-{-	newstr_empty( xxx_url );-	construct_url( http_prefix, fields_value( f, n, FIELDS_STRP ), xxx_url );-	if ( url_exists( f, urltag, xxx_url ) )-		newstr_empty( xxx_url );-}-void-doi_to_url( fields *f, int n, char *urltag, newstr *url )-{-	xxx_to_url( f, n, "http://dx.doi.org", urltag, url );-}-void-jstor_to_url( fields *f, int n, char *urltag, newstr *url )-{-	xxx_to_url( f, n, "http://www.jstor.org/stable", urltag, url );-}-void-pmid_to_url( fields *f, int n, char *urltag, newstr *url )-{-	xxx_to_url( f, n, "http://www.ncbi.nlm.nih.gov/pubmed", urltag, url );-}-void-arxiv_to_url( fields *f, int n, char *urltag, newstr *url )-{-	xxx_to_url( f, n, "http://arxiv.org/abs", urltag, url );-}--/* Rules for the pattern:- *   '#' = number- *   isalpha() = match precisely (matchcase==1) or match regardless of case- *   	(matchcase==0)- *   all others must match precisely- */-static int-string_pattern( char *s, char *pattern, int matchcase )-{-	int patlen, match, i;-	patlen = strlen( pattern );-	if ( strlen( s ) < patlen ) return 0; /* too short */-	for ( i=0; i<patlen; ++i ) {-		match = 0;-		if ( pattern[i]=='#' ) {-			if ( isdigit( (unsigned char)s[i] ) ) match = 1;-		} else if ( !matchcase && isalpha( (unsigned char)pattern[i] ) ) {-			if ( tolower((unsigned char)pattern[i])==tolower((unsigned char)s[i])) match = 1;-		} else {-			if ( pattern[i] == s[i] ) match = 1;-		}-		if ( !match ) return 0;-	}-	return 1;-}--/* science direct is now doing "M3  - doi: DOI: 10.xxxx/xxxxx" */-int-is_doi( char *s )-{-	if ( string_pattern( s, "##.####/", 0 ) ) return 0;-	if ( string_pattern( s, "doi:##.####/", 0 ) ) return 4;-	if ( string_pattern( s, "doi: ##.####/", 0 ) ) return 5;-	if ( string_pattern( s, "doi: DOI: ##.####/", 0 ) ) return 10;-	return -1;-}
− bibutils/doi.h
@@ -1,21 +0,0 @@-/*- * doi.h- *- * Copyright (c) Chris Putnam 2004-2013- *- * Source code released under the GPL version 2- *- */-#ifndef DOI_H-#define DOI_H--#include "newstr.h"-#include "fields.h"--extern void doi_to_url( fields *info, int n, char *urltag, newstr *doi_url );-extern int is_doi( char *s );-extern void pmid_to_url( fields *info, int n, char *urltag, newstr *pmid_url );-extern void arxiv_to_url( fields *info, int n, char *urltag, newstr *arxiv_url );-extern void jstor_to_url( fields *info, int n, char *urltag, newstr *jstor_url );--#endif
bibutils/ebiin.c view
@@ -1,7 +1,7 @@ /*  * ebiin.c  *- * Copyright (c) Chris Putnam 2004-2013+ * Copyright (c) Chris Putnam 2004-2017  *  * Program and source code released under the GPL version 2  *@@ -9,13 +9,17 @@ #include <stdio.h> #include <stdlib.h> #include "is_ws.h"-#include "newstr.h"-#include "newstr_conv.h"+#include "str.h"+#include "str_conv.h" #include "fields.h" #include "xml.h" #include "xml_encoding.h"-#include "ebiin.h"+#include "bibformats.h" +static int ebiin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset );+static int ebiin_processf( fields *ebiin, char *data, char *filename, long nref, param *p );++ /*****************************************************  PUBLIC: void ebiin_initparams() *****************************************************/@@ -42,8 +46,8 @@ 	p->all      = NULL; 	p->nall     = 0; -	list_init( &(p->asis) );-	list_init( &(p->corps) );+	slist_init( &(p->asis) );+	slist_init( &(p->corps) );  	if ( !progname ) p->progname = NULL; 	else p->progname = strdup( progname );@@ -52,14 +56,14 @@ /*****************************************************  PUBLIC: int ebiin_readf() *****************************************************/-int-ebiin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset )+static int+ebiin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset ) {-	newstr tmp;-	char *startptr = NULL, *endptr; 	int haveref = 0, inref = 0, file_charset = CHARSET_UNKNOWN, m;-	newstr_init( &tmp );-	while ( !haveref && newstr_fget( fp, buf, bufsize, bufpos, line ) ) {+	char *startptr = NULL, *endptr;+	str tmp;+	str_init( &tmp );+	while ( !haveref && str_fget( fp, buf, bufsize, bufpos, line ) ) { 		if ( line->data ) { 			m = xml_getencoding( line ); 			if ( m!=CHARSET_UNKNOWN ) file_charset = m;@@ -67,19 +71,19 @@ 		if ( line->data ) 			startptr = xml_findstart( line->data, "Publication" ); 		if ( startptr || inref ) {-			if ( inref ) newstr_strcat( &tmp, line->data );+			if ( inref ) str_strcat( &tmp, line ); 			else {-				newstr_strcat( &tmp, startptr );+				str_strcatc( &tmp, startptr ); 				inref = 1; 			}-			endptr = xml_findend( tmp.data, "Publication" );+			endptr = xml_findend( str_cstr( &tmp ), "Publication" ); 			if ( endptr ) {-				newstr_segcpy( reference, tmp.data, endptr );+				str_segcpy( reference, str_cstr( &tmp ), endptr ); 				haveref = 1; 			} 		} 	}-	newstr_free( &tmp );+	str_free( &tmp ); 	*fcharset = file_charset; 	return haveref; }@@ -101,9 +105,9 @@ 	int i, status; 	char *d; -	if ( !xml_hasdata( node ) ) goto out;+	if ( !xml_hasvalue( node ) ) goto out; -	d = xml_data( node );+	d = xml_value( node ); 	for ( i=0; i<nc; ++i ) { 		if ( c[i].a==NULL ) { 			if ( xml_tagexact( node, c[i].in ) ) {@@ -135,8 +139,8 @@ ebiin_title( xml *node, fields *info, int title_level ) { 	int status;-	if ( xml_hasdata( node ) ) {-		status = fields_add( info, "TITLE", xml_data( node ), title_level );+	if ( xml_hasvalue( node ) ) {+		status = fields_add( info, "TITLE", xml_value( node ), title_level ); 		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	} 	return BIBL_OK;@@ -148,38 +152,38 @@  *             <MedlineDate>2003 Jan-Feb</MedlineDate>  */ static int-ebiin_medlinedate_year( fields *info, char *p, newstr *s, int level, char **end )+ebiin_medlinedate_year( fields *info, char *p, str *s, int level, char **end ) { 	int status;-	*end = newstr_cpytodelim( s, p, " \t\n\r", 0 );-	if ( newstr_memerr( s ) ) return BIBL_ERR_MEMERR;-	if ( s->len ) {-		status = fields_add( info, "PARTYEAR", s->data, level );+	*end = str_cpytodelim( s, p, " \t\n\r", 0 );+	if ( str_memerr( s ) ) return BIBL_ERR_MEMERR;+	if ( str_has_value( s ) ) {+		status = fields_add( info, "PARTDATE:YEAR", s->data, level ); 		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	} 	return BIBL_OK; } static int-ebiin_medlinedate_month( fields *info, char *p, newstr *s, int level, char **end )+ebiin_medlinedate_month( fields *info, char *p, str *s, int level, char **end ) { 	int status;-	*end = newstr_cpytodelim( s, p, " \t\n\r", 0 );-	newstr_findreplace( s, "-", "/" );-	if ( newstr_memerr( s ) ) return BIBL_ERR_MEMERR;-	if ( s->len ) {-		status = fields_add( info, "PARTMONTH", s->data, level );+	*end = str_cpytodelim( s, p, " \t\n\r", 0 );+	str_findreplace( s, "-", "/" );+	if ( str_memerr( s ) ) return BIBL_ERR_MEMERR;+	if ( str_has_value( s ) ) {+		status = fields_add( info, "PARTDATE:MONTH", s->data, level ); 		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	} 	return BIBL_OK; } static int-ebiin_medlinedate_day( fields *info, char *p, newstr *s, int level, char **end )+ebiin_medlinedate_day( fields *info, char *p, str *s, int level, char **end ) { 	int status;-	*end = newstr_cpytodelim( s, p, " \t\n\r", 0 );-	if ( newstr_memerr( s ) ) return BIBL_ERR_MEMERR;-	if ( s->len ) {-		status = fields_add( info, "PARTDAY", s->data, level );+	*end = str_cpytodelim( s, p, " \t\n\r", 0 );+	if ( str_memerr( s ) ) return BIBL_ERR_MEMERR;+	if ( str_has_value( s ) ) {+		status = fields_add( info, "PARTDATE:DAY", s->data, level ); 		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	} 	return BIBL_OK;@@ -188,14 +192,14 @@ ebiin_medlinedate( fields *info, char *p, int level ) { 	int status;-	newstr s;-	newstr_init( &s );+	str s;+	str_init( &s ); 	status = ebiin_medlinedate_year( info, skip_ws( p ), &s, level, &p ); 	if ( status==BIBL_OK && *p ) 		status = ebiin_medlinedate_month( info, skip_ws( p ), &s, level, &p ); 	if ( status==BIBL_OK && *p ) 		status = ebiin_medlinedate_day( info, skip_ws( p ), &s, level, &p );-	newstr_free( &s );+	str_free( &s ); 	return status; } @@ -231,21 +235,21 @@ ebiin_journal1( xml *node, fields *info ) { 	xml_convert c[] = {-		{ "ISSN",     NULL, NULL, "ISSN",      1 },-		{ "Volume",   NULL, NULL, "VOLUME",    1 },-		{ "Issue",    NULL, NULL, "ISSUE",     1 },-		{ "Year",     NULL, NULL, "PARTYEAR",  1 },-		{ "Month",    NULL, NULL, "PARTMONTH", 1 },-		{ "Day",      NULL, NULL, "PARTDAY",   1 },-		{ "Language", NULL, NULL, "LANGUAGE",  1 },+		{ "ISSN",     NULL, NULL, "ISSN",           1 },+		{ "Volume",   NULL, NULL, "VOLUME",         1 },+		{ "Issue",    NULL, NULL, "ISSUE",          1 },+		{ "Year",     NULL, NULL, "PARTDATE:YEAR",  1 },+		{ "Month",    NULL, NULL, "PARTDATE:MONTH", 1 },+		{ "Day",      NULL, NULL, "PARTDATE:DAY",   1 },+		{ "Language", NULL, NULL, "LANGUAGE",       1 }, 	}; 	int nc = sizeof( c ) / sizeof( c[0] ), status, found;-	if ( xml_hasdata( node ) ) {+	if ( xml_hasvalue( node ) ) { 		status = ebiin_doconvert( node, info, c, nc, &found ); 		if ( status!=BIBL_OK ) return status; 		if ( !found ) { 			if ( xml_tagexact( node, "MedlineDate" ) ) {-				status = ebiin_medlinedate( info, xml_data( node ), 1 );+				status = ebiin_medlinedate( info, xml_value( node ), 1 ); 				if ( status!=BIBL_OK ) return status; 			} 		}@@ -270,26 +274,26 @@ { 	int i, status, ret = BIBL_OK; 	const int level = 1;-	newstr sp, ep, *up;+	str sp, ep, *up; -	newstrs_init( &sp, &ep, NULL );+	strs_init( &sp, &ep, NULL );  	/* ...start page */-	p = newstr_cpytodelim( &sp, skip_ws( p ), "-", 1 );-	if ( newstr_memerr( &sp ) ) {+	p = str_cpytodelim( &sp, skip_ws( p ), "-", 1 );+	if ( str_memerr( &sp ) ) { 		ret = BIBL_ERR_MEMERR; 		goto out; 	}  	/* ...end page */-	p = newstr_cpytodelim( &ep, skip_ws( p ), " \t\n\r", 0 );-	if ( newstr_memerr( &ep ) ) {+	p = str_cpytodelim( &ep, skip_ws( p ), " \t\n\r", 0 );+	if ( str_memerr( &ep ) ) { 		ret = BIBL_ERR_MEMERR; 		goto out; 	}  	if ( sp.len ) {-		status = fields_add( info, "PAGESTART", sp.data, level );+		status = fields_add( info, "PAGES:START", sp.data, level ); 		if ( status!=FIELDS_OK ) { 			ret = BIBL_ERR_MEMERR; 			goto out;@@ -301,12 +305,12 @@ 				sp.data[i] = ep.data[i-sp.len+ep.len]; 				up = &(sp); 		} else up = &(ep);-		status = fields_add( info, "PAGEEND", up->data, level );+		status = fields_add( info, "PAGES:STOP", up->data, level ); 		if ( status!=FIELDS_OK ) ret = BIBL_ERR_MEMERR; 	}  out:-	newstrs_free( &sp, &ep, NULL );+	strs_free( &sp, &ep, NULL ); 	return ret; } static int@@ -314,7 +318,7 @@ { 	int status; 	if ( xml_tagexact( node, "Pages" ) && node->value ) {-		status = ebiin_pages( info, xml_data( node ) );+		status = ebiin_pages( info, xml_value( node ) ); 		if ( status!=BIBL_OK ) return status; 	} 	if ( node->down ) {@@ -336,8 +340,8 @@ ebiin_abstract( xml *node, fields *info ) { 	int status;-	if ( xml_hasdata( node ) && xml_tagexact( node, "AbstractText" ) ) {-		status = fields_add( info, "ABSTRACT", xml_data( node ), 0 );+	if ( xml_hasvalue( node ) && xml_tagexact( node, "AbstractText" ) ) {+		status = fields_add( info, "ABSTRACT", xml_value( node ), 0 ); 		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	} 	else if ( node->next ) {@@ -357,32 +361,32 @@  * </AuthorList>  */ static int-ebiin_author( xml *node, newstr *name )+ebiin_author( xml *node, str *name ) { 	int status; 	char *p; 	if ( xml_tagexact( node, "LastName" ) ) { 		if ( name->len ) {-			newstr_prepend( name, "|" );-			newstr_prepend( name, xml_data( node ) );+			str_prepend( name, "|" );+			str_prepend( name, xml_value( node ) ); 		}-		else newstr_strcat( name, xml_data( node ) );+		else str_strcatc( name, xml_value( node ) ); 	} else if ( xml_tagexact( node, "ForeName" ) ||  	            xml_tagexact( node, "FirstName" ) ) {-		p = xml_data( node );+		p = xml_value( node ); 		while ( p && *p ) {-			if ( name->len ) newstr_addchar( name, '|' );+			if ( name->len ) str_addchar( name, '|' ); 			while ( *p && *p==' ' ) p++;-			while ( *p && *p!=' ' ) newstr_addchar( name, *p++ );+			while ( *p && *p!=' ' ) str_addchar( name, *p++ ); 		} 	} else if ( xml_tagexact( node, "Initials" ) && !strchr( name->data, '|' ) ) {-		p = xml_data( node );+		p = xml_value( node ); 		while ( p && *p ) {-			if ( name->len ) newstr_addchar( name, '|' );-			if ( !is_ws(*p ) ) newstr_addchar( name, *p++ );+			if ( name->len ) str_addchar( name, '|' );+			if ( !is_ws(*p ) ) str_addchar( name, *p++ ); 		} 	}-	if ( newstr_memerr( name ) ) return BIBL_ERR_MEMERR;+	if ( str_memerr( name ) ) return BIBL_ERR_MEMERR; 		  	if ( node->down ) { 		status = ebiin_author( node->down, name );@@ -399,9 +403,9 @@ ebiin_authorlist( xml *node, fields *info, int level ) { 	int fstatus, status = BIBL_OK;-	newstr name;+	str name; -	newstr_init( &name );+	str_init( &name ); 	node = node->down; 	while ( node ) { 		if ( xml_tagexact( node, "Author" ) && node->down ) {@@ -410,13 +414,13 @@ 			if ( name.len ) { 				fstatus = fields_add(info,"AUTHOR",name.data,level); 				if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }-				newstr_empty( &name );+				str_empty( &name ); 			} 		} 		node = node->next; 	} out:-	newstr_free( &name );+	str_free( &name ); 	return status; } @@ -436,8 +440,8 @@ ebiin_journal2( xml *node, fields *info ) { 	int status;-	if ( xml_tagwithdata( node, "TitleAbbreviation" ) ) {-		status = fields_add( info, "TITLE", xml_data( node ), 1 );+	if ( xml_tagwithvalue( node, "TitleAbbreviation" ) ) {+		status = fields_add( info, "TITLE", xml_value( node ), 1 ); 		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	} 	if ( node->down ) {@@ -465,8 +469,8 @@ ebiin_meshheading( xml *node, fields *info ) { 	int status;-	if ( xml_tagwithdata( node, "DescriptorName" ) ) {-		status = fields_add( info, "KEYWORD", xml_data( node ), 0 );+	if ( xml_tagwithvalue( node, "DescriptorName" ) ) {+		status = fields_add( info, "KEYWORD", xml_value( node ), 0 ); 		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	} 	if ( node->next ) {@@ -495,46 +499,46 @@ ebiin_book( xml *node, fields *info, int book_level ) { 	xml_convert book[] = {-		{ "Publisher",              NULL, NULL, "PUBLISHER",  0 },-		{ "Language",               NULL, NULL, "LANGUAGE",   0 },-		{ "ISBN10",                 NULL, NULL, "ISBN",       0 },-		{ "ISBN13",                 NULL, NULL, "ISBN13",     0 },-		{ "Year",                   NULL, NULL, "YEAR",       0 },-		{ "Month",                  NULL, NULL, "MONTH",      0 },-		{ "Day",                    NULL, NULL, "DAY",        0 },-		{ "PageTotal",              NULL, NULL, "TOTALPAGES", 0 },-		{ "SeriesName",             NULL, NULL, "TITLE",      1 },-		{ "SeriesISSN",             NULL, NULL, "ISSN",       0 },-		{ "OtherReportInformation", NULL, NULL, "NOTES",      0 },-		{ "Edition",                NULL, NULL, "EDITION",    0 },+		{ "Publisher",              NULL, NULL, "PUBLISHER",      0 },+		{ "Language",               NULL, NULL, "LANGUAGE",       0 },+		{ "ISBN10",                 NULL, NULL, "ISBN",           0 },+		{ "ISBN13",                 NULL, NULL, "ISBN13",         0 },+		{ "Year",                   NULL, NULL, "DATE:YEAR",      0 },+		{ "Month",                  NULL, NULL, "DATE:MONTH",     0 },+		{ "Day",                    NULL, NULL, "DATE:DAY",       0 },+		{ "PageTotal",              NULL, NULL, "PAGES:TOTAL",    0 },+		{ "SeriesName",             NULL, NULL, "TITLE",          1 },+		{ "SeriesISSN",             NULL, NULL, "ISSN",           0 },+		{ "OtherReportInformation", NULL, NULL, "NOTES",          0 },+		{ "Edition",                NULL, NULL, "EDITION",        0 }, 	}; 	int nbook = sizeof( book ) / sizeof( book[0] ); 	xml_convert inbook[] = {-		{ "Publisher",              NULL, NULL, "PUBLISHER",  1 },-		{ "Language",               NULL, NULL, "LANGUAGE",   0 },-		{ "ISBN10",                 NULL, NULL, "ISBN",       1 },-		{ "ISBN13",                 NULL, NULL, "ISBN13",     1 },-		{ "Year",                   NULL, NULL, "PARTYEAR",   1 },-		{ "Month",                  NULL, NULL, "PARTMONTH",  1 },-		{ "Day",                    NULL, NULL, "PARTDAY",    1 },-		{ "PageTotal",              NULL, NULL, "TOTALPAGES", 1 },-		{ "SeriesName",             NULL, NULL, "TITLE",      2 },-		{ "SeriesISSN",             NULL, NULL, "ISSN",       1 },-		{ "OtherReportInformation", NULL, NULL, "NOTES",      1 },-		{ "Edition",                NULL, NULL, "EDITION",    1 },+		{ "Publisher",              NULL, NULL, "PUBLISHER",      1 },+		{ "Language",               NULL, NULL, "LANGUAGE",       0 },+		{ "ISBN10",                 NULL, NULL, "ISBN",           1 },+		{ "ISBN13",                 NULL, NULL, "ISBN13",         1 },+		{ "Year",                   NULL, NULL, "PARTDATE:YEAR",  1 },+		{ "Month",                  NULL, NULL, "PARTDATE:MONTH", 1 },+		{ "Day",                    NULL, NULL, "PARTDATE:DAY",   1 },+		{ "PageTotal",              NULL, NULL, "PAGES:TOTAL",    1 },+		{ "SeriesName",             NULL, NULL, "TITLE",          2 },+		{ "SeriesISSN",             NULL, NULL, "ISSN",           1 },+		{ "OtherReportInformation", NULL, NULL, "NOTES",          1 },+		{ "Edition",                NULL, NULL, "EDITION",        1 }, 	}; 	int ninbook = sizeof( inbook ) / sizeof( inbook[0] ); 	xml_convert *c; 	int nc, status, found; 	if ( book_level==0 ) { c = book; nc = nbook; } 	else { c = inbook; nc = ninbook; }-	if ( xml_hasdata( node ) ) {+	if ( xml_hasvalue( node ) ) { 		status = ebiin_doconvert( node, info, c, nc, &found ); 		if ( status!=BIBL_OK ) return status; 		if ( !found ) { 			status = BIBL_OK; 			if ( xml_tagexact( node, "MedlineDate" ) )-				status = ebiin_medlinedate( info, xml_data( node ), book_level);+				status = ebiin_medlinedate( info, xml_value( node ), book_level); 			else if ( xml_tagexact( node, "Title" ) ) 				status = ebiin_title( node, info, book_level ); 			else if ( xml_tagexact( node, "Pagination" ) && node->down )@@ -586,7 +590,7 @@ static int ebiin_publication( xml *node, fields *info ) {-	int status;+	int status = BIBL_OK; 	if ( node->down ) { 		if ( xml_tagexact( node, "Article" ) ) 			status = ebiin_article( node->down, info );@@ -612,7 +616,7 @@ ebiin_fixtype( xml *node, fields *info ) { 	char *resource = NULL, *issuance = NULL, *genre1 = NULL, *genre2 = NULL;-	newstr *type;+	str *type; 	int reslvl, isslvl, gen1lvl, gen2lvl; 	int status; @@ -684,8 +688,8 @@ 	return BIBL_OK; } -int-ebiin_processf( fields *ebiin, char *data, char *filename, long nref )+static int+ebiin_processf( fields *ebiin, char *data, char *filename, long nref, param *p ) { 	int status; 	xml top;
− bibutils/ebiin.h
@@ -1,27 +0,0 @@-/*- * ebiin.h- *- * Copyright (c) Chris Putnam 2004-2013- *- * Source code released under the GPL version 2- *- */-#ifndef PUBIN_H-#define PUBIN_H--#include "newstr.h"-#include "fields.h"-#include "reftypes.h"-#include "bibutils.h"--extern int ebiin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );-extern int ebiin_processf( fields *ebiin, char *data, char *filename, long nref );--extern void ebiin_initparams( param *p, const char *progname );---extern variants med_all[];-extern int med_nall;--#endif-
bibutils/endin.c view
@@ -1,7 +1,7 @@ /*  * endin.c  *- * Copyright (c) Chris Putnam 2003-2014+ * Copyright (c) Chris Putnam 2003-2017  *  * Program and source code released under the GPL version 2  *@@ -11,19 +11,27 @@ #include <string.h> #include <ctype.h> #include "is_ws.h"-#include "doi.h"-#include "newstr.h"-#include "newstr_conv.h"+#include "str.h"+#include "str_conv.h" #include "fields.h"-#include "name.h"-#include "title.h"-#include "serialno.h"+#include "url.h" #include "reftypes.h"-#include "endin.h"+#include "bibformats.h"+#include "generic.h" +extern variants end_all[];+extern int end_nall;+ /*****************************************************  PUBLIC: void endin_initparams() *****************************************************/++static int endin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset );+static int endin_processf( fields *endin, char *p, char *filename, long nref, param *pm );+int endin_typef( fields *endin, char *filename, int nrefs, param *p );+int endin_convertf( fields *endin, fields *info, int reftype, param *p );+int endin_cleanf( bibl *bin, param *p );+ void endin_initparams( param *p, const char *progname ) {@@ -46,8 +54,8 @@ 	p->all      = end_all; 	p->nall     = end_nall; -	list_init( &(p->asis) );-	list_init( &(p->corps) );+	slist_init( &(p->asis) );+	slist_init( &(p->corps) );  	if ( !progname ) p->progname = NULL; 	else p->progname = strdup( progname );@@ -76,14 +84,14 @@ }  static int-readmore( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line )+readmore( FILE *fp, char *buf, int bufsize, int *bufpos, str *line ) { 	if ( line->len ) return 1;-	else return newstr_fget( fp, buf, bufsize, bufpos, line );+	else return str_fget( fp, buf, bufsize, bufpos, line ); } -int-endin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset )+static int+endin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset ) { 	int haveref = 0, inref = 0; 	unsigned char *up;@@ -108,14 +116,14 @@ 		} 		/* Each reference starts with a tag && ends with a blank line */ 		if ( endin_istag( p ) ) {-			if ( reference->len ) newstr_addchar( reference, '\n' );-			newstr_strcat( reference, p );+			if ( reference->len ) str_addchar( reference, '\n' );+			str_strcatc( reference, p ); 			inref = 1; 		} else if ( inref && p ) {-			newstr_addchar( reference, '\n' );-		   	newstr_strcat( reference, p );+			str_addchar( reference, '\n' );+			str_strcatc( reference, p ); 		}-		newstr_empty( line );+		str_empty( line ); 	} 	if ( reference->len ) haveref = 1; 	return haveref;@@ -125,20 +133,20 @@  PUBLIC: int endin_processf() *****************************************************/ static char*-process_endline( newstr *tag, newstr *data, char *p )+process_endline( str *tag, str *data, char *p ) { 	int  i;  	i = 0; 	while ( i<2 && *p ) {-		newstr_addchar( tag, *p++);+		str_addchar( tag, *p++); 		i++; 	} 	while ( *p==' ' || *p=='\t' ) p++;  	while ( *p && *p!='\r' && *p!='\n' )-		newstr_addchar( data, *p++ );-	newstr_trimendingws( data );+		str_addchar( data, *p++ );+	str_trimendingws( data );  	while ( *p=='\r' || *p=='\n' ) p++; @@ -146,45 +154,45 @@ }  static char *-process_endline2( newstr *tag, newstr *data, char *p )+process_endline2( str *tag, str *data, char *p ) { 	while ( *p==' ' || *p=='\t' ) p++; 	while ( *p && *p!='\r' && *p!='\n' )-		newstr_addchar( data, *p++ );-	newstr_trimendingws( data );+		str_addchar( data, *p++ );+	str_trimendingws( data ); 	while ( *p=='\r' || *p=='\n' ) p++; 	return p; } -int-endin_processf( fields *endin, char *p, char *filename, long nref )+static int+endin_processf( fields *endin, char *p, char *filename, long nref, param *pm ) {-	newstr tag, data;+	str tag, data; 	int status, n;-	newstrs_init( &tag, &data, NULL );+	strs_init( &tag, &data, NULL ); 	while ( *p ) {-		newstrs_empty( &tag, &data, NULL );+		strs_empty( &tag, &data, NULL ); 		if ( endin_istag( p ) ) { 			p = process_endline( &tag, &data, p );-			if ( data.len==0 ) continue;-			status = fields_add( endin, tag.data, data.data, 0 );+			if ( str_is_empty( &data ) ) continue;+			status = fields_add( endin, str_cstr( &tag ), str_cstr( &data ), 0 ); 			if ( status!=FIELDS_OK ) return 0; 		} else { 			p = process_endline2( &tag, &data, p ); 			/* endnote puts %K only on 1st line of keywords */ 			n = fields_num( endin );-			if ( n>0 && data.len ) {+			if ( n>0 && str_has_value( &data ) ) { 			if ( !strncmp( endin->tag[n-1].data, "%K", 2 ) ) {-				status = fields_add( endin, "%K", data.data, 0 );+				status = fields_add( endin, "%K", str_cstr( &data ), 0 ); 				if ( status!=FIELDS_OK ) return 0; 			} else {-				newstr_addchar( &(endin->data[n-1]), ' ' );-				newstr_strcat( &(endin->data[n-1]), data.data );+				str_addchar( &(endin->data[n-1]), ' ' );+				str_strcat( &(endin->data[n-1]), &data ); 			} 			} 		} 	}-	newstrs_free( &tag, &data, NULL );+	strs_free( &tag, &data, NULL ); 	return 1; } @@ -192,7 +200,7 @@  PUBLIC: int endin_typef() *****************************************************/ -/* Endnote defaults if no %0+/* Endnote defaults if no %0 tag  *  * if %J & %V - journal article  * if %B - book section@@ -201,18 +209,16 @@  * if !%B & !%J & !%R & !%I - journal article  */ int-endin_typef( fields *endin, char *filename, int nrefs, param *p, -	variants *all, int nall )+endin_typef( fields *endin, char *filename, int nrefs, param *p ) {-	char *refnum = "";-	int n, reftype, nrefnum, nj, nv, nb, nr, nt, ni;-	n = fields_find( endin, "%0", 0 );-	nrefnum = fields_find( endin, "%F", 0 );-	if ( nrefnum!=-1 ) refnum = endin->data[nrefnum].data;-	if ( n!=-1 ) {-		reftype = get_reftype( endin->data[n].data, nrefs, -			p->progname, all, nall, refnum );-	} else {+	int ntypename, nrefname, is_default, nj, nv, nb, nr, nt, ni;+	char *refname = "", *typename="";++	ntypename = fields_find( endin, "%0", LEVEL_MAIN );+	nrefname  = fields_find( endin, "%F", LEVEL_MAIN );+	if ( nrefname!=-1  ) refname  = fields_value( endin, nrefname,  FIELDS_CHRP_NOUSE );+	if ( ntypename!=-1 ) typename = fields_value( endin, ntypename, FIELDS_CHRP_NOUSE );+	else { 		nj = fields_find( endin, "%J", 0 ); 		nv = fields_find( endin, "%V", 0 ); 		nb = fields_find( endin, "%B", 0 );@@ -220,26 +226,19 @@ 		nt = fields_find( endin, "%T", 0 ); 		ni = fields_find( endin, "%I", 0 ); 		if ( nj!=-1 && nv!=-1 ) {-			reftype = get_reftype( "Journal Article", nrefs,-					p->progname, all, nall, refnum );+			typename = "Journal Article"; 		} else if ( nb!=-1 ) {-			reftype = get_reftype( "Book Section", nrefs,-					p->progname, all, nall, refnum );+			typename = "Book Section"; 		} else if ( nr!=-1 && nt==-1 ) {-			reftype = get_reftype( "Report", nrefs,-					p->progname, all, nall, refnum );+			typename = "Report"; 		} else if ( ni!=-1 && nb==-1 && nj==-1 && nr==-1 ) {-			reftype = get_reftype( "Book", nrefs,-					p->progname, all, nall, refnum );+			typename = "Book"; 		} else if ( nb==-1 && nj==-1 && nr==-1 && ni==-1 ) {-			reftype = get_reftype( "Journal Article", nrefs,-					p->progname, all, nall, refnum );-		} else {-			reftype = get_reftype( "", nrefs, p->progname, -					all, nall, refnum ); /* default */+			typename = "Journal Article"; 		} 	}-	return reftype;++	return get_reftype( typename, nrefs, p->progname, p->all, p->nall, refname, &is_default, REFTYPE_CHATTY ); }  /*****************************************************@@ -247,43 +246,44 @@ *****************************************************/  /* Wiley puts multiple authors separated by commas on the %A lines.- * We can detect this by finding the terminal comma in the data.+ * We can detect this by finding the terminal comma in the value+ * from the tag/value pair.  *  * "%A" "Author A. X. Last, Author N. B. Next,"  */ static int is_wiley_author( fields *endin, int n ) {-	newstr *t, *d;-	t = &(endin->tag[n]);-	if ( !t->data || strcmp( t->data, "%A" ) ) return 0;-	d = &( endin->data[n] );-	if ( !(d->data) || d->len==0 ) return 0;-	if ( d->data[d->len-1]!=',' ) return 0;+	str *t, *v;+	t = fields_tag( endin, n, FIELDS_STRP_NOUSE );+	if ( str_is_empty( t ) || strcmp( t->data, "%A" ) ) return 0;+	v = fields_value( endin, n, FIELDS_STRP_NOUSE );+	if ( str_is_empty( v ) ) return 0;+	if ( v->data[v->len-1]!=',' ) return 0; 	return 1; }  static int cleanup_wiley_author( fields *endin, int n ) {	-	newstr *instring, copy, name;+	str *instring, copy, name; 	int status, nauthor = 0; 	char *p; -	newstrs_init( &copy, &name, NULL );+	strs_init( &copy, &name, NULL );  	instring = &( endin->data[n] );-	newstr_newstrcpy( &copy, instring );+	str_strcpy( &copy, instring );  	p = copy.data; 	while ( *p ) { 		if ( *p==',' ) {-			if ( newstr_memerr( &name ) )+			if ( str_memerr( &name ) ) 				return BIBL_ERR_MEMERR; 			if ( nauthor==0 ) { 				/* ...replace the first author in the field */-				newstr_newstrcpy( instring, &name );-				if ( newstr_memerr( instring ) )+				str_strcpy( instring, &name );+				if ( str_memerr( instring ) ) 					return BIBL_ERR_MEMERR; 			} else { 				status = fields_add( endin, endin->tag[n].data,@@ -291,17 +291,17 @@ 				if ( status!=FIELDS_OK ) 					return BIBL_ERR_MEMERR; 			}-			newstr_empty( &name );+			str_empty( &name ); 			nauthor++; 			p++; 			while ( is_ws( *p ) ) p++; 		} else {-			newstr_addchar( &name, *p );+			str_addchar( &name, *p ); 			p++; 		} 	} -	newstrs_free( &copy, &name, NULL );+	strs_free( &copy, &name, NULL ); 	return BIBL_OK; } @@ -332,35 +332,6 @@  PUBLIC: int endin_convertf(), returns BIBL_OK or BIBL_ERR_MEMERR *****************************************************/ -static int-endin_addpage( fields *info, char *p, int level )-{-	newstr page;-	int status;--	newstr_init( &page );--	p = newstr_cpytodelim( &page, skip_ws( p ), "- \t\r\n", 0 );-	if ( newstr_memerr( &page ) ) return BIBL_ERR_MEMERR;-	if ( page.len>0 ) {-		status = fields_add( info, "PAGESTART", page.data, level );-		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;-	}--	while ( *p && (is_ws(*p) || *p=='-' ) ) p++;--	p = newstr_cpytodelim( &page, p, "- \t\r\n", 0 );-	if ( newstr_memerr( &page ) ) return BIBL_ERR_MEMERR;-	if ( page.len>0 ) {-		status = fields_add( info, "PAGEEND", page.data, level );-		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;-	}--	newstr_free( &page );--	return BIBL_OK;-}- /* month_convert()  * convert month name to number in format MM, e.g. "January" -> "01"  * if converted, return 1@@ -403,28 +374,29 @@ }  static int-endin_adddate( fields *info, char *tag, char *newtag, char *p, int level )+endin_date( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout ) { 	char *tags[3][2] = {-		{ "YEAR",  "PARTYEAR" },-		{ "MONTH", "PARTMONTH" },-		{ "DAY",   "PARTDAY" }+		{ "DATE:YEAR",  "PARTDATE:YEAR" },+		{ "DATE:MONTH", "PARTDATE:MONTH" },+		{ "DATE:DAY",   "PARTDATE:DAY" } 	};+	char *p = invalue->data; 	char month[10], *m; 	int part, status;-	newstr date;+	str date; -	newstr_init( &date );+	str_init( &date ); -	if ( !strncasecmp( newtag, "PART", 4 ) ) part = 1;+	if ( !strncasecmp( outtag, "PART", 4 ) ) part = 1; 	else part = 0;  	/* %D YEAR */-	if ( !strcasecmp( tag, "%D" ) ) {-		newstr_cpytodelim( &date, skip_ws( p ), "", 0 );-		if ( newstr_memerr( &date ) ) return BIBL_ERR_MEMERR;-		if ( date.len>0 ) {-			status = fields_add( info, tags[0][part], date.data, level );+	if ( !strcasecmp( intag->data, "%D" ) ) {+		str_cpytodelim( &date, skip_ws( p ), "", 0 );+		if ( str_memerr( &date ) ) return BIBL_ERR_MEMERR;+		if ( str_has_value( &date ) ) {+			status = fields_add( bibout, tags[0][part], date.data, level ); 			if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR; 		} 	}@@ -432,15 +404,15 @@ 	/* %8 MONTH DAY, YEAR */ 	/* %8 MONTH, YEAR */ 	/* %8 MONTH YEAR */-	else if ( !strcasecmp( tag, "%8" ) ) {+	else if ( !strcasecmp( intag->data, "%8" ) ) {  		/* ...get month */-		p = newstr_cpytodelim( &date, skip_ws( p ), " ,\n", 0 );-		if ( newstr_memerr( &date ) ) return BIBL_ERR_MEMERR;-		if ( date.len>0 ) {+		p = str_cpytodelim( &date, skip_ws( p ), " ,\n", 0 );+		if ( str_memerr( &date ) ) return BIBL_ERR_MEMERR;+		if ( str_has_value( &date ) ) { 			if ( month_convert( date.data, month ) ) m = month;-			else m = date.data;-			status = fields_add( info, tags[1][part], m, level );+			else m = str_cstr( &date );+			status = fields_add( bibout, tags[1][part], m, level ); 			if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR; 		} @@ -448,13 +420,13 @@ 		if ( *p==',' ) p++;  		/* ...get days */-		p = newstr_cpytodelim( &date, skip_ws( p ), ",\n", 0 );-		if ( newstr_memerr( &date ) ) return BIBL_ERR_MEMERR;+		p = str_cpytodelim( &date, skip_ws( p ), ",\n", 0 );+		if ( str_memerr( &date ) ) return BIBL_ERR_MEMERR; 		if ( date.len>0 && date.len<3 ) {-			status = fields_add( info, tags[2][part], date.data, level );+			status = fields_add( bibout, tags[2][part], date.data, level ); 			if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR; 		} else if ( date.len==4 ) {-			status = fields_add( info, tags[0][part], date.data, level );+			status = fields_add( bibout, tags[0][part], date.data, level ); 			if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR; 		} @@ -462,19 +434,19 @@ 		if ( *p==',' ) p++;  		/* ...get year */-		p = newstr_cpytodelim( &date, skip_ws( p ), " \t\n\r", 0 );-		if ( newstr_memerr( &date ) ) return BIBL_ERR_MEMERR;-		if ( date.len > 0 ) {-			status = fields_add( info, tags[0][part], date.data, level );+		p = str_cpytodelim( &date, skip_ws( p ), " \t\n\r", 0 );+		if ( str_memerr( &date ) ) return BIBL_ERR_MEMERR;+		if ( str_has_value( &date ) ) {+			status = fields_add( bibout, tags[0][part], date.data, level ); 			if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR; 		} 	}-	newstr_free( &date );+	str_free( &date ); 	return BIBL_OK; }  static int-endin_addtype( fields *info, char *data, int level )+endin_type( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout ) { 	lookups types[] = { 		{ "GENERIC",                "ARTICLE" },@@ -506,17 +478,16 @@ 	int  ntypes = sizeof( types ) / sizeof( lookups ); 	int  i, status, found=0; 	for ( i=0; i<ntypes; ++i ) {-		if ( !strcasecmp( types[i].oldstr, data ) ) {+		if ( !strcasecmp( types[i].oldstr, invalue->data ) ) { 			found = 1;-			status = fields_add( info, "INTERNAL_TYPE", types[i].newstr, level );+			status = fields_add( bibout, "INTERNAL_TYPE", types[i].newstr, level ); 			if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR; 		} 	} 	if ( !found ) {-		fprintf( stderr, "Did not identify reference type '%s'\n",-			data );+		fprintf( stderr, "Did not identify reference type '%s'\n", invalue->data ); 		fprintf( stderr, "Defaulting to journal article type\n");-		status = fields_add( info, "INTERNAL_TYPE", types[0].newstr, level );+		status = fields_add( bibout, "INTERNAL_TYPE", types[0].newstr, level ); 		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	} 	return BIBL_OK;@@ -531,110 +502,57 @@ 	} } -/* Wiley's EndNote download has DOI's in "%1" tag */-static int-endin_addnotes( fields *info, char *tag, char *value, int level )-{-	int fstatus, doi;-	doi = is_doi( value );-	if ( doi!=-1 )-		fstatus = fields_add( info, "DOI", &(value[doi]), level );-	else-		fstatus = fields_add( info, tag, value, level );-	if ( fstatus==FIELDS_OK ) return BIBL_OK;-	else return BIBL_ERR_MEMERR;-}--static int-endin_simple( fields *info, char *tag, char *value, int level )-{-	int fstatus = fields_add( info, tag, value, level );-	if ( fstatus==FIELDS_OK ) return BIBL_OK;-	else return BIBL_ERR_MEMERR;-}- int-endin_convertf( fields *endin, fields *info, int reftype, param *p, variants *all, int nall )+endin_convertf( fields *bibin, fields *bibout, int reftype, param *p ) {-	int i, level, n, process, nfields, ok, fstatus, status = BIBL_OK;-	char *newtag, *t;-	newstr *d;+	static int (*convertfns[NUM_REFTYPES])(fields *, int, str *, str *, int, param *, char *, fields *) = {+		[ 0 ... NUM_REFTYPES-1 ] = generic_null,+		[ SIMPLE       ] = generic_simple,+		[ TITLE        ] = generic_title,+		[ PERSON       ] = generic_person,+		[ SERIALNO     ] = generic_serialno,+		[ PAGES        ] = generic_pages,+		[ NOTES        ] = generic_notes,+		[ URL          ] = generic_url,+		[ TYPE         ] = endin_type,+		[ DATE         ] = endin_date,+        }; -	nfields = fields_num( endin );+	int i, level, process, nfields, fstatus, status = BIBL_OK;+	char *outtag;+	str *intag, *invalue;++	nfields = fields_num( bibin ); 	for ( i=0; i<nfields; ++i ) {-		/* Ensure that data exists */-		d = fields_value( endin, i, FIELDS_STRP_NOUSE );-		if ( d->len == 0 ) {-			fields_setused( endin, i );++		/* Ensure we have data */+		if ( fields_nodata( bibin, i ) ) {+			fields_setused( bibin, i ); 			continue; 		}++		intag = fields_tag( bibin, i, FIELDS_STRP );+		invalue = fields_value( bibin, i, FIELDS_STRP );+ 		/*-		 * All refer format tags start with '%'.  If we have one+		 * Refer format tags start with '%'.  If we have one 		 * that doesn't, assume that it comes from endx2xml 		 * and just copy and paste to output 		 */-		t = fields_tag( endin, i, FIELDS_CHRP );-		if ( t[0]!='%' ) {-			fstatus = fields_add( info, t, d->data, endin->level[i] );+		if ( str_has_value( intag ) && intag->data[0]!='%' ) {+			fstatus = fields_add( bibout, str_cstr( intag ), str_cstr( invalue ), bibin->level[i] ); 			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; 			continue; 		} -		n = translate_oldtag( t, reftype, all, nall, &process, &level, &newtag );-		if ( n==-1 ) {-			endin_notag( p, t, d->data );+		if ( !translate_oldtag( str_cstr( intag ), reftype, p->all, p->nall, &process, &level, &outtag ) ) {+			endin_notag( p, str_cstr( intag ), str_cstr( invalue ) ); 			continue; 		}-		if ( process == ALWAYS ) continue; /* add these later */ -		fields_setused( endin, i );--		switch ( process ) {--		case SIMPLE:-			status = endin_simple( info, newtag, d->data, level );-			break;--		case TYPE:-			status = endin_addtype( info, d->data, level );-			break;--		case TITLE:-			ok = title_process( info, newtag, d->data, level, p->nosplittitle );-			if ( !ok ) status = BIBL_ERR_MEMERR;-			status = BIBL_OK;-			break;--		case PERSON:-			ok = name_add( info, newtag, d->data, level, &(p->asis), &(p->corps) );-			if ( !ok ) status = BIBL_ERR_MEMERR;-			status = BIBL_OK;-			break;--		case DATE:-			status = endin_adddate( info, t, newtag,d->data,level);-			break;--		case PAGES:-			status = endin_addpage( info, d->data, level );-			break;--		case SERIALNO:-			ok = addsn( info, d->data, level );-			if ( !ok ) status = BIBL_ERR_MEMERR;-			status = BIBL_OK;-			break;--		case NOTES:-			status = endin_addnotes( info, newtag, d->data, level );-			break;--		default:-			fprintf(stderr,"%s: internal error -- illegal process number %d\n", p->progname, process );-			status = BIBL_OK;-			break;-		}+		fields_setused( bibin, i ); +		status = convertfns[ process ]( bibin, i, intag, invalue, level, p, outtag, bibout ); 		if ( status!=BIBL_OK ) return status;  	}
− bibutils/endin.h
@@ -1,30 +0,0 @@-/*- * endin.h- *- * Copyright (c) Chris Putnam 2003-2014- *- * Source code released under the GPL version 2- *- */-#ifndef ENDIN_H-#define ENDIN_H--#include "newstr.h"-#include "fields.h"-#include "reftypes.h"-#include "bibutils.h"--extern int endin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );-extern int endin_processf( fields *endin, char *p, char *filename, long nref );-extern int endin_typef( fields *endin, char *filename, int nrefs, param *p, variants *all, int nall );-extern int endin_convertf( fields *endin, fields *info, int reftype, param *p, variants *all, int nall );-extern int endin_cleanf( bibl *bin, param *p );--extern void endin_initparams( param *p, const char *progname );--extern variants end_all[];-extern int end_nall;---#endif-
bibutils/endout.c view
@@ -1,7 +1,7 @@ /*  * endout.c  *- * Copyright (c) Chris Putnam 2004-2013+ * Copyright (c) Chris Putnam 2004-2017  *  * Program and source code released under the GPL version 2  *@@ -11,13 +11,18 @@ #include <string.h> #include <ctype.h> #include "utf8.h"-#include "newstr.h"+#include "str.h" #include "strsearch.h" #include "fields.h"-#include "doi.h" #include "name.h"-#include "endout.h"+#include "title.h"+#include "url.h"+#include "bibformats.h" +static int  endout_write( fields *in, FILE *fp, param *p, unsigned long refnum );+static void endout_writeheader( FILE *outptr, param *p );++ void endout_initparams( param *p, const char *progname ) {@@ -142,7 +147,7 @@ } match_type;  static int-get_type( fields *info, param *p, unsigned long refnum )+get_type( fields *in, param *p, unsigned long refnum ) { 	/* Comment out TYPE_GENERIC entries as that is default, but          * keep in source as record of mapping decision. */@@ -257,20 +262,20 @@ 	char *tag, *data;  	/* Determine type from genre information */-	for ( i=0; i<info->n; ++i ) {-		tag = info->tag[i].data;+	for ( i=0; i<in->n; ++i ) {+		tag = fields_tag( in, i, FIELDS_CHRP ); 		if ( strcasecmp( tag, "GENRE" )!=0 && 		     strcasecmp( tag, "NGENRE" )!=0 ) continue;-		data = info->data[i].data;+		data = fields_value( in, i, FIELDS_CHRP ); 		for ( j=0; j<nmatch_genres; ++j ) { 			if ( !strcasecmp( data, match_genres[j].name ) ) { 				type = match_genres[j].type;-				fields_setused( info, i );+				fields_setused( in, i ); 			} 		} 		if ( p->verbose ) { 			if ( p->progname ) fprintf( stderr, "%s: ", p->progname );-			fprintf( stderr, "Type from tag '%s' data '%s': ", info->tag[i].data, info->data[i].data );+			fprintf( stderr, "Type from tag '%s' data '%s': ", tag, data ); 			write_type( stderr, type ); 			fprintf( stderr, "\n" ); 		}@@ -280,17 +285,17 @@ 			else if ( !strcasecmp( data, "thesis" ) ) 				type = TYPE_THESIS; 			else if ( !strcasecmp( data, "book" ) ) {-				if ( info->level[i]==0 ) type = TYPE_BOOK;+				if ( in->level[i]==0 ) type = TYPE_BOOK; 				else type = TYPE_INBOOK; 			} 			else if ( !strcasecmp( data, "collection" ) ) {-				if ( info->level[i]==0 ) type = TYPE_BOOK;+				if ( in->level[i]==0 ) type = TYPE_BOOK; 				else type = TYPE_INBOOK; 			}-			if ( type!=TYPE_UNKNOWN ) fields_setused( info, i );+			if ( type!=TYPE_UNKNOWN ) fields_setused( in, i ); 		} 		/* the inbook type should be defined if 'book' in host */-		if ( type==TYPE_BOOK && info->level[i]>0 ) type = TYPE_INBOOK;+		if ( type==TYPE_BOOK && in->level[i]>0 ) type = TYPE_INBOOK; 	} 	if ( p->verbose ) { 		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );@@ -301,15 +306,15 @@  	/* Determine from resource information */ 	if ( type==TYPE_UNKNOWN ) {-		for ( i=0; i<info->n; ++i ) {-			if ( strcasecmp( info->tag[i].data, "RESOURCE" ) )+		for ( i=0; i<in->n; ++i ) {+			if ( strcasecmp( fields_tag( in, i, FIELDS_CHRP ), "RESOURCE" ) ) 				continue;-			data = info->data[i].data;+			data = fields_value( in, i, FIELDS_CHRP ); 			if ( !strcasecmp( data, "moving image" ) ) 				type = TYPE_FILMBROADCAST; 			else if ( !strcasecmp( data, "software, multimedia" ) ) 				type = TYPE_PROGRAM;-			if ( type!=TYPE_UNKNOWN ) fields_setused( info, i );+			if ( type!=TYPE_UNKNOWN ) fields_setused( in, i ); 		} 		if ( p->verbose ) { 			if ( p->progname ) fprintf( stderr, "%s: ", p->progname );@@ -321,12 +326,12 @@  	/* Determine from issuance information */ 	if ( type==TYPE_UNKNOWN ) {-		for ( i=0; i<info->n; ++i ) {-			if ( strcasecmp( info->tag[i].data, "ISSUANCE" ) )+		for ( i=0; i<in->n; ++i ) {+			if ( strcasecmp( fields_tag( in, i, FIELDS_CHRP ), "ISSUANCE" ) ) 				continue;-			data = info->data[i].data;+			data = fields_value( in, i, FIELDS_CHRP ); 			if ( !strcasecmp( data, "monographic" ) ) {-				if ( info->level[i]==0 ) type = TYPE_BOOK;+				if ( in->level[i]==0 ) type = TYPE_BOOK; 				else type = TYPE_INBOOK; 			} 		}@@ -340,14 +345,14 @@  	/* default to generic or book chapter, depending on maxlevel */ 	if ( type==TYPE_UNKNOWN ) {-		maxlevel = fields_maxlevel( info );+		maxlevel = fields_maxlevel( in ); 		if ( maxlevel > 0 ) type = TYPE_INBOOK; 		else { 			if ( p->progname ) fprintf( stderr, "%s: ", p->progname ); 			fprintf( stderr, "Cannot identify TYPE in reference %lu ", refnum+1 );-			n = fields_find( info, "REFNUM", -1 );+			n = fields_find( in, "REFNUM", -1 ); 			if ( n!=-1 )-				fprintf( stderr, " %s", info->data[n].data );+				fprintf( stderr, " %s", (char *) fields_value( in, n, FIELDS_CHRP ) ); 			fprintf( stderr, " (defaulting to generic)\n" ); 			type = TYPE_GENERIC; 		}@@ -364,7 +369,7 @@ }  static void-output_type( FILE *fp, int type, param *p )+append_type( int type, fields *out, param *p, int *status ) { 	/* These are restricted to Endnote-defined types */ 	match_type genrenames[] = {@@ -410,315 +415,338 @@ 		{ "Unpublished Work",       TYPE_UNPUBLISHED }, 	}; 	int ngenrenames = sizeof( genrenames ) / sizeof( genrenames[0] );-	int i, found = 0;-	fprintf( fp, "%%0 ");+	int i, fstatus, found = 0; 	for ( i=0; i<ngenrenames && !found; ++i ) { 		if ( genrenames[i].type == type ) {-			fprintf( fp, "%s", genrenames[i].name );+			fstatus = fields_add( out, "%0", genrenames[i].name, LEVEL_MAIN );+			if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR; 			found = 1; 		} 	} 	if ( !found ) {-		fprintf( fp, "Generic" );+		fstatus = fields_add( out, "%0", "Generic", LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR; 		if ( p->progname ) fprintf( stderr, "%s: ", p->progname ); 		fprintf( stderr, "Cannot identify type %d\n", type ); 	}-	fprintf( fp, "\n" ); } -static void-output_title( FILE *fp, fields *info, char *full, char *sub, char *endtag, -		int level )+static int+append_title( fields *in, char *full, char *sub, char *endtag,+		int level, fields *out, int *status ) {-	newstr *mainttl = fields_findv( info, level, FIELDS_STRP, full );-	newstr *subttl  = fields_findv( info, level, FIELDS_STRP, sub );+	str *mainttl = fields_findv( in, level, FIELDS_STRP, full );+	str *subttl  = fields_findv( in, level, FIELDS_STRP, sub );+	str fullttl;+	int fstatus; -	if ( !mainttl ) return;+	str_init( &fullttl );+	title_combine( &fullttl, mainttl, subttl ); -	fprintf( fp, "%s %s", endtag, mainttl->data );-	if ( subttl ) {-		if ( mainttl->len > 0 &&-		     mainttl->data[ mainttl->len-1 ]!='?' )-				fprintf( fp, ":" );-		fprintf( fp, " %s", subttl->data );+	if ( str_memerr( &fullttl ) ) {+		*status = BIBL_ERR_MEMERR;+		goto out; 	}-	fprintf( fp, "\n" );++	if ( str_has_value( &fullttl ) ) {+		fstatus = fields_add( out, endtag, str_cstr( &fullttl ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	}+out:+	str_free( &fullttl );+	return 1; }  static void-output_people( FILE *fp, fields *info, char *tag, char *entag, int level )+append_people( fields *in, char *tag, char *entag, int level, fields *out, int *status ) {-	newstr oneperson;-	int i, n, flvl;+	int i, n, flvl, fstatus;+	str oneperson; 	char *ftag;-	newstr_init( &oneperson );-	n = fields_num( info );++	str_init( &oneperson );+	n = fields_num( in ); 	for ( i=0; i<n; ++i ) {-		flvl = fields_level( info, i );+		flvl = fields_level( in, i ); 		if ( level!=LEVEL_ANY && flvl!=level ) continue;-		ftag = fields_tag( info, i, FIELDS_CHRP );+		ftag = fields_tag( in, i, FIELDS_CHRP ); 		if ( !strcasecmp( ftag, tag ) ) {-			name_build_withcomma( &oneperson, fields_value( info, i, FIELDS_CHRP ) );-			fprintf( fp, "%s %s\n", entag, oneperson.data );+			name_build_withcomma( &oneperson, fields_value( in, i, FIELDS_CHRP ) );+			fstatus = fields_add_can_dup( out, entag, str_cstr( &oneperson ), LEVEL_MAIN );+			if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR; 		} 	}-	newstr_free( &oneperson );+	str_free( &oneperson ); }  static void-output_pages( FILE *fp, fields *info )+append_pages( fields *in, fields *out, int *status ) {-	char *sn = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "PAGESTART" );-	char *en = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "PAGEEND" );+	str *sn, *en;+	int fstatus;+	str pages; 	char *ar;++	sn = fields_findv( in, LEVEL_ANY, FIELDS_STRP, "PAGES:START" );+	en = fields_findv( in, LEVEL_ANY, FIELDS_STRP, "PAGES:STOP" ); 	if ( sn || en ) {-		fprintf( fp, "%%P ");-		if ( sn ) fprintf( fp, "%s", sn );-		if ( sn && en ) fprintf( fp, "-" );-		if ( en ) fprintf( fp, "%s", en );-		fprintf( fp, "\n" );+		str_init( &pages );+		if ( sn ) str_strcpy( &pages, sn );+		if ( sn && en ) str_strcatc( &pages, "-" );+		if ( en ) str_strcat( &pages, en );+		if ( str_memerr( &pages ) ) { *status = BIBL_ERR_MEMERR; str_free( &pages ); return; }+		fstatus = fields_add( out, "%P", str_cstr( &pages ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+		str_free( &pages ); 	} else {-		ar = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "ARTICLENUMBER" );-		if ( ar ) fprintf( fp, "%%P %s\n", ar );+		ar = fields_findv( in, LEVEL_ANY, FIELDS_CHRP, "ARTICLENUMBER" );+		if ( ar ) {+			fstatus = fields_add( out, "%P", ar, LEVEL_MAIN );+			if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+		} 	} }  static void-output_doi( FILE *fp, fields *f )+append_urls( fields *in, fields *out, int *status ) {-	newstr doi_url;-	int i, n;--	newstr_init( &doi_url );+	int lstatus;+	slist types; -	n = fields_num( f );-	for ( i=0; i<n; ++i ) {-		if ( !fields_match_tag( f, i, "DOI" ) ) continue;-		doi_to_url( f, i, "URL", &doi_url );-		if ( doi_url.len )-			fprintf( fp, "%%U %s\n", doi_url.data );+	lstatus = slist_init_valuesc( &types, "URL", "DOI", "PMID", "PMC", "ARXIV", "JSTOR", "MRNUMBER", NULL );+	if ( lstatus!=SLIST_OK ) {+		*status = BIBL_ERR_MEMERR;+		return; 	} -	newstr_free( &doi_url );-}--static void-output_pmid( FILE *fp, fields *f )-{-	newstr pmid_url;-	int i, n;--	newstr_init( &pmid_url );--	n = fields_num( f );-	for ( i=0; i<n; ++i ) {-		if ( !fields_match_tag( f, i, "PMID" ) ) continue;-		pmid_to_url( f, i, "URL", &pmid_url );-		if ( pmid_url.len )-			fprintf( fp, "%%U %s\n", pmid_url.data );-	}+	*status = urls_merge_and_add( in, LEVEL_ANY, out, "%U", LEVEL_MAIN, &types ); -	newstr_free( &pmid_url );+	slist_free( &types ); }  static void-output_arxiv( FILE *fp, fields *f )+append_year( fields *in, fields *out, int *status ) {-	newstr arxiv_url;-	int i, n;--	newstr_init( &arxiv_url );+	int fstatus;+	char *year; -	n = fields_num( f );-	for ( i=0; i<n; ++i ) {-		if ( !fields_match_tag( f, i, "ARXIV" ) ) continue;-		arxiv_to_url( f, i, "URL", &arxiv_url );-		if ( arxiv_url.len )-			fprintf( fp, "%%U %s\n", arxiv_url.data );+	year = fields_findv_firstof( in, LEVEL_ANY, FIELDS_CHRP, "DATE:YEAR", "PARTDATE:YEAR", NULL );+	if ( year ) {+		fstatus = fields_add( out, "%D", year, LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR; 	}--	newstr_free( &arxiv_url ); }  static void-output_jstor( FILE *fp, fields *f )-{-	newstr jstor_url;-	int i, n;--	newstr_init( &jstor_url );--	n = fields_num( f );-	for ( i=0; i<n; ++i ) {-		if ( !fields_match_tag( f, i, "JSTOR" ) ) continue;-		jstor_to_url( f, i, "URL", &jstor_url );-		if ( jstor_url.len )-			fprintf( fp, "%%U %s\n", jstor_url.data );-	}--	newstr_free( &jstor_url );-}--static void-output_year( FILE *fp, fields *info, int level )-{-	char *year = fields_findv_firstof( info, level, FIELDS_CHRP,-			"YEAR", "PARTYEAR", NULL );-	if ( year )-		fprintf( fp, "%%D %s\n", year );-}--static void-output_monthday( FILE *fp, fields *info, int level )+append_monthday( fields *in, fields *out, int *status ) { 	char *months[12] = { "January", "February", "March", "April", 		"May", "June", "July", "August", "September", "October", 		"November", "December" };-	int m;-	char *month = fields_findv_firstof( info, level, FIELDS_CHRP,-			"MONTH", "PARTMONTH", NULL );-	char *day   = fields_findv_firstof( info, level, FIELDS_CHRP,-			"DAY", "PARTDAY", NULL );+	char *month, *day;+	int m, fstatus;+	str monday;++	str_init( &monday );+	month = fields_findv_firstof( in, LEVEL_ANY, FIELDS_CHRP, "DATE:MONTH", "PARTDATE:MONTH", NULL );+	day   = fields_findv_firstof( in, LEVEL_ANY, FIELDS_CHRP, "DATE:DAY",   "PARTDATE:DAY",   NULL ); 	if ( month || day ) {-		fprintf( fp, "%%8 " ); 		if ( month ) { 			m = atoi( month );-			if ( m>0 && m<13 ) fprintf( fp, "%s", months[m-1] );-			else fprintf( fp, "%s", month );+			if ( m>0 && m<13 ) str_strcpyc( &monday, months[m-1] );+			else str_strcpyc( &monday, month ); 		}-		if ( month && day ) fprintf( fp, " " );-		if ( day ) fprintf( fp, "%s", day );-		fprintf( fp, "\n" );+		if ( month && day ) str_strcatc( &monday, " " );+		if ( day ) str_strcatc( &monday, day );+		fstatus = fields_add( out, "%8", str_cstr( &monday ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR; 	}+	str_free( &monday ); }  static void-output_thesishint( FILE *fp, int type )+append_thesishint( int type, fields *out, int *status ) {-	if ( type==TYPE_MASTERSTHESIS )-		fprintf( fp, "%%9 Masters thesis\n" );-	else if ( type==TYPE_PHDTHESIS )-		fprintf( fp, "%%9 Ph.D. thesis\n" );-	else if ( type==TYPE_DIPLOMATHESIS )-		fprintf( fp, "%%9 Diploma thesis\n" );-	else if ( type==TYPE_DOCTORALTHESIS )-		fprintf( fp, "%%9 Doctoral thesis\n" );-	else if ( type==TYPE_HABILITATIONTHESIS )-		fprintf( fp, "%%9 Habilitation thesis\n" );+	int fstatus;++	if ( type==TYPE_MASTERSTHESIS ) {+		fstatus = fields_add( out, "%9", "Masters thesis", LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	}+	else if ( type==TYPE_PHDTHESIS ) {+		fstatus = fields_add( out, "%9", "Ph.D. thesis", LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	}+	else if ( type==TYPE_DIPLOMATHESIS ) {+		fstatus = fields_add( out, "%9", "Diploma thesis", LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	}+	else if ( type==TYPE_DOCTORALTHESIS ) {+		fstatus = fields_add( out, "%9", "Doctoral thesis", LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	}+	else if ( type==TYPE_HABILITATIONTHESIS ) {+		fstatus = fields_add( out, "%9", "Habilitation thesis", LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	} }  static void-output_easyall( FILE *fp, fields *info, char *tag, char *entag, int level )+append_easyall( fields *in, char *tag, char *entag, int level, fields *out, int *status ) {+	vplist_index i;+	int fstatus; 	vplist a;-	int i; 	vplist_init( &a );-	fields_findv_each( info, level, FIELDS_CHRP, &a, tag );-	for ( i=0; i<a.n; ++i )-		fprintf( fp, "%s %s\n", entag, (char *) vplist_get( &a, i ) );+	fields_findv_each( in, level, FIELDS_CHRP, &a, tag );+	for ( i=0; i<a.n; ++i ) {+		fstatus = fields_add( out, entag, (char *) vplist_get( &a, i ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	} 	vplist_free( &a ); }  static void-output_easy( FILE *fp, fields *info, char *tag, char *entag, int level )+append_easy( fields *in, char *tag, char *entag, int level, fields *out, int *status ) {-	char *value = fields_findv( info, level, FIELDS_CHRP, tag );-	if ( value ) fprintf( fp, "%s %s\n", entag, value );+	char *value;+	int fstatus;++	value = fields_findv( in, level, FIELDS_CHRP, tag );+	if ( value ) {+		fstatus = fields_add( out, entag, value, LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	} } -void-endout_write( fields *info, FILE *fp, param *p, unsigned long refnum )+static int+append_data( fields *in, fields *out, param *p, unsigned long refnum ) {-	int type;+	int added, type, status = BIBL_OK; -	fields_clearused( info );+	fields_clearused( in ); -	type = get_type( info, p, refnum );+	type = get_type( in, p, refnum ); -	output_type( fp, type, p );+	append_type( type, out, p, &status ); -	output_title( fp, info, "TITLE",      "SUBTITLE",      "%T", LEVEL_MAIN );-	output_title( fp, info, "SHORTTITLE", "SHORTSUBTITLE", "%!", LEVEL_MAIN );+	added = append_title( in, "TITLE",      "SUBTITLE",      "%T", LEVEL_MAIN, out, &status );+	if ( added==0 ) append_title( in, "SHORTTITLE", "SHORTSUBTITLE", "%T", LEVEL_MAIN, out, &status );+	else            append_title( in, "SHORTTITLE", "SHORTSUBTITLE", "%!", LEVEL_MAIN, out, &status ); -	output_people( fp, info, "AUTHOR",     "%A", LEVEL_MAIN );-	output_people( fp, info, "EDITOR",     "%E", LEVEL_MAIN );+	append_people( in, "AUTHOR",     "%A", LEVEL_MAIN, out, &status );+	append_people( in, "EDITOR",     "%E", LEVEL_MAIN, out, &status ); 	if ( type==TYPE_ARTICLE || type==TYPE_MAGARTICLE || type==TYPE_ELECTRONICARTICLE || type==TYPE_NEWSARTICLE )-		output_people( fp, info, "EDITOR", "%E", LEVEL_HOST );+		append_people( in, "EDITOR", "%E", LEVEL_HOST, out, &status ); 	else if ( type==TYPE_INBOOK || type==TYPE_INPROCEEDINGS ) {-		output_people( fp, info, "EDITOR", "%E", LEVEL_HOST );+		append_people( in, "EDITOR", "%E", LEVEL_HOST, out, &status ); 	} else {-		output_people( fp, info, "EDITOR", "%Y", LEVEL_HOST );+		append_people( in, "EDITOR", "%Y", LEVEL_HOST, out, &status ); 	}-	output_people( fp, info, "TRANSLATOR", "%H", LEVEL_ANY  );+	append_people( in, "TRANSLATOR", "%H", LEVEL_ANY,    out, &status  ); -	output_people( fp, info, "AUTHOR",     "%Y", LEVEL_SERIES );-	output_people( fp, info, "EDITOR",     "%Y", LEVEL_SERIES );+	append_people( in, "AUTHOR",     "%Y", LEVEL_SERIES, out, &status );+	append_people( in, "EDITOR",     "%Y", LEVEL_SERIES, out, &status );  	if ( type==TYPE_CASE )-		output_easy(    fp, info, "AUTHOR:CORP", "%I", LEVEL_MAIN );+		append_easy(    in, "AUTHOR:CORP", "%I", LEVEL_MAIN, out, &status ); 	else if ( type==TYPE_HEARING )-		output_easyall( fp, info, "AUTHOR:CORP", "%S", LEVEL_MAIN );+		append_easyall( in, "AUTHOR:CORP", "%S", LEVEL_MAIN, out, &status ); 	else if ( type==TYPE_NEWSARTICLE )-		output_people(  fp, info, "REPORTER",    "%A", LEVEL_MAIN );+		append_people(  in, "REPORTER",    "%A", LEVEL_MAIN, out, &status ); 	else if ( type==TYPE_COMMUNICATION )-		output_people(  fp, info, "RECIPIENT",   "%E", LEVEL_ANY  );+		append_people(  in, "RECIPIENT",   "%E", LEVEL_ANY,  out, &status  ); 	else {-		output_easyall( fp, info, "AUTHOR:CORP",     "%A", LEVEL_MAIN );-		output_easyall( fp, info, "AUTHOR:ASIS",     "%A", LEVEL_MAIN );-		output_easyall( fp, info, "EDITOR:CORP",     "%E", LEVEL_ANY  );-		output_easyall( fp, info, "EDITOR:ASIS",     "%E", LEVEL_ANY  );-		output_easyall( fp, info, "TRANSLATOR:CORP", "%H", LEVEL_ANY  );-		output_easyall( fp, info, "TRANSLATOR:ASIS", "%H", LEVEL_ANY  );+		append_easyall( in, "AUTHOR:CORP",     "%A", LEVEL_MAIN, out, &status );+		append_easyall( in, "AUTHOR:ASIS",     "%A", LEVEL_MAIN, out, &status );+		append_easyall( in, "EDITOR:CORP",     "%E", LEVEL_ANY,  out, &status  );+		append_easyall( in, "EDITOR:ASIS",     "%E", LEVEL_ANY,  out, &status  );+		append_easyall( in, "TRANSLATOR:CORP", "%H", LEVEL_ANY,  out, &status  );+		append_easyall( in, "TRANSLATOR:ASIS", "%H", LEVEL_ANY,  out, &status  ); 	} -	if ( type==TYPE_ARTICLE || type==TYPE_MAGARTICLE || type==TYPE_ELECTRONICARTICLE || type==TYPE_NEWSARTICLE )-		output_title( fp, info, "TITLE", "SUBTITLE", "%J", LEVEL_HOST );+	if ( type==TYPE_ARTICLE || type==TYPE_MAGARTICLE || type==TYPE_ELECTRONICARTICLE || type==TYPE_NEWSARTICLE ) {+		added = append_title( in, "TITLE", "SUBTITLE", "%J", LEVEL_HOST, out, &status );+		if ( added==0 ) append_title( in, "SHORTTITLE", "SHORTSUBTITLE", "%J", LEVEL_HOST, out, &status );+	}+ 	else if ( type==TYPE_INBOOK || type==TYPE_INPROCEEDINGS ) {-		output_title( fp, info, "TITLE", "SUBTITLE", "%B", LEVEL_HOST );-	} else {-		output_title( fp, info, "TITLE", "SUBTITLE", "%S", LEVEL_HOST );+		added = append_title( in, "TITLE", "SUBTITLE", "%B", LEVEL_HOST, out, &status );+		if ( added==0 ) append_title( in, "SHORTTITLE", "SHORTSUBTITLE", "%B", LEVEL_HOST, out, &status ); 	} +	else {+		added = append_title( in, "TITLE", "SUBTITLE", "%S", LEVEL_HOST, out, &status );+		if ( added==0 ) append_title( in, "SHORTTITLE", "SHORTSUBTITLE", "%S", LEVEL_HOST, out, &status );+	}+ 	if ( type!=TYPE_CASE && type!=TYPE_HEARING ) {-		output_title( fp, info, "TITLE", "SUBTITLE", "%S", LEVEL_SERIES );+		append_title( in, "TITLE", "SUBTITLE", "%S", LEVEL_SERIES, out, &status ); 	} -	output_year( fp, info, LEVEL_ANY );-	output_monthday( fp, info, LEVEL_ANY );+	append_year    ( in, out, &status );+	append_monthday( in, out, &status ); -	output_easy( fp, info, "VOLUME",             "%V", LEVEL_ANY );-	output_easy( fp, info, "ISSUE",              "%N", LEVEL_ANY );-	output_easy( fp, info, "NUMBER",             "%N", LEVEL_ANY );-	output_easy( fp, info, "EDITION",            "%7", LEVEL_ANY );-	output_easy( fp, info, "PUBLISHER",          "%I", LEVEL_ANY );-	output_easy( fp, info, "ADDRESS",            "%C", LEVEL_ANY );-	output_easy( fp, info, "DEGREEGRANTOR",      "%C", LEVEL_ANY );-	output_easy( fp, info, "DEGREEGRANTOR:CORP", "%C", LEVEL_ANY );-	output_easy( fp, info, "DEGREEGRANTOR:ASIS", "%C", LEVEL_ANY );-	output_easy( fp, info, "SERIALNUMBER",       "%@", LEVEL_ANY );-	output_easy( fp, info, "ISSN",               "%@", LEVEL_ANY );-	output_easy( fp, info, "ISBN",               "%@", LEVEL_ANY );-	output_easy( fp, info, "LANGUAGE",           "%G", LEVEL_ANY );-	output_easy( fp, info, "REFNUM",             "%F", LEVEL_ANY );-	output_easyall( fp, info, "NOTES",           "%O", LEVEL_ANY );-	output_easy( fp, info, "ABSTRACT",           "%X", LEVEL_ANY );-	output_easy( fp, info, "CLASSIFICATION",     "%L", LEVEL_ANY );-	output_easyall( fp, info, "KEYWORD",         "%K", LEVEL_ANY );-	output_easyall( fp, info, "NGENRE",          "%9", LEVEL_ANY );-	output_thesishint( fp, type );-	output_easyall( fp, info, "DOI",             "%R", LEVEL_ANY );-	output_easyall( fp, info, "URL",             "%U", LEVEL_ANY ); -	output_easyall( fp, info, "FILEATTACH",      "%U", LEVEL_ANY ); -	output_doi( fp, info );-	output_pmid( fp, info );-	output_arxiv( fp, info );-	output_jstor( fp, info );-	output_pages( fp, info );+	append_easy    ( in, "VOLUME",             "%V", LEVEL_ANY, out, &status );+	append_easy    ( in, "ISSUE",              "%N", LEVEL_ANY, out, &status );+	append_easy    ( in, "NUMBER",             "%N", LEVEL_ANY, out, &status );+	append_easy    ( in, "EDITION",            "%7", LEVEL_ANY, out, &status );+	append_easy    ( in, "PUBLISHER",          "%I", LEVEL_ANY, out, &status );+	append_easy    ( in, "ADDRESS",            "%C", LEVEL_ANY, out, &status );+	append_easy    ( in, "DEGREEGRANTOR",      "%C", LEVEL_ANY, out, &status );+	append_easy    ( in, "DEGREEGRANTOR:CORP", "%C", LEVEL_ANY, out, &status );+	append_easy    ( in, "DEGREEGRANTOR:ASIS", "%C", LEVEL_ANY, out, &status );+	append_easy    ( in, "SERIALNUMBER",       "%@", LEVEL_ANY, out, &status );+	append_easy    ( in, "ISSN",               "%@", LEVEL_ANY, out, &status );+	append_easy    ( in, "ISBN",               "%@", LEVEL_ANY, out, &status );+	append_easy    ( in, "LANGUAGE",           "%G", LEVEL_ANY, out, &status );+	append_easy    ( in, "REFNUM",             "%F", LEVEL_ANY, out, &status );+	append_easyall ( in, "NOTES",              "%O", LEVEL_ANY, out, &status );+	append_easy    ( in, "ABSTRACT",           "%X", LEVEL_ANY, out, &status );+	append_easy    ( in, "CLASSIFICATION"   ,  "%L", LEVEL_ANY, out, &status );+	append_easyall ( in, "KEYWORD",            "%K", LEVEL_ANY, out, &status );+	append_easyall ( in, "NGENRE",             "%9", LEVEL_ANY, out, &status );+	append_thesishint( type, out, &status );+	append_easyall ( in, "DOI",                "%R", LEVEL_ANY, out, &status );+	append_easyall ( in, "URL",                "%U", LEVEL_ANY, out, &status );+	append_easyall ( in, "FILEATTACH",         "%U", LEVEL_ANY, out, &status );+	append_urls    ( in, out, &status );+	append_pages   ( in, out, &status );++	return status;+}++static void+output( FILE *fp, fields *out )+{+	int i;++	for ( i=0; i<out->n; ++i ) {+		fprintf( fp, "%s %s\n",+			(char*) fields_tag( out, i, FIELDS_CHRP ),+			(char*) fields_value( out, i, FIELDS_CHRP )+		);+	}+ 	fprintf( fp, "\n" ); 	fflush( fp ); } -void+static int+endout_write( fields *in, FILE *fp, param *p, unsigned long refnum )+{+	int status;+	fields out;++	fields_init( &out );+	status = append_data( in, &out, p, refnum );+	if ( status==BIBL_OK ) output( fp, &out );+	fields_free( &out );++	return status;+}++static void endout_writeheader( FILE *outptr, param *p ) { 	if ( p->utf8bom ) utf8_writebom( outptr );
− bibutils/endout.h
@@ -1,22 +0,0 @@-/*- * endout.h- *- * Copyright (c) Chris Putnam 2005-2013- *- * Source code released under the GPL version 2- *- */-#ifndef ENDOUT_H-#define ENDOUT_H--#include <stdio.h>-#include "bibutils.h"--extern void endout_write( fields *info, FILE *fp, param *p, -		unsigned long refnum );-extern void endout_writeheader( FILE *outptr, param *p );--extern void endout_initparams( param *p, const char *progname );---#endif
bibutils/endtypes.c view
@@ -1,7 +1,7 @@ /*  * endtypes.c  *- * Copyright (c) Chris Putnam 2003-2013+ * Copyright (c) Chris Putnam 2003-2017  *  * Program and source code released under the GPL version 2  *@@ -18,7 +18,7 @@ 	{ "%A", "AUTHOR",    PERSON, LEVEL_MAIN }, 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },-	{ "%D", "YEAR",      SIMPLE, LEVEL_MAIN },+	{ "%D", "DATE:YEAR",      SIMPLE, LEVEL_MAIN }, 	{ "%T", "TITLE" ,    TITLE,  LEVEL_MAIN }, 	{ "%J", "TITLE",     TITLE,  LEVEL_HOST }, /* for refer formats */ 	{ "%E", "2ND_AUTHOR",PERSON, LEVEL_MAIN },@@ -33,7 +33,7 @@ 	{ "%Y", "AUTHOR",   PERSON, LEVEL_SERIES }, 	{ "%S", "TITLE",     TITLE, LEVEL_SERIES }, 	{ "%7", "EDITION",      SIMPLE, LEVEL_MAIN },-	{ "%8", "MONTH",    DATE,   LEVEL_MAIN },+	{ "%8", "DATE:MONTH",    DATE,   LEVEL_MAIN }, 	{ "%9", "GENRE",        SIMPLE, LEVEL_MAIN }, 	{ "%?", "SUB_AUTHOR",   PERSON, LEVEL_MAIN }, /* subsidiary-authors */ 	{ "%!", "SHORTTITLE",   TITLE,  LEVEL_MAIN },@@ -53,7 +53,7 @@ 	{ "%K", "KEYWORD",      SIMPLE, LEVEL_MAIN },  	{ "%X", "ABSTRACT",     SIMPLE, LEVEL_MAIN }, 	{ "%O", "NOTES",        NOTES, LEVEL_MAIN },-	{ "%U", "URL",          SIMPLE, LEVEL_MAIN },+	{ "%U", "URL",          URL,    LEVEL_MAIN }, 	{ "%>", "PDFLINK",      SIMPLE, LEVEL_MAIN }, 	{ "%Z", "NOTES",        SIMPLE, LEVEL_MAIN }, 	{ "%W", "PHYSICALLOC",  SIMPLE, LEVEL_MAIN },  /* physical location */@@ -70,7 +70,7 @@ 	{ "%A", "AUTHOR",       PERSON,   LEVEL_MAIN }, 	{ "%H", "TRANSLATOR",   PERSON,   LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE",SIMPLE, LEVEL_MAIN },-	{ "%D", "PARTYEAR",     SIMPLE,   LEVEL_MAIN },+	{ "%D", "PARTDATE:YEAR",     SIMPLE,   LEVEL_MAIN }, 	{ "%T", "TITLE" ,       TITLE,    LEVEL_MAIN }, 	{ "%J", "TITLE",        TITLE,    LEVEL_HOST }, /* journal title */ 	{ "%B", "TITLE",        TITLE,    LEVEL_HOST }, /* journal title */@@ -79,7 +79,7 @@ 	{ "%N", "ISSUE",        SIMPLE,   LEVEL_MAIN }, 	{ "%P", "PAGES",        PAGES,    LEVEL_MAIN }, 	{ "%I", "PUBLISHER",    SIMPLE,   LEVEL_HOST }, -	{ "%8", "PARTMONTH",    DATE,     LEVEL_MAIN },+	{ "%8", "PARTDATE:MONTH",    DATE,     LEVEL_MAIN }, 	{ "%9", "GENRE",        SIMPLE,   LEVEL_MAIN }, 	{ "%!", "SHORTTITLE",   TITLE,    LEVEL_MAIN }, 	{ "%@", "SERIALNUMBER", SERIALNO, LEVEL_HOST },@@ -91,7 +91,7 @@ 	{ "%F", "REFNUM",       SIMPLE,   LEVEL_MAIN }, 	{ "%K", "KEYWORD",      SIMPLE,   LEVEL_MAIN }, 	{ "%X", "ABSTRACT",     SIMPLE,   LEVEL_MAIN },-	{ "%U", "URL",          SIMPLE,   LEVEL_MAIN },+	{ "%U", "URL",          URL,      LEVEL_MAIN }, 	{ "%O", "NOTES",        NOTES,    LEVEL_MAIN }, 	{ "%Z", "NOTES",        NOTES,    LEVEL_MAIN }, 	{ "%1", "CUSTOM1",      NOTES,    LEVEL_MAIN },@@ -120,7 +120,7 @@ 	{ "%A", "AUTHOR",    PERSON,  LEVEL_MAIN }, 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },-	{ "%D", "PARTYEAR",  SIMPLE,  LEVEL_MAIN },+	{ "%D", "PARTDATE:YEAR",  SIMPLE,  LEVEL_MAIN }, 	{ "%T", "TITLE",     TITLE,   LEVEL_MAIN }, 	{ "%J", "TITLE",     TITLE,   LEVEL_HOST }, /* magazine name */ 	{ "%B", "TITLE",     TITLE,   LEVEL_HOST }, /* magazine name */@@ -129,7 +129,7 @@ 	{ "%N", "ISSUE",     SIMPLE,  LEVEL_MAIN }, 	{ "%P", "PAGES",     PAGES,   LEVEL_MAIN }, 	{ "%I", "PUBLISHER", SIMPLE,    LEVEL_HOST }, -	{ "%8", "PARTMONTH", DATE,    LEVEL_MAIN },+	{ "%8", "PARTDATE:MONTH", DATE,    LEVEL_MAIN }, 	{ "%!", "SHORTTITLE",TITLE,   LEVEL_MAIN }, 	{ "%@", "SERIALNUMBER",      SERIALNO,LEVEL_HOST }, 	{ "%(", "TITLE",     SIMPLE,  LEVEL_ORIG }, /* original pub */@@ -140,7 +140,7 @@ 	{ "%F", "REFNUM",    SIMPLE,  LEVEL_MAIN }, 	{ "%K", "KEYWORD",   SIMPLE,  LEVEL_MAIN },  	{ "%X", "ABSTRACT",  SIMPLE,  LEVEL_MAIN },-	{ "%U", "URL",       SIMPLE,  LEVEL_MAIN },+	{ "%U", "URL",       URL,     LEVEL_MAIN }, 	{ "%O", "NOTES",     SIMPLE,  LEVEL_MAIN }, 	{ "%Z", "NOTES",     SIMPLE,  LEVEL_MAIN }, 	{ "%1", "CUSTOM1",      NOTES,    LEVEL_MAIN },@@ -168,7 +168,7 @@ 	{ "%A", "REPORTER",  PERSON,  LEVEL_MAIN }, 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },-	{ "%D", "PARTYEAR",  SIMPLE,  LEVEL_MAIN },+	{ "%D", "PARTDATE:YEAR",  SIMPLE,  LEVEL_MAIN }, 	{ "%T", "TITLE" ,    TITLE,   LEVEL_MAIN }, 	{ "%J", "TITLE",     TITLE,   LEVEL_HOST }, /* newspaper name */ 	{ "%B", "TITLE",     TITLE,   LEVEL_HOST }, /* newspaper name */@@ -177,7 +177,7 @@ 	{ "%N", "ISSUE",     SIMPLE,  LEVEL_MAIN }, 	{ "%P", "PAGES",     PAGES,   LEVEL_MAIN }, 	{ "%7", "EDITION",   SIMPLE,  LEVEL_MAIN },-	{ "%8", "PARTMONTH", DATE,    LEVEL_MAIN },+	{ "%8", "PARTDATE:MONTH", DATE,    LEVEL_MAIN }, 	{ "%!", "SHORTTITLE",TITLE,   LEVEL_MAIN }, 	{ "%@", "SERIALNUMBER",      SERIALNO, LEVEL_MAIN }, 	{ "%(", "TITLE",     SIMPLE, LEVEL_ORIG }, /* original pub */@@ -188,7 +188,7 @@ 	{ "%F", "REFNUM",    SIMPLE,  LEVEL_MAIN }, 	{ "%K", "KEYWORD",   SIMPLE,  LEVEL_MAIN },  	{ "%X", "ABSTRACT",  SIMPLE,  LEVEL_MAIN },-	{ "%U", "URL",       SIMPLE,  LEVEL_MAIN },+	{ "%U", "URL",       URL,     LEVEL_MAIN }, 	{ "%O", "NOTES",     SIMPLE,  LEVEL_MAIN }, 	{ "%Z", "NOTES",     SIMPLE,  LEVEL_MAIN }, 	{ "%1", "CUSTOM1",      NOTES,    LEVEL_MAIN },@@ -215,7 +215,7 @@ 	{ "%A", "AUTHOR",    PERSON,    LEVEL_MAIN }, 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },-	{ "%D", "YEAR",      SIMPLE,    LEVEL_MAIN },+	{ "%D", "DATE:YEAR",      SIMPLE,    LEVEL_MAIN }, 	{ "%T", "TITLE" ,    TITLE,     LEVEL_MAIN }, 	{ "%E", "AUTHOR",    PERSON,    LEVEL_HOST }, /* SERIES_AUTHOR */ 	{ "%B", "TITLE",     TITLE,     LEVEL_HOST }, /* SERIES_TITLE */@@ -225,7 +225,7 @@ 	{ "%V", "VOLUME" ,   SIMPLE,    LEVEL_MAIN }, 	{ "%N", "NUMBER",    SIMPLE,    LEVEL_MAIN }, 	{ "%6", "NUMVOLUMES",SIMPLE,    LEVEL_MAIN },-	{ "%P", "TOTALPAGES", SIMPLE,LEVEL_MAIN },+	{ "%P", "PAGES:TOTAL", SIMPLE,LEVEL_MAIN }, 	{ "%7", "EDITION",   SIMPLE,    LEVEL_MAIN }, 	{ "%?", "TRANSLATOR",PERSON,    LEVEL_MAIN }, 	{ "%!", "SHORTTITLE",TITLE,     LEVEL_MAIN },@@ -244,7 +244,7 @@ 	{ "%K", "KEYWORD",   SIMPLE,    LEVEL_MAIN },  	{ "%X", "ABSTRACT",  SIMPLE,    LEVEL_MAIN }, 	{ "%O", "NOTES",     NOTES,     LEVEL_MAIN },-	{ "%U", "URL",       SIMPLE,    LEVEL_MAIN },+	{ "%U", "URL",       URL,       LEVEL_MAIN }, 	{ "%Z", "NOTES",     SIMPLE,    LEVEL_MAIN }, 	{ "%+", "AUTHORADDRESS",SIMPLE, LEVEL_MAIN }, 	{ "%>", "PDFLINK",      SIMPLE, LEVEL_MAIN },@@ -264,7 +264,7 @@ 	{ "%A", "AUTHOR",    PERSON,    LEVEL_MAIN }, 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },-	{ "%D", "YEAR",      SIMPLE,    LEVEL_HOST },+	{ "%D", "DATE:YEAR",      SIMPLE,    LEVEL_HOST }, 	{ "%T", "TITLE" ,    TITLE,     LEVEL_MAIN }, 	{ "%E", "EDITOR",    PERSON,    LEVEL_HOST }, /* editor for book */ 	{ "%B", "TITLE",     TITLE,     LEVEL_HOST }, /* book title */@@ -294,7 +294,7 @@ 	{ "%K", "KEYWORD",   SIMPLE,    LEVEL_MAIN },  	{ "%X", "ABSTRACT",  SIMPLE,    LEVEL_MAIN }, 	{ "%O", "NOTES",     NOTES,     LEVEL_MAIN },-	{ "%U", "URL",       SIMPLE,    LEVEL_MAIN },+	{ "%U", "URL",       URL,       LEVEL_MAIN }, 	{ "%Z", "NOTES",     SIMPLE,    LEVEL_MAIN }, 	{ "%+", "AUTHORADDRESS",SIMPLE, LEVEL_MAIN }, 	{ "%>", "PDFLINK",      SIMPLE, LEVEL_MAIN },@@ -315,7 +315,7 @@ 	{ "%A", "EDITOR",    PERSON,    LEVEL_MAIN }, 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },-	{ "%D", "YEAR",      SIMPLE,    LEVEL_MAIN },+	{ "%D", "DATE:YEAR",      SIMPLE,    LEVEL_MAIN }, 	{ "%T", "TITLE" ,    TITLE,     LEVEL_MAIN }, 	{ "%E", "EDITOR",    PERSON,    LEVEL_HOST }, /* SERIES_EDITOR */ 	{ "%B", "TITLE",     TITLE,     LEVEL_HOST }, /* SERIES_TITLE */@@ -324,7 +324,7 @@ 	{ "%N", "NUMBER",    SIMPLE,    LEVEL_MAIN }, 	{ "%V", "VOLUME" ,   SIMPLE,    LEVEL_MAIN }, 	{ "%6", "NUMVOLUMES",SIMPLE,    LEVEL_HOST },-	{ "%P", "TOTALPAGES", SIMPLE,LEVEL_MAIN },+	{ "%P", "PAGES:TOTAL", SIMPLE,LEVEL_MAIN }, 	{ "%7", "EDITION",   SIMPLE,    LEVEL_MAIN }, 	{ "%?", "TRANSLATOR",PERSON,    LEVEL_MAIN }, 	{ "%!", "SHORTTITLE",TITLE,     LEVEL_MAIN },@@ -343,7 +343,7 @@ 	{ "%K", "KEYWORD",   SIMPLE,    LEVEL_MAIN },  	{ "%X", "ABSTRACT",  SIMPLE,    LEVEL_MAIN }, 	{ "%O", "NOTES",     NOTES,     LEVEL_MAIN },-	{ "%U", "URL",       SIMPLE,    LEVEL_MAIN },+	{ "%U", "URL",       URL,       LEVEL_MAIN }, 	{ "%Z", "NOTES",     NOTES,     LEVEL_MAIN }, 	{ "%+", "AUTHORADDRESS",SIMPLE, LEVEL_MAIN }, 	{ "%>", "PDFLINK",      SIMPLE, LEVEL_MAIN },@@ -363,13 +363,13 @@ 	{ "%A", "AUTHOR",    PERSON,  LEVEL_MAIN }, 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },-	{ "%D", "YEAR",      SIMPLE,  LEVEL_MAIN },+	{ "%D", "DATE:YEAR",      SIMPLE,  LEVEL_MAIN }, 	{ "%T", "TITLE",     TITLE,   LEVEL_MAIN }, 	{ "%B", "TITLE",     TITLE,   LEVEL_HOST }, /* COLLECTION_TITLE */ 	{ "%C", "ADDRESS",   SIMPLE,  LEVEL_MAIN }, 	{ "%N", "NUMBER",    SIMPLE,  LEVEL_MAIN }, 	{ "%P", "PAGES",     PAGES,   LEVEL_MAIN },-	{ "%8", "MONTH", DATE,    LEVEL_MAIN },+	{ "%8", "DATE:MONTH", DATE,    LEVEL_MAIN }, 	{ "%9", "GENRE",     SIMPLE,  LEVEL_MAIN }, 	{ "%!", "SHORTTITLE",TITLE,   LEVEL_MAIN }, 	{ "%M", "ACCESSNUM", SIMPLE,  LEVEL_MAIN },@@ -378,7 +378,7 @@ 	{ "%K", "KEYWORD",   SIMPLE,  LEVEL_MAIN },  	{ "%X", "ABSTRACT",  SIMPLE,  LEVEL_MAIN }, 	{ "%O", "NOTES",     NOTES,   LEVEL_MAIN },-	{ "%U", "URL",       SIMPLE,  LEVEL_MAIN },+	{ "%U", "URL",       URL,     LEVEL_MAIN }, 	{ "%Z", "NOTES",     NOTES,   LEVEL_MAIN }, 	{ "%1", "CUSTOM1",   NOTES,   LEVEL_MAIN }, 	{ "%2", "CUSTOM2",   NOTES,   LEVEL_MAIN },@@ -403,13 +403,13 @@ 	{ "%A", "AUTHOR",    PERSON,  LEVEL_MAIN }, 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },-	{ "%D", "YEAR",      SIMPLE,  LEVEL_MAIN },+	{ "%D", "DATE:YEAR",      SIMPLE,  LEVEL_MAIN }, 	{ "%T", "TITLE" ,    TITLE,   LEVEL_MAIN }, 	{ "%E", "RECIPIENT", PERSON,  LEVEL_MAIN }, 	{ "%C", "ADDRESS",   SIMPLE,  LEVEL_MAIN }, 	{ "%V", "VOLUME",    SIMPLE,  LEVEL_MAIN }, 	{ "%I", "PUBLISHER", SIMPLE,  LEVEL_MAIN },-	{ "%8", "MONTH", DATE,    LEVEL_MAIN },+	{ "%8", "DATE:MONTH", DATE,    LEVEL_MAIN }, 	{ "%9", "GENRE",     SIMPLE,  LEVEL_MAIN }, 	{ "%!", "SHORTTITLE",TITLE,   LEVEL_MAIN }, 	{ "%M", "ACCESSNUM", SIMPLE,  LEVEL_MAIN },@@ -418,7 +418,7 @@ 	{ "%K", "KEYWORD",   SIMPLE,  LEVEL_MAIN },  	{ "%X", "ABSTRACT",  SIMPLE,  LEVEL_MAIN }, 	{ "%O", "NOTES",     NOTES,   LEVEL_MAIN },-	{ "%U", "URL",       SIMPLE,  LEVEL_MAIN },+	{ "%U", "URL",       URL,     LEVEL_MAIN }, 	{ "%Z", "NOTES",     NOTES,   LEVEL_MAIN }, 	{ "%1", "CUSTOM1",   NOTES,   LEVEL_MAIN }, 	{ "%2", "CUSTOM2",   NOTES,   LEVEL_MAIN },@@ -442,7 +442,7 @@ 	{ "%A", "AUTHOR",    PERSON,  LEVEL_MAIN }, 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },-	{ "%D", "YEAR",      SIMPLE,  LEVEL_HOST },+	{ "%D", "DATE:YEAR",      SIMPLE,  LEVEL_HOST }, 	{ "%T", "TITLE" ,    TITLE,   LEVEL_MAIN }, 	{ "%E", "EDITOR",    PERSON,  LEVEL_MAIN }, 	{ "%B", "TITLE",     SIMPLE,  LEVEL_HOST }, @@ -455,7 +455,7 @@ 	{ "%Y", "EDITOR",    PERSON,  LEVEL_SERIES }, 	{ "%S", "TITLE",     TITLE,   LEVEL_SERIES }, 	{ "%7", "EDITION",   SIMPLE,  LEVEL_HOST },-	{ "%8", "MONTH", DATE,    LEVEL_MAIN },+	{ "%8", "DATE:MONTH", DATE,    LEVEL_MAIN }, 	{ "%!", "SHORTTITLE",TITLE,   LEVEL_MAIN }, 	{ "%1", "CUSTOM1",   NOTES,   LEVEL_MAIN }, 	{ "%2", "CUSTOM2",   NOTES,   LEVEL_MAIN },@@ -469,7 +469,7 @@ 	{ "%K", "KEYWORD",   SIMPLE,  LEVEL_MAIN },  	{ "%X", "ABSTRACT",  SIMPLE,  LEVEL_MAIN }, 	{ "%O", "NOTES",     NOTES,   LEVEL_MAIN },-	{ "%U", "URL",       SIMPLE,  LEVEL_MAIN },+	{ "%U", "URL",       URL,     LEVEL_MAIN }, 	{ "%Z", "NOTES",     NOTES,   LEVEL_MAIN }, 	{ "%+", "AUTHORADDRESS",SIMPLE,LEVEL_MAIN}, 	{ "%>", "PDFLINK",      SIMPLE, LEVEL_MAIN },@@ -488,7 +488,7 @@ 	{ "%A", "AUTHOR",       PERSON,   LEVEL_MAIN }, 	{ "%H", "TRANSLATOR",   PERSON,   LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE",SIMPLE, LEVEL_MAIN },-	{ "%D", "PARTYEAR",     SIMPLE,   LEVEL_MAIN },+	{ "%D", "PARTDATE:YEAR",     SIMPLE,   LEVEL_MAIN }, 	{ "%T", "TITLE" ,       TITLE,    LEVEL_MAIN }, 	{ "%J", "TITLE",        TITLE,    LEVEL_HOST }, /* journal title */ 	{ "%B", "TITLE",        TITLE,    LEVEL_HOST }, /* journal title */@@ -497,7 +497,7 @@ 	{ "%N", "ISSUE",        SIMPLE,   LEVEL_MAIN }, 	{ "%P", "PAGES",        PAGES,    LEVEL_MAIN }, 	{ "%I", "PUBLISHER",    SIMPLE,   LEVEL_HOST }, -	{ "%8", "PARTMONTH",    DATE,     LEVEL_MAIN },+	{ "%8", "PARTDATE:MONTH",    DATE,     LEVEL_MAIN }, 	{ "%9", "GENRE",        SIMPLE,   LEVEL_MAIN }, 	{ "%!", "SHORTTITLE",   TITLE,    LEVEL_MAIN }, 	{ "%@", "SERIALNUMBER", SERIALNO, LEVEL_HOST },@@ -509,7 +509,7 @@ 	{ "%F", "REFNUM",       SIMPLE,   LEVEL_MAIN }, 	{ "%K", "KEYWORD",      SIMPLE,   LEVEL_MAIN }, 	{ "%X", "ABSTRACT",     SIMPLE,   LEVEL_MAIN },-	{ "%U", "URL",          SIMPLE,   LEVEL_MAIN },+	{ "%U", "URL",          URL,      LEVEL_MAIN }, 	{ "%O", "NOTES",        NOTES,    LEVEL_MAIN }, 	{ "%Z", "NOTES",        NOTES,    LEVEL_MAIN }, 	{ "%1", "CUSTOM1",      NOTES,    LEVEL_MAIN },@@ -535,15 +535,15 @@ 	{ "%A", "AUTHOR",       PERSON, LEVEL_MAIN }, 	{ "%H", "TRANSLATOR",   PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },-	{ "%D", "YEAR",         SIMPLE, LEVEL_MAIN },+	{ "%D", "DATE:YEAR",         SIMPLE, LEVEL_MAIN }, 	{ "%T", "TITLE" ,       TITLE,  LEVEL_MAIN }, 	{ "%B", "ACADEMIC_DEPARTMENT", SIMPLE, LEVEL_MAIN }, 	{ "%C", "ADDRESS",      SIMPLE, LEVEL_MAIN }, 	{ "%I", "PUBLISHER",    SIMPLE, LEVEL_MAIN },  	{ "%V", "VOLUME",       SIMPLE, LEVEL_MAIN },-	{ "%P", "NUMPAGES",     PAGES,  LEVEL_MAIN },+	{ "%P", "PAGES:TOTAL",  PAGES,  LEVEL_MAIN }, 	{ "%9", "GENRE",        SIMPLE, LEVEL_MAIN }, /* thesis type */-	{ "%8", "MONTH",        DATE,   LEVEL_MAIN },+	{ "%8", "DATE:MONTH",   DATE,   LEVEL_MAIN }, 	{ "%!", "SHORTTITLE",   TITLE,  LEVEL_MAIN }, 	{ "%1", "CUSTOM1",      NOTES,  LEVEL_MAIN }, 	{ "%2", "CUSTOM2",      NOTES,  LEVEL_MAIN },@@ -557,7 +557,7 @@ 	{ "%K", "KEYWORD",      SIMPLE, LEVEL_MAIN },  	{ "%X", "ABSTRACT",     SIMPLE, LEVEL_MAIN }, 	{ "%O", "NOTES",        NOTES,  LEVEL_MAIN },-	{ "%U", "URL",          SIMPLE, LEVEL_MAIN },+	{ "%U", "URL",          URL,    LEVEL_MAIN }, 	{ "%Z", "NOTES",        NOTES,  LEVEL_MAIN }, 	{ "%+", "AUTHORADDRESS",SIMPLE, LEVEL_MAIN }, 	{ "%>", "PDFLINK",      SIMPLE, LEVEL_MAIN },@@ -576,7 +576,7 @@ 	{ "%A", "AUTHOR",    PERSON   , LEVEL_MAIN }, 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },-	{ "%D", "YEAR",      SIMPLE   , LEVEL_MAIN },+	{ "%D", "DATE:YEAR",      SIMPLE   , LEVEL_MAIN }, 	{ "%T", "TITLE" ,    TITLE    , LEVEL_MAIN }, 	{ "%C", "ADDRESS",   SIMPLE   , LEVEL_MAIN }, 	{ "%I", "PUBLISHER", SIMPLE   , LEVEL_MAIN },@@ -588,7 +588,7 @@ 	{ "%K", "KEYWORD",   SIMPLE   , LEVEL_MAIN },  	{ "%X", "ABSTRACT",  SIMPLE   , LEVEL_MAIN }, 	{ "%O", "NOTES",     SIMPLE   , LEVEL_MAIN },-	{ "%U", "URL",       SIMPLE   , LEVEL_MAIN },+	{ "%U", "URL",       URL,       LEVEL_MAIN }, 	{ "%Z", "NOTES",     SIMPLE   , LEVEL_MAIN }, 	{ "%1", "COMPUTER",  SIMPLE   , LEVEL_MAIN }, 	{ "%2", "CUSTOM2",   SIMPLE   , LEVEL_MAIN },@@ -613,14 +613,14 @@ 	{ "%A", "WRITER",    PERSON   , LEVEL_MAIN }, 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },-	{ "%D", "YEAR",      SIMPLE   , LEVEL_MAIN },+	{ "%D", "DATE:YEAR",      SIMPLE   , LEVEL_MAIN }, 	{ "%T", "TITLE" ,    TITLE    , LEVEL_MAIN }, 	{ "%B", "TITLE",     TITLE    , LEVEL_HOST }, /* COLLECTION_TITLE */ 	{ "%C", "ADDRESS",   SIMPLE   , LEVEL_MAIN }, 	{ "%I", "PUBLISHER", SIMPLE   , LEVEL_MAIN }, 	{ "%V", "EXTENTOFWORK",     SIMPLE   , LEVEL_MAIN }, 	{ "%N", "NUMBER",    SIMPLE   , LEVEL_MAIN },-	{ "%8", "MONTH", DATE     , LEVEL_MAIN },+	{ "%8", "DATE:MONTH", DATE     , LEVEL_MAIN }, 	{ "%9", "GENRE",     SIMPLE   , LEVEL_MAIN }, 	{ "%?", "PERFORMER", PERSON   , LEVEL_MAIN }, 	{ "%!", "SHORTTITLE",TITLE    , LEVEL_MAIN },@@ -630,7 +630,7 @@ 	{ "%K", "KEYWORD",   SIMPLE   , LEVEL_MAIN },  	{ "%X", "ABSTRACT",  SIMPLE   , LEVEL_MAIN }, 	{ "%O", "NOTES",     NOTES,     LEVEL_MAIN },-	{ "%U", "URL",       SIMPLE   , LEVEL_MAIN },+	{ "%U", "URL",       URL,       LEVEL_MAIN }, 	{ "%Z", "NOTES",     NOTES,     LEVEL_MAIN }, 	{ "%1", "CUSTOM1",   NOTES,     LEVEL_MAIN }, 	{ "%2", "CUSTOM2",   NOTES,     LEVEL_MAIN },@@ -654,14 +654,14 @@ 	{ "%A", "AUTHOR",       PERSON,   LEVEL_MAIN }, 	{ "%H", "TRANSLATOR",   PERSON,   LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },-	{ "%D", "YEAR",         SIMPLE,   LEVEL_MAIN },+	{ "%D", "DATE:YEAR",         SIMPLE,   LEVEL_MAIN }, 	{ "%T", "TITLE" ,       TITLE,    LEVEL_MAIN }, 	{ "%E", "DIRECTOR",     PERSON,   LEVEL_MAIN }, 	{ "%B", "TITLE",        TITLE,    LEVEL_HOST }, /* SERIES_TITLE */ 	{ "%C", "ADDRESS",      SIMPLE,   LEVEL_MAIN }, 	{ "%I", "PUBLISHER",    SIMPLE,   LEVEL_MAIN }, 	{ "%Y", "PRODUCER",     PERSON,   LEVEL_MAIN },-	{ "%8", "MONTH",        DATE,     LEVEL_MAIN },+	{ "%8", "DATE:MONTH",        DATE,     LEVEL_MAIN }, 	{ "%9", "GENRE",        SIMPLE,   LEVEL_MAIN }, 	{ "%!", "SHORTTITLE",   TITLE,    LEVEL_MAIN }, 	{ "%@", "SERIALNUMBER", SERIALNO, LEVEL_MAIN },@@ -672,7 +672,7 @@ 	{ "%K", "KEYWORD",      SIMPLE,   LEVEL_MAIN },  	{ "%X", "ABSTRACT",     SIMPLE,   LEVEL_MAIN }, 	{ "%O", "NOTES",        NOTES,    LEVEL_MAIN },-	{ "%U", "URL",          SIMPLE,   LEVEL_MAIN },+	{ "%U", "URL",          URL,      LEVEL_MAIN }, 	{ "%Z", "NOTES",        SIMPLE,   LEVEL_MAIN }, 	{ "%1", "CUSTOM1",      NOTES,    LEVEL_MAIN }, 	{ "%2", "CUSTOM2",      NOTES,    LEVEL_MAIN },@@ -696,7 +696,7 @@ 	{ "%A", "AUTHOR",    PERSON    , LEVEL_MAIN }, 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },-	{ "%D", "YEAR",      SIMPLE    , LEVEL_MAIN },+	{ "%D", "DATE:YEAR",      SIMPLE    , LEVEL_MAIN }, 	{ "%T", "TITLE" ,    TITLE     , LEVEL_MAIN }, 	{ "%C", "ADDRESS",   SIMPLE, LEVEL_MAIN }, 	{ "%I", "PUBLISHER", SIMPLE    , LEVEL_MAIN }, @@ -717,7 +717,7 @@ 	{ "%K", "KEYWORD",   SIMPLE,     LEVEL_MAIN },  	{ "%X", "ABSTRACT",  SIMPLE,     LEVEL_MAIN }, 	{ "%O", "NOTES",     NOTES,      LEVEL_MAIN },-	{ "%U", "URL",       SIMPLE,     LEVEL_MAIN },+	{ "%U", "URL",       URL,        LEVEL_MAIN }, 	{ "%V", "VOLUME",    SIMPLE,     LEVEL_MAIN }, 	{ "%Z", "NOTES",     NOTES,      LEVEL_MAIN }, 	{ "%W", "PHYSICALLOC",  SIMPLE, LEVEL_MAIN },  /* physical location */@@ -737,7 +737,7 @@ 	{ "%A", "AUTHOR",    PERSON    , LEVEL_MAIN }, 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },-	{ "%D", "YEAR",      SIMPLE    , LEVEL_MAIN },+	{ "%D", "DATE:YEAR",      SIMPLE    , LEVEL_MAIN }, 	{ "%T", "TITLE" ,    TITLE     , LEVEL_MAIN }, 	{ "%C", "ADDRESS",   SIMPLE, LEVEL_MAIN }, 	{ "%I", "PUBLISHER", SIMPLE    , LEVEL_MAIN }, @@ -758,7 +758,7 @@ 	{ "%K", "KEYWORD",   SIMPLE,     LEVEL_MAIN },  	{ "%X", "ABSTRACT",  SIMPLE,     LEVEL_MAIN }, 	{ "%O", "NOTES",     NOTES,      LEVEL_MAIN },-	{ "%U", "URL",       SIMPLE,     LEVEL_MAIN },+	{ "%U", "URL",       URL,        LEVEL_MAIN }, 	{ "%V", "VOLUME",    SIMPLE,     LEVEL_MAIN }, 	{ "%Z", "NOTES",     NOTES,      LEVEL_MAIN }, 	{ "%W", "PHYSICALLOC",  SIMPLE, LEVEL_MAIN },  /* physical location */@@ -778,11 +778,11 @@ 	{ "%A", "ARTIST",    PERSON   , LEVEL_MAIN }, 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },-	{ "%D", "YEAR",         SIMPLE   , LEVEL_MAIN },+	{ "%D", "DATE:YEAR",         SIMPLE   , LEVEL_MAIN }, 	{ "%T", "TITLE" ,       TITLE    , LEVEL_MAIN }, 	{ "%C", "ADDRESS",      SIMPLE   , LEVEL_MAIN }, 	{ "%I", "PUBLISHER",    SIMPLE   , LEVEL_MAIN },-	{ "%8", "MONTH",        DATE,   LEVEL_MAIN },+	{ "%8", "DATE:MONTH",        DATE,   LEVEL_MAIN }, 	{ "%9", "GENRE",        SIMPLE, LEVEL_MAIN }, 	{ "%!", "SHORTTITLE",   TITLE,  LEVEL_MAIN }, 	{ "%M", "ACCESSNUM",    SIMPLE, LEVEL_MAIN },@@ -791,7 +791,7 @@ 	{ "%K", "KEYWORD",      SIMPLE, LEVEL_MAIN },  	{ "%X", "ABSTRACT",     SIMPLE, LEVEL_MAIN }, 	{ "%O", "NOTES",        NOTES,  LEVEL_MAIN },-	{ "%U", "URL",          SIMPLE, LEVEL_MAIN },+	{ "%U", "URL",          URL,    LEVEL_MAIN }, 	{ "%Z", "NOTES",        NOTES,  LEVEL_MAIN }, 	{ "%1", "CUSTOM1",      NOTES,  LEVEL_MAIN }, 	{ "%2", "CUSTOM2",      NOTES,  LEVEL_MAIN },@@ -815,12 +815,12 @@ 	{ "%A", "AUTHOR",    PERSON   , LEVEL_MAIN }, 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },-	{ "%D", "YEAR",      SIMPLE   , LEVEL_MAIN },+	{ "%D", "DATE:YEAR",      SIMPLE   , LEVEL_MAIN }, 	{ "%T", "TITLE" ,    TITLE    , LEVEL_MAIN }, 	{ "%C", "ADDRESS",   SIMPLE   , LEVEL_MAIN }, 	{ "%I", "PUBLISHER", SIMPLE, LEVEL_MAIN }, 	{ "%P", "PAGES",     PAGES, LEVEL_MAIN },-	{ "%8", "MONTH",     DATE, LEVEL_MAIN },+	{ "%8", "DATE:MONTH",     DATE, LEVEL_MAIN }, 	{ "%9", "GENRE",     SIMPLE,    LEVEL_MAIN }, 	{ "%N", "NUMBER",    SIMPLE,    LEVEL_MAIN }, 	{ "%@", "SERIALNUMBER", SERIALNO, LEVEL_MAIN },@@ -831,7 +831,7 @@ 	{ "%K", "KEYWORD",   SIMPLE,    LEVEL_MAIN },  	{ "%X", "ABSTRACT",  SIMPLE,    LEVEL_MAIN }, 	{ "%O", "NOTES",     NOTES,     LEVEL_MAIN },-	{ "%U", "URL",       SIMPLE,    LEVEL_MAIN },+	{ "%U", "URL",       URL,       LEVEL_MAIN }, 	{ "%Z", "NOTES",     NOTES,     LEVEL_MAIN }, 	{ "%1", "CUSTOM1",   NOTES,     LEVEL_MAIN }, 	{ "%2", "CUSTOM2",   NOTES,     LEVEL_MAIN },@@ -856,7 +856,7 @@ 	{ "%A", "CARTOGRAPHER",    PERSON   , LEVEL_MAIN }, 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },-	{ "%D", "YEAR",      SIMPLE   , LEVEL_MAIN },+	{ "%D", "DATE:YEAR",      SIMPLE   , LEVEL_MAIN }, 	{ "%T", "TITLE" ,    TITLE    , LEVEL_MAIN }, 	{ "%C", "ADDRESS",   SIMPLE   , LEVEL_MAIN }, 	{ "%I", "PUBLISHER", SIMPLE   , LEVEL_MAIN },@@ -869,7 +869,7 @@ 	{ "%K", "KEYWORD",   SIMPLE   , LEVEL_MAIN },  	{ "%X", "ABSTRACT",  SIMPLE   , LEVEL_MAIN }, 	{ "%O", "NOTES",     SIMPLE   , LEVEL_MAIN },-	{ "%U", "URL",       SIMPLE   , LEVEL_MAIN },+	{ "%U", "URL",       URL,       LEVEL_MAIN }, 	{ "%Z", "NOTES",     SIMPLE   , LEVEL_MAIN }, 	{ "%1", "SCALE",     SIMPLE   , LEVEL_MAIN }, 	{ "%2", "CUSTOM2",   SIMPLE   , LEVEL_MAIN },@@ -894,7 +894,7 @@ 	{ "%A", "AUTHOR",    PERSON, LEVEL_MAIN  }, 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },-	{ "%D", "YEAR",      SIMPLE, LEVEL_MAIN  },+	{ "%D", "DATE:YEAR",      SIMPLE, LEVEL_MAIN  }, 	{ "%T", "TITLE" ,    TITLE, LEVEL_MAIN   }, 	{ "%B", "PUBLISHED_SOURCE", SIMPLE, LEVEL_MAIN}, 	{ "%C", "COUNTRY",   SIMPLE, LEVEL_MAIN  },@@ -909,7 +909,7 @@ 	{ "%K", "KEYWORD",   SIMPLE, LEVEL_MAIN  },  	{ "%X", "ABSTRACT",  SIMPLE, LEVEL_MAIN  }, 	{ "%O", "NOTES",     SIMPLE, LEVEL_MAIN  },-	{ "%U", "URL",       SIMPLE, LEVEL_MAIN  },+	{ "%U", "URL",       URL,    LEVEL_MAIN  }, 	{ "%Z", "NOTES",     SIMPLE, LEVEL_MAIN  }, 	{ "%1", "SCALE",     SIMPLE, LEVEL_MAIN  }, 	{ "%2", "CUSTOM2",   SIMPLE, LEVEL_MAIN  },@@ -931,7 +931,7 @@  static lookups hearing[] = { 	{ "%0", "INTERNAL_TYPE",         TYPE, LEVEL_MAIN    },-	{ "%D", "YEAR",         SIMPLE, LEVEL_MAIN  },+	{ "%D", "DATE:YEAR",         SIMPLE, LEVEL_MAIN  }, 	{ "%H", "TRANSLATOR",   PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN }, 	{ "%T", "TITLE" ,       TITLE, LEVEL_MAIN   },@@ -940,10 +940,10 @@ 	{ "%I", "PUBLISHER",    SIMPLE, LEVEL_MAIN  },  	{ "%6", "NUMVOLUMES",   SIMPLE, LEVEL_MAIN  }, 	{ "%N", "NUMBER",       SIMPLE, LEVEL_MAIN  },-	{ "%P", "NUMPAGES",     PAGES,  LEVEL_MAIN  },+	{ "%P", "PAGES:TOTAL",  PAGES,  LEVEL_MAIN  }, 	{ "%S", "LEGISLATIVEBODY:CORP", SIMPLE, LEVEL_MAIN  }, 	{ "%7", "SESSION",       SIMPLE, LEVEL_MAIN  },-	{ "%8", "MONTH",         DATE,   LEVEL_MAIN  },+	{ "%8", "DATE:MONTH",         DATE,   LEVEL_MAIN  }, 	{ "%!", "SHORTTITLE",    TITLE,  LEVEL_MAIN  }, 	{ "%(", "TITLE",         SIMPLE, LEVEL_ORIG }, /* orig publication */ 	{ "%M", "ACCESSNUM",     SIMPLE, LEVEL_MAIN  },@@ -952,7 +952,7 @@ 	{ "%K", "KEYWORD",       SIMPLE, LEVEL_MAIN  },  	{ "%X", "ABSTRACT",      SIMPLE, LEVEL_MAIN  }, 	{ "%O", "NOTES",         NOTES,  LEVEL_MAIN  },-	{ "%U", "URL",           SIMPLE, LEVEL_MAIN  },+	{ "%U", "URL",           URL,    LEVEL_MAIN  }, 	{ "%Z", "NOTES",         NOTES,  LEVEL_MAIN  }, 	{ "%1", "CUSTOM1",       NOTES,  LEVEL_MAIN  }, 	{ "%2", "CUSTOM2",       NOTES,  LEVEL_MAIN  },@@ -973,7 +973,7 @@  static lookups bill[] = { 	{ "%0", "INTERNAL_TYPE",      TYPE, LEVEL_MAIN    },-	{ "%D", "YEAR",      SIMPLE, LEVEL_MAIN  },+	{ "%D", "DATE:YEAR",      SIMPLE, LEVEL_MAIN  }, 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN }, 	{ "%T", "TITLE" ,    TITLE, LEVEL_MAIN   },@@ -984,7 +984,7 @@ 	{ "%&", "CODESECTION",SIMPLE, LEVEL_MAIN  }, 	{ "%S", "LEGISLATIVEBODY:CORP", SIMPLE, LEVEL_MAIN  }, 	{ "%7", "SESSION",   SIMPLE, LEVEL_MAIN  },-	{ "%8", "MONTH", DATE, LEVEL_MAIN    },+	{ "%8", "DATE:MONTH", DATE, LEVEL_MAIN    }, 	{ "%?", "SPONSOR",   PERSON, LEVEL_MAIN  }, 	{ "%!", "SHORTTITLE",TITLE,  LEVEL_MAIN   }, 	{ "%(", "TITLE",     SIMPLE, LEVEL_ORIG  }, /* original pub */@@ -994,7 +994,7 @@ 	{ "%K", "KEYWORD",   SIMPLE, LEVEL_MAIN  },  	{ "%X", "ABSTRACT",  SIMPLE, LEVEL_MAIN  }, 	{ "%O", "NOTES",     NOTES,  LEVEL_MAIN  },-	{ "%U", "URL",       SIMPLE, LEVEL_MAIN  },+	{ "%U", "URL",       URL,    LEVEL_MAIN  }, 	{ "%Z", "NOTES",     NOTES,  LEVEL_MAIN  }, 	{ "%1", "CUSTOM1",   NOTES,  LEVEL_MAIN  }, 	{ "%2", "CUSTOM2",   NOTES,  LEVEL_MAIN  },@@ -1015,7 +1015,7 @@  static lookups statute[] = { 	{ "%0", "INTERNAL_TYPE",      TYPE, LEVEL_MAIN    },-	{ "%D", "YEAR",      SIMPLE, LEVEL_MAIN  },+	{ "%D", "DATE:YEAR",      SIMPLE, LEVEL_MAIN  }, 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN }, 	{ "%T", "TITLE" ,    TITLE, LEVEL_MAIN   },@@ -1025,7 +1025,7 @@ 	{ "%P", "PAGES",     PAGES, LEVEL_MAIN    }, 	{ "%&", "SECTION",   SIMPLE, LEVEL_MAIN  }, 	{ "%7", "SESSION",   SIMPLE, LEVEL_MAIN  },-	{ "%8", "MONTH", DATE, LEVEL_MAIN    },+	{ "%8", "DATE:MONTH", DATE, LEVEL_MAIN    }, 	{ "%!", "SHORTTITLE",TITLE,  LEVEL_MAIN   }, 	{ "%(", "TITLE",     SIMPLE, LEVEL_ORIG  }, /* original pub */ 	{ "%M", "ACCESSNUM", SIMPLE, LEVEL_MAIN  },@@ -1034,7 +1034,7 @@ 	{ "%K", "KEYWORD",   SIMPLE, LEVEL_MAIN  },  	{ "%X", "ABSTRACT",  SIMPLE, LEVEL_MAIN  }, 	{ "%O", "NOTES",     NOTES,  LEVEL_MAIN  },-	{ "%U", "URL",       SIMPLE, LEVEL_MAIN  },+	{ "%U", "URL",       URL,    LEVEL_MAIN  }, 	{ "%Z", "NOTES",     NOTES,  LEVEL_MAIN  }, 	{ "%1", "CUSTOM1",   NOTES,  LEVEL_MAIN  }, 	{ "%2", "CUSTOM2",   NOTES,  LEVEL_MAIN  },@@ -1055,7 +1055,7 @@  static lookups lawcase[] = { 	{ "%0", "INTERNAL_TYPE",      TYPE, LEVEL_MAIN    },-	{ "%D", "YEAR",      SIMPLE, LEVEL_MAIN  },+	{ "%D", "DATE:YEAR",      SIMPLE, LEVEL_MAIN  }, 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN }, 	{ "%T", "TITLE" ,    TITLE, LEVEL_MAIN   },@@ -1065,7 +1065,7 @@ 	{ "%V", "VOLUME",    SIMPLE, LEVEL_MAIN   }, 	{ "%N", "PUBLICLAWNUMBER",    SIMPLE, LEVEL_MAIN  }, 	{ "%P", "STARTPAGE",     SIMPLE, LEVEL_MAIN  },-	{ "%8", "MONTH", DATE, LEVEL_MAIN    },+	{ "%8", "DATE:MONTH", DATE, LEVEL_MAIN    }, 	{ "%?", "COUNSEL",   PERSON, LEVEL_MAIN  }, 	{ "%!", "SHORTTITLE",TITLE,  LEVEL_MAIN   }, 	{ "%(", "TITLE",     SIMPLE, LEVEL_ORIG  }, /* original pub */@@ -1075,7 +1075,7 @@ 	{ "%K", "KEYWORD",   SIMPLE, LEVEL_MAIN  },  	{ "%X", "ABSTRACT",  SIMPLE, LEVEL_MAIN  }, 	{ "%O", "NOTES",     NOTES,  LEVEL_MAIN  },-	{ "%U", "URL",       SIMPLE, LEVEL_MAIN  },+	{ "%U", "URL",       URL,    LEVEL_MAIN  }, 	{ "%Z", "NOTES",     NOTES,  LEVEL_MAIN  }, 	{ "%1", "CUSTOM1",   NOTES,  LEVEL_MAIN  }, 	{ "%2", "CUSTOM2",   NOTES,  LEVEL_MAIN  },@@ -1099,7 +1099,7 @@ 	{ "%A", "AUTHOR",    PERSON, LEVEL_MAIN }, 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },-	{ "%D", "YEAR",      SIMPLE, LEVEL_MAIN },+	{ "%D", "DATE:YEAR",      SIMPLE, LEVEL_MAIN }, 	{ "%T", "TITLE" ,    TITLE,  LEVEL_MAIN }, 	{ "%J", "TITLE",     TITLE,  LEVEL_HOST }, /* for refer formats */ 	{ "%E", "2ND_AUTHOR",PERSON, LEVEL_MAIN },@@ -1114,7 +1114,7 @@ 	{ "%Y", "AUTHOR",    PERSON, LEVEL_SERIES }, 	{ "%S", "TITLE",     TITLE,  LEVEL_SERIES }, 	{ "%7", "EDITION",   SIMPLE, LEVEL_MAIN },-	{ "%8", "MONTH",     DATE,   LEVEL_MAIN },+	{ "%8", "DATE:MONTH",     DATE,   LEVEL_MAIN }, 	{ "%9", "GENRE",     SIMPLE, LEVEL_MAIN }, 	{ "%?", "SUB_AUTHOR",   PERSON, LEVEL_MAIN }, /* subsidiary-authors */ 	{ "%!", "SHORTTITLE",   TITLE,  LEVEL_MAIN },@@ -1134,7 +1134,7 @@ 	{ "%K", "KEYWORD",      SIMPLE, LEVEL_MAIN },  	{ "%X", "ABSTRACT",     SIMPLE, LEVEL_MAIN }, 	{ "%O", "NOTES",        NOTES,  LEVEL_MAIN },-	{ "%U", "URL",          SIMPLE, LEVEL_MAIN },+	{ "%U", "URL",          URL,    LEVEL_MAIN }, 	{ "%Z", "NOTES",        NOTES,  LEVEL_MAIN }, 	{ "%W", "PHYSICALLOC",  SIMPLE, LEVEL_MAIN },  /* physical location */ 	{ "%+", "AUTHORADDRESS",SIMPLE, LEVEL_MAIN },@@ -1152,7 +1152,7 @@ 	{ "%A", "AUTHOR",    PERSON, LEVEL_MAIN }, 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN }, 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },-	{ "%D", "YEAR",      SIMPLE, LEVEL_MAIN },+	{ "%D", "DATE:YEAR",      SIMPLE, LEVEL_MAIN }, 	{ "%T", "TITLE" ,    TITLE,  LEVEL_MAIN }, 	{ "%J", "TITLE",     TITLE,  LEVEL_HOST }, /* for refer formats */ 	{ "%E", "2ND_AUTHOR",PERSON, LEVEL_MAIN },@@ -1167,7 +1167,7 @@ 	{ "%Y", "AUTHOR",   PERSON, LEVEL_SERIES }, 	{ "%S", "TITLE",    TITLE, LEVEL_SERIES }, 	{ "%7", "EDITION",      SIMPLE, LEVEL_MAIN },-	{ "%8", "MONTH",    DATE,   LEVEL_MAIN },+	{ "%8", "DATE:MONTH",    DATE,   LEVEL_MAIN }, 	{ "%9", "GENRE",        SIMPLE, LEVEL_MAIN }, 	{ "%?", "SUB_AUTHOR",   PERSON, LEVEL_MAIN }, /* subsidiary-authors */ 	{ "%!", "SHORTTITLE",   TITLE,  LEVEL_MAIN },@@ -1187,7 +1187,7 @@ 	{ "%K", "KEYWORD",      SIMPLE, LEVEL_MAIN },  	{ "%X", "ABSTRACT",     SIMPLE, LEVEL_MAIN }, 	{ "%O", "NOTES",        NOTES,  LEVEL_MAIN },-	{ "%U", "URL",          SIMPLE, LEVEL_MAIN },+	{ "%U", "URL",          URL,    LEVEL_MAIN }, 	{ "%>", "PDFLINK",      SIMPLE, LEVEL_MAIN }, 	{ "%Z", "NOTES",        NOTES,  LEVEL_MAIN }, 	{ "%W", "PHYSICALLOC",  SIMPLE, LEVEL_MAIN },  /* physical location */
bibutils/endxmlin.c view
@@ -1,28 +1,37 @@ /*  * endxmlin.c  *- * Copyright (c) Chris Putnam 2006-2014+ * Copyright (c) Chris Putnam 2006-2017  *  * Program and source code released under the GPL version 2  *  */ #include <stdio.h> #include <stdlib.h>-#include "newstr.h"-#include "newstr_conv.h"+#include "str.h"+#include "str_conv.h" #include "fields.h" #include "name.h" #include "xml.h" #include "xml_encoding.h" #include "reftypes.h"-#include "endxmlin.h"-#include "endin.h"+#include "bibformats.h"  typedef struct { 	char *attrib; 	char *internal; } attribs; +extern variants end_all[];+extern int end_nall;++static int endxmlin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset );+static int endxmlin_processf( fields *endin, char *p, char *filename, long nref, param *pm );+extern int endin_typef( fields *endin, char *filename, int nrefs, param *p );+extern int endin_convertf( fields *endin, fields *info, int reftype, param *p );+extern int endin_cleanf( bibl *bin, param *p );++ /*****************************************************  PUBLIC: void endxmlin_initparams() *****************************************************/@@ -48,8 +57,8 @@ 	p->all      = end_all; 	p->nall     = end_nall; -	list_init( &(p->asis) );-	list_init( &(p->corps) );+	slist_init( &(p->asis) );+	slist_init( &(p->corps) );  	if ( !progname ) p->progname = NULL; 	else p->progname = strdup( progname );@@ -66,14 +75,13 @@ 	return 1; } -int-endxmlin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line,-	newstr *reference, int *fcharset )+static int+endxmlin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset ) {-	newstr tmp;+	str tmp; 	char *startptr = NULL, *endptr = NULL; 	int haveref = 0, inref = 0, done = 0, file_charset = CHARSET_UNKNOWN, m;-	newstr_init( &tmp );+	str_init( &tmp ); 	while ( !haveref && !done ) { 		if ( line->data ) { 			if ( !inref ) {@@ -90,21 +98,21 @@ 				int n = 8; 				char *p = &(line->data[line->len-1]); 				while ( *p && n ) { p--; n--; }-				newstr_segdel( line, line->data, p ); +				str_segdel( line, line->data, p ); 			} 		}  		if ( !startptr || !endptr ) { 			done = xml_readmore( fp, buf, bufsize, bufpos );-			newstr_strcat( line, buf );+			str_strcatc( line, buf ); 		} else {-			/* we can reallocate in the newstr_strcat, so re-find */+			/* we can reallocate in the str_strcat, so re-find */ 			startptr = xml_findstart( line->data, "RECORD" ); 			endptr = xml_findend( line->data, "RECORD" );-			newstr_segcpy( reference, startptr, endptr );+			str_segcpy( reference, startptr, endptr ); 			/* clear out information in line */-			newstr_strcpy( &tmp, endptr );-			newstr_newstrcpy( line, &tmp );+			str_strcpyc( &tmp, endptr );+			str_strcpy( line, &tmp ); 			haveref = 1; 		} 		if ( line->data ) {@@ -112,7 +120,7 @@ 			if ( m!=CHARSET_UNKNOWN ) file_charset = m; 		} 	}-	newstr_free( &tmp );+	str_free( &tmp ); 	*fcharset = file_charset; 	return haveref; }@@ -139,12 +147,13 @@  *   </datatype>  */ static int-endxmlin_datar( xml *node, newstr *s )+endxmlin_datar( xml *node, str *s ) { 	int status;-	if ( node->value && node->value->len ) {-		newstr_strcat( s, node->value->data );-		if ( newstr_memerr( s ) ) return BIBL_ERR_MEMERR;++	if ( str_has_value( node->value ) ) {+		str_strcat( s, node->value );+		if ( str_memerr( s ) ) return BIBL_ERR_MEMERR; 	} 	if ( node->down && xml_tagexact( node->down, "style" ) ) { 		status = endxmlin_datar( node->down, s );@@ -154,6 +163,7 @@ 		status = endxmlin_datar( node->next, s ); 		if ( status!=BIBL_OK ) return status; 	}+ 	return BIBL_OK; } @@ -161,15 +171,19 @@ endxmlin_data( xml *node, char *inttag, fields *info, int level ) { 	int status;-	newstr s;-	newstr_init( &s );+	str s;++	str_init( &s );+ 	status = endxmlin_datar( node, &s ); 	if ( status!=BIBL_OK ) return status;-	if ( s.len ) {++	if ( str_has_value( &s ) ) { 		status = fields_add( info, inttag, s.data, level ); 		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	}-	newstr_free( &s );++	str_free( &s ); 	return BIBL_OK; } @@ -190,15 +204,15 @@ 		{ "short-title", "SHORTTITLE" }, 	}; 	int i, status, n = sizeof( a ) / sizeof ( a[0] );-	newstr title;-	newstr_init( &title );+	str title;+	str_init( &title ); 	for ( i=0; i<n; ++i ) { 		if ( xml_tagexact( node, a[i].attrib ) && node->down ) {-			newstr_empty( &title );+			str_empty( &title ); 			status = endxmlin_datar( node, &title ); 			if ( status!=BIBL_OK ) return BIBL_ERR_MEMERR;-			newstr_trimstartingws( &title );-			newstr_trimendingws( &title );+			str_trimstartingws( &title );+			str_trimendingws( &title ); 			status = fields_add( info, a[i].internal, title.data, 0); 			if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR; 		}@@ -207,7 +221,7 @@ 		status = endxmlin_titles( node->next, info ); 		if ( status!=BIBL_OK ) return status; 	}-	newstr_free( &title );+	str_free( &title ); 	return BIBL_OK; } @@ -410,13 +424,14 @@ endxmlin_reftype( xml *node, fields *info ) { 	int status;-	newstr *s;+	str *s;+ 	s = xml_getattrib( node, "name" );-	if ( s && s->len ) {-		status = fields_add( info, "%0", s->data, 0 );-		newstr_free( s );+	if ( str_has_value( s ) ) {+		status = fields_add( info, "%0", str_cstr( s ), 0 ); 		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	}+ 	return BIBL_OK; } @@ -523,7 +538,7 @@ endxmlin_assembleref( xml *node, fields *info ) { 	int status;-	if ( node->tag->len==0 ) {+	if ( str_is_empty( node->tag ) ) { 		if ( node->down ) 			return endxmlin_assembleref( node->down, info ); 	} else if ( xml_tagexact( node, "RECORD" ) ) {@@ -541,8 +556,8 @@  * this is necessary as the xml format is as nasty and as overloaded  * as the tags used in the Refer format output  */-int-endxmlin_processf( fields *fin, char *data, char *filename, long nref )+static int+endxmlin_processf( fields *fin, char *data, char *filename, long nref, param *pm ) { 	int status; 	xml top;
− bibutils/endxmlin.h
@@ -1,23 +0,0 @@-/*- * endxmlin.h- *- * Copyright (c) Chris Putnam 2006-2014- *- * Source code released under the GPL version 2- *- */-#ifndef ENDXMLIN_H-#define ENDXMLIN_H--#include "newstr.h"-#include "fields.h"-#include "reftypes.h"-#include "bibutils.h"--extern int endxmlin_readf( FILE *fp, char *buf, int bufsize, int *bufpos,-	newstr *line, newstr *reference, int *fcharset );-extern int endxmlin_processf( fields *endin, char *p, char *filename, long nref );--extern void endxmlin_initparams( param *p, const char *progname );--#endif
bibutils/entities.c view
@@ -1,7 +1,7 @@ /*  * entities.c  *- * Copyright (c) Chris Putnam 2003-2013+ * Copyright (c) Chris Putnam 2003-2017  *  * Source code released under the GPL version 2  *
bibutils/entities.h view
@@ -1,7 +1,7 @@ /*  * entities.h  *- * Copyright (c) Chris Putnam 2003-2013+ * Copyright (c) Chris Putnam 2003-2017  *  * Source code released under the GPL version 2  *
bibutils/fields.c view
@@ -1,7 +1,7 @@ /*  * fields.c  *- * Copyright (c) Chris Putnam 2003-2013+ * Copyright (c) Chris Putnam 2003-2017  *  * Source code released under the GPL version 2  *@@ -36,8 +36,8 @@ 	int i;  	for ( i=0; i<f->max; ++i ) {-		newstr_free( &(f->tag[i]) );-		newstr_free( &(f->data[i]) );+		str_free( &(f->tag[i]) );+		str_free( &(f->data[i]) ); 	} 	if ( f->tag )   free( f->tag ); 	if ( f->data )  free( f->data );@@ -52,8 +52,8 @@ { 	int i, alloc = 20; -	f->tag   = (newstr *) malloc( sizeof(newstr) * alloc );-	f->data  = (newstr *) malloc( sizeof(newstr) * alloc );+	f->tag   = (str *) malloc( sizeof(str) * alloc );+	f->data  = (str *) malloc( sizeof(str) * alloc ); 	f->used  = (int *)    calloc( alloc, sizeof(int) ); 	f->level = (int *)    calloc( alloc, sizeof(int) ); 	if ( !f->tag || !f->data || !f->used || !f->level ){@@ -68,8 +68,8 @@ 	f->max = alloc; 	f->n = 0; 	for ( i=0; i<alloc; ++i ) {-		newstr_init( &(f->tag[i]) );-		newstr_init( &(f->data[i]) );+		str_init( &(f->tag[i]) );+		str_init( &(f->data[i]) ); 	} 	return FIELDS_OK; }@@ -77,12 +77,12 @@ static int fields_realloc( fields *f ) {-	newstr *newtags, *newdata;+	str *newtags, *newdata; 	int *newused, *newlevel; 	int i, alloc = f->max * 2; -	newtags = (newstr*) realloc( f->tag, sizeof(newstr) * alloc );-	newdata = (newstr*) realloc( f->data, sizeof(newstr) * alloc );+	newtags = (str*) realloc( f->tag, sizeof(str) * alloc );+	newdata = (str*) realloc( f->data, sizeof(str) * alloc ); 	newused = (int*)    realloc( f->used, sizeof(int) * alloc ); 	newlevel= (int*)    realloc( f->level, sizeof(int) * alloc ); @@ -97,17 +97,17 @@ 	f->max = alloc;  	for ( i=f->n; i<alloc; ++i ) {-		newstr_init( &(f->tag[i]) );-		newstr_init( &(f->data[i]) );+		str_init( &(f->tag[i]) );+		str_init( &(f->data[i]) ); 	}  	return FIELDS_OK; }  int-fields_add( fields *f, char *tag, char *data, int level )+_fields_add( fields *f, char *tag, char *data, int level, int mode ) {-	int i, status, found;+	int i, n, status;  	if ( !tag || !data ) return FIELDS_OK; @@ -119,38 +119,42 @@ 		if ( status!=FIELDS_OK ) return status; 	} -	/* Don't duplicate identical entries */-	found = 0;-	for ( i=0; i<f->n && !found; ++i ) {-		if ( f->level[i]==level &&-		     !strcasecmp( f->tag[i].data, tag ) &&-		     !strcasecmp( f->data[i].data, data ) ) found = 1;-	}-	if ( !found ) {-		f->used[ f->n ]  = 0;-		f->level[ f->n ] = level;-		newstr_strcpy( &(f->tag[f->n]), tag );-		newstr_strcpy( &(f->data[f->n]), data );-		if ( newstr_memerr( &(f->tag[f->n]) ) ||-		     newstr_memerr( &(f->data[f->n] ) ) )-			return FIELDS_ERR;-		f->n++;+	/* Don't duplicate identical entries if FIELDS_NO_DUPS */+	if ( mode == FIELDS_NO_DUPS ) {+		for ( i=0; i<f->n; i++ ) {+			if ( f->level[i]==level &&+			     !strcasecmp( f->tag[i].data, tag ) &&+			     !strcasecmp( f->data[i].data, data ) )+				return FIELDS_OK;+		} 	}++	n = f->n;+	f->used[ n ]  = 0;+	f->level[ n ] = level;+	str_strcpyc( &(f->tag[n]), tag );+	str_strcpyc( &(f->data[n]), data );++	if ( str_memerr( &(f->tag[n]) ) || str_memerr( &(f->data[n] ) ) )+		return FIELDS_ERR;++	f->n++;+ 	return FIELDS_OK; }  int-fields_add_tagsuffix( fields *f, char *tag, char *suffix,-		char *data, int level )+_fields_add_tagsuffix( fields *f, char *tag, char *suffix,+		char *data, int level, int mode ) {-	newstr newtag;+	str newtag; 	int ret; -	newstr_init( &newtag );-	newstr_mergestrs( &newtag, tag, suffix, NULL );-	if ( newstr_memerr( &newtag ) ) ret = FIELDS_ERR;-	else ret = fields_add( f, newtag.data, data, level );-	newstr_free( &newtag );+	str_init( &newtag );+	str_mergestrs( &newtag, tag, suffix, NULL );+	if ( str_memerr( &newtag ) ) ret = FIELDS_ERR;+	else ret = _fields_add( f, newtag.data, data, level, mode );+	str_free( &newtag );  	return ret; }@@ -161,7 +165,7 @@  *  * level==LEVEL_ANY is a special flag meaning any level can match  */-inline int+int fields_match_level( fields *f, int n, int level ) { 	if ( level==LEVEL_ANY ) return 1;@@ -174,28 +178,28 @@  * returns 1 if tag matches, 0 if not  *  */-inline int+int fields_match_tag( fields *info, int n, char *tag ) { 	if ( !strcmp( fields_tag( info, n, FIELDS_CHRP ), tag ) ) return 1; 	return 0; } -inline int+int fields_match_casetag( fields *info, int n, char *tag ) { 	if ( !strcasecmp( fields_tag( info, n, FIELDS_CHRP ), tag ) ) return 1; 	return 0; } -inline int+int fields_match_tag_level( fields *info, int n, char *tag, int level ) { 	if ( !fields_match_level( info, n, level ) ) return 0; 	return fields_match_tag( info, n, tag ); } -inline int+int fields_match_casetag_level( fields *info, int n, char *tag, int level ) { 	if ( !fields_match_level( info, n, level ) ) return 0;@@ -268,35 +272,44 @@ 	int n = fields_find( f, tag, level ); 	if ( n==-1 ) return fields_add( f, tag, data, level ); 	else {-		newstr_strcpy( &(f->data[n]), data );-		if ( newstr_memerr( &(f->data[n]) ) ) return FIELDS_ERR;+		str_strcpyc( &(f->data[n]), data );+		if ( str_memerr( &(f->data[n]) ) ) return FIELDS_ERR; 		return FIELDS_OK; 	} }  char *fields_null_value = "\0"; -inline int+int fields_used( fields *f, int n ) { 	if ( n >= 0 && n < f->n ) return f->used[n]; 	else return 0; } -inline int+int+fields_notag( fields *f, int n )+{+	str *t;+	if ( n >= 0 && n < f->n ) {+		t = &( f->tag[n] );+		if ( t->len > 0 ) return 0;+	}+	return 1;+}++int fields_nodata( fields *f, int n ) {-	newstr *d;+	str *d; 	if ( n >= 0 && n < f->n ) { 		d = &( f->data[n] ); 		if ( d->len > 0 ) return 0;-		return 1;-	} else {-		return 1; 	}+	return 1; } -inline int+int fields_num( fields *f ) { 	return f->n;@@ -311,7 +324,7 @@  * If the length of the tagged value is zero and the mode is  * FIELDS_STRP_NOLEN or FIELDS_CHRP_NOLEN, return a pointer to  * a static null string as the data field could be new due to- * the way newstr handles initialized strings with no data.+ * the way str handles initialized strings with no data.  *  */ @@ -504,3 +517,20 @@  	vplist_free( &tags ); }++void+fields_report( fields *f, FILE *fp )+{+	int i, n;+	n = fields_num( f );+	fprintf( fp, "# NUM   level = LEVEL   'TAG' = 'VALUE'\n" );+	for ( i=0; i<n; ++i ) {+		fprintf( stderr, "%d\tlevel = %d\t'%s' = '%s'\n",+			i+1,+			fields_level( f, i ),+			(char*)fields_tag( f, i, FIELDS_CHRP_NOUSE ),+			(char*)fields_value( f, i, FIELDS_CHRP_NOUSE )+		);+	}+}+
bibutils/fields.h view
@@ -1,7 +1,7 @@ /*  * fields.h  *- * Copyright (c) Chris Putnam 2003-2014+ * Copyright (c) Chris Putnam 2003-2017  *  * Source code released under the GPL version 2  *@@ -20,41 +20,52 @@ #define LEVEL_ORIG (-2)  #include <stdarg.h>-#include "newstr.h"+#include "str.h" #include "vplist.h" -typedef struct {-	newstr    *tag;-	newstr    *data;+typedef struct fields {+	str       *tag;+	str       *data; 	int       *used; 	int       *level; 	int       n; 	int       max; } fields; -extern void fields_init( fields *f );-extern fields *fields_new( void );-extern void fields_free( fields *f );+void    fields_init( fields *f );+fields *fields_new( void );+void    fields_free( fields *f ); -extern int  fields_add( fields *f, char *tag, char *data, int level );-extern int  fields_add_tagsuffix( fields *f, char *tag, char *suffix,-		char *data, int level );+#define FIELDS_CAN_DUP (0)+#define FIELDS_NO_DUPS (1) -extern int  fields_maxlevel( fields *f );-extern void fields_clearused( fields *f );-extern void fields_setused( fields *f, int n );-extern int  fields_replace_or_add( fields *f, char *tag, char *data, int level );+#define fields_add( a, b, c, d )         _fields_add( a, b, c, d, FIELDS_NO_DUPS )+#define fields_add_can_dup( a, b, c, d ) _fields_add( a, b, c, d, FIELDS_CAN_DUP )+#define fields_add_tagsuffix( a, b, c, d, e )         _fields_add( a, b, c, d, e, FIELDS_NO_DUPS )+#define fields_add_tagsuffix_can_dup( a, b, c, d, e ) _fields_add( a, b, c, d, e, FIELDS_CAN_DUP ) -extern inline int fields_num( fields *f );-extern inline int fields_used( fields *f, int n );-extern inline int fields_nodata( fields *f, int n );+int  _fields_add( fields *f, char *tag, char *data, int level, int mode );+int  _fields_add_tagsuffix( fields *f, char *tag, char *suffix,+		char *data, int level, int mode ); -extern inline int fields_match_level( fields *f, int n, int level );-extern inline int fields_match_tag( fields *f, int n, char *tag );-extern inline int fields_match_casetag( fields *f, int n, char *tag );-extern inline int fields_match_tag_level( fields *f, int n, char *tag, int level );-extern inline int fields_match_casetag_level( fields *f, int n, char *tag, int level );+int  fields_maxlevel( fields *f );+void fields_clearused( fields *f );+void fields_setused( fields *f, int n );+int  fields_replace_or_add( fields *f, char *tag, char *data, int level ); +int fields_num( fields *f );+int fields_used( fields *f, int n );+int fields_notag( fields *f, int n );+int fields_nodata( fields *f, int n );++int fields_match_level( fields *f, int n, int level );+int fields_match_tag( fields *f, int n, char *tag );+int fields_match_casetag( fields *f, int n, char *tag );+int fields_match_tag_level( fields *f, int n, char *tag, int level );+int fields_match_casetag_level( fields *f, int n, char *tag, int level );++void fields_report( fields *f, FILE *fp );+ #define FIELDS_STRP_FLAG     (2) #define FIELDS_POSP_FLAG     (4) #define FIELDS_NOLENOK_FLAG  (8)@@ -69,16 +80,16 @@ #define FIELDS_CHRP_NOUSE  (                            0                              ) #define FIELDS_STRP_NOUSE  (                     FIELDS_STRP_FLAG                      ) -extern void *fields_tag( fields *f, int n, int mode );-extern void *fields_value( fields *f, int n, int mode );-extern int   fields_level( fields *f, int n );+void *fields_tag( fields *f, int n, int mode );+void *fields_value( fields *f, int n, int mode );+int   fields_level( fields *f, int n );  -extern int   fields_find( fields *f, char *searchtag, int level );+int   fields_find( fields *f, char *searchtag, int level ); -extern void *fields_findv( fields *f, int level, int mode, char *tag );-extern void *fields_findv_firstof( fields *f, int level, int mode, ... );+void *fields_findv( fields *f, int level, int mode, char *tag );+void *fields_findv_firstof( fields *f, int level, int mode, ... ); -extern void  fields_findv_each( fields *f, int level, int mode, vplist *a, char *tag );-extern void  fields_findv_eachof( fields *f, int level, int mode, vplist *a, ... );+void  fields_findv_each( fields *f, int level, int mode, vplist *a, char *tag );+void  fields_findv_eachof( fields *f, int level, int mode, vplist *a, ... );  #endif
bibutils/gb18030.h view
@@ -1,7 +1,7 @@ /*  * gb18030.h  *- * Copyright (c) Chris Putnam 2008-2013+ * Copyright (c) Chris Putnam 2008-2017  *  * Source code released under the GPL version 2  *
+ bibutils/generic.c view
@@ -0,0 +1,81 @@+/* generic.c+ *+ * Copyright (c) Chris Putnam 2016-2017+ *+ * Source code released under GPL version 2+ *+ * xxxx_convertf() stubs that can be shared.+ */+#include "name.h"+#include "notes.h"+#include "pages.h"+#include "serialno.h"+#include "title.h"+#include "url.h"+#include "generic.h"++/* stub for processtypes that aren't used, such as DEFAULT and ALWAYS handled by bibcore.c  */+int+generic_null( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	return BIBL_OK;+}++int+generic_url( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	return urls_split_and_add( invalue->data, bibout, level );+}++int+generic_notes( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+        if ( notes_add( bibout, invalue, level ) ) return BIBL_OK;+        else return BIBL_ERR_MEMERR;+}++int+generic_pages( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+        if ( pages_add( bibout, outtag, invalue, level ) ) return BIBL_OK;+        else return BIBL_ERR_MEMERR;+}++int+generic_person( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+        if ( name_add( bibout, outtag, invalue->data, level, &(pm->asis), &(pm->corps) ) ) return BIBL_OK;+        else return BIBL_ERR_MEMERR;+}++int+generic_serialno( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	if ( addsn( bibout, invalue->data, level ) ) return BIBL_OK;+	return BIBL_ERR_MEMERR;+}++/* SIMPLE = just copy */+int+generic_simple( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	if ( fields_add( bibout, outtag, invalue->data, level ) == FIELDS_OK ) return BIBL_OK;+	else return BIBL_ERR_MEMERR;+}++/* just like generic_null(), but useful if we need one that isn't identical to generic_null() ala biblatexin.c */+int+generic_skip( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	fields_setused( bibin, n );+	return BIBL_OK;+}++int+generic_title( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+        if ( title_process( bibout, outtag, invalue->data, level, pm->nosplittitle ) ) return BIBL_OK;+        else return BIBL_ERR_MEMERR;+}++
+ bibutils/generic.h view
@@ -0,0 +1,23 @@+/* generic.h+ *+ * Copyright (c) Chris Putnam 2016-2017+ *+ * Source code released under GPL version 2+ *+ */+#ifndef GENERIC_H+#define GENERIC_H++#include "bibutils.h"++int generic_null    ( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout );+int generic_url     ( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout );+int generic_notes   ( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout );+int generic_pages   ( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout );+int generic_person  ( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout );+int generic_serialno( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout );+int generic_simple  ( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout );+int generic_skip    ( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout );+int generic_title   ( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout );++#endif
bibutils/intlist.c view
@@ -1,79 +1,142 @@ /*  * intlist.c  *- * Copyright (c) Chris Putnam 2007-2013+ * Copyright (c) Chris Putnam 2007-2017  *- * Version 9/5/2013+ * Version 1/12/2017  *  * Source code released under the GPL version 2  *  * Implements a simple managed array of ints  *  */+#include <stdlib.h>+#include <assert.h> #include "intlist.h" +#define INTLIST_MINALLOC (20)+ static int-intlist_alloc( intlist *il )+intlist_validn( intlist *il, int n ) {-	int alloc = 20, i;-	il->data = ( int * ) malloc( sizeof( int ) * alloc );-	if ( !(il->data) ) return 0;-	for ( i=0; i<alloc; ++i )-		il->data[i] = 0;-	il->max = alloc;-	il->n = 0;+	if ( n < 0 || n >= il->n ) return 0; 	return 1; } +int+intlist_wasfound( intlist *il, int n )+{+	if ( n!=-1 ) return 1;+	else return 0;+}++int+intlist_wasnotfound( intlist *il, int n )+{+	if ( n==-1 ) return 1;+	else return 0;+}+ static int-intlist_realloc( intlist *il )+intlist_alloc( intlist *il, int alloc_size ) {-	int *more;-	int alloc = il->max * 2, i;-	more = ( int * ) realloc( il->data, sizeof( int ) * alloc );-	if ( !more ) return 0;+	il->data = ( int * ) calloc( alloc_size, sizeof( int ) );+	if ( !(il->data) ) return INTLIST_MEMERR;+	il->max = alloc_size;+	il->n   = 0;+	return INTLIST_OK;+}++static int+intlist_realloc( intlist *il, int alloc_size )+{+	int i, *more;++	more = ( int * ) realloc( il->data, sizeof( int ) * alloc_size );+	if ( !more ) return INTLIST_MEMERR;+ 	il->data = more;-	for ( i=il->max; i<alloc; ++i )+	il->max  = alloc_size;++	for ( i=il->max; i<alloc_size; ++i ) 		il->data[i] = 0;-	il->max = alloc;-	return 1;++	return INTLIST_OK; } +static int+intlist_ensure_space( intlist *il, int n )+{+	int alloc = n;++	if ( il->max == 0 ) {+		if ( alloc < INTLIST_MINALLOC ) alloc = INTLIST_MINALLOC;+		return intlist_alloc( il, alloc );+	}++	else if ( il->max <= n ) {+		if ( alloc < il->max * 2 ) alloc = il->max * 2;+		return intlist_realloc( il, alloc );+	}++	return INTLIST_OK;+}+ /* intlist_add()  *- * Returns position of newly added value in range [0,n), -1 on error+ * Returns INTLIST_OK/INTLIST_MEMERR  */ int intlist_add( intlist *il, int value ) {-	if ( il->max==0 ) {-		if ( !intlist_alloc( il ) ) return -1;-	} else if ( il->n >= il->max ) {-		if ( !intlist_realloc( il ) ) return -1;+	int status;++	assert( il );++	status = intlist_ensure_space( il, il->n+1 );++	if ( status == INTLIST_OK ) {+		il->data[ il->n ] = value;+		il->n++; 	}-	il->data[ il->n ] = value;-	il->n++;-	return il->n - 1;++	return status; }  /* intlist_add_unique()  *- * Returns position of newly added (or previously added) value- * Returns -1 on (memory) error+ * Returns INTLIST_OK/INTLIST_MEMERR  */ int intlist_add_unique( intlist *il, int value ) { 	int n;++	assert( il );+ 	n = intlist_find( il, value );-	if ( n==-1 )-		n = intlist_add( il, value );-	return n;+	if ( intlist_wasnotfound( il, n ) )+		return intlist_add( il, value );+	else+		return INTLIST_OK; }+ int intlist_find_or_add( intlist *il, int value ) {-	return intlist_add_unique( il, value );+	int n, status;++	n = intlist_find( il, value );++	if ( intlist_wasfound( il, n ) ) {+		return n;+	}++	else {+		status = intlist_add( il, value );+		if ( status!=INTLIST_OK ) return -1;+		else return il->n - 1;+	} }  /* intlist_find()@@ -85,56 +148,74 @@ intlist_find( intlist *il, int value ) { 	int i;++	assert( il );+ 	for ( i=0; i<il->n; ++i ) 		if ( il->data[i]==value ) return i;+ 	return -1; } -static void+static int intlist_remove_pos_core( intlist *il, int pos ) { 	int i;++	assert( il );+ 	for ( i=pos; i<il->n-1; ++i ) 		il->data[i] = il->data[i+1]; 	il->n -= 1;++	return INTLIST_OK; }  /* intlist_remove_pos()  *- * Returns 1 on success, 0 on failure.+ * Returns INTLIST_OK on success.  */ int intlist_remove_pos( intlist *il, int pos ) {-	if ( pos < 0 || pos >= il->n ) return 0;-	intlist_remove_pos_core( il, pos );-	return 1;+	assert( il );+	assert( intlist_validn( il, pos ) );++	return intlist_remove_pos_core( il, pos ); }  /* intlist_remove()  *  * Removes first instance of value from the intlist.- * Returns 1 on success, 0 on error.+ * Returns INTLIST_OK/INTLIST_VALUE_MISSING  */ int intlist_remove( intlist *il, int value ) {-	int pos = intlist_find( il, value );-	if ( pos==-1 ) return 0;-	intlist_remove_pos_core( il, pos );-	return 1;+	int pos;++	assert( il );++	pos = intlist_find( il, value );+	if ( pos==-1 ) return INTLIST_VALUE_MISSING;++	return intlist_remove_pos_core( il, pos ); }  /* don't actually free space, just reset counter */ void intlist_empty( intlist *il ) {+	assert( il );+ 	il->n = 0; }  void intlist_free( intlist *il ) {+	assert( il );+ 	if ( il->data ) free( il->data ); 	intlist_init( il ); }@@ -142,33 +223,41 @@ void intlist_delete( intlist *il ) {-	intlist_free( il );+	assert( il );++	if ( il->data ) free( il->data ); 	free( il ); }  void intlist_init( intlist *il  ) {+	assert( il );+ 	il->data = NULL; 	il->max = 0; 	il->n = 0; } +/* Returns INTLIST_OK/INTLIST_MEMERR+ */+int+intlist_init_fill( intlist *il, int n, int v )+{+	intlist_init( il );+	return intlist_fill( il, n, v );+}+ /* intlist_init_range()  *  * Initializes intlist to values from [low,high) with step step.- * Returns -1 on failure, number of elements on success.+ * Returns INTLIST_OK/INTLIST_MEMERR.  */ int intlist_init_range( intlist *il, int low, int high, int step ) {-	int i, n; 	intlist_init( il );-	for ( i=low; i<high; i+= step ) {-		n = intlist_add( il, i );-		if ( n==-1 ) return -1;-	}-	return il->n;+	return intlist_fill_range( il, low, high, step ); }  /* intlist_new()@@ -179,25 +268,27 @@ intlist * intlist_new( void ) {-	intlist *il = ( intlist * ) malloc( sizeof( intlist ) );+	intlist *il;+	il = ( intlist * ) malloc( sizeof( intlist ) ); 	if ( il ) intlist_init( il ); 	return il; }  /* intlist_new_range()  *- * Allocates a intlist initialized to values from [low,high) with step step.- * Returns pointer to intlist on success, NULL on memory error;+ * Allocates a intlist initialized to values from [low,high) in increments of step.+ * Returns pointer to intlist on success, NULL on memory error.  */ intlist * intlist_new_range( int low, int high, int step ) { 	intlist *il;-	int n;-	il = ( intlist * ) malloc( sizeof( intlist ) );+	int status;++	il = intlist_new(); 	if ( il ) {-		n = intlist_init_range( il, low, high, step );-		if ( n==-1 ) {+		status = intlist_fill_range( il, low, high, step );+		if ( status==INTLIST_MEMERR ) { 			intlist_free( il ); 			free( il ); 			il = NULL;@@ -206,6 +297,96 @@ 	return il; } +/* intlist_new_range()+ *+ * Allocates a intlist initialized to n elements with value v.+ * Returns pointer to intlist on success, NULL on memory error.+ */+intlist *+intlist_new_fill( int n, int v )+{+	intlist *il;+	int status;++	il = intlist_new();+	if ( il ) {+		status = intlist_fill( il, n, v );+		if ( status==INTLIST_MEMERR ) {+			intlist_free( il );+			free( il );+			il = NULL;+		}+	}+	return il;+}++/* intlist_fill()+ *+ * Fill an intlist with n elements of value v.+ *+ * Returns INTLIST_OK or INTLIST_MEMERR.+ */+int+intlist_fill( intlist *il, int n, int v )+{+	int i, status;++	assert ( n > 0 );++	status = intlist_ensure_space( il, n );++	if ( status==INTLIST_OK ) {++		for ( i=0; i<n; ++i )+			il->data[i] = v;++		il->n = n;++	}++	return status;+}++/* intlist_fill_range()+ *+ * Fill an intlist with the values [low,high) in increments of step+ *+ * Returns INTLIST_OK or INTLIST_MEMERR.+ */+int+intlist_fill_range( intlist *il, int low, int high, int step )+{+	int i, n, status;++	n = ( high - low ) / step + 1;++	assert ( n > 0 );++	status = intlist_ensure_space( il, n );++	if ( status==INTLIST_OK ) {++		il->n = 0;++		/* ...fill intlist with range */+		if ( step > 0 ) {+			for ( i=low; i<high; i+=step ) {+				il->data[il->n] = i;+				il->n += 1;+			}+		}+		else {+			for ( i=low; i>high; i+=step ) {+				il->data[il->n] = i;+				il->n += 1;+			}+		}++	}++	return status;+}+ static int intcomp( const void *v1, const void *v2 ) {@@ -219,6 +400,8 @@ void intlist_sort( intlist *il ) {+	assert( il );+ 	qsort( il->data, il->n, sizeof( int ), intcomp ); } @@ -243,6 +426,9 @@ intlist_randomize( intlist *il ) { 	int i, j;++	assert( il );+ 	if ( il->n < 2 ) return; 	for ( i=0; i<il->n; ++i ) { 		j = randomint( i, il->n );@@ -251,18 +437,27 @@ 	} } -/* Returns 1 on success, 0 on error */+/* Returns INTLIST_OK/INTLIST_MEMERR */ int intlist_copy( intlist *to, intlist *from ) {-	int i;-	intlist_free( to );-	to->data = ( int* ) malloc( sizeof( int ) * from->n );-	if ( !to->data ) return 0;-	to->n = to->max = from->n;-	for ( i=0; i<from->n; ++i ) -		to->data[i] = from->data[i];-	return 1;+	int i, status;++	assert( to );+	assert( from );++	status = intlist_ensure_space( to, from->n );++	if ( status==INTLIST_OK ) {++		to->n = from->n;++		for ( i=0; i<from->n; ++i )+			to->data[i] = from->data[i];++	}++	return status; }  /* Returns pointer on success, NULL on error */@@ -270,12 +465,14 @@ intlist_dup( intlist *il ) { 	intlist *l;-	int n;+	int status; +	assert( il );+ 	l = intlist_new(); 	if ( l ) {-		n = intlist_copy( l, il );-		if ( !n ) {+		status = intlist_copy( l, il );+		if ( status==INTLIST_MEMERR ) { 			intlist_delete( l ); 			l = NULL; 		}@@ -287,49 +484,64 @@ int intlist_append( intlist *to, intlist *from ) {-	int i, n, nsave = to->n;-	for ( i=0; i<from->n; ++i ) {-		n = intlist_add( to, from->data[i] );-		if ( n==-1 ) {-			to->n = nsave;-			return -1;-		}+	int i, status;++	assert( to );+	assert( from );++	status = intlist_ensure_space( to, to->n + from->n );++	if ( status == INTLIST_OK ) {++		for ( i=0; i<from->n; ++i )+			to->data[ to->n + i ] = from->data[ i ];++		to->n += from->n; 	}-	return to->n;++	return status; }  int intlist_append_unique( intlist *to, intlist *from ) {-	int i, n, nsave = to->n;+	int i, nsave, status = INTLIST_OK;++	assert( to );+	assert( from );++	nsave = to->n; 	for ( i=0; i<from->n; ++i ) { 		if ( intlist_find( to, from->data[i] )!=-1 ) continue;-		n = intlist_add( to, from->data[i] );-		if ( n==-1 ) {+		status = intlist_add( to, from->data[i] );+		if ( status==INTLIST_MEMERR ) { 			to->n = nsave;-			return -1; 		} 	}-	return to->n;+	return status; }  int intlist_get( intlist *il, int pos ) {-	if ( pos<0 || pos>=il->n ) return 0;-	else return il->data[pos];+	assert( il );+	assert( intlist_validn( il, pos ) );++	return il->data[pos]; }  /* intlist_set()  *- *   Returns 1 on success, 0 on failure+ *   Returns INTLIST_OK  */ int intlist_set( intlist *il, int pos, int value ) {-	if ( pos<0 || pos>=il->n ) return 0;+	assert( il );+	assert( intlist_validn( il, pos ) );+ 	il->data[pos] = value;-	return 1;+	return INTLIST_OK; }  float@@ -339,6 +551,8 @@ 	float median; 	int m1, m2; +	assert( il );+ 	if ( il->n==0 ) return 0.0;  	tmp = intlist_dup( il );@@ -350,7 +564,7 @@ 		median = intlist_get( tmp, tmp->n / 2 ); 	} else { 		m1 = intlist_get( tmp, tmp->n / 2 );-		m2 = intlist_get( tmp, tmp->n / 2 + 1);+		m2 = intlist_get( tmp, tmp->n / 2 - 1); 		median = ( m1 + m2 ) / 2.0; 	} @@ -364,6 +578,8 @@ { 	float sum = 0.0; 	int i;++	assert( il );  	if ( il->n==0 ) return 0.0; 
bibutils/intlist.h view
@@ -1,9 +1,9 @@ /*  * intlist.h  *- * Copyright (c) Chris Putnam 2007-2013+ * Copyright (c) Chris Putnam 2007-2017  *- * Version 9/5/2013+ * Version 01/12/2017  *  * Source code released under the GPL version 2  *@@ -12,35 +12,41 @@ #ifndef INTLIST_H #define INTLIST_H -#include <stdio.h>-#include <stdlib.h>+#define INTLIST_OK            (0)+#define INTLIST_MEMERR        (-1)+#define INTLIST_VALUE_MISSING (-2)  typedef struct intlist { 	int n, max; 	int *data; } intlist; -extern void      intlist_init( intlist *il );-extern int       intlist_init_range( intlist *il, int low, int high, int step );-extern intlist * intlist_new( void );-extern intlist * intlist_new_range( int low, int high, int step );-extern void      intlist_delete( intlist *il );-extern void      intlist_sort( intlist *il );-extern void      intlist_randomize( intlist *il );-extern int       intlist_add( intlist *il, int value );-extern int       intlist_add_unique( intlist *il, int value );-extern int       intlist_find( intlist *il, int searchvalue );-extern int       intlist_find_or_add( intlist *il, int searchvalue );-extern void      intlist_empty( intlist *il );-extern void      intlist_free( intlist *il );-extern int       intlist_copy( intlist *to, intlist *from );-extern int       intlist_get( intlist *il, int pos );-extern int       intlist_set( intlist *il, int pos, int value );-extern int       intlist_remove( intlist *il, int searchvalue );-extern int       intlist_remove_pos( intlist *il, int pos );-extern int       intlist_append( intlist *to, intlist *from );-extern int       intlist_append_unique( intlist *to, intlist *from );-extern float     intlist_median( intlist *il );-extern float     intlist_mean( intlist *il );+void      intlist_init( intlist *il );+int       intlist_init_fill( intlist *il, int n, int value );+int       intlist_init_range( intlist *il, int low, int high, int step );+intlist * intlist_new( void );+intlist * intlist_new_fill( int n, int value );+intlist * intlist_new_range( int low, int high, int step );+void      intlist_delete( intlist *il );+void      intlist_sort( intlist *il );+void      intlist_randomize( intlist *il );+int       intlist_add( intlist *il, int value );+int       intlist_add_unique( intlist *il, int value );+int       intlist_fill( intlist *il, int n, int value );+int       intlist_fill_range( intlist *il, int low, int high, int step );+int       intlist_find( intlist *il, int searchvalue );+int       intlist_find_or_add( intlist *il, int searchvalue );+void      intlist_empty( intlist *il );+void      intlist_free( intlist *il );+int       intlist_copy( intlist *to, intlist *from );+intlist * intlist_dup( intlist *from );+int       intlist_get( intlist *il, int pos );+int       intlist_set( intlist *il, int pos, int value );+int       intlist_remove( intlist *il, int searchvalue );+int       intlist_remove_pos( intlist *il, int pos );+int       intlist_append( intlist *to, intlist *from );+int       intlist_append_unique( intlist *to, intlist *from );+float     intlist_median( intlist *il );+float     intlist_mean( intlist *il );  #endif
bibutils/is_ws.c view
@@ -1,7 +1,7 @@ /*  * is_ws.c  *- * Copyright (c) Chris Putnam 2003-2013+ * Copyright (c) Chris Putnam 2003-2017  *  * Source code released under the GPL version 2  *
bibutils/is_ws.h view
@@ -1,7 +1,7 @@ /*  * is_ws.h  *- * Copyright (c) Chris Putnam 2003-2013+ * Copyright (c) Chris Putnam 2003-2017  *  * Source code released under the GPL version 2  *
bibutils/isiin.c view
@@ -1,7 +1,7 @@ /*  * isiin.c  *- * Copyright (c) Chris Putnam 2004-2013+ * Copyright (c) Chris Putnam 2004-2017  *  * Program and source code released under the GPL version 2  *@@ -10,15 +10,23 @@ #include <stdlib.h> #include <string.h> #include "is_ws.h"-#include "newstr.h"-#include "newstr_conv.h"-#include "fields.h"+#include "str.h"+#include "str_conv.h" #include "name.h"-#include "title.h"-#include "serialno.h"+#include "fields.h" #include "reftypes.h"-#include "isiin.h"+#include "bibformats.h"+#include "generic.h" +extern variants isi_all[];+extern int isi_nall;++static int isiin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset );+static int isiin_typef( fields *isiin, char *filename, int nref, param *p );+static int isiin_convertf( fields *isiin, fields *info, int reftype, param *p );+static int isiin_processf( fields *isiin, char *p, char *filename, long nref, param *pm );++ /*****************************************************  PUBLIC: void isiin_initparams() *****************************************************/@@ -44,8 +52,8 @@ 	p->all      = isi_all; 	p->nall     = isi_nall; -	list_init( &(p->asis) );-	list_init( &(p->corps) );+	slist_init( &(p->asis) );+	slist_init( &(p->corps) );  	if ( !progname ) p->progname = NULL; 	else p->progname = strdup( progname );@@ -60,7 +68,7 @@  *   char 2 = uppercase alphabetic character or digit  */ static int-isiin_istag( char *buf )+is_isi_tag( char *buf ) { 	if ( ! (buf[0]>='A' && buf[0]<='Z') ) return 0; 	if ( ! (((buf[1]>='A' && buf[1]<='Z'))||(buf[1]>='0'&&buf[1]<='9')))@@ -69,14 +77,14 @@ }  static int-readmore( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line )+readmore( FILE *fp, char *buf, int bufsize, int *bufpos, str *line ) { 	if ( line->len ) return 1;-	else return newstr_fget( fp, buf, bufsize, bufpos, line );+	else return str_fget( fp, buf, bufsize, bufpos, line ); } -int-isiin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset )+static int+isiin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset ) { 	int haveref = 0, inref = 0; 	char *p;@@ -93,7 +101,7 @@ 			p += 3; 		} 		/* Each reference ends with 'ER ' */-		if ( isiin_istag( p ) ) {+		if ( is_isi_tag( p ) ) { 			if ( !strncmp( p, "FN ", 3 ) ) { 				if (strncasecmp( p, "FN ISI Export Format",20)){ 					fprintf( stderr, ": warning file FN type not '%s' not recognized.\n", /*r->progname,*/ p );@@ -104,20 +112,20 @@ 				} 			} else if ( !strncmp( p, "ER", 2 ) ) haveref = 1; 			else {-				newstr_addchar( reference, '\n' );-				newstr_strcat( reference, p );+				str_addchar( reference, '\n' );+				str_strcatc( reference, p ); 				inref = 1; 			}-			newstr_empty( line );+			str_empty( line ); 		} 		/* not a tag, but we'll append to the last values */ 		else if ( inref ) {-			newstr_addchar( reference, '\n' );-			newstr_strcat( reference, p );-			newstr_empty( line );+			str_addchar( reference, '\n' );+			str_strcatc( reference, p );+			str_empty( line ); 		} 		else {-			newstr_empty( line );+			str_empty( line ); 		} 	} 	return haveref;@@ -128,114 +136,159 @@ *****************************************************/  static char *-process_isiline( newstr *tag, newstr *data, char *p )+process_tagged_line( str *tag, str *data, char *p ) { 	int i;  	/* collect tag and skip past it */ 	i = 0; 	while ( i<2 && *p && *p!='\r' && *p!='\n') {-		newstr_addchar( tag, *p++ );+		str_addchar( tag, *p++ ); 		i++; 	} 	while ( *p==' ' || *p=='\t' ) p++; 	while ( *p && *p!='\r' && *p!='\n' )-		newstr_addchar( data, *p++ );-	newstr_trimendingws( data );+		str_addchar( data, *p++ );+	str_trimendingws( data ); 	while ( *p=='\r' || *p=='\n' ) p++; 	return p; } -int-isiin_processf( fields *isiin, char *p, char *filename, long nref )+static char *+process_untagged_line( str *data, char *p ) {-	int status, n, ret = 1;-	newstr tag, data;-	newstrs_init( &tag, &data, NULL );+	while ( *p==' ' || *p=='\t' ) p++;+	while ( *p && *p!='\r' && *p!='\n' )+		str_addchar( data, *p++ );+	str_trimendingws( data );+	while ( *p=='\r' || *p=='\n' ) p++;+	return p;+}++static int+add_tag_value( fields *isiin, str *tag, str *value, int *tag_added )+{+	int status;++	if ( str_has_value( value ) ) {+		status = fields_add( isiin, str_cstr( tag ), str_cstr( value ), 0 );+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;+		*tag_added = 1;+	}++	else {+		*tag_added = 0;+	}++	return BIBL_OK;+}++static int+merge_tag_value( fields *isiin, str *tag, str *value, int *tag_added )+{+	int n, status;++	if ( str_has_value( value ) ) {++		if ( *tag_added==1 ) {++			n = fields_num( isiin );+			if ( n==0 ) return BIBL_OK;++			/* only one AU or AF for list of authors */+			if ( !strcmp( str_cstr( tag ), "AU" ) ) {+				status = fields_add( isiin, "AU", str_cstr( value ), 0 );+				if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;+			} else if ( !strcmp( str_cstr( tag ), "AF" ) ) {+				status = fields_add( isiin, "AF", str_cstr( value ), 0 );+				if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;+			}+			/* otherwise append multiline data */+			else {+				str_addchar( &(isiin->data[n-1]),' ');+				str_strcat( &(isiin->data[n-1]), value );+				if ( str_memerr( &(isiin->data[n-1]) ) ) return BIBL_ERR_MEMERR;+			}+		}++		else {+                        status = fields_add( isiin, str_cstr( tag ), str_cstr( value ), 0 );+                        if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;+                        *tag_added = 1;+		}+	}++	return BIBL_OK;+}++static int+isiin_processf( fields *isiin, char *p, char *filename, long nref, param *pm )+{+	int status, tag_added = 0, ret = 1;+	str tag, value;++	strs_init( &tag, &value, NULL );+ 	while ( *p ) {-		newstrs_empty( &tag, &data, NULL );-		p = process_isiline( &tag, &data, p );-		if ( !data.len ) continue;-		if ( (tag.len>1) && isiin_istag( tag.data ) ) {-			status = fields_add( isiin, tag.data, data.data, 0 );-			if ( status!=FIELDS_OK ) {++		/* ...with tag, add */+		if ( is_isi_tag( p ) ) {+			str_empty( &tag );+			str_empty( &value );+			p = process_tagged_line( &tag, &value, p );+			status = add_tag_value( isiin, &tag, &value, &tag_added );+			if ( status!=BIBL_OK ) { 				ret = 0; 				goto out; 			}-		} else {-			n = fields_num( isiin );-			if ( n>0 ) {-				/* only one AU or AF for list of authors */-				if ( !strcmp( isiin->tag[n-1].data,"AU") ){-					status = fields_add( isiin, "AU", data.data, 0);-					if ( status!=FIELDS_OK ) ret = 0;-				} else if ( !strcmp( isiin->tag[n-1].data,"AF") ){-					status = fields_add( isiin, "AF", data.data, 0);-					if ( status!=FIELDS_OK ) ret = 0;-				}-				/* otherwise append multiline data */-				else {-					newstr_addchar( &(isiin->data[n-1]),' ');-					newstr_strcat( &(isiin->data[n-1]), data.data );-					if ( newstr_memerr( &(isiin->data[n-1]) ) ) ret = 0;-				}-				if ( ret==0 ) goto out;+		}++		/* ...untagged, merge -- one AU or AF for list of authors */+		else {+			str_empty( &value );+			p = process_untagged_line( &value, p );+			status = merge_tag_value( isiin, &tag, &value, &tag_added );+			if ( status!=BIBL_OK ) {+				ret = 0;+				goto out; 			} 		}+ 	} out:-	newstrs_free( &data, &tag, NULL );+	strs_free( &value, &tag, NULL ); 	return ret; }  /*****************************************************  PUBLIC: int isiin_typef() *****************************************************/-int-isiin_typef( fields *isiin, char *filename, int nref, param *p, variants *all, int nall )+static int+isiin_typef( fields *isiin, char *filename, int nref, param *p ) {-	char *refnum = "";-	int n, reftype, nrefnum;-	n = fields_find( isiin, "PT", 0 );-	nrefnum = fields_find ( isiin, "UT", 0 );-	if ( nrefnum!=-1 ) refnum = isiin->data[nrefnum].data;-	if ( n!=-1 )-		reftype = get_reftype( (isiin->data[n]).data, nref, p->progname, all, nall, refnum );-	else-		reftype = get_reftype( "", nref, p->progname, all, nall, refnum ); /* default */-	return reftype;+	int ntypename, nrefname, is_default;+	char *refname = "", *typename="";++	ntypename = fields_find( isiin, "PT", LEVEL_MAIN );+	nrefname  = fields_find( isiin, "UT", LEVEL_MAIN );++	if ( nrefname!=-1 )  refname  = fields_value( isiin, nrefname,  FIELDS_CHRP_NOUSE );+	if ( ntypename!=-1 ) typename = fields_value( isiin, ntypename, FIELDS_CHRP_NOUSE );++	return get_reftype( typename, nref, p->progname, p->all, p->nall, refname, &is_default, REFTYPE_CHATTY ); }  /*****************************************************  PUBLIC: int isiin_convertf(), returns BIBL_OK or BIBL_ERR_MEMERR *****************************************************/ -static int-isiin_keyword_process( fields *info, char *newtag, char *p, int level )-{-	int fstatus, status = BIBL_OK;-	newstr keyword;-	newstr_init( &keyword );-	while ( *p ) {-		p = newstr_cpytodelim( &keyword, skip_ws( p ), ";", 1 );-		if ( newstr_memerr( &keyword ) ) { status = BIBL_ERR_MEMERR; goto out; }-		if ( keyword.len ) {-			fstatus = fields_add( info, newtag, keyword.data, level );-			if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }-		}-	}-out:-	newstr_free( &keyword );-	return status;-}- /* pull off authors first--use AF before AU */ static int-isiin_addauthors( fields *isiin, fields *info, int reftype, variants *all, int nall, list *asis, list *corps )+isiin_addauthors( fields *isiin, fields *info, int reftype, variants *all, int nall, slist *asis, slist *corps ) { 	char *newtag, *authortype, use_af[]="AF", use_au[]="AU"; 	int level, i, n, has_af=0, has_au=0, nfields, ok;-	newstr *t, *d;+	str *t, *d;  	nfields = fields_num( isiin ); 	for ( i=0; i<nfields && has_af==0; ++i ) {@@ -259,6 +312,27 @@ 	return BIBL_OK; } +static int+isiin_keyword( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	int fstatus, status = BIBL_OK;+	char *p = invalue->data;+	str keyword;++	str_init( &keyword );+	while ( *p ) {+		p = str_cpytodelim( &keyword, skip_ws( p ), ";", 1 );+		if ( str_memerr( &keyword ) ) { status = BIBL_ERR_MEMERR; goto out; }+		if ( str_has_value( &keyword ) ) {+			fstatus = fields_add( bibout, outtag, keyword.data, level );+			if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }+		}+	}+out:+	str_free( &keyword );+	return status;+}+ static void isiin_report_notag( param *p, char *tag ) {@@ -269,79 +343,45 @@ }  static int-isiin_simple( fields *info, char *tag, char *value, int level )+isiin_convertf( fields *bibin, fields *bibout, int reftype, param *p ) {-	int fstatus = fields_add( info, tag, value, level );-	if ( fstatus==FIELDS_OK ) return BIBL_OK;-	else return BIBL_ERR_MEMERR;-}+	static int (*convertfns[NUM_REFTYPES])(fields *, int, str *, str *, int, param *, char *, fields *) = {+		[ 0 ... NUM_REFTYPES-1 ] = generic_null,+		[ SIMPLE       ] = generic_simple,+		[ TITLE        ] = generic_title,+		[ PERSON       ] = generic_person,+		[ SERIALNO     ] = generic_serialno,+		[ DATE         ] = generic_simple,+		[ NOTES        ] = generic_notes,+		[ KEYWORD      ] = isiin_keyword,+	}; -int-isiin_convertf( fields *isiin, fields *info, int reftype, param *p, variants *all, int nall )-{-	int process, level, i, n, nfields, ok, status;-	newstr *t, *d;-	char *newtag;+	int process, level, i, nfields, status;+	str *intag, *invalue;+	char *outtag; -	status = isiin_addauthors( isiin, info, reftype, all, nall, &(p->asis), &(p->corps) );+	status = isiin_addauthors( bibin, bibout, reftype, p->all, p->nall, &(p->asis), &(p->corps) ); 	if ( status!=BIBL_OK ) return status; -	nfields = fields_num( isiin );+	nfields = fields_num( bibin ); 	for ( i=0; i<nfields; ++i ) { -		t = fields_tag( isiin, i, FIELDS_STRP );-		if ( !strcasecmp( t->data, "AU" ) || !strcasecmp( t->data, "AF" ) )+		intag = fields_tag( bibin, i, FIELDS_STRP );+		if ( !strcasecmp( str_cstr( intag ), "AU" ) || !strcasecmp( str_cstr( intag ), "AF" ) ) 			continue; -		n = translate_oldtag( t->data, reftype, all, nall, &process, &level, &newtag );-		if ( n==-1 ) {-			isiin_report_notag( p, t->data );+		if ( !translate_oldtag( str_cstr( intag ), reftype, p->all, p->nall, &process, &level, &outtag ) ) {+			isiin_report_notag( p, str_cstr( intag ) ); 			continue; 		}-		if ( process == ALWAYS ) continue; /* add in core code */ -		d = fields_value( isiin, i, FIELDS_STRP );--		ok = 1;--		switch ( process ) {--		case SIMPLE:-		case DATE:-			status = isiin_simple( info, newtag, d->data, level );-			break;--		case PERSON:-			ok = name_add( info, newtag, d->data, level, &(p->asis), &(p->corps) );-			if ( ok ) status = BIBL_OK;-			else status = BIBL_ERR_MEMERR;-			break;--		case TITLE:-			ok = title_process( info, newtag, d->data, level, p->nosplittitle );-			if ( ok ) status = BIBL_OK;-			else status = BIBL_ERR_MEMERR;-			break;--		case KEYWORD:-			status = isiin_keyword_process( info, newtag, d->data, level );-			break;--		case SERIALNO:-			ok = addsn( info, d->data, level );-			if ( ok ) status = BIBL_OK;-			else status = BIBL_ERR_MEMERR;-			break;--		/* do nothing if process==TYPE || process==ALWAYS */-		default:-			status = BIBL_OK;-			break;--		}+		invalue = fields_value( bibin, i, FIELDS_STRP ); +		status = convertfns[ process ] ( bibin, i, intag, invalue, level, p, outtag, bibout ); 		if ( status!=BIBL_OK ) return status; 	}++	if ( status==BIBL_OK && p->verbose ) fields_report( bibout, stderr );  	return status; }
− bibutils/isiin.h
@@ -1,28 +0,0 @@-/*- * isiin.h- * - * Copyright (c) Chris Putnam 2004-2013- *- * Source code released under the GPL version 2- *- */-#ifndef ISIIN_H-#define ISIIN_H--#include "newstr.h"-#include "fields.h"-#include "reftypes.h"-#include "bibutils.h"--extern int isiin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );-extern int isiin_typef( fields *isiin, char *filename, int nref, param *p, variants *all, int nall );-extern int isiin_convertf( fields *isiin, fields *info, int reftype, param *p, variants *all, int nall );-extern int isiin_processf( fields *isiin, char *p, char *filename, long nref );--extern void isiin_initparams( param *p, const char *progname );--extern variants isi_all[];-extern int isi_nall;--#endif-
bibutils/isiout.c view
@@ -1,7 +1,7 @@ /*  * isiout.c  *- * Copyright (c) Chris Putnam 2008-2013+ * Copyright (c) Chris Putnam 2008-2017  *  * Source code released under the GPL version 2  *@@ -11,12 +11,16 @@ #include <string.h> #include <ctype.h> #include "utf8.h"-#include "newstr.h"+#include "str.h" #include "strsearch.h" #include "fields.h"+#include "title.h" #include "bibutils.h"-#include "isiout.h"+#include "bibformats.h" +static int  isiout_write( fields *info, FILE *fp, param *p, unsigned long refnum );+static void isiout_writeheader( FILE *outptr, param *p );+ void isiout_initparams( param *p, const char *progname ) {@@ -49,29 +53,18 @@         TYPE_BOOK    = 3, }; -static void-output_type( FILE *fp, int type )-{-	fprintf( fp, "PT " );-	if ( type==TYPE_ARTICLE ) fprintf( fp, "Journal" );-	else if ( type==TYPE_INBOOK ) fprintf( fp, "Chapter" );-	else if ( type==TYPE_BOOK ) fprintf( fp, "Book" );-	else fprintf( fp, "Unknown" );-	fprintf( fp, "\n" );-}- static int -get_type( fields *f )+get_type( fields *in ) {         int type = TYPE_UNKNOWN, i, n, level; 	char *tag, *value;-	n = fields_num( f );+	n = fields_num( in );         for ( i=0; i<n; ++i ) {-		tag = fields_tag( f, i, FIELDS_CHRP );+		tag = fields_tag( in, i, FIELDS_CHRP );                 if ( strcasecmp( tag, "GENRE" ) &&                      strcasecmp( tag, "NGENRE") ) continue;-		value = fields_value( f, i, FIELDS_CHRP );-		level = fields_level( f, i );+		value = fields_value( in, i, FIELDS_CHRP );+		level = fields_level( in, i );                 if ( !strcasecmp( value, "periodical" ) ||                      !strcasecmp( value, "academic journal" ) || 		     !strcasecmp( value, "journal article" ) ) {@@ -87,225 +80,297 @@ }  static void-output_titlecore( FILE *fp, fields *f, char *isitag, int level,-	char *maintag, char *subtag )+append_type( int type, fields *out, int *status ) {-	newstr *mainttl = fields_findv( f, level, FIELDS_STRP, maintag );-	newstr *subttl  = fields_findv( f, level, FIELDS_STRP, subtag );+	int fstatus;+	char *s; -	if ( !mainttl ) return;+	if ( type==TYPE_ARTICLE ) s = "Journal";+	else if ( type==TYPE_INBOOK ) s = "Chapter";+	else if ( type==TYPE_BOOK ) s = "Book";+	else s = "Unknown"; -	fprintf( fp, "%s %s", isitag, mainttl->data );-	if ( subttl ) {-		if ( mainttl->len > 0 &&-		     mainttl->data[ mainttl->len - 1 ]!='?' )-				fprintf( fp, ":" );-		fprintf( fp, " %s", subttl->data );+	fstatus = fields_add( out, "PT", s, LEVEL_MAIN );+	if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+}++static void+append_titlecore( fields *in, char *isitag, int level, char *maintag, char *subtag, fields *out, int *status )+{+	str *mainttl = fields_findv( in, level, FIELDS_STRP, maintag );+	str *subttl  = fields_findv( in, level, FIELDS_STRP, subtag );+	str fullttl;+	int fstatus;++	str_init( &fullttl );+	title_combine( &fullttl, mainttl, subttl );++	if ( str_memerr( &fullttl ) ) {+		*status = BIBL_ERR_MEMERR;+		goto out; 	}-	fprintf( fp, "\n" );++	if ( str_has_value( &fullttl ) ) {+		fstatus = fields_add( out, isitag, str_cstr( &fullttl ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	}+out:+	str_free( &fullttl ); }  static void-output_title( FILE *fp, fields *f, char *isitag, int level )+append_title( fields *in, char *isitag, int level, fields *out, int *status ) {-	output_titlecore( fp, f, isitag, level, "TITLE", "SUBTITLE" );+	append_titlecore( in, isitag, level, "TITLE", "SUBTITLE", out, status ); }  static void-output_abbrtitle( FILE *fp, fields *f, char *isitag, int level )+append_abbrtitle( fields *in, char *isitag, int level, fields *out, int *status ) {-	output_titlecore( fp, f, isitag, level, "SHORTTITLE", "SHORTSUBTITLE" );+	append_titlecore( in, isitag, level, "SHORTTITLE", "SHORTSUBTITLE", out, status ); }  static void-output_keywords( FILE *fp, fields *f )+append_keywords( fields *in, fields *out, int *status ) {+	vplist_index i;+	str keywords;+	int fstatus; 	vplist kw;-	int i;++	str_init( &keywords ); 	vplist_init( &kw );-	fields_findv_each( f, LEVEL_ANY, FIELDS_CHRP, &kw, "KEYWORD" );++	fields_findv_each( in, LEVEL_ANY, FIELDS_STRP, &kw, "KEYWORD" ); 	if ( kw.n ) {-		fprintf( fp, "DE " ); 		for ( i=0; i<kw.n; ++i ) {-			if ( i>0 ) fprintf( fp, "; " );-			fprintf( fp, "%s", (char *)vplist_get( &kw, i ) );+			if ( i>0 ) str_strcatc( &keywords, "; " );+			str_strcat( &keywords, (str *) vplist_get( &kw, i ) ); 		}-		fprintf( fp, "\n" );+		if ( str_memerr( &keywords ) ) { *status = BIBL_ERR_MEMERR; goto out; }+		fstatus = fields_add( out, "DE", str_cstr( &keywords ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) { *status = BIBL_ERR_MEMERR; goto out; } 	}+out: 	vplist_free( &kw );+	str_free( &keywords ); }  static void-output_person( FILE *fp, char *name )+process_person( str *person, char *name ) {-	newstr family, given, suffix;+	str family, given, suffix; 	char *p = name; -	newstrs_init( &family, &given, &suffix, NULL );+	str_empty( person ); +	strs_init( &family, &given, &suffix, NULL );+ 	while ( *p && *p!='|' )-		newstr_addchar( &family, *p++ );+		str_addchar( &family, *p++ );  	while ( *p=='|' && *(p+1)!='|' ) { 		p++;-		if ( *p!='|' ) newstr_addchar( &given, *p++ );+		if ( *p!='|' ) str_addchar( &given, *p++ ); 		while ( *p && *p!='|' ) p++; 	}  	if ( *p=='|' && *(p+1)=='|' ) { 		p += 2;-		while ( *p && *p!='|' ) newstr_addchar( &suffix, *p++ );+		while ( *p && *p!='|' ) str_addchar( &suffix, *p++ ); 	} -	if ( family.len ) fprintf( fp, "%s", family.data );-	if ( suffix.len ) {-		if ( family.len ) fprintf( fp, " %s", suffix.data );-		else fprintf( fp, "%s", suffix.data );+	if ( str_has_value( &family ) ) str_strcat( person, &family );+	if ( str_has_value( &suffix ) ) {+		if ( str_has_value( &family ) ) str_strcatc( person, " " );+		str_strcat( person, &suffix ); 	}-	if ( given.len ) fprintf( fp, ", %s", given.data );+	if ( str_has_value( &given ) ) {+		if ( str_has_value( person ) ) str_strcatc( person, ", " );+		str_strcat( person, &given );+	} -	newstrs_free( &family, &given, &suffix, NULL );+	strs_free( &family, &given, &suffix, NULL ); }  static void-output_people( FILE *fp, fields *f, char *tag, char *isitag, int level )+append_people( fields *f, char *tag, char *isitag, int level, fields *out, int *status ) {+	vplist_index i; 	vplist people;-	int i;+	str person;+	int fstatus;++	str_init( &person ); 	vplist_init( &people );+ 	fields_findv_each( f, level, FIELDS_CHRP, &people, tag );-	if ( people.n ) {-		fprintf( fp, "%s ", isitag );-		for ( i=0; i<people.n; ++i ) {-			if ( i!=0 ) fprintf( fp, "   " );-			output_person( fp, (char *)vplist_get( &people, i ) );-			fprintf( fp, "\n" );-		}+	for ( i=0; i<people.n; ++i ) {+		process_person( &person, (char *)vplist_get( &people, i ) );+		if ( str_memerr( &person ) ) { *status = BIBL_ERR_MEMERR; goto out; }+		if ( i==0 ) fstatus = fields_add_can_dup( out, isitag, str_cstr( &person ), LEVEL_MAIN );+		else        fstatus = fields_add_can_dup( out, "  ",   str_cstr( &person ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) { *status = BIBL_ERR_MEMERR; goto out; } 	}++out: 	vplist_free( &people );+	str_free( &person ); }  static void-output_easy( FILE *fp, fields *f, char *tag, char *isitag, int level )+append_easy( fields *in, char *tag, char *isitag, int level, fields *out, int *status ) {-	char *value = fields_findv( f, level, FIELDS_CHRP, tag );-	if ( value ) fprintf( fp, "%s %s\n", isitag, value );+	char *value;+	int fstatus;++	value = fields_findv( in, level, FIELDS_CHRP, tag );+	if ( value ) {+		fstatus = fields_add( out, isitag, value, LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	} }  static void-output_easyall( FILE *fp, fields *f, char *tag, char *isitag, int level )+append_easyall( fields *in, char *tag, char *isitag, int level, fields *out, int *status ) {+	vplist_index i;+	int fstatus; 	vplist a;-	int i;+ 	vplist_init( &a );-	fields_findv_each( f, level, FIELDS_CHRP, &a, tag );-	for ( i=0; i<a.n; ++i )-		fprintf( fp, "%s %s\n", isitag, (char *) vplist_get( &a, i ) );+	fields_findv_each( in, level, FIELDS_CHRP, &a, tag );+	for ( i=0; i<a.n; ++i ) {+		fstatus = fields_add( out, isitag, (char *) vplist_get( &a, i ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	} 	vplist_free( &a ); }  static void-output_date( FILE *fp, fields *f )+append_date( fields *in, fields *out, int *status ) {-	char *month = fields_findv_firstof( f, LEVEL_ANY, FIELDS_CHRP,-		"PARTMONTH", "MONTH", NULL );-	char *year  = fields_findv_firstof( f, LEVEL_ANY, FIELDS_CHRP,-		"PARTYEAR", "YEAR", NULL );-	if ( month ) fprintf( fp, "PD %s\n", month );-	if ( year )  fprintf( fp, "PY %s\n", year );+	char *month, *year;+	int fstatus;++	month = fields_findv_firstof( in, LEVEL_ANY, FIELDS_CHRP, "PARTDATE:MONTH", "DATE:MONTH", NULL );+	if ( month ) {+		fstatus = fields_add( out, "PD", month, LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	}+	year  = fields_findv_firstof( in, LEVEL_ANY, FIELDS_CHRP, "PARTDATE:YEAR",  "DATE:YEAR",  NULL );+	if ( year ) {+		fstatus = fields_add( out, "PY", year, LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	} } +static int+append_data( fields *in, fields *out )+{+	int type, status = BIBL_OK;++	type = get_type( in );++	append_type   ( type, out, &status );+	append_people ( in, "AUTHOR",      "AU", LEVEL_MAIN, out, &status );+	append_easyall( in, "AUTHOR:CORP", "AU", LEVEL_MAIN, out, &status );+	append_easyall( in, "AUTHOR:ASIS", "AU", LEVEL_MAIN, out, &status );++	append_title  ( in, "TI", LEVEL_MAIN, out, &status );+	if ( type==TYPE_ARTICLE ) {+		append_title( in, "SO", LEVEL_HOST,   out, &status );+		append_abbrtitle( in, "JI", LEVEL_HOST, out, &status );+		append_title( in, "SE", LEVEL_SERIES, out, &status );+	} else if ( type==TYPE_INBOOK ) {+		append_title( in, "BT", LEVEL_HOST,   out, &status );+		append_title( in, "SE", LEVEL_SERIES, out, &status );+	} else { /* type==BOOK */+		append_title( in, "SE", LEVEL_HOST,   out, &status );+	}++	append_date( in, out, &status );++	append_easy( in, "PAGES:START",    "BP", LEVEL_ANY, out, &status );+	append_easy( in, "PAGES:STOP",     "EP", LEVEL_ANY, out, &status );+	append_easy( in, "ARTICLENUMBER",  "AR", LEVEL_ANY, out, &status );+	append_easy( in, "PAGES:TOTAL",    "PG", LEVEL_ANY, 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, "DOI",            "DI", LEVEL_ANY, out, &status );+	append_easy( in, "ISIREFNUM",      "UT", LEVEL_ANY, out, &status );+	append_easy( in, "LANGUAGE",       "LA", LEVEL_ANY, out, &status );+	append_easy( in, "ISIDELIVERNUM",  "GA", LEVEL_ANY, out, &status );+	append_keywords( in, out, &status );+	append_easy( in, "ABSTRACT",       "AB", LEVEL_ANY, out, &status );+	append_easy( in, "TIMESCITED",     "TC", LEVEL_ANY, out, &status );+	append_easy( in, "NUMBERREFS",     "NR", LEVEL_ANY, out, &status );+	append_easy( in, "CITEDREFS",      "CR", LEVEL_ANY, out, &status );+	append_easy( in, "ADDRESS",        "PI", LEVEL_ANY, out, &status );++	return status;+}+ static void-output_verbose( fields *f, unsigned long refnum )+output_verbose( fields *f, const char *type, unsigned long refnum ) { 	char *tag, *value; 	int i, n, level;-	fprintf( stderr, "REF #%lu----\n", refnum+1 );++	fprintf( stderr, "REF #%lu %s---\n", refnum+1, type );+ 	n = fields_num( f ); 	for ( i=0; i<n; ++i ) { 		tag   = fields_tag( f, i, FIELDS_CHRP_NOUSE ); 		value = fields_value( f, i, FIELDS_CHRP_NOUSE ); 		level = fields_level( f, i );-		fprintf( stderr, "\t'%s'\t'%s'\t%d\n",-			tag, value, level );+		fprintf( stderr, "\t'%s'\t'%s'\t%d\n", tag, value, level ); 	}++	fflush( stderr ); } -void-isiout_write( fields *f, FILE *fp, param *p, unsigned long refnum )+static void+output( FILE *fp, fields *out ) {-        int type = get_type( f );+	int i; -	if ( p->format_opts & BIBL_FORMAT_VERBOSE )-		output_verbose( f, refnum );+	for ( i=0; i<out->n; ++i ) {+		fprintf( fp, "%s %s\n",+			( char * ) fields_tag  ( out, i, FIELDS_CHRP ),+			( char * ) fields_value( out, i, FIELDS_CHRP )+		);+	}+        fprintf( fp, "ER\n\n" );+        fflush( fp );+} -        output_type( fp, type );-	output_people( fp, f, "AUTHOR", "AU", 0 );-	output_easyall( fp, f, "AUTHOR:CORP", "AU", 0 );-	output_easyall( fp, f, "AUTHOR:ASIS", "AU", 0 );-/*      output_people( fp, f, "AUTHOR", "A2", 1 );-        output_people( fp, f, "AUTHOR:CORP", "A2", 1 );-        output_people( fp, f, "AUTHOR:ASIS", "A2", 1 );-        output_people( fp, f, "AUTHOR", "A3", 2 );-        output_people( fp, f, "AUTHOR:CORP", "A3", 2 );-        output_people( fp, f, "AUTHOR:ASIS", "A3", 2 );-        output_people( fp, f, "EDITOR", "ED", -1 );-	output_people( fp, f, "EDITOR:CORP", "ED", -1 );-        output_people( fp, f, "EDITOR:ASIS", "ED", -1 );*/-/*        output_date( fp, f, refnum );*/+static int+isiout_write( fields *in, FILE *fp, param *p, unsigned long refnum )+{+	int status;+	fields out; -        output_title( fp, f, "TI", 0 );-        if ( type==TYPE_ARTICLE ) {-		output_title( fp, f, "SO", 1 );-		output_abbrtitle( fp, f, "JI", 1 );-		output_title( fp, f, "SE", 2 );-	} else if ( type==TYPE_INBOOK ) {-		output_title( fp, f, "BT", 1 );-		output_title( fp, f, "SE", 2 );-	} else { /* type==BOOK */-		output_title( fp, f, "SE", 1 );-	}+	fields_init( &out ); -	output_date( fp, f );-/*	output_easy( fp, f, "PARTMONTH", "PD", -1 );-	output_easy( fp, f, "PARTYEAR", "PY", -1 );*/+	if ( p->format_opts & BIBL_FORMAT_VERBOSE )+		output_verbose( in, "IN", refnum ); -	output_easy( fp, f, "PAGESTART", "BP", -1 );-	output_easy( fp, f, "PAGEEND",   "EP", -1 );-        output_easy( fp, f, "ARTICLENUMBER", "AR", -1 );-        /* output article number as pages */-	output_easy( fp, f, "TOTALPAGES","PG", -1 );+	status = append_data( in, &out ); -        output_easy( fp, f, "VOLUME",    "VL", -1 );-        output_easy( fp, f, "ISSUE",     "IS", -1 );-        output_easy( fp, f, "NUMBER",    "IS", -1 );-	output_easy( fp, f, "DOI",       "DI", -1 );-	output_easy( fp, f, "ISIREFNUM", "UT", -1 );-	output_easy( fp, f, "LANGUAGE",  "LA", -1 );-	output_easy( fp, f, "ISIDELIVERNUM", "GA", -1 );-	output_keywords( fp, f );-	output_easy( fp, f, "ABSTRACT",  "AB", -1 );-	output_easy( fp, f, "TIMESCITED", "TC", -1 );-	output_easy( fp, f, "NUMBERREFS", "NR", -1 );-	output_easy( fp, f, "CITEDREFS",  "CR", -1 );-	output_easy( fp, f, "ADDRESS",    "PI", -1 );+	if ( status==BIBL_OK ) output( fp, &out ); -/*        output_easy( fp, f, "PUBLISHER", "PB", -1 );-        output_easy( fp, f, "DEGREEGRANTOR", "PB", -1 );-        output_easy( fp, f, "ADDRESS", "CY", -1 );-        output_easy( fp, f, "ABSTRACT", "AB", -1 );-        output_easy( fp, f, "ISSN", "SN", -1 );-        output_easy( fp, f, "ISBN", "SN", -1 );-        output_easyall( fp, f, "URL", "UR", -1 );-        output_easyall( fp, f, "FILEATTACH", "UR", -1 );-        output_pubmed( fp, f, refnum );-        output_easyall( fp, f, "NOTES", "N1", -1 );-        output_easyall( fp, f, "REFNUM", "ID", -1 );*/-        fprintf( fp, "ER\n\n" );-        fflush( fp );+	if ( p->format_opts & BIBL_FORMAT_VERBOSE )+		output_verbose( &out, "OUT", refnum );++	fields_free( &out );++	return status; } -void+static void isiout_writeheader( FILE *outptr, param *p ) { 	if ( p->utf8bom ) utf8_writebom( outptr );
− bibutils/isiout.h
@@ -1,21 +0,0 @@-/*- * isiout.h- *- * Copyright (c) Chris Putnam 2007-2013- *- * Source code released under the GPL version 2- *- */-#ifndef ISIOUT_H-#define ISIOUT_H--#include <stdio.h>-#include "bibutils.h"--extern void isiout_write( fields *info, FILE *fp, param *p,-		unsigned long refnum );-extern void isiout_writeheader( FILE *outptr, param *p );--extern void isiout_initparams( param *p, const char *progname );--#endif
bibutils/isitypes.c view
@@ -1,7 +1,7 @@ /*  * isitypes.c  *- * Copyright (c) Chris Putnam 2004-2013+ * Copyright (c) Chris Putnam 2004-2017  *  * Program and source code released under the GPL version 2  *@@ -24,17 +24,17 @@ 	{ "C1",     "ADDRESS",   SIMPLE, LEVEL_MAIN }, /* author address */ 	{ "PA",     "ADDRESS",   SIMPLE, LEVEL_HOST }, /* publisher address */ 	{ "RP",     "REPRINTADDRESS", SIMPLE, LEVEL_MAIN },-	{ "PY",     "PARTYEAR",  SIMPLE, LEVEL_MAIN },-	{ "PD",     "PARTMONTH", SIMPLE, LEVEL_MAIN },+	{ "PY",     "PARTDATE:YEAR",  SIMPLE, LEVEL_MAIN },+	{ "PD",     "PARTDATE:MONTH", SIMPLE, LEVEL_MAIN }, 	{ "VL",     "VOLUME",    SIMPLE, LEVEL_MAIN }, 	{ "AR",     "ARTICLENUMBER", SIMPLE, LEVEL_MAIN }, /* AR=article number that Phys. Rev. B uses instead of page numbers */-	{ "BP",     "PAGESTART", SIMPLE, LEVEL_MAIN },-	{ "EP",     "PAGEEND",   SIMPLE, LEVEL_MAIN },-	{ "PG",     "TOTALPAGES", SIMPLE, LEVEL_MAIN },+	{ "BP",     "PAGES:START", SIMPLE, LEVEL_MAIN },+	{ "EP",     "PAGES:STOP",   SIMPLE, LEVEL_MAIN },+	{ "PG",     "PAGES:TOTAL", SIMPLE, LEVEL_MAIN }, 	{ "IS",     "ISSUE",     SIMPLE, LEVEL_MAIN }, 	{ "SN",     "SERIALNUMBER", SERIALNO, LEVEL_HOST }, 	{ "AB",     "ABSTRACT",  SIMPLE, LEVEL_MAIN },-	{ "NF",     "NOTES",     SIMPLE, LEVEL_MAIN },+	{ "NF",     "NOTES",     NOTES,  LEVEL_MAIN }, 	{ "DE",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* author keywords */ 	{ "ID",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* new ISI keywords */ 	{ "LA",     "LANGUAGE",  SIMPLE, LEVEL_MAIN },@@ -67,16 +67,16 @@ 	{ "C1",     "ADDRESS",   SIMPLE, LEVEL_MAIN }, /* author address */ 	{ "PA",     "ADDRESS",   SIMPLE, LEVEL_MAIN }, /* publisher address */ 	{ "RP",     "REPRINTADDRESS", SIMPLE, LEVEL_MAIN },-	{ "PY",     "YEAR",      SIMPLE, LEVEL_MAIN },-	{ "PD",     "MONTH",     SIMPLE, LEVEL_MAIN },+	{ "PY",     "DATE:YEAR",      SIMPLE, LEVEL_MAIN },+	{ "PD",     "DATE:MONTH",     SIMPLE, LEVEL_MAIN }, 	{ "VL",     "VOLUME",    SIMPLE, LEVEL_MAIN },-	{ "BP",     "PAGESTART", SIMPLE, LEVEL_MAIN },-	{ "EP",     "PAGEEND",   SIMPLE, LEVEL_MAIN },-	{ "PG",     "TOTALPAGES", SIMPLE, LEVEL_MAIN },-	{ "IS",     "ISSUE",     SIMPLE, LEVEL_MAIN },+	{ "BP",     "PAGES:START", SIMPLE, LEVEL_MAIN },+	{ "EP",     "PAGES:STOP",  SIMPLE, LEVEL_MAIN },+	{ "PG",     "PAGES:TOTAL", SIMPLE, LEVEL_MAIN },+	{ "IS",     "ISSUE",       SIMPLE, LEVEL_MAIN }, 	{ "SN",     "SERIALNUMBER", SERIALNO, LEVEL_HOST }, 	{ "AB",     "ABSTRACT",  SIMPLE, LEVEL_MAIN },-	{ "NF",     "NOTES",     SIMPLE, LEVEL_MAIN },+	{ "NF",     "NOTES",     NOTES,  LEVEL_MAIN }, 	{ "DE",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* author keywords */ 	{ "ID",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* new ISI keywords */ 	{ "LA",     "LANGUAGE",  SIMPLE, LEVEL_MAIN },@@ -108,16 +108,16 @@ 	{ "C1",     "ADDRESS",   SIMPLE, LEVEL_MAIN }, /* author address */ 	{ "PA",     "ADDRESS",   SIMPLE, LEVEL_HOST }, /* publisher address */ 	{ "RP",     "REPRINTADDRESS", SIMPLE, LEVEL_MAIN },-	{ "PY",     "PARTYEAR",  SIMPLE, LEVEL_MAIN },-	{ "PD",     "PARTMONTH", SIMPLE, LEVEL_MAIN },+	{ "PY",     "PARTDATE:YEAR",  SIMPLE, LEVEL_MAIN },+	{ "PD",     "PARTDATE:MONTH", SIMPLE, LEVEL_MAIN }, 	{ "VL",     "VOLUME",    SIMPLE, LEVEL_MAIN },-	{ "BP",     "PAGESTART", SIMPLE, LEVEL_MAIN },-	{ "EP",     "PAGEEND",   SIMPLE, LEVEL_MAIN },-	{ "PG",     "TOTALPAGES", SIMPLE, LEVEL_HOST },-	{ "IS",     "ISSUE",     SIMPLE, LEVEL_MAIN },+	{ "BP",     "PAGES:START", SIMPLE, LEVEL_MAIN },+	{ "EP",     "PAGES:STOP",  SIMPLE, LEVEL_MAIN },+	{ "PG",     "PAGES:TOTAL", SIMPLE, LEVEL_HOST },+	{ "IS",     "ISSUE",       SIMPLE, LEVEL_MAIN }, 	{ "SN",     "SERIALNUMBER", SERIALNO, LEVEL_HOST }, 	{ "AB",     "ABSTRACT",  SIMPLE, LEVEL_MAIN },-	{ "NF",     "NOTES",     SIMPLE, LEVEL_MAIN },+	{ "NF",     "NOTES",     NOTES,  LEVEL_MAIN }, 	{ "DE",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* author keywords */ 	{ "ID",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* new ISI keywords */ 	{ "LA",     "LANGUAGE",  SIMPLE, LEVEL_MAIN },@@ -150,16 +150,16 @@ 	{ "C1",     "ADDRESS",   SIMPLE, LEVEL_MAIN }, /* author address */ 	{ "PA",     "ADDRESS",   SIMPLE, LEVEL_HOST }, /* publisher address */ 	{ "RP",     "REPRINTADDRESS", SIMPLE, LEVEL_MAIN },-	{ "PY",     "PARTYEAR",  SIMPLE, LEVEL_MAIN },-	{ "PD",     "PARTMONTH", SIMPLE, LEVEL_MAIN },+	{ "PY",     "PARTDATE:YEAR",  SIMPLE, LEVEL_MAIN },+	{ "PD",     "PARTDATE:MONTH", SIMPLE, LEVEL_MAIN }, 	{ "VL",     "VOLUME",    SIMPLE, LEVEL_MAIN },-	{ "BP",     "PAGESTART", SIMPLE, LEVEL_MAIN },-	{ "EP",     "PAGEEND",   SIMPLE, LEVEL_MAIN },-	{ "PG",     "TOTALPAGES", SIMPLE, LEVEL_MAIN },+	{ "BP",     "PAGES:START", SIMPLE, LEVEL_MAIN },+	{ "EP",     "PAGES:STOP",  SIMPLE, LEVEL_MAIN },+	{ "PG",     "PAGES:TOTAL", SIMPLE, LEVEL_MAIN }, 	{ "IS",     "ISSUE",     SIMPLE, LEVEL_MAIN }, 	{ "SN",     "SERIALNUMBER", SERIALNO, LEVEL_HOST }, 	{ "AB",     "ABSTRACT",  SIMPLE, LEVEL_MAIN },-	{ "NF",     "NOTES",     SIMPLE, LEVEL_MAIN },+	{ "NF",     "NOTES",     NOTES,  LEVEL_MAIN }, 	{ "DE",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* author keywords */ 	{ "ID",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* new ISI keywords */ 	{ "LA",     "LANGUAGE",  SIMPLE, LEVEL_MAIN },
bibutils/latex.c view
@@ -3,489 +3,493 @@  *  * convert between latex special chars and unicode  *- * Copyright (c) Chris Putnam 2004-2013+ * Copyright (c) Chris Putnam 2004-2017  *  * Source code released under the GPL version 2  *  */ #include <stdio.h>+#include <stdlib.h> #include <string.h> #include "latex.h" +#define LATEX_COMBO (0)  /* 'combo' no need for protection on output */+#define LATEX_MACRO (1)  /* 'macro_name' to be protected by {\macro_name} on output */+#define LATEX_MATH  (2)  /* 'math_expression' to be protected by $math_expression$ on output */+ struct latex_chars {-	unsigned int unicode;-	char *bib1, *bib2, *bib3;+	unsigned int unicode;      /* unicode code point */+	unsigned char type;        /* LATEX_COMBO/LATEX_MACRO/LATEX_MATH */+	char *out;                 /* unadorned latex combination for output */+	char *variant[3];         /* possible variations on input */ };  static struct latex_chars latex_chars[] = {  -   {  35, "\\#",     "",   ""        },    /* Number/pound/hash sign */-   {  36, "\\$",     "",   ""        },    /* Dollar Sign */-   {  37, "\\%",     "",   ""        },    /* Percent Sign */-   {  38, "\\&",     "",   ""        },    /* Ampersand */-   {  92, "{\\backslash}", "\\backslash", ""   }, /* Backslash */-   { 123, "\\{", "{\\textbraceleft}", "\\textbraceleft" }, /* Left Curly Bracket */-   { 125, "\\}", "{\\textbraceright}", "\\textbraceright" }, /* Right Curly Bracket */-   {  95, "\\_",     "", ""        },      /* Underscore alone indicates subscript */-   { 176, "{\\textdegree}", "\\textdegree", "^\\circ" }, /* Degree sign */-/* fix sticky spaces in bibtex token cleaning--allows tokens to be parsed properly */-/*   {  32, "~",       "\\ ", ""        }, */   /* "sticky" space */-   {  32, "\\ ",     "",   ""           },      /* escaping the space is used to avoid extra space after periods */-   { 126, "{\\textasciitilde}", "\\textasciitilde", "\\~{}" }, /* Tilde in latex */-                                 /* This is a cheat, should use "\verb" */-                                 /* Need same for ^ character */+                                            /* LaTeX special characters */+   {  32, LATEX_COMBO, " ",              { "\\ ",                NULL,                 NULL               } }, /* escaping the space is used to avoid extra space after periods */+   {  35, LATEX_MACRO, "#",              { "\\#",                NULL,                 NULL               } }, /* Number/pound/hash sign */+   {  36, LATEX_MACRO, "$",              { "\\$",                NULL,                 NULL               } }, /* Dollar Sign */+   {  37, LATEX_MACRO, "%",              { "\\%",                NULL,                 NULL               } }, /* Percent Sign */+   {  38, LATEX_MACRO, "&",              { "\\&",                NULL,                 NULL               } }, /* Ampersand */+   {  95, LATEX_MACRO, "_",              { "\\_",                NULL,                 NULL               } }, /* Underscore alone indicates subscript */+   { 123, LATEX_MACRO, "{",              { "\\{",                "{\\textbraceleft}",  "\\textbraceleft"  } }, /* Left Curly Bracket */+   { 125, LATEX_MACRO, "}",              { "\\}",                "{\\textbraceright}", "\\textbraceright" } }, /* Right Curly Bracket */+   {  92, LATEX_MACRO, "backslash",      { "{\\backslash}",      "\\backslash",        NULL               } }, /* Backslash */+   { 176, LATEX_MACRO, "textdegree",     { "{\\textdegree}",     "\\textdegree",       "^\\circ"          } }, /* Degree sign */+   { 126, LATEX_MACRO, "textasciitilde", { "{\\textasciitilde}", "\\textasciitilde",   "\\~{}"            } }, /* Tilde in latex */+/* fix sticky spaces "~" in bibtex token cleaning--allows tokens to be parsed properly */ -                                           /* Latin Capital A */-   { 192, "{\\`A}",  "\\`{A}",  "\\`A"  }, /*               with grave */-   { 193, "{\\'A}",  "\\'{A}",  "\\'A"  }, /*               with acute */-   { 194, "{\\^A}",  "\\^{A}",  "\\^A"  }, /*               with circumflex */-   { 195, "{\\~A}",  "\\~{A}",  "\\~A"  }, /*               with tilde */-   { 196, "{\\\"A}", "\\\"{A}", "\\\"A" }, /*               with diuresis */-   { 197, "{\\AA}",  "{\\r{A}}","\\r{A}"}, /*               with ring above */-   { 256, "{\\={A}}","\\={A}",  "\\=A"  }, /*               with macron */-   { 258, "{\\u{A}}","\\u{A}",  "\\u A" }, /*               with breve */-   { 260, "{\\k{A}}","\\k{A}",  "\\k A" }, /*               with ogonek */-   { 461, "{\\v{A}}","\\v{A}",  "\\v A" }, /*               with caron */+                                            /* Latin Capital A */+   { 192, LATEX_MACRO, "`A",   { "{\\`A}",   "\\`{A}",   "\\`A"  } }, /*               with grave */+   { 193, LATEX_MACRO, "'A",   { "{\\'A}",   "\\'{A}",   "\\'A"  } }, /*               with acute */+   { 194, LATEX_MACRO, "^A",   { "{\\^A}",   "\\^{A}",   "\\^A"  } }, /*               with circumflex */+   { 195, LATEX_MACRO, "~A",   { "{\\~A}",   "\\~{A}",   "\\~A"  } }, /*               with tilde */+   { 196, LATEX_MACRO, "\"A",  { "{\\\"A}",  "\\\"{A}",  "\\\"A" } }, /*               with diuresis */+   { 197, LATEX_MACRO, "AA",   { "{\\AA}",   "{\\r{A}}", "\\r{A}"} }, /*               with ring above */+   { 256, LATEX_MACRO, "={A}", { "{\\={A}}", "\\={A}",   "\\=A"  } }, /*               with macron */+   { 258, LATEX_MACRO, "u{A}", { "{\\u{A}}", "\\u{A}",   "\\u A" } }, /*               with breve */+   { 260, LATEX_MACRO, "k{A}", { "{\\k{A}}", "\\k{A}",   "\\k A" } }, /*               with ogonek */+   { 461, LATEX_MACRO, "v{A}", { "{\\v{A}}", "\\v{A}",   "\\v A" } }, /*               with caron */                                             /* Latin Small a */-   { 224, "{\\`a}",  "\\`{a}",  "\\`a"  }, /*               with grave */-   { 225, "{\\'a}",  "\\'{a}",  "\\'a"  }, /*               with acute */-   { 226, "{\\^a}",  "\\^{a}",  "\\^a"  }, /*               with circumflex */-   { 227, "{\\~a}",  "\\~{a}",  "\\~a"  }, /*               with tilde */-   { 228, "{\\\"a}", "\\\"{a}", "\\\"a" }, /*               with diuresis */-   { 229, "{\\aa}",  "{\\r{a}}","\\r{a}"}, /*               with ring above */-   { 257, "{\\={a}}","\\={a}",  "\\=a"  }, /*               with macron */-   { 259, "{\\u{a}}","\\u{a}",  "\\u a" }, /*               with breve */-   { 261, "{\\k{a}}","\\k{a}",  "\\k a" }, /*               with ogonek */-   { 462, "{\\v{a}}","\\v{a}",  "\\v a" }, /*               with caron */+   { 224, LATEX_MACRO, "`a",   { "{\\`a}",   "\\`{a}",   "\\`a"  } }, /*               with grave */+   { 225, LATEX_MACRO, "'a",   { "{\\'a}",   "\\'{a}",   "\\'a"  } }, /*               with acute */+   { 226, LATEX_MACRO, "^a",   { "{\\^a}",   "\\^{a}",   "\\^a"  } }, /*               with circumflex */+   { 227, LATEX_MACRO, "~a",   { "{\\~a}",   "\\~{a}",   "\\~a"  } }, /*               with tilde */+   { 228, LATEX_MACRO, "\"a",  { "{\\\"a}",  "\\\"{a}",  "\\\"a" } }, /*               with diuresis */+   { 229, LATEX_MACRO, "aa",   { "{\\aa}",   "{\\r{a}}", "\\r{a}"} }, /*               with ring above */+   { 257, LATEX_MACRO, "={a}", { "{\\={a}}", "\\={a}",   "\\=a"  } }, /*               with macron */+   { 259, LATEX_MACRO, "u{a}", { "{\\u{a}}", "\\u{a}",   "\\u a" } }, /*               with breve */+   { 261, LATEX_MACRO, "k{a}", { "{\\k{a}}", "\\k{a}",   "\\k a" } }, /*               with ogonek */+   { 462, LATEX_MACRO, "v{a}", { "{\\v{a}}", "\\v{a}",   "\\v a" } }, /*               with caron */ -   { 198, "{\\AE}",  "\\AE",    ""      }, /* Latin Capital AE */-   { 230, "{\\ae}",  "\\ae",    ""      }, /* Latin Small ae */+   { 198, LATEX_MACRO, "AE",   { "{\\AE}",   "\\AE",     NULL    } }, /* Latin Capital AE */+   { 230, LATEX_MACRO, "ae",   { "{\\ae}",   "\\ae",     NULL    } }, /* Latin Small ae */                                             /* Latin Capital C */-   { 199, "{\\c{C}}","\\c{C}",  "\\c c" }, /*               with cedilla */-   { 262, "{\\'{C}}","\\'{C}",  "\\'C"  }, /*               with acute */-   { 264, "{\\^{C}}","\\^{C}",  "\\^C"  }, /*               with circumflex */-   { 266, "{\\.{C}}","\\.{C}",  "\\.C"  }, /*               with dot above */-   { 268, "{\\v{C}}","\\v{C}",  "\\v C" }, /*               with caron (hacek) */+   { 199, LATEX_MACRO, "c{C}", { "{\\c{C}}", "\\c{C}",  "\\c c"  } }, /*               with cedilla */+   { 262, LATEX_MACRO, "'{C}", { "{\\'{C}}", "\\'{C}",  "\\'C"   } }, /*               with acute */+   { 264, LATEX_MACRO, "^{C}", { "{\\^{C}}", "\\^{C}",  "\\^C"   } }, /*               with circumflex */+   { 266, LATEX_MACRO, ".{C}", { "{\\.{C}}", "\\.{C}",  "\\.C"   } }, /*               with dot above */+   { 268, LATEX_MACRO, "v{C}", { "{\\v{C}}", "\\v{C}",  "\\v C"  } }, /*               with caron (hacek) */                                             /* Latin Small c */-   { 231, "{\\c{c}}","\\c{c}",  "\\c C" }, /*               with cedilla*/-   { 263, "{\\'{c}}","\\'{c}",  "\\'c"  }, /*               with acute */-   { 265, "{\\^{c}}","\\^{c}",  "\\^c"  }, /*               with circumflex */-   { 267, "{\\.{c}}","\\.{c}",  "\\.c"  }, /*               with dot above */-   { 269, "{\\v{c}}","\\v{c}",  "\\v c" }, /*               with caron (hacek) */+   { 231, LATEX_MACRO, "c{c}", { "{\\c{c}}", "\\c{c}",  "\\c C"  } }, /*               with cedilla*/+   { 263, LATEX_MACRO, "'{c}", { "{\\'{c}}", "\\'{c}",  "\\'c"   } }, /*               with acute */+   { 265, LATEX_MACRO, "^{c}", { "{\\^{c}}", "\\^{c}",  "\\^c"   } }, /*               with circumflex */+   { 267, LATEX_MACRO, ".{c}", { "{\\.{c}}", "\\.{c}",  "\\.c"   } }, /*               with dot above */+   { 269, LATEX_MACRO, "v{c}", { "{\\v{c}}", "\\v{c}",  "\\v c"  } }, /*               with caron (hacek) */                                             /* Latin Capital D */-   { 270, "{\\v{D}}","\\v{D}",  "\\v D" }, /*               with caron */-   { 272, "{\\DJ}",  "",        ""      }, /*               with stroke */+   { 270, LATEX_MACRO, "v{D}", { "{\\v{D}}", "\\v{D}",  "\\v D"  } }, /*               with caron */+   { 272, LATEX_MACRO, "DJ",   { "{\\DJ}",   NULL,      NULL     } }, /*               with stroke */                                             /* Latin Small d */-   { 271, "{\\v{d}}","\\v{d}",  "\\v d" }, /*               with caron */-   { 273, "{\\dj}",  "",        ""      }, /*               with stroke */+   { 271, LATEX_MACRO, "v{d}", { "{\\v{d}}", "\\v{d}",  "\\v d"  } }, /*               with caron */+   { 273, LATEX_MACRO, "dj",   { "{\\dj}",   NULL,      NULL     } }, /*               with stroke */                                             /* Latin Capital E */-   { 200, "{\\`E}",  "\\`{E}",  "\\`E"  }, /*               with grave */-   { 201, "{\\'E}",  "\\'{E}",  "\\'E"  }, /*               with acute */-   { 202, "{\\^E}",  "\\^{E}",  "\\^E"  }, /*               with circumflex */-   { 203, "{\\\"E}", "\\\"{E}", "\\\"E" }, /*               with diuresis */-   { 274, "{\\={E}}","\\={E}",  "\\=E"  }, /*               with macron */-   { 276, "{\\u{E}}","\\u{E}",  "\\u E" }, /*               with breve */-   { 278, "{\\.{E}}","\\.{E}",  "\\.E"  }, /*               with dot above */-   { 280, "{\\k{E}}","\\k{E}",  "\\k E" }, /*               with ogonek */-   { 282, "{\\v{E}}","\\v{E}",  "\\v E" }, /*               with caron */+   { 200, LATEX_MACRO, "`E",   { "{\\`E}",   "\\`{E}",  "\\`E"   } }, /*               with grave */+   { 201, LATEX_MACRO, "'E",   { "{\\'E}",   "\\'{E}",  "\\'E"   } }, /*               with acute */+   { 202, LATEX_MACRO, "^E",   { "{\\^E}",   "\\^{E}",  "\\^E"   } }, /*               with circumflex */+   { 203, LATEX_MACRO, "\"E",  { "{\\\"E}",  "\\\"{E}", "\\\"E"  } }, /*               with diuresis */+   { 274, LATEX_MACRO, "={E}", { "{\\={E}}", "\\={E}",  "\\=E"   } }, /*               with macron */+   { 276, LATEX_MACRO, "u{E}", { "{\\u{E}}", "\\u{E}",  "\\u E"  } }, /*               with breve */+   { 278, LATEX_MACRO, ".{E}", { "{\\.{E}}", "\\.{E}",  "\\.E"   } }, /*               with dot above */+   { 280, LATEX_MACRO, "k{E}", { "{\\k{E}}", "\\k{E}",  "\\k E"  } }, /*               with ogonek */+   { 282, LATEX_MACRO, "v{E}", { "{\\v{E}}", "\\v{E}",  "\\v E"  } }, /*               with caron */                                              /* Latin Small e */-   { 232, "{\\`e}",  "\\`{e}",  "\\`e"  }, /*               with grave */-   { 233, "{\\'e}",  "\\'{e}",  "\\'e"  }, /*               with acute */-   { 234, "{\\^e}",  "\\^{e}",  "\\^e"  }, /*               with circumflex */-   { 235, "{\\\"e}", "\\\"{e}", "\\\"e" }, /*               with diuresis */-   { 275, "{\\={e}}","\\={e}",  "\\=e"  }, /*               with macron */-   { 277, "{\\u{e}}","\\u{e}",  "\\u e" }, /*               with breve */-   { 279, "{\\.{e}}","\\.{e}",  "\\.e"  }, /*               with dot above */-   { 281, "{\\k{e}}","\\k{e}",  "\\k e" }, /*               with ogonek */-   { 283, "{\\v{e}}","\\v{e}",  "\\v e" }, /*               with caron */+   { 232, LATEX_MACRO, "`e",   { "{\\`e}",   "\\`{e}",  "\\`e"   } }, /*               with grave */+   { 233, LATEX_MACRO, "'e",   { "{\\'e}",   "\\'{e}",  "\\'e"   } }, /*               with acute */+   { 234, LATEX_MACRO, "^e",   { "{\\^e}",   "\\^{e}",  "\\^e"   } }, /*               with circumflex */+   { 235, LATEX_MACRO, "\"e",  { "{\\\"e}",  "\\\"{e}", "\\\"e"  } }, /*               with diuresis */+   { 275, LATEX_MACRO, "={e}", { "{\\={e}}", "\\={e}",  "\\=e"   } }, /*               with macron */+   { 277, LATEX_MACRO, "u{e}", { "{\\u{e}}", "\\u{e}",  "\\u e"  } }, /*               with breve */+   { 279, LATEX_MACRO, ".{e}", { "{\\.{e}}", "\\.{e}",  "\\.e"   } }, /*               with dot above */+   { 281, LATEX_MACRO, "k{e}", { "{\\k{e}}", "\\k{e}",  "\\k e"  } }, /*               with ogonek */+   { 283, LATEX_MACRO, "v{e}", { "{\\v{e}}", "\\v{e}",  "\\v e"  } }, /*               with caron */                                             /* Latin Capital G */-   { 284, "{\\^{G}}","\\^{G}",  "\\^G"  }, /*               with circumflex */-   { 286, "{\\u{G}}","\\u{G}",  "\\u G" }, /*               with breve */-   { 288, "{\\.{G}}","\\.{G}",  "\\.G"  }, /*               with dot above */-   { 290, "{\\c{G}}","\\c{G}",  "\\c G" }, /*               with cedilla */-   { 486, "{\\v{G}}","\\v{G}",  "\\v G" }, /*               with caron */-   { 500, "{\\'{G}}","\\'{G}",  "\\'G"  }, /*               with acute */+   { 284, LATEX_MACRO, "^{G}", { "{\\^{G}}", "\\^{G}",  "\\^G"   } }, /*               with circumflex */+   { 286, LATEX_MACRO, "u{G}", { "{\\u{G}}", "\\u{G}",  "\\u G"  } }, /*               with breve */+   { 288, LATEX_MACRO, ".{G}", { "{\\.{G}}", "\\.{G}",  "\\.G"   } }, /*               with dot above */+   { 290, LATEX_MACRO, "c{G}", { "{\\c{G}}", "\\c{G}",  "\\c G"  } }, /*               with cedilla */+   { 486, LATEX_MACRO, "v{G}", { "{\\v{G}}", "\\v{G}",  "\\v G"  } }, /*               with caron */+   { 500, LATEX_MACRO, "'{G}", { "{\\'{G}}", "\\'{G}",  "\\'G"   } }, /*               with acute */                                             /* Latin Small g */-   { 285, "{\\^{g}}","\\^{g}",  "\\^g"  }, /*               with circumflex */-   { 287, "{\\u{g}}","\\u{g}",  "\\u g" }, /*               with breve */-   { 289, "{\\.{g}}","\\.{g}",  "\\.g"  }, /*               with dot above */-   { 291, "{\\c{g}}","\\c{g}",  "\\c g" }, /*               with cedilla */-   { 487, "{\\v{g}}","\\v{g}",  "\\v g" }, /*               with caron */-   { 501, "{\\'{g}}","\\'{g}",  "\\'g"  }, /*               with acute */+   { 285, LATEX_MACRO, "^{g}", { "{\\^{g}}", "\\^{g}",  "\\^g"   } }, /*               with circumflex */+   { 287, LATEX_MACRO, "u{g}", { "{\\u{g}}", "\\u{g}",  "\\u g"  } }, /*               with breve */+   { 289, LATEX_MACRO, ".{g}", { "{\\.{g}}", "\\.{g}",  "\\.g"   } }, /*               with dot above */+   { 291, LATEX_MACRO, "c{g}", { "{\\c{g}}", "\\c{g}",  "\\c g"  } }, /*               with cedilla */+   { 487, LATEX_MACRO, "v{g}", { "{\\v{g}}", "\\v{g}",  "\\v g"  } }, /*               with caron */+   { 501, LATEX_MACRO, "'{g}", { "{\\'{g}}", "\\'{g}",  "\\'g"   } }, /*               with acute */                                             /* Latin Capital H */-   { 292, "{\\^{H}}","\\^{H}",  "\\^H"  }, /*               with circumflex */-/* { 294, "",        "",        ""      },*//*              with stroke */+   { 292, LATEX_MACRO, "^{H}", { "{\\^{H}}", "\\^{H}",  "\\^H"   } }, /*               with circumflex */+/* { 294, LATEX_MACRO, "",     { NULL,       NULL,      NULL     } },*//*              with stroke */                                             /* Latin Capital h */-   { 293, "{\\^{h}}","\\^{h}",  "\\^h"  }, /*               with circumflex */-/* { 295, "",        "",        ""      },*//*              with stroke */+   { 293, LATEX_MACRO, "^{h}", { "{\\^{h}}", "\\^{h}",  "\\^h"   } }, /*               with circumflex */+/* { 295, LATEX_MACRO, "",     { NULL,       NULL,      NULL     } },*//*              with stroke */                                              /* Latin Capital I */-   { 204, "{\\`I}",  "\\`{I}",  "\\`I"  }, /*               with grave */-   { 205, "{\\'I}",  "\\'{I}",  "\\'I"  }, /*               with acute */-   { 206, "{\\^I}",  "\\^{I}",  "\\^I"  }, /*               with circumflex */-   { 207, "{\\\"I}", "\\\"{I}", "\\\"I" }, /*               with diuresis */-   { 296, "{\\~{I}}","\\~{I}",  "\\~I"  }, /*               with tilde */-   { 298, "{\\={I}}","\\={I}",  "\\=I"  }, /*               with macron */-   { 300, "{\\u{I}}","\\u{I}",  "\\u I" }, /*               with breve */-   { 302, "{\\k{I}}","\\k{I}",  "\\k I" }, /*               with ogonek */-   { 304, "{\\.{I}}","\\.{I}",  "\\. I" }, /*               with dot above */-   { 463, "{\\v{I}}","\\v{I}",  "\\v I" }, /*               with caron */+   { 204, LATEX_MACRO, "`I",   { "{\\`I}",   "\\`{I}",  "\\`I"   } }, /*               with grave */+   { 205, LATEX_MACRO, "'I",   { "{\\'I}",   "\\'{I}",  "\\'I"   } }, /*               with acute */+   { 206, LATEX_MACRO, "^I",   { "{\\^I}",   "\\^{I}",  "\\^I"   } }, /*               with circumflex */+   { 207, LATEX_MACRO, "\"I",  { "{\\\"I}",  "\\\"{I}", "\\\"I"  } }, /*               with diuresis */+   { 296, LATEX_MACRO, "~{I}", { "{\\~{I}}", "\\~{I}",  "\\~I"   } }, /*               with tilde */+   { 298, LATEX_MACRO, "={I}", { "{\\={I}}", "\\={I}",  "\\=I"   } }, /*               with macron */+   { 300, LATEX_MACRO, "u{I}", { "{\\u{I}}", "\\u{I}",  "\\u I"  } }, /*               with breve */+   { 302, LATEX_MACRO, "k{I}", { "{\\k{I}}", "\\k{I}",  "\\k I"  } }, /*               with ogonek */+   { 304, LATEX_MACRO, ".{I}", { "{\\.{I}}", "\\.{I}",  "\\. I"  } }, /*               with dot above */+   { 463, LATEX_MACRO, "v{I}", { "{\\v{I}}", "\\v{I}",  "\\v I"  } }, /*               with caron */                                             /* Latin Small i */-   { 236, "{\\`i}",  "\\`{i}",  "\\`i"  }, /*               with grave */-   { 237, "{\\'i}",  "\\'{i}",  "\\'i"  }, /*               with acute */-   { 238, "{\\^i}",  "\\^{i}",  "\\^i"  }, /*               with circumflex */-   { 239, "{\\\"i}", "\\\"{i}", "\\\"i" }, /*               with diuresis */-   { 236, "{\\`\\i}",  "\\`{\\i}",  "\\`\\i"  }, /*         with grave */-   { 237, "{\\'\\i}",  "\\'{\\i}",  "\\'\\i"  }, /*         with acute */-   { 238, "{\\^\\i}",  "\\^{\\i}",  "\\^\\i"  }, /*         with circumflex */-   { 239, "{\\\"\\i}", "\\\"{\\i}", "\\\"\\i" }, /*         with diuresis */-   { 297, "{\\~{\\i}}","\\~{\\i}",  "\\~\\i{}"}, /*         with tilde */-   { 299, "{\\={\\i}}", "\\={\\i}", "\\=\\i{}"}, /*         with macron */-   { 301, "{\\u{\\i}}","\\u{\\i}",  "\\u\\i{}"}, /*         with breve */-   { 303, "{\\k{i}}","\\k{i}",  "\\k i" }, /*               with ogonek */-                                           /* Latex \i has no dot on "i"*/-   { 305, "{\\i}",     "\\i{}",     ""        }, /*         without dot above */-   { 464, "{\\v \\i{}}", "\\v \\i{}", ""      }, /*         with caron */+   { 236, LATEX_MACRO, "`i",   { "{\\`i}",   "\\`{i}",  "\\`i"   } }, /*               with grave */+   { 237, LATEX_MACRO, "'i",   { "{\\'i}",   "\\'{i}",  "\\'i"   } }, /*               with acute */+   { 238, LATEX_MACRO, "^i",   { "{\\^i}",   "\\^{i}",  "\\^i"   } }, /*               with circumflex */+   { 239, LATEX_MACRO, "\"i",  { "{\\\"i}",  "\\\"{i}", "\\\"i"  } }, /*               with diuresis */+   { 303, LATEX_MACRO, "k{i}", { "{\\k{i}}", "\\k{i}",  "\\k i"  } }, /*               with ogonek */+                                           /* Latex "\i" has no dot on "i" */+   { 305, LATEX_MACRO, "i",       { "{\\i}",      "\\i{}",    NULL       } }, /*    without dot above */+   { 236, LATEX_MACRO, "`{\\i}",  { "{\\`\\i}",   "\\`{\\i}", "\\`\\i"   } }, /*       with grave */+   { 237, LATEX_MACRO, "'{\\i}",  { "{\\'\\i}",   "\\'{\\i}", "\\'\\i"   } }, /*       with acute */+   { 238, LATEX_MACRO, "^{\\i}",  { "{\\^\\i}",   "\\^{\\i}", "\\^\\i"   } }, /*       with circumflex */+   { 239, LATEX_MACRO, "\"{\\i}", { "{\\\"\\i}",  "\\\"{\\i}","\\\"\\i"  } }, /*       with diuresis */+   { 297, LATEX_MACRO, "`{\\i}",  { "{\\~{\\i}}", "\\~{\\i}", "\\~\\i{}" } }, /*       with tilde */+   { 299, LATEX_MACRO, "={\\i}",  { "{\\={\\i}}", "\\={\\i}", "\\=\\i{}" } }, /*       with macron */+   { 301, LATEX_MACRO, "u{\\i}",  { "{\\u{\\i}}", "\\u{\\i}", "\\u\\i{}" } }, /*       with breve */+   { 464, LATEX_MACRO, "v{\\i}",  { "{\\v \\i{}}", "\\v \\i{}", NULL   } }, /*         with caron */ -/*   { 306, "",  "",    ""      },*/ /* Latin Capital IJ */-/*   { 307, ""  "",    ""       },*/ /* Latin Small ij */+/* { 306, LATEX_MACRO, "",     { NULL,       NULL,      NULL     } },*/ /* Latin Capital IJ */+/* { 307, LATEX_MACRO, "",     { NULL,       NULL,      NULL     } },*/ /* Latin Small ij */                                             /* Latin Capital J */-   { 308, "{\\^{J}}","\\^{J}",  "\\^J"  }, /*                with circumflex */+   { 308, LATEX_MACRO, "^{J}", { "{\\^{J}}", "\\^{J}",  "\\^J"   } }, /*               with circumflex */                                             /* Latin Small j */-   { 309, "{\\^{j}}","\\^{j}",  "\\^j"  }, /*                with circumflex */+   { 309, LATEX_MACRO, "^{j}", { "{\\^{j}}", "\\^{j}",  "\\^j"   } }, /*               with circumflex */                                             /* Latin Capital K */-   { 310, "{\\c{K}}","\\c{K}",  "\\c K" }, /*               with cedilla */-   { 488, "{\\v{K}}","\\v{K}",  "\\v K" }, /*               with caron */+   { 310, LATEX_MACRO, "c{K}", { "{\\c{K}}", "\\c{K}",  "\\c K"  } }, /*               with cedilla */+   { 488, LATEX_MACRO, "v{K}", { "{\\v{K}}", "\\v{K}",  "\\v K"  } }, /*               with caron */                                             /* Latin Small k */-   { 311, "{\\c{k}}","\\c{k}",  "\\c k" }, /*               with cedilla */-   { 489, "{\\v{k}}","\\v{k}",  "\\v k" }, /*               with caron */+   { 311, LATEX_MACRO, "c{k}", { "{\\c{k}}", "\\c{k}",  "\\c k"  } }, /*               with cedilla */+   { 489, LATEX_MACRO, "v{k}", { "{\\v{k}}", "\\v{k}",  "\\v k"  } }, /*               with caron */                                             /* Latin Capital L */-   { 313, "{\\'{L}}","\\'{L}",  "\\'L"  }, /*               with acute */-   { 315, "{\\c{L}}","\\c{L}",  "\\c L" }, /*               with cedilla */-   { 317, "{\\v{L}}","\\v{l}",  "\\v L" }, /*               with caron */-   { 319, "{L\\hspace{-0.35em}$\\cdot$}","L\\hspace{-0.35em}$\\cdot$", "" }, /*               with middle dot */-   { 321, "{\\L}",   "{\\L{}}", "\\L{}" }, /*               with stroke */+   { 313, LATEX_MACRO, "'{L}", { "{\\'{L}}", "\\'{L}",  "\\'L"   } }, /*               with acute */+   { 315, LATEX_MACRO, "c{L}", { "{\\c{L}}", "\\c{L}",  "\\c L"  } }, /*               with cedilla */+   { 317, LATEX_MACRO, "v{L}", { "{\\v{L}}", "\\v{l}",  "\\v L"  } }, /*               with caron */+   { 319, LATEX_COMBO, "{L\\hspace{-0.35em}$\\cdot$}", { "{L\\hspace{-0.35em}$\\cdot$}","L\\hspace{-0.35em}$\\cdot$", NULL } }, /*               with middle dot */+   { 321, LATEX_MACRO, "L",    { "{\\L}",   "{\\L{}}", "\\L{}"   } }, /*               with stroke */                                             /* Latin Small l */-   { 314, "{\\'{l}}","\\'{l}",  "\\'l"  }, /*               with acute */-   { 316, "{\\c{l}}","\\c{l}",  "\\c l" }, /*               with cedilla */-   { 318, "{\\v{l}}","\\v{l}",  "\\v l" }, /*               with caron */-   { 320, "{l$\\cdot$}","l$\\cdot$", "" }, /*               with middle dot */-   { 322, "{\\l}",   "{\\l{}}", "\\l{}" }, /*               with stroke */+   { 314, LATEX_MACRO, "'{l}", { "{\\'{l}}", "\\'{l}",  "\\'l"   } }, /*               with acute */+   { 316, LATEX_MACRO, "c{l}", { "{\\c{l}}", "\\c{l}",  "\\c l"  } }, /*               with cedilla */+   { 318, LATEX_MACRO, "v{l}", { "{\\v{l}}", "\\v{l}",  "\\v l"  } }, /*               with caron */+   { 320, LATEX_COMBO, "{l$\\cdot$}", { "{l$\\cdot$}","l$\\cdot$", NULL } }, /*               with middle dot */+   { 322, LATEX_MACRO, "l",    { "{\\l}",    "{\\l{}}", "\\l{}"  } }, /*               with stroke */                                             /* Latin Capital N */-   { 209, "{\\~{N}}","\\~{N}",  "\\~N"  }, /*               with tilde */-   { 323, "{\\'{N}}","\\'{N}",  "\\'N"  }, /*               with acute */-   { 325, "{\\c{N}}","\\c{N}",  "\\c N" }, /*               with cedilla */-   { 327, "{\\v{N}}","\\v{N}",  "\\v N" }, /*               with caron */+   { 209, LATEX_MACRO, "~{N}", { "{\\~{N}}", "\\~{N}",  "\\~N"   } }, /*               with tilde */+   { 323, LATEX_MACRO, "'{N}", { "{\\'{N}}", "\\'{N}",  "\\'N"   } }, /*               with acute */+   { 325, LATEX_MACRO, "c{N}", { "{\\c{N}}", "\\c{N}",  "\\c N"  } }, /*               with cedilla */+   { 327, LATEX_MACRO, "v{N}", { "{\\v{N}}", "\\v{N}",  "\\v N"  } }, /*               with caron */                                             /* Latin Small n */-   { 241, "{\\~{n}}","\\~{n}",  "\\~n"  }, /*               with tilde */-   { 324, "{\\'{n}}","\\'{n}",  "\\'n"  }, /*               with acute */-   { 326, "{\\c{n}}","\\c{n}",  "\\c N" }, /*               with cedilla */-   { 328, "{\\v{n}}","\\v{n}",  "\\v n" }, /*               with caron */-   { 329, "\n",      "",        ""      }, /*               preceeded by apostrophe */+   { 241, LATEX_MACRO, "~{n}", { "{\\~{n}}", "\\~{n}",  "\\~n"   } }, /*               with tilde */+   { 324, LATEX_MACRO, "'{n}", { "{\\'{n}}", "\\'{n}",  "\\'n"   } }, /*               with acute */+   { 326, LATEX_MACRO, "c{n}", { "{\\c{n}}", "\\c{n}",  "\\c N"  } }, /*               with cedilla */+   { 328, LATEX_MACRO, "v{n}", { "{\\v{n}}", "\\v{n}",  "\\v n"  } }, /*               with caron */+   { 329, LATEX_MACRO, "n",    { "\\n",      NULL,      NULL     } }, /*               preceeded by apostrophe */                                              /* Latin Capital O */-   { 210, "{\\`O}",  "\\`{O}",  "\\`O"  }, /*               with grave */-   { 211, "{\\'O}",  "\\'{O}",  "\\'O"  }, /*               with acute */-   { 212, "{\\^O}",  "\\^{O}",  "\\^O"  }, /*               with circumflex */-   { 213, "{\\~O}",  "\\~{O}",  "\\~O"  }, /*               with tilde */-   { 214, "{\\\"O}", "\\\"{O}", "\\\"O" }, /*               with diaeresis */-   { 216, "{\\O}",   "\\O",     ""      }, /*               with stroke */-   { 332, "{\\={O}}", "\\={O}", "\\=O"  }, /*               with macron */-   { 334, "{\\u{O}}", "\\u{O}", "\\u O" }, /*               with breve */-   { 336, "{\\H{O}}", "\\H{O}", "\\H O" }, /*               with double acute */-   { 465, "{\\v{O}}", "\\v{O}", "\\v O" }, /*               with caron */-   { 490, "{\\k{O}}", "\\k{O}", "\\k O" }, /*               with ogonek */+   { 210, LATEX_MACRO, "`O",   { "{\\`O}",   "\\`{O}",  "\\`O"   } }, /*               with grave */+   { 211, LATEX_MACRO, "'O",   { "{\\'O}",   "\\'{O}",  "\\'O"   } }, /*               with acute */+   { 212, LATEX_MACRO, "^O",   { "{\\^O}",   "\\^{O}",  "\\^O"   } }, /*               with circumflex */+   { 213, LATEX_MACRO, "~O",   { "{\\~O}",   "\\~{O}",  "\\~O"   } }, /*               with tilde */+   { 214, LATEX_MACRO, "\"O",  { "{\\\"O}",  "\\\"{O}", "\\\"O"  } }, /*               with diaeresis */+   { 216, LATEX_MACRO, "O",    { "{\\O}",    "\\O",     NULL     } }, /*               with stroke */+   { 332, LATEX_MACRO, "={O}", { "{\\={O}}", "\\={O}", "\\=O"    } }, /*               with macron */+   { 334, LATEX_MACRO, "u{O}", { "{\\u{O}}", "\\u{O}", "\\u O"   } }, /*               with breve */+   { 336, LATEX_MACRO, "H{O}", { "{\\H{O}}", "\\H{O}", "\\H O"   } }, /*               with double acute */+   { 465, LATEX_MACRO, "v{O}", { "{\\v{O}}", "\\v{O}", "\\v O"   } }, /*               with caron */+   { 490, LATEX_MACRO, "k{O}", { "{\\k{O}}", "\\k{O}", "\\k O"   } }, /*               with ogonek */                                             /* Latin Small o */-   { 242, "{\\`o}",  "\\`{o}",  "\\`o"  }, /*               with grave */-   { 243, "{\\'o}",  "\\'{o}",  "\\'o"  }, /*               with acute */-   { 244, "{\\^o}",  "\\^{o}",  "\\^o"  }, /*               with circumflex */-   { 245, "{\\~o}",  "\\~{o}",  "\\~o"  }, /*               with tilde */-   { 246, "{\\\"o}", "\\\"{o}", "\\\"o" }, /*               with diaeresis */-   { 248, "{\\o}",   "\\o",     ""      }, /*               with stroke */-   { 333, "{\\={o}}", "\\={o}", "\\=o"  }, /*               with macron */-   { 335, "{\\u{o}}", "\\u{o}", "\\u o" }, /*               with breve */-   { 337, "{\\H{o}}", "\\H{o}", "\\H o" }, /*               with double acute */-   { 466, "{\\v{o}}", "\\v{o}", "\\v o" }, /*               with caron */-   { 491, "{\\k{o}}", "\\k{o}", "\\k o" }, /*               with ogonek */+   { 242, LATEX_MACRO, "`o",   { "{\\`o}",   "\\`{o}",  "\\`o"   } }, /*               with grave */+   { 243, LATEX_MACRO, "'o",   { "{\\'o}",   "\\'{o}",  "\\'o"   } }, /*               with acute */+   { 244, LATEX_MACRO, "^o",   { "{\\^o}",   "\\^{o}",  "\\^o"   } }, /*               with circumflex */+   { 245, LATEX_MACRO, "~o",   { "{\\~o}",   "\\~{o}",  "\\~o"   } }, /*               with tilde */+   { 246, LATEX_MACRO, "\"o",  { "{\\\"o}",  "\\\"{o}", "\\\"o"  } }, /*               with diaeresis */+   { 248, LATEX_MACRO, "o",    { "{\\o}",    "\\o",     NULL     } }, /*               with stroke */+   { 333, LATEX_MACRO, "={o}", { "{\\={o}}", "\\={o}", "\\=o"    } }, /*               with macron */+   { 335, LATEX_MACRO, "u{o}", { "{\\u{o}}", "\\u{o}", "\\u o"   } }, /*               with breve */+   { 337, LATEX_MACRO, "H{o}", { "{\\H{o}}", "\\H{o}", "\\H o"   } }, /*               with double acute */+   { 466, LATEX_MACRO, "v{o}", { "{\\v{o}}", "\\v{o}", "\\v o"   } }, /*               with caron */+   { 491, LATEX_MACRO, "k{o}", { "{\\k{o}}", "\\k{o}", "\\k o"   } }, /*               with ogonek */ -   { 338, "{\\OE}",  "\\OE",    ""      }, /* Latin Capital OE */-   { 339, "{\\oe}",  "\\oe",    ""      }, /* Latin Small oe */+   { 338, LATEX_MACRO, "OE",   { "{\\OE}",   "\\OE",   NULL      } }, /* Latin Capital OE */+   { 339, LATEX_MACRO, "oe",   { "{\\oe}",   "\\oe",   NULL      } }, /* Latin Small oe */                                             /* Latin Capital R */-   { 340, "{\\'{R}}", "\\'{R}", "\\'R"  }, /*                 with acute */-   { 342, "{\\c{R}}", "\\c{R}", "\\c R" }, /*                 with cedilla */-   { 344, "{\\v{R}}", "\\v{R}", "\\v R" }, /*                 with caron */+   { 340, LATEX_MACRO, "'R",   { "{\\'{R}}", "\\'{R}", "\\'R"    } }, /*               with acute */+   { 342, LATEX_MACRO, "c{R}", { "{\\c{R}}", "\\c{R}", "\\c R"   } }, /*               with cedilla */+   { 344, LATEX_MACRO, "v{R}", { "{\\v{R}}", "\\v{R}", "\\v R"   } }, /*               with caron */                                              /* Latin Small r */-   { 341, "{\\'{r}}", "\\'{r}", "\\'r"  }, /*               with acute */-   { 343, "{\\c{r}}", "\\c{r}", "\\c r" }, /*               with cedilla */-   { 345, "{\\v{r}}", "\\v{r}", "\\v r" }, /*               with caron */+   { 341, LATEX_MACRO, "'r",   { "{\\'{r}}", "\\'{r}", "\\'r"    } }, /*               with acute */+   { 343, LATEX_MACRO, "c{r}", { "{\\c{r}}", "\\c{r}", "\\c r"   } }, /*               with cedilla */+   { 345, LATEX_MACRO, "v{r}", { "{\\v{r}}", "\\v{r}", "\\v r"   } }, /*               with caron */                                             /* Latin Capital S */-   { 346, "{\\'{S}}", "\\'{S}", "\\'S"  }, /*               with acute */-   { 348, "{\\^{S}}", "\\^{S}", "\\^S"  }, /*               with circumflex */-   { 350, "{\\c{S}}", "\\c{S}", "\\c S" }, /*               with cedilla */-   { 352, "{\\v{S}}", "\\v{S}", "\\v S" }, /*               with caron */+   { 346, LATEX_MACRO, "'{S}", { "{\\'{S}}", "\\'{S}", "\\'S"    } }, /*               with acute */+   { 348, LATEX_MACRO, "^{S}", { "{\\^{S}}", "\\^{S}", "\\^S"    } }, /*               with circumflex */+   { 350, LATEX_MACRO, "c{S}", { "{\\c{S}}", "\\c{S}", "\\c S"   } }, /*               with cedilla */+   { 352, LATEX_MACRO, "v{S}", { "{\\v{S}}", "\\v{S}", "\\v S"   } }, /*               with caron */                                             /* Latin Small s */-   { 347, "{\\'{s}}","\\'{s}",  "\\'s"  }, /*               with acute */-   { 349, "{\\^{s}}","\\^{s}",  "\\^s"  }, /*               with circumflex */-   { 351, "{\\c{s}}","\\c{s}",  "\\c s" }, /*               with cedilla */-   { 353, "{\\v{s}}","\\v{s}",  "\\v s" }, /*               with caron */+   { 347, LATEX_MACRO, "'{s}", { "{\\'{s}}", "\\'{s}", "\\'s"    } }, /*               with acute */+   { 349, LATEX_MACRO, "^{s}", { "{\\^{s}}", "\\^{s}", "\\^s"    } }, /*               with circumflex */+   { 351, LATEX_MACRO, "c{s}", { "{\\c{s}}", "\\c{s}", "\\c s"   } }, /*               with cedilla */+   { 353, LATEX_MACRO, "v{s}", { "{\\v{s}}", "\\v{s}", "\\v s"   } }, /*               with caron */                                             /* Latin Capital T */-   { 354, "{\\c{T}}", "\\c{T}", ""      }, /*               with cedilla */-   { 356, "{\\v{T}}", "\\v{T}", ""      }, /*               with caron */-/* { 358, "",         "",       ""      },*//*               with stroke */+   { 354, LATEX_MACRO, "c{T}", { "{\\c{T}}", "\\c{T}", NULL      } }, /*               with cedilla */+   { 356, LATEX_MACRO, "v{T}", { "{\\v{T}}", "\\v{T}", NULL      } }, /*               with caron */+/* { 358, LATEX_MACRO, "",     { NULL,       NULL,     NULL      } },*//*              with stroke */                                             /* Latin Small t */-   { 355, "{\\c{t}}", "\\c{t}", ""      }, /*               with cedilla */-   { 357, "{\\v{t}}", "\\v{t}", ""      }, /*               with caron */-/* { 359, "",         "",       ""      },*//*               with stroke */+   { 355, LATEX_MACRO, "c{T}", { "{\\c{t}}", "\\c{t}", NULL      } }, /*               with cedilla */+   { 357, LATEX_MACRO, "v{T}", { "{\\v{t}}", "\\v{t}", NULL      } }, /*               with caron */+/* { 359, LATEX_MACRO, "",     { NULL,       NULL,     NULL      } },*//*              with stroke */ -   { 223, "{\\ss}",  "\\ss",    ""      }, /* German sz ligature, "sharp s" */+   { 223, LATEX_MACRO, "ss",   { "{\\ss}",   "\\ss",   NULL      } }, /* German sz ligature, "sharp s" */                                             /* Latin Capital U */-   { 217, "{\\`U}",  "\\`{U}",  "\\`U"  }, /*               with grave */-   { 218, "{\\'U}",  "\\'{U}",  "\\'U"  }, /*               with acute */-   { 219, "{\\^U}",  "\\^{U}",  "\\^U"  }, /*               with circumflex */-   { 220, "{\\\"U}", "\\\"{U}", "\\\"U" }, /*               with diaeresis */-   { 360, "{\\~{U}}","\\~{U}",  "\\~U"  }, /*               with tilde */-   { 362, "{\\={U}}","\\={U}",  "\\=U"  }, /*               with macron */-   { 364, "{\\u{U}}","\\u{U}",  "\\u U" }, /*               with breve */-   { 366, "{\\r{U}}","\\r{U}",  "\\r U" }, /*               with ring above */-   { 368, "{\\H{U}}","\\H{U}",  "\\H U" }, /*               with double acute */-   { 370, "{\\k{U}}","\\k{U}",  "\\k U" }, /*               with ogonek */-   { 467, "{\\v{U}}","\\v{U}",  "\\v U" }, /*               with caron */+   { 217, LATEX_MACRO, "`U",   { "{\\`U}",   "\\`{U}", "\\`U"    } }, /*               with grave */+   { 218, LATEX_MACRO, "'U",   { "{\\'U}",   "\\'{U}", "\\'U"    } }, /*               with acute */+   { 219, LATEX_MACRO, "^U",   { "{\\^U}",   "\\^{U}", "\\^U"    } }, /*               with circumflex */+   { 220, LATEX_MACRO, "\"U",  { "{\\\"U}",  "\\\"{U}","\\\"U"   } }, /*               with diaeresis */+   { 360, LATEX_MACRO, "~{U}", { "{\\~{U}}", "\\~{U}", "\\~U"    } }, /*               with tilde */+   { 362, LATEX_MACRO, "={U}", { "{\\={U}}", "\\={U}", "\\=U"    } }, /*               with macron */+   { 364, LATEX_MACRO, "u{U}", { "{\\u{U}}", "\\u{U}", "\\u U"   } }, /*               with breve */+   { 366, LATEX_MACRO, "r{U}", { "{\\r{U}}", "\\r{U}", "\\r U"   } }, /*               with ring above */+   { 368, LATEX_MACRO, "H{U}", { "{\\H{U}}", "\\H{U}", "\\H U"   } }, /*               with double acute */+   { 370, LATEX_MACRO, "k{U}", { "{\\k{U}}", "\\k{U}", "\\k U"   } }, /*               with ogonek */+   { 467, LATEX_MACRO, "v{U}", { "{\\v{U}}", "\\v{U}", "\\v U"   } }, /*               with caron */                                             /* Latin Small u */-   { 249, "{\\`u}",  "\\`{u}",  "\\`u"  }, /*               with grave */-   { 250, "{\\'u}",  "\\'{u}",  "\\'u"  }, /*               with acute */-   { 251, "{\\^u}",  "\\^{u}",  "\\^u"  }, /*               with circumflex */-   { 252, "{\\\"u}", "\\\"{u}", "\\\"u" }, /*               with diaeresis */-   { 361, "{\\~{u}}","\\~{u}",  ""      }, /*               with tilde */-   { 363, "{\\={u}}","\\={u}",  "\\=u"  }, /*               with macron */-   { 365, "{\\u{u}}","\\u{u}",  "\\u u" }, /*               with breve */-   { 367, "{\\r{u}}","\\r{u}",  "\\r u" }, /*               with ring above */-   { 369, "{\\H{u}}","\\H{u}",  "\\H u" }, /*               with double acute */-   { 371, "{\\k{u}}","\\k{u}",  "\\k u" }, /*               with ogonek */-   { 468, "{\\v{u}}","\\v{u}",  "\\v u" }, /*               with caron */+   { 249, LATEX_MACRO, "`u",   { "{\\`u}",   "\\`{u}", "\\`u"    } }, /*               with grave */+   { 250, LATEX_MACRO, "'u",   { "{\\'u}",   "\\'{u}", "\\'u"    } }, /*               with acute */+   { 251, LATEX_MACRO, "^u",   { "{\\^u}",   "\\^{u}", "\\^u"    } }, /*               with circumflex */+   { 252, LATEX_MACRO, "\"u",  { "{\\\"u}",  "\\\"{u}","\\\"u"   } }, /*               with diaeresis */+   { 361, LATEX_MACRO, "~{u}", { "{\\~{u}}", "\\~{u}", NULL      } }, /*               with tilde */+   { 363, LATEX_MACRO, "={u}", { "{\\={u}}", "\\={u}", "\\=u"    } }, /*               with macron */+   { 365, LATEX_MACRO, "u{u}", { "{\\u{u}}", "\\u{u}", "\\u u"   } }, /*               with breve */+   { 367, LATEX_MACRO, "r{u}", { "{\\r{u}}", "\\r{u}", "\\r u"   } }, /*               with ring above */+   { 369, LATEX_MACRO, "H{u}", { "{\\H{u}}", "\\H{u}", "\\H u"   } }, /*               with double acute */+   { 371, LATEX_MACRO, "k{u}", { "{\\k{u}}", "\\k{u}", "\\k u"   } }, /*               with ogonek */+   { 468, LATEX_MACRO, "v{u}", { "{\\v{u}}", "\\v{u}", "\\v u"   } }, /*               with caron */                                             /* Latin Capital W */-   { 372, "{\\^{W}}", "\\^{W}", "\\^W"  }, /*               with circumflex */+   { 372, LATEX_MACRO, "^{W}", { "{\\^{W}}", "\\^{W}", "\\^W"    } }, /*               with circumflex */                                             /* Latin Small w */-   { 373, "{\\^{w}}", "\\^{w}", "\\^w"  }, /*               with circumflex */+   { 373, LATEX_MACRO, "^{w}", { "{\\^{w}}", "\\^{w}", "\\^w"    } }, /*               with circumflex */                                             /* Latin Capital Y */-   { 221, "{\\'{Y}}","\\'{Y}", "\\'Y"   }, /*               with acute */-   { 374, "{\\^{Y}}","\\^{Y}", "\\^Y"   }, /*               with circumflex */-   { 376, "{\\\"{Y}}","\\\"{Y}","\\\"Y" }, /*               with diaeresis */+   { 221, LATEX_MACRO, "'{Y}", { "{\\'{Y}}", "\\'{Y}", "\\'Y"    } }, /*               with acute */+   { 374, LATEX_MACRO, "^{Y}", { "{\\^{Y}}", "\\^{Y}", "\\^Y"    } }, /*               with circumflex */+   { 376, LATEX_MACRO, "\"{Y}",{ "{\\\"{Y}}","\\\"{Y}","\\\"Y"   } }, /*               with diaeresis */                                             /* Latin Small y */-   { 253, "{\\'y}",  "\\'{y}", "\\'y"   }, /*               with acute */-   { 255, "{\\\"y}", "\\\"{y}","\\\"y"  }, /*               with diaeresis */-   { 375, "{\\^{y}}","\\^{y}", "\\^y"   }, /*               with circumflex */+   { 253, LATEX_MACRO, "'y",   { "{\\'y}",  "\\'{y}", "\\'y"     } }, /*               with acute */+   { 255, LATEX_MACRO, "\"y",  { "{\\\"y}", "\\\"{y}","\\\"y"    } }, /*               with diaeresis */+   { 375, LATEX_MACRO, "^{y}", { "{\\^{y}}","\\^{y}", "\\^y"     } }, /*               with circumflex */                                             /* Latin Capital Z */-   { 377, "{\\'{Z}}","\\'{Z}", "\\'Z"   }, /*               with acute */-   { 379, "{\\.{Z}}","\\.{Z}", "\\.Z"   }, /*               with dot above */-   { 381, "{\\v{Z}}","\\v{Z}", "\\v Z"  }, /*               with caron */+   { 377, LATEX_MACRO, "'{Z}", { "{\\'{Z}}","\\'{Z}", "\\'Z"     } }, /*               with acute */+   { 379, LATEX_MACRO, ".{Z}", { "{\\.{Z}}","\\.{Z}", "\\.Z"     } }, /*               with dot above */+   { 381, LATEX_MACRO, "v{Z}", { "{\\v{Z}}","\\v{Z}", "\\v Z"    } }, /*               with caron */                                             /* Latin Small z */-   { 378, "{\\'{z}}","\\'{z}", "\\'z"   }, /*               with acute */-   { 380, "{\\.{z}}","\\.{z}", "\\.z"   }, /*               with dot above */-   { 382, "{\\v{z}}","\\v{z}", "\\v z"  }, /*               with caron */+   { 378, LATEX_MACRO, "'{z}", { "{\\'{z}}","\\'{z}", "\\'z"     } }, /*               with acute */+   { 380, LATEX_MACRO, ".{z}", { "{\\.{z}}","\\.{z}", "\\.z"     } }, /*               with dot above */+   { 382, LATEX_MACRO, "v{z}", { "{\\v{z}}","\\v{z}", "\\v z"    } }, /*               with caron */   				/* Needs to be before \nu */-   { 8203, "$\\null$", "\\null", "" },           /* No space &#x200B; */+   { 8203,LATEX_MATH, "null",  { "$\\null$", "\\null", NULL      } }, /* No space &#x200B; */ -   { 913, "$\\Alpha$", "\\Alpha", ""       }, /*GREEKCAPITALLETTERALPHA*/-   /* 902 = GREEKCAPITALLETTERALPHAWITHTONOS*/-   { 914, "$\\Beta$",  "\\Beta", ""       }, /*GREEKCAPITALLETTERBETA*/-   { 915, "$\\Gamma$", "\\Gamma", ""       }, /*GREEKCAPITALLETTERGAMMA*/-   { 916, "$\\Delta$", "\\Delta", ""       }, /*GREEKCAPITALLETTERDELTA*/-   { 917, "$\\Epsilon$", "\\Epsilon", ""     }, /*GREEKCAPITALLETTEREPSILON*/-   /* 904 = GREEKCAPITALLETTEREPSILONWITHTONOS*/-   { 918, "$\\Zeta$", "\\Zeta", ""        }, /*GREEKCAPITALLETTERZETA*/-   { 919, "$\\Eta$", "\\Eta", ""         }, /*GREEKCAPITALLETTERETA*/-   /* 905 = GREEKCAPITALLETTERETAWITHTONOS*/-   { 920, "$\\Theta$", "\\Theta", ""       }, /*GREEKCAPITALLETTERTHETA*/-   { 921, "$\\Iota$", "\\Iota", ""        }, /*GREEKCAPITALLETTERIOTA*/-   /* 938 = GREEKCAPITALLETTERIOTAWITHDIALYTIKA*/-   /* 906 = GREEKCAPITALLETTERIOTAWITHTONOS*/-   { 922, "$\\Kappa$", "\\Kappa", ""       }, /*GREEKCAPITALLETTERKAPPA*/-   { 923, "$\\Lambda$", "\\Lambda", ""      }, /*GREEKCAPITALLETTERLAMDA*/-   { 924, "$\\Mu$", "\\Mu", ""          }, /*GREEKCAPITALLETTERMU*/-   { 925, "$\\Nu$", "\\Nu", ""          }, /*GREEKCAPITALLETTERNU*/-   { 926, "$\\Xi$", "\\Xi", ""          }, /*GREEKCAPITALLETTERXI*/-   { 927, "$\\Omicron$", "\\Omicron", ""     }, /*GREEKCAPITALLETTEROMICRON*/-   /* 908 = GREEKCAPITALLETTEROMICRONWITHTONOS*/-   { 928, "$\\Pi$", "\\Pi", ""          }, /*GREEKCAPITALLETTERPI*/-   { 929, "$\\Rho$", "\\Rho", ""         }, /*GREEKCAPITALLETTERRHO*/-   { 931, "$\\Sigma$", "\\Sigma", ""       }, /*GREEKCAPITALLETTERSIGMA*/-   { 932, "$\\Tau$", "\\Tau", ""         }, /*GREEKCAPITALLETTERTAU*/-   { 933, "$\\Upsilon$", "\\Upsilon", ""     }, /*GREEKCAPITALLETTERUPSILON*/-   /* 939 = GREEKCAPITALLETTERUPSILONWITHDIALYTIKA*/-   /* 910 = GREEKCAPITALLETTERUPSILONWITHTONOS*/-   { 934, "$\\Phi$", "\\Phi", ""         }, /*GREEKCAPITALLETTERPHI*/-   { 935, "$\\Chi$", "\\Chi", ""         }, /*GREEKCAPITALLETTERCHI*/-   { 936, "$\\Psi$", "\\Psi", ""         }, /*GREEKCAPITALLETTERPSI*/-   { 937, "$\\Omega$", "\\Omega", ""       }, /*GREEKCAPITALLETTEROMEGA*/-   /* 911, = GREEKCAPITALLETTEROMEGAWITHTONOS*/+   { 913, LATEX_MATH, "Alpha",   { "$\\Alpha$",   "\\Alpha",    NULL    } }, /*GREEK CAPITAL LETTERALPHA*/+   { 914, LATEX_MATH, "Beta",    { "$\\Beta$",    "\\Beta",     NULL    } }, /*GREEK CAPITAL LETTERBETA*/+   { 915, LATEX_MATH, "Gamma",   { "$\\Gamma$",   "\\Gamma",    NULL    } }, /*GREEK CAPITAL LETTERGAMMA*/+   { 916, LATEX_MATH, "Delta",   { "$\\Delta$",   "\\Delta",    NULL    } }, /*GREEK CAPITAL LETTERDELTA*/+   { 917, LATEX_MATH, "Epsilon", { "$\\Epsilon$", "\\Epsilon",  NULL    } }, /*GREEK CAPITAL LETTEREPSILON*/+   { 918, LATEX_MATH, "Zeta",    { "$\\Zeta$",     "\\Zeta",    NULL    } }, /*GREEK CAPITAL LETTERZETA*/+   { 919, LATEX_MATH, "Eta",     { "$\\Eta$",      "\\Eta",     NULL    } }, /*GREEK CAPITAL LETTERETA*/+   { 920, LATEX_MATH, "Theta",   { "$\\Theta$",    "\\Theta",   NULL    } }, /*GREEK CAPITAL LETTERTHETA*/+   { 921, LATEX_MATH, "Iota",    { "$\\Iota$",     "\\Iota",    NULL    } }, /*GREEK CAPITAL LETTERIOTA*/+   { 922, LATEX_MATH, "Kappa",   { "$\\Kappa$",    "\\Kappa",   NULL    } }, /*GREEK CAPITAL LETTERKAPPA*/+   { 923, LATEX_MATH, "Lambda",  { "$\\Lambda$",   "\\Lambda",  NULL    } }, /*GREEK CAPITAL LETTERLAMDA*/+   { 924, LATEX_MATH, "Mu",      { "$\\Mu$",       "\\Mu",      NULL    } }, /*GREEK CAPITAL LETTERMU*/+   { 925, LATEX_MATH, "Nu",      { "$\\Nu$",       "\\Nu",      NULL    } }, /*GREEK CAPITAL LETTERNU*/+   { 926, LATEX_MATH, "Xi",      { "$\\Xi$",       "\\Xi",      NULL    } }, /*GREEK CAPITAL LETTERXI*/+   { 927, LATEX_MATH, "Omicron", { "$\\Omicron$",  "\\Omicron", NULL    } }, /*GREEK CAPITAL LETTEROMICRON*/+   { 928, LATEX_MATH, "Pi",      { "$\\Pi$",       "\\Pi",      NULL    } }, /*GREEK CAPITAL LETTERPI*/+   { 929, LATEX_MATH, "Rho",     { "$\\Rho$",      "\\Rho",     NULL    } }, /*GREEK CAPITAL LETTERRHO*/+   { 931, LATEX_MATH, "Sigma",   { "$\\Sigma$",    "\\Sigma",   NULL    } }, /*GREEK CAPITAL LETTERSIGMA*/+   { 932, LATEX_MATH, "Tau",     { "$\\Tau$",      "\\Tau",     NULL    } }, /*GREEK CAPITAL LETTERTAU*/+   { 933, LATEX_MATH, "Upsilon", { "$\\Upsilon$",  "\\Upsilon", NULL    } }, /*GREEK CAPITAL LETTERUPSILON*/+   { 934, LATEX_MATH, "Phi",     { "$\\Phi$",      "\\Phi",     NULL    } }, /*GREEK CAPITAL LETTERPHI*/+   { 935, LATEX_MATH, "Chi",     { "$\\Chi$",      "\\Chi",     NULL    } }, /*GREEK CAPITAL LETTERCHI*/+   { 936, LATEX_MATH, "Psi",     { "$\\Psi$",      "\\Psi",     NULL    } }, /*GREEK CAPITAL LETTERPSI*/+   { 937, LATEX_MATH, "Omega",   { "$\\Omega$",    "\\Omega",   NULL    } }, /*GREEK CAPITAL LETTEROMEGA*/+   /* 902 = GREEK CAPITAL LETTER ALPHAWITHTONOS*/+   /* 904 = GREEK CAPITAL LETTER EPSILONWITHTONOS*/+   /* 905 = GREEK CAPITAL LETTER ETAWITHTONOS*/+   /* 938 = GREEK CAPITAL LETTER IOTAWITHDIALYTIKA*/+   /* 906 = GREEK CAPITAL LETTER IOTAWITHTONOS*/+   /* 908 = GREEK CAPITAL LETTER OMICRONWITHTONOS*/+   /* 939 = GREEK CAPITAL LETTER UPSILONWITHDIALYTIKA*/+   /* 910 = GREEK CAPITAL LETTER UPSILONWITHTONOS*/+   /* 911, = GREEK CAPITAL LETTER OMEGAWITHTONOS*/ -   { 945, "$\\alpha$", "\\alpha", ""       }, /*GREEKSMALLLETTERALPHA*/-   /* 940 = GREEKSMALLLETTERALPHAWITHTONOS*/-   { 946, "$\\beta$", "\\beta", ""        }, /*GREEKSMALLLETTERBETA*/-   { 968, "$\\psi$", "\\psi", ""         }, /*GREEKSMALLLETTERPSI*/-   { 948, "$\\delta$", "\\delta", ""       }, /*GREEKSMALLLETTERDELTA*/-   { 949, "$\\epsilon$", "\\epsilon", ""     }, /*GREEKSMALLLETTEREPSILON*/-   /* 941 = GREEKSMALLLETTEREPSILONWITHTONOS*/-   { 966, "$\\phi$", "\\phi", ""         }, /*GREEKSMALLLETTERPHI*/-   { 947, "$\\gamma$", "\\gamma", ""       }, /*GREEKSMALLLETTERGAMMA*/-   { 951, "$\\eta$", "\\eta", ""         }, /*GREEKSMALLLETTERETA*/-   /* 942 = GREEKSMALLLETTERETAWITHTONOS */-   { 953, "$\\iota$", "\\iota", ""        }, /*GREEKSMALLLETTERIOTA*/-   /* 912 = GREEKSMALLLETTERIOTAWITHDIALYTIKAANDTONOS*/-   /* 943 = GREEKSMALLLETTERIOTAWITHTONOS */-   /* 970 = GREEKSMALLLETTERIOTAWITHDIALYTIKA */-   { 958, "$\\xi$", "\\xi", ""          }, /*GREEKSMALLLETTERXI*/-   { 954, "$\\kappa$", "\\kappa" , ""      }, /*GREEKSMALLLETTERKAPPA*/-   { 955, "$\\lambda$", "\\lambda", ""      }, /*GREEKSMALLLETTERLAMDA*/-   { 956, "$\\mu$", "\\mu", ""          }, /*GREEKSMALLLETTERMU*/-   { 957, "$\\nu$", "\\nu", ""          }, /*GREEKSMALLLETTERNU*/-   { 959, "$\\omicron$", "\\omicron", ""     }, /*GREEKSMALLLETTEROMICRON*/-   /* 972 = GREEKSMALLLETTEROMICRONWITHTONOS*/-   { 960, "$\\pi$", "\\pi", ""          }, /*GREEKSMALLLETTERPI*/-   { 961, "$\\rho$", "\\rho", ""         }, /*GREEKSMALLLETTERRHO*/-   { 963, "$\\sigma$", "\\sigma", ""       }, /*GREEKSMALLLETTERSIGMA*/-   { 964, "$\\tau$", "\\tau", ""         }, /*GREEKSMALLLETTERTAU*/-   { 952, "$\\theta$", "\\theta", ""       }, /*GREEKSMALLLETTERTHETA*/-   { 969, "$\\omega$", "\\omega", ""       }, /*GREEKSMALLLETTEROMEGA*/-   /* 974 = GREEKSMALLLETTEROMEGAWITHTONOS*/-   { 967, "$\\chi$", "\\chi", ""         }, /*GREEKSMALLLETTERCHI*/-   { 965, "$\\upsilon$", "\\upsilon", ""     }, /*GREEKSMALLLETTERUPSILON*/-   /* 973 = GREEKSMALLLETTERUPSILONWITHTONOS*/-   /* 971 = GREEKSMALLLETTERUPSILONWITHDIALYTIKA*/-   /* 944 = GREEKSMALLLETTERUPSILONWITHDIALYTIKAANDTONOS*/-   { 950, "$\\zeta$", "\\zeta", ""        },  /*GREEKSMALLLETTERZETA*/+   { 945, LATEX_MATH, "alpha",   { "$\\alpha$",    "\\alpha",   NULL    } }, /*GREEK SMALL LETTER ALPHA*/+   { 946, LATEX_MATH, "beta",    { "$\\beta$",     "\\beta",    NULL    } }, /*GREEK SMALL LETTER BETA*/+   { 968, LATEX_MATH, "psi",     { "$\\psi$",      "\\psi",     NULL    } }, /*GREEK SMALL LETTER PSI*/+   { 948, LATEX_MATH, "delta",   { "$\\delta$",    "\\delta",   NULL    } }, /*GREEK SMALL LETTER DELTA*/+   { 949, LATEX_MATH, "epsilon", { "$\\epsilon$",  "\\epsilon", NULL    } }, /*GREEK SMALL LETTER EPSILON*/+   { 966, LATEX_MATH, "phi",     { "$\\phi$",      "\\phi",     NULL    } }, /*GREEK SMALL LETTER PHI*/+   { 947, LATEX_MATH, "gamma",   { "$\\gamma$", "\\gamma", NULL }   }, /*GREEK SMALL LETTER GAMMA*/+   { 951, LATEX_MATH, "eta",     { "$\\eta$", "\\eta", NULL }     }, /*GREEK SMALL LETTER ETA*/+   { 953, LATEX_MATH, "iota",    { "$\\iota$", "\\iota", NULL }    }, /*GREEK SMALL LETTER IOTA*/+   { 958, LATEX_MATH, "xi",      { "$\\xi$", "\\xi", NULL }      }, /*GREEK SMALL LETTER XI*/+   { 954, LATEX_MATH, "kappa",   { "$\\kappa$", "\\kappa" , NULL }  }, /*GREEK SMALL LETTER KAPPA*/+   { 955, LATEX_MATH, "lambda",  { "$\\lambda$", "\\lambda", NULL }  }, /*GREEK SMALL LETTER LAMDA*/+   { 956, LATEX_MATH, "mu",      { "$\\mu$", "\\mu", NULL }      }, /*GREEK SMALL LETTER MU*/+   { 957, LATEX_MATH, "nu",      { "$\\nu$", "\\nu", NULL }      }, /*GREEK SMALL LETTER NU*/+   { 959, LATEX_MATH, "omicron", { "$\\omicron$", "\\omicron", NULL  }    }, /*GREEK SMALL LETTER OMICRON*/+   { 960, LATEX_MATH, "pi",      { "$\\pi$", "\\pi", NULL }      }, /*GREEK SMALL LETTER PI*/+   { 961, LATEX_MATH, "rho",     { "$\\rho$", "\\rho", NULL }     }, /*GREEK SMALL LETTER RHO*/+   { 963, LATEX_MATH, "sigma",   { "$\\sigma$", "\\sigma", NULL }   }, /*GREEK SMALL LETTER SIGMA*/+   { 964, LATEX_MATH, "tau",     { "$\\tau$", "\\tau", NULL }     }, /*GREEK SMALL LETTER TAU*/+   { 952, LATEX_MATH, "theta",   { "$\\theta$", "\\theta", NULL }   }, /*GREEK SMALL LETTER THETA*/+   { 969, LATEX_MATH, "omega",   { "$\\omega$", "\\omega", NULL }   }, /*GREEK SMALL LETTER OMEGA*/+   { 967, LATEX_MATH, "chi",     { "$\\chi$", "\\chi", NULL }     }, /*GREEK SMALL LETTER CHI*/+   { 965, LATEX_MATH, "upsilon", { "$\\upsilon$", "\\upsilon", NULL } }, /*GREEK SMALL LETTER UPSILON*/+   { 950, LATEX_MATH, "zeta",    { "$\\zeta$", "\\zeta", NULL }    },  /*GREEK SMALL LETTER ZETA*/+   /* 940 = GREEK SMALL LETTER ALPHAWITHTONOS*/+   /* 941 = GREEK SMALL LETTER EPSILONWITHTONOS*/+   /* 942 = GREEK SMALL LETTER ETAWITHTONOS */+   /* 912 = GREEK SMALL LETTER IOTAWITHDIALYTIKAANDTONOS*/+   /* 943 = GREEK SMALL LETTER IOTAWITHTONOS */+   /* 970 = GREEK SMALL LETTER IOTAWITHDIALYTIKA */+   /* 972 = GREEK SMALL LETTER OMICRONWITHTONOS*/+   /* 974 = GREEK SMALL LETTER OMEGAWITHTONOS*/+   /* 973 = GREEK SMALL LETTER UPSILONWITHTONOS*/+   /* 971 = GREEK SMALL LETTER UPSILONWITHDIALYTIKA*/+   /* 944 = GREEK SMALL LETTER UPSILONWITHDIALYTIKAANDTONOS*/ -   { 181, "{\\textmu}", "\\textmu", "$\\mu$" }, /* 181=micro sign, techically &#xB5; */+   { 181, LATEX_MACRO, "textmu", { "{\\textmu}", "\\textmu", "$\\mu$" } }, /* 181=micro sign, techically &#xB5; */  /* Make sure that these don't stomp on other latex things above */ -   { 8242, "{\\textasciiacutex}", "\\textasciiacutex", "$'$" },  /* Prime symbol &#x2032; */-   { 180, "{\\textasciiacute}", "\\textasciiacute", "\\'" }, /* acute accent &#xB4; */-/*   { 769,  "\\'",    "", "" },*/  /* Acute accent &#x0301;--apply to next char */--   { 8243, "{\\textacutedbl}", "\\textacutedbl", "$''$" },  /* Double prime &#x2033; */-   { 8245, "{\\textasciigrave}", "\\textasciigrave", "\\`" }, /* Grave accent &#x2035; */-/*   { 768,  "\\`",    "", "" },*/  /* Grave accent &#x0300;--apply to next char */+   { 8242, LATEX_MACRO, "textasciiacutex",   { "{\\textasciiacutex}",   "\\textasciiacutex",     "$'$"                 } }, /* Prime symbol &#x2032; */+   { 180,  LATEX_MACRO, "textasciiacute",    { "{\\textasciiacute}",    "\\textasciiacute",      "\\'"                 } }, /* acute accent &#xB4; */+   { 8243, LATEX_MACRO, "textacutedbl",      { "{\\textacutedbl}",      "\\textacutedbl",        "$''$"                } }, /* Double prime &#x2033; */+   { 8245, LATEX_MACRO, "textasciigrave",    { "{\\textasciigrave}",    "\\textasciigrave",      "\\`"                 } }, /* Grave accent &#x2035; */+/* { 768,  LATEX_MACRO, "`",                 { "\\`",                   NULL,                    NULL                  } },*//* Grave accent &#x0300;--apply to next char */+/* { 769,  LATEX_MACRO, "'",                 { "\\'",                   NULL,                    NULL                  } },*//* Acute accent &#x0301;--apply to next char */ -   { 8963, "{\\textasciicircum}", "\\textasciicircum", ""} , /* &#x2303; */-   { 184,  "{\\textasciicedilla}", "\\textasciicedilla", "" },  /* cedilla &#xB8; */-   { 168,  "{\\textasciidieresis}", "\\textasciidieresis", "" }, /* dieresis &#xA8; */-   { 175,  "{\\textasciimacron}", "\\textasciimacron", "" }, /* macron &#xAF; */+   { 8963, LATEX_MACRO, "textasciicircum",   { "{\\textasciicircum}",   "\\textasciicircum",     NULL                  } }, /* &#x2303; */+   { 184,  LATEX_MACRO, "textasciicedilla",  { "{\\textasciicedilla}",  "\\textasciicedilla",    NULL                  } }, /* cedilla &#xB8; */+   { 168,  LATEX_MACRO, "textasciidieresis", { "{\\textasciidieresis}", "\\textasciidieresis",   NULL                  } }, /* dieresis &#xA8; */+   { 175,  LATEX_MACRO, "textasciimacron",   { "{\\textasciimacron}",   "\\textasciimacron",     NULL                  } }, /* macron &#xAF; */ -   { 8593, "{\\textuparrow}", "\\textuparrow", "" },    /* Up arrow &#x2191; */-   { 8595, "{\\textdownarrow}", "\\textdownarrow", "" },  /* Down arrow &#x2193; */-   { 8594, "{\\textrightarrow}", "\\textrightarrow", "" }, /* Right arrow &#x2192; */-   { 8592, "{\\textleftarrow}", "\\textleftarrow", "" },  /* Left arrow &#x2190; */-   { 12296, "{\\textlangle}", "\\textlangle", "" } ,   /* L-angle &#x3008; */-   { 12297, "{\\textrangle}", "\\textrangle", "" } ,   /* L-angle &#x3009; */+   { 8593, LATEX_MACRO, "textuparrow",       { "{\\textuparrow}",       "\\textuparrow",         NULL                  } }, /* Up arrow &#x2191; */+   { 8595, LATEX_MACRO, "textdownarrow",     { "{\\textdownarrow}",     "\\textdownarrow",       NULL                  } }, /* Down arrow &#x2193; */+   { 8594, LATEX_MACRO, "textrightarrow",    { "{\\textrightarrow}",    "\\textrightarrow",      NULL                  } }, /* Right arrow &#x2192; */+   { 8592, LATEX_MACRO, "textleftarrow",     { "{\\textleftarrow}",     "\\textleftarrow",       NULL                  } }, /* Left arrow &#x2190; */+   { 12296,LATEX_MACRO, "textlangle",        { "{\\textlangle}",        "\\textlangle",          NULL                  } }, /* L-angle &#x3008; */+   { 12297,LATEX_MACRO, "textrangle",        { "{\\textrangle}",        "\\textrangle",          NULL                  } }, /* L-angle &#x3009; */ -   { 166, "{\\textbrokenbar}", "\\textbrokenbar", "" }, /* Broken vertical bar &#xA6; */-   { 167, "{\\textsection}", "\\textsection", "\\S{}" },   /* Section sign, &#xA7; */-   { 170, "{\\textordfeminine}", "\\textordfeminine", "$^a$" }, /* &#xAA; */-   { 172, "{\\textlnot}", "\\textlnot", "" },      /* Lnot &#xAC; */-   { 182, "{\\textparagraph}", "\\textparagraph", "" }, /* Paragraph sign &#xB6; */-   { 183, "{\\textperiodcentered}", "\\textperiodcentered", "" }, /* Period-centered &#xB7; */-   { 186, "{\\textordmasculine}", "\\textordmasculine", "" }, /* &#xBA; */-   { 8214, "{\\textbardbl}", "\\textbardbl", "" },   /* Double vertical bar &#x2016; */-   { 8224, "{\\textdagger}", "\\textdagger", "" },   /* Dagger &#x2020; */-   { 8225, "{\\textdaggerdbl}", "\\textdaggerdbl", "" },/* Double dagger &x2021; */-   { 8226, "{\\textbullet}", "\\textbullet", "" },   /* Bullet &#x2022; */-   { 8494, "{\\textestimated}", "\\textestimated", "" },/* Estimated &#x212E; */-   { 9526, "{\\textopenbullet}", "\\textopenbullet", "" },/* &#x2536; */+   { 166,  LATEX_MACRO, "textbrokenbar",     { "{\\textbrokenbar}",     "\\textbrokenbar",       NULL                  } }, /* Broken vertical bar &#xA6; */+   { 167,  LATEX_MACRO, "textsection",       { "{\\textsection}",       "\\textsection",         "\\S{}"               } }, /* Section sign, &#xA7; */+   { 170,  LATEX_MACRO, "textordfeminine",   { "{\\textordfeminine}",   "\\textordfeminine",     "$^a$"                } }, /* &#xAA; */+   { 172,  LATEX_MACRO, "textlnot",          { "{\\textlnot}",          "\\textlnot",            NULL                  } }, /* Lnot &#xAC; */+   { 182,  LATEX_MACRO, "textparagraph",     { "{\\textparagraph}",     "\\textparagraph",       NULL                  } }, /* Paragraph sign &#xB6; */+   { 183,  LATEX_MACRO, "textperiodcentered",{ "{\\textperiodcentered}","\\textperiodcentered",  NULL                  } }, /* Period-centered &#xB7; */+   { 186,  LATEX_MACRO, "textordmasculine",  { "{\\textordmasculine}",  "\\textordmasculine",    NULL                  } }, /* &#xBA; */+   { 8214, LATEX_MACRO, "textbardbl",        { "{\\textbardbl}",        "\\textbardbl",          NULL                  } }, /* Double vertical bar &#x2016; */+   { 8224, LATEX_MACRO, "textdagger",        { "{\\textdagger}",        "\\textdagger",          NULL                  } }, /* Dagger &#x2020; */+   { 8225, LATEX_MACRO, "textdaggerdbl",     { "{\\textdaggerdbl}",     "\\textdaggerdbl",       NULL                  } }, /* Double dagger &x2021; */+   { 8226, LATEX_MACRO, "textbullet",        { "{\\textbullet}",        "\\textbullet",          NULL                  } }, /* Bullet &#x2022; */+   { 8494, LATEX_MACRO, "textestimated",     { "{\\textestimated}",     "\\textestimated",       NULL                  } }, /* Estimated &#x212E; */+   { 9526, LATEX_MACRO, "textopenbullet",    { "{\\textopenbullet}",    "\\textopenbullet",      NULL                  } }, /* &#x2536; */ -   { 8220, "``", "{\\textquotedblleft}", "\\textquotedblleft" }, /* Opening double quote &#x201C; */-   { 8221, "''", "{\\textquotedblright}","\\textquotedblright" }, /* Closing double quote &#x201D; */-   { 8216, "`",  "{\\textquoteleft}", "\\textquoteleft" },    /* Opening single quote &#x2018; */-   { 8217, "'",  "{\\textquoteright}", "\\textquoteright" },   /* Closing single quote &#x2019; */-   { 8261, "{\\textlquill}", "\\textlquill", "" },         /* Left quill &#x2045; */-   { 8262, "{\\textrquill}", "\\textrquill", "" },         /* Right quill &#x2046; */+   { 8220, LATEX_COMBO, "``",                { "``",                    "{\\textquotedblleft}",  "\\textquotedblleft"  } }, /* Opening double quote &#x201C; */+   { 8221, LATEX_COMBO, "''",                { "''",                    "{\\textquotedblright}", "\\textquotedblright" } }, /* Closing double quote &#x201D; */+   { 8216, LATEX_COMBO, "`",                 { "`",                     "{\\textquoteleft}",     "\\textquoteleft"     } }, /* Opening single quote &#x2018; */+   { 8217, LATEX_COMBO, "'",                 { "'",                     "{\\textquoteright}",    "\\textquoteright"    } }, /* Closing single quote &#x2019; */+   { 8261, LATEX_MACRO, "textlquill",        { "{\\textlquill}",        "\\textlquill",          NULL                  } }, /* Left quill &#x2045; */+   { 8262, LATEX_MACRO, "textrquill",        { "{\\textrquill}",        "\\textrquill",          NULL                  } }, /* Right quill &#x2046; */ -   { 8212, "---",     "{\\textemdash}", "\\textemdash" },     /* Em-dash &#x2014; */-   { 8211, "--",      "{\\textendash}", "\\textendash" },     /* En-dash &#x2013; */-   { 8230, "\\ldots", "{\\textellipsis}", "\\textellipsis" },   /* Ellipsis &#x2026; */+   { 8212, LATEX_COMBO, "---",               { "---",                   "{\\textemdash}",        "\\textemdash"        } }, /* Em-dash &#x2014; */+   { 8211, LATEX_COMBO, "--",                { "--",                    "{\\textendash}",        "\\textendash"        } }, /* En-dash &#x2013; */+   { 8230, LATEX_MACRO, "ldots",             { "{\\ldots}",             "{\\textellipsis}",      "\\textellipsis"      } }, /* Ellipsis &#x2026; */ -   { 8194, "\\enspace", "\\hspace{.5em}", "" }, /* En-space &#x2002; */-   { 8195, "\\emspace", "\\hspace{1em}",  "" }, /* Em-space &#x2003; */-   { 8201, "\\thinspace", "", ""},              /* Thin space &#x2009; */-   { 8203, "{\\textnospace}", "\\textnospace", "" },           /* No space &#x200B; */-   { 9251, "{\\textvisiblespace}", "\\textvisiblespace", "" },      /* Visible space &#x2423; */+   { 8194, LATEX_MACRO, "enspace",           { "{\\enspace}",           "\\hspace{.5em}",        NULL                  } }, /* En-space &#x2002; */+   { 8195, LATEX_MACRO, "emspace",           { "{\\emspace}",           "\\hspace{1em}",         NULL                  } }, /* Em-space &#x2003; */+   { 8201, LATEX_MACRO, "thinspace",         { "{\\thinspace}",         NULL,                    NULL                  } }, /* Thin space &#x2009; */+   { 8203, LATEX_MACRO, "textnospace",       { "{\\textnospace}",       "\\textnospace",         NULL                  } }, /* No space &#x200B; */+   { 9251, LATEX_MACRO, "textvisiblespace",  { "{\\textvisiblespace}",  "\\textvisiblespace",    NULL                  } }, /* Visible space &#x2423; */ -   { 215, "{\\texttimes}", "\\texttimes", "" }, /* Multiplication symbol &#xD7; */-   { 247, "{\\textdiv}", "\\textdiv", "" },   /* Division symbol &#xF7; */-   { 177, "{\\textpm}", "\\textpm", "" }, /* Plus-minus character &#B1; */-   { 189, "{\\textonehalf}", "\\textonehalf", "" }, /* Vulgar fraction one half &#xBD; */-   { 188, "{\\textonequarter}", "\\textonequarter", "" }, /* Vulgar fraction one quarter &#xBD; */-   { 190, "{\\textthreequarters}", "\\textthreequarters", "" }, /* Vulgar fraction three quarters &#xBE; */-   { 8240, "{\\texttenthousand}", "\\texttenthousand", "" }, /* Per thousand sign &#x2030; */-   { 8241, "{\\textpertenthousand}", "\\textpertenthousand", "" }, /* Per ten thousand sign &#x2031;*/-   { 8260, "{\\textfractionsolidus}", "\\textfractionsolidus", "" }, /* &x8260; */-   { 8451, "{\\textcelcius}", "\\textcelcius", "" }, /* Celcicus &#x2103; */-   { 8470, "{\\textnumero}", "\\textnumero", "" },  /* Numero symbol &#x2116; */-   { 8486, "{\\textohm}", "\\textohm", "" }, /* Ohm symbol &#x2126; */-   { 8487, "{\\textmho}", "\\textmho", "" }, /* Mho symbol &#x2127; */-   { 8730, "{\\textsurd}", "\\textsurd", "" }, /* &#x221A; */+   { 215,  LATEX_MACRO, "texttimes",         { "{\\texttimes}",         "\\texttimes",           NULL                  } }, /* Multiplication symbol &#xD7; */+   { 247,  LATEX_MACRO, "textdiv",           { "{\\textdiv}",           "\\textdiv",             NULL                  } }, /* Division symbol &#xF7; */+   { 177,  LATEX_MACRO, "textpm",            { "{\\textpm}",            "\\textpm",              NULL                  } }, /* Plus-minus character &#B1; */+   { 189,  LATEX_MACRO, "textonehalf",       { "{\\textonehalf}",       "\\textonehalf",         NULL                  } }, /* Vulgar fraction one half &#xBD; */+   { 188,  LATEX_MACRO, "textonequarter",    { "{\\textonequarter}",    "\\textonequarter",      NULL                  } }, /* Vulgar fraction one quarter &#xBD; */+   { 190,  LATEX_MACRO, "textthreequarters", { "{\\textthreequarters}", "\\textthreequarters",   NULL                  } }, /* Vulgar fraction three quarters &#xBE; */+   { 8240, LATEX_MACRO, "texttenthousand",   { "{\\texttenthousand}",   "\\texttenthousand",     NULL                  } }, /* Per thousand sign &#x2030; */+   { 8241, LATEX_MACRO, "textpertenthousand",{ "{\\textpertenthousand}","\\textpertenthousand",  NULL                  } }, /* Per ten thousand sign &#x2031;*/+   { 8260, LATEX_MACRO, "textfractionssolidus",{"{\\textfractionsolidus}", "\\textfractionsolidus", NULL               } }, /* &x8260; */+   { 8451, LATEX_MACRO, "textcelcius",       { "{\\textcelcius}",       "\\textcelcius",         NULL                  } }, /* Celcicus &#x2103; */+   { 8470, LATEX_MACRO, "textnumero",        { "{\\textnumero}",        "\\textnumero",          NULL                  } }, /* Numero symbol &#x2116; */+   { 8486, LATEX_MACRO, "textohm",           { "{\\textohm}",           "\\textohm",             NULL                  } }, /* Ohm symbol &#x2126; */+   { 8487, LATEX_MACRO, "textmho",           { "{\\textmho}",           "\\textmho",             NULL                  } }, /* Mho symbol &#x2127; */+   { 8730, LATEX_MACRO, "textsurd",          { "{\\textsurd}",          "\\textsurd",            NULL                  } }, /* &#x221A; */ -   { 185, "{\\textonesuperior}", "\\textonesuperior", "" },   /*Superscript 1 &#xB9; */-   { 178, "{\\texttwosuperior}", "\\texttwosuperior", "" },   /*Superscript 2 &#xB2; */-   { 179, "{\\textthreesuperior}", "\\textthreesuperior", "" }, /*Superscript 3 &#xB3; */+   { 185,  LATEX_MACRO, "textonesuperior",   { "{\\textonesuperior}",   "\\textonesuperior",     "$^1$"                } }, /*Superscript 1 &#xB9; */+   { 178,  LATEX_MACRO, "texttwosuperior",   { "{\\texttwosuperior}",   "\\texttwosuperior",     "$^2$"                } }, /*Superscript 2 &#xB2; */+   { 179,  LATEX_MACRO, "textthreesuperior", { "{\\textthreesuperior}", "\\textthreesuperior",   "$^3$"                } }, /*Superscript 3 &#xB3; */ -   { 161, "{\\textexclamdown}", "\\textexclamdown", "" },   /* Inverted exclamation mark &#xA1;*/-   { 191, "{\\textquestiondown}", "\\textquestiondown", "" }, /* Inverted question mark &#xBF; */+   { 161,  LATEX_MACRO, "textexclamdown",    { "{\\textexclamdown}",    "\\textexclamdown",      NULL                  } }, /* Inverted exclamation mark &#xA1;*/+   { 191,  LATEX_MACRO, "textquestiondown",  { "{\\textquestiondown}",  "\\textquestiondown",    NULL                  } }, /* Inverted question mark &#xBF; */ -   { 162, "{\\textcent}", "\\textcent", "" },         /* Cent sign &#xA2; */-   { 163, "{\\textsterling}", "\\textsterling", "\\pounds" },     /* Pound sign &#xA3; */-   { 165, "{\\textyen}", "\\textyen", "" },          /* Yen sign &#xA5; */-   { 402, "{\\textflorin}", "\\textflorin", "" },       /* Florin sign &#x192; */-   { 3647, "{\\textbaht}", "\\textbaht", "" },        /* Thai currency &#xE3F; */-   { 8355, "{\\textfrenchfranc}", "\\textfrenchfranc", "" }, /* French franc &#x20A3; */-   { 8356, "{\\textlira}", "\\textlira", "" },        /* Lira &#x20A4; */-   { 8358, "{\\textnaira}", "\\textnaria", "" },       /* Naira &#x20A6; */-   { 8361, "{\\textwon}", "\\textwon", "" },         /* &#x20A9; */-   { 8363, "{\\textdong}", "\\textdong", "" },        /* Vietnamese currency &#x20AB; */-   { 8364, "{\\texteuro}", "\\texteuro", "" },        /* Euro sign */+   { 162,  LATEX_MACRO, "textcent",          { "{\\textcent}",          "\\textcent",            NULL                  } }, /* Cent sign &#xA2; */+   { 163,  LATEX_MACRO, "textsterling",      { "{\\textsterling}",      "\\textsterling",        "\\pounds"            } }, /* Pound sign &#xA3; */+   { 165,  LATEX_MACRO, "textyen",           { "{\\textyen}",           "\\textyen",             NULL                  } }, /* Yen sign &#xA5; */+   { 402,  LATEX_MACRO, "textflorin",        { "{\\textflorin}",        "\\textflorin",          NULL                  } }, /* Florin sign &#x192; */+   { 3647, LATEX_MACRO, "textbaht",          { "{\\textbaht}",          "\\textbaht",            NULL                  } }, /* Thai currency &#xE3F; */+   { 8355, LATEX_MACRO, "textfrenchfranc",   { "{\\textfrenchfranc}",   "\\textfrenchfranc",     NULL                  } }, /* French franc &#x20A3; */+   { 8356, LATEX_MACRO, "textlira",          { "{\\textlira}",          "\\textlira",            NULL                  } }, /* Lira &#x20A4; */+   { 8358, LATEX_MACRO, "textnaira",         { "{\\textnaira}",         "\\textnaria",           NULL                  } }, /* Naira &#x20A6; */+   { 8361, LATEX_MACRO, "textwon",           { "{\\textwon}",           "\\textwon",             NULL                  } }, /* &#x20A9; */+   { 8363, LATEX_MACRO, "textdong",          { "{\\textdong}",          "\\textdong",            NULL                  } }, /* Vietnamese currency &#x20AB; */+   { 8364, LATEX_MACRO, "texteuro",          { "{\\texteuro}",          "\\texteuro",            NULL                  } }, /* Euro sign */ -   { 169, "{\\textcopyright}", "\\textcopyright", "" },           /* Copyright (C) &#xA9; */-   { 175, "{\\textregistered}", "\\textregistered", "" },          /* Registered sign (R) &#xAF;*/-   { 8482, "{\\texttrademark}", "\\texttrademark", "$^{TM}$" },   /* Trademark (TM) &#x2122; */-   { 8480, "{\\textservicemark}", "\\textservicemark", "$^{SM}$" }, /* Servicemark (SM) &#x2120;*/-   { 8471, "{\\textcircledP}", "\\textcircledP", "" },           /* Circled P &#2117; */+   { 169,  LATEX_MACRO, "textcopyright",     { "{\\textcopyright}",     "\\textcopyright",       NULL                  } }, /* Copyright (C) &#xA9; */+   { 175,  LATEX_MACRO, "textregistered",    { "{\\textregistered}",    "\\textregistered",      NULL                  } }, /* Registered sign (R) &#xAF;*/+   { 8482, LATEX_MACRO, "texttrademark",     { "{\\texttrademark}",     "\\texttrademark",       "$^{TM}$"             } }, /* Trademark (TM) &#x2122; */+   { 8480, LATEX_MACRO, "textservicemark",   { "{\\textservicemark}",   "\\textservicemark",     "$^{SM}$"             } }, /* Servicemark (SM) &#x2120;*/+   { 8471, LATEX_MACRO, "textcircledP",      { "{\\textcircledP}",      "\\textcircledP",        NULL                  } }, /* Circled P &#2117; */  }; @@ -505,31 +509,35 @@ latex2char( char *s, unsigned int *pos, int *unicode ) { 	unsigned int value;-	char *p, *q[3];-	int i, j, l[3];+//	char *p, *q[3];+	int i, j, len;+	char *p;+ 	p = &( s[*pos] ); 	value = (unsigned char) *p; 	if ( value=='{' || value=='\\' || value=='~' ||  	     value=='$' || value=='\'' || value=='`' ||  	     value=='-' || value=='^' ) {-		if ( *p=='\\' && ( *p=='{' || *p=='}' ) ) {-		} else {+//		if ( *p=='\\' && ( *p=='{' || *p=='}' ) ) {+//		} else { 		for ( i=0; i<nlatex_chars; ++i ) {-			q[0] = latex_chars[i].bib1;-			l[0] = strlen( q[0] );-			q[1] = latex_chars[i].bib2;-			l[1] = strlen( q[1] );-			q[2] = latex_chars[i].bib3;-			l[2] = strlen( q[2] );+//			q[0] = latex_chars[i].bib1;+//			l[0] = strlen( q[0] );+//			q[1] = latex_chars[i].bib2;+//			l[1] = strlen( q[1] );+//			q[2] = latex_chars[i].bib3;+//			l[2] = strlen( q[2] ); 			for ( j=0; j<3; ++j ) {-				if ( l[j] && !strncmp( p, q[j], l[j] ) ) {-					*pos = *pos + l[j];+				if ( latex_chars[i].variant[j] == NULL ) continue;+				len = strlen( latex_chars[i].variant[j] );+				if ( !strncmp( p, latex_chars[i].variant[j], len ) ) {+					*pos = *pos + len; 					*unicode = 1; 					return latex_chars[i].unicode; 				} 			} 		}-		}+//		} 	} 	*unicode = 0; 	*pos = *pos + 1;@@ -539,20 +547,51 @@ void uni2latex( unsigned int ch, char buf[], int buf_size ) {-	int i;+	int i, j, n;++	if ( buf_size==0 ) return;+ 	buf[0] = '?'; 	buf[1] = '\0';+ 	if ( ch==' ' ) { 		buf[0] = ' '; /*special case to avoid &nbsp;*/ 		return; 	}+ 	for ( i=0; i<nlatex_chars; ++i ) { 		if ( ch == latex_chars[i].unicode ) {-			strncpy( buf, latex_chars[i].bib1, buf_size );-			buf[ buf_size-1 ] = '\0';+			n = 0;++			if ( latex_chars[i].type == LATEX_MACRO ) {+				if ( n < buf_size ) buf[n++] = '{';+				if ( n < buf_size ) buf[n++] = '\\';+			}+			else if ( latex_chars[i].type == LATEX_MATH ) {+				if ( n < buf_size ) buf[n++] = '$';+				if ( n < buf_size ) buf[n++] = '\\';+			}++			j = 0;+			while ( latex_chars[i].out[j] ) {+				if ( n < buf_size ) buf[n++] = latex_chars[i].out[j];+				j++;+			}++			if ( latex_chars[i].type == LATEX_MACRO ) {+				if ( n < buf_size ) buf[n++] = '}';+			}+			else if ( latex_chars[i].type == LATEX_MATH ) {+				if ( n < buf_size ) buf[n++] = '$';+			}++			if ( n < buf_size ) buf[n] = '\0';+			else buf[ buf_size-1 ] = '\0';+ 			return; 		} 	}-	if ( ch < 128 && buf[0]=='?' ) buf[0] = (char)ch;++	if ( ch < 128 ) buf[0] = (char)ch; } 
bibutils/latex.h view
@@ -1,7 +1,7 @@ /*  * latex.h  *- * Copyright (c) Chris Putnam 2004-2013+ * Copyright (c) Chris Putnam 2004-2017  *  * Source code released under the GPL version 2  *
− bibutils/list.c
@@ -1,607 +0,0 @@-/*- * list.c- *- * version: 2014-11-15- *- * Copyright (c) Chris Putnam 2004-2014- *- * Source code released under the GPL version 2- *- * Implements a simple managed array of newstrs.- *- */-#include "list.h"--void-list_init( list *a  )-{-	a->str = NULL;-	a->max = 0;-	a->n = 0;-	a->sorted = 1;-}--void-list_empty( list *a )-{-	int i;-	for ( i=0; i<a->max; ++i )-		newstr_empty( &(a->str[i]) );-	a->n = 0;-	a->sorted = 1;-}--void-list_free( list *a )-{-	int i;-	for ( i=0; i<a->max; ++i )-		newstr_free( &(a->str[i]) );-	free( a->str );-	list_init( a );-}--list *-list_new( void )-{-	list *a = ( list * ) malloc( sizeof ( list ) );-	if ( a ) list_init( a );-	return a;-}--void-list_delete( list *a )-{-	list_free( a );-	free( a );-}--/*- * returns 1 if n is valid string in list- */-static inline int-list_valid_num( list *a, int n )-{-	if ( n < 0 || n >= a->n ) return 0;-	return 1;-}--static int-list_comp( const void *v1, const void *v2 )-{-	newstr *s1 = ( newstr *) v1;-	newstr *s2 = ( newstr *) v2;-	if ( !s1->len && !s2->len ) return 0;-	else if ( !s1->len ) return -1;-	else if ( !s2->len ) return 1;-	else return strcmp( s1->data, s2->data );-}--static int-list_comp_step( list *a, int n1, int n2 )-{-	return list_comp( (const void*) &(a->str[n1]), (const void*) &(a->str[n2]) );-}--static newstr *-list_set_cleanup( list *a, int n )-{-	if ( newstr_memerr( &(a->str[n]) ) ) return NULL;-	if ( a->sorted ) {-		if ( n>0 && list_comp_step( a, n-1, n )>0 )-			a->sorted = 0;-	}-	if ( a->sorted ) {-		if ( n<a->n-1 && list_comp_step( a, n, n+1 )>0 )-			a->sorted = 0;-	}-	return &(a->str[n]);-}--newstr *-list_set( list *a, int n, newstr *s )-{-	if ( !list_valid_num( a, n ) ) return NULL;-	newstr_newstrcpy( &(a->str[n]), s );-	return list_set_cleanup( a, n );-}--newstr *-list_setc( list *a, int n, const char *s )-{-	if ( !list_valid_num( a, n ) ) return NULL;-	newstr_strcpy( &(a->str[n]), s );-	return list_set_cleanup( a, n );-}--/*- * return pointer to newstr 'n'- */-newstr *-list_get( list *a, int n )-{-	if ( !list_valid_num( a, n ) ) return NULL;-	else return &(a->str[n]);-}--/*- * return pointer to C string 'n'- *- * So long as the index is a valid number ensure- * that a pointer is returned even if the newstr doesn't- * point to data. Only return NULL if the index- * is invalid. Thus we can convert loops like:- *- * for ( i=0; i<a->n; ++i ) {- *      p = list_getc( a, i );- *      if ( p==NULL ) continue; // empty string- *      ...- * }- *- * to- *- * i = 0;- * while ( ( p = list_getc( a, i ) ) ) {- *      ...- *      i++;- * }- *- */-char *-list_getc( list *a, int n )-{-	static char empty[] = "";-	char *p;-	if ( !list_valid_num( a, n ) ) return NULL;-	p = a->str[n].data;-	if ( p ) return p;-	else return empty;-}--static int-list_alloc( list *a )-{-	int i, alloc = 20;-	a->str = ( newstr* ) malloc( sizeof( newstr ) * alloc );-	if ( !(a->str) ) return LIST_ERR;-	a->max = alloc;-	a->n = 0;-	for ( i=0; i<alloc; ++i )-		newstr_init( &(a->str[i]) );-	return LIST_OK;-}--static int-list_realloc( list *a )-{-	newstr *more;-	int i, alloc = a->max * 2;-	more = ( newstr* ) realloc( a->str, sizeof( newstr ) * alloc );-	if ( !more ) return LIST_ERR;-	a->str = more;-	for ( i=a->max; i<alloc; ++i )-		newstr_init( &(a->str[i]) );-	a->max = alloc;-	return LIST_OK;-}---static int-list_ensure_space( list *a )-{-	int status = LIST_OK;-	if ( a->max==0 )-		status = list_alloc( a );-	else if ( a->n >= a->max )-		status = list_realloc( a );-	return status;-}--newstr *-list_addvp( list *a, unsigned char mode, void *vp )-{-	newstr *s = NULL;-	int status;-	status = list_ensure_space( a );-	if ( status==LIST_OK ) {-		s = &( a->str[a->n] );-		if ( mode==LIST_CHR )-			newstr_strcpy( s, (const char*) vp );-		else if ( mode==LIST_STR )-			newstr_newstrcpy( s, (newstr*) vp );-		else-			return NULL;-		if ( newstr_memerr( s ) ) return NULL;-		a->n++;-		if ( a->sorted && a->n > 1 ) {-			if ( list_comp_step( a, a->n-2, a->n-1 ) > 0 )-				a->sorted = 0;-		}-	}-	return s;-}-newstr *-list_addc( list *a, const char *s )-{-	return list_addvp( a, LIST_CHR, (void*)s );-}-newstr *-list_add( list *a, newstr *s )-{-	return list_addvp( a, LIST_STR, (void*)s );-}--newstr *-list_addvp_unique( list *a, unsigned char mode, void *vp )-{-	newstr *s;-	int n;-	if ( mode==LIST_CHR )-		n = list_find( a, (const char*) vp );-	else if ( mode==LIST_STR )-		n = list_find( a, ( (newstr*) vp )->data );-	else-		return NULL;-	if ( n!=-1 )-		s = &( a->str[n] );-	else {-		s = list_addvp( a, mode, vp );-	}-	return s;-}-newstr *-list_addc_unique( list *a, const char *s )-{-	return list_addvp_unique( a, LIST_CHR, (void*)s );-}-newstr *-list_add_unique( list *a, newstr *s )-{-	return list_addvp_unique( a, LIST_STR, (void*)s );-}--int-list_addvp_all( list *a, unsigned char mode, ... )-{-	int ret = LIST_OK;-	va_list ap;-	newstr *s;-	void *v;-	va_start( ap, mode );-	do {-		if ( mode==LIST_CHR ) v = va_arg( ap, char * );-		else v = va_arg( ap, newstr * );-		if ( v ) {-			s = list_addvp( a, mode, v );-			if ( s==NULL ) { ret = LIST_ERR; goto out; }-		}-	} while ( v );-out:-	va_end( ap );-	return ret;-}--int-list_add_all( list *a, ... )-{-	int ret = LIST_OK;-	va_list ap;-	newstr *s, *v;-	va_start( ap, a );-	do {-		v = va_arg( ap, newstr * );-		if ( v ) {-			s = list_addvp( a, LIST_STR, (void*)v );-			if ( s==NULL ) { ret = LIST_ERR; goto out; }-		}-	} while ( v );-out:-	va_end( ap );-	return ret;-}--int-list_addc_all( list *a, ... )-{-	int ret = LIST_OK;-	va_list ap;-	newstr *s;-	const char *v;-	va_start( ap, a );-	do {-		v = va_arg( ap, const char * );-		if ( v ) {-			s = list_addvp( a, LIST_CHR, (void*)v );-			if ( s==NULL ) { ret = LIST_ERR; goto out; }-		}-	} while ( v );-out:-	va_end( ap );-	return ret;-}--int-list_append( list *a, list *toadd )-{-	newstr *s;-	int i;-	for ( i=0; i<toadd->n; ++i ) {-		s = list_add( a, &(toadd->str[i]) );-		if ( !s ) return LIST_ERR;-	}-	return LIST_OK;-}--int-list_append_unique( list *a, list *toadd )-{-	newstr *s;-	int i;-	for ( i=0; i<toadd->n; ++i ) {-		s = list_add_unique( a, &(toadd->str[i]) );-		if ( !s ) return LIST_ERR;-	}-	return LIST_OK;-}--int-list_remove( list *a, int n )-{-	int i;-	if ( !list_valid_num( a, n ) ) return -1;-	for ( i=n+1; i<a->n; ++i ) {-		newstr_newstrcpy( &(a->str[i-1]), &(a->str[i]) );-		if ( newstr_memerr( &(a->str[i-1]) ) ) return LIST_ERR;-	}-	a->n--;-	return LIST_OK;-}--void-list_swap( list *a, int n1, int n2 )-{-	newstr_swapstrings( &(a->str[n1]), &(a->str[n2]) );-}--void-list_sort( list *a )-{-	qsort( a->str, a->n, sizeof( newstr ), list_comp );-	a->sorted = 1;-}--static int-list_find_sorted( list *a, const char *searchstr )-{-	int min, max, mid, comp;-	newstr s, *cs;-	newstr_init( &s );-	newstr_strcpy( &s, searchstr );-	min = 0;-	max = a->n - 1;-	while ( min <= max ) {-		mid = ( min + max ) / 2;-		cs = list_get( a, mid );-		comp = list_comp( (void*)cs, (void*) (&s) );-		if ( comp==0 ) {-			newstr_free( &s );-			return mid;-		}-		else if ( comp > 0 ) max = mid - 1;-		else if ( comp < 0 ) min = mid + 1;-	}-	newstr_free( &s );-	return -1;-}--static int-list_find_simple( list *a, const char *searchstr, int nocase )-{-	int i;-	if ( nocase ) {-		for ( i=0; i<a->n; ++i )-			if ( !strcasecmp(a->str[i].data,searchstr) ) -				return i;-	} else {-		for ( i=0; i<a->n; ++i )-			if ( !strcmp(a->str[i].data,searchstr) )-				return i;-	}-	return -1;-}--int-list_find( list *a, const char *searchstr )-{-	if ( a->n==0 ) return -1;-	if ( a->sorted )-		return list_find_sorted( a, searchstr );-	else-		return list_find_simple( a, searchstr, 0 );-}--int-list_findnocase( list *a, const char *searchstr )-{-	return list_find_simple( a, searchstr, 1 );-}--int-list_fillfp( list *a, FILE *fp, unsigned char skip_blank_lines )-{-	int bufpos = 0, ret = LIST_OK;-	char buf[512]="";-	newstr line;--	list_empty( a );-	newstr_init( &line );-	while ( newstr_fget( fp, buf, sizeof(buf), &bufpos, &line ) ) {-		if ( skip_blank_lines && line.len==0 ) continue;-		if ( !list_add( a, &line ) ) { ret = LIST_ERR; goto out; }-	}-out:-	newstr_free( &line );-	return ret;-}--int-list_fill( list *a, const char *filename, unsigned char skip_blank_lines )-{-	FILE *fp;-	int ret;--	fp = fopen( filename, "r" );-	if ( !fp ) return LIST_ERR_CANNOTOPEN;--	ret = list_fillfp( a, fp, skip_blank_lines );--	fclose( fp );--	return ret;-}--int-list_copy( list *to, list *from )-{-	int i;--	list_free( to );--	if ( from->n==0 ) return LIST_OK;--	to->str = ( newstr * ) malloc( sizeof( newstr ) * from->n );-	if ( !to->str ) {-		to->n = to->max = 0;-		return LIST_ERR;-	}--	to->max = from->n;-	to->sorted = from->sorted;--	for ( i=0; i<from->n; i++ )-		newstr_init( &(to->str[i]) );--	for ( i=0; i<from->n; i++ ) {-		newstr_newstrcpy( &(to->str[i]), &(from->str[i]) );-		if ( newstr_memerr( &(to->str[i]) ) ) return LIST_ERR;-		to->n += 1;-	}-	return LIST_OK;-}--list *-list_dup( list *from )-{-	list *to;-	int ok;--	to = list_new();-	if ( to ) {-		ok = list_copy( to, from );-		if ( !ok ) {-			list_delete( to );-			to = NULL;-		}-	}--	return to;-}--int-list_match_entry( list *a, int n, char *s )-{-	if ( n < 0 || n >= a->n ) return 0;-	if ( strcmp( a->str[n].data, s ) ) return 0;-	return 1;-}--void-list_trimend( list *a, int n )-{-	int i;-	if ( a->n - n < 1 ) {-		list_empty( a );-	} else {-		for ( i=a->n -n; i<a->n; ++i ) {-			newstr_empty( &(a->str[i]) );-		}-		a->n -= n;-	}-}--int-list_tokenizec( list *tokens, char *p, const char *delim, int merge_delim )-{-	int ret = LIST_OK;-	newstr s, *t;-	char *q;-	list_empty( tokens );-	newstr_init( &s );-	while ( p && *p ) {-		q = p;-		while ( *q && !strchr( delim, *q ) ) q++;-		newstr_segcpy( &s, p, q );-		if ( newstr_memerr( &s ) ) { ret = LIST_ERR; goto out; }-		if ( s.len ) {-			t = list_addvp( tokens, LIST_STR, (void*) &s );-			if ( !t ) { ret = LIST_ERR; goto out; }-		} else if ( !merge_delim ) {-			t = list_addvp( tokens, LIST_CHR, (void*) "" );-			if ( !t ) { ret = LIST_ERR; goto out; }-		}-		p = q;-		if ( *p ) p++;-	}-out:-	newstr_free( &s );-	return ret;-}--int-list_tokenize( list *tokens, newstr *in, const char *delim, int merge_delim )-{-	return list_tokenizec( tokens, in->data, delim, merge_delim );-}--void-lists_init( list *a, ... )-{-	list *a2;-	va_list ap;-	list_init( a );-	va_start( ap, a );-	do {-		a2 = va_arg( ap, list * );-		if ( a2 ) list_init( a2 );-	} while ( a2 );-	va_end( ap );-}--void-lists_free( list *a, ... )-{-	list *a2;-	va_list ap;-	list_free( a );-	va_start( ap, a );-	do {-		a2 = va_arg( ap, list * );-		if ( a2 ) list_free( a2 );-	} while ( a2 );-	va_end( ap );-}--void-lists_empty( list *a, ... )-{-	list *a2;-	va_list ap;-	list_empty( a );-	va_start( ap, a );-	do {-		a2 = va_arg( ap, list * );-		if ( a2 ) list_empty( a2 );-	} while ( a2 );-	va_end( ap );-}-
− bibutils/list.h
@@ -1,87 +0,0 @@-/*- * list.h- *- * version: 2014-11-15- *- * Copyright (c) Chris Putnam 2004-2014- *- * Source code released under the GPL version 2- *- */--#ifndef LISTS_H-#define LISTS_H--#include <stdio.h>-#include <stdlib.h>-#include <stdarg.h>-#include <string.h>-#include "newstr.h"--#define LIST_ERR (0)-#define LIST_ERR_CANNOTOPEN (-1)-#define LIST_OK  (1)--#define LIST_CHR (0)-#define LIST_STR (1)--typedef struct list {-	int n, max;-	newstr *str;-	unsigned char sorted;-} list;---extern void    lists_init( list *a, ... );-extern void    lists_free( list *a, ... );-extern void    lists_empty( list *a, ... );---extern void    list_init( list *a );-extern void    list_free( list *a );-extern void    list_empty( list *a );--extern list *  list_new( void );-extern void    list_delete( list * );--extern list*   list_dup( list *a );-extern int     list_copy( list *to, list *from );--extern newstr * list_addvp( list *a, unsigned char mode, void *vp );-extern newstr * list_addc( list *a, const char *value );-extern newstr * list_add( list *a, newstr *value );--extern int      list_addvp_all( list *a, unsigned char mode, ... );-extern int      list_addc_all( list *a, ... );-extern int      list_add_all( list *a, ... );--extern newstr * list_addvp_unique( list *a, unsigned char mode, void *vp );-extern newstr * list_addc_unique( list *a, const char *value );-extern newstr * list_add_unique( list *a, newstr *value );--extern int     list_append( list *a, list *toadd );-extern int     list_append_unique( list *a, list *toadd );--extern int     list_remove( list *a, int n );--extern newstr* list_get( list *a, int n );-extern char*   list_getc( list *a, int n );--extern newstr* list_set( list *a, int n, newstr *s );-extern newstr* list_setc( list *a, int n, const char *s );--extern void    list_sort( list *a );--extern void    list_swap( list *a, int n1, int n2 );--extern int     list_find( list *a, const char *searchstr );-extern int     list_findnocase( list *a, const char *searchstr );-extern int     list_match_entry( list *a, int n, char *s );-extern void    list_trimend( list *a, int n );--extern int     list_fill( list *a, const char *filename, unsigned char skip_blank_lines );-extern int     list_fillfp( list *a, FILE *fp, unsigned char skip_blank_lines );-extern int     list_tokenize( list *tokens, newstr *in, const char *delim, int merge_delim );-extern int     list_tokenizec( list *tokens, char *p, const char *delim, int merge_delim );--#endif
bibutils/marc.c view
@@ -1,7 +1,7 @@ /*  * marc.c  *- * Copyright (c) Chris Putnam 2004-2014+ * Copyright (c) Chris Putnam 2004-2017  *  * Source code released under the GPL version 2  *
bibutils/marc.h view
@@ -1,7 +1,7 @@ /*  * marc.h  *- * Copyright (c) Chris Putnam 2008-2013+ * Copyright (c) Chris Putnam 2008-2017  *  * Source code released under the GPL version 2  *
bibutils/medin.c view
@@ -1,7 +1,7 @@ /*  * medin.c  *- * Copyright (c) Chris Putnam 2004-2014+ * Copyright (c) Chris Putnam 2004-2017  *  * Source code released under the GPL version 2  *@@ -9,15 +9,19 @@ #include <stdio.h> #include <stdlib.h> #include "is_ws.h"-#include "newstr.h"-#include "newstr_conv.h"+#include "str.h"+#include "str_conv.h" #include "fields.h" #include "xml.h" #include "xml_encoding.h"-#include "medin.h" #include "iso639_2.h" #include "bibutils.h"+#include "bibformats.h" +static int medin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset );+static int medin_processf( fields *medin, char *data, char *filename, long nref, param *p );++ /*****************************************************  PUBLIC: void medin_initparams() *****************************************************/@@ -44,8 +48,8 @@ 	p->all      = NULL; 	p->nall     = 0; -	list_init( &(p->asis) );-	list_init( &(p->corps) );+	slist_init( &(p->asis) );+	slist_init( &(p->corps) );  	if ( !progname ) p->progname = NULL; 	else p->progname = strdup( progname );@@ -82,14 +86,14 @@ 	return endptr; } -int-medin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset )+static int+medin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset ) {-	newstr tmp;+	str tmp; 	char *startptr = NULL, *endptr; 	int haveref = 0, inref = 0, file_charset = CHARSET_UNKNOWN, m, type = -1;-	newstr_init( &tmp );-	while ( !haveref && newstr_fget( fp, buf, bufsize, bufpos, line ) ) {+	str_init( &tmp );+	while ( !haveref && str_fget( fp, buf, bufsize, bufpos, line ) ) { 		if ( line->data ) { 			m = xml_getencoding( line ); 			if ( m!=CHARSET_UNKNOWN ) file_charset = m;@@ -98,19 +102,19 @@ 			startptr = medin_findstartwrapper( line->data, &type ); 		} 		if ( startptr || inref ) {-			if ( inref ) newstr_strcat( &tmp, line->data );+			if ( inref ) str_strcat( &tmp, line ); 			else {-				newstr_strcat( &tmp, startptr );+				str_strcatc( &tmp, startptr ); 				inref = 1; 			}-			endptr = medin_findendwrapper( tmp.data, type );+			endptr = medin_findendwrapper( str_cstr( &tmp ), type ); 			if ( endptr ) {-				newstr_segcpy( reference, tmp.data, endptr );+				str_segcpy( reference, str_cstr( &tmp ), endptr ); 				haveref = 1; 			} 		} 	}-	newstr_free( &tmp );+	str_free( &tmp ); 	*fcharset = file_charset; 	return haveref; }@@ -132,8 +136,8 @@ 	int i, fstatus; 	char *d; 	*found = 0;-	if ( !xml_hasdata( node ) ) return BIBL_OK;-	d = xml_data( node );+	if ( !xml_hasvalue( node ) ) return BIBL_OK;+	d = xml_value( node ); 	for ( i=0; i<nc && *found==0; ++i ) { 		if ( c[i].a==NULL ) { 			if ( xml_tagexact( node, c[i].in ) ) {@@ -159,8 +163,8 @@ medin_articletitle( xml *node, fields *info ) { 	int fstatus, status = BIBL_OK;-	if ( xml_hasdata( node ) ) {-		fstatus = fields_add( info, "TITLE", xml_data( node ), 0 );+	if ( xml_hasvalue( node ) ) {+		fstatus = fields_add( info, "TITLE", xml_value( node ), 0 ); 		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR; 	} 	return status;@@ -171,33 +175,36 @@ medin_medlinedate( fields *info, char *p, int level ) { 	int fstatus;-	newstr tmp;+	str tmp; -	newstr_init( &tmp );+	str_init( &tmp ); -	p = newstr_cpytodelim( &tmp, skip_ws( p ), " \t\n\r", 0 );-	if ( newstr_memerr( &tmp ) ) return BIBL_ERR_MEMERR;-	if ( tmp.len > 0 ) {-		fstatus = fields_add( info, "PARTYEAR", tmp.data, level );+	p = str_cpytodelim( &tmp, skip_ws( p ), " \t\n\r", 0 );+	if ( str_memerr( &tmp ) ) return BIBL_ERR_MEMERR;++	if ( str_has_value( &tmp ) ) {+		fstatus = fields_add( info, "PARTDATE:YEAR", str_cstr( &tmp ), level ); 		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	} -	p = newstr_cpytodelim( &tmp, skip_ws( p ), " \t\n\r", 0 );-	if ( newstr_memerr( &tmp ) ) return BIBL_ERR_MEMERR;-	if ( tmp.len > 0 ) {-		newstr_findreplace( &tmp, "-", "/" );-		fstatus = fields_add( info, "PARTMONTH", tmp.data, level );+	p = str_cpytodelim( &tmp, skip_ws( p ), " \t\n\r", 0 );+	if ( str_memerr( &tmp ) ) return BIBL_ERR_MEMERR;++	if ( str_has_value( &tmp ) ) {+		str_findreplace( &tmp, "-", "/" );+		fstatus = fields_add( info, "PARTDATE:MONTH", str_cstr( &tmp ), level ); 		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	} -	p = newstr_cpytodelim( &tmp, skip_ws( p ), " \t\n\r", 0 );-	if ( newstr_memerr( &tmp ) ) return BIBL_ERR_MEMERR;-	if ( tmp.len > 0 ) {-		fstatus = fields_add( info, "PARTDAY", tmp.data, level );+	p = str_cpytodelim( &tmp, skip_ws( p ), " \t\n\r", 0 );+	if ( str_memerr( &tmp ) ) return BIBL_ERR_MEMERR;++	if ( str_has_value( &tmp ) ) {+		fstatus = fields_add( info, "PARTDATE:DAY", str_cstr( &tmp ), level ); 		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	} -	newstr_free( &tmp );+	str_free( &tmp );  	return BIBL_OK; }@@ -209,7 +216,7 @@ { 	char *code, *language; 	int fstatus;-	code = xml_data( node );+	code = xml_value( node ); 	if ( !code ) return BIBL_OK; 	language = iso639_2_from_code( code ); 	if ( language )@@ -252,22 +259,22 @@ medin_journal1( xml *node, fields *info ) { 	xml_convert c[] = {-		{ "Title",           NULL, NULL, "TITLE",      1 },-		{ "ISOAbbreviation", NULL, NULL, "SHORTTITLE", 1 },-		{ "ISSN",            NULL, NULL, "ISSN",       1 },-		{ "Volume",          NULL, NULL, "VOLUME",     1 },-		{ "Issue",           NULL, NULL, "ISSUE",      1 },-		{ "Year",            NULL, NULL, "PARTYEAR",   1 },-		{ "Month",           NULL, NULL, "PARTMONTH",  1 },-		{ "Day",             NULL, NULL, "PARTDAY",    1 },+		{ "Title",           NULL, NULL, "TITLE",          1 },+		{ "ISOAbbreviation", NULL, NULL, "SHORTTITLE",     1 },+		{ "ISSN",            NULL, NULL, "ISSN",           1 },+		{ "Volume",          NULL, NULL, "VOLUME",         1 },+		{ "Issue",           NULL, NULL, "ISSUE",          1 },+		{ "Year",            NULL, NULL, "PARTDATE:YEAR",  1 },+		{ "Month",           NULL, NULL, "PARTDATE:MONTH", 1 },+		{ "Day",             NULL, NULL, "PARTDATE:DAY",   1 }, 	}; 	int nc = sizeof( c ) / sizeof( c[0] ), status, found;-	if ( xml_hasdata( node ) ) {+	if ( xml_hasvalue( node ) ) { 		status = medin_doconvert( node, info, c, nc, &found ); 		if ( status!=BIBL_OK ) return status; 		if ( !found ) { 			if ( xml_tagexact( node, "MedlineDate" ) ) {-				status = medin_medlinedate( info, xml_data( node ), 1 );+				status = medin_medlinedate( info, xml_value( node ), 1 ); 				if ( status!=BIBL_OK ) return status; 			} 			if ( xml_tagexact( node, "Language" ) ) {@@ -295,28 +302,28 @@ medin_pagination( xml *node, fields *info ) { 	int i, fstatus, status;-	newstr sp, ep;+	str sp, ep; 	char *p, *pp; 	if ( xml_tagexact( node, "MedlinePgn" ) && node->value ) {-		newstrs_init( &sp, &ep, NULL );-		p = newstr_cpytodelim( &sp, xml_data( node ), "-", 1 );-		if ( newstr_memerr( &sp ) ) return BIBL_ERR_MEMERR;-		if ( sp.len ) {-			fstatus = fields_add( info, "PAGESTART", sp.data, 1 );+		strs_init( &sp, &ep, NULL );+		p = str_cpytodelim( &sp, xml_value( node ), "-", 1 );+		if ( str_memerr( &sp ) ) return BIBL_ERR_MEMERR;+		if ( str_has_value( &sp ) ) {+			fstatus = fields_add( info, "PAGES:START", str_cstr( &sp ), 1 ); 			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; 		}-		p = newstr_cpytodelim( &ep, p, "", 0 );-		if ( newstr_memerr( &ep ) ) return BIBL_ERR_MEMERR;-		if ( ep.len ) {+		p = str_cpytodelim( &ep, p, "", 0 );+		if ( str_memerr( &ep ) ) return BIBL_ERR_MEMERR;+		if ( str_has_value( &ep ) ) { 			if ( sp.len > ep.len ) { 				for ( i=sp.len-ep.len; i<sp.len; ++i ) 					sp.data[i] = ep.data[i-sp.len+ep.len]; 				pp = sp.data; 			} else  pp = ep.data;-			fstatus = fields_add( info, "PAGEEND", pp, 1 );+			fstatus = fields_add( info, "PAGES:STOP", pp, 1 ); 			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; 		}-		newstrs_free( &sp, &ep, NULL );+		strs_free( &sp, &ep, NULL ); 	} 	if ( node->down ) { 		status = medin_pagination( node->down, info );@@ -337,8 +344,8 @@ medin_abstract( xml *node, fields *info ) { 	int fstatus;-	if ( xml_tagwithdata( node, "AbstractText" ) ) {-		fstatus = fields_add( info, "ABSTRACT", xml_data( node ), 0 );+	if ( xml_tagwithvalue( node, "AbstractText" ) ) {+		fstatus = fields_add( info, "ABSTRACT", xml_value( node ), 0 ); 		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	} else if ( node->next ) return medin_abstract( node->next, info ); 	return BIBL_OK;@@ -357,28 +364,28 @@  * </AuthorList>  */ static int-medin_author( xml *node, newstr *name )+medin_author( xml *node, str *name ) { 	char *p; 	if ( xml_tagexact( node, "LastName" ) ) {-		if ( name->len ) {-			newstr_prepend( name, "|" );-			newstr_prepend( name, xml_data( node ) );+		if ( str_has_value( name ) ) {+			str_prepend( name, "|" );+			str_prepend( name, xml_value( node ) ); 		}-		else newstr_strcat( name, xml_data( node ) );+		else str_strcatc( name, xml_value( node ) ); 	} else if ( xml_tagexact( node, "ForeName" ) ||  	            xml_tagexact( node, "FirstName" ) ) {-		p = xml_data( node );+		p = xml_value( node ); 		while ( p && *p ) {-			if ( name->len ) newstr_addchar( name, '|' );+			if ( str_has_value( name ) ) str_addchar( name, '|' ); 			while ( *p && *p==' ' ) p++;-			while ( *p && *p!=' ' ) newstr_addchar( name, *p++ );+			while ( *p && *p!=' ' ) str_addchar( name, *p++ ); 		} 	} else if ( xml_tagexact( node, "Initials" ) && !strchr( name->data, '|' )) {-		p = xml_data( node );+		p = xml_value( node ); 		while ( p && *p ) {-			if ( name->len ) newstr_addchar( name, '|' );-			if ( !is_ws(*p) ) newstr_addchar( name, *p++ );+			if ( str_has_value( name ) ) str_addchar( name, '|' );+			if ( !is_ws(*p) ) str_addchar( name, *p++ ); 		} 	} 	if ( node->next ) medin_author( node->next, name );@@ -386,10 +393,10 @@ }  static int-medin_corpauthor( xml *node, newstr *name )+medin_corpauthor( xml *node, str *name ) { 	if ( xml_tagexact( node, "CollectiveName" ) ) {-		newstr_strcpy( name, xml_data( node ) );+		str_strcpyc( name, xml_value( node ) ); 	} else if ( node->next ) medin_corpauthor( node->next, name ); 	return BIBL_OK; }@@ -398,28 +405,28 @@ medin_authorlist( xml *node, fields *info ) { 	int fstatus, status;-	newstr name;+	str name; 	char *tag;-	newstr_init( &name );+	str_init( &name ); 	node = node->down; 	while ( node ) { 		if ( xml_tagexact( node, "Author" ) && node->down ) { 			status = medin_author( node->down, &name ); 			tag = "AUTHOR";-			if ( !name.len ) {+			if ( str_is_empty( &name ) ) { 				status = medin_corpauthor( node->down, &name ); 				tag = "AUTHOR:CORP"; 			}-			if ( newstr_memerr( &name ) || status!=BIBL_OK ) return BIBL_ERR_MEMERR;-			if ( name.len ) {+			if ( str_memerr( &name ) || status!=BIBL_OK ) return BIBL_ERR_MEMERR;+			if ( str_has_value( &name ) ) { 				fstatus = fields_add(info,tag,name.data,0); 				if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; 			}-			newstr_empty( &name );+			str_empty( &name ); 		} 		node = node->next; 	}-	newstr_free( &name );+	str_free( &name ); 	return BIBL_OK; } @@ -439,8 +446,8 @@ medin_journal2( xml *node, fields *info ) { 	int fstatus, status = BIBL_OK;-	if ( xml_tagwithdata( node, "MedlineTA" ) && fields_find( info, "TITLE", 1 )==-1 ) {-		fstatus = fields_add( info, "TITLE", xml_data( node ), 1 );+	if ( xml_tagwithvalue( node, "MedlineTA" ) && fields_find( info, "TITLE", 1 )==-1 ) {+		fstatus = fields_add( info, "TITLE", xml_value( node ), 1 ); 		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	} 	if ( node->down ) {@@ -465,8 +472,8 @@ medin_meshheading( xml *node, fields *info ) { 	int fstatus, status = BIBL_OK;-	if ( xml_tagwithdata( node, "DescriptorName" ) ) {-		fstatus = fields_add( info, "KEYWORD", xml_data( node ), 0 );+	if ( xml_tagwithvalue( node, "DescriptorName" ) ) {+		fstatus = fields_add( info, "KEYWORD", xml_value( node ), 0 ); 		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	} 	if ( node->next ) status = medin_meshheading( node->next, info );@@ -491,7 +498,7 @@  *         <ArticleId IdType="pubmed">14523232</ArticleId>  *         <ArticleId IdType="doi">10.1073/pnas.2133463100</ArticleId>  *         <ArticleId IdType="pii">2133463100</ArticleId>- *         <ArticleId IdType="medline">22922082</ArticleId>+ *         <ArticleId IdType="pmc">PMC4833866</ArticleId>  *     </ArticleIdList>  * </PubmedData>  *@@ -504,6 +511,7 @@ 		{ "ArticleId", "IdType", "doi",     "DOI",     0 }, 		{ "ArticleId", "IdType", "pubmed",  "PMID",    0 }, 		{ "ArticleId", "IdType", "medline", "MEDLINE", 0 },+		{ "ArticleId", "IdType", "pmc",     "PMC",     0 }, 		{ "ArticleId", "IdType", "pii",     "PII",     0 }, 	}; 	int nc = sizeof( c ) / sizeof( c[0] ), found, status;@@ -537,12 +545,12 @@ 	else if ( xml_tagexact( node, "Language" ) ) 		status = medin_language( node, info, 0 ); 	else if ( xml_tagexact( node, "Affiliation" ) ) {-		fstatus = fields_add( info, "ADDRESS", xml_data( node ), 0 );+		fstatus = fields_add( info, "ADDRESS", xml_value( node ), 0 ); 		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR; 	} 	if ( status!=BIBL_OK ) return status; 	if ( node->next ) status = medin_article( node->next, info );-	return BIBL_OK;+	return status; }  static int@@ -616,8 +624,8 @@ 	return status; } -int-medin_processf( fields *medin, char *data, char *filename, long nref )+static int+medin_processf( fields *medin, char *data, char *filename, long nref, param *p ) { 	int status; 	xml top;
− bibutils/medin.h
@@ -1,26 +0,0 @@-/*- * medin.h- *- * Copyright (c) Chris Putnam 2004-2014- *- * Source code released under the GPL version 2- *- */-#ifndef MEDIN_H-#define MEDIN_H--#include "newstr.h"-#include "fields.h"-#include "reftypes.h"-#include "bibutils.h"--extern int medin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );-extern int medin_processf( fields *medin, char *data, char *filename, long nref );--extern void medin_initparams( param *p, const char *progname );--extern variants med_all[];-extern int med_nall;--#endif-
bibutils/modsin.c view
@@ -1,7 +1,7 @@ /*  * modsin.c  *- * Copyright (c) Chris Putnam 2004-2014+ * Copyright (c) Chris Putnam 2004-2017  *  * Source code released under the GPL version 2  *@@ -11,8 +11,8 @@ #include <string.h> #include <ctype.h> #include "is_ws.h"-#include "newstr.h"-#include "newstr_conv.h"+#include "str.h"+#include "str_conv.h" #include "xml.h" #include "xml_encoding.h" #include "fields.h"@@ -20,12 +20,16 @@ #include "reftypes.h" #include "modstypes.h" #include "marc.h"+#include "url.h" #include "iso639_1.h" #include "iso639_2.h" #include "iso639_3.h" #include "bibutils.h"-#include "modsin.h"+#include "bibformats.h" +static int modsin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset );+static int modsin_processf( fields *medin, char *data, char *filename, long nref, param *p );+ /*****************************************************  PUBLIC: void modsin_initparams() *****************************************************/@@ -55,8 +59,8 @@ 	p->all      = NULL; 	p->nall     = 0; -	list_init( &(p->asis) );-	list_init( &(p->corps) );+	slist_init( &(p->asis) );+	slist_init( &(p->corps) );  	if ( !progname ) p->progname = NULL; 	else p->progname = strdup( progname );@@ -69,13 +73,13 @@ static char modsns[]="mods";  static int-modsin_detailr( xml *node, newstr *value )+modsin_detailr( xml *node, str *value ) { 	int status = BIBL_OK; 	if ( node->value && node->value->len ) {-		if ( value->len ) newstr_addchar( value, ' ' );-		newstr_newstrcat( value, node->value );-		if ( newstr_memerr( value ) ) return BIBL_ERR_MEMERR;+		if ( value->len ) str_addchar( value, ' ' );+		str_strcat( value, node->value );+		if ( str_memerr( value ) ) return BIBL_ERR_MEMERR; 	} 	if ( node->down ) { 		status = modsin_detailr( node->down, value );@@ -89,26 +93,26 @@ static int modsin_detail( xml *node, fields *info, int level ) {-	newstr type, value, *tp;+	str type, value, *tp; 	int fstatus, status = BIBL_OK; 	if ( node->down ) {-		newstrs_init( &type, &value, NULL );+		strs_init( &type, &value, NULL ); 		tp = xml_getattrib( node, "type" ); 		if ( tp ) {-			newstr_newstrcpy( &type, tp );-			newstr_toupper( &type );-			if ( newstr_memerr( &type ) ) goto out;+			str_strcpy( &type, tp );+			str_toupper( &type );+			if ( str_memerr( &type ) ) goto out; 		} 		status = modsin_detailr( node->down, &value ); 		if ( status!=BIBL_OK ) goto out; 		if ( type.data && !strcasecmp( type.data, "PAGE" ) ) {-			fstatus = fields_add( info, "PAGESTART", value.data, level );+			fstatus = fields_add( info, "PAGES:START", value.data, level ); 		} else { 			fstatus = fields_add( info, type.data, value.data, level ); 		} 		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR; out:-		newstrs_free( &type, &value, NULL );+		strs_free( &type, &value, NULL ); 	} 	return status; }@@ -118,56 +122,56 @@ { 	int fstatus, status = BIBL_OK; 	char *tag, *p = NULL;-	newstr s;+	str s; 	if ( node->value ) p = node->value->data; 	if ( p ) {-		newstr_init( &s );+		str_init( &s ); -		p = newstr_cpytodelim( &s, skip_ws( p ), "-", 1 );-		if ( newstr_memerr( &s ) ) { status = BIBL_ERR_MEMERR; goto out; }-		if ( s.len ) {-			tag = ( part ) ? "PARTYEAR" : "YEAR";-			fstatus =  fields_add( info, tag, s.data, level );+		p = str_cpytodelim( &s, skip_ws( p ), "-", 1 );+		if ( str_memerr( &s ) ) { status = BIBL_ERR_MEMERR; goto out; }+		if ( str_has_value( &s ) ) {+			tag = ( part ) ? "PARTDATE:YEAR" : "DATE:YEAR";+			fstatus =  fields_add( info, tag, str_cstr( &s ), level ); 			if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; } 		} -		p = newstr_cpytodelim( &s, skip_ws( p ), "-", 1 );-		if ( newstr_memerr( &s ) ) { status = BIBL_ERR_MEMERR; goto out; }-		if ( s.len ) {-			tag = ( part ) ? "PARTMONTH" : "MONTH";-			fstatus =  fields_add( info, tag, s.data, level );+		p = str_cpytodelim( &s, skip_ws( p ), "-", 1 );+		if ( str_memerr( &s ) ) { status = BIBL_ERR_MEMERR; goto out; }+		if ( str_has_value( &s ) ) {+			tag = ( part ) ? "PARTDATE:MONTH" : "DATE:MONTH";+			fstatus =  fields_add( info, tag, str_cstr( &s ), level ); 			if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; } 		} -		p = newstr_cpytodelim( &s, skip_ws( p ), "", 0 );-		if ( newstr_memerr( &s ) ) { status = BIBL_ERR_MEMERR; goto out; }-		if ( s.len ) {-			tag = ( part ) ? "PARTDAY" : "DAY";-			fstatus =  fields_add( info, tag, s.data, level );+		p = str_cpytodelim( &s, skip_ws( p ), "", 0 );+		if ( str_memerr( &s ) ) { status = BIBL_ERR_MEMERR; goto out; }+		if ( str_has_value( &s ) ) {+			tag = ( part ) ? "PARTDATE:DAY" : "DATE:DAY";+			fstatus =  fields_add( info, tag, str_cstr( &s ), level ); 			if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; } 		} out:-		newstr_free( &s );+		str_free( &s ); 	} 	return status; }  static int-modsin_pager( xml *node, newstr *sp, newstr *ep, newstr *tp, newstr *lp )+modsin_pager( xml *node, str *sp, str *ep, str *tp, str *lp ) { 	int status = BIBL_OK; 	if ( xml_tagexact( node, "start" ) ) {-		newstr_newstrcpy( sp, node->value );-		if ( newstr_memerr( sp ) ) return BIBL_ERR_MEMERR;+		str_strcpy( sp, node->value );+		if ( str_memerr( sp ) ) return BIBL_ERR_MEMERR; 	} else if ( xml_tagexact( node, "end" ) ) {-		newstr_newstrcpy( ep, node->value );-		if ( newstr_memerr( ep ) ) return BIBL_ERR_MEMERR;+		str_strcpy( ep, node->value );+		if ( str_memerr( ep ) ) return BIBL_ERR_MEMERR; 	} else if ( xml_tagexact( node, "total" ) ) {-		newstr_newstrcpy( tp, node->value );-		if ( newstr_memerr( tp ) ) return BIBL_ERR_MEMERR;+		str_strcpy( tp, node->value );+		if ( str_memerr( tp ) ) return BIBL_ERR_MEMERR; 	} else if ( xml_tagexact( node, "list" ) ) {-		newstr_newstrcpy( lp, node->value );-		if ( newstr_memerr( lp ) ) return BIBL_ERR_MEMERR;+		str_strcpy( lp, node->value );+		if ( str_memerr( lp ) ) return BIBL_ERR_MEMERR; 	} 	if ( node->down ) { 		status = modsin_pager( node->down, sp, ep, tp, lp );@@ -182,53 +186,49 @@ modsin_page( xml *node, fields *info, int level ) { 	int fstatus, status = BIBL_OK;-	newstr sp, ep, tp, lp;+	str sp, ep, tp, lp; 	xml *dnode = node->down;  	if ( !dnode ) return BIBL_OK; -	newstrs_init( &sp, &ep, &tp, &lp, NULL );+	strs_init( &sp, &ep, &tp, &lp, NULL );  	status = modsin_pager( dnode, &sp, &ep, &tp, &lp ); 	if ( status!=BIBL_OK ) goto out; -	if ( sp.len || ep.len ) {-		if ( sp.len ) {-			fstatus = fields_add( info, "PAGESTART", sp.data, level );+	if ( str_has_value( &sp ) || str_has_value( &ep ) ) {+		if ( str_has_value( &sp ) ) {+			fstatus = fields_add( info, "PAGES:START", str_cstr( &sp ), level ); 			if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; } 		}-		if ( ep.len ) {-			fstatus = fields_add( info, "PAGEEND", ep.data, level );+		if ( str_has_value( &ep ) ) {+			fstatus = fields_add( info, "PAGES:STOP", str_cstr( &ep ), level ); 			if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; } 		}-	} else if ( lp.len ) {-		fstatus = fields_add( info, "PAGESTART", lp.data, level );+	} else if ( str_has_value( &lp ) ) {+		fstatus = fields_add( info, "PAGES:START", str_cstr( &lp ), level ); 		if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; } 	}-	if ( tp.len ) {-		fstatus = fields_add( info, "TOTALPAGES", tp.data, level );+	if ( str_has_value( &tp ) ) {+		fstatus = fields_add( info, "PAGES:TOTAL", str_cstr( &tp ), level ); 		if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; } 	} out:-	newstrs_free( &sp, &ep, &tp, &lp, NULL );-	return BIBL_OK;+	strs_free( &sp, &ep, &tp, &lp, NULL );+	return status; }  static int-modsin_titler( xml *node, newstr *title, newstr *subtitle )+modsin_titler( xml *node, str *title, str *subtitle ) { 	int status = BIBL_OK; 	if ( xml_tagexact( node, "title" ) ) {-		if ( title->len ) {-			newstr_strcat( title, " : " );-			newstr_newstrcat( title, node->value );-		} else {-			newstr_newstrcat( title, node->value );-		}-		if ( newstr_memerr( title ) ) return BIBL_ERR_MEMERR;+		if ( str_has_value( title ) ) str_strcatc( title, " : " );+		str_strcat( title, node->value );+		if ( str_memerr( title ) ) return BIBL_ERR_MEMERR; 	} else if ( xml_tagexact( node, "subTitle" ) ) {-		newstr_newstrcat( subtitle, node->value );-		if ( newstr_memerr( subtitle ) ) return BIBL_ERR_MEMERR;+		str_strcat( subtitle, node->value );+		if ( str_memerr( subtitle ) ) return BIBL_ERR_MEMERR; 	} 	if ( node->down ) { 		status = modsin_titler( node->down, title, subtitle );@@ -247,31 +247,31 @@ 		{ "SUBTITLE", "SHORTSUBTITLE" }, 	}; 	int fstatus, status = BIBL_OK;-	newstr title, subtitle;-	xml *dnode = node->down;+	str title, subtitle;+	xml *dnode; 	int abbr;  	dnode = node->down; 	if ( !dnode ) return status; -	newstrs_init( &title, &subtitle, NULL );+	strs_init( &title, &subtitle, NULL ); 	abbr = xml_tag_attrib( node, "titleInfo", "type", "abbreviated" );  	status = modsin_titler( dnode, &title, &subtitle ); 	if ( status!=BIBL_OK ) goto out; -	if ( title.len ) {-		fstatus = fields_add( info, titletag[0][abbr], title.data, level );+	if ( str_has_value( &title ) ) {+		fstatus = fields_add( info, titletag[0][abbr], str_cstr( &title ), level ); 		if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; } 	} -	if ( subtitle.len ) {-		fstatus = fields_add( info, titletag[1][abbr], subtitle.data, level );+	if ( str_has_value( &subtitle ) ) {+		fstatus = fields_add( info, titletag[1][abbr], str_cstr( &subtitle ), level ); 		if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; } 	}  out:-	newstrs_free( &title, &subtitle, NULL );+	strs_free( &title, &subtitle, NULL ); 	return status; } @@ -284,24 +284,24 @@  * "author" or "author|creator" or "edt" or "editor|edt".  */ static int-modsin_marcrole_convert( newstr *s, char *suffix, newstr *out )+modsin_marcrole_convert( str *s, char *suffix, str *out ) { 	convert roles[] = {-		{ "author",              "AUTHOR" },-		{ "aut",                 "AUTHOR" },-		{ "aud",                 "AUTHOR" },-		{ "aui",                 "AUTHOR" },-		{ "aus",                 "AUTHOR" },-		{ "creator",             "AUTHOR" },-		{ "cre",                 "AUTHOR" },-		{ "editor",              "EDITOR" },-		{ "edt",                 "EDITOR" },-		{ "degree grantor",      "DEGREEGRANTOR" },-		{ "dgg",                 "DEGREEGRANTOR" },-		{ "organizer of meeting","ORGANIZER" },-		{ "orm",                 "ORGANIZER" },-		{ "patent holder",       "ASSIGNEE" },-		{ "pth",                 "ASSIGNEE" }+		{ "author",              "AUTHOR",        0, 0 },+		{ "aut",                 "AUTHOR",        0, 0 },+		{ "aud",                 "AUTHOR",        0, 0 },+		{ "aui",                 "AUTHOR",        0, 0 },+		{ "aus",                 "AUTHOR",        0, 0 },+		{ "creator",             "AUTHOR",        0, 0 },+		{ "cre",                 "AUTHOR",        0, 0 },+		{ "editor",              "EDITOR",        0, 0 },+		{ "edt",                 "EDITOR",        0, 0 },+		{ "degree grantor",      "DEGREEGRANTOR", 0, 0 },+		{ "dgg",                 "DEGREEGRANTOR", 0, 0 },+		{ "organizer of meeting","ORGANIZER",     0, 0 },+		{ "orm",                 "ORGANIZER",     0, 0 },+		{ "patent holder",       "ASSIGNEE",      0, 0 },+		{ "pth",                 "ASSIGNEE",      0, 0 } 	}; 	int nroles = sizeof( roles ) / sizeof( roles[0] ); 	int i, nmismatch, n = -1, status = BIBL_OK;@@ -330,26 +330,26 @@ 	}  	if ( n!=-1 ) {-		newstr_strcpy( out, roles[n].internal );-		if ( suffix ) newstr_strcat( out, suffix );+		str_strcpyc( out, roles[n].internal );+		if ( suffix ) str_strcatc( out, suffix ); 	} else {-		newstr_strcpy( out, s->data );+		str_strcpy( out, s ); 	}-	if ( newstr_memerr( out ) ) status = BIBL_ERR_MEMERR;+	if ( str_memerr( out ) ) status = BIBL_ERR_MEMERR; 	return status; }  static int-modsin_asis_corp_r( xml *node, newstr *name, newstr *role )+modsin_asis_corp_r( xml *node, str *name, str *role ) { 	int status = BIBL_OK; 	if ( xml_tagexact( node, "namePart" ) ) {-		newstr_newstrcpy( name, node->value );-		if ( newstr_memerr( name ) ) return BIBL_ERR_MEMERR;+		str_strcpy( name, node->value );+		if ( str_memerr( name ) ) return BIBL_ERR_MEMERR; 	} else if ( xml_tagexact( node, "roleTerm" ) ) {-		if ( role->len ) newstr_addchar( role, '|' );-		newstr_newstrcat( role, node->value );-		if ( newstr_memerr( role ) ) return BIBL_ERR_MEMERR;+		if ( role->len ) str_addchar( role, '|' );+		str_strcat( role, node->value );+		if ( str_memerr( role ) ) return BIBL_ERR_MEMERR; 	} 	if ( node->down ) { 		status = modsin_asis_corp_r( node->down, name, role );@@ -361,84 +361,141 @@ }  static int-modsin_personr( xml *node, newstr *name, newstr *suffix, newstr *roles )-{-	newstr outname;-	int status = BIBL_OK;-	newstr_init( &outname );-	if ( xml_tagexact( node, "namePart" ) ) {-		if ( xml_tag_attrib( node, "namePart", "type", "family" ) ) {-			if ( name->len ) newstr_prepend( name, "|" );-			newstr_prepend( name, node->value->data );-		} else if (xml_tag_attrib( node, "namePart", "type", "suffix") ||-		           xml_tag_attrib( node, "namePart", "type", "termsOfAddress" )) {-			if ( suffix->len ) newstr_addchar( suffix, ' ' );-			newstr_strcat( suffix, node->value->data );-		} else if (xml_tag_attrib( node, "namePart", "type", "date")){-		} else {-			if ( name->len ) newstr_addchar( name, '|' );-			name_parse( &outname, node->value, NULL, NULL );-			newstr_newstrcat( name, &outname );-		}-	} else if ( xml_tagexact( node, "roleTerm" ) ) {-		if ( roles->len ) newstr_addchar( roles, '|' );-		newstr_newstrcat( roles, node->value );-	}-	if ( node->down ) {-		status = modsin_personr( node->down, name, suffix, roles );-		if ( status!=BIBL_OK ) goto out;-	}-	if ( node->next ) status = modsin_personr( node->next, name, suffix, roles );-out:-	newstr_free( &outname );-	return status;-}--static int modsin_asis_corp( xml *node, fields *info, int level, char *suffix ) { 	int fstatus, status = BIBL_OK;-	newstr name, roles, role_out;+	str name, roles, role_out; 	xml *dnode = node->down; 	if ( dnode ) {-		newstrs_init( &name, &roles, &role_out, NULL );+		strs_init( &name, &roles, &role_out, NULL ); 		status = modsin_asis_corp_r( dnode, &name, &roles ); 		if ( status!=BIBL_OK ) goto out; 		status = modsin_marcrole_convert( &roles, suffix, &role_out ); 		if ( status!=BIBL_OK ) goto out;-		fstatus = fields_add( info, role_out.data, name.data, level );+		fstatus = fields_add( info, str_cstr( &role_out ), str_cstr( &name ), level ); 		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR; out:-		newstrs_free( &name, &roles, &role_out, NULL );+		strs_free( &name, &roles, &role_out, NULL ); 	} 	return status; }  static int+modsin_roler( xml *node, str *roles )+{+	if ( roles->len ) str_addchar( roles, '|' );+	str_strcat( roles, node->value );+	if ( str_memerr( roles ) ) return BIBL_ERR_MEMERR;+	else return BIBL_OK;+}++static int+modsin_personr( xml *node, str *familyname, str *givenname, str *suffix )+{+	int status = BIBL_OK;++	if ( xml_tag_attrib( node, "namePart", "type", "family" ) ) {+		if ( str_has_value( familyname ) ) str_addchar( familyname, ' ' );+		str_strcat( familyname, node->value );+		if ( str_memerr( familyname ) ) status = BIBL_ERR_MEMERR;+	}++	else if ( xml_tag_attrib( node, "namePart", "type", "suffix") ||+	          xml_tag_attrib( node, "namePart", "type", "termsOfAddress" )) {+		if ( str_has_value( suffix ) ) str_addchar( suffix, ' ' );+		str_strcat( suffix, node->value );+		if ( str_memerr( suffix ) ) status = BIBL_ERR_MEMERR;+	}++	else if (xml_tag_attrib( node, "namePart", "type", "date") ){+		/* no nothing */+	}++	else {+		if ( str_has_value( givenname ) ) str_addchar( givenname, '|' );+		str_strcat( givenname, node->value );+		if ( str_memerr( givenname ) ) status = BIBL_ERR_MEMERR;+	}++	return status;+}++static int modsin_person( xml *node, fields *info, int level ) {-	newstr name, suffix, roles, role_out;+	str familyname, givenname, name, suffix, roles, role_out; 	int fstatus, status = BIBL_OK;-	xml *dnode = node->down;-	if ( dnode ) {-		newstrs_init( &name, &suffix, &roles, &role_out, NULL );+	xml *dnode, *rnode; -		status = modsin_personr( dnode, &name, &suffix, &roles );-		if ( status!=BIBL_OK ) goto out;-		if ( suffix.len ) {-			newstr_strcat( &name, "||" );-			newstr_newstrcat( &name, &suffix );-			if ( newstr_memerr( &name ) ) { status=BIBL_ERR_MEMERR; goto out; }+	dnode = node->down;+	if ( !dnode ) return status;++	strs_init( &name, &familyname, &givenname, &suffix, &roles, &role_out, NULL );++	while ( dnode ) {++		if ( xml_tagexact( dnode, "namePart" ) ) {+			status = modsin_personr( dnode, &familyname, &givenname, &suffix );+			if ( status!=BIBL_OK ) goto out; 		} -		status = modsin_marcrole_convert( &roles, NULL, &role_out );-		if ( status!=BIBL_OK ) goto out;+		else if ( xml_tagexact( dnode, "role" ) ) {+			rnode = dnode->down;+			while ( rnode ) {+				if ( xml_tagexact( rnode, "roleTerm" ) ) {+					status = modsin_roler( rnode, &roles );+					if ( status!=BIBL_OK ) goto out;+				}+				rnode = rnode->next;+			}+		} -		fstatus = fields_add( info, role_out.data, name.data, level );-		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;-out:-		newstrs_free( &name, &suffix, &roles, &role_out, NULL );+		dnode = dnode->next;+ 	}++	/*+	 * Handle:+	 *          <namePart type='given'>Noah A.</namePart>+	 *          <namePart type='family'>Smith</namePart>+	 * without mangling the order of "Noah A."+	 */+	if ( str_has_value( &familyname ) ) {+		str_strcpy( &name, &familyname );+		if ( givenname.len ) {+			str_addchar( &name, '|' );+			str_strcat( &name, &givenname );+		}+	}++	/*+	 * Handle:+	 *          <namePart>Noah A. Smith</namePart>+	 * with name order mangling.+	 */+	else {+		if ( str_has_value( &givenname ) )+			name_parse( &name, &givenname, NULL, NULL );+	}++	if ( str_has_value( &suffix ) ) {+		str_strcatc( &name, "||" );+		str_strcat( &name, &suffix );+	}++	if ( str_memerr( &name ) ) {+		status=BIBL_ERR_MEMERR;+		goto out;+	}++	status = modsin_marcrole_convert( &roles, NULL, &role_out );+	if ( status!=BIBL_OK ) goto out;++	fstatus = fields_add_can_dup( info, str_cstr( &role_out ), str_cstr( &name ), level );+	if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;++out:+	strs_free( &name, &familyname, &givenname, &suffix, &roles, &role_out, NULL ); 	return status; } @@ -452,7 +509,7 @@  	tag = ( school ) ? school_tag : address_tag; -	fstatus = fields_add( info, tag, xml_data( node ), level );+	fstatus = fields_add( info, tag, xml_value( node ), level ); 	if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;  	return BIBL_OK;@@ -462,26 +519,26 @@ modsin_placeterm_code( xml *node, fields *info, int level ) { 	int fstatus, status = BIBL_OK;-	newstr s, *auth;+	str s, *auth; -	newstr_init( &s );+	str_init( &s );  	auth = xml_getattrib( node, "authority" ); 	if ( auth && auth->len ) {-		newstr_newstrcpy( &s, auth );-		newstr_addchar( &s, '|' );+		str_strcpy( &s, auth );+		str_addchar( &s, '|' ); 	}-	newstr_newstrcat( &s, node->value );+	str_strcat( &s, node->value ); -	if ( newstr_memerr( &s ) ) {+	if ( str_memerr( &s ) ) { 		status = BIBL_ERR_MEMERR; 		goto out; 	} -	fstatus = fields_add( info, "CODEDADDRESS", s.data, level );+	fstatus = fields_add( info, "CODEDADDRESS", str_cstr( &s ), level ); 	if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR; out:-	newstr_free( &s );+	str_free( &s ); 	return status; } @@ -489,13 +546,13 @@ modsin_placeterm( xml *node, fields *info, int level, int school ) { 	int status = BIBL_OK;-	newstr *type;+	str *type;  	type = xml_getattrib( node, "type" );-	if ( type && type->len ) {-		if ( !strcmp( type->data, "text" ) )+	if ( str_has_value( type ) ) {+		if ( !strcmp( str_cstr( type ), "text" ) ) 			status = modsin_placeterm_text( node, info, level, school );-		else if ( !strcmp( type->data, "code" ) )+		else if ( !strcmp( str_cstr( type ), "code" ) ) 			status = modsin_placeterm_code( node, info, level ); 	} @@ -520,21 +577,21 @@ }  static int-modsin_origininfor( xml *node, fields *info, int level, newstr *pub, newstr *add, newstr *addc, newstr *ed, newstr *iss )+modsin_origininfor( xml *node, fields *info, int level, str *pub, str *add, str *addc, str *ed, str *iss ) { 	int status = BIBL_OK; 	if ( xml_tagexact( node, "dateIssued" ) ) 		status = modsin_date( node, info, level, 0 );-	else if ( xml_tagexact( node, "publisher" ) && xml_hasdata( node ) ) {-		newstr_newstrcat( pub, node->value );-		if ( newstr_memerr( pub ) ) return BIBL_ERR_MEMERR;-	} else if ( xml_tagexact( node, "edition" ) && xml_hasdata( node ) ) {-		newstr_newstrcat( ed, node->value );-		if( newstr_memerr( ed ) ) return BIBL_ERR_MEMERR;-	} else if ( xml_tagexact( node, "issuance" ) && xml_hasdata( node ) ) {-		newstr_newstrcat( iss, node->value );-		if ( newstr_memerr( iss ) ) return BIBL_ERR_MEMERR;-	} else if ( xml_tagexact( node, "place" ) && xml_hasdata( node ) )+	else if ( xml_tagexact( node, "publisher" ) && xml_hasvalue( node ) ) {+		str_strcat( pub, node->value );+		if ( str_memerr( pub ) ) return BIBL_ERR_MEMERR;+	} else if ( xml_tagexact( node, "edition" ) && xml_hasvalue( node ) ) {+		str_strcat( ed, node->value );+		if( str_memerr( ed ) ) return BIBL_ERR_MEMERR;+	} else if ( xml_tagexact( node, "issuance" ) && xml_hasvalue( node ) ) {+		str_strcat( iss, node->value );+		if ( str_memerr( iss ) ) return BIBL_ERR_MEMERR;+	} else if ( xml_tagexact( node, "place" ) && xml_hasvalue( node ) ) 		status = modsin_placer( node, info, level, 0 ); 	if ( status!=BIBL_OK ) return status; 	if ( node->down ) {@@ -549,35 +606,35 @@ static int modsin_origininfo( xml *node, fields *info, int level ) {-	newstr publisher, address, addcode, edition, issuance;+	str publisher, address, addcode, edition, issuance; 	int fstatus, status = BIBL_OK; 	if ( node->down ) {-		newstrs_init( &publisher, &address, &addcode, &edition, &issuance, NULL );+		strs_init( &publisher, &address, &addcode, &edition, &issuance, NULL ); 		status = modsin_origininfor( node->down, info, level, &publisher,  				&address, &addcode, &edition, &issuance ); 		if ( status!=BIBL_OK ) goto out;-		if ( publisher.len ) {-			fstatus = fields_add( info, "PUBLISHER", publisher.data, level );+		if ( str_has_value( &publisher ) ) {+			fstatus = fields_add( info, "PUBLISHER", str_cstr( &publisher ), level ); 			if ( fstatus!=FIELDS_OK ) { status=BIBL_ERR_MEMERR; goto out; } 		}-		if ( address.len ) {-			fstatus = fields_add( info, "ADDRESS", address.data, level );+		if ( str_has_value( &address ) ) {+			fstatus = fields_add( info, "ADDRESS", str_cstr( &address ), level ); 			if ( fstatus!=FIELDS_OK ) { status=BIBL_ERR_MEMERR; goto out; } 		}-		if ( addcode.len ) {-			fstatus = fields_add( info, "CODEDADDRESS", addcode.data, level );+		if ( str_has_value( &addcode ) ) {+			fstatus = fields_add( info, "CODEDADDRESS", str_cstr( &addcode ), level ); 			if ( fstatus!=FIELDS_OK ) { status=BIBL_ERR_MEMERR; goto out; } 		}-		if ( edition.len ) {-			fstatus = fields_add( info, "EDITION", edition.data, level );+		if ( str_has_value( &edition ) ) {+			fstatus = fields_add( info, "EDITION", str_cstr( &edition ), level ); 			if ( fstatus!=FIELDS_OK ) { status=BIBL_ERR_MEMERR; goto out; } 		}-		if ( issuance.len ) {-			fstatus = fields_add( info, "ISSUANCE", issuance.data, level );+		if ( str_has_value( &issuance ) ) {+			fstatus = fields_add( info, "ISSUANCE", str_cstr( &issuance ), level ); 			if ( fstatus!=FIELDS_OK ) { status=BIBL_ERR_MEMERR; goto out; } 		} out:-		newstrs_free( &publisher, &address, &addcode, &edition, &issuance, NULL );+		strs_free( &publisher, &address, &addcode, &edition, &issuance, NULL ); 	} 	return status; }@@ -586,7 +643,11 @@ modsin_subjectr( xml *node, fields *info, int level ) { 	int fstatus, status = BIBL_OK;-	if ( xml_tagexact( node, "topic" ) || xml_tagexact( node, "geographic" )) {+	if ( xml_tag_attrib( node, "topic", "class", "primary" ) ) {+		fstatus = fields_add( info, "EPRINTCLASS", node->value->data, level );+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;+	}+	else if ( xml_tagexact( node, "topic" ) || xml_tagexact( node, "geographic" )) { 		fstatus = fields_add( info, "KEYWORD", node->value->data, level ); 		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	}@@ -610,10 +671,10 @@ modsin_id1( xml *node, fields *info, int level ) { 	int fstatus;-	newstr *ns;+	str *ns; 	ns = xml_getattrib( node, "ID" );-	if ( ns && ns->len ) {-		fstatus = fields_add( info, "REFNUM", ns->data, level );+	if ( str_has_value( ns ) ) {+		fstatus = fields_add( info, "REFNUM", str_cstr( ns ), level ); 		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	} 	return BIBL_OK;@@ -633,8 +694,8 @@ 	int i, ismarc = 0, isadded = 0, fstatus; 	char *d; -	if ( !xml_hasdata( node ) ) return BIBL_OK;-	d = xml_data( node );+	if ( !xml_hasvalue( node ) ) return BIBL_OK;+	d = xml_value( node ); 	if ( marc_findgenre( d )!=-1 ) ismarc = 1; 	if ( !ismarc ) { 		for ( i=0; i<nadded && ismarc==0 && isadded==0; ++i )@@ -665,16 +726,16 @@ 	int fstatus, status = BIBL_OK; 	char *d = NULL; 	if ( xml_tagexact( node, "languageTerm" ) ) {-		if ( xml_hasdata( node ) ) {+		if ( xml_hasvalue( node ) ) { 			if ( xml_hasattrib( node, "type", "code" ) ) { 				if ( xml_hasattrib( node, "authority", "iso639-1" ) )-					d = iso639_1_from_code( xml_data( node ) );+					d = iso639_1_from_code( xml_value( node ) ); 				else if ( xml_hasattrib( node, "authority", "iso639-2b" ) )-					d = iso639_2_from_code( xml_data( node ) );+					d = iso639_2_from_code( xml_value( node ) ); 				else if ( xml_hasattrib( node, "authority", "iso639-3" ))-					d = iso639_3_from_code( xml_data( node ) );+					d = iso639_3_from_code( xml_value( node ) ); 			}-			if ( !d ) d  = xml_data( node );+			if ( !d ) d  = xml_value( node ); 			fstatus = fields_add( info, "LANGUAGE", d, level ); 			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; 		}@@ -688,8 +749,8 @@ { 	int fstatus, status = BIBL_OK; 	/* Old versions of MODS had <language>English</language> */-	if ( xml_hasdata( node ) ) {-		fstatus = fields_add( info, "LANGUAGE", xml_data( node ), level );+	if ( xml_hasvalue( node ) ) {+		fstatus = fields_add( info, "LANGUAGE", xml_value( node ), level ); 		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	} @@ -702,8 +763,8 @@ modsin_simple( xml *node, fields *info, char *tag, int level ) { 	int fstatus;-	if ( xml_hasdata( node ) ) {-		fstatus = fields_add( info, tag, xml_data( node ), level );+	if ( xml_hasvalue( node ) ) {+		fstatus = fields_add( info, tag, xml_value( node ), level ); 		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	} 	return BIBL_OK;@@ -713,22 +774,29 @@ modsin_locationr( xml *node, fields *info, int level ) { 	int fstatus, status = BIBL_OK;+	char *url        = "URL";+	char *fileattach = "FILEATTACH"; 	char *tag=NULL;  	if ( xml_tagexact( node, "url" ) ) { 		if ( xml_hasattrib( node, "access", "raw object" ) )-			tag = "FILEATTACH";+			tag = fileattach; 		else-			tag = "URL";-	} else if ( xml_tagexact( node, "physicalLocation" ) ) {+			tag = url;+	}+	else if ( xml_tagexact( node, "physicalLocation" ) ) { 		if ( xml_hasattrib( node, "type", "school" ) ) 			tag = "SCHOOL"; 		else 			tag = "LOCATION"; 	} -	if ( tag ) {-		fstatus = fields_add( info, tag, node->value->data, level );+	if ( tag == url ) {+		status = urls_split_and_add( xml_value( node ), info, level );+		if ( status!=BIBL_OK ) return status;+	}+	else if ( tag ) {+		fstatus = fields_add( info, tag, xml_value( node ), level ); 		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	} @@ -749,13 +817,13 @@ }  static int-modsin_descriptionr( xml *node, newstr *s )+modsin_descriptionr( xml *node, str *s ) { 	int status = BIBL_OK; 	if ( xml_tagexact( node, "extent" ) || 	     xml_tagexact( node, "note" ) ) {-		newstr_newstrcpy( s, node->value );-		if ( newstr_memerr( s ) ) return BIBL_ERR_MEMERR;+		str_strcpy( s, node->value );+		if ( str_memerr( s ) ) return BIBL_ERR_MEMERR; 	} 	if ( node->down ) { 		status = modsin_descriptionr( node->down, s );@@ -769,29 +837,29 @@ modsin_description( xml *node, fields *info, int level ) { 	int fstatus, status = BIBL_OK;-	newstr s;-	newstr_init( &s );+	str s;+	str_init( &s ); 	if ( node->down ) { 		status = modsin_descriptionr( node->down, &s ); 		if ( status!=BIBL_OK ) goto out; 	} else { 		if ( node->value && node->value->len > 0 )-			newstr_newstrcpy( &s, node->value );-		if ( newstr_memerr( &s ) ) {+			str_strcpy( &s, node->value );+		if ( str_memerr( &s ) ) { 			status = BIBL_ERR_MEMERR; 			goto out; 		} 	}-	if ( s.len ) {-		fstatus = fields_add( info, "DESCRIPTION", s.data, level );+	if ( str_has_value( &s ) ) {+		fstatus = fields_add( info, "DESCRIPTION", str_cstr( &s ), level ); 		if ( fstatus!=FIELDS_OK ) { 			status = BIBL_ERR_MEMERR; 			goto out; 		} 	} out:-	newstr_free( &s );-	return BIBL_OK;+	str_free( &s );+	return status; }  static int@@ -824,8 +892,8 @@ { 	int fstatus, status = BIBL_OK; 	char *tag, *d;-	if ( xml_hasdata( node ) ) {-		d = xml_data( node );+	if ( xml_hasvalue( node ) ) {+		d = xml_value( node ); 		if ( xml_tag_attrib( node, "classification", "authority", "lcc" ) ) 			tag = "LCC"; 		else@@ -847,8 +915,8 @@ 	/* extract recordIdentifier */ 	curr = node; 	while ( curr ) {-		if ( xml_tagexact( curr, "recordIdentifier" ) && xml_hasdata( curr ) ) {-			d = xml_data( curr );+		if ( xml_tagexact( curr, "recordIdentifier" ) && xml_hasvalue( curr ) ) {+			d = xml_value( curr ); 			fstatus = fields_add( info, "REFNUM", d, level ); 			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; 		}@@ -861,21 +929,24 @@ modsin_identifier( xml *node, fields *info, int level ) { 	convert ids[] = {-		{ "citekey",       "REFNUM"       },-		{ "issn",          "ISSN"         },-		{ "isbn",          "ISBN"         },-		{ "doi",           "DOI"          },-		{ "url",           "URL"          },-		{ "uri",           "URL"          },-		{ "pmid",          "PMID"         },-		{ "pubmed",        "PMID"         },-		{ "medline",       "MEDLINE"      },-		{ "arXiv",         "ARXIV"        },-		{ "pii",           "PII"          },-		{ "isi",           "ISIREFNUM"    },-		{ "serial number", "SERIALNUMBER" },-		{ "accessnum",     "ACCESSNUM"    },-		{ "jstor",         "JSTOR"        },+		{ "citekey",       "REFNUM",      0, 0 },+		{ "issn",          "ISSN",        0, 0 },+		{ "coden",         "CODEN",       0, 0 },+		{ "isbn",          "ISBN",        0, 0 },+		{ "doi",           "DOI",         0, 0 },+		{ "url",           "URL",         0, 0 },+		{ "uri",           "URL",         0, 0 },+		{ "pmid",          "PMID",        0, 0 },+		{ "pubmed",        "PMID",        0, 0 },+		{ "medline",       "MEDLINE",     0, 0 },+		{ "pmc",           "PMC",         0, 0 },+		{ "arXiv",         "ARXIV",       0, 0 },+		{ "MRnumber",      "MRNUMBER",    0, 0 },+		{ "pii",           "PII",         0, 0 },+		{ "isi",           "ISIREFNUM",   0, 0 },+		{ "serial number", "SERIALNUMBER",0, 0 },+		{ "accessnum",     "ACCESSNUM",   0, 0 },+		{ "jstor",         "JSTOR",       0, 0 }, 	}; 	int i, fstatus, n = sizeof( ids ) / sizeof( ids[0] ); 	if ( !node->value || node->value->len==0 ) return BIBL_OK;@@ -892,11 +963,11 @@ modsin_mods( xml *node, fields *info, int level ) { 	convert simple[] = {-		{ "note",            "NOTES" },-		{ "abstract",        "ABSTRACT" },-		{ "bibtex-annote",   "ANNOTE" },-		{ "typeOfResource",  "RESOURCE" },-		{ "tableOfContents", "CONTENTS" },+		{ "note",            "NOTES",    0, 0 },+		{ "abstract",        "ABSTRACT", 0, 0 },+		{ "bibtex-annote",   "ANNOTE",   0, 0 },+		{ "typeOfResource",  "RESOURCE", 0, 0 },+		{ "tableOfContents", "CONTENTS", 0, 0 }, 	}; 	int nsimple = sizeof( simple ) / sizeof( simple[0] ); 	int i, found = 0, status = BIBL_OK;@@ -944,6 +1015,10 @@ 			  xml_tag_attrib( node, "relatedItem", "type", "series" ) ) { 			if ( node->down ) status = modsin_mods( node->down, info, level+1 ); 		}+		else if ( xml_tag_attrib( node, "relatedItem", "type", "original" ) ) {+			if ( node->down ) status = modsin_mods( node->down, info, LEVEL_ORIG );+		}+ 		if ( status!=BIBL_OK ) return status; 	} @@ -971,8 +1046,8 @@ 	return status; } -int-modsin_processf( fields *modsin, char *data, char *filename, long nref )+static int+modsin_processf( fields *modsin, char *data, char *filename, long nref, param *p ) { 	int status; 	xml top;@@ -1011,32 +1086,31 @@ 	return xml_findend( p, "mods" ); } -int-modsin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line,-		newstr *reference, int *fcharset )+static int+modsin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset ) {-	newstr tmp;+	str tmp; 	int m, file_charset = CHARSET_UNKNOWN; 	char *startptr = NULL, *endptr = NULL; -	newstr_init( &tmp );+	str_init( &tmp );  	do {-		if ( line->data ) newstr_newstrcat( &tmp, line );-		if ( tmp.data ) {+		if ( line->data ) str_strcat( &tmp, line );+		if ( str_has_value( &tmp ) ) { 			m = xml_getencoding( &tmp ); 			if ( m!=CHARSET_UNKNOWN ) file_charset = m; 			startptr = modsin_startptr( tmp.data ); 			endptr = modsin_endptr( tmp.data ); 		} else startptr = endptr = NULL;-		newstr_empty( line );+		str_empty( line ); 		if ( startptr && endptr ) {-			newstr_segcpy( reference, startptr, endptr );-			newstr_strcpy( line, endptr );+			str_segcpy( reference, startptr, endptr );+			str_strcpyc( line, endptr ); 		}-	} while ( !endptr && newstr_fget( fp, buf, bufsize, bufpos, line ) );+	} while ( !endptr && str_fget( fp, buf, bufsize, bufpos, line ) ); -	newstr_free( &tmp );+	str_free( &tmp ); 	*fcharset = file_charset; 	return ( reference->len > 0 ); }
− bibutils/modsin.h
@@ -1,20 +0,0 @@-/*- * modsin.h- *- * Copyright (c) Chris Putnam 2004-2014- *- * Source code released under the GPL version 2- *- */-#ifndef MODSIN_H-#define MODSIN_H--#include "newstr.h"-#include "fields.h"-#include "reftypes.h"--extern int modsin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );-extern int modsin_processf( fields *medin, char *data, char *filename, long nref );-extern void modsin_initparams( param *p, const char *progname );--#endif
bibutils/modsout.c view
@@ -1,25 +1,30 @@ /*  * modsout.c  *- * Copyright (c) Chris Putnam 2003-2014+ * Copyright (c) Chris Putnam 2003-2017  *  * Source code released under the GPL version 2  *  */ #include <stdio.h> #include <stdlib.h>+#include <stdarg.h> #include <string.h> #include "is_ws.h"-#include "newstr.h"+#include "str.h" #include "charsets.h"-#include "newstr_conv.h"+#include "str_conv.h" #include "fields.h" #include "iso639_2.h" #include "utf8.h"-#include "modsout.h" #include "modstypes.h" #include "marc.h"+#include "bibformats.h" +static void modsout_writeheader( FILE *outptr, param *p );+static void modsout_writefooter( FILE *outptr );+static int  modsout_write( fields *info, FILE *outptr, param *p, unsigned long numrefs );+ void modsout_initparams( param *p, const char *progname ) {@@ -41,96 +46,134 @@ 	p->writef  = modsout_write; } -static int-increment_level( int level, int amt )-{-	if ( level > -1 ) return level+amt;-	else return level-amt;-}+/* output_tag()+ *+ * mode = TAG_OPEN,         "<tag>"+ * mode = TAG_CLOSE,        "</tag>"+ * mode = TAG_OPENCLOSE,    "<tag>data</tag>"+ * mode = TAG_SELFCLOSE,    "<tag/>"+ *+ * newline = TAG_NONEWLINE, "<tag>"+ * newline = TAG_NEWLINE,   "<tag>\n"+ *+ */+#define TAG_OPEN      (0)+#define TAG_CLOSE     (1)+#define TAG_OPENCLOSE (2)+#define TAG_SELFCLOSE (3) +#define TAG_NONEWLINE (0)+#define TAG_NEWLINE   (1)+ static void-output_tab0( FILE *outptr, int level )+output_tag_core( FILE *outptr, int nindents, char *tag, char *data, unsigned char mode, unsigned char newline, va_list *attrs ) {+	char *attr, *val; 	int i;-	level = abs( level );-	for ( i=0; i<=level; ++i ) fprintf( outptr, "    " );-} -static void-output_tab1( FILE *outptr, int level, char *tag )-{-	output_tab0( outptr, level );+	for ( i=0; i<nindents; ++i ) fprintf( outptr, "    " );++	if ( mode!=TAG_CLOSE )+		fprintf( outptr, "<" );+	else+		fprintf( outptr, "</" );+ 	fprintf( outptr, "%s", tag );-} -static void-output_tab2_attrib( FILE *outptr, int level, char *tag, char *data, -	char *attrib, char *type, int cr )-{-	output_tab0( outptr, level );-	fprintf( outptr, "<%s", tag );-	if ( attrib && type ) fprintf( outptr, " %s=\"%s\"", attrib, type );-	fprintf( outptr, ">%s</%s>", data, tag );-	if ( cr ) fprintf( outptr, "\n" );-}+	do {+		attr = va_arg( *attrs, char * );+		if ( attr ) val  = va_arg( *attrs, char * );+		if ( attr && val )+			fprintf( outptr, " %s=\"%s\"", attr, val );+	} while ( attr && val ); -static void-output_tab4( FILE *outptr, int level, char *tag, char *aname, char *avalue,-		char *data, int cr )-{-	output_tab0( outptr, level );-	fprintf( outptr, "<%s %s=\"%s\">%s</%s>", tag,aname,avalue,data,tag);-	if ( cr ) fprintf( outptr, "\n" );+	if ( mode!=TAG_SELFCLOSE )+		fprintf( outptr, ">" );+	else+		fprintf( outptr, "/>" );++	if ( mode==TAG_OPENCLOSE ) {+		fprintf( outptr, "%s</%s>", data, tag );+	}++	if ( newline==TAG_NEWLINE )+		fprintf( outptr, "\n" ); } +/* output_tag()+ *+ *     output XML tag+ *+ * mode     = [ TAG_OPEN | TAG_CLOSE | TAG_OPENCLOSE | TAG_SELFCLOSE ]+ * newline  = [ TAG_NEWLINE | TAG_NONEWLINE ]+ *+ * for mode TAG_OPENCLOSE, ensure that value is non-NULL, as string pointed to by value+ * will be output in the tag+ */ static void-output_tab6( FILE *outptr, int level, char *tag, char *aname, char *avalue,-		char *bname, char *bvalue, char *data, int cr )+output_tag( FILE *outptr, int nindents, char *tag, char *value, unsigned char mode, unsigned char newline, ... ) {-	output_tab0( outptr, level );-	fprintf( outptr, "<%s %s=\"%s\" %s=\"%s\">%s</%s>", tag,aname,avalue,bname,bvalue,data,tag);-	if ( cr ) fprintf( outptr, "\n" );+	va_list attrs;++	va_start( attrs, newline );+	output_tag_core( outptr, nindents, tag, value, mode, newline, &attrs );+	va_end( attrs ); } +/* output_fil()+ *+ *     output XML tag, but lookup data in fields struct+ *+ * mode     = [ TAG_OPEN | TAG_CLOSE | TAG_OPENCLOSE | TAG_SELFCLOSE ]+ * newline  = [ TAG_NEWLINE | TAG_NONEWLINE ]+ *+ * value looked up in fields will only be used in mode TAG_OPENCLOSE+ */ static void-output_fill2( FILE *outptr, int level, char *tag, fields *f, int n, int cr )+output_fil( FILE *outptr, int nindents, char *tag, fields *f, int n, unsigned char mode, unsigned char newline, ... ) {+	va_list attrs; 	char *value;+ 	if ( n!=-1 ) {-		value = fields_value( f, n, FIELDS_CHRP );-		output_tab2_attrib( outptr, level, tag, value, -			NULL, NULL, cr );-		fields_setused( f, n );+		value = (char *) fields_value( f, n, FIELDS_CHRP );+		va_start( attrs, newline );+		output_tag_core( outptr, nindents, tag, value, mode, newline, &attrs );+		va_end( attrs ); 	} } -static void-output_fill4( FILE *outptr, int level, char *tag, char *aname, char *avalue,-		fields *f, int n, int cr )+static inline int+lvl2indent( int level ) {-	char *value;-	if ( n!=-1 ) {-		value = fields_value( f, n, FIELDS_CHRP );-		output_tab4( outptr, level, tag, aname, avalue,-				value, cr );-		fields_setused( f, n );-	}+	if ( level < -1 ) return -level + 1;+	else return level + 1; } -/*- * Find the positions of all convert.internal tags and store the- * locations in convert.code.+static inline int+incr_level( int level, int amt )+{+	if ( level > -1 ) return level+amt;+	else return level-amt;+}++/* convert_findallfields()  *- * Return number of the tags found+ *       Find the positions of all convert.internal tags in the fields+ *       structure and store the locations in convert.pos element.+ *+ *       Return number of the tags found.  */ static int-find_alltags( fields *f, convert *parts, int nparts, int level )+convert_findallfields( fields *f, convert *parts, int nparts, int level ) {-	int i, n=0;+	int i, n = 0;+ 	for ( i=0; i<nparts; ++i ) {-		parts[i].code = fields_find( f, parts[i].internal, level );-		n += ( parts[i].code!=-1 );+		parts[i].pos = fields_find( f, parts[i].internal, level );+		n += ( parts[i].pos!=-1 ); 	}+ 	return n; } @@ -141,83 +184,76 @@ 	int subttl = fields_find( f, "SUBTITLE", level ); 	int shrttl = fields_find( f, "SHORTTITLE", level ); 	int parttl = fields_find( f, "PARTTITLE", level );+	char *val; -	output_tab1( outptr, level, "<titleInfo>\n" );-	output_fill2( outptr, increment_level(level,1), "title", f, ttl, 1 );-	output_fill2( outptr, increment_level(level,1), "subTitle", f, subttl, 1 );-	output_fill2( outptr, increment_level(level,1), "partName", f, parttl, 1 );+	output_tag( outptr, lvl2indent(level),               "titleInfo", NULL,      TAG_OPEN,      TAG_NEWLINE, NULL );+	output_fil( outptr, lvl2indent(incr_level(level,1)), "title",     f, ttl,    TAG_OPENCLOSE, TAG_NEWLINE, NULL );+	output_fil( outptr, lvl2indent(incr_level(level,1)), "subTitle",  f, subttl, TAG_OPENCLOSE, TAG_NEWLINE, NULL );+	output_fil( outptr, lvl2indent(incr_level(level,1)), "partName",  f, parttl, TAG_OPENCLOSE, TAG_NEWLINE, NULL );+	/* MODS output doesn't verify if we don't at least have a <title/> element */ 	if ( ttl==-1 && subttl==-1 )-		output_tab1( outptr, increment_level(level,1), "<title/>\n" );-	output_tab1( outptr, level, "</titleInfo>\n" );+		output_tag( outptr, lvl2indent(incr_level(level,1)), "title", NULL,  TAG_SELFCLOSE, TAG_NEWLINE, NULL );+	output_tag( outptr, lvl2indent(level),               "titleInfo", NULL,      TAG_CLOSE,     TAG_NEWLINE, NULL );  	/* output shorttitle if it's different from normal title */ 	if ( shrttl!=-1 ) {-		if ( ttl==-1 || subttl!=-1 ||-			strcmp(f->data[ttl].data,f->data[shrttl].data) ) {-			output_tab1( outptr, level, -					"<titleInfo type=\"abbreviated\">\n" );-			output_fill2( outptr, level+1, "title", f, shrttl,1);-			output_tab1( outptr, level, "</titleInfo>\n" );+		val = (char *) fields_value( f, shrttl, FIELDS_CHRP );+		if ( ttl==-1 || subttl!=-1 || strcmp(f->data[ttl].data,val) ) {+			output_tag( outptr, lvl2indent(level),               "titleInfo", NULL, TAG_OPEN,      TAG_NEWLINE, "type", "abbreviated", NULL );+			output_tag( outptr, lvl2indent(incr_level(level,1)), "title",     val,  TAG_OPENCLOSE, TAG_NEWLINE, NULL );+			output_tag( outptr, lvl2indent(level),               "titleInfo", NULL, TAG_CLOSE,     TAG_NEWLINE, NULL ); 		}-		fields_setused( f, shrttl ); 	} }  static void-output_personalstart( FILE *outptr, int level )-{-	int j;-	for ( j=0; j<=level; ++j ) fprintf( outptr, "    " );-		fprintf( outptr, "<name type=\"personal\">\n" );-}--static void output_name( FILE *outptr, char *p, int level ) {-	newstr family, part, suffix;+	str family, part, suffix; 	int n=0; -	newstrs_init( &family, &part, &suffix, NULL );+	strs_init( &family, &part, &suffix, NULL ); -	while ( *p && *p!='|' ) newstr_addchar( &family, *p++ );+	while ( *p && *p!='|' ) str_addchar( &family, *p++ ); 	if ( *p=='|' ) p++;  	while ( *p ) {-		while ( *p && *p!='|' ) newstr_addchar( &part, *p++ );+		while ( *p && *p!='|' ) str_addchar( &part, *p++ ); 		/* truncate periods from "A. B. Jones" names */ 		if ( part.len ) { 			if ( part.len==2 && part.data[1]=='.' ) { 				part.len=1; 				part.data[1]='\0'; 			}-			if ( n==0 ) output_personalstart( outptr, level );-			output_tab4( outptr, increment_level(level,1), "namePart", "type", -					"given", part.data, 1 );+			if ( n==0 )+				output_tag( outptr, lvl2indent(level), "name", NULL, TAG_OPEN, TAG_NEWLINE, "type", "personal", NULL );+			output_tag( outptr, lvl2indent(incr_level(level,1)), "namePart", part.data, TAG_OPENCLOSE, TAG_NEWLINE, "type", "given", NULL ); 			n++; 		} 		if ( *p=='|' ) { 			p++; 			if ( *p=='|' ) { 				p++;-				while ( *p && *p!='|' ) newstr_addchar( &suffix, *p++ );+				while ( *p && *p!='|' ) str_addchar( &suffix, *p++ ); 			}-			newstr_empty( &part );+			str_empty( &part ); 		} 	}  	if ( family.len ) {-		if ( n==0 ) output_personalstart( outptr, level );-		output_tab4( outptr, increment_level(level,1), "namePart", "type", "family",-				family.data, 1 );+		if ( n==0 )+			output_tag( outptr, lvl2indent(level), "name", NULL, TAG_OPEN, TAG_NEWLINE, "type", "personal", NULL );+		output_tag( outptr, lvl2indent(incr_level(level,1)), "namePart", family.data, TAG_OPENCLOSE, TAG_NEWLINE, "type", "family", NULL );+		n++; 	}  	if ( suffix.len ) {-		if ( n==0 ) output_personalstart( outptr, level );-		output_tab4( outptr, increment_level(level,1), "namePart", "type", "suffix",-				suffix.data, 1 );+		if ( n==0 )+			output_tag( outptr, lvl2indent(level), "name", NULL, TAG_OPEN, TAG_NEWLINE, "type", "personal", NULL );+		output_tag( outptr, lvl2indent(incr_level(level,1)), "namePart", suffix.data, TAG_OPENCLOSE, TAG_NEWLINE, "type", "suffix", NULL ); 	} -	newstrs_free( &part, &family, &suffix, NULL );+	strs_free( &part, &family, &suffix, NULL ); }  @@ -241,140 +277,166 @@ output_names( fields *f, FILE *outptr, int level ) { 	convert   names[] = {-	  { "author",                              "AUTHOR",          MARC_AUTHORITY },-	  { "editor",                              "EDITOR",          MARC_AUTHORITY },-	  { "annotator",                           "ANNOTATOR",       MARC_AUTHORITY },-	  { "artist",                              "ARTIST",          MARC_AUTHORITY },-	  { "author",                              "2ND_AUTHOR",      MARC_AUTHORITY },-	  { "author",                              "3RD_AUTHOR",      MARC_AUTHORITY },-	  { "author",                              "SUB_AUTHOR",      MARC_AUTHORITY },-	  { "author",                              "COMMITTEE",       MARC_AUTHORITY },-	  { "author",                              "COURT",           MARC_AUTHORITY },-	  { "author",                              "LEGISLATIVEBODY", MARC_AUTHORITY },-	  { "author of afterword, colophon, etc.", "AFTERAUTHOR",     MARC_AUTHORITY },-	  { "author of introduction, etc.",        "INTROAUTHOR",     MARC_AUTHORITY },-	  { "cartographer",                        "CARTOGRAPHER",    MARC_AUTHORITY },-	  { "collaborator",                        "COLLABORATOR",    MARC_AUTHORITY },-	  { "commentator",                         "COMMENTATOR",     MARC_AUTHORITY },-	  { "compiler",                            "COMPILER",        MARC_AUTHORITY },-	  { "degree grantor",                      "DEGREEGRANTOR",   MARC_AUTHORITY },-	  { "director",                            "DIRECTOR",        MARC_AUTHORITY },-	  { "event",                               "EVENT",           NO_AUTHORITY   },-	  { "inventor",                            "INVENTOR",        MARC_AUTHORITY },-	  { "organizer of meeting",                "ORGANIZER",       MARC_AUTHORITY },-	  { "patent holder",                       "ASSIGNEE",        MARC_AUTHORITY },-	  { "performer",                           "PERFORMER",       MARC_AUTHORITY },-	  { "producer",                            "PRODUCER",        MARC_AUTHORITY },-	  { "recipient",                           "RECIPIENT",       MARC_AUTHORITY },-	  { "redactor",                            "REDACTOR",        MARC_AUTHORITY },-	  { "reporter",                            "REPORTER",        MARC_AUTHORITY },-	  { "sponsor",                             "SPONSOR",         MARC_AUTHORITY },-	  { "translator",                          "TRANSLATOR",      MARC_AUTHORITY },-	  { "writer",                              "WRITER",          MARC_AUTHORITY },+	  { "author",                              "AUTHOR",          0, MARC_AUTHORITY },+	  { "editor",                              "EDITOR",          0, MARC_AUTHORITY },+	  { "annotator",                           "ANNOTATOR",       0, MARC_AUTHORITY },+	  { "artist",                              "ARTIST",          0, MARC_AUTHORITY },+	  { "author",                              "2ND_AUTHOR",      0, MARC_AUTHORITY },+	  { "author",                              "3RD_AUTHOR",      0, MARC_AUTHORITY },+	  { "author",                              "SUB_AUTHOR",      0, MARC_AUTHORITY },+	  { "author",                              "COMMITTEE",       0, MARC_AUTHORITY },+	  { "author",                              "COURT",           0, MARC_AUTHORITY },+	  { "author",                              "LEGISLATIVEBODY", 0, MARC_AUTHORITY },+	  { "author of afterword, colophon, etc.", "AFTERAUTHOR",     0, MARC_AUTHORITY },+	  { "author of introduction, etc.",        "INTROAUTHOR",     0, MARC_AUTHORITY },+	  { "cartographer",                        "CARTOGRAPHER",    0, MARC_AUTHORITY },+	  { "collaborator",                        "COLLABORATOR",    0, MARC_AUTHORITY },+	  { "commentator",                         "COMMENTATOR",     0, MARC_AUTHORITY },+	  { "compiler",                            "COMPILER",        0, MARC_AUTHORITY },+	  { "degree grantor",                      "DEGREEGRANTOR",   0, MARC_AUTHORITY },+	  { "director",                            "DIRECTOR",        0, MARC_AUTHORITY },+	  { "event",                               "EVENT",           0, NO_AUTHORITY   },+	  { "inventor",                            "INVENTOR",        0, MARC_AUTHORITY },+	  { "organizer of meeting",                "ORGANIZER",       0, MARC_AUTHORITY },+	  { "patent holder",                       "ASSIGNEE",        0, MARC_AUTHORITY },+	  { "performer",                           "PERFORMER",       0, MARC_AUTHORITY },+	  { "producer",                            "PRODUCER",        0, MARC_AUTHORITY },+	  { "recipient",                           "RECIPIENT",       0, MARC_AUTHORITY },+	  { "redactor",                            "REDACTOR",        0, MARC_AUTHORITY },+	  { "reporter",                            "REPORTER",        0, MARC_AUTHORITY },+	  { "sponsor",                             "SPONSOR",         0, MARC_AUTHORITY },+	  { "translator",                          "TRANSLATOR",      0, MARC_AUTHORITY },+	  { "writer",                              "WRITER",          0, MARC_AUTHORITY }, 	}; 	int i, n, nfields, ntypes = sizeof( names ) / sizeof( convert ); 	int f_asis, f_corp, f_conf;-	newstr role;+	str role; -	newstr_init( &role );+	str_init( &role ); 	nfields = fields_num( f ); 	for ( n=0; n<ntypes; ++n ) { 		for ( i=0; i<nfields; ++i ) { 			if ( fields_level( f, i )!=level ) continue; 			if ( f->data[i].len==0 ) continue; 			f_asis = f_corp = f_conf = 0;-			newstr_strcpy( &role, f->tag[i].data );-			if ( newstr_findreplace( &role, ":ASIS", "" )) f_asis=1;-			if ( newstr_findreplace( &role, ":CORP", "" )) f_corp=1;-			if ( newstr_findreplace( &role, ":CONF", "" )) f_conf=1;+			str_strcpyc( &role, f->tag[i].data );+			if ( str_findreplace( &role, ":ASIS", "" )) f_asis=1;+			if ( str_findreplace( &role, ":CORP", "" )) f_corp=1;+			if ( str_findreplace( &role, ":CONF", "" )) f_conf=1; 			if ( strcasecmp( role.data, names[n].internal ) ) 				continue; 			if ( f_asis ) {-				output_tab0( outptr, level );-				fprintf( outptr, "<name>\n" );-				output_fill2( outptr, increment_level(level,1), "namePart", f, i, 1 );+				output_tag( outptr, lvl2indent(level),               "name",     NULL, TAG_OPEN,      TAG_NEWLINE, NULL );+				output_fil( outptr, lvl2indent(incr_level(level,1)), "namePart", f, i, TAG_OPENCLOSE, TAG_NEWLINE, NULL ); 			} else if ( f_corp ) {-				output_tab0( outptr, level );-				fprintf( outptr, "<name type=\"corporate\">\n" );-				output_fill2( outptr, increment_level(level,1), "namePart", f, i, 1 );+				output_tag( outptr, lvl2indent(level),               "name",     NULL, TAG_OPEN,      TAG_NEWLINE, "type", "corporate", NULL );+				output_fil( outptr, lvl2indent(incr_level(level,1)), "namePart", f, i, TAG_OPENCLOSE, TAG_NEWLINE, NULL ); 			} else if ( f_conf ) {-				output_tab0( outptr, level );-				fprintf( outptr, "<name type=\"conference\">\n" );-				output_fill2( outptr, increment_level(level,1), "namePart", f, i, 1 );+				output_tag( outptr, lvl2indent(level),               "name",     NULL, TAG_OPEN,      TAG_NEWLINE, "type", "conference", NULL );+				output_fil( outptr, lvl2indent(incr_level(level,1)), "namePart", f, i, TAG_OPENCLOSE, TAG_NEWLINE, NULL ); 			} else { 				output_name(outptr, f->data[i].data, level); 			}-			output_tab1( outptr, increment_level(level,1), "<role>\n" );-			output_tab1( outptr, increment_level(level,2), "<roleTerm" );+			output_tag( outptr, lvl2indent(incr_level(level,1)), "role", NULL, TAG_OPEN, TAG_NEWLINE, NULL ); 			if ( names[n].code & MARC_AUTHORITY )-				fprintf( outptr, " authority=\"marcrelator\"");-			fprintf( outptr, " type=\"text\">");-			fprintf( outptr, "%s", names[n].mods );-			fprintf( outptr, "</roleTerm>\n");-			output_tab1( outptr, increment_level(level,1), "</role>\n" );-			output_tab1( outptr, level, "</name>\n" );+				output_tag( outptr, lvl2indent(incr_level(level,2)), "roleTerm", names[n].mods, TAG_OPENCLOSE, TAG_NEWLINE, "authority", "marcrelator", "type", "text", NULL );+			else+				output_tag( outptr, lvl2indent(incr_level(level,2)), "roleTerm", names[n].mods, TAG_OPENCLOSE, TAG_NEWLINE, "type", "text", NULL );+			output_tag( outptr, lvl2indent(incr_level(level,1)), "role", NULL, TAG_CLOSE, TAG_NEWLINE, NULL );+			output_tag( outptr, lvl2indent(level),               "name", NULL, TAG_CLOSE, TAG_NEWLINE, NULL ); 			fields_setused( f, i ); 		} 	}-	newstr_free( &role );+	str_free( &role ); } +/* datepos[ NUM_DATE_TYPES ]+ *     use define to ensure that the array and loops don't get out of sync+ *     datepos[0] -> DATE:YEAR/PARTDATE:YEAR+ *     datepos[1] -> DATE:MONTH/PARTDATE:MONTH+ *     datepos[2] -> DATE:DAY/PARTDATE:DAY+ *     datepos[3] -> DATE/PARTDATE+ */+#define DATE_YEAR      (0)+#define DATE_MONTH     (1)+#define DATE_DAY       (2)+#define DATE_ALL       (3)+#define NUM_DATE_TYPES (4)+ static int-output_finddateissued( fields *f, int level, int pos[] )+find_datepos( fields *f, int level, unsigned char use_altnames, int datepos[NUM_DATE_TYPES] ) {-	char      *src_names[] = { "YEAR", "MONTH", "DAY", "DATE" };-	char      *alt_names[] = { "PARTYEAR", "PARTMONTH", "PARTDAY", "PARTDATE" };-	int       i, found = -1, ntypes = 4;+	char      *src_names[] = { "DATE:YEAR", "DATE:MONTH", "DATE:DAY", "DATE" };+	char      *alt_names[] = { "PARTDATE:YEAR", "PARTDATE:MONTH", "PARTDATE:DAY", "PARTDATE" };+	int       found = 0;+	int       i; -	for ( i=0; i<ntypes; ++i ) {-		pos[i] = fields_find( f, src_names[i], level );-		if ( pos[i]!=-1 ) found = pos[i];-	}-	/* for LEVEL_MAIN, do what it takes to find a date */-	if ( found==-1 && level==0 ) {-		for ( i=0; i<ntypes; ++i ) {-			pos[i] = fields_find( f, src_names[i], -1 );-			if ( pos[i]!=-1 ) found = pos[i];-		}-	}-	if ( found==-1 && level==0 ) {-		for ( i=0; i<ntypes; ++i ) {-			pos[i] = fields_find( f, alt_names[i], -1 );-			if ( pos[i]!=-1 ) found = pos[i];-		}+	for ( i=0; i<NUM_DATE_TYPES; ++i ) {+		if ( !use_altnames )+			datepos[i] = fields_find( f, src_names[i], level );+		else+			datepos[i] = fields_find( f, alt_names[i], level );+		if ( datepos[i]!=-1 ) found = 1; 	}+ 	return found; } -static void-output_datepieces( fields *f, FILE *outptr, int pos[4] )+/* find_dateinfo()+ *+ *      fill datepos[] array with position indexes to date information in fields *f+ *+ *      when generating dates for LEVEL_MAIN, first look at level=LEVEL_MAIN, but if that+ *      fails, use LEVEL_ANY (-1)+ *+ *      returns 1 if date information found, 0 otherwise+ */+static int+find_dateinfo( fields *f, int level, int datepos[ NUM_DATE_TYPES ] ) {-	int nprinted = 0, i;-	for ( i=0; i<3 && pos[i]!=-1; ++i ) {-		if ( nprinted>0 ) fprintf( outptr, "-" );-		if ( i>0 && f->data[pos[i]].len==1 )-			fprintf( outptr, "0" ); /*zero pad Jan,Feb,etc*/-		fprintf( outptr,"%s",f->data[pos[i]].data );-		nprinted++;-		fields_setused( f, pos[i] );+	int found;++	/* default to finding date information for the current level */+	found = find_datepos( f, level, 0, datepos );++	/* for LEVEL_MAIN, do whatever it takes to find a date */+	if ( !found && level == LEVEL_MAIN ) {+		found = find_datepos( f, -1, 0, datepos ); 	}+	if ( !found && level == LEVEL_MAIN ) {+		found = find_datepos( f, -1, 1, datepos );+	}++	return found; }  static void-output_dateall( fields *f, FILE *outptr, int pos )+output_datepieces( fields *f, FILE *outptr, int pos[ NUM_DATE_TYPES ] ) {-	fprintf( outptr, "%s", f->data[pos].data );-	fields_setused( f, pos );+	str *s;+	int i;++	for ( i=0; i<3 && pos[i]!=-1; ++i ) {+		if ( i>0 ) fprintf( outptr, "-" );+		/* zero pad month or days written as "1", "2", "3" ... */+		if ( i==DATE_MONTH || i==DATE_DAY ) {+			s = fields_value( f, pos[i], FIELDS_STRP_NOUSE );+			if ( s->len==1 ) {+				fprintf( outptr, "0" );+			}+		}+		fprintf( outptr, "%s", (char *) fields_value( f, pos[i], FIELDS_CHRP ) );+	} }  static void-output_dateissued( fields *f, FILE *outptr, int level, int pos[4] )+output_dateissued( fields *f, FILE *outptr, int level, int pos[ NUM_DATE_TYPES ] ) {-	output_tab1( outptr, increment_level(level,1), "<dateIssued>" );-	if ( pos[0]!=-1 || pos[1]!=-1 || pos[2]!=-1 ) {+	output_tag( outptr, lvl2indent(incr_level(level,1)), "dateIssued", NULL, TAG_OPEN, TAG_NONEWLINE, NULL );+	if ( pos[ DATE_YEAR ]!=-1 || pos[ DATE_MONTH ]!=-1 || pos[ DATE_DAY ]!=-1 ) { 		output_datepieces( f, outptr, pos ); 	} else {-		output_dateall( f, outptr, pos[3] );+		fprintf( outptr, "%s", (char *) fields_value( f, pos[ DATE_ALL ], FIELDS_CHRP ) ); 	} 	fprintf( outptr, "</dateIssued>\n" ); }@@ -382,73 +444,83 @@ static void output_origin( fields *f, FILE *outptr, int level ) {-	convert origin[] = {-		{ "issuance",	  "ISSUANCE",	0 },-		{ "publisher",	  "PUBLISHER",	0 },-		{ "place",	  "ADDRESS",	1 },-		{ "place",	  "AUTHORADDRESS",	0 },-		{ "edition",	  "EDITION",	0 },-		{ "dateCaptured", "URLDATE",    0 }+	convert parts[] = {+		{ "issuance",	  "ISSUANCE",      0, 0 },+		{ "publisher",	  "PUBLISHER",     0, 0 },+		{ "place",	  "ADDRESS",       0, 1 },+		{ "place",	  "AUTHORADDRESS", 0, 0 },+		{ "edition",	  "EDITION",       0, 0 },+		{ "dateCaptured", "URLDATE",       0, 0 } 	};-	int n, ntypes = sizeof( origin ) / sizeof ( convert );-	int found, datefound, pos[5], date[4];+	int nparts = sizeof( parts ) / sizeof( parts[0] );+	int i, found, datefound, datepos[ NUM_DATE_TYPES ]; -	/* find all information to be outputted */-	found = -1;-	for ( n=0; n<ntypes; ++n ) {-		pos[n] = fields_find( f, origin[n].internal, level );-		if ( pos[n]!=-1 ) found = pos[n];-	}-	datefound = output_finddateissued( f, level, date );-	if ( found==-1 && datefound==-1 ) return;+	found     = convert_findallfields( f, parts, nparts, level );+	datefound = find_dateinfo( f, level, datepos );+	if ( !found && !datefound ) return; -	output_tab1( outptr, level, "<originInfo>\n" );-	output_fill2( outptr, increment_level(level,1), "issuance", f, pos[0], 1 );-	if ( datefound!=-1 ) output_dateissued( f, outptr, level, date ); -	for ( n=1; n<ntypes; n++ ) {-		if ( pos[n]==-1 ) continue;-		output_tab0( outptr, increment_level(level,1) );-		fprintf( outptr, "<%s", origin[n].mods );-		fprintf( outptr, ">" );-		if ( origin[n].code ) {-			fprintf( outptr, "\n" );-			output_fill4( outptr, increment_level(level,2), -				"placeTerm", "type", "text", f, pos[n], 1 );-			output_tab0( outptr, increment_level(level,1) );-		} else {-			fprintf( outptr, "%s", f->data[pos[n]].data );-			fields_setused( f, pos[n] );+	output_tag( outptr, lvl2indent(level), "originInfo", NULL, TAG_OPEN, TAG_NEWLINE, NULL );++	/* issuance must precede date */+	if ( parts[0].pos!=-1 )+		output_fil( outptr, lvl2indent(incr_level(level,1)), "issuance", f, parts[0].pos, TAG_OPENCLOSE, TAG_NEWLINE, NULL );++	/* date */+	if ( datefound )+		output_dateissued( f, outptr, level, datepos );++	/* rest of the originInfo elements */+	for ( i=1; i<nparts; i++ ) {++		/* skip missing originInfo elements */+		if ( parts[i].pos==-1 ) continue;++		/* normal originInfo element */+		if ( parts[i].code==0 ) {+			output_fil( outptr, lvl2indent(incr_level(level,1)), parts[i].mods, f, parts[i].pos, TAG_OPENCLOSE, TAG_NEWLINE, NULL ); 		}-		fprintf( outptr, "</%s>\n", origin[n].mods );++		/* originInfo with placeTerm info */+		else {+			output_tag( outptr, lvl2indent(incr_level(level,1)), parts[i].mods, NULL,            TAG_OPEN,      TAG_NEWLINE, NULL );+			output_fil( outptr, lvl2indent(incr_level(level,2)), "placeTerm",   f, parts[i].pos, TAG_OPENCLOSE, TAG_NEWLINE, "type", "text", NULL );+			output_tag( outptr, lvl2indent(incr_level(level,1)), parts[i].mods, NULL,            TAG_CLOSE,     TAG_NEWLINE, NULL );+		} 	}-	output_tab1( outptr, level, "</originInfo>\n" );++	output_tag( outptr, lvl2indent(level), "originInfo", NULL, TAG_CLOSE, TAG_NEWLINE, NULL ); } +/* output_language_core()+ *+ *      generates language output for tag="langauge" or tag="languageOfCataloging"+ *      if possible, outputs iso639-2b code for the language+ *+ * <language>+ *     <languageTerm type="text">xxx</languageTerm>+ * </language>+ *+ * <language>+ *     <languageTerm type="text">xxx</languageTerm>+ *     <languageTerm type="code" authority="iso639-2b">xxx</languageTerm>+ * </language>+ *+ */ static void output_language_core( fields *f, int n, FILE *outptr, char *tag, int level ) {-	newstr usetag; 	char *lang, *code;-	lang = fields_value( f, n, FIELDS_CHRP );++	lang = (char *) fields_value( f, n, FIELDS_CHRP ); 	code = iso639_2_from_language( lang );-	newstr_init( &usetag );-	newstr_addchar( &usetag, '<' );-	newstr_strcat( &usetag, tag );-	newstr_strcat( &usetag, ">\n" );-	output_tab1( outptr, level, usetag.data );-	output_fill4( outptr, increment_level(level,1),-		"languageTerm", "type", "text", f, n, 1 );++	output_tag( outptr, lvl2indent(level),               tag,            NULL, TAG_OPEN,      TAG_NEWLINE, NULL );+	output_tag( outptr, lvl2indent(incr_level(level,1)), "languageTerm", lang, TAG_OPENCLOSE, TAG_NEWLINE, "type", "text", NULL ); 	if ( code ) {-		output_tab6( outptr, increment_level(level,1),-			"languageTerm", "type", "code", "authority", "iso639-2b",-			code, 1 );+		output_tag( outptr, lvl2indent(incr_level(level,1)), "languageTerm", code, TAG_OPENCLOSE, TAG_NEWLINE, "type", "code", "authority", "iso639-2b", NULL ); 	}-	newstr_strcpy( &usetag, "</" );-	newstr_strcat( &usetag, tag );-	newstr_strcat( &usetag, ">\n" );-	output_tab1( outptr, level, usetag.data );-	newstr_free( &usetag );+	output_tag( outptr, lvl2indent(level),               tag,            NULL, TAG_CLOSE,     TAG_NEWLINE, NULL ); }  static void@@ -463,19 +535,29 @@ static void output_description( fields *f, FILE *outptr, int level ) {-	int n = fields_find( f, "DESCRIPTION", level );+	char *val;+	int n;++	n = fields_find( f, "DESCRIPTION", level ); 	if ( n!=-1 ) {-		output_tab1( outptr, level, "<physicalDescription>\n" );-		output_fill2( outptr, increment_level(level,1), "note", f, n, 1 );-		output_tab1( outptr, level, "</physicalDescription>\n" );+		val = ( char * ) fields_value( f, n, FIELDS_CHRP );+		output_tag( outptr, lvl2indent(level),               "physicalDescription", NULL, TAG_OPEN,      TAG_NEWLINE, NULL );+		output_tag( outptr, lvl2indent(incr_level(level,1)), "note",                val,  TAG_OPENCLOSE, TAG_NEWLINE, NULL );+		output_tag( outptr, lvl2indent(level),               "physicalDescription", NULL, TAG_CLOSE,     TAG_NEWLINE, NULL ); 	} }  static void output_toc( fields *f, FILE *outptr, int level ) {-	int n = fields_find( f, "CONTENTS", level );-	output_fill2( outptr, level, "tableOfContents", f, n, 1 );+	char *val;+	int n;++	n = fields_find( f, "CONTENTS", level );+	if ( n!=-1 ) {+		val = (char *) fields_value( f, n, FIELDS_CHRP );+		output_tag( outptr, lvl2indent(level), "tableOfContents", val, TAG_OPENCLOSE, TAG_NEWLINE, NULL );+	} }  /* detail output@@ -485,14 +567,13 @@  * <detail type="volume"><number>xxx</number></detail  */ static void-mods_output_detail( fields *f, FILE *outptr, int item, char *item_name,-		int level )+mods_output_detail( fields *f, FILE *outptr, int n, char *item_name, int level ) {-	if ( item==-1 ) return;-	output_tab0( outptr, increment_level( level, 1 ) );-	fprintf( outptr, "<detail type=\"%s\"><number>%s</number></detail>\n", -			item_name, f->data[item].data );-	fields_setused( f, item );+	if ( n!=-1 ) {+		output_tag( outptr, lvl2indent(incr_level(level,1)), "detail", NULL,  TAG_OPEN,      TAG_NONEWLINE, "type", item_name, NULL );+		output_fil( outptr, 0,                                "number", f, n,  TAG_OPENCLOSE, TAG_NONEWLINE, NULL );+		output_tag( outptr, 0,                                "detail", NULL,  TAG_CLOSE,     TAG_NEWLINE,   NULL );                       +	} }  @@ -504,27 +585,38 @@  * </extent>  */ static void-mods_output_extents( fields *f, FILE *outptr, int start, int end,-		int total, char *extype, int level )+mods_output_extents( fields *f, FILE *outptr, int start, int end, int total, char *extype, int level ) {-	output_tab0( outptr, increment_level(level,1) );-	fprintf( outptr, "<extent unit=\"%s\">\n", extype);-	output_fill2( outptr, increment_level(level,2), "start", f, start, 1 );-	output_fill2( outptr, increment_level(level,2), "end", f, end, 1 );-	output_fill2( outptr, increment_level(level,2), "total", f, total, 1 );-	output_tab1 ( outptr, increment_level(level,1), "</extent>\n" );+	char *val;++	output_tag( outptr, lvl2indent(incr_level(level,1)), "extent", NULL, TAG_OPEN, TAG_NEWLINE, "unit", extype, NULL );+	if ( start!=-1 ) {+		val = (char *) fields_value( f, start, FIELDS_CHRP );+		output_tag( outptr, lvl2indent(incr_level(level,2)), "start", val, TAG_OPENCLOSE, TAG_NEWLINE, NULL );+	}+	if ( end!=-1 ) {+		val = (char *) fields_value( f, end, FIELDS_CHRP );+		output_tag( outptr, lvl2indent(incr_level(level,2)), "end",   val, TAG_OPENCLOSE, TAG_NEWLINE, NULL );+	}+	if ( total!=-1 ) {+		val = (char *) fields_value( f, total, FIELDS_CHRP );+		output_tag( outptr, lvl2indent(incr_level(level,2)), "total", val, TAG_OPENCLOSE, TAG_NEWLINE, NULL );+	}+	output_tag( outptr, lvl2indent(incr_level(level,1)), "extent", NULL, TAG_CLOSE,     TAG_NEWLINE, NULL ); }  static void try_output_partheader( FILE *outptr, int wrote_header, int level ) {-	if ( !wrote_header ) output_tab1( outptr, level, "<part>\n" );+	if ( !wrote_header )+		output_tag( outptr, lvl2indent(level), "part", NULL, TAG_OPEN, TAG_NEWLINE, NULL ); }  static void try_output_partfooter( FILE *outptr, int wrote_header, int level ) {-	if ( wrote_header ) output_tab1( outptr, level, "</part>\n" );+	if ( wrote_header )+		output_tag( outptr, lvl2indent(level), "part", NULL, TAG_CLOSE, TAG_NEWLINE, NULL ); }  /* part date output@@ -535,33 +627,31 @@ static int output_partdate( fields *f, FILE *outptr, int level, int wrote_header ) {-	convert parts[3] = {-		{ "",	"PARTYEAR",                -1 },-		{ "",	"PARTMONTH",               -1 },-		{ "",	"PARTDAY",                 -1 },+	convert parts[] = {+		{ "",	"PARTDATE:YEAR",           0, 0 },+		{ "",	"PARTDATE:MONTH",          0, 0 },+		{ "",	"PARTDATE:DAY",            0, 0 }, 	}; 	int nparts = sizeof(parts)/sizeof(parts[0]); -	if ( !find_alltags( f, parts, nparts, level ) ) return 0;+	if ( !convert_findallfields( f, parts, nparts, level ) ) return 0;  	try_output_partheader( outptr, wrote_header, level );-	output_tab1( outptr, increment_level(level,1), "<date>" ); -	if ( parts[0].code!=-1 ) {-		fprintf( outptr, "%s", f->data[ parts[0].code ].data);-		fields_setused( f, parts[0].code );+	output_tag( outptr, lvl2indent(incr_level(level,1)), "date", NULL, TAG_OPEN, TAG_NONEWLINE, NULL );++	if ( parts[0].pos!=-1 ) {+		fprintf( outptr, "%s", (char *) fields_value( f, parts[0].pos, FIELDS_CHRP ) ); 	} else fprintf( outptr, "XXXX" ); -	if ( parts[1].code!=-1 ) {-		fprintf( outptr, "-%s", f->data[parts[1].code].data );-		fields_setused( f, parts[1].code );+	if ( parts[1].pos!=-1 ) {+		fprintf( outptr, "-%s", (char *) fields_value( f, parts[1].pos, FIELDS_CHRP ) ); 	} -	if ( parts[2].code!=-1 ) {-		if ( parts[1].code!=-1 ) fprintf( outptr, "-" );-		else fprintf( outptr, "-XX-" );-		fprintf( outptr, "%s", f->data[parts[2].code].data );-		fields_setused( f, parts[2].code );+	if ( parts[2].pos!=-1 ) {+		if ( parts[1].pos==-1 )+			fprintf( outptr, "-XX" );+		fprintf( outptr, "-%s", (char *) fields_value( f, parts[2].pos, FIELDS_CHRP ) ); 	}  	fprintf( outptr,"</date>\n");@@ -572,37 +662,32 @@ static int output_partpages( fields *f, FILE *outptr, int level, int wrote_header ) {-	convert parts[4] = {-		{ "",  "PAGESTART",                -1 },-		{ "",  "PAGEEND",                  -1 },-		{ "",  "PAGES",                    -1 },-		{ "",  "TOTALPAGES",               -1 }+	convert parts[] = {+		{ "",  "PAGES:START",              0, 0 },+		{ "",  "PAGES:STOP",               0, 0 },+		{ "",  "PAGES",                    0, 0 },+		{ "",  "PAGES:TOTAL",              0, 0 } 	}; 	int nparts = sizeof(parts)/sizeof(parts[0]); -	if ( !find_alltags( f, parts, nparts, level ) ) return 0;+	if ( !convert_findallfields( f, parts, nparts, level ) ) return 0;  	try_output_partheader( outptr, wrote_header, level ); -	/* If PAGESTART or PAGEEND are  undefined */-	if ( parts[0].code==-1 || parts[1].code==-1 ) {-		if ( parts[0].code!=-1 )-			mods_output_detail( f, outptr, parts[0].code,-				"page", level );-		if ( parts[1].code!=-1 )-			mods_output_detail( f, outptr, parts[1].code,-				"page", level );-		if ( parts[2].code!=-1 )-			mods_output_detail( f, outptr, parts[2].code,-				"page", level );-		if ( parts[3].code!=-1 )-			mods_output_extents( f, outptr, -1, -1,-					parts[3].code, "page", level );+	/* If PAGES:START or PAGES:STOP are undefined */+	if ( parts[0].pos==-1 || parts[1].pos==-1 ) {+		if ( parts[0].pos!=-1 )+			mods_output_detail( f, outptr, parts[0].pos, "page", level );+		if ( parts[1].pos!=-1 )+			mods_output_detail( f, outptr, parts[1].pos, "page", level );+		if ( parts[2].pos!=-1 )+			mods_output_detail( f, outptr, parts[2].pos, "page", level );+		if ( parts[3].pos!=-1 )+			mods_output_extents( f, outptr, -1, -1, parts[3].pos, "page", level ); 	}-	/* If both PAGESTART and PAGEEND are defined */+	/* If both PAGES:START and PAGES:STOP are defined */ 	else {-		mods_output_extents( f, outptr, parts[0].code, -			parts[1].code, parts[3].code, "page", level );+		mods_output_extents( f, outptr, parts[0].pos, parts[1].pos, parts[3].pos, "page", level ); 	}  	return 1;@@ -612,34 +697,32 @@ output_partelement( fields *f, FILE *outptr, int level, int wrote_header ) { 	convert parts[] = {-		{ "volume",          "VOLUME",          -1 },-		{ "section",         "SECTION",         -1 },-		{ "issue",           "ISSUE",           -1 },-		{ "number",          "NUMBER",          -1 },-		{ "publiclawnumber", "PUBLICLAWNUMBER", -1 },-		{ "session",         "SESSION",         -1 },-		{ "articlenumber",   "ARTICLENUMBER",   -1 },-		{ "part",            "PART",            -1 },-		{ "chapter",         "CHAPTER",         -1 },-		{ "report number",   "REPORTNUMBER",    -1 },+		{ "",                "NUMVOLUMES",      0, 0 },+		{ "volume",          "VOLUME",          0, 0 },+		{ "section",         "SECTION",         0, 0 },+		{ "issue",           "ISSUE",           0, 0 },+		{ "number",          "NUMBER",          0, 0 },+		{ "publiclawnumber", "PUBLICLAWNUMBER", 0, 0 },+		{ "session",         "SESSION",         0, 0 },+		{ "articlenumber",   "ARTICLENUMBER",   0, 0 },+		{ "part",            "PART",            0, 0 },+		{ "chapter",         "CHAPTER",         0, 0 },+		{ "report number",   "REPORTNUMBER",    0, 0 }, 	};-	int i, nparts = sizeof( parts ) / sizeof( convert ), n;+	int i, nparts = sizeof( parts ) / sizeof( convert ); -	n = fields_find( f, "NUMVOLUMES", level );-	if ( !find_alltags( f, parts, nparts, level ) && n==-1 ) return 0;+	if ( !convert_findallfields( f, parts, nparts, level ) ) return 0;+ 	try_output_partheader( outptr, wrote_header, level ); -	for ( i=0; i<nparts; ++i ) {-		if ( parts[i].code==-1 ) continue;-		mods_output_detail( f, outptr, parts[i].code, parts[i].mods,-				level );+	/* start loop at 1 to skip NUMVOLUMES */+	for ( i=1; i<nparts; ++i ) {+		if ( parts[i].pos==-1 ) continue;+		mods_output_detail( f, outptr, parts[i].pos, parts[i].mods, level ); 	} -	if ( n!=-1 ) {-		output_tab1( outptr, level, "<extent unit=\"volumes\">\n" );-		output_fill2( outptr, increment_level(level,1), "total", f, n, 1 );-		output_tab1( outptr, level, "</extent>\n" );-	}+	if ( parts[0].pos!=-1 )+		mods_output_extents( f, outptr, -1, -1, parts[0].pos, "volumes", level );  	return 1; }@@ -660,66 +743,78 @@ 	int n; 	n = fields_find( f, "LANGCATALOG", level ); 	if ( n!=-1 ) {-		output_tab1( outptr, level, "<recordInfo>\n" );-		output_language_core( f, n, outptr, "languageOfCataloging", increment_level(level,1) );-		output_tab1( outptr, level, "</recordInfo>\n" );+		output_tag( outptr, lvl2indent(level), "recordInfo", NULL, TAG_OPEN, TAG_NEWLINE, NULL );+		output_language_core( f, n, outptr, "languageOfCataloging", incr_level(level,1) );+		output_tag( outptr, lvl2indent(level), "recordInfo", NULL, TAG_CLOSE, TAG_NEWLINE, NULL ); 	} } +/* output_genre()+ *+ * <genre authority="marcgt">thesis</genre>+ * <genre>Diploma thesis</genre>+ */ static void output_genre( fields *f, FILE *outptr, int level ) {-	int i, ismarc, n;-	char *value;+	char *value, *attr, *attrvalue="marcgt";+	int i, n;+ 	n = fields_num( f ); 	for ( i=0; i<n; ++i ) { 		if ( fields_level( f, i ) != level ) continue;-		if ( !fields_match_tag( f, i, "GENRE" ) &&-		     !fields_match_tag( f, i, "NGENRE" ) )-			continue;+		if ( !fields_match_tag( f, i, "GENRE" ) && !fields_match_tag( f, i, "NGENRE" ) ) continue; 		value = fields_value( f, i, FIELDS_CHRP );-		if ( marc_findgenre( value )!=-1 ) ismarc = 1;-		else ismarc = 0;-		output_tab1( outptr, level, "<genre" );-		if ( ismarc ) -			fprintf( outptr, " authority=\"marcgt\"" );-		fprintf( outptr, ">%s</genre>\n", value );-		fields_setused( f, i );+		attr = ( marc_findgenre( value ) == -1 ) ? NULL : "authority";+		output_tag( outptr, lvl2indent(level), "genre", value, TAG_OPENCLOSE, TAG_NEWLINE, attr, attrvalue, NULL ); 	} } +/* output_resource()+ *+ * <typeOfResource>text</typeOfResource>+ */ static void-output_typeresource( fields *f, FILE *outptr, int level )+output_resource( fields *f, FILE *outptr, int level ) {-	int n, ismarc = 0; 	char *value;+	int n;+ 	n = fields_find( f, "RESOURCE", level ); 	if ( n!=-1 ) { 		value = fields_value( f, n, FIELDS_CHRP );-		if ( marc_findresource( value )!=-1 ) ismarc = 1;-		if ( !ismarc ) {-			fprintf( stderr, "Illegal typeofResource = '%s'\n", value );+		if ( marc_findresource( value )!=-1 ) {+			output_fil( outptr, lvl2indent(level), "typeOfResource", f, n, TAG_OPENCLOSE, TAG_NEWLINE, NULL ); 		} else {-			output_fill2( outptr, level, "typeOfResource", f, n, 1 );+			fprintf( stderr, "Illegal typeofResource = '%s'\n", value ); 		}-		fields_setused( f, n ); 	} }  static void output_type( fields *f, FILE *outptr, int level ) {-	int n = fields_find( f, "INTERNAL_TYPE", 0 );+	int n;++	/* silence warnings about INTERNAL_TYPE being unused */+	n = fields_find( f, "INTERNAL_TYPE", 0 ); 	if ( n!=-1 ) fields_setused( f, n );-	output_typeresource( f, outptr, level );++	output_resource( f, outptr, level ); 	output_genre( f, outptr, level ); } +/* output_abs()+ *+ * <abstract>xxxx</abstract>+ */ static void output_abs( fields *f, FILE *outptr, int level ) {-	int nabs = fields_find( f, "ABSTRACT", level );-	output_fill2( outptr, level, "abstract", f, nabs, 1 );+	int n;++	n = fields_find( f, "ABSTRACT", level );+	output_fil( outptr, lvl2indent(level), "abstract", f, n, TAG_OPENCLOSE, TAG_NEWLINE, NULL ); }  static void@@ -727,39 +822,52 @@ { 	int i, n; 	char *t;+ 	n = fields_num( f ); 	for ( i=0; i<n; ++i ) { 		if ( fields_level( f, i ) != level ) continue; 		t = fields_tag( f, i, FIELDS_CHRP_NOUSE ); 		if ( !strcasecmp( t, "NOTES" ) )-			output_fill2( outptr, level, "note", f, i, 1 );+			output_fil( outptr, lvl2indent(level), "note", f, i, TAG_OPENCLOSE, TAG_NEWLINE, NULL ); 		else if ( !strcasecmp( t, "PUBSTATE" ) )-			output_fill4( outptr, level, "note", "type", "publication status", f, i, 1 );+			output_fil( outptr, lvl2indent(level), "note", f, i, TAG_OPENCLOSE, TAG_NEWLINE, "type", "publication status", NULL ); 		else if ( !strcasecmp( t, "ANNOTE" ) )-			output_fill2( outptr, level, "bibtex-annote", f, i, 1 );+			output_fil( outptr, lvl2indent(level), "bibtex-annote", f, i, TAG_OPENCLOSE, TAG_NEWLINE, NULL ); 		else if ( !strcasecmp( t, "TIMESCITED" ) )-			output_fill4( outptr, level, "note", "type", "times cited", f, i, 1 );+			output_fil( outptr, lvl2indent(level), "note", f, i, TAG_OPENCLOSE, TAG_NEWLINE, "type", "times cited", NULL ); 		else if ( !strcasecmp( t, "ANNOTATION" ) )-			output_fill4( outptr, level, "note", "type", "annotation", f, i, 1 );+			output_fil( outptr, lvl2indent(level), "note", f, i, TAG_OPENCLOSE, TAG_NEWLINE, "type", "annotation", NULL ); 		else if ( !strcasecmp( t, "ADDENDUM" ) )-			output_fill4( outptr, level, "note", "type", "addendum", f, i, 1 );+			output_fil( outptr, lvl2indent(level), "note", f, i, TAG_OPENCLOSE, TAG_NEWLINE, "type", "addendum", NULL ); 		else if ( !strcasecmp( t, "BIBKEY" ) )-			output_fill4( outptr, level, "note", "type", "bibliography key", f, i, 1 );+			output_fil( outptr, lvl2indent(level), "note", f, i, TAG_OPENCLOSE, TAG_NEWLINE, "type", "bibliography key", NULL ); 	} } +/* output_key()+ *+ * <subject>+ *    <topic>xxxx</topic>+ * </subject>+ */ static void output_key( fields *f, FILE *outptr, int level ) { 	int i, n;+ 	n = fields_num( f ); 	for ( i=0; i<n; ++i ) { 		if ( fields_level( f, i ) != level ) continue; 		if ( !strcasecmp( f->tag[i].data, "KEYWORD" ) ) {-			output_tab1( outptr, level, "<subject>\n" );-			output_fill2( outptr, increment_level(level,1), "topic", f, i, 1 );-			output_tab1( outptr, level, "</subject>\n" );+			output_tag( outptr, lvl2indent(level),               "subject", NULL, TAG_OPEN,      TAG_NEWLINE, NULL );+			output_fil( outptr, lvl2indent(incr_level(level,1)), "topic",   f, i, TAG_OPENCLOSE, TAG_NEWLINE, NULL );+			output_tag( outptr, lvl2indent(level),               "subject", NULL, TAG_CLOSE,     TAG_NEWLINE, NULL ); 		}+		else if ( !strcasecmp( f->tag[i].data, "EPRINTCLASS" ) ) {+			output_tag( outptr, lvl2indent(level),               "subject", NULL, TAG_OPEN,      TAG_NEWLINE, NULL );+			output_fil( outptr, lvl2indent(incr_level(level,1)), "topic",   f, i, TAG_OPENCLOSE, TAG_NEWLINE, "class", "primary", NULL );+			output_tag( outptr, lvl2indent(level),               "subject", NULL, TAG_CLOSE,     TAG_NEWLINE, NULL );+		} 	} } @@ -767,89 +875,92 @@ output_sn( fields *f, FILE *outptr, int level ) { 	convert sn_types[] = {-		{ "isbn",      "ISBN",      0 },-		{ "isbn",      "ISBN13",    0 },-		{ "lccn",      "LCCN",      0 },-		{ "issn",      "ISSN",      0 },-		{ "citekey",   "REFNUM",    0 },-		{ "doi",       "DOI",       0 },-		{ "eid",       "EID",       0 },-		{ "eprint",    "EPRINT",    0 },-		{ "eprinttype","EPRINTTYPE",0 },-		{ "pubmed",    "PMID",      0 },-		{ "medline",   "MEDLINE",   0 },-		{ "pii",       "PII",       0 },-		{ "arXiv",     "ARXIV",     0 },-		{ "isi",       "ISIREFNUM", 0 },-		{ "accessnum", "ACCESSNUM", 0 },-		{ "jstor",     "JSTOR",     0 },-		{ "isrn",      "ISRN",      0 },+		{ "isbn",      "ISBN",      0, 0 },+		{ "isbn",      "ISBN13",    0, 0 },+		{ "lccn",      "LCCN",      0, 0 },+		{ "issn",      "ISSN",      0, 0 },+		{ "coden",     "CODEN",     0, 0 },+		{ "citekey",   "REFNUM",    0, 0 },+		{ "doi",       "DOI",       0, 0 },+		{ "eid",       "EID",       0, 0 },+		{ "eprint",    "EPRINT",    0, 0 },+		{ "eprinttype","EPRINTTYPE",0, 0 },+		{ "pubmed",    "PMID",      0, 0 },+		{ "MRnumber",  "MRNUMBER",  0, 0 },+		{ "medline",   "MEDLINE",   0, 0 },+		{ "pii",       "PII",       0, 0 },+		{ "pmc",       "PMC",       0, 0 },+		{ "arXiv",     "ARXIV",     0, 0 },+		{ "isi",       "ISIREFNUM", 0, 0 },+		{ "accessnum", "ACCESSNUM", 0, 0 },+		{ "jstor",     "JSTOR",     0, 0 },+		{ "isrn",      "ISRN",      0, 0 }, 	};-	int n, ntypes = sizeof( sn_types ) / sizeof( sn_types[0] );-	int found, i, nfields;+	int ntypes = sizeof( sn_types ) / sizeof( sn_types[0] );+	int i, n; -	found = fields_find ( f, "CALLNUMBER", level );-	output_fill2( outptr, level, "classification", f, found, 1 );+	/* output call number */+	n = fields_find( f, "CALLNUMBER", level );+	output_fil( outptr, lvl2indent(level), "classification", f, n, TAG_OPENCLOSE, TAG_NEWLINE, NULL ); -	for ( n=0; n<ntypes; ++n ) {-		found = fields_find( f, sn_types[n].internal, level );-		if ( found==-1 ) continue;-		output_tab0( outptr, level );-		fprintf( outptr, "<identifier type=\"%s\">%s</identifier>\n",-				sn_types[n].mods,-				f->data[found].data-		       );-		fields_setused( f, found );+	/* output specialized serialnumber */+	convert_findallfields( f, sn_types, ntypes, level );+	for ( i=0; i<ntypes; ++i ) {+		if ( sn_types[i].pos==-1 ) continue;+		output_fil( outptr, lvl2indent(level), "identifier", f, sn_types[i].pos, TAG_OPENCLOSE, TAG_NEWLINE, "type", sn_types[i].mods, NULL ); 	}-	nfields = fields_num( f );-	for ( i=0; i<nfields; ++i ) {++	/* output _all_ elements of type SERIALNUMBER */+	n = fields_num( f );+	for ( i=0; i<n; ++i ) { 		if ( f->level[i]!=level ) continue;-		if ( !strcasecmp( f->tag[i].data, "SERIALNUMBER" ) ) {-			output_tab0( outptr, level );-			fprintf( outptr, "<identifier type=\"%s\">%s</identifier>\n",-				"serial number", f->data[i].data );-			fields_setused( f, i );-		}+		if ( strcasecmp( f->tag[i].data, "SERIALNUMBER" ) ) continue;+		output_fil( outptr, lvl2indent(level), "identifier", f, i, TAG_OPENCLOSE, TAG_NEWLINE, "type", "serial number", NULL ); 	} } +/* output_url()+ *+ * <location>+ *     <url>URL</url>+ *     <url urlType="pdf">PDFLINK</url>+ *     <url displayLabel="Electronic full text" access="raw object">PDFLINK</url>+ *     <physicalLocation>LOCATION</physicalLocation>+ * </location>+ */ static void output_url( fields *f, FILE *outptr, int level ) {-	int location = fields_find( f, "LOCATION", level );-	int url = fields_find( f, "URL", level );+	int location   = fields_find( f, "LOCATION",   level );+	int url        = fields_find( f, "URL",        level ); 	int fileattach = fields_find( f, "FILEATTACH", level );-	int pdflink = fields_find( f, "PDFLINK", level );+	int pdflink    = fields_find( f, "PDFLINK",    level ); 	int i, n;+ 	if ( url==-1 && location==-1 && pdflink==-1 && fileattach==-1 ) return;-	output_tab1( outptr, level, "<location>\n" );+	output_tag( outptr, lvl2indent(level), "location", NULL, TAG_OPEN, TAG_NEWLINE, NULL );+ 	n = fields_num( f ); 	for ( i=0; i<n; ++i ) { 		if ( f->level[i]!=level ) continue;-		if ( !strcasecmp( f->tag[i].data, "URL" ) ) {-			output_fill2( outptr, increment_level(level,1), "url", f, i, 1 );-		}+		if ( strcasecmp( f->tag[i].data, "URL" ) ) continue;+		output_fil( outptr, lvl2indent(incr_level(level,1)), "url", f, i, TAG_OPENCLOSE, TAG_NEWLINE, NULL ); 	} 	for ( i=0; i<n; ++i ) { 		if ( f->level[i]!=level ) continue;-		if ( !strcasecmp( f->tag[i].data, "PDFLINK" ) ) {-			output_fill2( outptr, increment_level(level,1), "url",-				/*"urlType", "pdf",*/ f, i, 1 );-		}+		if ( strcasecmp( f->tag[i].data, "PDFLINK" ) ) continue;+/*		output_fil( outptr, lvl2indent(incr_level(level,1)), "url", f, i, TAG_OPENCLOSE, TAG_NEWLINE, "urlType", "pdf", NULL ); */+		output_fil( outptr, lvl2indent(incr_level(level,1)), "url", f, i, TAG_OPENCLOSE, TAG_NEWLINE, NULL ); 	} 	for ( i=0; i<n; ++i ) { 		if ( f->level[i]!=level ) continue;-		if ( !strcasecmp( f->tag[i].data, "FILEATTACH" ) ){-			output_tab0( outptr, increment_level(level,1) );-			fprintf( outptr, "<url displayLabel=\"Electronic full text\" access=\"raw object\">" );-			fprintf( outptr, "%s</url>\n", f->data[i].data );-			fields_setused( f, i );-		}+		if ( strcasecmp( f->tag[i].data, "FILEATTACH" ) ) continue;+		output_fil( outptr, lvl2indent(incr_level(level,1)), "url", f, i, TAG_OPENCLOSE, TAG_NEWLINE, "displayLabel", "Electronic full text", "access", "raw object", NULL ); 	} 	if ( location!=-1 )-		output_fill2( outptr, increment_level(level,1), "physicalLocation", f, -				location, 1 );-	output_tab1( outptr, level, "</location>\n" );+		output_fil( outptr, lvl2indent(incr_level(level,1)), "physicalLocation", f, location, TAG_OPENCLOSE, TAG_NEWLINE, NULL );++	output_tag( outptr, lvl2indent(level), "location", NULL, TAG_CLOSE, TAG_NEWLINE, NULL ); }  /* refnum should start with a non-number and not include spaces -- ignore this */@@ -913,20 +1024,16 @@ 	output_description( f, outptr, level );  	if ( level >= 0 && level < max ) {-		output_tab0( outptr, level );-		fprintf( outptr, "<relatedItem type=\"host\">\n" );-		output_citeparts( f, outptr, increment_level(level,1), max );-		output_tab0( outptr, level );-		fprintf( outptr, "</relatedItem>\n");+		output_tag( outptr, lvl2indent(level), "relatedItem", NULL, TAG_OPEN,  TAG_NEWLINE, "type", "host", NULL );+		output_citeparts( f, outptr, incr_level(level,1), max );+		output_tag( outptr, lvl2indent(level), "relatedItem", NULL, TAG_CLOSE, TAG_NEWLINE, NULL ); 	} 	/* Look for original item things */ 	orig_level = original_items( f, level ); 	if ( orig_level ) {-		output_tab0( outptr, level );-		fprintf( outptr, "<relatedItem type=\"original\">\n" );+		output_tag( outptr, lvl2indent(level), "relatedItem", NULL, TAG_OPEN,  TAG_NEWLINE, "type", "original", NULL ); 		output_citeparts( f, outptr, orig_level, max );-		output_tab0( outptr, level );-		fprintf( outptr, "</relatedItem>\n" );+		output_tag( outptr, lvl2indent(level), "relatedItem", NULL, TAG_CLOSE, TAG_NEWLINE, NULL ); 	} 	output_abs(        f, outptr, level ); 	output_notes(      f, outptr, level );@@ -957,7 +1064,7 @@ 		for ( i=0; i<n; ++i ) { 			if ( fields_level( f, i ) != 0 ) continue; 			tag = fields_tag( f, i, FIELDS_CHRP_NOUSE );-			if ( strncasecmp( tag, "AUTHOR", 6 ) ) continue;+			if ( strcasecmp( tag, "AUTHOR" ) && strcasecmp( tag, "AUTHOR:ASIS" ) && strcasecmp( tag, "AUTHOR:CORP" ) ) continue; 			value = fields_value( f, i, FIELDS_CHRP_NOUSE ); 			if ( nwritten==0 ) fprintf( stderr, "\tAuthor(s) (level=0):\n" ); 			fprintf( stderr, "\t\t'%s'\n", value );@@ -967,7 +1074,7 @@ 		for ( i=0; i<n; ++i ) { 			if ( fields_level( f, i ) != 0 ) continue; 			tag = fields_tag( f, i, FIELDS_CHRP_NOUSE );-			if ( strcasecmp( tag, "YEAR" ) && strcasecmp( tag, "PARTYEAR" ) ) continue;+			if ( strcasecmp( tag, "DATE:YEAR" ) && strcasecmp( tag, "PARTDATE:YEAR" ) ) continue; 			value = fields_value( f, i, FIELDS_CHRP_NOUSE ); 			if ( nwritten==0 ) fprintf( stderr, "\tYear(s) (level=0):\n" ); 			fprintf( stderr, "\t\t'%s'\n", value );@@ -996,12 +1103,12 @@ 	} } -void+static int modsout_write( fields *f, FILE *outptr, param *p, unsigned long numrefs ) { 	int max, dropkey; 	max = fields_maxlevel( f );-	dropkey = ( p->format_opts & MODSOUT_DROPKEY );+	dropkey = ( p->format_opts & BIBL_FORMAT_MODSOUT_DROPKEY );  	output_head( f, outptr, dropkey, numrefs ); 	output_citeparts( f, outptr, 0, max );@@ -1009,9 +1116,11 @@  	fprintf( outptr, "</mods>\n" ); 	fflush( outptr );++	return BIBL_OK; } -void+static void modsout_writeheader( FILE *outptr, param *p ) { 	if ( p->utf8bom ) utf8_writebom( outptr );@@ -1020,7 +1129,7 @@ 	fprintf(outptr,"<modsCollection xmlns=\"http://www.loc.gov/mods/v3\">\n"); } -void+static void modsout_writefooter( FILE *outptr ) { 	fprintf(outptr,"</modsCollection>\n");
− bibutils/modsout.h
@@ -1,27 +0,0 @@-/*- * modsout.h- *- * Copyright (c) Chris Putnam 2003-2014- *- * Source code released under the GPL version 2- *- */-#ifndef MODSOUT_H-#define MODSOUT_H--/* format-specific options */-#define MODSOUT_DROPKEY (2)--#include <stdio.h>-#include <stdlib.h>-#include "bibl.h"-#include "bibutils.h"--extern void modsout_writeheader( FILE *outptr, param *p );-extern void modsout_writefooter( FILE *outptr );-extern void modsout_write( fields *info, FILE *outptr,-	param *p, unsigned long numrefs );-extern void modsout_initparams( param *p, const char *progname );--#endif-
bibutils/modstypes.c view
@@ -1,7 +1,7 @@ /*  * modstypes.c  *- * Copyright (c) Chris Putnam 2004-2013+ * Copyright (c) Chris Putnam 2004-2017  *  * Source code released under the GPL version 2  *      @@ -16,19 +16,20 @@  *  */ convert identifier_types[] = {-                { "citekey", "REFNUM" },-                { "issn",    "ISSN"   },-                { "isbn",    "ISBN"   },-                { "doi",     "DOI"    },-                { "url",     "URL"    },-                { "uri",     "URL"    },-                { "pubmed",  "PUBMED" },-                { "medline", "MEDLINE" },-                { "pii",     "PII" },-                { "isi",     "ISIREFNUM" },-		{ "lccn",    "LCCN" },-                { "serial number", "SERIALNUMBER" },-                { "accessnum", "ACCESSNUM" }+	{ "citekey",       "REFNUM"    },+	{ "issn",          "ISSN"      },+	{ "isbn",          "ISBN"      },+	{ "doi",           "DOI"       },+	{ "url",           "URL"       },+	{ "uri",           "URL"       },+	{ "pubmed",        "PMID",     },+	{ "medline",       "MEDLINE"   },+	{ "pmc",           "PMC"       },+	{ "pii",           "PII"       },+	{ "isi",           "ISIREFNUM" },+	{ "lccn",          "LCCN"      },+	{ "serial number", "SERIALNUMBER" },+	{ "accessnum",     "ACCESSNUM"    } };  int nidentifier_types = sizeof( identifier_types ) / sizeof( identifier_types[0] );
bibutils/modstypes.h view
@@ -1,7 +1,7 @@ /*  * modstypes.h  *- * Copyright (c) Chris Putnam 2008-2013+ * Copyright (c) Chris Putnam 2008-2017  *  * Source code released under the GPL version 2  *@@ -9,8 +9,9 @@ #ifndef MODSTYPES_H #define MODSTYPES_H typedef struct convert {-        char *mods; /* old */-        char *internal; /* new */+	char *mods;     /* old */+	char *internal; /* new */+	int pos; 	int code; } convert; 
bibutils/name.c view
@@ -3,7 +3,7 @@  *  * mangle names w/ and w/o commas  *- * Copyright (c) Chris Putnam 2004-2014+ * Copyright (c) Chris Putnam 2004-2017  *  * Source code released under the GPL version 2  *@@ -14,9 +14,9 @@ #include "utf8.h" #include "unicode.h" #include "is_ws.h"-#include "newstr.h"+#include "str.h" #include "fields.h"-#include "list.h"+#include "slist.h" #include "intlist.h" #include "name.h" @@ -26,12 +26,12 @@  * to 'family suffix, given given  */ void-name_build_withcomma( newstr *s, char *p )+name_build_withcomma( str *s, char *p ) { 	int nseps = 0, nch; 	char *suffix, *stopat; -	newstr_empty( s );+	str_empty( s );  	suffix = strstr( p, "||" ); 	if ( suffix ) stopat = suffix;@@ -41,18 +41,18 @@ 		nch = 0; 		if ( nseps==1 ) { 			if ( suffix ) {-				newstr_addchar( s, ' ' );-				newstr_strcat( s, suffix+2 );+				str_addchar( s, ' ' );+				str_strcatc( s, suffix+2 ); 			}-			newstr_addchar( s, ',' );+			str_addchar( s, ',' ); 		}-		if ( nseps ) newstr_addchar( s, ' ' );+		if ( nseps ) str_addchar( s, ' ' ); 		while ( p!=stopat && *p!='|' ) {-			newstr_addchar( s, *p++ );+			str_addchar( s, *p++ ); 			nch++; 		} 		if ( p!=stopat && *p=='|' ) p++;-		if ( nseps!=0 && nch==1 ) newstr_addchar( s, '.' );+		if ( nseps!=0 && nch==1 ) str_addchar( s, '.' ); 		nseps++; 	} }@@ -63,14 +63,14 @@  * of name lists.  */ int-name_findetal( list *tokens )+name_findetal( slist *tokens ) {-	newstr *s1, *s2;+	str *s1, *s2;  	if ( tokens->n==0 ) return 0;  	/* ...check last entry for full 'et al.' or variant */-	s2 = list_get( tokens, tokens->n - 1 );+	s2 = slist_str( tokens, tokens->n - 1 ); 	if ( !strcasecmp( s2->data, "et alia" ) || 	     !strcasecmp( s2->data, "et al." )  || 	     !strcasecmp( s2->data, "et al.," )  ||@@ -84,7 +84,7 @@ 	if ( tokens->n==1 ) return 0;  	/* ...check last two entries for full 'et' and 'al.' */-	s1 = list_get( tokens, tokens->n - 2 );+	s1 = slist_str( tokens, tokens->n - 2 ); 	if ( !strcasecmp( s1->data, "et" ) ) { 		if ( !strcasecmp( s2->data, "alia" ) || 		     !strcasecmp( s2->data, "al." )  ||@@ -134,13 +134,13 @@ }  static int-has_suffix( list *tokens, int begin, int end, int *suffixpos )+has_suffix( slist *tokens, int begin, int end, int *suffixpos ) { 	int i, ret;-	newstr *s;+	str *s;  	/* ...check last element, e.g. "H. F. Author, Sr." */-	s = list_get( tokens, end - 1 );+	s = slist_str( tokens, end - 1 ); 	ret = identify_suffix( s->data ); 	if ( ret ) { 		*suffixpos = end - 1;@@ -149,9 +149,9 @@  	/* ...try to find one after a comma, e.g. "Author, Sr., H. F." */ 	for ( i=begin; i<end-1; ++i ) {-		s = list_get( tokens, i );+		s = slist_str( tokens, i ); 		if ( s->len && s->data[ s->len - 1 ]==',' ) {-			s = list_get( tokens, i+1 );+			s = slist_str( tokens, i+1 ); 			ret = identify_suffix( s->data ); 			if ( ret ) { 				*suffixpos = i+1;@@ -164,7 +164,7 @@ }  static int-add_given_split( newstr *name, newstr *s )+add_given_split( str *name, str *s ) { 	unsigned int unicode_char; 	unsigned int pos = 0;@@ -174,49 +174,49 @@ 		if ( is_ws( (char) unicode_char ) ) continue; 		else if ( unicode_char==(unsigned int)'.' ) { 			if ( s->data[pos]=='-' ) {-				newstr_strcat( name, ".-" );+				str_strcatc( name, ".-" ); 				pos += 1; 				unicode_char = utf8_decode( s->data, &pos ); 				utf8_encode_str( unicode_char, utf8s );-				newstr_strcat( name, utf8s );-				newstr_addchar( name, '.' );+				str_strcatc( name, utf8s );+				str_addchar( name, '.' ); 			} 		} else if ( unicode_char==(unsigned int)'-' ) {-			newstr_strcat( name, ".-" );+			str_strcatc( name, ".-" ); 			unicode_char = utf8_decode( s->data, &pos ); 			utf8_encode_str( unicode_char, utf8s );-			newstr_strcat( name, utf8s );-			newstr_addchar( name, '.' );+			str_strcatc( name, utf8s );+			str_addchar( name, '.' ); 		} else if ( unicode_char==(unsigned int)',' ) { /* nothing */ 		} else {-			newstr_addchar( name, '|' );+			str_addchar( name, '|' ); 			utf8_encode_str( unicode_char, utf8s );-			newstr_strcat( name, utf8s );+			str_strcatc( name, utf8s ); 		} 	} 	return 1; }  static unsigned char-token_has_no_upper( list *tokens, int n )+token_has_no_upper( slist *tokens, int n ) { 	unsigned short m;-	newstr *s;-	s = list_get( tokens, n );-	m = unicode_utf8_classify_newstr( s );+	str *s;+	s = slist_str( tokens, n );+	m = unicode_utf8_classify_str( s ); 	if ( m & UNICODE_UPPER ) return 0; 	else return 1; }  static unsigned char-token_has_upper( list *tokens, int n )+token_has_upper( slist *tokens, int n ) { 	if ( token_has_no_upper( tokens, n ) ) return 0; 	else return 1; }  static int-name_multielement_nocomma( intlist *given, intlist *family, list *tokens, int begin, int end, int suffixpos )+name_multielement_nocomma( intlist *given, intlist *family, slist *tokens, int begin, int end, int suffixpos ) { 	int family_start, family_end; 	int i, n;@@ -253,9 +253,9 @@ }  static int-name_multielement_comma( intlist *given, intlist *family, list *tokens, int begin, int end, int comma, int suffixpos )+name_multielement_comma( intlist *given, intlist *family, slist *tokens, int begin, int end, int comma, int suffixpos ) {-	newstr *s;+	str *s; 	int i;  	/* ...family names */@@ -263,8 +263,8 @@ 		if ( i==suffixpos ) continue; 		intlist_add( family, i ); 	}-	s = list_get( tokens, comma );-	newstr_trimend( s, 1 ); /* remove comma */+	s = slist_str( tokens, comma );+	str_trimend( s, 1 ); /* remove comma */ 	intlist_add( family, comma );  	/* ...given names */@@ -277,26 +277,26 @@ }  static int-name_mutlielement_build( newstr *name, intlist *given, intlist *family, list *tokens )+name_mutlielement_build( str *name, intlist *given, intlist *family, slist *tokens ) { 	unsigned short case_given = 0, case_family = 0, should_split = 0;-	newstr *s;+	str *s; 	int i, m;  	/* ...copy and analyze family name */ 	for ( i=0; i<family->n; ++i ) { 		m = intlist_get( family, i );-		s = list_get( tokens, m );-		if ( i ) newstr_addchar( name, ' '  );-		newstr_newstrcat( name, s );-		case_family |= unicode_utf8_classify_newstr( s );+		s = slist_str( tokens, m );+		if ( i ) str_addchar( name, ' '  );+		str_strcat( name, s );+		case_family |= unicode_utf8_classify_str( s ); 	}  	/* ...check given name case */ 	for ( i=0; i<given->n; ++i ) { 		m = intlist_get( given, i );-		s = list_get( tokens, m );-		case_given |= unicode_utf8_classify_newstr( s );+		s = slist_str( tokens, m );+		case_given |= unicode_utf8_classify_str( s ); 	}  	if ( ( ( case_family & UNICODE_MIXEDCASE ) == UNICODE_MIXEDCASE ) &&@@ -306,35 +306,35 @@  	for ( i=0; i<given->n; ++i ) { 		m = intlist_get( given, i );-		s = list_get( tokens, m );+		s = slist_str( tokens, m ); 		if ( !should_split ) {-			newstr_addchar( name, '|' );-			newstr_newstrcat( name, s );+			str_addchar( name, '|' );+			str_strcat( name, s ); 		} else add_given_split( name, s ); 	} 	return 1; }  static int-name_construct_multi( newstr *outname, list *tokens, int begin, int end )+name_construct_multi( str *outname, slist *tokens, int begin, int end ) { 	int i, suffix, suffixpos=-1, comma=-1; 	intlist given, family;-	newstr *s;+	str *s;  	intlist_init( &family ); 	intlist_init( &given ); -	newstr_empty( outname );+	str_empty( outname );  	suffix = has_suffix( tokens, begin, end, &suffixpos );  	for ( i=begin; i<end && comma==-1; i++ ) { 		if ( i==suffixpos ) continue;-		s = list_get( tokens, i );+		s = slist_str( tokens, i ); 		if ( s->data[ s->len -1 ] == ',' ) { 			if ( suffix && i==suffixpos-1 && !(suffix&WITHCOMMA) )-				newstr_trimend( s, 1 );+				str_trimend( s, 1 ); 			else 				comma = i; 		}@@ -348,10 +348,10 @@ 	name_mutlielement_build( outname, &given, &family, tokens );  	if ( suffix ) {-		if ( suffix & JUNIOR ) newstr_strcat( outname, "||Jr." );-		if ( suffix & SENIOR ) newstr_strcat( outname, "||Sr." );-		if ( suffix & THIRD  ) newstr_strcat( outname, "||III" );-		if ( suffix & FOURTH ) newstr_strcat( outname, "||IV"  );+		if ( suffix & JUNIOR ) str_strcatc( outname, "||Jr." );+		if ( suffix & SENIOR ) str_strcatc( outname, "||Sr." );+		if ( suffix & THIRD  ) str_strcatc( outname, "||III" );+		if ( suffix & FOURTH ) str_strcatc( outname, "||IV"  ); 	}  	intlist_free( &given );@@ -361,18 +361,18 @@ }  int-name_addmultielement( fields *info, char *tag, list *tokens, int begin, int end, int level )+name_addmultielement( fields *info, char *tag, slist *tokens, int begin, int end, int level ) { 	int status, ok = 1;-	newstr name;+	str name; -	newstr_init( &name );+	str_init( &name );  	name_construct_multi( &name, tokens, begin, end );-	status = fields_add( info, tag, name.data, level );+	status = fields_add_can_dup( info, tag, name.data, level ); 	if ( status!=FIELDS_OK ) ok = 0; -	newstr_free( &name );+	str_free( &name );  	return ok; }@@ -388,14 +388,14 @@ name_addsingleelement( fields *info, char *tag, char *name, int level, int corp ) { 	int status, ok = 1;-	newstr outtag;-	newstr_init( &outtag );-	newstr_strcpy( &outtag, tag );-	if ( !corp ) newstr_strcat( &outtag, ":ASIS" );-	else newstr_strcat( &outtag, ":CORP" );-	status = fields_add( info, outtag.data, name, level );+	str outtag;+	str_init( &outtag );+	str_strcpyc( &outtag, tag );+	if ( !corp ) str_strcatc( &outtag, ":ASIS" );+	else str_strcatc( &outtag, ":CORP" );+	status = fields_add_can_dup( info, outtag.data, name, level ); 	if ( status!=FIELDS_OK ) ok = 0;-	newstr_free( &outtag );+	str_free( &outtag ); 	return ok; } @@ -409,31 +409,31 @@  * Returns 3 on ok and name in corps list  */ int-name_parse( newstr *outname, newstr *inname, list *asis, list *corps )+name_parse( str *outname, str *inname, slist *asis, slist *corps ) {-	list tokens;+	slist tokens; 	int ret = 1; -	newstr_empty( outname );+	str_empty( outname ); 	if ( !inname || !inname->len ) return ret; -	list_init( &tokens );+	slist_init( &tokens ); -	if ( asis && list_find( asis, inname->data ) !=-1 ) {-		newstr_newstrcpy( outname, inname );+	if ( asis && slist_find( asis, inname ) !=-1 ) {+		str_strcpy( outname, inname ); 		ret = 2; 		goto out;-	} else if ( corps && list_find( corps, inname->data ) != -1 ) {-		newstr_newstrcpy( outname, inname );+	} else if ( corps && slist_find( corps, inname ) != -1 ) {+		str_strcpy( outname, inname ); 		ret = 3; 		goto out; 	} -	newstr_findreplace( inname, ",", ", " );-	list_tokenize( &tokens, inname, " ", 1 );+	str_findreplace( inname, ",", ", " );+	slist_tokenize( &tokens, inname, " ", 1 );  	if ( tokens.n==1 ) {-		newstr_newstrcpy( outname, inname );+		str_strcpy( outname, inname ); 		ret = 2; 	} else { 		name_construct_multi( outname, &tokens, 0, tokens.n );@@ -442,17 +442,17 @@  out: -	list_free( &tokens );+	slist_free( &tokens );  	return ret; }  static char *-name_copy( newstr *name, char *p )+name_copy( str *name, char *p ) { 	char *start, *end, *q; -	newstr_empty( name );+	str_empty( name );  	start = p = skip_ws( p ); @@ -465,7 +465,7 @@ 	if ( *p=='|' ) p++;  	for ( q=start; q<=end; q++ )-		newstr_addchar( name, *q );+		str_addchar( name, *q );  	return p; }@@ -486,16 +486,16 @@  * "Author, H. F."  */ int-name_add( fields *info, char *tag, char *q, int level, list *asis, list *corps )+name_add( fields *info, char *tag, char *q, int level, slist *asis, slist *corps ) { 	int ok, status, nametype, ret = 1;-	newstr inname, outname;-	list tokens;+	str inname, outname;+	slist tokens;  	if ( !q ) return 0; -	list_init( &tokens );-	newstrs_init( &inname, &outname, NULL );+	slist_init( &tokens );+	strs_init( &inname, &outname, NULL );  	while ( *q ) { @@ -505,7 +505,7 @@ 		if ( !nametype ) { ret = 0; goto out; }  		if ( nametype==1 ) {-			status = fields_add( info, tag, outname.data, level );+			status = fields_add_can_dup( info, tag, outname.data, level ); 			ok = ( status==FIELDS_OK ) ? 1 : 0; 		} 		else if ( nametype==2 )@@ -518,8 +518,8 @@ 	}  out:-	newstrs_free( &inname, &outname, NULL );-	list_free( &tokens );+	strs_free( &inname, &outname, NULL );+	slist_free( &tokens );  	return ret; }
bibutils/name.h view
@@ -3,7 +3,7 @@  *  * mangle names w/ and w/o commas  *- * Copyright (c) Chris Putnam 2004-2014+ * Copyright (c) Chris Putnam 2004-2017  *  * Source code released under the GPL version 2  *@@ -11,16 +11,16 @@ #ifndef NAME_H #define NAME_H -#include "newstr.h"-#include "list.h"+#include "str.h"+#include "slist.h" #include "fields.h" -extern int  name_add( fields *info, char *tag, char *q, int level, list *asis, list *corps );-extern void name_build_withcomma( newstr *s, char *p );-extern int  name_parse( newstr *outname, newstr *inname, list *asis, list *corps );+extern int  name_add( fields *info, char *tag, char *q, int level, slist *asis, slist *corps );+extern void name_build_withcomma( str *s, char *p );+extern int  name_parse( str *outname, str *inname, slist *asis, slist *corps ); extern int  name_addsingleelement( fields *info, char *tag, char *name, int level, int corp );-extern int  name_addmultielement( fields *info, char *tag, list *tokens, int begin, int end, int level );-extern int  name_findetal( list *tokens );+extern int  name_addmultielement( fields *info, char *tag, slist *tokens, int begin, int end, int level );+extern int  name_findetal( slist *tokens );  #endif 
+ bibutils/nbibin.c view
@@ -0,0 +1,505 @@+/*+ * nbibin.c+ *+ * Copyright (c) Chris Putnam 2016-2017+ *+ * Source code released under the GPL version 2+ *+ */+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <ctype.h>+#include "is_ws.h"+#include "str.h"+#include "str_conv.h"+#include "fields.h"+#include "name.h"+#include "title.h"+#include "url.h"+#include "serialno.h"+#include "reftypes.h"+#include "bibformats.h"+#include "generic.h"++extern variants nbib_all[];+extern int nbib_nall;++/*****************************************************+ PUBLIC: void nbib_initparams()+*****************************************************/++static int nbib_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset );+static int nbib_processf( fields *nbib, char *p, char *filename, long nref, param *pm );+static int nbib_typef( fields *nbib, char *filename, int nref, param *p );+static int nbib_convertf( fields *nbib, fields *info, int reftype, param *p );++void+nbibin_initparams( param *p, const char *progname )+{+	p->readformat       = BIBL_NBIBIN;+	p->charsetin        = BIBL_CHARSET_DEFAULT;+	p->charsetin_src    = BIBL_SRC_DEFAULT;+	p->latexin          = 0;+	p->xmlin            = 0;+	p->utf8in           = 0;+	p->nosplittitle     = 0;+	p->verbose          = 0;+	p->addcount         = 0;+	p->output_raw       = 0;++	p->readf    = nbib_readf;+	p->processf = nbib_processf;+	p->cleanf   = NULL;+	p->typef    = nbib_typef;+	p->convertf = nbib_convertf;+	p->all      = nbib_all;+	p->nall     = nbib_nall;++	slist_init( &(p->asis) );+	slist_init( &(p->corps) );++	if ( !progname ) p->progname = NULL;+	else p->progname = strdup( progname );+}++/*****************************************************+ PUBLIC: int nbib_readf()+*****************************************************/++/* RIS definition of a tag is strict:+    character 1 = uppercase alphabetic character+    character 2 = uppercase alphabetic character+    character 3 = character or space (ansi 32)+    character 4 = character or space (ansi 32)+    character 5 = dash (ansi 45)+    character 6 = space (ansi 32)+*/+static int+is_upperchar( char c )+{+	if ( c>='A' && c<='Z' ) return 1;+	else return 0;+}++static int+is_upperchar_space( char c )+{+	if ( c==' ' ) return 1;+	if ( c>='A' && c<='Z' ) return 1;+	else return 0;+}++static int+nbib_istag( char *buf )+{+	if ( !is_upperchar( buf[0] ) ) return 0;+	if ( !is_upperchar( buf[1] ) ) return 0;+	if ( !is_upperchar_space( buf[2] ) ) return 0;+	if ( !is_upperchar_space( buf[3] ) ) return 0;+	if (buf[4]!='-') return 0;+	if (buf[5]!=' ') return 0;+	return 1;+}++static int+readmore( FILE *fp, char *buf, int bufsize, int *bufpos, str *line )+{+	if ( line->len ) return 1;+	else return str_fget( fp, buf, bufsize, bufpos, line );+}++static int+skip_utf8_bom( str *line, int *fcharset )+{+	unsigned char *up;++	if ( line->len < 3 ) return 0;++	up = ( unsigned char *) str_cstr( line );+	if ( up[0]==0xEF && up[1]==0xBB && up[2]==0xBF ) {+		*fcharset = CHARSET_UNICODE;+		return 3;+	}++	return 0;+}++static int+nbib_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset )+{+	int n, haveref = 0, inref = 0, readtoofar = 0;+	char *p;++	*fcharset = CHARSET_UNKNOWN;++	while ( !haveref && readmore( fp, buf, bufsize, bufpos, line ) ) {++		/* ...references are terminated by an empty line */+		if ( !line->data || line->len==0 ) {+			if ( reference->len ) haveref = 1;+			continue;+		}++		/* ...recognize and skip over UTF8 BOM */+		n = skip_utf8_bom( line, fcharset );+		p = &( line->data[n] );++		/* Each reference starts with 'PMID- ' && ends with blank line */+		if ( strncmp(p,"PMID- ",6)==0 ) {+			if ( !inref ) {+				inref = 1;+			} else {+				/* we've read too far.... */+				readtoofar = 1;+				inref = 0;+			}+		}+		if ( nbib_istag( p ) ) {+			if ( !inref ) {+				fprintf(stderr,"Warning.  Tagged line not "+					"in properly started reference.\n");+				fprintf(stderr,"Ignored: '%s'\n", p );+			} else if ( !strncmp(p,"ER  -",5) ) {+				inref = 0;+			} else {+				str_addchar( reference, '\n' );+				str_strcatc( reference, p );+			}+		}+		/* not a tag, but we'll append to last values ...*/+		else if ( inref && strlen( p ) >= 6 ) {+			str_strcatc( reference, p+5 );+		}+		if ( !readtoofar ) str_empty( line );+	}+	if ( inref ) haveref = 1;+	return haveref;+}++/*****************************************************+ PUBLIC: int nbib_processf()+*****************************************************/++static char*+process_line2( str *tag, str *data, char *p )+{+	while ( *p==' ' || *p=='\t' ) p++;+	while ( *p && *p!='\r' && *p!='\n' )+		str_addchar( data, *p++ );+	while ( *p=='\r' || *p=='\n' ) p++;+	return p;+}++static char*+process_line( str *tag, str *data, char *p )+{+	int i;++	i = 0;+	while ( i<6 && *p ) {+		if ( *p!=' ' && *p!='-' ) str_addchar( tag, *p );+		p++;+		i++;+	}+	while ( *p==' ' || *p=='\t' ) p++;+	while ( *p && *p!='\r' && *p!='\n' )+		str_addchar( data, *p++ );+	str_trimendingws( data );+	while ( *p=='\n' || *p=='\r' ) p++;+	return p;+}++static int+nbib_processf( fields *nbib, char *p, char *filename, long nref, param *pm )+{+	str tag, data;+	int status, n;++	strs_init( &tag, &data, NULL );++	while ( *p ) {+		if ( nbib_istag( p ) )+			p = process_line( &tag, &data, p );+		/* no anonymous fields allowed */+		if ( str_has_value( &tag ) ) {+			status = fields_add( nbib, str_cstr( &tag ), str_cstr( &data ), 0 );+			if ( status!=FIELDS_OK ) return 0;+		} else {+			p = process_line2( &tag, &data, p );+			n = fields_num( nbib );+			if ( data.len && n>0 ) {+				str *od;+				od = fields_value( nbib, n-1, FIELDS_STRP );+				str_addchar( od, ' ' );+				str_strcat( od, &data );+			}+		}+		strs_empty( &tag, &data, NULL );+	}++	strs_free( &tag, &data, NULL );+	return 1;+}++/*****************************************************+ PUBLIC: int nbib_typef()+*****************************************************/++/*+ * PT  - Case Reports+ * PT  - Journal Article+ * PT  - Research Support, N.I.H., Extramural+ * PT  - Review+ */+static int+nbib_typef( fields *nbib, char *filename, int nref, param *p )+{+	int reftype, nrefname, is_default;+	char *typename, *refname = "";+	vplist_index i;+	vplist a;++	nrefname  = fields_find( nbib, "PMID", LEVEL_MAIN );+	if ( nrefname!=-1 ) refname = fields_value( nbib, nrefname, FIELDS_CHRP_NOUSE );++	vplist_init( &a );++	fields_findv_each( nbib, LEVEL_MAIN, FIELDS_CHRP_NOUSE, &a, "PT" );+	is_default = 1;+	for ( i=0; i<a.n; ++i ) {+		typename = vplist_get( &a, i );+		reftype  = get_reftype( typename, nref, p->progname, p->all, p->nall, refname, &is_default, REFTYPE_SILENT );+		if ( !is_default ) break;+	}++	if ( a.n==0 )+		reftype = get_reftype( "", nref, p->progname, p->all, p->nall, refname, &is_default, REFTYPE_CHATTY );+	else if ( is_default ) {+                if ( p->progname ) fprintf( stderr, "%s: ", p->progname );+                fprintf( stderr, "Did not recognize type of refnum %d (%s).\n"+                        "\tDefaulting to %s.\n", nref, refname, p->all[0].type );+	}++	vplist_free( &a );++	return reftype;+}++/*****************************************************+ PUBLIC: int nbib_convertf()+*****************************************************/++/* PB  - 2016 May 7 */++static int+nbibin_date( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	int fstatus, status = BIBL_OK;+	str s;+	char *p;++	p = str_cstr( invalue );+	if ( !p ) return status;++	str_init( &s );++	/* ...handle year */+		while ( *p && !is_ws( *p ) ) {+			str_addchar( &s, *p );+			p++;+		}++		if ( str_memerr( &s ) ) {+			status = BIBL_ERR_MEMERR;+			goto out;+		}++		if ( str_has_value( &s ) ) {+			fstatus = fields_add( bibout, "DATE:YEAR", str_cstr( &s ), LEVEL_MAIN );+			if ( fstatus!=FIELDS_OK ) {+				status = BIBL_ERR_MEMERR;+				goto out;+			}+		}++	/* ...handle month */+		str_empty( &s );+		while ( is_ws( *p ) ) p++;+		while ( *p && !is_ws( *p ) ) {+			str_addchar( &s, *p );+			p++;+		}++		if ( str_memerr( &s ) ) {+			status = BIBL_ERR_MEMERR;+			goto out;+		}++		if ( str_has_value( &s ) ) {+			fstatus = fields_add( bibout, "DATE:MONTH", str_cstr( &s ), LEVEL_MAIN );+			if ( fstatus!=FIELDS_OK ) {+				status = BIBL_ERR_MEMERR;+				goto out;+			}+		}++	/* ...handle day */+		str_empty( &s );+		while ( is_ws( *p ) ) p++;+		while ( *p && !is_ws( *p ) ) {+			str_addchar( &s, *p );+			p++;+		}++		if ( str_memerr( &s ) ) {+			status = BIBL_ERR_MEMERR;+			goto out;+		}++		if ( str_has_value( &s ) ) {+			fstatus = fields_add( bibout, "DATE:DAY", str_cstr( &s ), LEVEL_MAIN );+			if ( fstatus!=FIELDS_OK ) {+				status = BIBL_ERR_MEMERR;+				goto out;+			}+		}++out:+	str_free( &s );++	return status;+}++/* the LID and AID fields that can be doi's or pii's */+static int+nbibin_doi( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	int fstatus, sstatus, status = BIBL_OK;+	char *id, *type, *usetag="";+	slist tokens;++	slist_init( &tokens );++	sstatus = slist_tokenize( &tokens, invalue, " ", 1 );+	if ( sstatus!=SLIST_OK ) {+		status = BIBL_ERR_MEMERR;+		goto out;+	}++	if ( tokens.n == 2 ) {+		id   = slist_cstr( &tokens, 0 );+		type = slist_cstr( &tokens, 1 );+		if ( !strcmp( type, "[doi]" ) ) usetag = "DOI";+		else if ( !strcmp( type, "[pii]" ) ) usetag = "PII";+		if ( strlen( outtag ) > 0 ) {+			fstatus = fields_add( bibout, usetag, id, LEVEL_MAIN );+			if ( fstatus!=FIELDS_OK ) {+				status = BIBL_ERR_MEMERR;+				goto out;+			}+		}+	}+out:+	slist_free( &tokens );+	return status;+}++static int+nbibin_pages( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout )+{+	int fstatus, status = BIBL_OK;+	str sp, tmp, ep;+	char *p;+	int i;++	p = str_cstr( invalue );+	if ( !p ) return BIBL_OK;++	strs_init( &sp, &tmp, &ep, NULL );++	while ( *p && *p!='-' ) {+		str_addchar( &sp, *p );+		p++;+	}++	if ( str_memerr( &sp ) ) {+		status = BIBL_ERR_MEMERR;+		goto out;+	}++	while ( *p=='-' ) p++;++	while ( *p ) {+		str_addchar( &tmp, *p );+		p++;+	}++	if ( sp.len ) {+		fstatus = fields_add( bibout, "PAGES:START", str_cstr( &sp ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) {+			status = BIBL_ERR_MEMERR;+			goto out;+		}+	}++	if ( tmp.len ) {+		for ( i=0; i<sp.len - tmp.len; ++i )+			str_addchar( &ep, sp.data[i] );+		str_strcat( &ep, &tmp );++		fstatus = fields_add( bibout, "PAGES:STOP", str_cstr( &ep ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) {+			status = BIBL_ERR_MEMERR;+			goto out;+		}+	}+out:+	strs_free( &sp, &tmp, &ep, NULL );+	return status;+}++static void+nbib_report_notag( param *p, char *tag )+{+	if ( p->verbose && strcmp( tag, "TY" ) ) {+		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );+		fprintf( stderr, "Did not identify NBIB tag '%s'\n", tag );+	}+}++static int+nbib_convertf( fields *bibin, fields *bibout, int reftype, param *p )+{+	static int (*convertfns[NUM_REFTYPES])(fields *, int i, str *, str *, int, param *, char *, fields *) = {+		[ 0 ... NUM_REFTYPES-1 ] = generic_null,+		[ SIMPLE       ] = generic_simple,+		[ TITLE        ] = generic_title,+		[ PERSON       ] = generic_person,+		[ SKIP         ] = generic_skip,+		[ DATE         ] = nbibin_date,+		[ PAGES        ] = nbibin_pages,+		[ DOI          ] = nbibin_doi,+        };+	int process, level, i, nfields, status = BIBL_OK;+	str *intag, *invalue;+	char *outtag;++	nfields = fields_num( bibin );++	for ( i=0; i<nfields; ++i ) {+		intag = fields_tag( bibin, i, FIELDS_STRP );+		if ( !translate_oldtag( intag->data, reftype, p->all, p->nall, &process, &level, &outtag ) ) {+			nbib_report_notag( p, intag->data );+			continue;+		}+		invalue = fields_value( bibin, i, FIELDS_STRP );++		status = convertfns[ process ] ( bibin, i, intag, invalue, level, p, outtag, bibout );+		if ( status!=BIBL_OK ) return status;+	}++	if ( status==BIBL_OK && p->verbose ) fields_report( bibout, stderr );++	return status;+}
+ bibutils/nbibtypes.c view
@@ -0,0 +1,68 @@+/*+ * nbibtypes.c+ *+ * Copyright (c) Chris Putnam 2016-2017+ *+ * Program and source code released under the GPL version 2+ *+ */+#include <stdio.h>+#include <string.h>+#include "is_ws.h"+#include "fields.h"+#include "reftypes.h"++static lookups article[] = {+	{ "PMID",   "PMID",               SIMPLE, LEVEL_MAIN },+	{ "OWN",    "",                   SKIP,   LEVEL_MAIN },+	{ "STAT",   "",                   SKIP,   LEVEL_MAIN },+	{ "DA",     "",                   SKIP,   LEVEL_MAIN },+	{ "DCOM",   "",                   SKIP,   LEVEL_MAIN },+	{ "LR",     "",                   SKIP,   LEVEL_MAIN },+	{ "IS",     "",                   SKIP,   LEVEL_MAIN },+	{ "VI",     "VOLUME",             SIMPLE, LEVEL_MAIN },+	{ "IP",     "ISSUE",              SIMPLE, LEVEL_MAIN },+	{ "DP",     "",                   DATE,   LEVEL_MAIN }, /* date published? */+	{ "TI",     "TITLE",              TITLE,  LEVEL_MAIN },+	{ "PG",     "PAGES",              PAGES,  LEVEL_MAIN },+	{ "LID",    "DOI",                DOI,    LEVEL_MAIN }, /* linking ID? -- can be DOI/PII */+	{ "AB",     "ABSTRACT",           SIMPLE, LEVEL_MAIN },+	{ "FAU",    "AUTHOR",             PERSON, LEVEL_MAIN },+	{ "AU",     "",                   SKIP,   LEVEL_MAIN },+	{ "AD",     "",                   SKIP,   LEVEL_MAIN },+	{ "LA",     "",                   SKIP,   LEVEL_MAIN },+	{ "GR",     "",                   SKIP,   LEVEL_MAIN },+	{ "DEP",    "",                   SKIP,   LEVEL_MAIN }, /* a date */+	{ "PL",     "ADDRESS",            SIMPLE, LEVEL_MAIN }, /* Publisher location */+	{ "TA",     "SHORTTITLE",         SIMPLE, LEVEL_HOST }, /* Journal title abbreviation */+	{ "JT",     "TITLE",              SIMPLE, LEVEL_HOST }, /* Journal title */+	{ "JID",    "",                   SKIP,   LEVEL_HOST }, /* Journal ID? */+	{ "SB",     "",                   SKIP,   LEVEL_MAIN },+	{ "PMC",    "PMC",                SIMPLE, LEVEL_MAIN },+	{ "OID",    "",                   SKIP,   LEVEL_MAIN },+	{ "EDAT",   "",                   SKIP,   LEVEL_MAIN },+	{ "MHDA",   "",                   SKIP,   LEVEL_MAIN },+	{ "CRDT",   "",                   SKIP,   LEVEL_MAIN },+	{ "PHST",   "",                   SKIP,   LEVEL_MAIN }, /* Publication history? */+	{ "AID",    "DOI",                DOI,    LEVEL_MAIN }, /* Article ID? -- can be DOI/PII */+	{ "PST",    "",                   SKIP,   LEVEL_MAIN },+	{ "SO",     "",                   SKIP,   LEVEL_MAIN },+	{ " ",      "INTERNAL_TYPE|ARTICLE",  ALWAYS, LEVEL_MAIN },+	{ " ",      "ISSUANCE|continuing",    ALWAYS, LEVEL_HOST },+	{ " ",      "RESOURCE|text",          ALWAYS, LEVEL_MAIN },+	{ " ",      "GENRE|journal article",  ALWAYS, LEVEL_MAIN },+	{ " ",      "GENRE|periodical",       ALWAYS, LEVEL_HOST },+	{ " ",      "GENRE|academic journal", ALWAYS, LEVEL_HOST }+};++#define ORIG(a) ( &(a[0]) )+#define SIZE(a) ( sizeof( a ) / sizeof( lookups ) )+#define REFTYPE(a,b) { a, ORIG(b), SIZE(b) }++variants nbib_all[] = {+	REFTYPE( "Journal article", article ),+	REFTYPE( "News",            article ),+};++int nbib_nall = sizeof( nbib_all ) / sizeof( variants );+
− bibutils/newstr.c
@@ -1,901 +0,0 @@-/*- * newstr.c- *- * Version: 04/27/14- *- * Copyright (c) Chris Putnam 1999-2014- *- * Source code released under the GPL version 2- *- *- * routines for dynamically allocated strings- *- */-#include <stdio.h>-#include <stdlib.h>-#include <stdarg.h>-#include <string.h>-#include <ctype.h>-#include <limits.h>-#include "newstr.h"-#include "is_ws.h"--/* Do not use asserts in NEWSTR_NOASSERT defined */-#ifdef NEWSTR_NOASSERT-#define NDEBUG-#endif-#include <assert.h>--#define newstr_initlen (64)---/* Clear memory in resize/free if NEWSTR_PARANOIA defined */--#ifndef NEWSTR_PARANOIA--static void -newstr_realloc( newstr *s, unsigned long minsize )-{-	char *newptr;-	unsigned long size;-	assert( s );-	size = 2 * s->dim;-	if (size < minsize) size = minsize;-	newptr = (char *) realloc( s->data, sizeof( *(s->data) )*size );-	if ( !newptr ) {-		fprintf(stderr,"Error.  Cannot reallocate memory (%ld bytes) in newstr_realloc.\n", sizeof(*(s->data))*size);-		exit( EXIT_FAILURE );-	}-	s->data = newptr;-	s->dim = size;-}--/* define as a no-op */-#define newstr_nullify( s )--#else--static void -newstr_realloc( newstr *s, unsigned long minsize )-{-	char *newptr;-	unsigned long size;-	assert( s );-	size = 2 * s->dim;-	if ( size < minsize ) size = minsize;-	newptr = (char *) malloc( sizeof( *(s->data) ) * size );-	if ( !newptr ) {-		fprintf( stderr, "Error.  Cannot reallocate memory (%d bytes)"-			" in newstr_realloc.\n", sizeof(*(s->data))*size );-		exit( EXIT_FAILURE );-	}-	if ( s->data ) {-		newstr_nullify( s );-		free( s->data );-	}-	s->data = newptr;-	s->dim = size;-}--static inline void-newstr_nullify( newstr *s )-{-	memset( s->data, 0, s->dim );-}--#endif--void -newstr_init( newstr *s )-{-	assert( s );-	s->dim = 0;-	s->len = 0;-	s->data = NULL;-}--void-newstr_initstr( newstr *s, const char *initstr )-{-	assert( s );-	assert( initstr );-	newstr_init( s );-	newstr_strcpy( s, initstr );-}--void-newstrs_init( newstr *s, ... )-{-	newstr *s2;-	va_list ap;-	newstr_init( s );-	va_start( ap, s );-	do {-		s2 = va_arg( ap, newstr * );-		if ( s2 ) newstr_init( s2 );-	} while ( s2 );-	va_end( ap );-}--/*- * This is currently a stub. Later it will- * report whether or not a newstr function- * could not be performed due to a memory- * error.- */-int-newstr_memerr( newstr *s )-{-	return 0;-}--void-newstr_mergestrs( newstr *s, ... )-{-	va_list ap;-	const char *cp;-	newstr_empty( s );-	va_start( ap, s );-	do {-		cp = va_arg( ap, const char * );-		if ( cp ) newstr_strcat( s, cp );-	} while ( cp );-	va_end( ap );-}--static void -newstr_initalloc( newstr *s, unsigned long minsize )-{-	unsigned long size = newstr_initlen;-	assert( s );-	if ( minsize > newstr_initlen ) size = minsize;-	s->data = (char *) malloc (sizeof( *(s->data) ) * size);-	if ( !s->data ) {-		fprintf(stderr,"Error.  Cannot allocate memory in newstr_initalloc.\n");-		exit( EXIT_FAILURE );-	}-	s->data[0]='\0';-	s->dim=size;-	s->len=0;-}--newstr *-newstr_new( void )-{-	newstr *s = (newstr *) malloc( sizeof( *s ) );-	if ( s )-		newstr_initalloc( s, newstr_initlen );-	return s;-}--void -newstr_free( newstr *s )-{-	assert( s );-	if ( s->data ) {-		newstr_nullify( s );-		free( s->data );-	}-	s->dim = 0;-	s->len = 0;-	s->data = NULL;-}--void-newstrs_free( newstr *s, ... )-{-	newstr *s2;-	va_list ap;-	newstr_free( s );-	va_start( ap, s );-	do {-		s2 = va_arg( ap, newstr * );-		if ( s2 ) newstr_free( s2 );-	} while ( s2 );-	va_end( ap );-}--void-newstr_delete( newstr *s )-{-	assert( s );-	newstr_free( s );-	free( s );-}--void-newstr_empty( newstr *s )-{-	assert( s );-	if ( s->data ) {-		newstr_nullify( s );-		s->data[0] = '\0';-	}-	s->len = 0;-}--void-newstrs_empty( newstr *s, ... )-{-	newstr *s2;-	va_list ap;-	newstr_empty( s );-	va_start( ap, s );-	do {-		s2 = va_arg( ap, newstr * );-		if ( s2 ) newstr_empty( s2 );-	} while ( s2 );-	va_end( ap );-}--void-newstr_addchar( newstr *s, char newchar )-{-	assert( s );-	if ( newchar=='\0' ) return; /* appending '\0' is a null operation */-	if ( !s->data || s->dim==0 ) -		newstr_initalloc( s, newstr_initlen );-	if ( s->len + 2 > s->dim ) -		newstr_realloc( s, s->len*2 );-	s->data[s->len++] = newchar;-	s->data[s->len] = '\0';-}--/* newstr_addutf8- *- * Add potential multibyte character to s starting at pointer p.- * Multibyte Unicode characters have the high bit set.- *- * Since we can progress more than one byte at p, return the- * properly updated pointer p.- */-const char *-newstr_addutf8( newstr *s, const char *p )-{-	if ( ! ((*p) & 128 ) ) {-		newstr_addchar( s, *p );-		p++;-	} else {-		while ( ((*p) & 128) ) {-			newstr_addchar( s, *p );-			p++;-		}-	}-	return p;-}--void -newstr_fprintf( FILE *fp, newstr *s )-{-	assert( s );-	if ( s->data ) fprintf( fp, "%s", s->data );-}--void-newstr_prepend( newstr *s, const char *addstr )-{-	unsigned long lenaddstr, i;-	assert( s && addstr );-	lenaddstr = strlen( addstr );-	if ( lenaddstr==0 ) return;-	if ( !s->data || !s->dim )-		newstr_initalloc( s, lenaddstr+1 );-	else {-		if ( s->len + lenaddstr  + 1 > s->dim )-			newstr_realloc( s, s->len + lenaddstr + 1 );-		for ( i=s->len+lenaddstr-1; i>=lenaddstr; i-- )-			s->data[i] = s->data[i-lenaddstr];-	}-	strncpy( s->data, addstr, lenaddstr );-	s->len += lenaddstr;-	s->data[ s->len ] = '\0';-}--static inline void-newstr_strcat_ensurespace( newstr *s, unsigned long n )-{-	unsigned long m = s->len + n + 1;-	if ( !s->data || !s->dim )-		newstr_initalloc( s, m );-	else if ( s->len + n + 1 > s->dim )-		newstr_realloc( s, m );-}--static inline void -newstr_strcat_internal( newstr *s, const char *addstr, unsigned long n )-{-	newstr_strcat_ensurespace( s, n );-	strncat( &(s->data[s->len]), addstr, n );-	s->len += n;-	s->data[s->len]='\0';-}--void-newstr_newstrcat( newstr *s, newstr *old )-{-	assert ( s && old );-	if ( !old->data ) return;-	else newstr_strcat_internal( s, old->data, old->len );-}--void-newstr_strcat( newstr *s, const char *addstr )-{-	unsigned long n;-	assert( s && addstr );-	n = strlen( addstr );-	newstr_strcat_internal( s, addstr, n );-}--void-newstr_segcat( newstr *s, char *startat, char *endat )-{-	unsigned long n;-	char *p;--	assert( s && startat && endat );-	assert( (size_t) startat < (size_t) endat );--	if ( startat==endat ) return;--	n = 0;-	p = startat;-	while ( p!=endat ) {-		n++;-		p++;-	}--	newstr_strcat_internal( s, startat, n );-}--void-newstr_indxcat( newstr *s, char *p, unsigned long start, unsigned long stop )-{-	unsigned long i;-	assert( s && p );-	assert( start <= stop );-	for ( i=start; i<stop; ++i )-		newstr_addchar( s, p[i] );-}--/* newstr_cpytodelim()- *     term      = string of characters to be used as terminators- *     finalstep = set to non-zero to position return value past the- *                 terminating character- */-char *-newstr_cpytodelim( newstr *s, char *p, const char *delim, unsigned char finalstep )-{-	newstr_empty( s );-	return newstr_cattodelim( s, p, delim, finalstep );-}--/* newstr_cpytodelim()- *     term      = string of characters to be used as terminators- *     finalstep = set to non-zero to position return value past the- *                 terminating character- */-char *-newstr_cattodelim( newstr *s, char *p, const char *delim, unsigned char finalstep )-{-	while ( p && *p && !strchr( delim, *p ) ) {-		newstr_addchar( s, *p );-		p++;-	}-	if ( *p && finalstep ) p++;-	return p;-}--static inline void-newstr_strcpy_ensurespace( newstr *s, unsigned long n )-{-	unsigned long m = n + 1;-	if ( !s->data || !s->dim )-		newstr_initalloc( s, m );-	else if ( m > s->dim )-		newstr_realloc( s, m );-}--static inline void-newstr_strcpy_internal( newstr *s, const char *p, unsigned long n )-{-	newstr_strcpy_ensurespace( s, n );-	strncpy( s->data, p, n );-	s->data[n] = '\0';-	s->len = n;-}--void-newstr_newstrcpy( newstr *s, newstr *old )-{-	assert( s );-	if ( s==old ) return;-	else if ( !old || old->len==0 ) newstr_empty( s );-	else newstr_strcpy_internal( s, old->data, old->len );-}--void -newstr_strcpy( newstr *s, const char *addstr )-{-	unsigned long n;-	assert( s && addstr );-	n = strlen( addstr );-	newstr_strcpy_internal( s, addstr, n );-}--/* newstr_segcpy( s, start, end );- *- * copies [start,end) into s- */-void-newstr_segcpy( newstr *s, char *startat, char *endat )-{-	unsigned long n;-	char *p;--	assert( s && startat && endat );-	assert( ((size_t) startat) <= ((size_t) endat) );--	if ( startat==endat ) {-		newstr_empty( s );-		return;-	}--	n = 0;-	p = startat;-	while ( p!=endat ) {-		p++;-		n++;-	}--	newstr_strcpy_internal( s, startat, n );-}--/*- * newstr_indxcpy( s, in, start, stop );- *- * copies in[start,stop) (excludes stop) into s- */-void-newstr_indxcpy( newstr *s, char *p, unsigned long start, unsigned long stop )-{-	unsigned long i;-	assert( s && p );-	assert( start <= stop );-	if ( start == stop ) {-		newstr_empty( s );-		return;-	}-	newstr_strcpy_ensurespace( s, stop-start+1 );-	for ( i=start; i<stop; ++i )-		s->data[i-start] = p[i];-	s->len = stop-start;-	s->data[s->len] = '\0';-}--newstr *-newstr_strdup( const char *s1 )-{-	newstr *s2 = newstr_new();-	if ( s2 )-		newstr_strcpy( s2, s1 );-	return s2;-}--void-newstr_segdel( newstr *s, char *p, char *q )-{-	newstr tmp1, tmp2;-	char *r;-	assert( s );-	r = &(s->data[s->len]);-	newstr_init( &tmp1 );-	newstr_init( &tmp2 );-	newstr_segcpy( &tmp1, s->data, p );-	newstr_segcpy( &tmp2, q, r );-	newstr_empty( s );-	if ( tmp1.data ) newstr_strcat( s, tmp1.data );-	if ( tmp2.data ) newstr_strcat( s, tmp2.data );-	newstr_free( &tmp2 );-	newstr_free( &tmp1 );-}--/*- * newstr_findreplace()- *- *   if replace is "" or NULL, then delete find- */--int-newstr_findreplace( newstr *s, const char *find, const char *replace )-{-	long diff;-	size_t findstart, searchstart;-	size_t p1, p2;-	size_t find_len, rep_len, curr_len;-	char empty[2] = "";-	unsigned long minsize;-	char *p;-	int n = 0;--	assert( s && find );-	if ( !s->data || !s->dim ) return n;-	if ( !replace ) replace = empty;--	find_len = strlen( find );-	rep_len  = strlen( replace );-	diff     = rep_len - find_len;-	if ( diff < 0 ) diff = 0;--	searchstart=0;-	while ((p=strstr(s->data + searchstart,find))!=NULL) {-		curr_len = strlen(s->data);-		findstart=(size_t) p - (size_t) s->data;-		minsize = curr_len + diff + 1;-	 	if (s->dim <= minsize) newstr_realloc( s, minsize );-		if ( find_len > rep_len ) {-			p1 = findstart + rep_len;-			p2 = findstart + find_len;-			while( s->data[p2] )-				s->data[p1++]=s->data[p2++];-			s->data[p1]='\0';-			n++;-		} else if ( find_len < rep_len ) {-			for ( p1=curr_len; p1>=findstart+find_len; p1-- )-				s->data[p1+diff] = s->data[p1];-			n++;-		}-		for (p1=0; p1<rep_len; p1++)-			s->data[findstart+p1]=replace[p1];-		searchstart = findstart + rep_len; -		s->len += rep_len - find_len;-	}-	return n;-}---/* newstr_fget()- *   returns 0 if we're done, 1 if we're not done- *   extracts line by line (regardless of end characters)- *   and feeds from buf....- */-int-newstr_fget( FILE *fp, char *buf, int bufsize, int *pbufpos, newstr *outs )-{-	int  bufpos = *pbufpos, done = 0;-	char *ok;-	assert( fp && outs );-	newstr_empty( outs );-	while ( !done ) {-		while ( buf[bufpos] && buf[bufpos]!='\r' && buf[bufpos]!='\n' )-			newstr_addchar( outs, buf[bufpos++] );-		if ( buf[bufpos]=='\0' ) {-			ok = fgets( buf, bufsize, fp );-			bufpos=*pbufpos=0;-			if ( !ok && feof(fp) ) { /* end-of-file */-				buf[bufpos] = 0;-				if ( outs->len==0 ) return 0; /*nothing in out*/-				else return 1; /*one last out */-			}-		} else if ( buf[bufpos]=='\r' || buf[bufpos]=='\n' ) done=1;-	}-	if ( ( buf[bufpos]=='\n' && buf[bufpos+1]=='\r') ||-	     ( buf[bufpos]=='\r' && buf[bufpos+1]=='\n') ) bufpos+=2;-	else if ( buf[bufpos]=='\n' || buf[bufpos]=='\r' ) bufpos+=1; -	*pbufpos = bufpos;-	return 1;-}--void-newstr_toupper( newstr *s )-{-	unsigned long i;-	assert( s );-	for ( i=0; i<s->len; ++i )-		s->data[i] = toupper( (unsigned char)s->data[i] );-}--void-newstr_tolower( newstr *s )-{-	unsigned long i;-	assert( s );-	for ( i=0; i<s->len; ++i )-		s->data[i] = tolower( (unsigned char)s->data[i] );-}--/* newstr_swapstrings( s1, s2 )- * be sneaky and swap internal newstring data from one- * string to another- */-void-newstr_swapstrings( newstr *s1, newstr *s2 )-{-	char *tmpp;-	int tmp;--	assert( s1 && s2 );--	/* swap dimensioning info */-	tmp = s1->dim;-	s1->dim = s2->dim;-	s2->dim = tmp;--	/* swap length info */-	tmp = s1->len;-	s1->len = s2->len;-	s2->len = tmp;--	/* swap data */-	tmpp = s1->data;-	s1->data = s2->data;-	s2->data = tmpp;-}--void-newstr_trimstartingws( newstr *s )-{-	char *p, *q;-	int n;--	assert( s );--	if ( s->len==0 || !is_ws( s->data[0] ) ) return;--	n = 0;-	p = s->data;-	while ( is_ws( *p ) ) p++;--	q = s->data;-	while ( *p ) {-		*q++ = *p++;-		n++;-	}-	*q = '\0';--	s->len = n;-}--void-newstr_trimendingws( newstr *s )-{-	assert( s );-	while ( s->len > 0 && is_ws( s->data[s->len-1] ) ) {-		s->data[s->len-1] = '\0';-		s->len--;-	}-}--int-newstr_match_first( newstr *s, char ch )-{-	assert( s );-	if ( !s->len ) return 0;-	if ( s->data[0] == ch ) return 1;-	return 0;-}--int-newstr_match_end( newstr *s, char ch )-{-	assert( s );-	if ( !s->len ) return 0;-	if ( s->data[ s->len - 1 ] == ch ) return 1;-	return 0;-}--void-newstr_trimbegin( newstr *s, unsigned long n )-{-	char *p, *q;--	assert( s );--	if ( n==0 ) return;-	if ( s->len==0 ) return;-	if ( n >= s->len ) {-		newstr_empty( s );-		return;-	}--	p = s->data;-	while ( n-- > 0 ) p++;--	n = 0;-	q = s->data;-	while ( *p ) {-		*q++ = *p++;-		n++;-	}-	*q = '\0';--	s->len = n;-}--void-newstr_trimend( newstr *s, unsigned long n )-{-	assert( s );--	if ( n==0 ) return;-	if ( n >= s->len ) {-		newstr_empty( s );-		return;-	}--	s->len -= n;-	s->data[ s->len ] = '\0';-}--void-newstr_pad( newstr *s, unsigned long len, char ch )-{-	unsigned long i;-	assert( s );-	for ( i=s->len; i<len; i++ )-		newstr_addchar( s, ch );-}--void-newstr_copyposlen( newstr *s, newstr *in, unsigned long pos, unsigned long len )-{-	unsigned long i, max;-	assert( s );-	newstr_empty( s );-	max = pos+len;-	if ( max > in->len ) max = in->len;-	for ( i=pos; i<max; ++i )-		newstr_addchar( s, in->data[i] );-}--static void-newstr_check_case( newstr *s, int *lowercase, int *uppercase )-{-	int i;-	assert( s );-	*lowercase = 0;-	*uppercase = 0;-	if ( s->len < 1 ) return;-	for ( i=0; i<s->len && !( *lowercase && *uppercase ); ++i ) {-		if ( isalpha( (unsigned char)s->data[i] ) ) {-			if ( isupper( (unsigned char)s->data[i] ) ) *uppercase += 1;-			else if ( islower( (unsigned char)s->data[i] ) ) *lowercase += 1;-		}-	}-}--int-newstr_is_mixedcase( newstr *s )-{-	int lowercase, uppercase;-	newstr_check_case( s, &lowercase, &uppercase );-	if ( lowercase > 0 && uppercase > 0 ) return 1;-	return 0;-}--int-newstr_is_lowercase( newstr *s )-{-	int lowercase, uppercase;-	newstr_check_case( s, &lowercase, &uppercase );-	if ( lowercase > 0 && uppercase == 0 ) return 1;-	return 0;-}--int-newstr_is_uppercase( newstr *s )-{-	int lowercase, uppercase;-	newstr_check_case( s, &lowercase, &uppercase );-	if ( lowercase == 0 && uppercase > 0 ) return 1;-	return 0;-}--void-newstr_stripws( newstr *s )-{-	unsigned long len = 0;-	char *p, *q;-	assert( s );-	if ( s->len ) {-		p = q = s->data;-		while ( *p ) {-			if ( !is_ws( *p ) ) {-				*q = *p;-				q++;-				len++;-			}-			p++;-		}-		*q = '\0';-	}-	s->len = len;-}--int-newstr_newstrcmp( const newstr *s, const newstr *t )-{-	assert( s );-	assert( t );-	if ( s->len == 0 && t->len == 0 ) return 0;-	if ( s->len == 0 ) return strcmp( "", t->data );-	if ( t->len == 0 ) return strcmp( s->data, "" );-	return strcmp( s->data, t->data );-}--void-newstr_reverse( newstr *s )-{-	unsigned long i, max;-	char tmp;-	assert( s );-	max = s->len / 2;-	for ( i=0; i<max; ++i ) {-		tmp = s->data[ i ];-		s->data[ i ] = s->data[ s->len - 1 - i ];-		s->data[ s->len - 1 - i ] = tmp;-	}-}--int-newstr_fgetline( newstr *s, FILE *fp )-{-	int ch, eol = 0;-	assert( s );-	assert( fp );-	newstr_empty( s );-	if ( feof( fp ) ) return 0;-	while ( !feof( fp ) && !eol ) {-		ch = fgetc( fp );-		if ( ch == EOF ) {-			if ( s->len ) return 1;-			else return 0;-		}-		else if ( ch == '\n' ) eol = 1;-		else if ( ch == '\r' ) {-			ch = fgetc( fp );-			if ( ch != '\n' ) ungetc( ch, fp );-			eol = 1;-		} else {-			newstr_addchar( s, (char) ch );-		}-	}-	return 1;-}--/*- * s = "Hi!\0", s.len = 3- *- * newstr_char( s, 0 ) = 'H'  newstr_revchar( s, 0 ) = '!'- * newstr_char( s, 1 ) = 'i'  newstr_revchar( s, 1 ) = 'i'- * newstr_char( s, 2 ) = '!'  newstr_revchar( s, 2 ) = 'H'- * newstr_char( s, 3 ) = '\0' newstr_revchar( s, 3 ) = '\0'- */-char-newstr_char( newstr *s, unsigned long n )-{-	assert( s );-	if ( s->len==0 || n >= s->len ) return '\0';-	return s->data[ n ];-}--char-newstr_revchar( newstr *s, unsigned long n )-{-	assert( s );-	if ( s->len==0 || n >= s->len ) return '\0';-	return s->data[ s->len - n - 1];-}--void-newstr_makepath( newstr *path, const char *dirname, const char *filename, char sep )-{-	assert( path );-	if ( dirname ) newstr_strcpy( path, dirname );-	else newstr_empty( path );--	if ( path->len && path->data[path->len-1]!=sep )-		newstr_addchar( path, sep );--	if ( filename ) newstr_strcat( path, filename );-}
− bibutils/newstr.h
@@ -1,101 +0,0 @@-/*- * newstr.h- *- * Version: 04/27/14- *- * Copyright (c) Chris Putnam 1999-2014- *- * Source code released under the GPL version 2- *- */-#ifndef NEWSTR_H-#define NEWSTR_H--#include <stdio.h>--typedef struct newstr {-	char *data;-	unsigned long dim;-	unsigned long len;-}  newstr;--newstr *newstr_new         ( void ); -void    newstr_delete      ( newstr *s );--void    newstr_init        ( newstr *s );-void    newstr_initstr     ( newstr *s, const char *initstr );-void    newstr_empty       ( newstr *s );-void    newstr_free        ( newstr *s );--void    newstrs_init       ( newstr *s, ... );-void    newstrs_empty      ( newstr *s, ... );-void    newstrs_free       ( newstr *s, ... );--void newstr_mergestrs   ( newstr *s, ... );-newstr *newstr_strdup   ( const char *p );-void newstr_addchar     ( newstr *s, char newchar );-void newstr_reverse     ( newstr *s );-const char *newstr_addutf8    ( newstr *s, const char *p );-void newstr_strcat      ( newstr *s, const char *addstr );-void newstr_newstrcat   ( newstr *s, newstr *old );-void newstr_segcat      ( newstr *s, char *startat, char *endat );-char *newstr_cpytodelim  ( newstr *s, char *p, const char *delim, unsigned char finalstep );-char *newstr_cattodelim  ( newstr *s, char *p, const char *delim, unsigned char finalstep );-void newstr_prepend     ( newstr *s, const char *addstr );-void newstr_strcpy      ( newstr *s, const char *addstr );-void newstr_newstrcpy   ( newstr *s, newstr *old );-void newstr_segcpy      ( newstr *s, char *startat, char *endat );-void newstr_segdel      ( newstr *s, char *startat, char *endat );-void newstr_indxcpy     ( newstr *s, char *p, unsigned long start, unsigned long stop );-void newstr_indxcat     ( newstr *s, char *p, unsigned long start, unsigned long stop );-void newstr_fprintf     ( FILE *fp, newstr *s );-int  newstr_fget        ( FILE *fp, char *buf, int bufsize, int *pbufpos,-                          newstr *outs );-char newstr_char        ( newstr *s, unsigned long n );-char newstr_revchar     ( newstr *s, unsigned long n );-int  newstr_fgetline    ( newstr *s, FILE *fp );-int  newstr_findreplace ( newstr *s, const char *find, const char *replace );-void newstr_toupper     ( newstr *s );-void newstr_tolower     ( newstr *s );-void newstr_trimstartingws( newstr *s );-void newstr_trimendingws( newstr *s );-void newstr_swapstrings ( newstr *s1, newstr *s2 );-void newstr_stripws     ( newstr *s );--int  newstr_match_first ( newstr *s, char ch );-int  newstr_match_end   ( newstr *s, char ch );-void newstr_trimbegin   ( newstr *s, unsigned long n );-void newstr_trimend     ( newstr *s, unsigned long n );--void newstr_pad         ( newstr *s, unsigned long len, char ch );-void newstr_copyposlen  ( newstr *s, newstr *in, unsigned long pos, unsigned long len );--void newstr_makepath    ( newstr *path, const char *dirname, const char *filename, char sep );---int  newstr_is_mixedcase( newstr *s );-int  newstr_is_lowercase( newstr *s );-int  newstr_is_uppercase( newstr *s );--int  newstr_newstrcmp    ( const newstr *s, const newstr *t );--int  newstr_memerr( newstr *s );---/* #define NEWSTR_PARANOIA- *- * set to clear memory before it is freed or reallocated- * note that this is slower...may be important if string- * contains sensitive information- */--/* #define NEWSTR_NOASSERT- *- * set to turn off the use of asserts (and associated call to exit)- * in newstr functions...useful for library construction for- * Linux distributions that don't want libraries calling exit, but- * not useful during code development- */--#endif-
− bibutils/newstr_conv.c
@@ -1,197 +0,0 @@-/*- * newstr_conv.c- *- * Copyright (c) Chris Putnam 1999-2014- *- * Source code released under the GPL version 2- *- * newstring routines for converting newstrings between character sets- *- */-#include <stdio.h>-#include <stdlib.h>-#include <string.h>-#include <ctype.h>-#include <limits.h>-#include "newstr.h"-#include "latex.h"-#include "entities.h"-#include "utf8.h"-#include "gb18030.h"-#include "charsets.h"-#include "newstr_conv.h"--static void-addentity( newstr *s, unsigned int ch )-{-	char buf[512];-	sprintf( buf, "&#%d;", ch );-	newstr_strcat( s, buf );-}--/* These are the five minimal predefined entites in XML */-static int-minimalxmlchars( newstr *s, unsigned int ch )-{-	if ( ch==34 ) { newstr_strcat( s, "&quot;" ); return 1; }-	else if ( ch==38 ) { newstr_strcat( s, "&amp;" ); return 1; }-	else if ( ch==39 ) { newstr_strcat( s, "&apos;" ); return 1; }-	else if ( ch==60 ) { newstr_strcat( s, "&lt;" ); return 1; }-	else if ( ch==62 ) { newstr_strcat( s, "&gt;" ); return 1; }-	return 0;-}--static void-addxmlchar( newstr *s, unsigned int ch )-{-	if ( minimalxmlchars( s, ch ) ) return;-	if ( ch > 127 ) addentity( s, ch );-	else newstr_addchar( s, ch );-}--static void-addutf8char( newstr *s, unsigned int ch, int xmlout )-{-	unsigned char code[6];-	int nc, i;-	if ( xmlout ) {-		if ( minimalxmlchars( s, ch ) ) return;-		if ( ch > 127 && xmlout == NEWSTR_CONV_XMLOUT_ENTITIES )-			{ addentity( s, ch ); return; }-	}-	nc = utf8_encode( ch, code );-	for ( i=0; i<nc; ++i )-		newstr_addchar( s, code[i] );-}--static void-addgb18030char( newstr *s, unsigned int ch, int xmlout )-{-	unsigned char code[4];-	int nc, i;-	if ( xmlout ) {-		if ( minimalxmlchars( s, ch ) ) return;-		if ( ch > 127 && xmlout == NEWSTR_CONV_XMLOUT_ENTITIES )-			{ addentity( s, ch ); return; }-	}-	nc = gb18030_encode( ch, code );-	for ( i=0; i<nc; ++i )-		newstr_addchar( s, code[i] );-}--static void-addlatexchar( newstr *s, unsigned int ch, int xmlout, int utf8out )-{-	char buf[512];-	uni2latex( ch, buf, sizeof( buf ) );-	/* If the unicode character isn't recognized as latex output-	 * a '?' unless the user has requested unicode output.  If so,-	 * output the unicode.-	 */-	if ( utf8out && !strcmp( buf, "?" ) ) {-		addutf8char( s, ch, xmlout );-	} else {-		newstr_strcat( s, buf );-	}-}--/*- * get_unicode()- * - *   This can be a little tricky.  If the character is simply encoded- *   such as UTF8 for > 128 or by numeric xml entities such as "&#534;"- *   then the output of decode_entity() and utf8_decode will necessarily- *   be in the charsetin character set.  On the other hand, if it's a- *   fancy latex expression, such as "\alpha", or a non-numeric xml entity- *   like "&amp;", then we'll get the Unicode value (because our lists only- *   keep the Unicode equivalent).- *- *   The unicode variable indicates whether or not a Unicode-based listing- *   was used to convert the character (remember that charsetin could be- *   Unicode independently).- *- *   The charset variable is used to keep track of what character set- *   the character is in prior to conversion.- *- */--static unsigned int-get_unicode( newstr *s, unsigned int *pi, int charsetin, int latexin, int utf8in, int xmlin )-{-	unsigned int ch;-	int unicode = 0, err = 0;-	if ( xmlin && s->data[*pi]=='&' ) {-		ch = decode_entity( s->data, pi, &unicode, &err );-	} else if ( charsetin==CHARSET_GB18030 ) {-		ch = gb18030_decode( s->data, pi );-		unicode = 1;-	} else if ( latexin ) {-		/* Must handle bibtex files in UTF8/Unicode */-		if ( utf8in && ( s->data[*pi] & 128 ) ) {-			ch = utf8_decode( s->data, pi );-			unicode = 1;-		} else ch = latex2char( s->data, pi, &unicode );-	}-	else if ( utf8in )-		ch = utf8_decode( s->data, pi );-	else {-		ch = (unsigned int) s->data[*pi];-		*pi = *pi + 1;-	}-	if ( !unicode && charsetin!=CHARSET_UNICODE )-		ch = charset_lookupchar( charsetin, ch );-	return ch;-}--static int-write_unicode( newstr *s, unsigned int ch, int charsetout, int latexout,-		int utf8out, int xmlout )-{-	unsigned int c;-	if ( latexout ) {-		addlatexchar( s, ch, xmlout, utf8out );-	} else if ( utf8out ) {-		addutf8char( s, ch, xmlout );-	} else if ( charsetout==CHARSET_GB18030 ) {-		addgb18030char( s, ch, xmlout );-	} else {-		c = charset_lookupuni( charsetout, ch );-		if ( xmlout ) addxmlchar( s, c );-		else newstr_addchar( s, c );-	}-	return 1;-}--/*- * Returns 1 on memory error condition- */-int-newstr_convert( newstr *s,-	int charsetin,  int latexin,  int utf8in,  int xmlin,-	int charsetout, int latexout, int utf8out, int xmlout )-{-	unsigned int pos = 0;-	unsigned int ch;-	newstr ns;-	int ok = 1;--	if ( !s || s->len==0 ) return ok;--	newstr_init( &ns );--	if ( charsetin==CHARSET_UNKNOWN ) charsetin = CHARSET_DEFAULT;-	if ( charsetout==CHARSET_UNKNOWN ) charsetout = CHARSET_DEFAULT;--	while ( s->data[pos] ) {-		ch = get_unicode( s, &pos, charsetin, latexin, utf8in, xmlin );-		ok = write_unicode( &ns, ch, charsetout, latexout, utf8out, xmlout );-		if ( !ok ) goto out;-	}--	newstr_swapstrings( s, &ns );-out:-	newstr_free( &ns );--	return ok;-}-
− bibutils/newstr_conv.h
@@ -1,23 +0,0 @@-/*- * newstring_conv.h- *- * Copyright (c) Chris Putnam 1999-2014- *- * Source code released under the GPL version 2- *- */-#ifndef NEWSTR_CONV_H-#define NEWSTR_CONV_H--#define NEWSTR_CONV_XMLOUT_FALSE    (0)-#define NEWSTR_CONV_XMLOUT_TRUE     (1)-#define NEWSTR_CONV_XMLOUT_ENTITIES (3)--#include "newstr.h"--extern int newstr_convert( newstr *s,-		int charsetin, int latexin, int utf8in, int xmlin, -		int charsetout, int latexout, int utf8out, int xmlout );--#endif-
+ bibutils/notes.c view
@@ -0,0 +1,102 @@+/*+ * notes.c+ *+ * Copyright (c) Chris Putnam 2016-2017+ *+ * Program and source code released under the GPL version 2+ *+ */+#include <string.h>+#include "url.h"+#include "notes.h"++/*+ * notes are mostly directly copies; however, lots of formats hide+ * URLs/DOIs in the notes fields. For example:+ *+ * For RIS, Oxford Journals hides DOI in the N1 field.+ * For Endnote, Wiley hides DOI in the %1 field.+ * etc.+ */++typedef struct url_t {+	char *prefix;+	char *tag;+	int offset;+} url_t;++static void+notes_added_url( fields *bibout, str *invalue, int level, int *ok )+{+	url_t prefixes[] = {+		{ "arXiv:",                                    "ARXIV",     6 },+		{ "http://arxiv.org/abs/",                     "ARXIV",    21 },+		{ "jstor:",                                    "JSTOR",     6 },+		{ "http://www.jstor.org/stable/",              "JSTOR",    28 },+		{ "medline:",                                  "MEDLINE",   8 },+		{ "pubmed:",                                   "PMID",      7 },+		{ "http://www.ncbi.nlm.nih.gov/pubmed/",       "PMID",     35 },+		{ "http://www.ncbi.nlm.nih.gov/pmc/articles/", "PMC",      41 },+		{ "http://dx.doi.org/",                        "DOI",      19 },+		{ "isi:",                                      "ISIREFNUM", 4 },+	};+	int nprefixes = sizeof( prefixes ) / sizeof( prefixes[0] );++	char *p = invalue->data;+	char *tag = "URL";+	int fstatus;+	int i;++	/* bibtex/biblatex-specific */+	if ( !strncasecmp( p, "\\urllink", 8 ) ) p += 8;+	if ( !strncasecmp( p, "\\url", 4 ) ) p += 4;++	for ( i=0; i<nprefixes; ++i ) {+		if ( !strncasecmp( p, prefixes[i].prefix, prefixes[i].offset ) ) {+			tag = prefixes[i].tag;+			p   = p + prefixes[i].offset;+			break;+		}+	}++	fstatus = fields_add( bibout, tag, p, level );++	if ( fstatus==FIELDS_OK ) *ok = 1;+	else *ok = 0;+}++static int+notes_added_doi( fields *bibout, str *invalue, int level, int *ok )+{+	int doi, fstatus;++	doi = is_doi( invalue->data );++	if ( doi != -1 ) {+		fstatus = fields_add( bibout, "DOI", &(invalue->data[doi]), level );+		if ( fstatus != FIELDS_OK ) *ok = 0;+		return 1;+	}++	else return 0;+}++int+notes_add( fields *bibout, str *invalue, int level )+{+	int fstatus, done = 0, ok = 1;++	if ( !is_embedded_link( invalue->data ) ) {+		fstatus = fields_add( bibout, "NOTES", invalue->data, level );+		if ( fstatus != FIELDS_OK ) ok = 0;+	}++	else {++		done = notes_added_doi( bibout, invalue, level, &ok );+		if ( !done ) notes_added_url( bibout, invalue, level, &ok );++	}++	return ok;+}
+ bibutils/notes.h view
@@ -0,0 +1,17 @@+/*+ * notes.h+ *+ * Copyright (c) Chris Putnam 2016-2017+ *+ * Source code released under the GPL version 2+ *+ */+#ifndef NOTES_H+#define NOTES_H++#include "bibutils.h"++int notes_add( fields *bibout, str *invalue, int level );++#endif+
+ bibutils/pages.c view
@@ -0,0 +1,87 @@+/*+ * pages.c+ *+ * Copyright (c) Chris Putnam 2016-2017+ *+ * Program and source code released under GPL verison 2+ */+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include "is_ws.h"+#include "utf8.h"+#include "pages.h"++/* extract_range()+ *+ * Handle input strings like:+ *+ * "1-15"+ * " 1 - 15 "+ * " 1000--- 1500"+ * " 1 <<em-dash>> 10"+ * " 107 111"+ */+static void+extract_range( str *input, str *begin, str *end )+{+	/* -30 is the first character of a UTF8 em-dash and en-dash */+	const char terminators[] = { ' ', '-', '\t', '\r', '\n', -30, '\0' };+	char *p;++	str_empty( begin );+	str_empty( end );++	if ( input->len==0 ) return;++	p = skip_ws( input->data );+	while ( *p && !strchr( terminators, *p ) )+		str_addchar( begin, *p++ );++	p = skip_ws( p );++	while ( *p=='-' ) p++;+	while ( utf8_is_emdash( p ) ) p+=3;+	while ( utf8_is_endash( p ) ) p+=3;++	p = skip_ws( p );++	while ( *p && !strchr( terminators, *p ) )+		str_addchar( end, *p++ );+}++int+pages_add( fields *bibout, char *outtag, str *invalue, int level )+{+	int fstatus, status = 1;+	str start, stop;++	str_init( &start );+	str_init( &stop );++	extract_range( invalue, &start, &stop );++	if ( str_memerr( &start ) || str_memerr( &stop ) ) {+		status = 0;+		goto out;+	}++	if ( start.len>0 ) {+		fstatus = fields_add( bibout, "PAGES:START", start.data, level );+		if ( fstatus!=FIELDS_OK ) {+			status = 0;+			goto out;+		}+	}++	if ( stop.len>0 ) {+		fstatus = fields_add( bibout, "PAGES:STOP", stop.data, level );+		if ( fstatus!=FIELDS_OK ) status = 0;+	}++out:+	str_free( &start );+	str_free( &stop );+	return status;+}+
+ bibutils/pages.h view
@@ -0,0 +1,16 @@+/*+ * pages.h+ *+ * Copyright (c) Chris Putnam 2016-2017+ *+ * Program and source code released under the GPL version 2+ */+#ifndef PAGES_H+#define PAGES_H++#include "bibl.h"++int pages_add( fields *bibout, char *outtag, str *invalue, int level );++#endif+
bibutils/reftypes.c view
@@ -1,7 +1,7 @@ /*  * reftypes.c  *- * Copyright (c) Chris Putnam 2003-2013+ * Copyright (c) Chris Putnam 2003-2017  *  * Source code released under the GPL version 2  *@@ -13,16 +13,27 @@ #include "reftypes.h"  int-get_reftype( char *p, long refnum, char *progname, variants *all, int nall, char *tag )+get_reftype( char *p, long refnum, char *progname, variants *all, int nall, char *tag, int *is_default, int chattiness ) { 	int i;+ 	p = skip_ws( p );-	for ( i=0; i<nall; ++i )++	*is_default = 0;++	for ( i=0; i<nall; ++i ) { 		if ( !strncasecmp( all[i].type, p, strlen(all[i].type) ) )  			return i;-	if ( progname ) fprintf( stderr, "%s: ", progname );-	fprintf( stderr, "Did not recognize type '%s' of refnum %ld (%s).\n"-		"\tDefaulting to article.\n", p, refnum, tag );+	}++	*is_default = 1;++	if ( chattiness==REFTYPE_CHATTY ) {+		if ( progname ) fprintf( stderr, "%s: ", progname );+		fprintf( stderr, "Did not recognize type '%s' of refnum %ld (%s).\n"+			"\tDefaulting to %s.\n", p, refnum, tag, all[0].type );+	}+ 	return 0; } @@ -52,6 +63,7 @@ 		*processingtype = ((all[reftype]).tags[n]).processingtype; 		*level          = ((all[reftype]).tags[n]).level; 		*newtag         = ((all[reftype]).tags[n]).newstr;+		return 1; 	}-	return n;+	return 0; }
bibutils/reftypes.h view
@@ -1,7 +1,7 @@ /*  * reftypes.h  *- * Copyright (c) Chris Putnam 2003-2013+ * Copyright (c) Chris Putnam 2003-2017  *  * Source code released under the GPL version 2  *@@ -9,9 +9,13 @@ #ifndef REFTYPES_H #define REFTYPES_H +#define REFTYPE_CHATTY  (0)+#define REFTYPE_SILENT  (1)+ /* Reftypes handled by core code */ #define ALWAYS          (0) #define DEFAULT         (1)+#define SKIP            (2)  /* Reftypes to be handled by converters */ #define SIMPLE          (2)@@ -26,17 +30,18 @@ #define HOWPUBLISHED    (11) #define LINKEDFILE      (12) #define KEYWORD         (13)-#define BT_URL          (14) /* Bibtex URL */-#define BT_NOTE         (15) /* Bibtex Note */-#define BT_SENTE        (16) /* Bibtex 'Sente' */-#define BT_GENRE        (17) /* Bibtex Genre */-#define BT_EPRINT       (18) /* Bibtex 'Eprint' */-#define BT_ORG          (19) /* Bibtex Organization */-#define BLT_THESIS_TYPE (20) /* Biblatex Thesis Type */-#define BLT_SCHOOL      (21) /* Biblatex School */-#define BLT_EDITOR      (22) /* Biblatex Editor */-#define BLT_SUBTYPE     (23) /* Biblatex entrysubtype */-#define BLT_SKIP        (24) /* Biblatex Skip Entry */+#define URL             (14)+#define BT_SENTE        (15) /* Bibtex 'Sente' */+#define BT_GENRE        (16) /* Bibtex Genre */+#define BT_EPRINT       (17) /* Bibtex 'Eprint' */+#define BT_ORG          (18) /* Bibtex Organization */+#define BLT_THESIS_TYPE (19) /* Biblatex Thesis Type */+#define BLT_SCHOOL      (20) /* Biblatex School */+#define BLT_EDITOR      (21) /* Biblatex Editor */+#define BLT_SUBTYPE     (22) /* Biblatex entrysubtype */+#define BLT_SKIP        (23) /* Biblatex Skip Entry */+#define EPRINT          (24)+#define NUM_REFTYPES    (25)  typedef struct { 	char *oldstr;@@ -51,10 +56,8 @@ 	int     ntags; } variants; -extern int get_reftype( char *q, long refnum, char *progname, variants *all, int nall, char *tag );-extern int process_findoldtag( char *oldtag, int reftype, variants all[], int nall );-extern int translate_oldtag( char *oldtag, int reftype, variants all[], int nall, int *processingtype, int *level, char **newtag );--+int get_reftype( char *q, long refnum, char *progname, variants *all, int nall, char *tag, int *is_default, int chattiness );+int process_findoldtag( char *oldtag, int reftype, variants all[], int nall );+int translate_oldtag( char *oldtag, int reftype, variants all[], int nall, int *processingtype, int *level, char **newtag );  #endif
bibutils/risin.c view
@@ -1,7 +1,7 @@ /*  * risin.c  *- * Copyright (c) Chris Putnam 2003-2014+ * Copyright (c) Chris Putnam 2003-2017  *  * Source code released under the GPL version 2  *@@ -10,19 +10,30 @@ #include <stdlib.h> #include <string.h> #include <ctype.h>-#include "newstr.h"-#include "newstr_conv.h"+#include "str.h"+#include "str_conv.h" #include "fields.h" #include "name.h" #include "title.h"+#include "url.h"+#include "utf8.h" #include "serialno.h" #include "reftypes.h"-#include "doi.h"-#include "risin.h"+#include "bibformats.h"+#include "generic.h" +extern variants ris_all[];+extern int ris_nall;+ /*****************************************************  PUBLIC: void risin_initparams() *****************************************************/++static int risin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset );+static int risin_processf( fields *risin, char *p, char *filename, long nref, param *pm );+static int risin_typef( fields *risin, char *filename, int nref, param *p );+static int risin_convertf( fields *risin, fields *info, int reftype, param *p );+ void risin_initparams( param *p, const char *progname ) {@@ -45,8 +56,8 @@ 	p->all      = ris_all; 	p->nall     = ris_nall; -	list_init( &(p->asis) );-	list_init( &(p->corps) );+	slist_init( &(p->asis) );+	slist_init( &(p->corps) );  	if ( !progname ) p->progname = NULL; 	else p->progname = strdup( progname );@@ -63,77 +74,114 @@     character 4 = space (ansi 32)     character 5 = dash (ansi 45)     character 6 = space (ansi 32)++  some sources don't have a space at character 6 if there+  is no data (such as "ER  -" records). Handle this.++  www.omicsonline.org mangles the RIS specification and+  puts _three_ spaces before the dash.  Handle this too. */ static int-risin_istag( char *buf )+is_ris_tag( char *buf ) { 	if (! (buf[0]>='A' && buf[0]<='Z') ) return 0; 	if (! (((buf[1]>='A' && buf[1]<='Z'))||(buf[1]>='0'&&buf[1]<='9')) )  		return 0; 	if (buf[2]!=' ') return 0; 	if (buf[3]!=' ') return 0;-	if (buf[4]!='-') return 0;-	if (buf[5]!=' ') return 0;-	return 1;++	/*...RIS fits specifications with two spaces */+	if (buf[4]=='-') {+		if ( buf[5]==' ' || buf[5]=='\0' || buf[5]=='\n' || buf[5]=='\r' ) return 1;+	}++	/* ...extra space in tag? */+	else if (buf[4]==' ') {+		if ( buf[5]=='-' && ( buf[6]==' ' || buf[6]=='\0' || buf[6]=='\n' || buf[6]=='\r' ) ) return 1;+	}++	return 0; }  static int-readmore( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line )+is_ris_start_tag( char *p ) {+	/* ...TY tag that fits specifications */+	if ( !strncmp( p, "TY  - ",  6 ) ) return 1;+	/* ...TY tag with an extra space? */+	if ( !strncmp( p, "TY   - ", 7 ) ) return 1;+	return 0;+}++static int+is_ris_end_tag( char *p )+{+	/* ...ER tag that fits specifications */+	if ( !strncmp( p, "ER  -",  5 ) ) return 1;+	/* ...ER tag with an extra space? */+	if ( !strncmp( p, "ER   -", 6 ) ) return 1;+	return 0;+}++static int+readmore( FILE *fp, char *buf, int bufsize, int *bufpos, str *line )+{ 	if ( line->len ) return 1;-	else return newstr_fget( fp, buf, bufsize, bufpos, line );+	else return str_fget( fp, buf, bufsize, bufpos, line ); } -int-risin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, -		newstr *reference, int *fcharset )+static int+risin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset ) { 	int haveref = 0, inref = 0, readtoofar = 0;-	unsigned char *up; 	char *p;+ 	*fcharset = CHARSET_UNKNOWN;+ 	while ( !haveref && readmore( fp, buf, bufsize, bufpos, line ) ) {-		if ( !line->data || line->len==0 ) continue;++		if ( str_is_empty( line ) ) continue;+ 		p = &( line->data[0] );-		/* Recognize UTF8 BOM */-		up = (unsigned char * ) p;-		if ( line->len > 2 && -				up[0]==0xEF && up[1]==0xBB && up[2]==0xBF ) {++		if ( utf8_is_bom( p ) ) { 			*fcharset = CHARSET_UNICODE; 			p += 3; 		}-		/* Each reference starts with 'TY  - ' && -		 * ends with 'ER  - ' */-		if ( strncmp(p,"TY  - ",6)==0 ) {-			if ( !inref ) {-				inref = 1;-			} else {++		/* References are bounded by tags 'TY  - ' && 'ER  - ' */+		if ( is_ris_start_tag( p ) ) {+			if ( !inref ) inref = 1;+			else { 				/* we've read too far.... */ 				readtoofar = 1; 				inref = 0; 			} 		}-		if ( risin_istag( p ) ) {++		if ( is_ris_tag( p ) ) { 			if ( !inref ) { 				fprintf(stderr,"Warning.  Tagged line not " 					"in properly started reference.\n"); 				fprintf(stderr,"Ignored: '%s'\n", p );-			} else if ( !strncmp(p,"ER  -",5) ) {+			} else if ( is_ris_end_tag( p ) ) { 				inref = 0; 			} else {-				newstr_addchar( reference, '\n' );-				newstr_strcat( reference, p );+				str_addchar( reference, '\n' );+				str_strcatc( reference, p ); 			} 		} 		/* not a tag, but we'll append to last values ...*/-		else if ( inref && strncmp(p,"ER  -",5)) {-			newstr_addchar( reference, '\n' );-			newstr_strcat( reference, p );+		else if ( inref && !is_ris_end_tag( p ) ) {+			str_addchar( reference, '\n' );+			str_strcatc( reference, p ); 		} 		if ( !inref && reference->len ) haveref = 1;-		if ( !readtoofar ) newstr_empty( line );+		if ( !readtoofar ) str_empty( line ); 	}+ 	if ( inref ) haveref = 1;+ 	return haveref; } @@ -142,103 +190,143 @@ *****************************************************/  static char*-process_line2( newstr *tag, newstr *data, char *p )+process_untagged_line( str *value, char *p ) { 	while ( *p==' ' || *p=='\t' ) p++; 	while ( *p && *p!='\r' && *p!='\n' )-		newstr_addchar( data, *p++ );+		str_addchar( value, *p++ ); 	while ( *p=='\r' || *p=='\n' ) p++; 	return p; }  static char*-process_line( newstr *tag, newstr *data, char *p )+process_tagged_line( str *tag, str *value, char *p ) { 	int i = 0;-	while ( i<6 && *p ) {-		if ( i<2 ) newstr_addchar( tag, *p );++	while ( i<6 && *p && *p!='\n' && *p!='\r' ) {+		if ( i<2 ) str_addchar( tag, *p ); 		p++; 		i++; 	}+ 	while ( *p==' ' || *p=='\t' ) p++;+ 	while ( *p && *p!='\r' && *p!='\n' )-		newstr_addchar( data, *p++ );-	newstr_trimendingws( data );+		str_addchar( value, *p++ );+	str_trimendingws( value );+ 	while ( *p=='\n' || *p=='\r' ) p++;+ 	return p; } -int-risin_processf( fields *risin, char *p, char *filename, long nref )+static int+merge_tag_value( fields *risin, str *tag, str *value, int *tag_added ) {-	newstr tag, data;-	int status, n;+	str *oldval;+	int n, status; -	newstrs_init( &tag, &data, NULL );+	if ( str_has_value( value ) ) {+		if ( *tag_added==1 ) {+			n = fields_num( risin );+			if ( n>0 ) {+				oldval = fields_value( risin, n-1, FIELDS_STRP );+				str_addchar( oldval, ' ' );+				str_strcat( oldval, value );+				if ( str_memerr( oldval ) ) return BIBL_ERR_MEMERR;+			}+		}+		else  {+			status = fields_add( risin, str_cstr( tag ), str_cstr( value ), 0 );+			if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;+			*tag_added = 1;+		}+	}+	return BIBL_OK;+} +static int+add_tag_value( fields *risin, str *tag, str *value, int *tag_added )+{+	int status;++	if ( str_has_value( value ) ) {+		status = fields_add( risin, str_cstr( tag ), str_cstr( value ), 0 );+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;+		*tag_added = 1;+	}++	else {+		*tag_added = 0;+	}++	return BIBL_OK;+}++static int+risin_processf( fields *risin, char *p, char *filename, long nref, param *pm )+{+	int status, tag_added = 0, ret = 1;+	str tag, value;++	strs_init( &tag, &value, NULL );+ 	while ( *p ) {-		if ( risin_istag( p ) ) {-		p = process_line( &tag, &data, p );-		/* no anonymous fields allowed */-		if ( tag.len )-			status = fields_add( risin, tag.data, data.data, 0 );-			if ( status!=FIELDS_OK ) return 0;-		} else {-			p = process_line2( &tag, &data, p );-			n = fields_num( risin );-			if ( data.len && n>0 ) {-				newstr *od;-				od = fields_value( risin, n-1, FIELDS_STRP );-				newstr_addchar( od, ' ' );-				newstr_strcat( od, data.data );++		/* ...tag, add entry */+		if ( is_ris_tag( p ) ) {+			str_empty( &tag );+			str_empty( &value );+			p = process_tagged_line( &tag, &value, p );+			status = add_tag_value( risin, &tag, &value, &tag_added );+			if ( status!=BIBL_OK ) {+				ret = 0;+				goto out; 			} 		}-		newstrs_empty( &tag, &data, NULL );++		/* ...no tag, merge with previous line */+		else {+			str_empty( &value );+			p = process_untagged_line( &value, p );+			status = merge_tag_value( risin, &tag, &value, &tag_added );+			if ( status!=BIBL_OK ) {+				ret = 0;+				goto out;+			}+		}+ 	}+out: -	newstrs_free( &tag, &data, NULL );-	return 1;+	strs_free( &tag, &value, NULL );+	return ret; }  /*****************************************************  PUBLIC: int risin_typef() *****************************************************/ -int-risin_typef( fields *risin, char *filename, int nref, param *p, variants *all, int nall )+static int+risin_typef( fields *risin, char *filename, int nref, param *p ) {-	char *refnum = "";-	int n, reftype, nreftype;-	n = fields_find( risin, "TY", 0 );-	nreftype = fields_find( risin, "ID", 0 );-	if ( nreftype!=-1 ) refnum = risin[n].data->data;-	if ( n!=-1 )-		reftype = get_reftype( (risin[n].data)->data, nref, p->progname,-			all, nall, refnum );-	else-		reftype = get_reftype( "", nref, p->progname, all, nall, refnum ); /*default */-	return reftype;+	int ntypename, nrefname, is_default;+	char *refname = "", *typename = "";++	ntypename = fields_find( risin, "TY", LEVEL_MAIN );+	nrefname  = fields_find( risin, "ID", LEVEL_MAIN );+	if ( ntypename!=-1 ) typename = fields_value( risin, ntypename, FIELDS_CHRP_NOUSE );+	if ( nrefname!=-1 )  refname  = fields_value( risin, nrefname,  FIELDS_CHRP_NOUSE );++	return get_reftype( typename, nref, p->progname, p->all, p->nall, refname, &is_default, REFTYPE_CHATTY ); }  /*****************************************************  PUBLIC: int risin_convertf() *****************************************************/ -/* oxfordjournals hide the DOI in the NOTES N1 field */ static int-risin_addnotes( fields *f, char *tag, newstr *s, int level )-{-	int doi, status;-	doi = is_doi( s->data );-	if ( doi!=-1 )-		status = fields_add( f, "DOI", &(s->data[doi]), level );-	else-		status = fields_add( f, tag, s->data, level );-	if ( status==FIELDS_OK ) return BIBL_OK;-	else return BIBL_ERR_MEMERR;-}--static int is_uri_file_scheme( char *p ) { 	if ( !strncmp( p, "file:", 5 ) ) return 5;@@ -246,209 +334,214 @@ }  static int-is_uri_remote_scheme( char *p )-{-	char *scheme[] = { "http:", "ftp:", "git:", "gopher:" };-	int i, len, nschemes = sizeof( scheme ) / sizeof( scheme[0] );-	for ( i=0; i<nschemes; ++i ) {-		len = strlen( scheme[i] );-		if ( !strncmp( p, scheme[i], len ) ) return len;-	}-	return 0;-}--static int-risin_addfile( fields *f, char *tag, newstr *s, int level )+risin_linkedfile( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout ) {-	int status, n;+	int fstatus, m; 	char *p;  	/* if URL is file:///path/to/xyz.pdf, only store "///path/to/xyz.pdf" */-	n = is_uri_file_scheme( s->data );-	if ( n ) {+	m = is_uri_file_scheme( str_cstr( invalue ) );+	if ( m ) { 		/* skip past "file:" and store only actual path */-		p = s->data + n;-		status = fields_add( f, tag, p, level );-		if ( status==FIELDS_OK ) return BIBL_OK;+		p = invalue->data + m;+		fstatus = fields_add( bibout, outtag, p, level );+		if ( fstatus==FIELDS_OK ) return BIBL_OK; 		else return BIBL_ERR_MEMERR; 	}  	/* if URL is http:, ftp:, etc. store as a URL */-	n = is_uri_remote_scheme( s->data );-	if ( n ) {-		status = fields_add( f, "URL", s->data, level );-		if ( status==FIELDS_OK ) return BIBL_OK;+	m = is_uri_remote_scheme( str_cstr( invalue ) );+	if ( m!=-1 ) {+		fstatus = fields_add( bibout, "URL", str_cstr( invalue ), level );+		if ( fstatus==FIELDS_OK ) return BIBL_OK; 		else return BIBL_ERR_MEMERR; 	}  	/* badly formed, RIS wants URI, but store value anyway */-	status = fields_add( f, tag, s->data, level );-	if ( status==FIELDS_OK ) return BIBL_OK;+	fstatus = fields_add( bibout, outtag, str_cstr( invalue ), level );+	if ( fstatus==FIELDS_OK ) return BIBL_OK; 	else return BIBL_ERR_MEMERR; }  /* scopus puts DOI in the DO or DI tag, but it needs cleaning */ static int-risin_adddoi( fields *f, char *tag, newstr *s, int level )+risin_doi( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout ) {-	int status, doi;-	doi = is_doi( s->data );+	int fstatus, doi;+	doi = is_doi( str_cstr( invalue ) ); 	if ( doi!=-1 ) {-		status = fields_add( f, "DOI", &(s->data[doi]), level );-		if ( status==FIELDS_OK ) return BIBL_OK;-		else return BIBL_ERR_MEMERR;+		fstatus = fields_add( bibout, "DOI", &(invalue->data[doi]), level );+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	}-	else return BIBL_OK;+	return BIBL_OK; }  static int-risin_adddate( fields *f, char *tag, newstr *d, int level )+risin_date( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout ) {-	char *p = d->data;-	newstr date;+	char *p = invalue->data; 	int part, status;+	str date; -	part = ( !strncasecmp( tag, "PART", 4 ) );+	part = ( !strncasecmp( outtag, "PART", 4 ) ); -	newstr_init( &date );-	while ( *p && *p!='/' ) newstr_addchar( &date, *p++ );+	str_init( &date );+	while ( *p && *p!='/' ) str_addchar( &date, *p++ );+	if ( str_memerr( &date ) ) return BIBL_ERR_MEMERR; 	if ( *p=='/' ) p++;-	if ( date.len>0 ) {-		if ( part ) status = fields_add( f, "PARTYEAR", date.data, level );-		else        status = fields_add( f, "YEAR",     date.data, level );+	if ( str_has_value( &date ) ) {+		if ( part ) status = fields_add( bibout, "PARTDATE:YEAR", str_cstr( &date ), level );+		else        status = fields_add( bibout, "DATE:YEAR",     str_cstr( &date ), level ); 		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	} -	newstr_empty( &date );-	while ( *p && *p!='/' ) newstr_addchar( &date, *p++ );+	str_empty( &date );+	while ( *p && *p!='/' ) str_addchar( &date, *p++ );+	if ( str_memerr( &date ) ) return BIBL_ERR_MEMERR; 	if ( *p=='/' ) p++;-	if ( date.len>0 ) {-		if ( part ) status = fields_add( f, "PARTMONTH", date.data, level );-		else        status = fields_add( f, "MONTH",     date.data, level );+	if ( str_has_value( &date ) ) {+		if ( part ) status = fields_add( bibout, "PARTDATE:MONTH", str_cstr( &date ), level );+		else        status = fields_add( bibout, "DATE:MONTH",     str_cstr( &date ), level ); 		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	} -	newstr_empty( &date );-	while ( *p && *p!='/' ) newstr_addchar( &date, *p++ );+	str_empty( &date );+	while ( *p && *p!='/' ) str_addchar( &date, *p++ );+	if ( str_memerr( &date ) ) return BIBL_ERR_MEMERR; 	if ( *p=='/' ) p++;-	if ( date.len>0 ) {-		if ( part ) status = fields_add( f, "PARTDAY", date.data, level );-		else        status = fields_add( f, "DAY",     date.data, level );+	if ( str_has_value( &date ) ) {+		if ( part ) status = fields_add( bibout, "PARTDATE:DAY", str_cstr( &date ), level );+		else        status = fields_add( bibout, "DATE:DAY",     str_cstr( &date ), level ); 		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	} -	newstr_empty( &date );-	while ( *p ) newstr_addchar( &date, *p++ );-	if ( date.len>0 ) {-		if ( part ) status = fields_add( f, "PARTDATEOTHER", date.data,level);-		else        status = fields_add( f, "DATEOTHER", date.data, level );+	str_empty( &date );+	while ( *p ) str_addchar( &date, *p++ );+	if ( str_memerr( &date ) ) return BIBL_ERR_MEMERR;+	if ( str_has_value( &date ) ) {+		if ( part ) status = fields_add( bibout, "PARTDATE:OTHER", str_cstr( &date ), level );+		else        status = fields_add( bibout, "DATE:OTHER",     str_cstr( &date ), level ); 		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR; 	}-	newstr_free( &date );+	str_free( &date ); 	return BIBL_OK; } -static void-risin_report_notag( param *p, char *tag )-{-	if ( p->verbose && strcmp( tag, "TY" ) ) {-		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );-		fprintf( stderr, "Did not identify RIS tag '%s'\n", tag );-	}-}- static int-risin_simple( fields *f, char *tag, char *value, int level )+risin_person( fields *bibin, int n, str *intag, str *invalue, int level, param *pm, char *outtag, fields *bibout ) {-	int fstatus = fields_add( f, tag, value, level );-	if ( fstatus==FIELDS_OK ) return BIBL_OK;-	else return BIBL_ERR_MEMERR;-}+	int i, begin, end, ok, status = BIBL_OK;+	slist tokens;+	str name; -int-risin_convertf( fields *risin, fields *f, int reftype, param *p, variants *all, int nall )-{-	int process, level, i, n, nfields, ok, fstatus, status = BIBL_OK;-	char *outtag, *tag, *value;-	newstr *t, *d;+	str_init( &name );+	slist_init( &tokens ); -	nfields = fields_num( risin );+	status = slist_tokenize( &tokens, invalue, " \t\r\n", 1 );+	if ( status!=SLIST_OK ) { status = BIBL_ERR_MEMERR; goto out; } -	for ( i=0; i<nfields; ++i ) {-		t = fields_tag( risin, i, FIELDS_STRP );-		n = translate_oldtag( t->data, reftype, all, nall, &process, &level, &outtag );-		if ( n==-1 ) {-			risin_report_notag( p, t->data );-			continue;+	begin = 0;+	while ( begin < tokens.n ) {++		end = begin + 1;++		while ( end < tokens.n && strcasecmp( slist_cstr( &tokens, end ), "and" ) )+			end++;++		str_empty( &name );+		for ( i=begin; i<end; ++i ) {+			if ( i>begin ) str_addchar( &name, ' ' );+			str_strcat( &name, slist_str( &tokens, i ) ); 		}-		if ( process==ALWAYS ) continue; /* add in core code */ -		d = fields_value( risin, i, FIELDS_STRP );+		ok = name_add( bibout, outtag, str_cstr( &name ), level, &(pm->asis), &(pm->corps) );+		if ( !ok ) { status = BIBL_ERR_MEMERR; goto out; } -		switch ( process ) {+		begin = end + 1; -		case SIMPLE:-			status = risin_simple( f, outtag, d->data, level );-			break;+		/* Handle repeated 'and' errors */+		while ( begin < tokens.n && !strcasecmp( slist_cstr( &tokens, begin ), "and" ) )+			begin++; -		case PERSON:-			ok = name_add( f, outtag, d->data, level, &(p->asis), &(p->corps) );-			if ( ok ) status = BIBL_OK;-			else status = BIBL_ERR_MEMERR;-			break;+	} -		case TITLE:-			ok = title_process( f, outtag, d->data, level, p->nosplittitle );-			if ( ok ) status = BIBL_OK;-			else status = BIBL_ERR_MEMERR;-			break;+out:+	str_free( &name );+	slist_free( &tokens );+	return status;+} -		case SERIALNO:-			ok = addsn( f, d->data, level );-			if ( ok ) status = BIBL_OK;-			else status = BIBL_ERR_MEMERR;-			break;+/* look for thesis-type hint */+static int+risin_thesis_hints( fields *bibin, int reftype, param *p, fields *bibout )+{+	int i, nfields, fstatus;+	char *tag, *value; -		case DATE:-			status = risin_adddate( f, outtag, d, level );-			break;+	if ( strcasecmp( p->all[reftype].type, "THES" ) ) return BIBL_OK; -		case NOTES:-			status = risin_addnotes( f, outtag, d, level );-			break;+	nfields = fields_num( bibin );+	for ( i=0; i<nfields; ++i ) {+		tag = fields_tag( bibin, i, FIELDS_CHRP );+		if ( strcasecmp( tag, "U1" ) ) continue;+		value = fields_value( bibin, i, FIELDS_CHRP );+		if ( !strcasecmp(value,"Ph.D. Thesis")||+		     !strcasecmp(value,"Masters Thesis")||+		     !strcasecmp(value,"Diploma Thesis")||+		     !strcasecmp(value,"Doctoral Thesis")||+		     !strcasecmp(value,"Habilitation Thesis")) {+			fstatus = fields_add( bibout, "GENRE", value, 0 );+			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;+		}+	}+	return BIBL_OK;+} -		case DOI:-			status = risin_adddoi( f, outtag, d, level );-			break;+static void+risin_report_notag( param *p, char *tag )+{+	if ( p->verbose && strcmp( tag, "TY" ) ) {+		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );+		fprintf( stderr, "Did not identify RIS tag '%s'\n", tag );+	}+} -		case LINKEDFILE:-			status = risin_addfile( f, outtag, d, level );-			break;+static int+risin_convertf( fields *bibin, fields *bibout, int reftype, param *p )+{+	static int (*convertfns[NUM_REFTYPES])(fields *, int, str *, str *, int, param *, char *, fields *) = {+		[ 0 ... NUM_REFTYPES-1 ] = generic_null,+		[ SIMPLE       ] = generic_simple,+		[ TITLE        ] = generic_title,+		[ PERSON       ] = risin_person,+		[ SERIALNO     ] = generic_serialno,+		[ NOTES        ] = generic_notes,+		[ URL          ] = generic_url,+		[ DATE         ] = risin_date,+		[ DOI          ] = risin_doi,+		[ LINKEDFILE   ] = risin_linkedfile,+        };+	int process, level, i, nfields, status = BIBL_OK;+	str *intag, *invalue;+	char *outtag; -		default:-			status = BIBL_OK;-			break;+	nfields = fields_num( bibin ); +	for ( i=0; i<nfields; ++i ) {+		intag = fields_tag( bibin, i, FIELDS_STRP );+		if ( !translate_oldtag( intag->data, reftype, p->all, p->nall, &process, &level, &outtag ) ) {+			risin_report_notag( p, intag->data );+			continue; 		}+		invalue = fields_value( bibin, i, FIELDS_STRP );++		status = convertfns[ process ] ( bibin, i, intag, invalue, level, p, outtag, bibout ); 		if ( status!=BIBL_OK ) return status; 	} -	/* look for thesis-type hint */-	if ( !strcasecmp( all[reftype].type, "THES" ) ) {-		for ( i=0; i<nfields; ++i ) {-			tag = fields_tag( risin, i, FIELDS_CHRP );-			if ( strcasecmp( tag, "U1" ) ) continue;-			value = fields_value( risin, i, FIELDS_CHRP );-			if ( !strcasecmp(value,"Ph.D. Thesis")||-			     !strcasecmp(value,"Masters Thesis")||-			     !strcasecmp(value,"Diploma Thesis")||-			     !strcasecmp(value,"Doctoral Thesis")||-			     !strcasecmp(value,"Habilitation Thesis")) {-				fstatus = fields_add( f, "GENRE", value, 0 );-				if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;-			}-		}-	}+	if ( status == BIBL_OK ) status = risin_thesis_hints( bibin, reftype, p, bibout );++	if ( status==BIBL_OK && p->verbose ) fields_report( bibout, stderr );  	return status; }
− bibutils/risin.h
@@ -1,28 +0,0 @@-/*- * risin.h- *- * Copyright (c) Chris Putnam 2003-2014- *- * Source code released under the GPL version 2- *- */-#ifndef RISIN_H-#define RISIN_H--#include "newstr.h"-#include "fields.h"-#include "reftypes.h"-#include "bibutils.h"--extern int risin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );-extern int risin_processf( fields *risin, char *p, char *filename, long nref );-extern int risin_typef( fields *risin, char *filename, int nref, param *p, variants *all, int nall );-extern int risin_convertf( fields *risin, fields *info, int reftype, param *p, variants *all, int nall ); --extern void risin_initparams( param *p, const char *progname );--extern variants ris_all[];-extern int ris_nall;--#endif-
bibutils/risout.c view
@@ -1,7 +1,7 @@ /*  * risout.c  *- * Copyright (c) Chris Putnam 2003-2013+ * Copyright (c) Chris Putnam 2003-2017  *  * Source code released under the GPL version 2  *@@ -11,13 +11,18 @@ #include <string.h> #include <ctype.h> #include "utf8.h"-#include "newstr.h"+#include "str.h" #include "strsearch.h" #include "fields.h"-#include "doi.h" #include "name.h"-#include "risout.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 ) {@@ -44,7 +49,7 @@ }  enum { -	TYPE_UNKNOWN,+	TYPE_UNKNOWN = 0, 	TYPE_STD,                /* standard/generic */ 	TYPE_ABSTRACT,           /* abstract */ 	TYPE_ARTICLE,            /* article */@@ -55,9 +60,9 @@ 	TYPE_ELEC,               /* electronic */ 	TYPE_HEAR,               /* hearing */ 	TYPE_MAGARTICLE,         /* magazine article */-	TYPE_NEWS,               /* newspaper */+	TYPE_NEWSPAPER,          /* newspaper */ 	TYPE_MPCT,               /* mpct */-	TYPE_PAMP,               /* pamphlet */+	TYPE_PAMPHLET,           /* pamphlet */ 	TYPE_PATENT,             /* patent */ 	TYPE_PCOMM,              /* personal communication */ 	TYPE_PROGRAM,            /* program */@@ -71,43 +76,80 @@ 	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 ) {-	switch( type ) {-	case TYPE_UNKNOWN:            fprintf( fp, "TYPE_UNKNOWN" );            break;-	case TYPE_STD:                fprintf( fp, "TYPE_STD" );                break;-	case TYPE_ABSTRACT:           fprintf( fp, "TYPE_ABSTRACT" );           break;-	case TYPE_ARTICLE:            fprintf( fp, "TYPE_ARTICLE" );            break;-	case TYPE_BOOK:               fprintf( fp, "TYPE_BOOK" );               break;-	case TYPE_CASE:               fprintf( fp, "TYPE_CASE" );               break;-	case TYPE_INBOOK:             fprintf( fp, "TYPE_INBOOK" );             break;-	case TYPE_CONF:               fprintf( fp, "TYPE_CONF" );               break;-	case TYPE_ELEC:               fprintf( fp, "TYPE_ELEC" );               break;-	case TYPE_HEAR:               fprintf( fp, "TYPE_HEAR" );               break;-	case TYPE_MAGARTICLE:         fprintf( fp, "TYPE_MAGARTICLE" );         break;-	case TYPE_NEWS:               fprintf( fp, "TYPE_NEWS" );               break;-	case TYPE_MPCT:               fprintf( fp, "TYPE_MCPT" );               break;-	case TYPE_PAMP:               fprintf( fp, "TYPE_PAMP" );               break;-	case TYPE_PATENT:             fprintf( fp, "TYPE_PATENT" );             break;-	case TYPE_PCOMM:              fprintf( fp, "TYPE_PCOMM" );              break;-	case TYPE_PROGRAM:            fprintf( fp, "TYPE_PROGRAM" );            break;-	case TYPE_REPORT:             fprintf( fp, "TYPE_REPORT" );             break;-	case TYPE_STATUTE:            fprintf( fp, "TYPE_STATUTE" );            break;-	case TYPE_THESIS:             fprintf( fp, "TYPE_THESIS" );             break;-	case TYPE_MASTERSTHESIS:      fprintf( fp, "TYPE_MASTERSTHESIS" );      break;-	case TYPE_PHDTHESIS:          fprintf( fp, "TYPE_PHDTHESIS" );          break;-	case TYPE_DIPLOMATHESIS:      fprintf( fp, "TYPE_DIPLOMATHESIS" );      break;-	case TYPE_DOCTORALTHESIS:     fprintf( fp, "TYPE_DOCTORALTHESIS" );     break;-	case TYPE_HABILITATIONTHESIS: fprintf( fp, "TYPE_HABILITATIONTHESIS" ); break;-	case TYPE_MAP:                fprintf( fp, "TYPE_MAP" );                break;-	case TYPE_UNPUBLISHED:        fprintf( fp, "TYPE_UNPUBLISHED" );        break;-	default:                      fprintf( fp, "Error - type not in enum" );break;-	}+	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_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;@@ -125,7 +167,7 @@ 		{ "journal article",           TYPE_ARTICLE }, 		{ "magazine",                  TYPE_MAGARTICLE }, 		{ "conference publication",    TYPE_CONF },-		{ "newspaper",                 TYPE_NEWS },+		{ "newspaper",                 TYPE_NEWSPAPER }, 		{ "legislation",               TYPE_STATUTE }, 		{ "communication",             TYPE_PCOMM }, 		{ "hearing",                   TYPE_HEAR },@@ -144,26 +186,19 @@ 		{ "map",                       TYPE_MAP }, 	}; 	int nmatch_genres = sizeof( match_genres ) / sizeof( match_genres[0] );-	int type, i, j; 	char *tag, *value;+	int type, i, j;  	type = TYPE_UNKNOWN;  	for ( i=0; i<fields_num( f ); ++i ) {-		if ( !fields_match_tag( f, i, "GENRE" ) &&-		     !fields_match_tag( f, i, "NGENRE" ) )-			continue;+		tag = ( char * ) fields_tag( f, i, FIELDS_CHRP );+		if ( strcmp( tag, "GENRE" ) && strcmp( tag, "NGENRE" ) ) continue; 		value = ( char * ) fields_value( f, i, FIELDS_CHRP ); 		for ( j=0; j<nmatch_genres; ++j ) 			if ( !strcasecmp( match_genres[j].name, value ) ) 				type = match_genres[j].type;-		if ( p->verbose ) {-			tag = ( char * ) fields_tag( f, i, FIELDS_CHRP );-			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" );-		}+		if ( p->verbose ) verbose_type_assignment( tag, value, p, type ); 		if ( type==TYPE_UNKNOWN ) { 			if ( !strcasecmp( value, "periodical" ) ) 				type = TYPE_ARTICLE;@@ -181,12 +216,7 @@  	} -	if ( p->verbose ) {-		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );-		fprintf( stderr, "Type from genre element: " );-		write_type( stderr, type );-		fprintf( stderr, "\n" );-	}+	if ( p->verbose ) verbose_type_identified( "genre", p, type );  	return type; }@@ -202,7 +232,8 @@ 		{ "cartographic",              TYPE_MAP     }, 	}; 	int nmatch_res = sizeof( match_res ) / sizeof( match_res[0] );-	int type, i, j;+	vplist_index i;+	int type, j; 	char *value; 	vplist a; @@ -217,20 +248,10 @@ 			if ( !strcasecmp( value, match_res[j].name ) ) 				type = match_res[j].type; 		}-		if ( p->verbose ) {-			if ( p->progname ) fprintf( stderr, "%s: ", p->progname );-			fprintf( stderr, "Type from tag 'RESOURCE' data '%s': ", value );-			write_type( stderr, type );-			fprintf( stderr, "\n" );-		}+		if ( p->verbose ) verbose_type_assignment( "RESOURCE", value, p, type ); 	} -	if ( p->verbose ) {-		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );-		fprintf( stderr, "Type from resource element: " );-		write_type( stderr, type );-		fprintf( stderr, "\n" );-	}+	if ( p->verbose ) verbose_type_identified( "resource", p, type );  	vplist_free( &a ); 	return type;@@ -245,13 +266,13 @@ 	int i, monographic = 0, monographic_level = 0; //	int text = 0; 	for ( i=0; i<f->n; ++i ) {-		if ( !strcasecmp( f->tag[i].data, "issuance" ) &&-		     !strcasecmp( f->data[i].data, "MONOGRAPHIC" ) ){+		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( f->tag[i].data, "typeOfResource" ) &&-//		     !strcasecmp( f->data[i].data,"text") ) {+//		if ( !strcasecmp( (char *) fields_tag( f, i, FIELDS_CHRP_NOUSE ), "typeOfResource" ) &&+//		     !strcasecmp( (char *) fields_value( f, i, FIELDS_CHRP_NOUSE ), "text" ) ) { //			text = 1; //		} 	}@@ -295,242 +316,241 @@ }  static void-output_type( FILE *fp, int type, param *p )+append_type( int type, param *p, fields *out, int *status ) {-	match_type tyout[] = {-		{ "STD",  TYPE_STD },-		{ "ABST", TYPE_ABSTRACT },-		{ "JOUR", TYPE_ARTICLE },-		{ "BOOK", TYPE_BOOK },-		{ "CASE", TYPE_CASE },-		{ "CHAP", TYPE_INBOOK },-		{ "CONF", TYPE_CONF },-		{ "ELEC", TYPE_ELEC },-		{ "HEAR", TYPE_HEAR },-		{ "MGZN", TYPE_MAGARTICLE },-		{ "NEWS", TYPE_NEWS },-		{ "MPCT", TYPE_MPCT },-		{ "PAMP", TYPE_PAMP },-		{ "PAT",  TYPE_PATENT },-		{ "PCOMM",TYPE_PCOMM },-		{ "COMP", TYPE_PROGRAM },-		{ "RPRT", TYPE_REPORT },-		{ "STAT", TYPE_STATUTE },-		{ "THES", TYPE_THESIS },-		{ "THES", TYPE_MASTERSTHESIS },-		{ "THES", TYPE_PHDTHESIS },-		{ "THES", TYPE_DIPLOMATHESIS },-		{ "THES", TYPE_DOCTORALTHESIS },-		{ "THES", TYPE_HABILITATIONTHESIS },-		{ "MAP",  TYPE_MAP },-		{ "UNPB", TYPE_UNPUBLISHED }+	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 ntyout = sizeof( tyout ) / sizeof( tyout[0] );-	int i, found;+	int fstatus; -	fprintf( fp, "TY  - " );-	found = 0;-	for ( i=0; i<ntyout && !found ; ++i ) {-		if ( tyout[i].type == type ) {-			fprintf( fp, "%s", tyout[i].name );-			found = 1;-		}-	}-	/* Report internal error, default to TYPE_STD */-	if ( !found ) {+	if ( type < 0 || type >= NUM_TYPES ) { 		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );-		fprintf( stderr, "Internal Error: Cannot identify type %d\n",-			type );-		fprintf( fp, "STD" );+		fprintf( stderr, "Internal error: Cannot recognize type %d, switching to TYPE_STD %d\n", type, TYPE_STD );+		type = TYPE_STD; 	}-	fprintf( fp, "\n" );++	fstatus = fields_add( out, "TY", typenames[ type ], LEVEL_MAIN );+	if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR; }  static void-output_people( FILE *fp, fields *f, char *tag, char *ristag, int level )+append_people( fields *f, char *tag, char *ristag, int level, fields *out, int *status ) {-	newstr oneperson;+	vplist_index i;+	str oneperson; 	vplist people;-	int i;-	newstr_init( &oneperson );+	int fstatus;++	str_init( &oneperson ); 	vplist_init( &people ); 	fields_findv_each( f, level, FIELDS_CHRP, &people, tag ); 	for ( i=0; i<people.n; ++i ) { 		name_build_withcomma( &oneperson, ( char * ) vplist_get( &people, i ) );-		fprintf( fp, "%s  - %s\n", ristag, oneperson.data );+		if ( str_memerr( &oneperson ) ) { *status = BIBL_ERR_MEMERR; goto out; }+		fstatus = fields_add_can_dup( out, ristag, str_cstr( &oneperson ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) { *status = BIBL_ERR_MEMERR; goto out; } 	}+out: 	vplist_free( &people );-	newstr_free( &oneperson );+	str_free( &oneperson ); }  static void-output_date( FILE *fp, fields *f )+append_date( fields *in, fields *out, int *status ) {-	char *year  = fields_findv_firstof( f, LEVEL_ANY, FIELDS_CHRP,-			"YEAR", "PARTYEAR", NULL );-	char *month = fields_findv_firstof( f, LEVEL_ANY, FIELDS_CHRP,-			"MONTH", "PARTMONTH", NULL );-	char *day   = fields_findv_firstof( f, LEVEL_ANY, FIELDS_CHRP,-			"DAY", "PARTDAY", NULL );-	if ( year )-		fprintf( fp, "PY  - %s\n", year );+	char *year, *month, *day;+	str date;+	int fstatus;++	year  = fields_findv_firstof( in, LEVEL_ANY, FIELDS_CHRP, "DATE:YEAR",  "PARTDATE:YEAR",  NULL );+	month = fields_findv_firstof( in, LEVEL_ANY, FIELDS_CHRP, "DATE:MONTH", "PARTDATE:MONTH", NULL );+	day   = fields_findv_firstof( in, LEVEL_ANY, FIELDS_CHRP, "DATE:DAY",   "PARTDATE:DAY",   NULL );++	if ( year ) {+		fstatus = fields_add( out, "PY", year, LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	}+ 	if ( year || month || day ) {-		fprintf( fp, "DA  - " );-		if ( year ) fprintf( fp, "%s", year );-		fprintf( fp, "/" );-		if ( month ) fprintf( fp, "%s", month );-		fprintf( fp, "/" );-		if ( day ) fprintf( fp, "%s", day );-		fprintf( fp, "\n" );+		str_init( &date );++		if ( year ) str_strcatc( &date, year );+		str_addchar( &date, '/' );+		if ( month ) str_strcatc( &date, month );+		str_addchar( &date, '/' );+		if ( day ) str_strcatc( &date, day );++		if ( str_memerr( &date ) ) { *status = BIBL_ERR_MEMERR; str_free( &date ); return; }++		fstatus = fields_add( out, "DA", str_cstr( &date ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;++		str_free( &date ); 	} }  static void-output_titlecore( FILE *fp, fields *f, char *ristag, int level,-	char *maintag, char *subtag )+append_titlecore( fields *in, char *ristag, int level, char *maintag, char *subtag, fields *out, int *status ) {-	newstr *mainttl = fields_findv( f, level, FIELDS_STRP, maintag );-	newstr *subttl  = fields_findv( f, level, FIELDS_STRP, subtag );+	str *mainttl = fields_findv( in, level, FIELDS_STRP, maintag );+	str *subttl  = fields_findv( in, level, FIELDS_STRP, subtag );+	str fullttl;+	int fstatus; -	if ( !mainttl ) return;+	str_init( &fullttl ); -	fprintf( fp, "%s  - %s", ristag, mainttl->data );-	if ( subttl ) {-		if ( mainttl->len > 0 &&-		     mainttl->data[ mainttl->len - 1 ]!='?' )-			fprintf( fp, ":" );-		fprintf( fp, " %s", subttl->data );+	title_combine( &fullttl, mainttl, subttl );++	if ( str_memerr( &fullttl ) ) {+		*status = BIBL_ERR_MEMERR;+		goto out; 	}-	fprintf( fp, "\n" );-} -static int-type_is_element( int type )-{-	if ( type==TYPE_ARTICLE )    return 1;-	if ( type==TYPE_INBOOK )     return 1;-	if ( type==TYPE_MAGARTICLE ) return 1;-	if ( type==TYPE_NEWS )       return 1;-	if ( type==TYPE_ABSTRACT )   return 1;-	if ( type==TYPE_CONF )       return 1;-	return 0;-}+	if ( str_has_value( &fullttl ) ) {+		fstatus = fields_add( out, ristag, str_cstr( &fullttl ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	} -static int-type_uses_journal( int type )-{-	if ( type==TYPE_ARTICLE )    return 1;-	if ( type==TYPE_MAGARTICLE ) return 1;-	return 0;+out:+	str_free( &fullttl ); }  static void-output_alltitles( FILE *fp, fields *f, int type )+append_alltitles( fields *in, int type, fields *out, int *status ) {-	output_titlecore( fp, f, "TI", 0, "TITLE", "SUBTITLE" );-	output_titlecore( fp, f, "T2", -1, "SHORTTITLE", "SHORTSUBTITLE" );-	if ( type_is_element( type ) ) {-		if ( type_uses_journal( type ) )-			output_titlecore( fp, f, "JO", 1, "TITLE", "SUBTITLE" );-		else output_titlecore( fp, f, "BT", 1, "TITLE", "SUBTITLE" );-		output_titlecore( fp, f, "T3", 2, "TITLE", "SUBTITLE" );+	append_titlecore( in, "TI", 0, "TITLE", "SUBTITLE", out, status );+	append_titlecore( in, "T2", -1, "SHORTTITLE", "SHORTSUBTITLE", out, status );+	if ( type_is_element[ type ] ) {+		if ( type_uses_journal[ type ] )+			append_titlecore( in, "JO", 1, "TITLE", "SUBTITLE", out, status );+		else append_titlecore( in, "BT", 1, "TITLE", "SUBTITLE", out, status );+		append_titlecore( in, "T3", 2, "TITLE", "SUBTITLE", out, status ); 	} else {-		output_titlecore( fp, f, "T3", 1, "TITLE", "SUBTITLE" );+		append_titlecore( in, "T3", 1, "TITLE", "SUBTITLE", out, status ); 	} }  static void-output_pages( FILE *fp, fields *f )+append_pages( fields *in, fields *out, int *status ) {-	char *sn = fields_findv( f, LEVEL_ANY, FIELDS_CHRP, "PAGESTART" );-	char *en = fields_findv( f, LEVEL_ANY, FIELDS_CHRP, "PAGEEND" );-	char *ar;+	char *sn, *en, *ar;+	int fstatus; +	sn = fields_findv( in, LEVEL_ANY, FIELDS_CHRP, "PAGES:START" );+	en = fields_findv( in, LEVEL_ANY, FIELDS_CHRP, "PAGES:STOP" );+ 	if ( sn || en ) {-		if ( sn ) fprintf( fp, "SP  - %s\n", sn );-		if ( en ) fprintf( fp, "EP  - %s\n", en );+		if ( sn ) {+			fstatus = fields_add( out, "SP", sn, LEVEL_MAIN );+			if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+		}+		if ( en ) {+			fstatus = fields_add( out, "EP", en, LEVEL_MAIN );+			if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+		} 	} else {-		ar = fields_findv( f, LEVEL_ANY, FIELDS_CHRP, "ARTICLENUMBER" );-		if ( ar ) fprintf( fp, "SP  - %s\n", ar );+		ar = fields_findv( in, LEVEL_ANY, FIELDS_CHRP, "ARTICLENUMBER" );+		if ( ar ) {+			fstatus = fields_add( out, "SP", ar, LEVEL_MAIN );+			if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+		} 	} }  static void-output_keywords( FILE *fp, fields *f )+append_keywords( fields *in, fields *out, int *status ) {+	vplist_index i;+	int fstatus; 	vplist vpl;-	int i;+ 	vplist_init( &vpl );-	fields_findv_each( f, LEVEL_ANY, FIELDS_CHRP, &vpl, "KEYWORD" );-	for ( i=0; i<vpl.n; ++i )-		fprintf( fp, "KW  - %s\n", ( char * ) vplist_get( &vpl, i ) );+	fields_findv_each( in, LEVEL_ANY, FIELDS_CHRP, &vpl, "KEYWORD" );+	for ( i=0; i<vpl.n; ++i ) {+		fstatus = fields_add( out, "KW", ( char * ) vplist_get( &vpl, i ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	} 	vplist_free( &vpl ); }  static void-output_pmid( FILE *fp, fields *f )+append_urls( fields *in, fields *out, int *status ) {-	newstr s;-	int i;-	newstr_init( &s );-	for ( i=0; i<fields_num( f ); ++i ) {-		if ( !fields_match_tag( f, i, "PMID" ) ) continue;-		pmid_to_url( f, i, "URL", &s );-		if ( s.len )-			fprintf( fp, "UR  - %s\n", s.data );+	int lstatus;+	slist types;++	lstatus = slist_init_valuesc( &types, "URL", "DOI", "PMID", "PMC", "ARXIV", "JSTOR", "MRNUMBER", NULL );+	if ( lstatus!=SLIST_OK ) {+		*status = BIBL_ERR_MEMERR;+		return; 	}-	newstr_free( &s );++	*status = urls_merge_and_add( in, LEVEL_ANY, out, "UR", LEVEL_MAIN, &types );++	slist_free( &types );+ }  static void-output_arxiv( FILE *fp, fields *f )+append_thesishint( int type, fields *out, int *status ) {-	newstr s;-	int i;-	newstr_init( &s );-	for ( i=0; i<fields_num( f ); ++i ) {-		if ( !fields_match_tag( f, i, "ARXIV" ) ) continue;-		arxiv_to_url( f, i, "URL", &s );-		if ( s.len )-			fprintf( fp, "UR  - %s\n", s.data );+	int fstatus;++	if ( type==TYPE_MASTERSTHESIS ) {+		fstatus = fields_add( out, "U1", "Masters thesis", LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR; 	}-	newstr_free( &s );-} -static void-output_jstor( FILE *fp, fields *f )-{-	newstr s;-	int i;-	newstr_init( &s );-	for ( i=0; i<fields_num( f ); ++i ) {-		if ( !fields_match_tag( f, i, "JSTOR" ) ) continue;-		jstor_to_url( f, i, "URL", &s );-		if ( s.len )-			fprintf( fp, "UR  - %s\n", s.data );+	else if ( type==TYPE_PHDTHESIS ) {+		fstatus = fields_add( out, "U1", "Ph.D. thesis", LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR; 	}-	newstr_free( &s );-} -static void-output_thesishint( FILE *fp, int type )-{-	if ( type==TYPE_MASTERSTHESIS )-		fprintf( fp, "%s  - %s\n", "U1", "Masters thesis" );-	else if ( type==TYPE_PHDTHESIS )-		fprintf( fp, "%s  - %s\n", "U1", "Ph.D. thesis" );-	else if ( type==TYPE_DIPLOMATHESIS )-		fprintf( fp, "%s  - %s\n", "U1", "Diploma thesis" );-	else if ( type==TYPE_DOCTORALTHESIS )-		fprintf( fp, "%s  - %s\n", "U1", "Doctoral thesis" );-	else if ( type==TYPE_HABILITATIONTHESIS )-		fprintf( fp, "%s  - %s\n", "U1", "Habilitation thesis" );+	else if ( type==TYPE_DIPLOMATHESIS ) {+		fstatus = fields_add( out, "U1", "Diploma thesis", LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	}++	else if ( type==TYPE_DOCTORALTHESIS ) {+		fstatus = fields_add( out, "U1", "Doctoral thesis", LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	}++	else if ( type==TYPE_HABILITATIONTHESIS ) {+		fstatus = fields_add( out, "U1", "Habilitation thesis", LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	} }  static int is_uri_scheme( char *p ) {-	char *scheme[] = { "http:", "file:", "ftp:", "git:", "gopher:" };+	char *scheme[] = { "http:", "https:", "file:", "ftp:", "git:", "gopher:" }; 	int i, len, nschemes = sizeof( scheme ) / sizeof( scheme[0] ); 	for ( i=0; i<nschemes; ++i ) { 		len = strlen( scheme[i] );@@ -541,120 +561,164 @@   static void-output_file( FILE *fp, fields *f, char *tag, char *ristag, int level )+append_file( fields *in, char *tag, char *ristag, int level, fields *out, int *status ) {+	vplist_index i;+	str filename;+	int fstatus; 	vplist a; 	char *fl;-	int i;++	str_init( &filename ); 	vplist_init( &a );-	fields_findv_each( f, level, FIELDS_CHRP, &a, tag );+	fields_findv_each( in, level, FIELDS_CHRP, &a, tag ); 	for ( i=0; i<a.n; ++i ) {-		fprintf( fp, "%s  - ", ristag ); 		fl = ( char * ) vplist_get( &a, i );-		if ( !is_uri_scheme( fl ) )-			fprintf( fp, "file:" );-		fprintf( fp, "%s\n", fl );+		str_empty( &filename );+		if ( !is_uri_scheme( fl ) ) str_strcatc( &filename, "file:" );+		str_strcatc( &filename, fl );+		if ( str_memerr( &filename ) ) { *status = BIBL_ERR_MEMERR; goto out; }+		fstatus = fields_add( out, ristag, str_cstr( &filename ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) { *status = BIBL_ERR_MEMERR; goto out; } 	}+out: 	vplist_free( &a );+	str_free( &filename ); }  static void-output_easy( FILE *fp, fields *f, char *tag, char *ristag, int level )+append_easy( fields *in, char *tag, char *ristag, int level, fields *out, int *status ) {-	char *value = fields_findv( f, level, FIELDS_CHRP, tag );-	if ( value ) fprintf( fp, "%s  - %s\n", ristag, value );+	char *value;+	int fstatus;++	value = fields_findv( in, level, FIELDS_CHRP, tag );+	if ( value ) {+		fstatus = fields_add( out, ristag, value, LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	} }  static void-output_easyall( FILE *fp, fields *f, char *tag, char *ristag, int level )+append_easyall( fields *in, char *tag, char *ristag, int level, fields *out, int *status ) {+	vplist_index i;+	int fstatus; 	vplist a;-	int i;+ 	vplist_init( &a );-	fields_findv_each( f, level, FIELDS_CHRP, &a, tag );-	for ( i=0; i<a.n; ++i )-		fprintf( fp, "%s  - %s\n", ristag, (char *) vplist_get( &a, i ) );+	fields_findv_each( in, level, FIELDS_CHRP, &a, tag );+	for ( i=0; i<a.n; ++i ) {+		fstatus = fields_add( out, ristag, (char *) vplist_get( &a, i ), LEVEL_MAIN );+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;+	} 	vplist_free( &a ); }  static void-output_allpeople( FILE *fp, fields *f, int type )+append_allpeople( fields *in, int type, fields *out, int *status ) {-	output_people(  fp, f, "AUTHOR",      "AU", LEVEL_MAIN   );-	output_easyall( fp, f, "AUTHOR:CORP", "AU", LEVEL_MAIN   );-	output_easyall( fp, f, "AUTHOR:ASIS", "AU", LEVEL_MAIN   );-	output_people(  fp, f, "AUTHOR",      "A2", LEVEL_HOST   );-	output_easyall( fp, f, "AUTHOR:CORP", "A2", LEVEL_HOST   );-	output_easyall( fp, f, "AUTHOR:ASIS", "A2", LEVEL_HOST   );-	output_people(  fp, f, "AUTHOR",      "A3", LEVEL_SERIES );-	output_easyall( fp, f, "AUTHOR:CORP", "A3", LEVEL_SERIES );-	output_easyall( fp, f, "AUTHOR:ASIS", "A3", LEVEL_SERIES );-	output_people(  fp, f, "EDITOR",      "ED", LEVEL_MAIN   );-	output_easyall( fp, f, "EDITOR:CORP", "ED", LEVEL_MAIN   );-	output_easyall( fp, f, "EDITOR:ASIS", "ED", LEVEL_MAIN   );-	if ( type_is_element( type ) ) {-		output_people(  fp, f, "EDITOR",      "ED", LEVEL_HOST   );-		output_easyall( fp, f, "EDITOR:CORP", "ED", LEVEL_HOST   );-		output_easyall( fp, f, "EDITOR:ASIS", "ED", LEVEL_HOST   );+	append_people ( in, "AUTHOR",      "AU", LEVEL_MAIN,   out, status );+	append_easyall( in, "AUTHOR:CORP", "AU", LEVEL_MAIN,   out, status );+	append_easyall( in, "AUTHOR:ASIS", "AU", LEVEL_MAIN,   out, status );+	append_people ( in, "AUTHOR",      "A2", LEVEL_HOST,   out, status );+	append_easyall( in, "AUTHOR:CORP", "A2", LEVEL_HOST,   out, status );+	append_easyall( in, "AUTHOR:ASIS", "A2", LEVEL_HOST,   out, status );+	append_people ( in, "AUTHOR",      "A3", LEVEL_SERIES, out, status );+	append_easyall( in, "AUTHOR:CORP", "A3", LEVEL_SERIES, out, status );+	append_easyall( in, "AUTHOR:ASIS", "A3", LEVEL_SERIES, out, status );+	append_people ( in, "EDITOR",      "ED", LEVEL_MAIN,   out, status );+	append_easyall( in, "EDITOR:CORP", "ED", LEVEL_MAIN,   out, status );+	append_easyall( in, "EDITOR:ASIS", "ED", LEVEL_MAIN,   out, status );+	if ( type_is_element[ type ] ) {+		append_people ( in, "EDITOR",      "ED", LEVEL_HOST, out, status );+		append_easyall( in, "EDITOR:CORP", "ED", LEVEL_HOST, out, status );+		append_easyall( in, "EDITOR:ASIS", "ED", LEVEL_HOST, out, status ); 	} else {-		output_people(  fp, f, "EDITOR",      "A3", LEVEL_HOST   );-		output_easyall( fp, f, "EDITOR:CORP", "A3", LEVEL_HOST   );-		output_easyall( fp, f, "EDITOR:ASIS", "A3", LEVEL_HOST   );+		append_people ( in, "EDITOR",      "A3", LEVEL_HOST, out, status );+		append_easyall( in, "EDITOR:CORP", "A3", LEVEL_HOST, out, status );+		append_easyall( in, "EDITOR:ASIS", "A3", LEVEL_HOST, out, status ); 	}-	output_people(  fp, f, "EDITOR",      "A3", LEVEL_SERIES );-	output_easyall( fp, f, "EDITOR:CORP", "A3", LEVEL_SERIES );-	output_easyall( fp, f, "EDITOR:ASIS", "A3", LEVEL_SERIES );+	append_people ( in, "EDITOR",      "A3", LEVEL_SERIES, out, status );+	append_easyall( in, "EDITOR:CORP", "A3", LEVEL_SERIES, out, status );+	append_easyall( in, "EDITOR:ASIS", "A3", LEVEL_SERIES, out, status ); } -void-risout_write( fields *f, FILE *fp, param *p, unsigned long refnum )+static void+output( FILE *fp, fields *out ) {-	int type;-	type = get_type( f, p );-	output_type( fp, type, p );--	output_allpeople( fp, f, type );--	output_date( fp, f );+	char *tag, *value;+	int i; -	output_alltitles( fp, f, type );+	for ( i=0; i<out->n; ++i ) {+		tag   = fields_tag( out, i, FIELDS_CHRP );+		value = fields_value( out, i, FIELDS_CHRP );+		fprintf( fp, "%s  - %s\n", tag, value );+	} -	output_pages( fp, f );-	output_easy( fp, f, "VOLUME",             "VL", LEVEL_ANY );-	output_easy( fp, f, "ISSUE",              "IS", LEVEL_ANY );-	output_easy( fp, f, "NUMBER",             "IS", LEVEL_ANY );-	output_easy( fp, f, "EDITION",            "ET", LEVEL_ANY );-	output_easy( fp, f, "NUMVOLUMES",         "NV", LEVEL_ANY );-	output_easy( fp, f, "AUTHORADDRESS",      "AD", LEVEL_ANY );-	output_easy( fp, f, "PUBLISHER",          "PB", LEVEL_ANY );-	output_easy( fp, f, "DEGREEGRANTOR",      "PB", LEVEL_ANY );-	output_easy( fp, f, "DEGREEGRANTOR:ASIS", "PB", LEVEL_ANY );-	output_easy( fp, f, "DEGREEGRANTOR:CORP", "PB", LEVEL_ANY );-	output_easy( fp, f, "ADDRESS",            "CY", LEVEL_ANY );-	output_keywords( fp, f );-	output_easy( fp, f, "ABSTRACT",           "AB", LEVEL_ANY );-	output_easy( fp, f, "CALLNUMBER",         "CN", LEVEL_ANY );-	output_easy( fp, f, "ISSN",               "SN", LEVEL_ANY );-	output_easy( fp, f, "ISBN",               "SN", LEVEL_ANY );-	output_easyall( fp, f, "URL",             "UR", LEVEL_ANY );-	output_easyall( fp, f, "DOI",             "DO", LEVEL_ANY );-	output_file(    fp, f, "FILEATTACH",      "L1", LEVEL_ANY );-	output_file(    fp, f, "FIGATTACH",       "L4", LEVEL_ANY );-	output_easy( fp, f, "CAPTION",            "CA", LEVEL_ANY );-	output_pmid( fp, f );-	output_arxiv( fp, f );-	output_jstor( fp, f );-	output_easy( fp, f, "LANGUAGE",           "LA", LEVEL_ANY );-	output_easy( fp, f, "NOTES",              "N1", LEVEL_ANY );-	output_easy( fp, f, "REFNUM",             "ID", LEVEL_ANY );-	output_thesishint( fp, type ); 	fprintf( fp, "ER  - \n" ); 	fflush( fp ); } -void+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 ); }-
− bibutils/risout.h
@@ -1,22 +0,0 @@-/*- * risout.h- *- * Copyright (c) Chris Putnam 2005-2013- *- * Source code released under the GPL version 2- *- */-#ifndef RISOUT_H-#define RISOUT_H--#include <stdio.h>-#include "bibutils.h"--extern void risout_write( fields *info, FILE *fp, param *p,-		unsigned long refnum );-extern void risout_writeheader( FILE *outptr, param *p );--extern void risout_initparams( param *p, const char *progname );---#endif
bibutils/ristypes.c view
@@ -1,7 +1,7 @@ /*  * ristypes.c  *- * Copyright (c) Chris Putnam 2003-2013+ * Copyright (c) Chris Putnam 2003-2017  *  * Source code released under the GPL version 2  *@@ -34,13 +34,13 @@ 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */ 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Name of Database */ 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */ 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */ 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */ 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */ 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */ 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */@@ -62,13 +62,13 @@ 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */ 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */ 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */ 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Resarch Notes -> Notes */+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Resarch Notes -> Notes */ 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */ 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */ 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */ 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */ 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */ 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */@@ -80,11 +80,11 @@ 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */ 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */ 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated? */-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated? */+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */ };  static lookups article[] = {@@ -108,13 +108,13 @@ 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */ 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */ 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */ 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */ 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */ 	{ "ED", "EDITOR",       PERSON,  LEVEL_HOST },   /* Deprecated? */-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */ 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */ 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */@@ -136,13 +136,13 @@ 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */ 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */ 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_HOST },   /* Publisher */-	{ "PY", "PARTYEAR",     DATE,    LEVEL_MAIN },   /* Year */+	{ "PY", "PARTDATE:YEAR",DATE,    LEVEL_MAIN },   /* Year */ 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */ 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */ 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */ 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_HOST },   /* ISBN/ISSN */-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */ 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */ 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */ 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */@@ -154,12 +154,12 @@ 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */ 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */ 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */-	{ "Y1", "PARTYEAR",     DATE,    LEVEL_MAIN },   /* Deprecated */-	{ "Y2", "PARTMONTH",    SIMPLE,  LEVEL_MAIN },   /* Access Date */-	{ "  ", "INTERNAL_TYPE|ARTICLE",           ALWAYS, LEVEL_MAIN },+	{ "Y1", "PARTDATE:YEAR",DATE,    LEVEL_MAIN },   /* Deprecated */+	{ "Y2", "PARTDATE:MONTH",SIMPLE, LEVEL_MAIN },   /* Access Date */+	{ "  ", "INTERNAL_TYPE|ARTICLE",  ALWAYS, LEVEL_MAIN }, 	{ "  ", "ISSUANCE|continuing",    ALWAYS, LEVEL_HOST }, 	{ "  ", "RESOURCE|text",          ALWAYS, LEVEL_MAIN }, 	{ "  ", "GENRE|journal article",  ALWAYS, LEVEL_MAIN },@@ -189,13 +189,13 @@ 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */ 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */ 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */ 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */ 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */ 	{ "ED", "EDITOR",       PERSON,  LEVEL_HOST },   /* Deprecated? */-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */ 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */ 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */@@ -217,13 +217,13 @@ 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */ 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */ 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_HOST },   /* Publisher */-	{ "PY", "PARTYEAR",     DATE,    LEVEL_MAIN },   /* Year */+	{ "PY", "PARTDATE:YEAR",DATE,    LEVEL_MAIN },   /* Year */ 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */ 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */ 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */ 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_HOST },   /* ISBN/ISSN */-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */ 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */ 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */ 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */@@ -235,11 +235,11 @@ 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */ 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */ 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */-	{ "Y1", "PARTYEAR",     DATE,    LEVEL_MAIN },   /* Deprecated */-	{ "Y2", "PARTMONTH",    SIMPLE,  LEVEL_MAIN },   /* Access Date */+	{ "Y1", "PARTDATE:YEAR",DATE,    LEVEL_MAIN },   /* Deprecated */+	{ "Y2", "PARTDATE:MONTH",SIMPLE, LEVEL_MAIN },   /* Access Date */ 	{ "  ", "ISSUANCE|continuing",    ALWAYS, LEVEL_HOST }, 	{ "  ", "RESOURCE|text",          ALWAYS, LEVEL_MAIN }, 	{ "  ", "GENRE|periodical",       ALWAYS, LEVEL_HOST },@@ -267,13 +267,13 @@ 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */ 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */ 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */ 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */ 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */ 	{ "ED", "EDITOR",       PERSON,  LEVEL_HOST },   /* Deprecated? */-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */ 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */ 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */@@ -295,13 +295,13 @@ 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */ 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */ 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_HOST },   /* Publisher */-	{ "PY", "PARTYEAR",     DATE,    LEVEL_MAIN },   /* Year */+	{ "PY", "PARTDATE:YEAR",DATE,    LEVEL_MAIN },   /* Year */ 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */ 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */ 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */ 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_HOST },   /* ISBN/ISSN */-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */ 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */ 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */ 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */@@ -313,15 +313,15 @@ 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */ 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */ 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */-	{ "Y1", "PARTYEAR",     DATE,    LEVEL_MAIN },   /* Deprecated */-	{ "Y2", "PARTMONTH",    SIMPLE,  LEVEL_MAIN },   /* Access Date */-	{ "  ", "INTERNAL_TYPE|NEWSARTICLE",       ALWAYS, LEVEL_MAIN },-	{ "  ", "ISSUANCE|continuing",    ALWAYS, LEVEL_HOST },-	{ "  ", "RESOURCE|text",          ALWAYS, LEVEL_MAIN },-	{ "  ", "GENRE|newspaper",        ALWAYS, LEVEL_HOST }+	{ "Y1", "PARTDATE:YEAR",DATE,    LEVEL_MAIN },   /* Deprecated */+	{ "Y2", "PARTDATE:MONTH",SIMPLE, LEVEL_MAIN },   /* Access Date */+	{ "  ", "INTERNAL_TYPE|NEWSARTICLE", ALWAYS, LEVEL_MAIN },+	{ "  ", "ISSUANCE|continuing",       ALWAYS, LEVEL_HOST },+	{ "  ", "RESOURCE|text",             ALWAYS, LEVEL_MAIN },+	{ "  ", "GENRE|newspaper",           ALWAYS, LEVEL_HOST } };  static lookups book[] = {@@ -346,13 +346,13 @@ 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */ 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */ 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */ 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */ 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */ 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */ 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */ 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */@@ -374,13 +374,13 @@ 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */ 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */ 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */ 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */ 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */ 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */ 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */ 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */ 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */ 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title -- here abbreviated title for series*/@@ -392,14 +392,14 @@ 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */ 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */ 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */-	{ "  ", "ISSUANCE|monographic",  ALWAYS, LEVEL_MAIN },-	{ "  ", "GENRE|book",    ALWAYS, LEVEL_MAIN },-	{ "  ", "RESOURCE|text", ALWAYS, LEVEL_MAIN }+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */+	{ "  ", "ISSUANCE|monographic",   ALWAYS, LEVEL_MAIN },+	{ "  ", "GENRE|book",             ALWAYS, LEVEL_MAIN },+	{ "  ", "RESOURCE|text",          ALWAYS, LEVEL_MAIN } };  static lookups inbook[] = {@@ -424,13 +424,13 @@ 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */ 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_HOST },   /* Deprecated? */ 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_HOST },   /* Place Published */-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */ 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */ 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */ 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */ 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */ 	{ "ED", "EDITOR",       PERSON,  LEVEL_HOST },   /* Deprecated? */-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */ 	{ "ET", "EDITION",      SIMPLE,  LEVEL_HOST },   /* Edition */ 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_HOST },   /* Number */@@ -452,13 +452,13 @@ 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */ 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */ 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_HOST },   /* Publisher */-	{ "PY", "YEAR",         DATE,    LEVEL_HOST },   /* Year */+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_HOST },   /* Year */ 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */ 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */ 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */ 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_HOST },   /* ISBN/ISSN */-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */ 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */ 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */ 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_SERIES }, /* 'Secondary' Title -- here abbreviated title for series*/@@ -470,11 +470,11 @@ 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */ 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_HOST },   /* Volume */ 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_HOST },   /* Deprecated? */-	{ "Y1", "YEAR",         DATE,    LEVEL_HOST },   /* Deprecated */-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_HOST },   /* Access Date */+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_HOST },   /* Deprecated */+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_HOST },   /* Access Date */ 	{ "  ", "GENRE|book chapter",   ALWAYS, LEVEL_MAIN }, 	{ "  ", "GENRE|book",           ALWAYS, LEVEL_HOST }, 	{ "  ", "ISSUANCE|monographic", ALWAYS, LEVEL_HOST },@@ -502,13 +502,13 @@ 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */ 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */ 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */ 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */ 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */ 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */ 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */ 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */@@ -530,13 +530,13 @@ 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */ 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */ 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_HOST },   /* Publisher */-	{ "PY", "YEAR",         DATE,    LEVEL_HOST },   /* Year */+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_HOST },   /* Year */ 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */ 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */ 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */ 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */ 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */ 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */ 	{ "BT", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Book Title */@@ -549,12 +549,12 @@ 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */ 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */ 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */-	{ "Y1", "YEAR",         DATE,    LEVEL_HOST },   /* Deprecated */-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_HOST },   /* Access Date */-	{ "  ", "INTERNAL_TYPE|CONFERENCE",       ALWAYS, LEVEL_MAIN },+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_HOST },   /* Deprecated */+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_HOST },   /* Access Date */+	{ "  ", "INTERNAL_TYPE|CONFERENCE",     ALWAYS, LEVEL_MAIN }, 	{ "  ", "RESOURCE|text",                ALWAYS, LEVEL_MAIN }, 	{ "  ", "GENRE|conference publication", ALWAYS, LEVEL_HOST } };@@ -581,13 +581,13 @@ 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */ 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */ 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */ 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */ 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */ 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */ 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */ 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */@@ -609,13 +609,13 @@ 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */ 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */ 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */ 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */ 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */ 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */ 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */ 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */ 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */ 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */@@ -627,12 +627,12 @@ 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */ 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */ 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */-	{ "  ", "INTERNAL_TYPE|STATUTE",          ALWAYS, LEVEL_MAIN },+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */+	{ "  ", "INTERNAL_TYPE|STATUTE", ALWAYS, LEVEL_MAIN }, 	{ "  ", "RESOURCE|text",         ALWAYS, LEVEL_MAIN }, 	{ "  ", "GENRE|legislation",     ALWAYS, LEVEL_MAIN } };@@ -659,13 +659,13 @@ 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */ 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */ 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */ 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */ 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */ 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */ 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */ 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */@@ -687,13 +687,13 @@ 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */ 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */ 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */ 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */ 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */ 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */ 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */ 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */ 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */ 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */@@ -705,11 +705,11 @@ 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */ 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */ 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */ 	{ "  ", "INTERNAL_TYPE|HEARING", ALWAYS, LEVEL_MAIN }, 	{ "  ", "GENRE|hearing",         ALWAYS, LEVEL_MAIN } };@@ -736,13 +736,13 @@ 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */ 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */ 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */ 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */ 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */ 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */ 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */ 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */@@ -764,13 +764,13 @@ 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */ 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */ 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */ 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */ 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */ 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */ 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */ 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */ 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */ 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */@@ -782,11 +782,11 @@ 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */ 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */ 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */ 	{ "  ", "INTERNAL_TYPE|CASE",              ALWAYS, LEVEL_MAIN }, 	{ "  ", "GENRE|legal case and case notes", ALWAYS, LEVEL_MAIN } };@@ -813,13 +813,13 @@ 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */ 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */ 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */ 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */ 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */ 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */ 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */ 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */@@ -841,13 +841,13 @@ 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */ 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */ 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */ 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */ 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */ 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */ 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */ 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */ 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */ 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */@@ -859,11 +859,11 @@ 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */ 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */ 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */ 	{ "  ", "INTERNAL_TYPE|ARTICLE", ALWAYS, LEVEL_MAIN }, 	{ "  ", "GENRE|communication",   ALWAYS, LEVEL_MAIN } };@@ -890,13 +890,13 @@ 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */ 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */ 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */ 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */ 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */ 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */ 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */ 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */@@ -918,13 +918,13 @@ 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */ 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */ 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */ 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */ 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */ 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */ 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */ 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */ 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */ 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */@@ -936,11 +936,11 @@ 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */ 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */ 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */ 	{ "  ", "INTERNAL_TYPE|THESIS",  ALWAYS,  LEVEL_MAIN }, 	{ "  ", "RESOURCE|text",         ALWAYS,  LEVEL_MAIN }, 	{ "  ", "GENRE|thesis",          ALWAYS,  LEVEL_MAIN },@@ -968,13 +968,13 @@ 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */ 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */ 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */ 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */ 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */ 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */ 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */ 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */@@ -996,13 +996,13 @@ 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */ 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */ 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */ 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */ 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */ 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */ 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */ 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */ 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */ 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */@@ -1014,11 +1014,11 @@ 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */ 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */ 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */ 	{ "  ", "INTERNAL_TYPE|REPORT",  ALWAYS,  LEVEL_MAIN }, 	{ "  ", "RESOURCE|text",         ALWAYS,  LEVEL_MAIN }, 	{ "  ", "GENRE|report",          ALWAYS,  LEVEL_MAIN }@@ -1046,13 +1046,13 @@ 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */ 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */ 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */ 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */ 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */ 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */ 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */ 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */@@ -1074,13 +1074,13 @@ 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */ 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */ 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */ 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */ 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */ 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */ 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */ 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */ 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */ 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */@@ -1092,11 +1092,11 @@ 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */ 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */ 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */ 	{ "  ", "GENRE|abstract or summary", ALWAYS,  LEVEL_MAIN } }; @@ -1122,13 +1122,13 @@ 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */ 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */ 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */ 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */ 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */ 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */ 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */ 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */@@ -1150,13 +1150,13 @@ 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */ 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */ 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */ 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */ 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */ 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */ 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */ 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */ 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */ 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */@@ -1168,11 +1168,11 @@ 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */ 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */ 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */ 	{ "  ", "RESOURCE|software, multimedia", ALWAYS, LEVEL_MAIN } }; @@ -1198,13 +1198,13 @@ 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */ 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */ 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */ 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */ 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */ 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */ 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */ 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */@@ -1226,13 +1226,13 @@ 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */ 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */ 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */ 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */ 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */ 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */ 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */ 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */ 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */ 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */@@ -1244,11 +1244,11 @@ 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */ 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */ 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */ 	{ "  ", "RESOURCE|text", ALWAYS, LEVEL_MAIN }, 	{ "  ", "GENRE|patent",  ALWAYS, LEVEL_MAIN } };@@ -1275,13 +1275,13 @@ 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */ 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */ 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */ 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */ 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */ 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */ 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */ 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */@@ -1303,13 +1303,13 @@ 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */ 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */ 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */ 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */ 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */ 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */ 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */ 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */ 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */ 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */@@ -1321,11 +1321,11 @@ 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */ 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */ 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */ 	{ " ",  "RESOURCE|software, multimedia", ALWAYS, LEVEL_MAIN }, 	{ " ",  "GENRE|electronic",              ALWAYS, LEVEL_MAIN }, };@@ -1352,13 +1352,13 @@ 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */ 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */ 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */ 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */ 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */ 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */ 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */ 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */@@ -1380,13 +1380,13 @@ 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */ 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */ 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */ 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */ 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */ 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */ 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */ 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */ 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */ 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */@@ -1398,11 +1398,11 @@ 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */ 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */ 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */ 	{ " ",  "RESOURCE|text",  ALWAYS, LEVEL_MAIN }, 	{ " ",  "GENRE|pamphlet", ALWAYS, LEVEL_MAIN }, };@@ -1429,13 +1429,13 @@ 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */ 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Name of Database */ 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */ 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */ 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */ 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */ 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */ 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */@@ -1457,13 +1457,13 @@ 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */ 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */ 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */ 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Resarch Notes -> Notes */+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Resarch Notes -> Notes */ 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */ 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */ 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */ 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */ 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */ 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */@@ -1475,11 +1475,11 @@ 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */ 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */ 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated? */-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated? */+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */ 	{ " ",  "RESOURCE|cartographic",   ALWAYS, LEVEL_MAIN }, 	{ " ",  "GENRE|map",               ALWAYS, LEVEL_MAIN } };@@ -1506,13 +1506,13 @@ 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */ 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */ 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */ 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */ 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */ 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */ 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */ 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */ 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */@@ -1534,13 +1534,13 @@ 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */ 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */ 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */ 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */ 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */ 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */ 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */ 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */ 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */ 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */@@ -1552,13 +1552,13 @@ 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */ 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */ 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */ 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */-	{ " ",         "RESOURCE|text",   ALWAYS, LEVEL_MAIN },-	{ " ",         "GENRE|unpublished",      ALWAYS, LEVEL_MAIN }+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */+	{ " ",  "RESOURCE|text",     ALWAYS, LEVEL_MAIN },+	{ " ",  "GENRE|unpublished", ALWAYS, LEVEL_MAIN } };  #define ORIG(a) ( &(a[0]) )
bibutils/serialno.c view
@@ -1,7 +1,7 @@ /*  * serialno.c  *- * Copyright (c) Chris Putnam 2005-2014+ * Copyright (c) Chris Putnam 2005-2017  *  * Source code released under the GPL version 2  *
bibutils/serialno.h view
@@ -1,7 +1,7 @@ /*  * serialno.h  *- * Copyright (c) Chris Putnam 2005-2014+ * Copyright (c) Chris Putnam 2005-2017  *  * Source code released under the GPL version 2  *
+ bibutils/slist.c view
@@ -0,0 +1,865 @@+/*+ * slist.c+ *+ * version: 2017-07-04+ *+ * Copyright (c) Chris Putnam 2004-2017+ *+ * Source code released under the GPL version 2+ *+ * Implements a simple managed array of strs.+ *+ */+#include "slist.h"++/* Do not use asserts in VPLIST_NOASSERT defined */+#ifdef VPLIST_NOASSERT+#define NDEBUG+#endif+#include <assert.h>++#define SLIST_MINALLOC (20)++#define SLIST_EXACT_SIZE  (0)+#define SLIST_DOUBLE_SIZE (1)++/*+ * returns 1 if n is valid string in slist+ */+static inline int+slist_valid_num( slist *a, slist_index n )+{+	if ( n < 0 || n >= a->n ) return 0;+	return 1;+}++void+slist_init( slist *a  )+{+	assert( a );++	a->strs = NULL;+	a->max = 0;+	a->n = 0;+	a->sorted = 1;+}++int+slist_init_values( slist *a, ... )+{+	int status = SLIST_OK;+	va_list ap;+	str *s, *t;++	slist_init( a );++	va_start( ap, a );+	do {+		s = va_arg( ap, str * );+		if ( s ) {+			t = slist_add( a, s );+			if ( !t ) {+				status = SLIST_ERR_MEMERR;+				goto out;+			}+		}+	} while ( s );+out:+	va_end( ap );++	return status;+}++int+slist_init_valuesc( slist *a, ... )+{+	int status = SLIST_OK;+	va_list ap;+	char *s;+	str *t;++	slist_init( a );++	va_start( ap, a );+	do {+		s = va_arg( ap, char * );+		if ( s ) {+			t = slist_addc( a, s );+			if ( !t ) {+				status = SLIST_ERR_MEMERR;+				goto out;+			}+		}+	} while ( s );+out:+	va_end( ap );++	return status;+}++void+slist_empty( slist *a )+{+	slist_index i;++	assert( a );++	for ( i=0; i<a->max; ++i )+		str_empty( &(a->strs[i]) );++	a->n = 0;+	a->sorted = 1;+}++void+slist_free( slist *a )+{+	slist_index i;++	assert( a );++	for ( i=0; i<a->max; ++i )+		str_free( &(a->strs[i]) );++	free( a->strs );+	slist_init( a );+}++slist *+slist_new( void )+{+	slist *a;++	a = ( slist * ) malloc( sizeof ( slist ) );+	if ( a ) slist_init( a );++	return a;+}++void+slist_delete( slist *a )+{+	assert( a );++	slist_free( a );+	free( a );+}++void+slist_deletev( void *v )+{+	slist_delete( (slist*) v );+}++void+slist_swap( slist *a, slist_index n1, slist_index n2 )+{+	assert( a );++	if ( slist_valid_num( a, n1 ) && slist_valid_num( a, n2 ) )+		str_swapstrings( &(a->strs[n1]), &(a->strs[n2]) );+}++static int+slist_comp( const void *v1, const void *v2 )+{+	str *s1 = ( str *) v1;+	str *s2 = ( str *) v2;+	if ( !s1->len && !s2->len ) return 0;+	else if ( !s1->len ) return -1;+	else if ( !s2->len ) return 1;+	else return str_strcmp( s1, s2 );+}++static int+slist_comp_step( slist *a, slist_index n1, slist_index n2 )+{+	return slist_comp( (const void*) &(a->strs[n1]), (const void*) &(a->strs[n2]) );+}++static str *+slist_set_cleanup( slist *a, slist_index n )+{+	if ( str_memerr( &(a->strs[n]) ) ) return NULL;+	if ( a->sorted ) {+		if ( n>0 && slist_comp_step( a, n-1, n )>0 )+			a->sorted = 0;+	}+	if ( a->sorted ) {+		if ( n<a->n-1 && slist_comp_step( a, n, n+1 )>0 )+			a->sorted = 0;+	}+	return &(a->strs[n]);+}++str *+slist_setc( slist *a, slist_index n, const char *s )+{+	assert( a );+	assert( s );++	if ( !slist_valid_num( a, n ) ) return NULL;+	str_strcpyc( &(a->strs[n]), s );+	return slist_set_cleanup( a, n );+}++str *+slist_set( slist *a, slist_index n, str *s )+{+	assert( s );++	return slist_setc( a, n, str_cstr( s ) );+}++/*+ * return pointer to str 'n'+ */+str *+slist_str( slist *a, slist_index n )+{+	assert( a );++	if ( !slist_valid_num( a, n ) ) return NULL;+	else return &(a->strs[n]);+}++/*+ * return pointer to C string 'n'+ *+ * So long as the index is a valid number ensure+ * that a pointer is returned even if the newstr isn't+ * allocated. Only return NULL if the index+ * is invalid. Thus we can convert loops like:+ *+ * for ( i=0; i<a->n; ++i ) {+ *      p = slist_cstr( a, i );+ *      if ( p==NULL ) continue; // empty string+ *      ...+ * }+ *+ * to+ *+ * i = 0;+ * while ( ( p = slist_cstr( a, i ) ) ) {+ *      ...+ *      i++;+ * }+ *+ */+char *+slist_cstr( slist *a, slist_index n )+{+	static char empty[] = "";+	char *p;++	assert( a );++	if ( !slist_valid_num( a, n ) ) return NULL;+	p = str_cstr( &(a->strs[n]) );+	if ( p ) return p;+	else return empty;+}++static inline int+slist_alloc( slist *a, slist_index alloc )+{+	slist_index i;++	a->strs = ( str* ) malloc( sizeof( str ) * alloc );+	if ( !(a->strs) ) return SLIST_ERR_MEMERR;++	a->max = alloc;+	a->n   = 0;++	for ( i=0; i<alloc; ++i )+		str_init( &(a->strs[i]) );++	return SLIST_OK;+}++static inline int+slist_realloc( slist *a, slist_index alloc )+{+	slist_index i;+	str *more;++	more = ( str* ) realloc( a->strs, sizeof( str ) * alloc );+	if ( !more ) return SLIST_ERR_MEMERR;++	a->strs = more;++	for ( i=a->max; i<alloc; ++i )+		str_init( &(a->strs[i]) );++	a->max = alloc;++	return SLIST_OK;+}++#define SLIST_EXACT_SIZE  (0)+#define SLIST_DOUBLE_SIZE (1)++static int+slist_ensure_space( slist *a, slist_index n, int mode )+{+	int status = SLIST_OK;+	int alloc = n;++	if ( a->max==0 ) {+		if ( mode == SLIST_DOUBLE_SIZE && alloc < SLIST_MINALLOC ) alloc = SLIST_MINALLOC;+		status = slist_alloc( a, alloc );+	}++	else if ( a->max < n ) {+		if ( mode == SLIST_DOUBLE_SIZE && alloc < a->max * 2 ) alloc = a->max * 2;+		status = slist_realloc( a, alloc );+	}++	return status;+}++str *+slist_addvp( slist *a, unsigned char mode, void *vp )+{+	str *s = NULL;+	int status;++	status = slist_ensure_space( a, a->n+1, SLIST_DOUBLE_SIZE );++	if ( status==SLIST_OK ) {++		s = &( a->strs[a->n] );++		if ( mode==SLIST_CHR )+			str_strcpyc( s, (const char*) vp );+		else+			str_strcpy( s, (str*) vp );++		if ( str_memerr( s ) ) return NULL;+		a->n++;+		if ( a->sorted && a->n > 1 ) {+			if ( slist_comp_step( a, a->n-2, a->n-1 ) > 0 )+				a->sorted = 0;+		}++	}++	return s;+}+str *+slist_addc( slist *a, const char *s )+{+	return slist_addvp( a, SLIST_CHR, (void*)s );+}+str *+slist_add( slist *a, str *s )+{+	return slist_addvp( a, SLIST_STR, (void*)s );+}++str *+slist_addvp_unique( slist *a, unsigned char mode, void *vp )+{+	str *s;+	int n;++	if ( mode==SLIST_CHR )+		n = slist_findc( a, (const char*) vp );+	else+		n = slist_find( a, (str*) vp );++	if ( slist_wasfound( a, n ) )+		s = &( a->strs[n] );+	else+		s = slist_addvp( a, mode, vp );++	return s;+}+str *+slist_addc_unique( slist *a, const char *s )+{+	return slist_addvp_unique( a, SLIST_CHR, (void*)s );+}+str *+slist_add_unique( slist *a, str *s )+{+	return slist_addvp_unique( a, SLIST_STR, (void*)s );+}++int+slist_addvp_all( slist *a, unsigned char mode, ... )+{+	int ret = SLIST_OK;+	va_list ap;+	void *v;+	str *s;++	va_start( ap, mode );++	do {++		if ( mode==SLIST_CHR )+			v = va_arg( ap, char * );+		else+			v = va_arg( ap, str * );++		if ( v ) {+			s = slist_addvp( a, mode, v );+			if ( s==NULL ) {+				ret = SLIST_ERR_MEMERR;+				goto out;+			}+		}++	} while ( v );++out:+	va_end( ap );+	return ret;+}++int+slist_add_all( slist *a, ... )+{+	int ret = SLIST_OK;+	va_list ap;+	str *s, *v;++	va_start( ap, a );++	do {+		v = va_arg( ap, str * );++		if ( v ) {+			s = slist_addvp( a, SLIST_STR, (void*)v );+			if ( s==NULL ) {+				ret = SLIST_ERR_MEMERR;+				goto out;+			}+		}++	} while ( v );+out:+	va_end( ap );+	return ret;+}++int+slist_addc_all( slist *a, ... )+{+	int ret = SLIST_OK;+	const char *v;+	va_list ap;+	str *s;++	va_start( ap, a );++	do {++		v = va_arg( ap, const char * );++		if ( v ) {+			s = slist_addvp( a, SLIST_CHR, (void*)v );+			if ( s==NULL ) {+				ret = SLIST_ERR_MEMERR;+				goto out;+			}+		}++	} while ( v );+out:+	va_end( ap );+	return ret;+}++int+slist_append( slist *a, slist *toadd )+{+	int i, status;++	assert( a );+	assert( toadd );++	status = slist_ensure_space( a, a->n + toadd->n, SLIST_EXACT_SIZE );++	if ( status == SLIST_OK ) {++		for ( i=0; i<toadd->n; ++i ) {+			str_strcpy( &(a->strs[a->n+i]), &(toadd->strs[i]) );+			if ( str_memerr( &(a->strs[a->n+i]) ) ) return SLIST_ERR_MEMERR;+		}++		a->n += toadd->n;++	}++	return status;+}++int+slist_append_unique( slist *a, slist *toadd )+{+	str *s;+	int i;++	assert( a );+	assert( toadd );++	for ( i=0; i<toadd->n; ++i ) {+		s = slist_add_unique( a, &(toadd->strs[i]) );+		if ( !s ) return SLIST_ERR_MEMERR;+	}++	return SLIST_OK;+}++int+slist_remove( slist *a, slist_index n )+{+	int i;++	assert( a );++	if ( !slist_valid_num( a, n ) ) return SLIST_ERR_BADPARAM;++	for ( i=n+1; i<a->n; ++i ) {+		str_strcpy( &(a->strs[i-1]), &(a->strs[i]) );+		if ( str_memerr( &(a->strs[i-1]) ) ) return SLIST_ERR_MEMERR;+	}++	a->n--;++	return SLIST_OK;+}++void+slist_sort( slist *a )+{+	qsort( a->strs, a->n, sizeof( str ), slist_comp );+	a->sorted = 1;+}++static slist_index+slist_find_sorted( slist *a, const char *searchstr )+{+	slist_index min, max, mid;+	str s, *cs;+	int comp;++	assert( a );+	assert( searchstr );++	str_initstrc( &s, searchstr );+	min = 0;+	max = a->n - 1;+	while ( min <= max ) {+		mid = ( min + max ) / 2;+		cs = slist_str( a, mid );+		comp = slist_comp( (void*)cs, (void*) (&s) );+		if ( comp==0 ) {+			str_free( &s );+			return mid;+		}+		else if ( comp > 0 ) max = mid - 1;+		else if ( comp < 0 ) min = mid + 1;+	}+	str_free( &s );+	return -1;+}++static slist_index+slist_find_simple( slist *a, const char *searchstr, int nocase )+{+	slist_index i;++	assert( a );+	assert( searchstr );++	if ( nocase ) {+		for ( i=0; i<a->n; ++i )+			if ( !str_strcasecmpc( &(a->strs[i]), searchstr ) )+				return i;+	} else {+		for ( i=0; i<a->n; ++i )+			if ( !str_strcmpc( &(a->strs[i]), searchstr ) )+				return i;+	}+	return -1;+}++slist_index+slist_findc( slist *a, const char *searchstr )+{+	assert( a );++	if ( a->n==0 ) return -1;+	if ( a->sorted )+		return slist_find_sorted( a, searchstr );+	else+		return slist_find_simple( a, searchstr, 0 );+}++slist_index+slist_find( slist *a, str *searchstr )+{+	if ( searchstr->len==0 ) return -1;+	return slist_findc( a, str_cstr( searchstr ) );+}++slist_index+slist_findnocasec( slist *a, const char *searchstr )+{+	assert( a );++	return slist_find_simple( a, searchstr, 1 );+}++slist_index+slist_findnocase( slist *a, str *searchstr )+{+	if ( searchstr->len==0 ) return -1;+	return slist_findnocasec( a, str_cstr( searchstr ) );+}++int+slist_wasfound( slist *a, slist_index n )+{+	return ( n!=-1 );+}++int+slist_wasnotfound( slist *a, slist_index n )+{+	return ( n==-1 );+}++int+slist_fillfp( slist *a, FILE *fp, unsigned char skip_blank_lines )+{+	int ret = SLIST_OK;+	str line, *s;++	assert( a );+	assert( fp );++	slist_empty( a );+	str_init( &line );++	while ( str_fgetline( &line, fp ) ) {+		if ( skip_blank_lines && line.len==0 ) continue;+		s = slist_add( a, &line );+		if ( !s ) {+			ret = SLIST_ERR_MEMERR;+			goto out;+		}+	}++out:+	str_free( &line );+	return ret;+}++int+slist_fill( slist *a, const char *filename, unsigned char skip_blank_lines )+{+	FILE *fp;+	int ret;++	fp = fopen( filename, "r" );+	if ( !fp ) return SLIST_ERR_CANTOPEN;++	ret = slist_fillfp( a, fp, skip_blank_lines );++	fclose( fp );++	return ret;+}++int+slist_copy( slist *to, slist *from )+{+	slist_index i;+	int status;++	assert( to );+	assert( from );++	slist_free( to );++	if ( from->n==0 ) return SLIST_OK;++	status = slist_ensure_space( to, from->n, SLIST_EXACT_SIZE );++	if ( status == SLIST_OK ) {++		to->sorted = from->sorted;+		to->n      = from->n;++		for ( i=0; i<from->n; i++ ) {+			str_strcpy( &(to->strs[i]), &(from->strs[i]) );+			if ( str_memerr( &(to->strs[i]) ) ) return SLIST_ERR_MEMERR;+		}++	}+	return SLIST_OK;+}++slist *+slist_dup( slist *from )+{+	int status;+	slist *to;++	to = slist_new();+	if ( to ) {+		status = slist_copy( to, from );+		if ( status!=SLIST_OK ) {+			slist_delete( to );+			to = NULL;+		}+	}++	return to;+}++unsigned long+slist_get_maxlen( slist *a )+{+	unsigned long max = 0;+	slist_index i;+	str *s;++	assert( a );++	for ( i=0; i<a->n; ++i ) {+		s = slist_str( a, i );+		if ( s->len > max ) max = s->len;+	}++	return max;+}++void+slist_dump( slist *a, FILE *fp, int newline )+{+	slist_index i;++	assert( a );+	assert( fp );++	if ( newline ) {+		for ( i=0; i<a->n; ++i )+			fprintf( fp, "%s\n", slist_cstr( a, i ) );+	}++	else {+		for ( i=0; i<a->n; ++i )+			fprintf( fp, "%s", slist_cstr( a, i ) );+	}+}++int+slist_match_entry( slist *a, int n, const char *s )+{+	assert( a );++	if ( !slist_valid_num( a, n ) ) return 0;+	if ( str_strcmpc( &(a->strs[n]), s ) ) return 0;+	return 1;+}++void+slist_trimend( slist *a, int n )+{+	slist_index i;++	assert( a );++	if ( a->n - n < 1 ) {+		slist_empty( a );+	} else {+		for ( i=a->n -n; i<a->n; ++i ) {+			str_empty( &(a->strs[i]) );+		}+		a->n -= n;+	}+}++int+slist_tokenizec( slist *tokens, char *p, const char *delim, int merge_delim )+{+	int ret = SLIST_OK;+	str s, *t;+	char *q;++	assert( tokens );++	slist_empty( tokens );+	str_init( &s );+	while ( p && *p ) {+		q = p;+		while ( *q && !strchr( delim, *q ) ) q++;+		str_segcpy( &s, p, q );+		if ( str_memerr( &s ) ) { ret = SLIST_ERR_MEMERR; goto out; }+		if ( s.len ) {+			t = slist_addvp( tokens, SLIST_STR, (void*) &s );+			if ( !t ) { ret = SLIST_ERR_MEMERR; goto out; }+		} else if ( !merge_delim ) {+			t = slist_addvp( tokens, SLIST_CHR, (void*) "" );+			if ( !t ) { ret = SLIST_ERR_MEMERR; goto out; }+		}+		p = q;+		if ( *p ) p++;+	}+out:+	str_free( &s );+	return ret;+}++int+slist_tokenize( slist *tokens, str *in, const char *delim, int merge_delim )+{+	return slist_tokenizec( tokens, str_cstr( in ), delim, merge_delim );+}++void+slists_init( slist *a, ... )+{+	slist *a2;+	va_list ap;+	slist_init( a );+	va_start( ap, a );+	do {+		a2 = va_arg( ap, slist * );+		if ( a2 ) slist_init( a2 );+	} while ( a2 );+	va_end( ap );+}++void+slists_free( slist *a, ... )+{+	slist *a2;+	va_list ap;+	slist_free( a );+	va_start( ap, a );+	do {+		a2 = va_arg( ap, slist * );+		if ( a2 ) slist_free( a2 );+	} while ( a2 );+	va_end( ap );+}++void+slists_empty( slist *a, ... )+{+	slist *a2;+	va_list ap;+	slist_empty( a );+	va_start( ap, a );+	do {+		a2 = va_arg( ap, slist * );+		if ( a2 ) slist_empty( a2 );+	} while ( a2 );+	va_end( ap );+}
+ bibutils/slist.h view
@@ -0,0 +1,100 @@+/*+ * slist.h+ *+ * version: 2017-07-04+ *+ * Copyright (c) Chris Putnam 2004-2017+ *+ * Source code released under the GPL version 2+ *+ */++#ifndef SLIST_H+#define SLIST_H++#include <stdio.h>+#include <stdlib.h>+#include <stdarg.h>+#include <string.h>+#include "str.h"++#define SLIST_OK            (0)+#define SLIST_ERR_MEMERR   (-1)+#define SLIST_ERR_CANTOPEN (-2)+#define SLIST_ERR_BADPARAM (-3)++#define SLIST_CHR (0)+#define SLIST_STR (1)++typedef int slist_index;++typedef struct slist {+	slist_index n, max;+	int sorted;+	str *strs;+} slist;+++void    slists_init( slist *a, ... );+void    slists_free( slist *a, ... );+void    slists_empty( slist *a, ... );+++void    slist_init( slist *a );+int     slist_init_values ( slist *a, ... );+int     slist_init_valuesc( slist *a, ... );+void    slist_free( slist *a );+void    slist_empty( slist *a );++slist * slist_new( void );+void    slist_delete( slist * );+void    slist_deletev( void *v );++slist * slist_dup( slist *a );+int     slist_copy( slist *to, slist *from );+void    slist_swap( slist *a, slist_index n1, slist_index n2 );++str *   slist_addvp( slist *a, unsigned char mode, void *vp );+str *   slist_addc( slist *a, const char *value );+str *   slist_add( slist *a, str *value );++int     slist_addvp_all( slist *a, unsigned char mode, ... );+int     slist_addc_all( slist *a, ... );+int     slist_add_all( slist *a, ... );++str *   slist_addvp_unique( slist *a, unsigned char mode, void *vp );+str *   slist_addc_unique( slist *a, const char *value );+str *   slist_add_unique( slist *a, str *value );++int     slist_append( slist *a, slist *toadd );+int     slist_append_unique( slist *a, slist *toadd );++int     slist_remove( slist *a, slist_index n );++str *   slist_str( slist *a, slist_index n );+char *  slist_cstr( slist *a, slist_index n );++str *   slist_set( slist *a, slist_index n, str *s );+str *   slist_setc( slist *a, slist_index n, const char *s );++void    slist_sort( slist *a );++int     slist_find( slist *a, str *searchstr );+int     slist_findc( slist *a, const char *searchstr );+int     slist_findnocase( slist *a, str *searchstr );+int     slist_findnocasec( slist *a, const char *searchstr );+int     slist_wasfound( slist *a, slist_index n );+int     slist_wasnotfound( slist *a, slist_index n );++int     slist_match_entry( slist *a, slist_index n, const char *s );+void    slist_trimend( slist *a, slist_index n );++unsigned long slist_get_maxlen( slist *a );+void    slist_dump( slist *a, FILE *fp, int newline );++int     slist_fill( slist *a, const char *filename, unsigned char skip_blank_lines );+int     slist_fillfp( slist *a, FILE *fp, unsigned char skip_blank_lines );+int     slist_tokenize( slist *tokens, str *in, const char *delim, int merge_delim );+int     slist_tokenizec( slist *tokens, char *p, const char *delim, int merge_delim );++#endif
+ bibutils/str.c view
@@ -0,0 +1,1041 @@+/*+ * str.c+ *+ * Version: 2017-07-03+ *+ * Copyright (c) Chris Putnam 1999-2017+ *+ * Source code released under the GPL version 2+ *+ *+ * routines for dynamically allocated strings+ *+ */+#include <stdio.h>+#include <stdlib.h>+#include <stdarg.h>+#include <string.h>+#include <ctype.h>+#include <limits.h>+#include "is_ws.h"+#include "str.h"++/* Do not use asserts in STR_NOASSERT defined */+#ifdef STR_NOASSERT+#define NDEBUG+#endif+#include <assert.h>++#define str_initlen (64)+++/* Clear memory in resize/free if STR_PARANOIA defined */++#ifndef STR_PARANOIA++static void +str_realloc( str *s, unsigned long minsize )+{+	char *newptr;+	unsigned long size;+	assert( s );+	size = 2 * s->dim;+	if (size < minsize) size = minsize;+	newptr = (char *) realloc( s->data, sizeof( *(s->data) )*size );+	if ( !newptr ) {+		fprintf(stderr,"Error.  Cannot reallocate memory (%ld bytes) in str_realloc.\n", sizeof(*(s->data))*size);+		exit( EXIT_FAILURE );+	}+	s->data = newptr;+	s->dim = size;+}++/* define as a no-op */+#define str_nullify( s )++#else++static void +str_realloc( str *s, unsigned long minsize )+{+	char *newptr;+	unsigned long size;+	assert( s );+	size = 2 * s->dim;+	if ( size < minsize ) size = minsize;+	newptr = (char *) malloc( sizeof( *(s->data) ) * size );+	if ( !newptr ) {+		fprintf( stderr, "Error.  Cannot reallocate memory (%d bytes)"+			" in str_realloc.\n", sizeof(*(s->data))*size );+		exit( EXIT_FAILURE );+	}+	if ( s->data ) {+		str_nullify( s );+		free( s->data );+	}+	s->data = newptr;+	s->dim = size;+}++static inline void+str_nullify( str *s )+{+	memset( s->data, 0, s->dim );+}++#endif++void +str_init( str *s )+{+	assert( s );+	s->dim = 0;+	s->len = 0;+	s->data = NULL;+}++void+str_initstr( str *s, str *from )+{+	assert( s );+	assert( from );+	str_init( s );+	str_strcpy( s, from );+}++void+str_initstrc( str *s, const char *initstr )+{+	assert( s );+	assert( initstr );+	str_init( s );+	str_strcpyc( s, initstr );+}++void+str_initstrsc( str *s, ... )+{+	const char *c;+	va_list ap;+	str_init( s );+	va_start( ap, s );+	do {+		c = va_arg( ap, const char * );+		if ( c ) str_strcatc( s, c );+	} while ( c );+	va_end( ap );+}++void+strs_init( str *s, ... )+{+	str *s2;+	va_list ap;+	str_init( s );+	va_start( ap, s );+	do {+		s2 = va_arg( ap, str * );+		if ( s2 ) str_init( s2 );+	} while ( s2 );+	va_end( ap );+}++/*+ * This is currently a stub. Later it will+ * report whether or not a str function+ * could not be performed due to a memory+ * error.+ */+int+str_memerr( str *s )+{+	return 0;+}++void+str_mergestrs( str *s, ... )+{+	va_list ap;+	const char *cp;+	str_empty( s );+	va_start( ap, s );+	do {+		cp = va_arg( ap, const char * );+		if ( cp ) str_strcatc( s, cp );+	} while ( cp );+	va_end( ap );+}++static void +str_initalloc( str *s, unsigned long minsize )+{+	unsigned long size = str_initlen;+	assert( s );+	if ( minsize > str_initlen ) size = minsize;+	s->data = (char *) malloc (sizeof( *(s->data) ) * size);+	if ( !s->data ) {+		fprintf(stderr,"Error.  Cannot allocate memory in str_initalloc.\n");+		exit( EXIT_FAILURE );+	}+	s->data[0]='\0';+	s->dim=size;+	s->len=0;+}++str *+str_new( void )+{+	str *s = (str *) malloc( sizeof( *s ) );+	if ( s )+		str_initalloc( s, str_initlen );+	return s;+}++void +str_free( str *s )+{+	assert( s );+	if ( s->data ) {+		str_nullify( s );+		free( s->data );+	}+	s->dim = 0;+	s->len = 0;+	s->data = NULL;+}++void+strs_free( str *s, ... )+{+	str *s2;+	va_list ap;+	str_free( s );+	va_start( ap, s );+	do {+		s2 = va_arg( ap, str * );+		if ( s2 ) str_free( s2 );+	} while ( s2 );+	va_end( ap );+}++void+str_delete( str *s )+{+	assert( s );+	str_free( s );+	free( s );+}++void+str_empty( str *s )+{+	assert( s );+	if ( s->data ) {+		str_nullify( s );+		s->data[0] = '\0';+	}+	s->len = 0;+}++void+strs_empty( str *s, ... )+{+	str *s2;+	va_list ap;+	str_empty( s );+	va_start( ap, s );+	do {+		s2 = va_arg( ap, str * );+		if ( s2 ) str_empty( s2 );+	} while ( s2 );+	va_end( ap );+}++void+str_addchar( str *s, char newchar )+{+	assert( s );+	if ( newchar=='\0' ) return; /* appending '\0' is a null operation */+	if ( !s->data || s->dim==0 ) +		str_initalloc( s, str_initlen );+	if ( s->len + 2 > s->dim ) +		str_realloc( s, s->len*2 );+	s->data[s->len++] = newchar;+	s->data[s->len] = '\0';+}++/* str_addutf8+ *+ * Add potential multibyte character to s starting at pointer p.+ * Multibyte Unicode characters have the high bit set.+ *+ * Since we can progress more than one byte at p, return the+ * properly updated pointer p.+ */+const char *+str_addutf8( str *s, const char *p )+{+	if ( ! ((*p) & 128 ) ) {+		str_addchar( s, *p );+		p++;+	} else {+		while ( ((*p) & 128) ) {+			str_addchar( s, *p );+			p++;+		}+	}+	return p;+}++char *+str_cstr( str *s )+{+	assert( s );+	return s->data;+}++void +str_fprintf( FILE *fp, str *s )+{+	assert( s );+	if ( s->data ) fprintf( fp, "%s", s->data );+}++void+str_prepend( str *s, const char *addstr )+{+	unsigned long lenaddstr, i;+	assert( s && addstr );+	lenaddstr = strlen( addstr );+	if ( lenaddstr==0 ) return;+	if ( !s->data || !s->dim )+		str_initalloc( s, lenaddstr+1 );+	else {+		if ( s->len + lenaddstr  + 1 > s->dim )+			str_realloc( s, s->len + lenaddstr + 1 );+		for ( i=s->len+lenaddstr-1; i>=lenaddstr; i-- )+			s->data[i] = s->data[i-lenaddstr];+	}+	strncpy( s->data, addstr, lenaddstr );+	s->len += lenaddstr;+	s->data[ s->len ] = '\0';+}++static inline void+str_strcat_ensurespace( str *s, unsigned long n )+{+	unsigned long m = s->len + n + 1;+	if ( !s->data || !s->dim )+		str_initalloc( s, m );+	else if ( s->len + n + 1 > s->dim )+		str_realloc( s, m );+}++static inline void +str_strcat_internal( str *s, const char *addstr, unsigned long n )+{+	str_strcat_ensurespace( s, n );+	strncat( &(s->data[s->len]), addstr, n );+	s->len += n;+	s->data[s->len]='\0';+}++void+str_strcat( str *s, str *from )+{+	assert ( s && from );+	if ( !from->data ) return;+	else str_strcat_internal( s, from->data, from->len );+}++void+str_strcatc( str *s, const char *from )+{+	unsigned long n;+	assert( s && from );+	n = strlen( from );+	str_strcat_internal( s, from, n );+}++void+str_segcat( str *s, char *startat, char *endat )+{+	unsigned long n;+	char *p;++	assert( s && startat && endat );+	assert( (size_t) startat < (size_t) endat );++	if ( startat==endat ) return;++	n = 0;+	p = startat;+	while ( p!=endat ) {+		n++;+		p++;+	}++	str_strcat_internal( s, startat, n );+}++void+str_indxcat( str *s, char *p, unsigned long start, unsigned long stop )+{+	unsigned long i;+	assert( s && p );+	assert( start <= stop );+	for ( i=start; i<stop; ++i )+		str_addchar( s, p[i] );+}++/* str_cpytodelim()+ *     term      = string of characters to be used as terminators+ *     finalstep = set to non-zero to position return value past the+ *                 terminating character+ */+char *+str_cpytodelim( str *s, char *p, const char *delim, unsigned char finalstep )+{+	assert( s );+	str_empty( s );+	return str_cattodelim( s, p, delim, finalstep );+}++/* str_cpytodelim()+ *     term      = string of characters to be used as terminators+ *     finalstep = set to non-zero to position return value past the+ *                 terminating character+ */+char *+str_cattodelim( str *s, char *p, const char *delim, unsigned char finalstep )+{+	assert( s );+	while ( p && *p && !strchr( delim, *p ) ) {+		str_addchar( s, *p );+		p++;+	}+	if ( p && *p && finalstep ) p++;+	return p;+}++static inline void+str_strcpy_ensurespace( str *s, unsigned long n )+{+	unsigned long m = n + 1;+	if ( !s->data || !s->dim )+		str_initalloc( s, m );+	else if ( m > s->dim )+		str_realloc( s, m );+}++static inline void+str_strcpy_internal( str *s, const char *p, unsigned long n )+{+	str_strcpy_ensurespace( s, n );+	strncpy( s->data, p, n );+	s->data[n] = '\0';+	s->len = n;+}++void+str_strcpy( str *s, str *from )+{+	assert( s );+	assert( from );+	if ( s==from ) return;+	else if ( !from || from->len==0 ) str_empty( s );+	else str_strcpy_internal( s, from->data, from->len );+}++void +str_strcpyc( str *s, const char *from )+{+	unsigned long n;+	assert( s && from );+	n = strlen( from );+	str_strcpy_internal( s, from, n );+}++/* str_segcpy( s, start, end );+ *+ * copies [start,end) into s+ */+void+str_segcpy( str *s, char *startat, char *endat )+{+	unsigned long n;+	char *p;++	assert( s && startat && endat );+	assert( ((size_t) startat) <= ((size_t) endat) );++	if ( startat==endat ) {+		str_empty( s );+		return;+	}++	n = 0;+	p = startat;+	while ( p!=endat ) {+		p++;+		n++;+	}++	str_strcpy_internal( s, startat, n );+}++/*+ * str_indxcpy( s, in, start, stop );+ *+ * copies in[start,stop) (excludes stop) into s+ */+void+str_indxcpy( str *s, char *p, unsigned long start, unsigned long stop )+{+	unsigned long i;+	assert( s && p );+	assert( start <= stop );+	if ( start == stop ) {+		str_empty( s );+		return;+	}+	str_strcpy_ensurespace( s, stop-start+1 );+	for ( i=start; i<stop; ++i )+		s->data[i-start] = p[i];+	s->len = stop-start;+	s->data[s->len] = '\0';+}++str *+str_strdup( str *from )+{+	str *s = str_new();+	if ( s )+		str_strcpy( s, from );+	return s;+}++str *+str_strdupc( const char *from )+{+	str *s = str_new();+	if ( s )+		str_strcpyc( s, from );+	return s;+}++void+str_segdel( str *s, char *p, char *q )+{+	str tmp1, tmp2;+	char *r;+	assert( s );+	r = &(s->data[s->len]);+	str_init( &tmp1 );+	str_init( &tmp2 );+	str_segcpy( &tmp1, s->data, p );+	str_segcpy( &tmp2, q, r );+	str_empty( s );+	if ( tmp1.data ) str_strcat( s, &tmp1 );+	if ( tmp2.data ) str_strcat( s, &tmp2 );+	str_free( &tmp2 );+	str_free( &tmp1 );+}++/*+ * str_findreplace()+ *+ *   if replace is "" or NULL, then delete find+ */++int+str_findreplace( str *s, const char *find, const char *replace )+{+	long diff;+	size_t findstart, searchstart;+	size_t p1, p2;+	size_t find_len, rep_len, curr_len;+	char empty[2] = "";+	unsigned long minsize;+	char *p;+	int n = 0;++	assert( s && find );+	if ( !s->data || !s->dim ) return n;+	if ( !replace ) replace = empty;++	find_len = strlen( find );+	rep_len  = strlen( replace );+	diff     = rep_len - find_len;+	if ( diff < 0 ) diff = 0;++	searchstart=0;+	while ((p=strstr(s->data + searchstart,find))!=NULL) {+		curr_len = strlen(s->data);+		findstart=(size_t) p - (size_t) s->data;+		minsize = curr_len + diff + 1;+		if (s->dim <= minsize) str_realloc( s, minsize );+		if ( find_len > rep_len ) {+			p1 = findstart + rep_len;+			p2 = findstart + find_len;+			while( s->data[p2] )+				s->data[p1++]=s->data[p2++];+			s->data[p1]='\0';+			n++;+		} else if ( find_len < rep_len ) {+			for ( p1=curr_len; p1>=findstart+find_len; p1-- )+				s->data[p1+diff] = s->data[p1];+			n++;+		}+		for (p1=0; p1<rep_len; p1++)+			s->data[findstart+p1]=replace[p1];+		searchstart = findstart + rep_len; +		s->len += rep_len - find_len;+	}+	return n;+}+++/* str_fget()+ *   returns 0 if we're done, 1 if we're not done+ *   extracts line by line (regardless of end characters)+ *   and feeds from buf....+ */+int+str_fget( FILE *fp, char *buf, int bufsize, int *pbufpos, str *outs )+{+	int  bufpos = *pbufpos, done = 0;+	char *ok;+	assert( fp && outs );+	str_empty( outs );+	while ( !done ) {+		while ( buf[bufpos] && buf[bufpos]!='\r' && buf[bufpos]!='\n' )+			str_addchar( outs, buf[bufpos++] );+		if ( buf[bufpos]=='\0' ) {+			ok = fgets( buf, bufsize, fp );+			bufpos=*pbufpos=0;+			if ( !ok && feof(fp) ) { /* end-of-file */+				buf[bufpos] = 0;+				if ( outs->len==0 ) return 0; /*nothing in out*/+				else return 1; /*one last out */+			}+		} else if ( buf[bufpos]=='\r' || buf[bufpos]=='\n' ) done=1;+	}+	if ( ( buf[bufpos]=='\n' && buf[bufpos+1]=='\r') ||+	     ( buf[bufpos]=='\r' && buf[bufpos+1]=='\n') ) bufpos+=2;+	else if ( buf[bufpos]=='\n' || buf[bufpos]=='\r' ) bufpos+=1; +	*pbufpos = bufpos;+	return 1;+}++void+str_toupper( str *s )+{+	unsigned long i;+	assert( s );+	for ( i=0; i<s->len; ++i )+		s->data[i] = toupper( (unsigned char)s->data[i] );+}++void+str_tolower( str *s )+{+	unsigned long i;+	assert( s );+	for ( i=0; i<s->len; ++i )+		s->data[i] = tolower( (unsigned char)s->data[i] );+}++/* str_swapstrings( s1, s2 )+ * be sneaky and swap internal string data from one+ * string to another+ */+void+str_swapstrings( str *s1, str *s2 )+{+	char *tmpp;+	int tmp;++	assert( s1 && s2 );++	/* swap dimensioning info */+	tmp = s1->dim;+	s1->dim = s2->dim;+	s2->dim = tmp;++	/* swap length info */+	tmp = s1->len;+	s1->len = s2->len;+	s2->len = tmp;++	/* swap data */+	tmpp = s1->data;+	s1->data = s2->data;+	s2->data = tmpp;+}++void+str_trimstartingws( str *s )+{+	char *p, *q;+	int n;++	assert( s );++	if ( s->len==0 || !is_ws( s->data[0] ) ) return;++	n = 0;+	p = s->data;+	while ( is_ws( *p ) ) p++;++	q = s->data;+	while ( *p ) {+		*q++ = *p++;+		n++;+	}+	*q = '\0';++	s->len = n;+}++void+str_trimendingws( str *s )+{+	assert( s );+	while ( s->len > 0 && is_ws( s->data[s->len-1] ) ) {+		s->data[s->len-1] = '\0';+		s->len--;+	}+}++int+str_match_first( str *s, char ch )+{+	assert( s );+	if ( !s->len ) return 0;+	if ( s->data[0] == ch ) return 1;+	return 0;+}++int+str_match_end( str *s, char ch )+{+	assert( s );+	if ( !s->len ) return 0;+	if ( s->data[ s->len - 1 ] == ch ) return 1;+	return 0;+}++void+str_trimbegin( str *s, unsigned long n )+{+	char *p, *q;++	assert( s );++	if ( n==0 ) return;+	if ( s->len==0 ) return;+	if ( n >= s->len ) {+		str_empty( s );+		return;+	}++	p = s->data;+	while ( n-- > 0 ) p++;++	n = 0;+	q = s->data;+	while ( *p ) {+		*q++ = *p++;+		n++;+	}+	*q = '\0';++	s->len = n;+}++void+str_trimend( str *s, unsigned long n )+{+	assert( s );++	if ( n==0 ) return;+	if ( n >= s->len ) {+		str_empty( s );+		return;+	}++	s->len -= n;+	s->data[ s->len ] = '\0';+}++void+str_pad( str *s, unsigned long len, char ch )+{+	unsigned long i;+	assert( s );+	for ( i=s->len; i<len; i++ )+		str_addchar( s, ch );+}++void+str_copyposlen( str *s, str *in, unsigned long pos, unsigned long len )+{+	unsigned long i, max;+	assert( s );+	str_empty( s );+	max = pos+len;+	if ( max > in->len ) max = in->len;+	for ( i=pos; i<max; ++i )+		str_addchar( s, in->data[i] );+}++static void+str_check_case( str *s, int *lowercase, int *uppercase )+{+	int i;+	assert( s );+	*lowercase = 0;+	*uppercase = 0;+	if ( s->len < 1 ) return;+	for ( i=0; i<s->len && !( *lowercase && *uppercase ); ++i ) {+		if ( isalpha( (unsigned char)s->data[i] ) ) {+			if ( isupper( (unsigned char)s->data[i] ) ) *uppercase += 1;+			else if ( islower( (unsigned char)s->data[i] ) ) *lowercase += 1;+		}+	}+}++int+str_is_mixedcase( str *s )+{+	int lowercase, uppercase;+	str_check_case( s, &lowercase, &uppercase );+	if ( lowercase > 0 && uppercase > 0 ) return 1;+	return 0;+}++int+str_is_lowercase( str *s )+{+	int lowercase, uppercase;+	str_check_case( s, &lowercase, &uppercase );+	if ( lowercase > 0 && uppercase == 0 ) return 1;+	return 0;+}++int+str_is_uppercase( str *s )+{+	int lowercase, uppercase;+	str_check_case( s, &lowercase, &uppercase );+	if ( lowercase == 0 && uppercase > 0 ) return 1;+	return 0;+}++void+str_stripws( str *s )+{+	unsigned long len = 0;+	char *p, *q;+	assert( s );+	if ( s->len ) {+		p = q = s->data;+		while ( *p ) {+			if ( !is_ws( *p ) ) {+				*q = *p;+				q++;+				len++;+			}+			p++;+		}+		*q = '\0';+	}+	s->len = len;+}++int+str_strcmp( const str *s, const str *t )+{+	assert( s );+	assert( t );+	if ( s->len == 0 && t->len == 0 ) return 0;+	if ( s->len == 0 ) return strcmp( "", t->data );+	if ( t->len == 0 ) return strcmp( s->data, "" );+	return strcmp( s->data, t->data );+}++int+str_strcmpc( const str *s, const char *t )+{+	assert( s );+	assert( t );+	if ( s->len == 0 ) return strcmp( "", t );+	return strcmp( s->data, t );+}++int+str_strncmp( const str *s, const str *t, size_t n )+{+	assert( s );+	assert( t );+	if ( s->len == 0 && t->len == 0 ) return 0;+	if ( s->len == 0 ) return strncmp( "", t->data, n );+	if ( t->len == 0 ) return strncmp( s->data, "", n );+	return strncmp( s->data, t->data, n );+}++int+str_strncmpc( const str *s, const char *t, size_t n )+{+	assert( s );+	assert( t );+	if ( s->len == 0 ) return strncmp( "", t, n );+	return strncmp( s->data, t, n );+}++int+str_strcasecmp( const str *s, const str *t )+{+	assert( s );+	assert( t );+	if ( s->len == 0 && t->len == 0 ) return 0;+	if ( s->len == 0 ) return strcasecmp( "", t->data );+	if ( t->len == 0 ) return strcasecmp( s->data, "" );+	return strcasecmp( s->data, t->data );+}++int+str_strcasecmpc( const str *s, const char *t )+{+	assert( s );+	assert( t );+	if ( s->len == 0 ) return strcasecmp( "", t );+	return strcasecmp( s->data, t );+}++char *+str_strstr( const str *s, const str *t )+{+	assert( s );+	assert( t );+	if ( s->len == 0 && t->len == 0 ) return strstr( "", "" );+	if ( s->len == 0 ) return strstr( "", t->data );+	if ( t->len == 0 ) return strstr( s->data, "" );+	return strstr( s->data, t->data );+}++char *+str_strstrc( const str *s, const char *t )+{+	assert( s );+	assert( t );+	if ( s->len == 0 ) return strstr( "", t );+	return strstr( s->data, t );+}++void+str_reverse( str *s )+{+	unsigned long i, max;+	char tmp;+	assert( s );+	max = s->len / 2;+	for ( i=0; i<max; ++i ) {+		tmp = s->data[ i ];+		s->data[ i ] = s->data[ s->len - 1 - i ];+		s->data[ s->len - 1 - i ] = tmp;+	}+}++int+str_fgetline( str *s, FILE *fp )+{+	int ch, eol = 0;+	assert( s );+	assert( fp );+	str_empty( s );+	if ( feof( fp ) ) return 0;+	while ( !feof( fp ) && !eol ) {+		ch = fgetc( fp );+		if ( ch == EOF ) {+			if ( s->len ) return 1;+			else return 0;+		}+		else if ( ch == '\n' ) eol = 1;+		else if ( ch == '\r' ) {+			ch = fgetc( fp );+			if ( ch != '\n' ) ungetc( ch, fp );+			eol = 1;+		} else {+			str_addchar( s, (char) ch );+		}+	}+	return 1;+}++/*+ * s = "Hi!\0", s.len = 3+ *+ * str_char( s, 0 ) = 'H'  str_revchar( s, 0 ) = '!'+ * str_char( s, 1 ) = 'i'  str_revchar( s, 1 ) = 'i'+ * str_char( s, 2 ) = '!'  str_revchar( s, 2 ) = 'H'+ * str_char( s, 3 ) = '\0' str_revchar( s, 3 ) = '\0'+ */+char+str_char( str *s, unsigned long n )+{+	assert( s );+	if ( s->len==0 || n >= s->len ) return '\0';+	return s->data[ n ];+}++char+str_revchar( str *s, unsigned long n )+{+	assert( s );+	if ( s->len==0 || n >= s->len ) return '\0';+	return s->data[ s->len - n - 1];+}++void+str_makepath( str *path, const char *dirname, const char *filename, char sep )+{+	assert( path );+	if ( dirname ) str_strcpyc( path, dirname );+	else str_empty( path );++	if ( path->len && path->data[path->len-1]!=sep )+		str_addchar( path, sep );++	if ( filename ) str_strcatc( path, filename );+}++void+str_fill( str *s, unsigned long n, char fillchar )+{+	unsigned long i;+	assert( s );+	if ( !s->data || s->dim==0 )+		str_initalloc( s, n+1 );+	if ( n + 1 > s->dim )+		str_realloc( s, n+1 );+	for ( i=0; i<n; ++i )+		s->data[i] = fillchar;+	s->data[n] = '\0';+	s->len = n;+}++int+str_has_value( str *s )+{+	if ( !s || s->len==0 ) return 0;+	return 1;+}++int+str_is_empty( str *s )+{+	if ( !s || s->len==0 ) return 1;+	return 0;+}
+ bibutils/str.h view
@@ -0,0 +1,124 @@+/*+ * str.h+ *+ * Version: 2017-07-03+ *+ * Copyright (c) Chris Putnam 1999-2017+ *+ * Source code released under the GPL version 2+ *+ */+#ifndef STR_H+#define STR_H++#include <stdio.h>++typedef struct str {+	char *data;+	unsigned long dim;+	unsigned long len;+}  str;++str *  str_new         ( void );+void   str_delete      ( str *s );++void   str_init        ( str *s );+void   str_initstr     ( str *s, str *from );+void   str_initstrc    ( str *s, const char *initstr );+void   str_initstrsc   ( str *s, ... );+void   str_empty       ( str *s );+void   str_free        ( str *s );++void   strs_init       ( str *s, ... );+void   strs_empty      ( str *s, ... );+void   strs_free       ( str *s, ... );++str*   str_strdup ( str *s );+str*   str_strdupc( const char *p );++void   str_strcat ( str *s, str *from );+void   str_strcatc( str *s, const char *from );++void   str_strcpy ( str *s, str *from );+void   str_strcpyc( str *s, const char *from );++int    str_strcmp ( const str *s, const str *t );+int    str_strcmpc( const str *s, const char *t );++int    str_strncmp ( const str *s, const str *t,  size_t n );+int    str_strncmpc( const str *s, const char *t, size_t n );++int    str_strcasecmp ( const str *s, const str *t );+int    str_strcasecmpc( const str *s, const char *t );++char * str_strstr ( const str *s, const str *t );+char * str_strstrc( const str *s, const char *t );++void str_prepend     ( str *s, const char *addstr );+void str_mergestrs   ( str *s, ... );++void str_addchar     ( str *s, char newchar );+void str_reverse     ( str *s );+const char *str_addutf8    ( str *s, const char *p );+void str_segcat      ( str *s, char *startat, char *endat );+char *str_cpytodelim  ( str *s, char *p, const char *delim, unsigned char finalstep );+char *str_cattodelim  ( str *s, char *p, const char *delim, unsigned char finalstep );+void str_prepend     ( str *s, const char *addstr );+void str_segcpy      ( str *s, char *startat, char *endat );+void str_segdel      ( str *s, char *startat, char *endat );+void str_indxcpy     ( str *s, char *p, unsigned long start, unsigned long stop );+void str_indxcat     ( str *s, char *p, unsigned long start, unsigned long stop );+void str_fprintf     ( FILE *fp, str *s );+int  str_fget        ( FILE *fp, char *buf, int bufsize, int *pbufpos,+                          str *outs );+char * str_cstr      ( str *s );+char str_char        ( str *s, unsigned long n );+char str_revchar     ( str *s, unsigned long n );+int  str_fgetline    ( str *s, FILE *fp );+int  str_findreplace ( str *s, const char *find, const char *replace );+void str_toupper     ( str *s );+void str_tolower     ( str *s );+void str_trimstartingws( str *s );+void str_trimendingws( str *s );+void str_swapstrings ( str *s1, str *s2 );+void str_stripws     ( str *s );++int  str_match_first ( str *s, char ch );+int  str_match_end   ( str *s, char ch );+void str_trimbegin   ( str *s, unsigned long n );+void str_trimend     ( str *s, unsigned long n );++void str_pad         ( str *s, unsigned long len, char ch );+void str_copyposlen  ( str *s, str *in, unsigned long pos, unsigned long len );++void str_makepath    ( str *path, const char *dirname, const char *filename, char sep );++void str_fill        ( str *s, unsigned long n, char fillchar );++int  str_is_mixedcase( str *s );+int  str_is_lowercase( str *s );+int  str_is_uppercase( str *s );++int  str_memerr( str *s );++int  str_has_value( str *s );+int  str_is_empty( str *s );+++/* #define STR_PARANOIA+ *+ * set to clear memory before it is freed or reallocated+ * note that this is slower...may be important if string+ * contains sensitive information+ */++/* #define STR_NOASSERT+ *+ * set to turn off the use of asserts (and associated call to exit)+ * in str functions...useful for library construction for+ * Linux distributions that don't want libraries calling exit, but+ * not useful during code development+ */++#endif+
+ bibutils/str_conv.c view
@@ -0,0 +1,196 @@+/*+ * str_conv.c+ *+ * Copyright (c) Chris Putnam 1999-2017+ *+ * Source code released under the GPL version 2+ *+ * str routines for converting strs between character sets+ *+ */+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <ctype.h>+#include <limits.h>+#include "latex.h"+#include "entities.h"+#include "utf8.h"+#include "gb18030.h"+#include "charsets.h"+#include "str_conv.h"++static void+addentity( str *s, unsigned int ch )+{+	char buf[512];+	sprintf( buf, "&#%d;", ch );+	str_strcatc( s, buf );+}++/* These are the five minimal predefined entites in XML */+static int+minimalxmlchars( str *s, unsigned int ch )+{+	if ( ch==34 )      { str_strcatc( s, "&quot;" ); return 1; }+	else if ( ch==38 ) { str_strcatc( s, "&amp;" );  return 1; }+	else if ( ch==39 ) { str_strcatc( s, "&apos;" ); return 1; }+	else if ( ch==60 ) { str_strcatc( s, "&lt;" );   return 1; }+	else if ( ch==62 ) { str_strcatc( s, "&gt;" );   return 1; }+	return 0;+}++static void+addxmlchar( str *s, unsigned int ch )+{+	if ( minimalxmlchars( s, ch ) ) return;+	if ( ch > 127 ) addentity( s, ch );+	else str_addchar( s, ch );+}++static void+addutf8char( str *s, unsigned int ch, int xmlout )+{+	unsigned char code[6];+	int nc, i;+	if ( xmlout ) {+		if ( minimalxmlchars( s, ch ) ) return;+		if ( ch > 127 && xmlout == STR_CONV_XMLOUT_ENTITIES )+			{ addentity( s, ch ); return; }+	}+	nc = utf8_encode( ch, code );+	for ( i=0; i<nc; ++i )+		str_addchar( s, code[i] );+}++static void+addgb18030char( str *s, unsigned int ch, int xmlout )+{+	unsigned char code[4];+	int nc, i;+	if ( xmlout ) {+		if ( minimalxmlchars( s, ch ) ) return;+		if ( ch > 127 && xmlout == STR_CONV_XMLOUT_ENTITIES )+			{ addentity( s, ch ); return; }+	}+	nc = gb18030_encode( ch, code );+	for ( i=0; i<nc; ++i )+		str_addchar( s, code[i] );+}++static void+addlatexchar( str *s, unsigned int ch, int xmlout, int utf8out )+{+	char buf[512];+	uni2latex( ch, buf, sizeof( buf ) );+	/* If the unicode character isn't recognized as latex output+	 * a '?' unless the user has requested unicode output.  If so,+	 * output the unicode.+	 */+	if ( utf8out && !strcmp( buf, "?" ) ) {+		addutf8char( s, ch, xmlout );+	} else {+		str_strcatc( s, buf );+	}+}++/*+ * get_unicode()+ * + *   This can be a little tricky.  If the character is simply encoded+ *   such as UTF8 for > 128 or by numeric xml entities such as "&#534;"+ *   then the output of decode_entity() and utf8_decode will necessarily+ *   be in the charsetin character set.  On the other hand, if it's a+ *   fancy latex expression, such as "\alpha", or a non-numeric xml entity+ *   like "&amp;", then we'll get the Unicode value (because our lists only+ *   keep the Unicode equivalent).+ *+ *   The unicode variable indicates whether or not a Unicode-based listing+ *   was used to convert the character (remember that charsetin could be+ *   Unicode independently).+ *+ *   The charset variable is used to keep track of what character set+ *   the character is in prior to conversion.+ *+ */++static unsigned int+get_unicode( str *s, unsigned int *pi, int charsetin, int latexin, int utf8in, int xmlin )+{+	unsigned int ch;+	int unicode = 0, err = 0;+	if ( xmlin && s->data[*pi]=='&' ) {+		ch = decode_entity( s->data, pi, &unicode, &err );+	} else if ( charsetin==CHARSET_GB18030 ) {+		ch = gb18030_decode( s->data, pi );+		unicode = 1;+	} else if ( latexin ) {+		/* Must handle bibtex files in UTF8/Unicode */+		if ( utf8in && ( s->data[*pi] & 128 ) ) {+			ch = utf8_decode( s->data, pi );+			unicode = 1;+		} else ch = latex2char( s->data, pi, &unicode );+	}+	else if ( utf8in )+		ch = utf8_decode( s->data, pi );+	else {+		ch = (unsigned int) s->data[*pi];+		*pi = *pi + 1;+	}+	if ( !unicode && charsetin!=CHARSET_UNICODE )+		ch = charset_lookupchar( charsetin, ch );+	return ch;+}++static int+write_unicode( str *s, unsigned int ch, int charsetout, int latexout,+		int utf8out, int xmlout )+{+	unsigned int c;+	if ( latexout ) {+		addlatexchar( s, ch, xmlout, utf8out );+	} else if ( utf8out ) {+		addutf8char( s, ch, xmlout );+	} else if ( charsetout==CHARSET_GB18030 ) {+		addgb18030char( s, ch, xmlout );+	} else {+		c = charset_lookupuni( charsetout, ch );+		if ( xmlout ) addxmlchar( s, c );+		else str_addchar( s, c );+	}+	return 1;+}++/*+ * Returns 1 on memory error condition+ */+int+str_convert( str *s,+	int charsetin,  int latexin,  int utf8in,  int xmlin,+	int charsetout, int latexout, int utf8out, int xmlout )+{+	unsigned int pos = 0;+	unsigned int ch;+	str ns;+	int ok = 1;++	if ( !s || s->len==0 ) return ok;++	str_init( &ns );++	if ( charsetin==CHARSET_UNKNOWN ) charsetin = CHARSET_DEFAULT;+	if ( charsetout==CHARSET_UNKNOWN ) charsetout = CHARSET_DEFAULT;++	while ( s->data[pos] ) {+		ch = get_unicode( s, &pos, charsetin, latexin, utf8in, xmlin );+		ok = write_unicode( &ns, ch, charsetout, latexout, utf8out, xmlout );+		if ( !ok ) goto out;+	}++	str_swapstrings( s, &ns );+out:+	str_free( &ns );++	return ok;+}+
+ bibutils/str_conv.h view
@@ -0,0 +1,23 @@+/*+ * str_conv.h+ *+ * Copyright (c) Chris Putnam 1999-2017+ *+ * Source code released under the GPL version 2+ *+ */+#ifndef STR_CONV_H+#define STR_CONV_H++#define STR_CONV_XMLOUT_FALSE    (0)+#define STR_CONV_XMLOUT_TRUE     (1)+#define STR_CONV_XMLOUT_ENTITIES (3)++#include "str.h"++extern int str_convert( str *s,+		int charsetin, int latexin, int utf8in, int xmlin, +		int charsetout, int latexout, int utf8out, int xmlout );++#endif+
bibutils/strsearch.c view
@@ -1,6 +1,6 @@ /* strsearch.c  *- * Copyright (c) Chris Putnam 1995-2013+ * Copyright (c) Chris Putnam 1995-2017  *  * Source code released under the GPL version 2  *
bibutils/strsearch.h view
@@ -1,7 +1,7 @@ /*  * strsearch.h  *- * Copyright (c) Chris Putnam 1995-2013+ * Copyright (c) Chris Putnam 1995-2017  *  * Source code released under the GPL version 2  *
bibutils/title.c view
@@ -3,7 +3,7 @@  *  * process titles into title/subtitle pairs for MODS  *- * Copyright (c) Chris Putnam 2004-2014+ * Copyright (c) Chris Putnam 2004-2017  *  * Source code released under the GPL version 2  *@@ -11,7 +11,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h>-#include "newstr.h"+#include "str.h" #include "fields.h" #include "title.h" #include "is_ws.h"@@ -20,12 +20,12 @@ title_process( fields *info, char *tag, char *data, int level,  	unsigned char nosplittitle ) {-	newstr title, subtitle;+	str title, subtitle; 	char *p, *q; 	int status; -	newstr_init( &title );-	newstr_init( &subtitle );+	str_init( &title );+	str_init( &subtitle );  	if ( nosplittitle ) q = NULL; 	else {@@ -33,36 +33,68 @@ 		if ( !q ) q = strstr( data, "? " ); 	} -	if ( !q ) newstr_strcpy( &title, data );+	if ( !q ) str_strcpyc( &title, data ); 	else { 		p = data;-		while ( p!=q ) newstr_addchar( &title, *p++ );-		if ( *q=='?' ) newstr_addchar( &title, '?' );+		while ( p!=q ) str_addchar( &title, *p++ );+		if ( *q=='?' ) str_addchar( &title, '?' ); 		q++; 		q = skip_ws( q );-		while ( *q ) newstr_addchar( &subtitle, *q++ );+		while ( *q ) str_addchar( &subtitle, *q++ ); 	}  	if ( strncasecmp( "SHORT", tag, 5 ) ) {-		if ( title.len>0 ) {-			status = fields_add( info, "TITLE", title.data, level );+		if ( str_has_value( &title ) ) {+			status = fields_add( info, "TITLE", str_cstr( &title ), level ); 			if ( status!=FIELDS_OK ) return 0; 		}-		if ( subtitle.len>0 ) {-			status = fields_add( info, "SUBTITLE", subtitle.data, level );+		if ( str_has_value( &subtitle ) ) {+			status = fields_add( info, "SUBTITLE", str_cstr( &subtitle ), level ); 			if ( status!=FIELDS_OK ) return 0; 		} 	} else {-		if ( title.len>0 ) {-			status = fields_add( info, "SHORTTITLE", title.data, level );+		if ( str_has_value( &title ) ) {+			status = fields_add( info, "SHORTTITLE", str_cstr( &title ), level ); 			if ( status!=FIELDS_OK ) return 0; 		} 		/* no SHORT-SUBTITLE! */ 	} -	newstr_free( &subtitle );-	newstr_free( &title );+	str_free( &subtitle );+	str_free( &title );  	return 1; } +/* title_combine()+ *+ * Combine a main title and a subtitle into a full title.+ *+ * Example:+ * 	Main title = "A Clearing in the Distance"+ * 	Subtitle   = "The Biography of Frederick Law Olmstead"+ * 	Full title = "A Clearing in the Distance: The Biography of Frederick Law Olmstead"+ * Example:+ *	Main title = "What Makes a Good Team Player?"+ *	Subtitle   = "Personality and Team Effectiveness"+ *	Full title = "What Makes a Good Team Player? Personality and Team Effectiveness"+ */+void+title_combine( str *fullttl, str *mainttl, str *subttl )+{+	str_empty( fullttl );++	if ( !mainttl ) return;++	str_strcpy( fullttl, mainttl );++	if ( subttl ) {+		if ( str_has_value( mainttl ) ) {+			if ( mainttl->data[ mainttl->len - 1 ] != '?' && mainttl->data[ mainttl->len - 1] != ':' )+				str_strcatc( fullttl, ": " );+			else+				str_strcatc( fullttl, " " );+		}+		str_strcat( fullttl, subttl );+	}+}
bibutils/title.h view
@@ -3,7 +3,7 @@  *  * process titles into title/subtitle pairs for MODS  *- * Copyright (c) Chris Putnam 2004-2014+ * Copyright (c) Chris Putnam 2004-2017  *  * Source code released under the GPL verison 2  *@@ -11,10 +11,10 @@ #ifndef TITLE_H #define TITLE_H -#include "newstr.h"+#include "str.h" #include "fields.h" -extern int title_process( fields *info, char *tag, char *data, int level,-		unsigned char nosplittitle );+int  title_process( fields *info, char *tag, char *data, int level, unsigned char nosplittitle );+void title_combine( str *fullttl, str *mainttl, str *subttl );  #endif
bibutils/unicode.c view
@@ -317,13 +317,13 @@ }  unsigned short-unicode_utf8_classify_newstr( newstr *s )+unicode_utf8_classify_str( str *s ) { 	unsigned int unicode_character, pos = 0; 	unsigned short value = 0; 	int n; 	while ( pos < s->len ) {-		unicode_character = utf8_decode( s->data, &pos );+		unicode_character = utf8_decode( str_cstr( s ), &pos ); 		n = unicode_find( unicode_character ); 		if ( n==-1 ) value |= UNICODE_SYMBOL; 		else value |= unicodeinfo[n].info;
bibutils/unicode.h view
@@ -1,14 +1,14 @@ /*  * unicode.h  *- * Copyright (c) Chris Putnam 2004-2013+ * Copyright (c) Chris Putnam 2004-2017  *  * Program and source code released under the GPL version 2  */ #ifndef UNICODE_H #define UNICODE_H -#include "newstr.h"+#include "str.h"  #define UNICODE_SYMBOL    (1) #define UNICODE_UPPER     (2) /* Uppercase letter */@@ -17,6 +17,6 @@ #define UNICODE_MIXEDCASE ( UNICODE_UPPER | UNICODE_LOWER )  extern unsigned short unicode_utf8_classify( char *p );-extern unsigned short unicode_utf8_classify_newstr( newstr *s );+extern unsigned short unicode_utf8_classify_str( str *s );  #endif
+ bibutils/url.c view
@@ -0,0 +1,313 @@+/*+ * url.c+ *+ * doi_to_url()+ * Handle outputing DOI as a URL (Endnote and RIS formats)+ *     1) Append https://doi.org as necessary+ *     2) Check for overlap with pre-existing URL for the DOI+ *+ * is_doi()+ * Check for DOI buried in another field.+ *+ * Copyright (c) Chris Putnam 2008-2017+ *+ * Source code released under the GPL version 2+ *+ */+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <ctype.h>+#include "bibutils.h"+#include "url.h"++static void+construct_url( char *prefix, str *id, str *id_url, char sep )+{+	if ( !strncasecmp( str_cstr( id ), "http:", 5 ) )+		str_strcpy( id_url, id );+	else {+		str_strcpyc( id_url, prefix );+		if ( sep!='\0' ) {+			if ( id->data[0]!=sep ) str_addchar( id_url, sep );+		}+		str_strcat( id_url, id );+	}+}++static int+url_exists( fields *f, char *urltag, str *doi_url )+{+	int i, n;+	if ( urltag ) {+		n = fields_num( f );+		for ( i=0; i<n; ++i ) {+			if ( strcmp( fields_tag( f, i, FIELDS_CHRP ), urltag ) ) continue;+			if ( strcmp( fields_value( f, i, FIELDS_CHRP ), str_cstr( doi_url ) ) ) continue;+			return 1;+		}+	}+	return 0;+}++static void+xxx_to_url( fields *f, int n, char *http_prefix, char *urltag, str *xxx_url, char sep )+{+	str_empty( xxx_url );+	construct_url( http_prefix, fields_value( f, n, FIELDS_STRP ), xxx_url, sep );+	if ( url_exists( f, urltag, xxx_url ) )+		str_empty( xxx_url );+}+void+doi_to_url( fields *f, int n, char *urltag, str *url )+{+	xxx_to_url( f, n, "https://doi.org", urltag, url, '/' );+}+void+jstor_to_url( fields *f, int n, char *urltag, str *url )+{+	xxx_to_url( f, n, "http://www.jstor.org/stable", urltag, url, '/' );+}+void+pmid_to_url( fields *f, int n, char *urltag, str *url )+{+	xxx_to_url( f, n, "http://www.ncbi.nlm.nih.gov/pubmed", urltag, url, '/' );+}+void+pmc_to_url( fields *f, int n, char *urltag, str *url )+{+	xxx_to_url( f, n, "http://www.ncbi.nlm.nih.gov/pmc/articles", urltag, url, '/' );+}+void+arxiv_to_url( fields *f, int n, char *urltag, str *url )+{+	xxx_to_url( f, n, "http://arxiv.org/abs", urltag, url, '/' );+}+void+mrnumber_to_url( fields *f, int n, char *urltag, str *url )+{+	xxx_to_url( f, n, "http://www.ams.org/mathscinet-getitem?mr=", urltag, url, '\0' );+}++/* Rules for the pattern:+ *   '#' = number+ *   isalpha() = match precisely (matchcase==1) or match regardless of case+ *   	(matchcase==0)+ *   all others must match precisely+ */+static int+string_pattern( char *s, char *pattern, int matchcase )+{+	int patlen, match, i;+	patlen = strlen( pattern );+	if ( strlen( s ) < patlen ) return 0; /* too short */+	for ( i=0; i<patlen; ++i ) {+		match = 0;+		if ( pattern[i]=='#' ) {+			if ( isdigit( (unsigned char)s[i] ) ) match = 1;+		} else if ( !matchcase && isalpha( (unsigned char)pattern[i] ) ) {+			if ( tolower((unsigned char)pattern[i])==tolower((unsigned char)s[i])) match = 1;+		} else {+			if ( pattern[i] == s[i] ) match = 1;+		}+		if ( !match ) return 0;+	}+	return 1;+}++/* science direct is now doing "M3  - doi: DOI: 10.xxxx/xxxxx" */+int+is_doi( char *s )+{+	if ( string_pattern( s, "##.####/", 0 ) ) return 0;+	if ( string_pattern( s, "doi:##.####/", 0 ) ) return 4;+	if ( string_pattern( s, "doi: ##.####/", 0 ) ) return 5;+	if ( string_pattern( s, "doi: DOI: ##.####/", 0 ) ) return 10;+	return -1;+}++/* determine if string has the header of a Universal Resource Identifier+ *+ * returns -1, if not true+ * returns offset that skips over the URI scheme, if true+ */+int+is_uri_remote_scheme( char *p )+{+	char *scheme[]   = { "http:", "https:", "ftp:", "git:", "gopher:" };+	int  schemelen[] = { 5,       6,        4,      4,      7         };+        int i, nschemes = sizeof( scheme ) / sizeof( scheme[0] );+        for ( i=0; i<nschemes; ++i ) {+                if ( !strncasecmp( p, scheme[i], schemelen[i] ) ) return schemelen[i];+        }+        return -1;+}++int+is_reference_database( char *p )+{+	char *scheme[]   = { "arXiv:", "pubmed:", "medline:", "isi:" };+	int  schemelen[] = { 6,        7,         8,          4      };+        int i, nschemes = sizeof( scheme ) / sizeof( scheme[0] );+        for ( i=0; i<nschemes; ++i ) {+                if ( !strncasecmp( p, scheme[i], schemelen[i] ) ) return schemelen[i];+        }+        return -1;+}++/* many fields have been abused to embed URLs, DOIs, etc. */+int+is_embedded_link( char *s )+{+	if ( is_uri_remote_scheme( s )  != -1 ) return 1;+	if ( is_reference_database( s ) != -1 ) return 1;+	if ( is_doi( s ) !=-1 ) return 1;+	return 0;+}++typedef struct url_t {+	char *tag;+	char *prefix;+	int offset;+} url_t;++static url_t prefixes[] = {+	/*              00000000001111111112222222222333333333344444444445 */+	/*              12345678901234567890123456789012345678901234567890 */+	{ "ARXIV",     "http://arxiv.org/abs/",                     21 },+	{ "DOI",       "https://doi.org/",                          16 },+	{ "JSTOR",     "http://www.jstor.org/stable/",              28 },+	{ "MRNUMBER",  "http://www.ams.org/mathscinet-getitem?mr=", 41 },+	{ "PMID",      "http://www.ncbi.nlm.nih.gov/pubmed/",       35 },+	{ "PMC",       "http://www.ncbi.nlm.nih.gov/pmc/articles/", 41 },+	{ "ISIREFNUM", "isi:",                                       4 },+};+static int nprefixes = sizeof( prefixes ) / sizeof( prefixes[0] );++/* do not add, but recognize */+static url_t extraprefixes[] = {+	/*              00000000001111111112222222222333333333344444444445 */+	/*              12345678901234567890123456789012345678901234567890 */+	{ "ARXIV",     "arXiv:",                                     6 },+	{ "DOI",       "http://dx.doi.org/",                        18 },+	{ "JSTOR",     "jstor:",                                     6 },+	{ "PMID",      "pmid:",                                      5 },+	{ "PMID",      "pubmed:",                                    7 },+	{ "PMC",       "pmc:",                                       4 },+	{ "URL",       "\\urllink",                                  8 },+	{ "URL",       "\\url",                                      4 },+};+static int nextraprefixes = sizeof( extraprefixes ) / sizeof( extraprefixes[0] );++static int+find_prefix( char *s, url_t *p, int np )+{+	int i;++	for ( i=0; i<np; ++i )+		if ( !strncmp( p[i].prefix, s, p[i].offset ) ) return i;++	return -1;+}++int+urls_split_and_add( char *value_in, fields *out, int lvl_out )+{+	int n, fstatus, status = BIBL_OK;+	char *tag = "URL";+	int offset = 0;++	n = find_prefix( value_in, prefixes, nprefixes );+	if ( n!=-1 ) {+		tag    = prefixes[n].tag;+		offset = prefixes[n].offset;+	} else {+		n = find_prefix( value_in, extraprefixes, nextraprefixes );+		if ( n!=-1 ) {+			tag    = extraprefixes[n].tag;+			offset = extraprefixes[n].offset;+		}+	}++	fstatus = fields_add( out, tag, &(value_in[offset]), lvl_out );+	if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;++	return status;+}++/* urls_add_type()+ *+ * Append urls of a specific type with a specific prefix (which can be empty).+ * We don't allow duplications here.+ *+ */+static int+urls_merge_and_add_type( fields *out, char *tag_out, int lvl_out, char *prefix, vplist *values )+{+	int fstatus, status = BIBL_OK;+	vplist_index i;+	str url;++	str_init( &url );++	for ( i=0; i<values->n; ++i ) {+		str_strcpyc( &url, prefix );+		str_strcatc( &url, ( char * ) vplist_get( values, i ) );+		fstatus = fields_add( out, tag_out, str_cstr( &url ), lvl_out );+		if ( fstatus!=FIELDS_OK ) {+			status = BIBL_ERR_MEMERR;+			goto out;+		}++	}+out:+	str_free( &url );+	return status;+}++/*+ * urls_merge_and_add()+ *+ * Append urls of types controlled by the list type and automatically append appropriate+ * prefixes. If no prefix is found for the entry, don't add one (e.g. "URL" entries).+ *+ * Control of the types to be added by list type is necessary as some reference formats+ * like bibtex ought to do special things with DOI, ARXIV, MRNUMBER, and the like.+ */+int+urls_merge_and_add( fields *in, int lvl_in, fields *out, char *tag_out, int lvl_out, slist *types )+{+	int i, j, status = BIBL_OK;+	char *tag, *prefix, *empty="";+	vplist a;++	vplist_init( &a );++	for ( i=0; i<types->n; ++i ) {++		tag = slist_cstr( types, i );++		/* ...look for data of requested type; if not found skip */+		vplist_empty( &a );+		fields_findv_each( in, lvl_in, FIELDS_CHRP, &a, tag );+		if ( a.n==0 ) continue;++		/* ...find the prefix (if present) */+		prefix = empty;+		for ( j=0; j<nprefixes; ++j ) {+			if ( !strcmp( prefixes[j].tag, tag ) ) {+				prefix = prefixes[j].prefix;+				break; /* take the first prefix in the list */+			}+		}++		/* ...append all data of this type */+		status = urls_merge_and_add_type( out, tag_out, lvl_out, prefix, &a );+		if ( status!=BIBL_OK ) goto out;+	}++out:+	vplist_free( &a );++	return status;+}
+ bibutils/url.h view
@@ -0,0 +1,30 @@+/*+ * url.h+ *+ * Copyright (c) Chris Putnam 2004-2017+ *+ * Source code released under the GPL version 2+ *+ */+#ifndef URL_H+#define URL_H++#include "slist.h"+#include "fields.h"++int is_doi( char *s );+int is_uri_remote_scheme( char *p );+int is_embedded_link( char *s );++void doi_to_url( fields *info, int n, char *urltag, str *doi_url );+void pmid_to_url( fields *info, int n, char *urltag, str *pmid_url );+void pmc_to_url( fields *info, int n, char *urltag, str *pmid_url );+void arxiv_to_url( fields *info, int n, char *urltag, str *arxiv_url );+void jstor_to_url( fields *info, int n, char *urltag, str *jstor_url );+void mrnumber_to_url( fields *info, int n, char *urltag, str *jstor_url );++int urls_merge_and_add( fields *in, int lvl_in, fields *out, char *tag_out, int lvl_out, slist *types );+int urls_split_and_add( char *value_in, fields *out, int lvl_out );+++#endif
bibutils/utf8.c view
@@ -1,12 +1,13 @@ /*  * utf8.c  *- * Copyright (c) Chris Putnam 2004-2013+ * Copyright (c) Chris Putnam 2004-2017  *  * Source code released under the GPL version 2  *  */ #include <stdio.h>+#include <string.h> #include "utf8.h"  /* UTF-8 encoding@@ -146,5 +147,42 @@ 	nc = utf8_encode( 0xFEFF, code ); 	for ( i=0; i<nc; ++i ) 		fprintf(outptr,"%c",code[i]);+}++int+utf8_is_bom( char *p )+{+	unsigned char *up = ( unsigned char * ) p;++	/* ...if null-terminated string is too short, we're ok */+	if ( up[0]!=0xEF ) return 0;+	if ( up[1]!=0xBB ) return 0;+	if ( up[2]!=0xBF ) return 0;++	return 1;+}++/* utf8_is_emdash()+ *+ *emdash = 0xE2 (-30) 0x80 (-128) 0x94 (-108)+ */+int+utf8_is_emdash( char *p )+{+	const char emdash[3] = { -30, -128, -108 };+	if ( strncmp( p, emdash, 3 ) ) return 0;+	return 1;+}++/* utf8_is_endash()+ *+ * endash = 0xE2 (-30) 0x80 (-128) 0x93 (-109)+ */+int+utf8_is_endash( char *p )+{+	const char endash[3] = { -30, -128, -109 };+	if ( strncmp( p, endash, 3 ) ) return 0;+	return 1; } 
bibutils/utf8.h view
@@ -1,7 +1,7 @@ /*  * utf8.h  *- * Copyright (c) Chris Putnam 2004-2013+ * Copyright (c) Chris Putnam 2004-2017  *  * Source code released under the GPL version 2  *@@ -11,10 +11,12 @@  #include <stdio.h> -extern int utf8_encode( unsigned int value, unsigned char out[6] );-extern void utf8_encode_str( unsigned int value, char outstr[7] );-extern unsigned int utf8_decode( char *s, unsigned int *pi );-extern void utf8_writebom( FILE *outptr );-+int          utf8_encode( unsigned int value, unsigned char out[6] );+void         utf8_encode_str( unsigned int value, char outstr[7] );+unsigned int utf8_decode( char *s, unsigned int *pi );+void         utf8_writebom( FILE *outptr );+int          utf8_is_bom( char *p );+int          utf8_is_emdash( char *p );+int          utf8_is_endash( char *p );  #endif
bibutils/vplist.c view
@@ -1,9 +1,9 @@ /*  * vplist.c  *- * Version: 4/08/2013+ * Version: 1/9/2017  *- * Copyright (c) Chris Putnam 2011-2013+ * Copyright (c) Chris Putnam 2011-2017  *  * Source code released under the GPL version 2  *@@ -11,9 +11,19 @@  *  */ #include <stdlib.h>-#include <assert.h> #include "vplist.h" +/* Do not use asserts in VPLIST_NOASSERT defined */+#ifdef VPLIST_NOASSERT+#define NDEBUG+#endif+#include <assert.h>++#define VPLIST_MINALLOC (20)++#define VPLIST_EXACT_SIZE  (0)+#define VPLIST_DOUBLE_SIZE (1)+ void vplist_init( vplist *vpl ) {@@ -31,186 +41,347 @@ 	return vpl; } -int-vplist_find( vplist *vpl, void *v )+static inline int+vplist_alloc( vplist *vpl, vplist_index alloc ) {-	int i;-	assert( vpl );-	for ( i=0; i<vpl->n; ++i )-		if ( vpl->data[i]==v ) return i;-	return -1;+	vpl->data = ( void ** ) malloc( sizeof( void * ) * alloc );+	if ( !vpl->data ) return VPLIST_MEMERR;++	vpl->max = alloc;+	vpl->n = 0;++	return VPLIST_OK; } -int-vplist_copy( vplist *to, vplist *from )+static inline int+vplist_realloc( vplist *vpl, vplist_index alloc ) {-	int i;-	assert( to );-	assert( from );-	if ( from->n > to->max ) {-		if ( to->max ) free( to->data );-		to->data = ( void ** ) malloc( sizeof( void * ) * from->n );-		if ( !to->data ) return 0;-		to->max = from->n;+	void **more;++	more = ( void ** ) realloc( vpl->data, sizeof( void * ) * alloc );+	if ( !more ) return VPLIST_MEMERR;++	vpl->data = more;+	vpl->max  = alloc;++	return VPLIST_OK;+}++/* vplist_ensure_space( vpl, n, mode )+ *+ *    Makes sure that vplist can hold at least n members, allocating memory if required.+ *+ *    mode+ *       - Can either be VPLIST_DOUBLE_SIZE or VPLIST_EXACT_SIZE.+ *       - If VPLIST_EXACT_SIZE and current size < n, size will be exactly n.+ *       - If VPLIST_DOUBLE_SIZE and current size < n, size will be doubled (or VPLIST_MINALLOC + *         if the vplist is empty) or n, whichever is bigger.+ *+ *    Returns VPLIST_OK or VPLIST_MEMERR.+ */+static int+vplist_ensure_space( vplist *vpl, vplist_index n, unsigned char mode )+{+	vplist_index alloc = n;+	int status = VPLIST_OK;++	if ( vpl->max == 0 ) {+		if ( mode == VPLIST_DOUBLE_SIZE && alloc < VPLIST_MINALLOC ) alloc = VPLIST_MINALLOC;+		status = vplist_alloc( vpl, alloc ); 	}-	for ( i=0; i<from->n; ++i )-		to->data[i] = from->data[i];-	to->n = from->n;-	return 1;++	else if ( vpl->max < n ) {+		if ( mode == VPLIST_DOUBLE_SIZE && alloc < 2 * vpl->max ) alloc = 2 * vpl->max;+		status = vplist_realloc( vpl, alloc );+	}++	return status; }  int-vplist_append( vplist *to, vplist *from )+vplist_copy( vplist *to, vplist *from ) {-	int i, ok;+	vplist_index i;+	int status;+ 	assert( to ); 	assert( from );-	for ( i=0; i<from->n; ++i ) {-		ok = vplist_add( to, from->data[i] );-		if ( !ok ) return 0;++	status = vplist_ensure_space( to, from->n, VPLIST_EXACT_SIZE );++	if ( status == VPLIST_OK ) {++		for ( i=0; i<from->n; ++i )+			to->data[i] = from->data[i];+		to->n = from->n;+ 	}-	return 1;-} -static int-vplist_validindex( vplist *vpl, int n )-{-	if ( n < 0 || n >= vpl->n ) return 0;-	return 1;+	return status; } -static int-vplist_alloc( vplist *vpl )+int+vplist_fill( vplist *vpl, vplist_index n, void *v ) {-	int alloc = 20;-	vpl->data = ( void ** ) malloc( sizeof( void * ) * alloc );-	if ( !vpl->data ) return 0;-	vpl->max = alloc;-	vpl->n = 0;-	return 1;-}+	vplist_index i;+	int status; -static int-vplist_realloc( vplist *vpl )-{-	void **more;-	int alloc = vpl->max * 2;-	more = ( void ** ) realloc( vpl->data, sizeof( void * ) * alloc );-	if ( !more ) return 0;-	vpl->data = more;-	vpl->max = alloc;-	return 1;+	assert( vpl );++	status = vplist_ensure_space( vpl, n, VPLIST_EXACT_SIZE );++	if ( status == VPLIST_OK ) {++		for ( i=0; i<n; ++i )+			vpl->data[i] = v;+		vpl->n = n;++	}++	return status; }  int vplist_add( vplist *vpl, void *v ) {-	int ok = 1;+	int status;  	assert( vpl ); -	/* ensure sufficient space */-	if ( vpl->max==0 ) ok = vplist_alloc( vpl );-	else if ( vpl->n >= vpl->max ) ok = vplist_realloc( vpl );+	status = vplist_ensure_space( vpl, vpl->n + 1, VPLIST_DOUBLE_SIZE ); -	if ( ok ) {+	if ( status == VPLIST_OK ) {+ 		vpl->data[vpl->n] = v; 		vpl->n++;+ 	} -	return ok;+	return status; } -void *-vplist_get( vplist *vpl, int n )+int+vplist_insert_list( vplist *vpl, vplist_index pos, vplist *add ) {+	vplist_index i;+	int status;+ 	assert( vpl );-	if ( !vplist_validindex( vpl, n ) ) return NULL;-	return vpl->data[ n ];+	assert( add );+	assert( pos <= vpl->n );++	/* nothing to do here */+	if ( add->n < 1 ) return VPLIST_OK;++	status = vplist_ensure_space( vpl, vpl->n + add->n, VPLIST_DOUBLE_SIZE );++	if ( status == VPLIST_OK ) {++		for ( i=vpl->n-1; i>=pos; --i )+			vpl->data[i+add->n] = vpl->data[i];++		for ( i=0; i<add->n; ++i )+			vpl->data[pos+i] = add->data[i];++		vpl->n += add->n;+	}++	return status; } -void-vplist_set( vplist *vpl, int n, void *v )+int+vplist_append( vplist *vpl, vplist *add ) {+	vplist_index i;+	int status;+ 	assert( vpl );-	if ( !vplist_validindex( vpl, n ) ) return;-	vpl->data[ n ] = v;+	assert( add );++	status = vplist_ensure_space( vpl, vpl->n + add->n, VPLIST_DOUBLE_SIZE );++	if ( status == VPLIST_OK ) {++		for ( i=0; i<add->n; ++i )+			vpl->data[ vpl->n + i ] = add->data[i];++		vpl->n += add->n;++	}++	return status; } +static void+vplist_freemembers( vplist *vpl, vplist_ptrfree vpf )+{+	vplist_index i;+	void *v;+	for ( i=0; i<vpl->n; ++i ) {+		v = vplist_get( vpl, i );+		if ( v ) (*vpf)( v );+	}+}+ void-vplist_remove( vplist *vpl, int n )+vplist_emptyfn( vplist *vpl, vplist_ptrfree vpf ) {-	int i; 	assert( vpl );-	if ( !vplist_validindex( vpl, n ) ) return;-	for ( i=n+1; i<vpl->n; ++i )-		vpl->data[ i-1 ] = vpl->data[ i ];-	vpl->n -= 1;+	if ( vpf ) vplist_freemembers( vpl, vpf );+	vpl->n = 0; }  void-vplist_removevp( vplist *vpl, void *v )+vplist_empty( vplist *vpl ) {-	int n;+	vplist_emptyfn( vpl, NULL );+}++void+vplist_freefn( vplist *vpl, vplist_ptrfree vpf )+{ 	assert( vpl );-	do {-		n = vplist_find( vpl, v );-		if ( n!=-1 ) vplist_remove( vpl, n );-	} while ( n!=-1 );+	if ( vpf ) vplist_freemembers( vpl, vpf );+	if ( vpl->data ) free( vpl->data );+	vplist_init( vpl ); } -static void-vplist_freemembers( vplist *vpl, vplist_ptrfree vpf )+void+vplist_free( vplist *vpl ) {-	int i;-	for ( i=0; i<vpl->n; ++i )-		(*vpf)( vplist_get( vpl, i ) );+	vplist_freefn( vpl, NULL ); }  void-vplist_empty( vplist *vpl )+vplist_deletefn( vplist **vpl, vplist_ptrfree vpf ) {-	assert( vpl );-	vpl->n = 0;+	vplist_freefn( *vpl, vpf );+	free( *vpl );+	*vpl = NULL; }  void-vplist_emptyfn( vplist *vpl, vplist_ptrfree vpf )+vplist_delete( vplist **vpl ) {+	vplist_deletefn( vpl, NULL );+}++static inline int+vplist_validindex( vplist *vpl, vplist_index n )+{+	if ( n < 0 || n >= vpl->n ) return 0;+	return 1;+}++void *+vplist_get( vplist *vpl, vplist_index n )+{ 	assert( vpl );-	vplist_freemembers( vpl, vpf );-	vplist_empty( vpl );+	if ( !vplist_validindex( vpl, n ) ) return NULL;+	return vpl->data[ n ]; }  void-vplist_free( vplist *vpl )+vplist_set( vplist *vpl, vplist_index n, void *v ) { 	assert( vpl );-	if ( vpl->data ) free( vpl->data );-	vplist_init( vpl );+	assert( vplist_validindex( vpl, n ) );+	vpl->data[ n ] = v; } +int+vplist_find( vplist *vpl, void *v )+{+	vplist_index i;+	assert( vpl );+	for ( i=0; i<vpl->n; ++i )+		if ( vpl->data[i]==v ) return i;+	return -1;+}+ void-vplist_freefn( vplist *vpl, vplist_ptrfree vpf )+vplist_swap( vplist *vpl, vplist_index n1, vplist_index n2 ) {+	void *tmp;+ 	assert( vpl );-	vplist_freemembers( vpl, vpf );-	vplist_free( vpl );+	assert( vplist_validindex( vpl, n1 ) );+	assert( vplist_validindex( vpl, n2 ) );++	tmp           = vpl->data[n1];+	vpl->data[n1] = vpl->data[n2];+	vpl->data[n2] = tmp; } +int+vplist_removefn( vplist *vpl, vplist_index n, vplist_ptrfree vpf )+{+	vplist_index i;++	assert( vpl );+	assert( vplist_validindex( vpl, n ) );++	if ( vpf ) (*vpf)( vplist_get( vpl, n ) );++	for ( i=n+1; i<vpl->n; ++i )+		vpl->data[ i-1 ] = vpl->data[ i ];+	vpl->n -= 1;++	return 1;+}++int+vplist_remove( vplist *vpl, vplist_index n )+{+	return vplist_removefn( vpl, n, NULL );+}++int+vplist_removevpfn( vplist *vpl, void *v, vplist_ptrfree vpf )+{+	vplist_index n;+	int count = 0;++	assert( vpl );++	do {+		n = vplist_find( vpl, v );+		if ( vplist_found( vpl, n ) ) {+			vplist_removefn( vpl, n, vpf );+			count++;+		}+	} while ( vplist_found( vpl, n ) );++	return count;+}++int+vplist_removevp( vplist *vpl, void *v )+{+	return vplist_removevpfn( vpl, v, NULL );+}+ void-vplist_destroy( vplist **vpl )+vplist_remove_rangefn( vplist *vpl, vplist_index start, vplist_index endplusone, vplist_ptrfree vpf ) {-	assert( *vpl );-	vplist_free( *vpl );-	free( *vpl );-	*vpl = NULL;+	vplist_index i, n;++	assert( endplusone <= vpl->n );+	assert( endplusone > start );++	n = endplusone - start;+	if ( vpf ) {+		for ( i=start; i<endplusone; ++i )+			(*vpf)( vplist_get( vpl, i ) );+	}+	for ( i=endplusone; i<vpl->n; ++i ) {+		vpl->data[i-n] = vpl->data[i];+	}+	vpl->n -= n; }  void-vplist_destroyfn( vplist **vpl, vplist_ptrfree vpf )+vplist_remove_range( vplist *vpl, vplist_index start, vplist_index endplusone ) {-	assert( *vpl );-	vplist_freemembers( *vpl, vpf );-	vplist_destroy( vpl );+	vplist_remove_rangefn( vpl, start, endplusone, NULL ); }
bibutils/vplist.h view
@@ -1,10 +1,12 @@ /*  * vplist.h  *- * Version: 4/08/2013+ * generic container to hold a list of pointers to void  *- * Copyright (c) Chris Putnam 2011-2013+ * Version: 1/9/2017  *+ * Copyright (c) Chris Putnam 2011-2017+ *  * Source code released under the GPL version 2  *  */@@ -12,25 +14,41 @@ #ifndef VPLIST_H #define VPLIST_H -/* vplist = void pointer list (generic container struct)- */+#define VPLIST_MEMERR (-1)+#define VPLIST_OK     (0)++typedef int vplist_index;+ typedef struct vplist {-	int n, max;+	vplist_index n, max; 	void **data; } vplist; +#define vplist_found( vpl, n ) ( n!=-1 )+#define vplist_notfound( vpl, n ) ( n==-1 )+ typedef void (*vplist_ptrfree)(void*); -extern void     vplist_init( vplist *vpl );-extern vplist * vplist_new( void );-extern int      vplist_add( vplist *vpl, void *v );-extern int      vplist_copy( vplist *to, vplist *from );-extern int      vplist_append( vplist *to, vplist *from );-extern void *   vplist_get( vplist *vpl, int n );-extern void     vplist_set( vplist *vpl, int n, void *v );-extern void     vplist_remove( vplist *vpl, int n );-extern void     vplist_removevp( vplist *vpl, void *v );-extern int      vplist_find( vplist *vpl, void *v );+vplist *     vplist_new( void );++void   vplist_init          ( vplist *vpl );+int    vplist_add           ( vplist *vpl, void *v );+int    vplist_fill          ( vplist *vpl, vplist_index n, void *v );+int    vplist_copy          ( vplist *to,  vplist *from );+int    vplist_append        ( vplist *vpl, vplist *add );+int    vplist_insert_list   ( vplist *vpl, vplist_index pos, vplist *add );+void * vplist_get           ( vplist *vpl, vplist_index n );+void   vplist_set           ( vplist *vpl, vplist_index n, void *v );+void   vplist_swap          ( vplist *vpl, vplist_index n1, vplist_index n2 );+int    vplist_remove        ( vplist *vpl, vplist_index n );+int    vplist_removefn      ( vplist *vpl, vplist_index n, vplist_ptrfree vpf );+int    vplist_removevp      ( vplist *vpl, void *v );+int    vplist_removevpfn    ( vplist *vpl, void *v, vplist_ptrfree vpf );+void   vplist_remove_rangefn( vplist *vpl, vplist_index start, vplist_index endplusone, vplist_ptrfree vpf );+void   vplist_remove_range  ( vplist *vpl, vplist_index start, vplist_index endplusone );++vplist_index vplist_find( vplist *vpl, void *v );+ /*  * vplist_empty does not free space  *@@ -49,20 +67,20 @@  *  * vplist_emptyfn( &vpl, free );  */-extern void   vplist_empty( vplist *vpl );-extern void   vplist_emptyfn( vplist *vpl, vplist_ptrfree fn );+void   vplist_empty  ( vplist *vpl );+void   vplist_emptyfn( vplist *vpl, vplist_ptrfree fn ); /*  * vplist_free frees the space for the data array of void * elements.  *  * if members require their own free calls, then call vplist_freefn()  */-extern void vplist_free( vplist *vpl );-extern void vplist_freefn( vplist *vpl, vplist_ptrfree fn );+void vplist_free  ( vplist *vpl );+void vplist_freefn( vplist *vpl, vplist_ptrfree fn ); /*- * vplist_destroy does vplist_free and deallocates the struct+ * vplist_delete does vplist_free and deallocates the struct  * vplist * and replaces with NULL.  */-extern void vplist_destroy( vplist **vpl );-extern void vplist_destroyfn( vplist **vpl, vplist_ptrfree fn );+void vplist_delete  ( vplist **vpl );+void vplist_deletefn( vplist **vpl, vplist_ptrfree fn );  #endif
bibutils/wordin.c view
@@ -1,7 +1,7 @@ /*  * wordin.c  *- * Copyright (c) Chris Putnam 2010-2013+ * Copyright (c) Chris Putnam 2010-2017  *  * Source code released under the GPL version 2  *@@ -9,13 +9,17 @@ #include <stdio.h> #include <stdlib.h> #include "is_ws.h"-#include "newstr.h"-#include "newstr_conv.h"+#include "str.h"+#include "str_conv.h" #include "fields.h" #include "xml.h" #include "xml_encoding.h"-#include "wordin.h"+#include "bibformats.h" +static int wordin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset );+static int wordin_processf( fields *wordin, char *data, char *filename, long nref, param *p );++ /*****************************************************  PUBLIC: void wordin_initparams() *****************************************************/@@ -43,8 +47,8 @@ 	p->all      = NULL; 	p->nall     = 0; -	list_init( &(p->asis) );-	list_init( &(p->corps) );+	slist_init( &(p->asis) );+	slist_init( &(p->corps) );  	if ( !progname ) p->progname = NULL; 	else p->progname = strdup( progname );@@ -68,35 +72,35 @@ 	return endptr; } -int-wordin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset )+static int+wordin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, str *line, str *reference, int *fcharset ) {-	newstr tmp;+	str tmp; 	char *startptr = NULL, *endptr; 	int haveref = 0, inref = 0, file_charset = CHARSET_UNKNOWN, m, type = 1;-	newstr_init( &tmp );-	while ( !haveref && newstr_fget( fp, buf, bufsize, bufpos, line ) ) {-		if ( line->data ) {+	str_init( &tmp );+	while ( !haveref && str_fget( fp, buf, bufsize, bufpos, line ) ) {+		if ( str_cstr( line ) ) { 			m = xml_getencoding( line ); 			if ( m!=CHARSET_UNKNOWN ) file_charset = m; 		}-		if ( line->data ) {-			startptr = wordin_findstartwrapper( line->data, &type );+		if ( str_cstr( line ) ) {+			startptr = wordin_findstartwrapper( str_cstr( line ), &type ); 		} 		if ( startptr || inref ) {-			if ( inref ) newstr_strcat( &tmp, line->data );+			if ( inref ) str_strcat( &tmp, line ); 			else {-				newstr_strcat( &tmp, startptr );+				str_strcatc( &tmp, startptr ); 				inref = 1; 			}-			endptr = wordin_findendwrapper( tmp.data, type );+			endptr = wordin_findendwrapper( str_cstr( &tmp ), type ); 			if ( endptr ) {-				newstr_segcpy( reference, tmp.data, endptr );+				str_segcpy( reference, str_cstr( &tmp ), endptr ); 				haveref = 1; 			} 		} 	}-	newstr_free( &tmp );+	str_free( &tmp ); 	*fcharset = file_charset; 	return haveref; }@@ -122,13 +126,13 @@  * Returns BIBL_ERR_MEMERR on memory error, BIBL_OK otherwise.  */ static int-wordin_person_last( xml *node, newstr *name )+wordin_person_last( xml *node, str *name ) { 	while ( node && !xml_tagexact( node, "b:Last" ) ) 		node = node->next;-	if ( node && node->value->len ) {-		newstr_strcpy( name, node->value->data );-		if ( newstr_memerr( name ) ) return BIBL_ERR_MEMERR;+	if ( node && str_has_value( node->value ) ) {+		str_strcpyc( name, xml_value( node ) );+		if ( str_memerr( name ) ) return BIBL_ERR_MEMERR; 	} 	return BIBL_OK; }@@ -141,14 +145,14 @@  * Returns BIBL_ERR_MEMERR on memory error, BIBL_OK otherwise  */ static int-wordin_person_first( xml *node, newstr *name )+wordin_person_first( xml *node, str *name ) { 	for ( ; node; node=node->next ) { 		if ( !xml_tagexact( node, "b:First" ) ) continue;-		if ( node->value->len ) {-			if ( name->len ) newstr_addchar( name, '|' );-			newstr_strcat( name, node->value->data );-			if ( newstr_memerr( name ) ) return BIBL_ERR_MEMERR;+		if ( str_has_value( node->value ) ) {+			if ( str_has_value( name ) ) str_addchar( name, '|' );+			str_strcatc( name, xml_value( node ) );+			if ( str_memerr( name ) ) return BIBL_ERR_MEMERR; 		} 	} 	return BIBL_OK;@@ -158,9 +162,9 @@ wordin_person( xml *node, fields *info, char *type ) { 	int status, ret = BIBL_OK;-	newstr name;+	str name; -	newstr_init( &name );+	str_init( &name );  	status = wordin_person_last( node, &name ); 	if ( status!=BIBL_OK ) {@@ -174,10 +178,10 @@ 		goto out; 	} -	status = fields_add( info, type, name.data, 0 );+	status = fields_add( info, type, str_cstr( &name ), 0 ); 	if ( status != FIELDS_OK ) ret = BIBL_ERR_MEMERR; out:-	newstr_free( &name );+	str_free( &name ); 	return ret; } @@ -201,42 +205,42 @@ wordin_pages( xml *node, fields *info ) { 	int i, status, ret = BIBL_OK;-	newstr sp, ep;+	str sp, ep; 	char *p; -	newstrs_init( &sp, &ep, NULL );+	strs_init( &sp, &ep, NULL ); -	p = xml_data( node );+	p = xml_value( node ); 	while ( *p && *p!='-' )-		newstr_addchar( &sp, *p++ );-	if ( newstr_memerr( &sp ) ) {+		str_addchar( &sp, *p++ );+	if ( str_memerr( &sp ) ) { 		ret = BIBL_ERR_MEMERR; 		goto out; 	}  	if ( *p=='-' ) p++; 	while ( *p )-		newstr_addchar( &ep, *p++ );-	if ( newstr_memerr( &ep ) ) {+		str_addchar( &ep, *p++ );+	if ( str_memerr( &ep ) ) { 		ret = BIBL_ERR_MEMERR; 		goto out; 	} -	if ( sp.len ) {-		status = fields_add( info, "PAGESTART", sp.data, 1 );+	if ( str_has_value( &sp ) ) {+		status = fields_add( info, "PAGES:START", str_cstr( &sp ), 1 ); 		if ( status!=FIELDS_OK ) { 			ret = BIBL_ERR_MEMERR; 			goto out; 		} 	} -	if ( ep.len ) {+	if ( str_has_value( &ep ) ) { 		if ( sp.len > ep.len ) { 			for ( i=sp.len-ep.len; i<sp.len; ++i ) 				sp.data[i] = ep.data[i-sp.len+ep.len];-			status = fields_add( info, "PAGEEND", sp.data, 1 );+			status = fields_add( info, "PAGES:STOP", str_cstr( &sp ), 1 ); 		} else-			status = fields_add( info, "PAGEEND", ep.data, 1 );+			status = fields_add( info, "PAGES:STOP", str_cstr( &ep ), 1 ); 		if ( status!=FIELDS_OK ) { 			ret = BIBL_ERR_MEMERR; 			goto out;@@ -244,7 +248,7 @@ 	}  out:-	newstrs_free( &sp, &ep, NULL );+	strs_free( &sp, &ep, NULL ); 	return ret; } @@ -252,28 +256,28 @@ wordin_reference( xml *node, fields *info ) { 	int status, ret = BIBL_OK;-	if ( xml_hasdata( node ) ) {+	if ( xml_hasvalue( node ) ) { 		if ( xml_tagexact( node, "b:Tag" ) ) {-			status = fields_add( info, "REFNUM", xml_data( node ), 0 );+			status = fields_add( info, "REFNUM", xml_value( node ), 0 ); 			if ( status!=FIELDS_OK ) ret = BIBL_ERR_MEMERR; 		} else if ( xml_tagexact( node, "b:SourceType" ) ) { 		} else if ( xml_tagexact( node, "b:City" ) ) {-			status = fields_add( info, "ADDRESS", xml_data( node ), 0 );+			status = fields_add( info, "ADDRESS", xml_value( node ), 0 ); 			if ( status!=FIELDS_OK ) ret = BIBL_ERR_MEMERR; 		} else if ( xml_tagexact( node, "b:Publisher" ) ) {-			status = fields_add( info, "PUBLISHER", xml_data( node ), 0 );+			status = fields_add( info, "PUBLISHER", xml_value( node ), 0 ); 			if ( status!=FIELDS_OK ) ret = BIBL_ERR_MEMERR; 		} else if ( xml_tagexact( node, "b:Title" ) ) {-			status = fields_add( info, "TITLE", xml_data( node ), 0 );+			status = fields_add( info, "TITLE", xml_value( node ), 0 ); 			if ( status!=FIELDS_OK ) ret = BIBL_ERR_MEMERR; 		} else if ( xml_tagexact( node, "b:JournalName" ) ) {-			status = fields_add( info, "TITLE", xml_data( node ), 1 );+			status = fields_add( info, "TITLE", xml_value( node ), 1 ); 			if ( status!=FIELDS_OK ) ret = BIBL_ERR_MEMERR; 		} else if ( xml_tagexact( node, "b:Volume" ) ) {-			status = fields_add( info, "VOLUME", xml_data( node ), 1 );+			status = fields_add( info, "VOLUME", xml_value( node ), 1 ); 			if ( status!=FIELDS_OK ) ret = BIBL_ERR_MEMERR; 		} else if ( xml_tagexact( node, "b:Comments" ) ) {-			status = fields_add( info, "NOTES", xml_data( node ), 0 );+			status = fields_add( info, "NOTES", xml_value( node ), 0 ); 			if ( status!=FIELDS_OK ) ret = BIBL_ERR_MEMERR; 		} else if ( xml_tagexact( node, "b:Pages" ) ) { 			ret = wordin_pages( node, info );@@ -293,14 +297,14 @@ 	int ret = BIBL_OK; 	if ( xml_tagexact( node, "b:Source" ) ) { 		if ( node->down ) ret = wordin_reference( node->down, info );-	} else if ( node->tag->len==0 && node->down ) {+	} else if ( str_is_empty( node->tag ) && node->down ) { 		ret = wordin_assembleref( node->down, info ); 	} 	return ret; } -int-wordin_processf( fields *wordin, char *data, char *filename, long nref )+static int+wordin_processf( fields *wordin, char *data, char *filename, long nref, param *p ) { 	int status, ret = 1; 	xml top;
− bibutils/wordin.h
@@ -1,23 +0,0 @@-/*- * wordin.h- *- * Copyright (c) Chris Putnam 2009-2013- *- * Source code released under the GPL version 2- *- */-#ifndef WORDIN_H-#define WORDIN_H--#include "newstr.h"-#include "fields.h"-#include "reftypes.h"-#include "bibutils.h"--extern int wordin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );-extern int wordin_processf( fields *wordin, char *data, char *filename, long nref );--extern void wordin_initparams( param *p, const char *progname );--#endif-
bibutils/wordout.c view
@@ -3,7 +3,7 @@  *   * (Word 2007 format)  *- * Copyright (c) Chris Putnam 2007-2014+ * Copyright (c) Chris Putnam 2007-2017  *  * Source code released under the GPL version 2  *@@ -11,11 +11,15 @@ #include <stdio.h> #include <stdlib.h> #include <string.h>-#include "newstr.h"+#include "str.h" #include "fields.h" #include "utf8.h"-#include "wordout.h"+#include "bibformats.h" +static void wordout_writeheader( FILE *outptr, param *p );+static void wordout_writefooter( FILE *outptr );+static int  wordout_write( fields *info, FILE *outptr, param *p, unsigned long numrefs );+ void wordout_initparams( param *p, const char *progname ) {@@ -41,8 +45,9 @@ }  typedef struct convert {-	char oldtag[25];-	char newtag[25];+	char *oldtag;+	char *newtag;+	char *prefix; 	int  code; } convert; @@ -102,24 +107,28 @@  * fixed output  */ static void-output_fixed( FILE *outptr, char *tag, char *data, int level )+output_fixed( FILE *outptr, char *tag, char *value, int level ) { 	int i; 	for ( i=0; i<level; ++i ) fprintf( outptr, " " );-	fprintf( outptr, "<%s>%s</%s>\n", tag, data, tag );+	fprintf( outptr, "<%s>%s</%s>\n", tag, value, tag ); }  /* detail output  *  */ static void-output_item( fields *info, FILE *outptr, char *tag, int item, int level )+output_item( fields *info, FILE *outptr, char *tag, char *prefix, int item, int level ) { 	int i; 	if ( item==-1 ) return; 	for ( i=0; i<level; ++i ) fprintf( outptr, " " );-	fprintf( outptr, "<%s>%s</%s>\n", tag, info->data[item].data, tag );-	fields_setused( info, item );+	fprintf( outptr, "<%s>%s%s</%s>\n",+		tag,+		prefix,+		(char*) fields_value( info, item, FIELDS_CHRP ),+		tag+	); }  static void@@ -157,7 +166,7 @@         int i, n;         for ( i=0; i<nc; ++i ) {                 n = fields_find( info, c[i].oldtag, c[i].code );-                if ( n!=-1 ) output_item( info, outptr, c[i].newtag, n, 0 );+                if ( n!=-1 ) output_item( info, outptr, c[i].newtag, c[i].prefix, n, 0 );         }  }@@ -195,11 +204,11 @@ get_type_from_genre( fields *info ) { 	int type = TYPE_UNKNOWN, i, j, level;-	char *genre;+	char *genre, *tag; 	for ( i=0; i<info->n; ++i ) {-		if ( strcasecmp( info->tag[i].data, "GENRE" ) &&-			strcasecmp( info->tag[i].data, "NGENRE" ) ) continue;-		genre = info->data[i].data;+		tag = (char *) fields_tag( info, i, FIELDS_CHRP );+		if ( strcasecmp( tag, "GENRE" ) && strcasecmp( tag, "NGENRE" ) ) continue;+		genre = (char *) fields_value( info, i, FIELDS_CHRP ); 		for ( j=0; j<ngenres; ++j ) { 			if ( !strcasecmp( genres[j].out, genre ) ) 				type = genres[j].value;@@ -220,7 +229,7 @@ 			} 			else if ( !strcasecmp( genre, "conference publication" ) ) { 				if ( level==0 ) type=TYPE_CONFERENCE;-				type = TYPE_PROCEEDINGS;+				else type = TYPE_PROCEEDINGS; 			} 			else if ( !strcasecmp( genre, "thesis" ) ) { 	                        if ( type==TYPE_UNKNOWN ) type=TYPE_THESIS;@@ -240,11 +249,11 @@ get_type_from_resource( fields *info ) { 	int type = TYPE_UNKNOWN, i;-	char *resource;+	char *tag, *resource; 	for ( i=0; i<info->n; ++i ) {-		if ( strcasecmp( info->tag[i].data, "GENRE" )!=0 &&-			strcasecmp( info->tag[i].data, "NGENRE" )!=0 ) continue;-		resource = info->data[i].data;+		tag = (char *) fields_tag( info, i, FIELDS_CHRP );+		if ( strcasecmp( tag, "GENRE" ) && strcasecmp( tag, "NGENRE" ) ) continue;+		resource = (char *) fields_value( info, i, FIELDS_CHRP ); 		if ( !strcasecmp( resource, "moving image" ) ) 			type = TYPE_FILM; 	}@@ -262,43 +271,68 @@ }  static void-output_titleinfo( fields *info, FILE *outptr, char *tag, int level )+output_titlebits( char *mainttl, char *subttl, FILE *outptr ) {-	newstr *mainttl = fields_findv( info, level, FIELDS_STRP, "TITLE" );-	newstr *subttl  = fields_findv( info, level, FIELDS_STRP, "SUBTITLE" );+	if ( mainttl ) fprintf( outptr, "%s", mainttl );+	if ( subttl ) {+		if ( mainttl ) {+			if ( mainttl[ strlen( mainttl ) - 1 ] != '?' )+				fprintf( outptr, ": " );+			else fprintf( outptr, " " );+		}+		fprintf( outptr, "%s", subttl );+	}+}++static void+output_titleinfo( char *mainttl, char *subttl, FILE *outptr, char *tag, int level )+{ 	if ( mainttl || subttl ) { 		fprintf( outptr, "<%s>", tag );-		if ( mainttl ) fprintf( outptr, "%s", mainttl->data );-		if ( subttl ) {-			if ( mainttl ) {-				if ( mainttl->len > 0 &&-				     mainttl->data[mainttl->len-1]!='?' )-					fprintf( outptr, ": " );-				else fprintf( outptr, " " );-			}-			fprintf( outptr, "%s", subttl->data );-		}+		output_titlebits( mainttl, subttl, outptr ); 		fprintf( outptr, "</%s>\n", tag ); 	} }  static void-output_title( fields *info, FILE *outptr, int level )+output_generaltitle( fields *info, FILE *outptr, char *tag, int level ) {-	char *ttl    = fields_findv( info, level, FIELDS_CHRP, "TITLE" );-	char *subttl = fields_findv( info, level, FIELDS_CHRP, "SUBTITLE" );-	char *shrttl = fields_findv( info, level, FIELDS_CHRP, "SHORTTITLE" );+	char *ttl       = fields_findv( info, level, FIELDS_CHRP, "TITLE" );+	char *subttl    = fields_findv( info, level, FIELDS_CHRP, "SUBTITLE" );+	char *shrttl    = fields_findv( info, level, FIELDS_CHRP, "SHORTTITLE" );+	char *shrsubttl = fields_findv( info, level, FIELDS_CHRP, "SHORTSUBTITLE" ); -	output_titleinfo( info, outptr, "b:Title", level );+	if ( ttl ) {+		output_titleinfo( ttl, subttl, outptr, tag, level );+	}+	else if ( shrttl ) {+		output_titleinfo( shrttl, shrsubttl, outptr, tag, level );+	}+} -	/* output shorttitle if it's different from normal title */-	if ( shrttl ) {-		if ( !ttl || ( strcmp( shrttl, ttl ) || subttl ) ) {-			fprintf( outptr,  " <b:ShortTitle>" );-			fprintf( outptr, "%s", shrttl );-			fprintf( outptr, "</b:ShortTitle>\n" );+static void+output_maintitle( fields *info, FILE *outptr, int level )+{+	char *ttl       = fields_findv( info, level, FIELDS_CHRP, "TITLE" );+	char *subttl    = fields_findv( info, level, FIELDS_CHRP, "SUBTITLE" );+	char *shrttl    = fields_findv( info, level, FIELDS_CHRP, "SHORTTITLE" );+	char *shrsubttl = fields_findv( info, level, FIELDS_CHRP, "SHORTSUBTITLE" );++	if ( ttl ) {+		output_titleinfo( ttl, subttl, outptr, "b:Title", level );++		/* output shorttitle if it's different from normal title */+		if ( shrttl ) {+			if ( !ttl || ( strcmp( shrttl, ttl ) || subttl ) ) {+				fprintf( outptr,  " <b:ShortTitle>" );+				output_titlebits( shrttl, shrsubttl, outptr );+				fprintf( outptr, "</b:ShortTitle>\n" );+			} 		} 	}+	else if ( shrttl ) {+		output_titleinfo( shrttl, shrsubttl, outptr, "b:Title", level );+	} }  static void@@ -312,40 +346,39 @@ static void output_name( FILE *outptr, char *p ) {-	newstr family, part;+	str family, part; 	int n=0, npart=0; -	newstr_init( &family );-	while ( *p && *p!='|' ) newstr_addchar( &family, *p++ );+	str_init( &family );+	while ( *p && *p!='|' ) str_addchar( &family, *p++ ); 	if ( *p=='|' ) p++;-	if ( family.len ) {+	if ( str_has_value( &family ) ) { 		fprintf( outptr, "<b:Person>" );-		fprintf( outptr, "<b:Last>%s</b:Last>",family.data );+		fprintf( outptr, "<b:Last>%s</b:Last>", str_cstr( &family ) ); 		n++; 	}-	newstr_free( &family );+	str_free( &family ); -	newstr_init( &part );+	str_init( &part ); 	while ( *p ) {-		while ( *p && *p!='|' ) newstr_addchar( &part, *p++ );-		if ( part.len ) {+		while ( *p && *p!='|' ) str_addchar( &part, *p++ );+		if ( str_has_value( &part ) ) { 			if ( n==0 ) fprintf( outptr, "<b:Person>" ); 			if ( npart==0 ) -				fprintf( outptr, "<b:First>%s</b:First>",-					part.data );-			else fprintf( outptr, "<b:Middle>%s</b:Middle>",-					part.data );+				fprintf( outptr, "<b:First>%s</b:First>", str_cstr( &part ) );+			else+				fprintf( outptr, "<b:Middle>%s</b:Middle>", str_cstr( &part ) ); 			n++; 			npart++; 		} 		if ( *p=='|' ) { 			p++;-			newstr_empty( &part );+			str_empty( &part ); 		} 	} 	if ( n ) fprintf( outptr, "</b:Person>\n" ); -	newstr_free( &part );+	str_free( &part ); }  @@ -354,12 +387,12 @@ #define NAME_CORP (4)  static int-extract_name_and_info( newstr *outtag, newstr *intag )+extract_name_and_info( str *outtag, str *intag ) { 	int code = NAME;-	newstr_newstrcpy( outtag, intag );-	if ( newstr_findreplace( outtag, ":ASIS", "" ) ) code = NAME_ASIS;-	if ( newstr_findreplace( outtag, ":CORP", "" ) ) code = NAME_CORP;+	str_strcpy( outtag, intag );+	if ( str_findreplace( outtag, ":ASIS", "" ) ) code = NAME_ASIS;+	if ( str_findreplace( outtag, ":CORP", "" ) ) code = NAME_CORP; 	return code; } @@ -367,25 +400,24 @@ output_name_type( fields *info, FILE *outptr, int level,  			char *map[], int nmap, char *tag ) {-	newstr ntag;+	str ntag; 	int i, j, n=0, code, nfields;-	newstr_init( &ntag );+	str_init( &ntag ); 	nfields = fields_num( info ); 	for ( j=0; j<nmap; ++j ) { 		for ( i=0; i<nfields; ++i ) { 			code = extract_name_and_info( &ntag, &(info->tag[i]) );-			if ( strcasecmp( ntag.data, map[j] ) ) continue;+			if ( strcasecmp( str_cstr( &ntag ), map[j] ) ) continue; 			if ( n==0 ) 				fprintf( outptr, "<%s><b:NameList>\n", tag ); 			if ( code != NAME )-				output_name_nomangle( outptr, info->data[i].data );+				output_name_nomangle( outptr, (char *) fields_value( info, i, FIELDS_CHRP ) ); 			else -				output_name( outptr, info->data[i].data );-			fields_setused( info, i );+				output_name( outptr, (char *) fields_value( info, i, FIELDS_CHRP ) ); 			n++; 		} 	}-	newstr_free( &ntag );+	str_free( &ntag ); 	if ( n ) 		fprintf( outptr, "</b:NameList></%s>\n", tag ); }@@ -418,11 +450,11 @@ output_date( fields *info, FILE *outptr, int level ) { 	char *year  = fields_findv_firstof( info, level, FIELDS_CHRP,-			"PARTYEAR", "YEAR", NULL );+			"PARTDATE:YEAR", "DATE:YEAR", NULL ); 	char *month = fields_findv_firstof( info, level, FIELDS_CHRP,-			"PARTMONTH", "MONTH", NULL );+			"PARTDATE:MONTH", "DATE:MONTH", NULL ); 	char *day   = fields_findv_firstof( info, level, FIELDS_CHRP,-			"PARTDAY", "DAY", NULL );+			"PARTDATE:DAY", "DATE:DAY", NULL ); 	if ( year )  output_itemv( outptr, "b:Year", year, 0 ); 	if ( month ) output_itemv( outptr, "b:Month", month, 0 ); 	if ( day )   output_itemv( outptr, "b:Day", day, 0 );@@ -431,8 +463,8 @@ static void output_pages( fields *info, FILE *outptr, int level ) {-	char *sn = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "PAGESTART" );-	char *en = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "PAGEEND" );+	char *sn = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "PAGES:START" );+	char *en = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "PAGES:STOP" ); 	char *ar = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "ARTICLENUMBER" ); 	if ( sn || en ) 		output_range( outptr, "b:Pages", sn, en, level );@@ -444,13 +476,13 @@ output_includedin( fields *info, FILE *outptr, int type ) { 	if ( type==TYPE_JOURNALARTICLE ) {-		output_titleinfo( info, outptr, "b:JournalName", 1 );+		output_generaltitle( info, outptr, "b:JournalName", 1 ); 	} else if ( type==TYPE_ARTICLEINAPERIODICAL ) {-		output_titleinfo( info, outptr, "b:PeriodicalTitle", 1 );+		output_generaltitle( info, outptr, "b:PeriodicalTitle", 1 ); 	} else if ( type==TYPE_BOOKSECTION ) {-		output_titleinfo( info, outptr, "b:ConferenceName", 1 ); /*??*/+		output_generaltitle( info, outptr, "b:ConferenceName", 1 ); /*??*/ 	} else if ( type==TYPE_PROCEEDINGS ) {-		output_titleinfo( info, outptr, "b:ConferenceName", 1 );+		output_generaltitle( info, outptr, "b:ConferenceName", 1 ); 	} } @@ -483,7 +515,7 @@ 			strcasecmp( tag, "DEGREEGRANTOR:ASIS") & 			strcasecmp( tag, "DEGREEGRANTOR:CORP")) 				continue;-		output_item( info, outptr, "b:Institution", i, 0 );+		output_item( info, outptr, "b:Institution", "", i, 0 ); 	} } @@ -534,9 +566,9 @@ static void output_comments( fields *info, FILE *outptr, int level ) {+	vplist_index i; 	vplist notes; 	char *abs;-	int i;  	vplist_init( &notes ); @@ -564,20 +596,26 @@ output_citeparts( fields *info, FILE *outptr, int level, int max, int type ) { 	convert origin[] = {-		{ "ADDRESS",	"b:City",	LEVEL_ANY },-		{ "PUBLISHER",	"b:Publisher",	LEVEL_ANY },-		{ "EDITION",	"b:Edition",	LEVEL_ANY }+		{ "ADDRESS",	"b:City",	"", LEVEL_ANY },+		{ "PUBLISHER",	"b:Publisher",	"", LEVEL_ANY },+		{ "EDITION",	"b:Edition",	"", LEVEL_ANY } 	}; 	int norigin = sizeof( origin ) / sizeof ( convert ); 	 	convert parts[] = {-		{ "VOLUME",          "b:Volume",  LEVEL_ANY },-		{ "SECTION",         "b:Section", LEVEL_ANY },-		{ "ISSUE",           "b:Issue",   LEVEL_ANY },-		{ "NUMBER",          "b:Issue",   LEVEL_ANY },-		{ "PUBLICLAWNUMBER", "b:Volume",  LEVEL_ANY },-		{ "SESSION",         "b:Issue",   LEVEL_ANY },-		{ "URL",             "b:Url",     LEVEL_ANY },+		{ "VOLUME",          "b:Volume",  "", LEVEL_ANY },+		{ "SECTION",         "b:Section", "", LEVEL_ANY },+		{ "ISSUE",           "b:Issue",   "", LEVEL_ANY },+		{ "NUMBER",          "b:Issue",   "", LEVEL_ANY },+		{ "PUBLICLAWNUMBER", "b:Volume",  "", LEVEL_ANY },+		{ "SESSION",         "b:Issue",   "", LEVEL_ANY },+		{ "URL",             "b:Url",     "", LEVEL_ANY },+		{ "JSTOR",           "b:Url",     "http://www.jstor.org/stable/", LEVEL_ANY },+		{ "ARXIV",           "b:Url",     "http://arxiv.org/abs/",        LEVEL_ANY },+		{ "PMID",            "b:Url",     "http://www.ncbi.nlm.nih.gov/pubmed/", LEVEL_ANY },+		{ "PMC",             "b:Url",     "http://www.ncbi.nlm.nih.gov/pmc/articles/", LEVEL_ANY },+		{ "DOI",             "b:Url",     "https://doi.org/", LEVEL_ANY },+		{ "MRNUMBER",        "b:Url",     "http://www.ams.org/mathscinet-getitem?mr=", LEVEL_ANY }, 	}; 	int nparts=sizeof(parts)/sizeof(convert); 	@@ -589,11 +627,11 @@ 	output_list( info, outptr, parts, nparts ); 	output_pages( info, outptr, level ); 	output_names( info, outptr, level, type );-	output_title( info, outptr, 0 );+	output_maintitle( info, outptr, 0 ); 	output_comments( info, outptr, level ); } -void+static int wordout_write( fields *info, FILE *outptr, param *p, unsigned long numrefs ) { 	int max = fields_maxlevel( info );@@ -604,9 +642,11 @@ 	fprintf( outptr, "</b:Source>\n" );  	fflush( outptr );++	return BIBL_OK; } -void+static void wordout_writeheader( FILE *outptr, param *p ) { 	if ( p->utf8bom ) utf8_writebom( outptr );@@ -616,7 +656,7 @@ 		" xmlns=\"http://schemas.openxmlformats.org/officeDocument/2006/bibliography\" >\n"); } -void+static void wordout_writefooter( FILE *outptr ) { 	fprintf(outptr,"</b:Sources>\n");
− bibutils/wordout.h
@@ -1,27 +0,0 @@-/*- * wordout.h- *- * Copyright (c) Chris Putnam 2008-2013- *- * Source code released under the GPL version 2- *- */-#ifndef WORDOUT_H-#define WORDOUT_H--/* format-specific options */-#define WORDOUT_DROPKEY (2)--#include <stdio.h>-#include "bibl.h"-#include "bibutils.h"--extern void wordout_writeheader( FILE *outptr, param *p );-extern void wordout_writefooter( FILE *outptr );-extern void wordout_write( fields *info, FILE *outptr, param *p,-	unsigned long numrefs );-extern void wordout_initparams( param *p, const char *progname );---#endif-
bibutils/xml.c view
@@ -1,7 +1,7 @@ /*  * xml.c  *- * Copyright (c) Chris Putnam 2004-2013+ * Copyright (c) Chris Putnam 2004-2017  *  * Source code released under the GPL version 2  *@@ -11,7 +11,6 @@ #include <string.h> #include "is_ws.h" #include "strsearch.h"-#include "newstr.h" #include "xml.h"  char *xml_pns = NULL;@@ -21,8 +20,8 @@ { 	xml_attrib *a = (xml_attrib *) malloc( sizeof( xml_attrib ) ); 	if ( a ) {-		list_init( &(a->attrib) );-		list_init( &(a->value) );+		slist_init( &(a->attrib) );+		slist_init( &(a->value) ); 	} 	return a; }@@ -30,17 +29,17 @@ static void xmlattrib_add( xml_attrib *a, char *attrib, char *value  ) {-	if ( attrib ) list_addc( &(a->attrib), attrib );-	else list_addc( &(a->attrib), "" );-	if ( value ) list_addc( &(a->value), value );-	else list_addc( &(a->value), "" );+	if ( attrib ) slist_addc( &(a->attrib), attrib );+	else slist_addc( &(a->attrib), "" );+	if ( value ) slist_addc( &(a->value), value );+	else slist_addc( &(a->value), "" ); }  static void xmlattrib_free( xml_attrib *a ) {-	list_free( &(a->attrib) );-	list_free( &(a->value ) );+	slist_free( &(a->attrib) );+	slist_free( &(a->value ) ); }  static xml *@@ -55,11 +54,11 @@ xml_free( xml *x ) { 	if ( x->tag ) {-		newstr_free( x->tag );+		str_free( x->tag ); 		free( x->tag ); 	} 	if ( x->value ) {-		newstr_free( x->value );+		str_free( x->value ); 		free( x->value ); 	} 	if ( x->a ) {@@ -73,8 +72,8 @@ void xml_init( xml *x ) {-	x->tag = newstr_new();-	x->value = newstr_new();+	x->tag = str_new();+	x->value = str_new(); 	x->a = NULL; 	x->down = NULL; 	x->next = NULL;@@ -117,14 +116,14 @@ 	xml_attrib *a = NULL; 	char quote_character = '\"'; 	int inquotes = 0;-	newstr aname, aval;-	newstr_init( &aname );-	newstr_init( &aval );+	str aname, aval;+	str_init( &aname );+	str_init( &aval ); 	while ( *p && !xml_terminator(p,type) ) { 		/* get attribute name */ 		while ( *p==' ' || *p=='\t' ) p++; 		while ( *p && !strchr( "= \t", *p ) && !xml_terminator(p,type)){-			newstr_addchar( &aname, *p );+			str_addchar( &aname, *p ); 			p++; 		} 		while ( *p==' ' || *p=='\t' ) p++;@@ -138,18 +137,18 @@ 		} 		while ( *p && ((!xml_terminator(p,type) && !strchr("= \t", *p ))||inquotes)){ 			if ( *p==quote_character ) inquotes=0;-			else newstr_addchar( &aval, *p );+			else str_addchar( &aval, *p ); 			p++; 		}-		if ( aname.len ) {+		if ( str_has_value( &aname ) ) { 			if ( !a ) a = xmlattrib_new();-			xmlattrib_add( a, aname.data, aval.data );+			xmlattrib_add( a, str_cstr( &aname ), str_cstr( &aval ) ); 		}-		newstr_empty( &aname );-		newstr_empty( &aval );+		str_empty( &aname );+		str_empty( &aval ); 	}-	newstr_free( &aname );-	newstr_free( &aval );+	str_free( &aname );+	str_free( &aval ); 	*ap = a; 	return p; }@@ -164,30 +163,30 @@  * 	XML_OPENCLOSE <A/>  */ static char *-xml_processtag( char *p, newstr *tag, xml_attrib **attrib, int *type )+xml_processtag( char *p, str *tag, xml_attrib **attrib, int *type ) { 	*attrib = NULL; 	if ( *p=='<' ) p++; 	if ( *p=='!' ) {-		while ( *p && *p!='>' ) newstr_addchar( tag, *p++ );+		while ( *p && *p!='>' ) str_addchar( tag, *p++ ); 		*type = XML_COMMENT; 	} else if ( *p=='?' ) { 		*type = XML_DESCRIPTOR; 		p++; /* skip '?' */ 		while ( *p && !strchr( " \t", *p ) && !xml_terminator(p,type) )-			newstr_addchar( tag, *p++ );+			str_addchar( tag, *p++ ); 		if ( *p==' ' || *p=='\t' ) 			p = xml_processattrib( p, attrib, type ); 	} else if ( *p=='/' ) { 		while ( *p && !strchr( " \t", *p ) && !xml_terminator(p,type) )-			newstr_addchar( tag, *p++ );+			str_addchar( tag, *p++ ); 		*type = XML_CLOSE; 		if ( *p==' ' || *p=='\t' )  			p = xml_processattrib( p, attrib, type ); 	} else { 		*type = XML_OPEN; 		while ( *p && !strchr( " \t", *p ) && !xml_terminator(p,type) )-			newstr_addchar( tag, *p++ );+			str_addchar( tag, *p++ ); 		if ( *p==' ' || *p=='\t' )  			p = xml_processattrib( p, attrib, type ); 	}@@ -210,28 +209,28 @@ char * xml_tree( char *p, xml *onode ) {-	newstr tag;+	str tag; 	xml_attrib *attrib; 	int type, is_style = 0; -	newstr_init( &tag );+	str_init( &tag );  	while ( *p ) { 		/* retain white space for <style> tags in endnote xml */-		if ( onode->tag && onode->tag->data && -			!strcasecmp(onode->tag->data,"style") ) is_style=1;+		if ( onode->tag && str_cstr( onode->tag ) &&+			!strcasecmp( str_cstr( onode->tag ),"style") ) is_style=1; 		while ( *p && *p!='<' ) { 			if ( onode->value->len>0 || is_style || !is_ws( *p ) )-				newstr_addchar( onode->value, *p );+				str_addchar( onode->value, *p ); 			p++; 		} 		if ( *p=='<' ) {-			newstr_empty( &tag );+			str_empty( &tag ); 			p = xml_processtag( p, &tag, &attrib, &type ); 			if ( type==XML_OPEN || type==XML_OPENCLOSE || 			     type==XML_DESCRIPTOR ) { 				xml *nnode = xml_new();-				newstr_newstrcpy( nnode->tag, &tag );+				str_strcpy( nnode->tag, &tag ); 				nnode->a = attrib; 				xml_appendnode( onode, nnode ); 				if ( type==XML_OPEN )@@ -243,7 +242,7 @@ 		} 	} out:-	newstr_free( &tag );+	str_free( &tag ); 	return p; } @@ -253,13 +252,13 @@ 	int i,j; 	if ( !x ) return; 	for ( i=0; i<n; ++i ) printf( "    " );-	printf("n=%d tag='%s' value='%s'\n", n, x->tag->data, x->value->data );+	printf("n=%d tag='%s' value='%s'\n", n, str_cstr( x->tag ), str_cstr( x->value ) ); 	if ( x->a ) { 		for ( j=0; j<x->a->value.n; ++j ) { 			for ( i=0; i<n; ++i ) printf( "    " ); 			printf("    attrib='%s' value='%s'\n",-				(x->a)->attrib.str[j].data,-				(x->a)->value.str[j].data );+				slist_cstr( &(x->a)->attrib, j ),+				slist_cstr( &(x->a)->attrib, j ) ); 		} 	} 	if ( x->down ) xml_draw( x->down, n+1 );@@ -269,85 +268,95 @@ char * xml_findstart( char *buffer, char *tag ) {-	newstr starttag;+	str starttag; 	char *p; -	newstr_init( &starttag );-	newstr_addchar( &starttag, '<' );-	newstr_strcat( &starttag, tag );-	newstr_addchar( &starttag, ' ' );-	p = strsearch( buffer, starttag.data );+	str_init( &starttag );+	str_addchar( &starttag, '<' );+	str_strcatc( &starttag, tag );+	str_addchar( &starttag, ' ' );+	p = strsearch( buffer, str_cstr( &starttag ) );  	if ( !p ) { 		starttag.data[ starttag.len-1 ] = '>';-		p = strsearch( buffer, starttag.data );+		p = strsearch( buffer, str_cstr( &starttag ) ); 	} -	newstr_free( &starttag );+	str_free( &starttag ); 	return p; }  char * xml_findend( char *buffer, char *tag ) {-	newstr endtag;+	str endtag; 	char *p; -	newstr_init( &endtag );-	newstr_strcpy( &endtag, "</" );+	str_init( &endtag );+	str_strcpyc( &endtag, "</" ); 	if ( xml_pns ) {-		newstr_strcat( &endtag, xml_pns );-		newstr_addchar( &endtag, ':' );+		str_strcatc( &endtag, xml_pns );+		str_addchar( &endtag, ':' ); 	}-	newstr_strcat( &endtag, tag );-	newstr_addchar( &endtag, '>' );+	str_strcatc( &endtag, tag );+	str_addchar( &endtag, '>' ); -	p = strsearch( buffer, endtag.data );+	p = strsearch( buffer, str_cstr( &endtag ) );  	if ( p && *p ) { 		if ( *p ) p++;  /* skip <random_tag></end> combo */ 		while ( *p && *(p-1)!='>' ) p++; 	} -	newstr_free( &endtag );+	str_free( &endtag ); 	return p; } -int-xml_tagexact( xml *node, char *s )+static int+xml_tagexact_simple( xml* node, char *s ) {-	newstr tag;+	if ( node->tag->len!=strlen( s ) ) return 0;+	if ( strcasecmp( str_cstr( node->tag ), s ) ) return 0;+	return 1;+}+static int+xml_tagexact_pns( xml* node, char *s )+{ 	int found = 0;-	if ( xml_pns ) {-		newstr_init( &tag );-		newstr_strcpy( &tag, xml_pns );-		newstr_addchar( &tag, ':' );-		newstr_strcat( &tag, s );-		if ( node->tag->len==tag.len &&-				!strcasecmp( node->tag->data, tag.data ) )-			found = 1;-		newstr_free( &tag );-	} else {-		if ( node->tag->len==strlen( s ) && -				!strcasecmp( node->tag->data, s ) )-			found = 1;-	}+	str tag;++	str_init( &tag );+	str_strcpyc( &tag, xml_pns );+	str_addchar( &tag, ':' );+	str_strcatc( &tag, s );+	if ( node->tag->len==tag.len &&+			!strcasecmp( str_cstr( node->tag ), str_cstr( &tag ) ) )+		found = 1;+	str_free( &tag );+ 	return found; }+int+xml_tagexact( xml *node, char *s )+{+	if ( xml_pns ) return xml_tagexact_pns( node, s );+	else           return xml_tagexact_simple( node, s );+}  int xml_hasattrib( xml *node, char *attrib, char *value ) { 	xml_attrib *na = node->a;+	char *a, *v; 	int i;  	if ( na ) {  		for ( i=0; i<na->attrib.n; ++i ) {-			if ( !na->attrib.str[i].data || !na->value.str[i].data )-				continue;-			if ( !strcasecmp( na->attrib.str[i].data, attrib ) &&-			     !strcasecmp( na->value.str[i].data, value ) )+			a = slist_cstr( &(na->attrib), i );+			v = slist_cstr( &(na->value),  i );+			if ( !a || !v ) continue;+			if ( !strcasecmp( a, attrib ) && !strcasecmp( v, value ) ) 				return 1; 		} @@ -363,38 +372,43 @@ 	return xml_hasattrib( node, attrib, value ); } -newstr *+str * xml_getattrib( xml *node, char *attrib ) {-	newstr *ns = NULL; 	xml_attrib *na = node->a;-	int i, nattrib;+	str *ns = NULL;+	int i;+ 	if ( na ) {-		nattrib = na->attrib.n;-		for ( i=0; i<nattrib; ++i )-			if ( !strcasecmp( na->attrib.str[i].data, attrib ) )-				ns = &(na->value.str[i]);+		for ( i=0; i<na->attrib.n; ++i )+			if ( !strcasecmp( slist_cstr( &(na->attrib), i ), attrib ) )+				ns = slist_str( &(na->value), i ); 	} 	return ns; }  int-xml_hasdata( xml *node )+xml_hasvalue( xml *node ) {-	if ( node && node->value && node->value->data ) return 1;+	if ( node && node->value && str_cstr( node->value ) ) return 1; 	return 0; }  char *-xml_data( xml *node )+xml_tag( xml *node ) {-	return node->value->data;+	return str_cstr( node->tag ); } +char *+xml_value( xml *node )+{+	return str_cstr( node->value );+}+ int-xml_tagwithdata( xml *node, char *tag )+xml_tagwithvalue( xml *node, char *tag ) {-	if ( !xml_hasdata( node ) ) return 0;+	if ( !xml_hasvalue( node ) ) return 0; 	return xml_tagexact( node, tag ); }-
bibutils/xml.h view
@@ -1,7 +1,7 @@ /*  * xml.h  *- * Copyright (c) Chris Putnam 2004-2013+ * Copyright (c) Chris Putnam 2004-2017  *  * Source code released under the GPL version 2  *@@ -9,36 +9,37 @@ #ifndef XML_H #define XML_H -#include "list.h"-#include "newstr.h"+#include "slist.h"+#include "str.h"  typedef struct xml_attrib {-	list attrib;-	list value;+	slist attrib;+	slist value; } xml_attrib;  typedef struct xml {-	newstr *tag;-	newstr *value;+	str *tag;+	str *value; 	xml_attrib *a; 	struct xml *down; 	struct xml *next; } xml; -extern void xml_init( xml *x );-extern newstr * xml_getattrib( xml *node, char *attrib );-extern char * xml_findstart( char *buffer, char *tag );-extern char * xml_findend( char *buffer, char *tag );-extern int xml_tagexact( xml *node, char *s );-extern int xml_tag_attrib( xml *node, char *s, char *attrib, char *value );-extern int xml_hasattrib( xml *node, char *attrib, char *value );-extern void xml_free( xml *x );-extern char * xml_tree( char *p, xml *onode );-extern int xml_hasdata( xml *node );-extern char * xml_data( xml *node );-extern int xml_tagwithdata( xml *node, char *tag );+void     xml_init        ( xml *x );+void     xml_free        ( xml *x );+str *    xml_getattrib   ( xml *node, char *attrib );+char *   xml_findstart   ( char *buffer, char *tag );+char *   xml_findend     ( char *buffer, char *tag );+int      xml_tagexact    ( xml *node, char *s );+int      xml_tag_attrib  ( xml *node, char *s, char *attrib, char *value );+int      xml_hasattrib   ( xml *node, char *attrib, char *value );+char *   xml_tree        ( char *p, xml *onode );+int      xml_hasvalue    ( xml *node );+char *   xml_value       ( xml *node );+char *   xml_tag         ( xml *node );+int      xml_tagwithvalue( xml *node, char *tag ); -extern char *xml_pns; /* global Namespace */+char *   xml_pns; /* global Namespace */  #endif 
bibutils/xml_encoding.c view
@@ -1,7 +1,7 @@ /*  * xml_getencoding.c  *- * Copyright (c) Chris Putnam 2007-2013+ * Copyright (c) Chris Putnam 2007-2017  *  * Source code released under the GPL version 2  *@@ -10,29 +10,31 @@ #include <stdlib.h> #include <string.h> #include "charsets.h"-#include "newstr.h"-#include "newstr_conv.h"+#include "str.h"+#include "str_conv.h" #include "xml.h" #include "xml_encoding.h"  static int xml_getencodingr( xml *node ) {-	newstr *s; 	int n = CHARSET_UNKNOWN, m;+	str *s;+	char *t;+ 	if ( xml_tagexact( node, "xml" ) ) { 		s = xml_getattrib( node, "encoding" );-		if ( s && s->data ) {-			if ( !strcasecmp( s->data, "UTF-8" ) )+		if ( str_has_value( s ) ) {+			t = str_cstr( s );+			if ( !strcasecmp( t, "UTF-8" ) ) 				n = CHARSET_UNICODE;-			else if ( !strcasecmp( s->data, "UTF8" ) )+			else if ( !strcasecmp( t, "UTF8" ) ) 				n = CHARSET_UNICODE;-			else if ( !strcasecmp( s->data, "GB18030" ) )+			else if ( !strcasecmp( t, "GB18030" ) ) 				n = CHARSET_GB18030;-			else n = charset_find( s->data );+			else n = charset_find( t ); 			if ( n==CHARSET_UNKNOWN ) {-				fprintf( stderr, "Warning: did not recognize "-					"encoding '%s'\n", s->data );+				fprintf( stderr, "Warning: did not recognize encoding '%s'\n", t ); 			} 		} 	}@@ -44,29 +46,31 @@ 		m = xml_getencodingr( node->next ); 		if ( m!=CHARSET_UNKNOWN ) n = m; 	}+ 	return n; }  int-xml_getencoding( newstr *s )+xml_getencoding( str *s ) {-	newstr descriptor;-	xml descriptxml; 	int file_charset = CHARSET_UNKNOWN;+	str descriptor;+	xml descriptxml; 	char *p, *q;-	p = strstr( s->data, "<?xml" );-	if ( !p ) p = strstr( s->data, "<?XML" );++	p = strstr( str_cstr( s ), "<?xml" );+	if ( !p ) p = strstr( str_cstr( s ), "<?XML" ); 	if ( p ) { 		q = strstr( p, "?>" ); 		if ( q ) {-			newstr_init( &descriptor );-			newstr_segcpy( &descriptor, p, q+2 );+			str_init( &descriptor );+			str_segcpy( &descriptor, p, q+2 ); 			xml_init( &descriptxml );-			xml_tree( descriptor.data, &descriptxml );+			xml_tree( str_cstr( &descriptor ), &descriptxml ); 			file_charset = xml_getencodingr( &descriptxml ); 			xml_free( &descriptxml );-			newstr_free( &descriptor );-			newstr_segdel( s, p, q+2 );+			str_free( &descriptor );+			str_segdel( s, p, q+2 ); 		} 	} 	return file_charset;
bibutils/xml_encoding.h view
@@ -1,7 +1,7 @@ /*  * xml_getencoding.h  *- * Copyright (c) Chris Putnam 2007-2013+ * Copyright (c) Chris Putnam 2007-2017  *  * Source code released under the GPL version 2  *@@ -9,6 +9,6 @@ #ifndef XML_GETENCODING_H #define XML_GETENCODING_H -extern int xml_getencoding( newstr *s );+extern int xml_getencoding( str *s );  #endif
hs-bibutils.cabal view
@@ -1,6 +1,6 @@ name:               hs-bibutils-version:            5.5-homepage:           http://istitutocolli.org/repos/hs-bibutils/+version:            6.2+homepage:           https://github.com/wilx/hs-bibutils  synopsis:           Haskell bindings to bibutils, the bibliography                     conversion utilities.@@ -9,15 +9,12 @@                     library that interconverts between various                     bibliography formats using a common MODS-format                     XML intermediate.-		    .+                    .                     hs-bibutils is available under the GNU GPL license. See                     the LICENSE file for details.                     .                     For more details about bibutils, please check:-		    <http://sourceforge.net/p/bibutils/home/Bibutils/>.-                    .-                    The original API documentation is available here:-                    <http://www.scripps.edu/~cdputnam/software/bibutils/library_specs.html>.+                    <http://sourceforge.net/p/bibutils/home/Bibutils/>.                     .                     The package release number refers to the release number of                     the included bibutils library.@@ -26,78 +23,78 @@ license:            GPL license-file:       LICENSE author:             Andrea Rossato-maintainer:         andrea.rossato@unitn.it-cabal-version:      >= 1.4+maintainer:         Václav Haisman <vhaisman@gmail.com>+cabal-version:      >= 1.23 build-type:         Simple extra-source-files:-        bibutils/adsout.c bibutils/adsout.h bibutils/adsout_journals.c-        bibutils/bibcore.c bibutils/bibl.c bibutils/bibl.h-        bibutils/biblatexin.c bibutils/biblatexin.h-        bibutils/bibtexin.c bibutils/bibtexin.h bibutils/bibtexout.c-        bibutils/bibtexout.h bibutils/bibtextypes.c-        bibutils/bibutils.c bibutils/bibutils.h bibutils/bltypes.c-        bibutils/charsets.c bibutils/charsets.h bibutils/copacin.c-        bibutils/copacin.h bibutils/copactypes.c bibutils/doi.c-        bibutils/doi.h bibutils/ebiin.c bibutils/ebiin.h-        bibutils/endin.c bibutils/endin.h bibutils/endout.c-        bibutils/endout.h bibutils/endtypes.c bibutils/endxmlin.c-        bibutils/endxmlin.h bibutils/entities.c bibutils/entities.h+        bibutils/adsout.c bibutils/adsout_journals.c bibutils/bibcore.c+        bibutils/bibformats.h bibutils/biblatexin.c bibutils/bibl.c+        bibutils/bibl.h bibutils/bibtexin.c bibutils/bibtexout.c+        bibutils/bibtextypes.c bibutils/bibutils.c bibutils/bibutils.h+        bibutils/bltypes.c bibutils/charsets.c bibutils/charsets.h+        bibutils/copacin.c bibutils/copactypes.c bibutils/ebiin.c+        bibutils/endin.c bibutils/endout.c bibutils/endtypes.c+        bibutils/endxmlin.c bibutils/entities.c bibutils/entities.h         bibutils/fields.c bibutils/fields.h bibutils/gb18030.c-        bibutils/gb18030.h bibutils/gb18030_enumeration.c-        bibutils/intlist.c bibutils/intlist.h bibutils/is_ws.c-        bibutils/is_ws.h bibutils/isiin.c bibutils/isiin.h-        bibutils/isiout.c bibutils/isiout.h bibutils/isitypes.c+        bibutils/gb18030_enumeration.c bibutils/gb18030.h bibutils/generic.c+        bibutils/generic.h bibutils/intlist.c bibutils/intlist.h+        bibutils/isiin.c bibutils/isiout.c bibutils/isitypes.c         bibutils/iso639_1.c bibutils/iso639_1.h bibutils/iso639_2.c         bibutils/iso639_2.h bibutils/iso639_3.c bibutils/iso639_3.h-        bibutils/latex.c bibutils/latex.h bibutils/list.c-        bibutils/list.h bibutils/marc.c bibutils/marc.h-        bibutils/medin.c bibutils/medin.h bibutils/modsin.c-        bibutils/modsin.h bibutils/modsout.c bibutils/modsout.h-        bibutils/modstypes.c bibutils/modstypes.h bibutils/name.c-        bibutils/name.h bibutils/newstr.c bibutils/newstr.h-        bibutils/newstr_conv.c bibutils/newstr_conv.h-        bibutils/reftypes.c bibutils/reftypes.h bibutils/risin.c-        bibutils/risin.h bibutils/risout.c bibutils/risout.h+        bibutils/is_ws.c bibutils/is_ws.h bibutils/latex.c bibutils/latex.h+        bibutils/marc.c bibutils/marc.h bibutils/medin.c bibutils/modsin.c+        bibutils/modsout.c bibutils/modstypes.c bibutils/modstypes.h+        bibutils/name.c bibutils/name.h bibutils/nbibin.c+        bibutils/nbibtypes.c bibutils/notes.c bibutils/notes.h+        bibutils/pages.c bibutils/pages.h bibutils/reftypes.c+        bibutils/reftypes.h bibutils/risin.c bibutils/risout.c         bibutils/ristypes.c bibutils/serialno.c bibutils/serialno.h-        bibutils/strsearch.c bibutils/strsearch.h bibutils/title.c-        bibutils/title.h bibutils/unicode.c bibutils/unicode.h-        bibutils/utf8.c bibutils/utf8.h bibutils/vplist.c-        bibutils/vplist.h bibutils/wordin.c bibutils/wordin.h-        bibutils/wordout.c bibutils/wordout.h bibutils/xml.c-        bibutils/xml.h bibutils/xml_encoding.c bibutils/xml_encoding.h+        bibutils/slist.c bibutils/slist.h bibutils/str.c bibutils/str_conv.c+        bibutils/str_conv.h bibutils/str.h bibutils/strsearch.c+        bibutils/strsearch.h bibutils/title.c bibutils/title.h+        bibutils/unicode.c bibutils/unicode.h bibutils/url.c bibutils/url.h+        bibutils/utf8.c bibutils/utf8.h bibutils/vplist.c bibutils/vplist.h+        bibutils/wordin.c bibutils/wordout.c bibutils/xml.c+        bibutils/xml_encoding.c bibutils/xml_encoding.h bibutils/xml.h+        README.md ChangeLog.md  library+    default-language: Haskell2010     exposed-modules:  Text.Bibutils     other-modules:     ghc-options:      -funbox-strict-fields -Wall-    ghc-prof-options: -prof -auto-all     hs-source-dirs:   src-    extensions:       ForeignFunctionInterface+    default-extensions:       ForeignFunctionInterface     include-dirs:     bibutils     includes: bibutils.h     c-sources:         cbits/stub.c-        bibutils/adsout.c bibutils/adsout_journals.c-        bibutils/bibcore.c bibutils/bibl.c bibutils/biblatexin.c-        bibutils/bibtexin.c bibutils/bibtexout.c-        bibutils/bibtextypes.c bibutils/bibutils.c bibutils/bltypes.c-        bibutils/charsets.c bibutils/copacin.c bibutils/copactypes.c-        bibutils/doi.c bibutils/ebiin.c bibutils/endin.c+        bibutils/adsout.c bibutils/adsout_journals.c bibutils/bibcore.c+        bibutils/biblatexin.c bibutils/bibl.c bibutils/bibtexin.c+        bibutils/bibtexout.c bibutils/bibtextypes.c bibutils/bibutils.c+        bibutils/bltypes.c bibutils/charsets.c bibutils/copacin.c+        bibutils/copactypes.c bibutils/ebiin.c bibutils/endin.c         bibutils/endout.c bibutils/endtypes.c bibutils/endxmlin.c         bibutils/entities.c bibutils/fields.c bibutils/gb18030.c-        bibutils/intlist.c bibutils/is_ws.c bibutils/isiin.c-        bibutils/isiout.c bibutils/isitypes.c bibutils/iso639_1.c-        bibutils/iso639_2.c bibutils/iso639_3.c bibutils/latex.c-        bibutils/list.c bibutils/marc.c bibutils/medin.c+        bibutils/generic.c bibutils/intlist.c+        bibutils/isiin.c bibutils/isiout.c bibutils/isitypes.c+        bibutils/iso639_1.c bibutils/iso639_2.c bibutils/iso639_3.c+        bibutils/is_ws.c bibutils/latex.c bibutils/marc.c bibutils/medin.c         bibutils/modsin.c bibutils/modsout.c bibutils/modstypes.c-        bibutils/name.c bibutils/newstr.c bibutils/newstr_conv.c-        bibutils/reftypes.c bibutils/risin.c bibutils/risout.c-        bibutils/ristypes.c bibutils/serialno.c bibutils/strsearch.c-        bibutils/title.c bibutils/unicode.c bibutils/utf8.c-        bibutils/vplist.c bibutils/wordin.c bibutils/wordout.c-        bibutils/xml.c bibutils/xml_encoding.c+        bibutils/name.c bibutils/nbibin.c bibutils/nbibtypes.c+        bibutils/notes.c bibutils/pages.c bibutils/reftypes.c+        bibutils/risin.c bibutils/risout.c bibutils/ristypes.c+        bibutils/serialno.c bibutils/slist.c bibutils/str.c+        bibutils/str_conv.c bibutils/strsearch.c bibutils/title.c+        bibutils/unicode.c bibutils/url.c bibutils/utf8.c bibutils/vplist.c+        bibutils/wordin.c bibutils/wordout.c bibutils/xml.c+        bibutils/xml_encoding.c      if impl(ghc >= 6.10)        build-depends: base >= 4, syb     else        build-depends: base >= 3 && < 4++source-repository head+    type:     git+    location: https://github.com/wilx/hs-bibutils
src/Text/Bibutils.hsc view
@@ -5,7 +5,7 @@ -- Copyright   :  (C) 2008 Andrea Rossato -- License     :  BSD3 ----- Maintainer  :  andrea.rossato@unitn.it+-- Maintainer  :  vhaisman@gmail.com -- Stability   :  provisional -- Portability :  portable --@@ -98,7 +98,6 @@     , bibout_uppercase     , bibout_strictkey     , modsout_dropkey-    , wordout_dropkey      -- * Charsets     , Charset@@ -403,19 +402,16 @@  newtype FormatOpt = FormatOpt { unFormatOpt :: CInt } -#include "bibtexout.h"-#include "modsout.h"-#include "wordout.h"+#include "bibutils.h"  #{enum FormatOpt, FormatOpt- , bibout_finalcomma = BIBOUT_FINALCOMMA- , bibout_singledash = BIBOUT_SINGLEDASH- , bibout_whitespace = BIBOUT_WHITESPACE- , bibout_brackets   = BIBOUT_BRACKETS- , bibout_uppercase  = BIBOUT_UPPERCASE- , bibout_strictkey  = BIBOUT_STRICTKEY- , modsout_dropkey   = MODSOUT_DROPKEY- , wordout_dropkey   = WORDOUT_DROPKEY+ , bibout_finalcomma = BIBL_FORMAT_BIBOUT_FINALCOMMA+ , bibout_singledash = BIBL_FORMAT_BIBOUT_SINGLEDASH+ , bibout_whitespace = BIBL_FORMAT_BIBOUT_WHITESPACE+ , bibout_brackets   = BIBL_FORMAT_BIBOUT_BRACKETS+ , bibout_uppercase  = BIBL_FORMAT_BIBOUT_UPPERCASE+ , bibout_strictkey  = BIBL_FORMAT_BIBOUT_STRICTKEY+ , modsout_dropkey   = BIBL_FORMAT_MODSOUT_DROPKEY  }  newtype Status = Status { status :: CInt }