diff --git a/bibutils/adsout.c b/bibutils/adsout.c
--- a/bibutils/adsout.c
+++ b/bibutils/adsout.c
@@ -1,8 +1,8 @@
 /*
  * adsout.c
  *
- * Copyright (c) Richard Mathar 2007-2013
- * Copyright (c) Chris Putnam 2007-2013
+ * Copyright (c) Richard Mathar 2007-2014
+ * Copyright (c) Chris Putnam 2007-2014
  *
  * Program and source code released under the GPL version 2
  *
@@ -29,7 +29,7 @@
 	p->latexout         = 0;
 	p->utf8out          = BIBL_CHARSET_UTF8_DEFAULT;
 	p->utf8bom          = BIBL_CHARSET_BOM_DEFAULT;
-	p->xmlout           = 0;
+	p->xmlout           = BIBL_XMLOUT_FALSE;
 	p->nosplittitle     = 0;
 	p->verbose          = 0;
 	p->addcount         = 0;
diff --git a/bibutils/bibcore.c b/bibutils/bibcore.c
--- a/bibutils/bibcore.c
+++ b/bibutils/bibcore.c
@@ -1,7 +1,7 @@
 /*
  * bibcore.c
  *
- * Copyright (c) Chris Putnam 2005-2013
+ * Copyright (c) Chris Putnam 2005-2014
  *
  * Source code released under the GPL version 2
  *
@@ -88,16 +88,26 @@
 	fflush( fp );
 }
 
-static void
+/* bibl_duplicateparams()
+ *
+ * Returns status of BIBL_OK or BIBL_ERR_MEMERR
+ */
+static int
 bibl_duplicateparams( param *np, param *op )
 {
+	int ok;
 	list_init( &(np->asis) );
 	list_init( &(np->corps) );
-	list_copy( &(np->asis), &(op->asis ) );
-	list_copy( &(np->corps), &(op->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;
 	
 	if ( !op->progname ) np->progname = NULL;
-	else np->progname = strdup( op->progname );
+	else {
+		np->progname = strdup( op->progname );
+		if ( !np->progname ) return BIBL_ERR_MEMERR;
+	}
 
 	np->readformat = op->readformat;
 	np->writeformat = op->writeformat;
@@ -133,78 +143,121 @@
 	np->all = op->all;
 	np->nall = op->nall;
 
+	return BIBL_OK;
 }
 
-static void
+/* bibl_setreadparams()
+ *
+ * Returns status of BIBL_OK or BIBL_ERR_MEMERR
+ */
+static int
 bibl_setreadparams( param *np, param *op )
 {
-	bibl_duplicateparams( np, op );
-	np->utf8out = 1;
-	np->charsetout = BIBL_CHARSET_UNICODE;
-	np->charsetout_src = BIBL_SRC_DEFAULT;
-	np->xmlout = 0;
-	np->latexout = 0;
-	np->writeformat = BIBL_INTERNALOUT;
+	int status;
+	status = bibl_duplicateparams( np, op );
+	if ( status == BIBL_OK ) {
+		np->utf8out        = 1;
+		np->charsetout     = BIBL_CHARSET_UNICODE;
+		np->charsetout_src = BIBL_SRC_DEFAULT;
+		np->xmlout         = BIBL_XMLOUT_FALSE;
+		np->latexout       = 0;
+		np->writeformat    = BIBL_INTERNALOUT;
+	}
+	return status;
 }
 
-static void
+/* bibl_setwriteparams()
+ *
+ * Returns status of BIBL_OK or BIBL_ERR_MEMERR
+ */
+static int
 bibl_setwriteparams( param *np, param *op )
 {
-	bibl_duplicateparams( np, op );
-	np->xmlin = 0;
-	np->latexin = 0;
-	np->utf8in = 1;
-	np->charsetin = BIBL_CHARSET_UNICODE;
-	np->charsetin_src = BIBL_SRC_DEFAULT;
-	np->readformat = BIBL_INTERNALIN;
+	int status;
+	status = bibl_duplicateparams( np, op );
+	if ( status == BIBL_OK ) {
+		np->xmlin         = 0;
+		np->latexin       = 0;
+		np->utf8in        = 1;
+		np->charsetin     = BIBL_CHARSET_UNICODE;
+		np->charsetin_src = BIBL_SRC_DEFAULT;
+		np->readformat    = BIBL_INTERNALIN;
+	}
+	return status;
 }
 
 void
 bibl_freeparams( param *p )
 {
-	list_free( &(p->asis) );
-	list_free( &(p->corps) );
-	if ( p->progname ) free( p->progname );
-}
-
-static void
-bibl_readlist( list *pl, char *progname, char *filename )
-{
-	if ( !list_fill( pl, filename ) ) {
-		fprintf( stderr, "%s: warning problems reading '%s' "
-			"obtained %d elements\n", progname, filename,
-			pl->n );
+	if ( p ) {
+		list_free( &(p->asis) );
+		list_free( &(p->corps) );
+		if ( p->progname ) free( p->progname );
 	}
 }
 
-void
-bibl_readasis( param *p, char *filename )
+int
+bibl_readasis( param *p, char *f )
 {
-	bibl_readlist( &(p->asis), p->progname, filename );
-}
+	int status;
 
-void
-bibl_readcorps( param *p, char *filename )
-{
-	bibl_readlist( &(p->corps), p->progname, filename );
+	if ( !p ) return BIBL_ERR_BADINPUT;
+	if ( !f ) return BIBL_ERR_BADINPUT;
+
+	status = list_fill( &(p->asis), f, 1 );
+
+	if ( status == LIST_ERR_CANNOTOPEN ) return BIBL_ERR_CANTOPEN;
+	else if ( status == 0 ) return BIBL_ERR_MEMERR;
+	return BIBL_OK;
 }
 
-static void
-bibl_addtolist( list *pl, char *entry )
+int
+bibl_readcorps( param *p, char *f )
 {
-	list_add( pl, entry );
+	int status;
+
+	if ( !p ) return BIBL_ERR_BADINPUT;
+	if ( !f ) return BIBL_ERR_BADINPUT;
+
+	status = list_fill( &(p->corps), f, 1 );
+
+	if ( status == LIST_ERR_CANNOTOPEN ) return BIBL_ERR_CANTOPEN;
+	else if ( status == 0 ) return BIBL_ERR_MEMERR;
+	return BIBL_OK;
 }
 
-void
-bibl_addtoasis( param *p, char *entry )
+/* bibl_addtoasis()
+ *
+ * Returns BIBL_OK or BIBL_ERR_MEMERR
+ */
+int
+bibl_addtoasis( param *p, char *d )
 {
-	bibl_addtolist( &(p->asis), entry );
+	newstr *s;
+
+	if ( !p ) return BIBL_ERR_BADINPUT;
+	if ( !d ) return BIBL_ERR_BADINPUT;
+
+	s = list_addc( &(p->asis), d );
+
+	return ( s==NULL )? BIBL_ERR_MEMERR : BIBL_OK;
 }
 
-void
-bibl_addtocorps( param *p, char *entry )
+/* bibl_addtocorps()
+ *
+ * Returns BIBL_OK or BIBL_ERR_MEMERR
+ */
+int
+bibl_addtocorps( param *p, char *d )
 {
-	bibl_addtolist( &(p->corps), entry );
+	newstr *s;
+
+	if ( !p ) return BIBL_ERR_BADINPUT;
+	if ( !d ) return BIBL_ERR_BADINPUT;
+
+	s = list_addc( &(p->corps), d );
+
+	return ( s==NULL )? BIBL_ERR_MEMERR : BIBL_OK;
 }
 
 void
@@ -240,7 +293,7 @@
 	else return 0;
 }
 
-void
+static void
 bibl_verbose2( fields *f, char *filename, long nrefs )
 {
 	int i, n;
@@ -256,7 +309,8 @@
 	fflush( stderr );
 }
 
-void
+#if 0
+static void
 bibl_verbose1( fields *f, fields *orig, char *filename, long nrefs )
 {
 	int i, n;
@@ -270,8 +324,9 @@
 	}
 	if ( f ) bibl_verbose2( f, filename, nrefs );
 }
+#endif
 
-void
+static void
 bibl_verbose0( bibl *bin )
 {
 	int i;
@@ -287,7 +342,7 @@
  * tag = "NGENRE"
  * value = "Masters thesis"
  */
-static void
+static int
 extract_tag_value( newstr *tag, newstr *value, char *p )
 {
 	newstr_empty( tag );
@@ -295,12 +350,18 @@
 		newstr_addchar( tag, *p );
 		p++;
 	}
+	if ( newstr_memerr( tag ) ) return BIBL_ERR_MEMERR;
+
 	if ( p && *p=='|' ) p++;
+
 	newstr_empty( value );
 	while ( p && *p ) {
 		newstr_addchar( value, *p );
 		p++;
 	}
+	if ( newstr_memerr( tag ) ) return BIBL_ERR_MEMERR;
+
+	return BIBL_OK;
 }
 
 /* process_defaultadd()
@@ -312,29 +373,40 @@
 static int
 process_defaultadd( fields *f, int reftype, param *r )
 {
-	int i, n, process, level, ok = 1;
+	int i, n, process, level, status, ret = BIBL_OK;
 	newstr tag, value;
 	char *p;
 
 	newstrs_init( &tag, &value, NULL );
 
 	for ( i=0; i<r->all[reftype].ntags; ++i ) {
+
 		process = ((r->all[reftype]).tags[i]).processingtype;
 		if ( process!=DEFAULT ) continue;
+
 		level   = ((r->all[reftype]).tags[i]).level;
 		p       = ((r->all[reftype]).tags[i]).newstr;
-		extract_tag_value( &tag, &value, p );
+
+		status = extract_tag_value( &tag, &value, p );
+		if ( status!=BIBL_OK ) {
+			ret = status;
+			goto out;
+		}
+
 		n = fields_find( f, tag.data, level );
 		if ( n==-1 ) {
-			ok = fields_add( f, tag.data, value.data, level );
-			if ( !ok ) goto out;
+			status = fields_add( f, tag.data, value.data, level );
+			if ( status!=FIELDS_OK ) {
+				ret = BIBL_ERR_MEMERR;
+				goto out;
+			}
 		}
+
 	}
 out:
 	newstrs_free( &tag, &value, NULL );
 
-	if ( ok ) return BIBL_OK;
-	else return BIBL_ERR_MEMERR;
+	return ret;
 }
 
 /* process_alwaysadd()
@@ -346,27 +418,37 @@
 static int
 process_alwaysadd( fields *f, int reftype, param *r )
 {
-	int i, process, level, ok = 1;
+	int i, process, level, status, ret = BIBL_OK;
 	newstr tag, value;
 	char *p;
 
 	newstrs_init( &tag, &value, NULL );
 
 	for ( i=0; i<r->all[reftype].ntags; ++i ) {
+
 		process = ((r->all[reftype]).tags[i]).processingtype;
 		if ( process!=ALWAYS ) continue;
+
 		level   = ((r->all[reftype]).tags[i]).level;
-		p = ((r->all[reftype]).tags[i]).newstr;
-		extract_tag_value( &tag, &value, p );
-		ok = fields_add( f, tag.data, value.data, level );
-		if ( !ok ) goto out;
+		p       = ((r->all[reftype]).tags[i]).newstr;
+
+		status = extract_tag_value( &tag, &value, p );
+		if ( status!=BIBL_OK ) {
+			ret = status;
+			goto out;
+		}
+
+		status = fields_add( f, tag.data, value.data, level );
+		if ( status!=FIELDS_OK ) {
+			ret = BIBL_ERR_MEMERR;
+			goto out;
+		}
 	}
 
 out:
 	newstrs_free( &tag, &value, NULL );
 
-	if ( ok ) return BIBL_OK;
-	else return BIBL_ERR_MEMERR;
+	return ret;
 }
 
 static int
@@ -384,7 +466,7 @@
 		if ( !ref ) {
 			ret = BIBL_ERR_MEMERR;
 			bibl_free( bin );
-			goto out0;
+			goto out;
 		}
 		if ( p->processf( ref, reference.data, filename, nrefs+1 )){
 			ok = bibl_addref( bin, ref );
@@ -393,7 +475,7 @@
 				bibl_free( bin );
 				fields_free( ref );
 				free( ref );
-				goto out0;
+				goto out;
 			}
 		} else {
 			fields_free( ref );
@@ -411,7 +493,7 @@
 		}
 	}
 	if ( p->charsetin==CHARSET_UNICODE ) p->utf8in = 1;
-out0:
+out:
 	newstr_free( &line );
 	newstr_free( &reference );
 	return ret;
@@ -421,15 +503,19 @@
 static int
 bibl_notexify( char *tag )
 {
-	char *protected[] = { "DOI", "URL", "REFNUM" };
+	char *protected[] = { "DOI", "URL", "REFNUM", "FILEATTACH" };
 	int i, nprotected = sizeof( protected ) / sizeof( protected[0] );
 	for ( i=0; i<nprotected; ++i )
 		if ( !strcasecmp( tag, protected[i] ) ) return 1;
 	return 0;
 }
 
+/* bibl_fixcharsetdata()
+ *
+ * returns BIBL_OK or BIBL_ERR_MEMERR
+ */
 static int
-bibl_fixcharsetfields( fields *ref, param *p )
+bibl_fixcharsetdata( fields *ref, param *p )
 {
 	newstr *data;
 	char *tag;
@@ -453,30 +539,35 @@
 				p->charsetout, p->latexout, p->utf8out, p->xmlout );
 		}
 
-		if ( !ok ) return 0;
+		if ( !ok ) return BIBL_ERR_MEMERR;
 	}
 
-	return 1;
+	return BIBL_OK;
 }
 
+/* bibl_fixcharsets()
+ *
+ * returns BIBL_OK or BIBL_ERR_MEMERR
+ */
 static int
 bibl_fixcharsets( bibl *b, param *p )
 {
+	int status = BIBL_OK;
 	long i;
-	int ok;
-	for ( i=0; i<b->nrefs; ++i ) {
-		ok = bibl_fixcharsetfields( b->ref[i], p );
-		if ( !ok ) return 0;
-	}
-	return 1;
+	for ( i=0; i<b->nrefs && status==BIBL_OK; ++i )
+		status = bibl_fixcharsetdata( b->ref[i], p );
+	return status;
 }
 
 static int
-build_refnum( fields *f, long nrefs )
+build_refnum( fields *f, long nrefs, int *n )
 {
 	char *year, *author, *p, num[512];
+	int status, ret = BIBL_OK;
 	newstr refnum;
 
+	*n = -1;
+
 	newstr_init( &refnum );
 
 	year = fields_findv( f, LEVEL_MAIN, FIELDS_CHRP_NOUSE, "YEAR" );
@@ -500,38 +591,56 @@
 		sprintf( num, "%ld", nrefs );
 		newstr_mergestrs( &refnum, "ref", num, NULL );
 	}
+	if ( newstr_memerr( &refnum ) ) {
+		ret = BIBL_ERR_MEMERR;
+		goto out;
+	}
 
-	fields_add( f, "REFNUM", refnum.data, 0 );
+	status = fields_add( f, "REFNUM", refnum.data, 0 );
+	if ( status!=FIELDS_OK ) ret = BIBL_ERR_MEMERR;
+	else *n = fields_find( f, "REFNUM", 0 );
+
+out:
 	newstr_free( &refnum );
 
-	return fields_find( f, "REFNUM", 0 );
+	return ret;
 }
 
-static void
+static int
 bibl_checkrefid( bibl *b, param *p )
 {
+	char buf[512];
+	int n, status;
 	fields *ref;
 	long i;
-	char buf[512];
-	int n;
+
 	for ( i=0; i<b->nrefs; ++i ) {
 		ref = b->ref[i];
 		n = fields_find( ref, "REFNUM", 0 );
-		if ( n==-1 ) n = build_refnum( ref, i+1 );
+		if ( n==-1 ) {
+			status = build_refnum( ref, i+1, &n );
+			if ( status!=BIBL_OK ) return status;
+		}
 		if ( p->addcount ) {
 			sprintf( buf, "_%ld", i+1 );
 			newstr_strcat( &(ref->data[n]), buf );
+			if ( newstr_memerr( &(ref->data[n]) ) )
+				return BIBL_ERR_MEMERR;
 		}
 	}
+
+	return BIBL_OK;
 }
 
 static int
 generate_citekey( fields *f, int nref )
 {
-	newstr citekey;
-	int n1, n2;
+	int n1, n2, status, ret;
 	char *p, buf[100];
+	newstr citekey;
+
 	newstr_init( &citekey );
+
 	n1 = fields_find( f, "AUTHOR", 0 );
 	if ( n1==-1 ) n1 = fields_find( f, "AUTHOR", -1 );
 	n2 = fields_find( f, "YEAR", 0 );
@@ -549,21 +658,31 @@
 			if ( !is_ws( *p ) ) newstr_addchar( &citekey, *p );
 			p++;
 		}
-		fields_add( f, "REFNUM", citekey.data, 0 );
+		if ( newstr_memerr( &citekey ) ) {
+			ret = -1;
+			goto out;
+		}
+		status = fields_add( f, "REFNUM", citekey.data, 0 );
+		if ( status!=FIELDS_OK ) {
+			ret = -1;
+			goto out;
+		}
 	} else {
 		sprintf( buf, "ref%d\n", nref );
 		newstr_strcpy( &citekey, buf );
 	}
+	ret = fields_find( f, "REFNUM", -1 );
+out:
 	newstr_free( &citekey );
-	return fields_find( f, "REFNUM", -1 );
+	return ret;
 }
 
-static void
+static int
 resolve_citekeys( bibl *b, list *citekeys, int *dup )
 {
-	char abc[]="abcdefghijklmnopqrstuvwxyz";
+	const char abc[]="abcdefghijklmnopqrstuvwxyz";
+	int nsame, ntmp, n, i, j, status = BIBL_OK;
 	newstr tmp;
-	int nsame, ntmp, n, i, j;
 
 	newstr_init( &tmp );
 
@@ -573,6 +692,10 @@
 		for ( j=i; j<citekeys->n; ++j ) {
 			if ( dup[j]!=i ) continue;
 			newstr_newstrcpy( &tmp, &(citekeys->str[j]) );
+			if ( newstr_memerr( &tmp ) ) {
+				status = BIBL_ERR_MEMERR;
+				goto out;
+			}
 			ntmp = nsame;
 			while ( ntmp >= 26 ) {
 				newstr_addchar( &tmp, 'a' );
@@ -580,38 +703,56 @@
 			}
 			if ( ntmp<26 && ntmp>=0 )
 			newstr_addchar( &tmp, abc[ntmp] );
+			if ( newstr_memerr( &tmp ) ) {
+				status = BIBL_ERR_MEMERR;
+				goto out;
+			}
 			nsame++;
 			dup[j] = -1;
 			n = fields_find( b->ref[j], "REFNUM", -1 );
-			if ( n!=-1 )
+			if ( n!=-1 ) {
 				newstr_newstrcpy(&((b->ref[j])->data[n]),&tmp);
+				if ( newstr_memerr( &((b->ref[j])->data[n]) ) ) {
+					status = BIBL_ERR_MEMERR;
+					goto out;
+				}
+			}
 		}
 	}
+out:
 	newstr_free( &tmp );
+	return status;
 }
 
-static void
+static int
 get_citekeys( bibl *b, list *citekeys )
 {
+	newstr *s;
 	fields *f;
 	int i, n;
 	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 )
-			list_add( citekeys, f->data[n].data );
-		else
-			list_add( citekeys, "" );
+		if ( n!=-1 && f->data[n].data ) {
+			s = list_add( citekeys, &(f->data[n]) );
+			if ( !s ) return BIBL_ERR_MEMERR;
+		} else {
+			s = list_addc( citekeys, "" );
+			if ( !s ) return BIBL_ERR_MEMERR;
+		}
 	}
+	return BIBL_OK;
 }
 
 static int 
 dup_citekeys( bibl *b, list *citekeys )
 {
-	int i, j, *dup, ndup=0;
+	int i, j, status = BIBL_OK, *dup, ndup=0;
+
 	dup = ( int * ) malloc( sizeof( int ) * citekeys->n );
-	if ( !dup ) return 0;
+	if ( !dup ) return BIBL_ERR_MEMERR;
+
 	for ( i=0; i<citekeys->n; ++i ) dup[i] = -1;
 	for ( i=0; i<citekeys->n-1; ++i ) {
 		if ( dup[i]!=-1 ) continue;
@@ -624,32 +765,37 @@
 			}
 		}
 	}
-	if ( ndup ) resolve_citekeys( b, citekeys, dup );
+	if ( ndup ) status = resolve_citekeys( b, citekeys, dup );
 	free( dup );
-	return ndup;
+	return status;
 }
 
-static void
+static int
 uniqueify_citekeys( bibl *b )
 {
 	list citekeys;
+	int status;
 	list_init( &citekeys );
-	get_citekeys( b, &citekeys );
-	dup_citekeys( b, &citekeys );
+	status = get_citekeys( b, &citekeys );
+	if ( status!=BIBL_OK ) goto out;
+	status = dup_citekeys( b, &citekeys );
+out:
 	list_free( &citekeys );
+	return status;
 }
 
-static void
+static int
 clean_ref( bibl *bin, param *p )
 {
-	if ( p->cleanf ) p->cleanf( bin, p );
+	if ( p->cleanf ) return p->cleanf( bin, p );
+	else return BIBL_OK;
 }
 
 static int 
 convert_ref( bibl *bin, char *fname, bibl *bout, param *p )
 {
 	fields *rin, *rout;
-	int reftype = 0, ok;
+	int reftype = 0, ok, status;
 	long i;
 
 	for ( i=0; i<bin->nrefs; ++i ) {
@@ -658,37 +804,41 @@
 		if ( !rout ) return BIBL_ERR_MEMERR;
 		if ( p->typef ) 
 			reftype = p->typef( rin, fname, i+1, p, p->all, p->nall );
-		ok = p->convertf( rin, rout, reftype, p, p->all, p->nall );
-		if ( ok!=BIBL_OK ) return ok;
+		status = p->convertf( rin, rout, reftype, p, p->all, p->nall );
+		if ( status!=BIBL_OK ) return status;
 		if ( p->all ) {
-			ok = process_alwaysadd( rout, reftype, p );
-			if ( ok!=BIBL_OK ) return ok;
-			ok = process_defaultadd( rout, reftype, p );
-			if ( ok!=BIBL_OK ) return ok;
+			status = process_alwaysadd( rout, reftype, p );
+			if ( status!=BIBL_OK ) return status;
+			status = process_defaultadd( rout, reftype, p );
+			if ( status!=BIBL_OK ) return status;
 		}
-		bibl_addref( bout, rout );
+		ok = bibl_addref( bout, rout );
+		if ( !ok ) return BIBL_ERR_MEMERR;
 	}
-	uniqueify_citekeys( bout );
-	return BIBL_OK;
+	status = uniqueify_citekeys( bout );
+	return status;
 }
 
 int
 bibl_read( bibl *b, FILE *fp, char *filename, param *p )
 {
-	int ret, ok;
+	int ok, status;
 	param lp;
 	bibl bin;
 
-	if ( !b ) return BIBL_ERR_BADINPUT;
+	if ( !b )  return BIBL_ERR_BADINPUT;
 	if ( !fp ) return BIBL_ERR_BADINPUT;
-	if ( !p ) return BIBL_ERR_BADINPUT;
+	if ( !p )  return BIBL_ERR_BADINPUT;
+
 	if ( bibl_illegalinmode( p->readformat ) ) return BIBL_ERR_BADINPUT;
 
-	bibl_setreadparams( &lp, p );
+	status = bibl_setreadparams( &lp, p );
+	if ( status!=BIBL_OK ) return status;
+
 	bibl_init( &bin );
 
-	ret = read_ref( fp, &bin, filename, &lp );
-	if ( ret!=BIBL_OK ) return ret;
+	status = read_ref( fp, &bin, filename, &lp );
+	if ( status!=BIBL_OK ) return status;
 
 	if ( debug_set( p ) ) {
 		fflush( stdout );
@@ -700,8 +850,8 @@
 	}
 
 	if ( !lp.output_raw || ( lp.output_raw & BIBL_RAW_WITHCHARCONVERT ) ) {
-		ok = bibl_fixcharsets( &bin, &lp );
-		if ( !ok ) return BIBL_ERR_MEMERR;
+		status = bibl_fixcharsets( &bin, &lp );
+		if ( status!=BIBL_OK ) return status;
 		if ( debug_set( p ) ) {
 			fprintf( stderr, "-------------------post_fixcharsets start for bibl_read\n");
 			bibl_verbose0( &bin );
@@ -710,7 +860,8 @@
 		}
 	}
 	if ( !lp.output_raw ) {
-		clean_ref( &bin, &lp );
+		status = clean_ref( &bin, &lp );
+		if ( status!=BIBL_OK ) return status;
 		if ( debug_set( p ) ) {
 			fprintf( stderr, "-------------------post_clean_ref start for bibl_read\n");
 			bibl_verbose0( &bin );
@@ -779,48 +930,53 @@
 }
 
 static int
-output_bibl( FILE *fp, bibl *b, param *p )
+bibl_writeeachfp( FILE *fp, bibl *b, param *p )
 {
 	long i;
-	if ( !p->singlerefperfile && p->headerf ) p->headerf( fp, p );
 	for ( i=0; i<b->nrefs; ++i ) {
-		if ( p->singlerefperfile ) { 
-			fp = singlerefname( b->ref[i], i, p->writeformat );
-			if ( fp ) {
-				if ( p->headerf ) p->headerf( fp, p );
-			} else return BIBL_ERR_CANTOPEN;
-		}
+		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 );
-		if ( p->singlerefperfile ) {
-			if ( p->footerf ) p->footerf( fp );
-			fclose( fp );
-		}
+		if ( p->footerf ) p->footerf( fp );
+		fclose( fp );
 	}
-	if ( !p->singlerefperfile && p->footerf ) p->footerf( fp );
-	return 1;
+	return BIBL_OK;
 }
 
+static int
+bibl_writefp( FILE *fp, bibl *b, param *p )
+{
+	long i;
+	if ( p->headerf ) p->headerf( fp, p );
+	for ( i=0; i<b->nrefs; ++i )
+		p->writef( b->ref[i], fp, p, i );
+	if ( p->footerf ) p->footerf( fp );
+	return BIBL_OK;
+}
+
 int
 bibl_write( bibl *b, FILE *fp, param *p )
 {
+	int status;
 	param lp;
-	int ok;
 
 	if ( !b ) return BIBL_ERR_BADINPUT;
 	if ( !p ) return BIBL_ERR_BADINPUT;
 	if ( bibl_illegaloutmode( p->writeformat ) ) return BIBL_ERR_BADINPUT;
 	if ( !fp && ( !p || !p->singlerefperfile ) ) return BIBL_ERR_BADINPUT;
 
-	bibl_setwriteparams( &lp, p );
+	status = bibl_setwriteparams( &lp, p );
+	if ( status!=BIBL_OK ) return status;
 
-	ok = bibl_fixcharsets( b, &lp );
-	if ( !ok ) return BIBL_ERR_MEMERR;
+	status = bibl_fixcharsets( b, &lp );
+	if ( status!=BIBL_OK ) return status;
 
 	if ( debug_set( p ) ) report_params( stderr, "bibl_write", &lp );
 
-	ok = output_bibl( fp, b, &lp );
-	if ( !ok ) return BIBL_ERR_MEMERR;
+	if ( p->singlerefperfile ) status = bibl_writeeachfp( fp, b, &lp );
+	else status = bibl_writefp( fp, b, &lp );
 
-	return BIBL_OK;
+	return status;
 }
 
diff --git a/bibutils/bibl.c b/bibutils/bibl.c
--- a/bibutils/bibl.c
+++ b/bibutils/bibl.c
@@ -1,7 +1,7 @@
 /*
  * bibl.c
  *
- * Copyright (c) Chris Putnam 2005-2013
+ * Copyright (c) Chris Putnam 2005-2014
  *
  * Source code released under the GPL version 2
  *
@@ -80,19 +80,20 @@
 bibl_copy( bibl *bout, bibl *bin )
 {
 	fields *refin, *refout;
-	int i, j, n, ok, level;
+	int i, j, n, status, ok, level;
 	char *tag, *value;
 	for ( i=0; i<bin->nrefs; ++i ) {
 		refin = bin->ref[i];
 		refout = fields_new();
+		if ( !refout ) return 0;
 		n = fields_num( refin );
 		for ( j=0; j<n; ++j ) {
 			tag   = fields_tag( refin, j, FIELDS_CHRP );
 			value = fields_value( refin, j, FIELDS_CHRP );
 			level = fields_level( refin, j );
 			if ( tag && value ) {
-				ok = fields_add( refout, tag, value, level );
-				if ( !ok ) return 0;
+				status = fields_add( refout, tag, value, level );
+				if ( status!=FIELDS_OK ) return 0;
 			}
 		}
 		ok = bibl_addref( bout, refout );
diff --git a/bibutils/bibl.h b/bibutils/bibl.h
--- a/bibutils/bibl.h
+++ b/bibutils/bibl.h
@@ -1,7 +1,7 @@
 /*
  * bibl.h
  *
- * Copyright (c) Chris Putnam 2005-2013
+ * Copyright (c) Chris Putnam 2005-2014
  *
  * Source code released under the GPL version 2
  *
diff --git a/bibutils/biblatexin.c b/bibutils/biblatexin.c
--- a/bibutils/biblatexin.c
+++ b/bibutils/biblatexin.c
@@ -1,1114 +1,1413 @@
 /*
  * biblatexin.c
  *
- * Copyright (c) Chris Putnam 2008-2013
- * Copyright (c) Johannes Wilm 2010-2013
- *
- * 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"
-
-static list find    = { 0, 0, 0, NULL };
-static list replace = { 0, 0, 0, NULL };
-
-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 );
-}
-
-/*
- * 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;
-}
-
-static char *
-biblatex_item( char *p, newstr *s )
-{
-	int surrounding_quotes = 0;
-	int nbrackets = 0;
-	int nquotes = 0;
-	while ( *p ) {
-		if ( !nquotes && !nbrackets ) {
-			if ( *p==',' || *p=='=' || *p=='}' || *p==')' )
-				goto out;
-		}
-		if ( *p=='\"' && *(p-1)!='\\' && nbrackets==0 ) {
-			if ( s->len == 0 ) surrounding_quotes = 1;
-			else {
-				if ( !surrounding_quotes ) newstr_addchar( s, *p );
-				if ( nquotes ) surrounding_quotes = 0;
-			}
-			nquotes = ( nquotes==0 );
-		} else if ( *p=='{' ) {
-			if ( nbrackets>0 || nquotes ) newstr_addchar( s, *p );
-			nbrackets++;
-		} else if ( *p=='}' ) {
-			nbrackets--;
-			if ( nbrackets>0 || nquotes ) newstr_addchar( s, *p );
-		} else {
-			if ( !is_ws( *p ) ) newstr_addchar( s, *p );
-			else {
-				if ( s->len!=0 && *p!='\n' && *p!='\r' )
-					newstr_addchar( s, *p );
-				else if ( s->len!=0 && (*p=='\n' || *p=='\r')) {
-					newstr_addchar( s, ' ' );
-					while ( is_ws( *(p+1) ) ) p++;
-				}
-			}
-		}
-		p++;
-	}
-out:
-	newstr_trimendingws( s );
-	return p;
-}
-
-static char *
-process_biblatexline( char *p, newstr *tag, newstr *data )
-{
-	p = skip_ws( p );
-	p = biblatex_item( p, tag );
-	p = skip_ws( p );
-	if ( *p=='=' ) {
-		p++;
-		p = skip_ws( p );
-		p = biblatex_item( p, data );
-		p = skip_ws( p );
-	}
-	if ( *p==',' || *p=='}' || *p==')' ) p++;
-	p = skip_ws( p );
-	return p;
-}
-
-static void
-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, "\\$", "$" );
-	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", "_" );
-}
-
-static void
-biblatex_split( list *tokens, newstr *s )
-{
-	int i, n = s->len, nbrackets = 0;
-	newstr currtok;
-
-	newstr_init( &currtok );
-
-	for ( i=0; i<n; ++i ) {
-		if ( s->data[i]=='{' ) {
-			nbrackets++;
-			newstr_addchar( &currtok, '{' );
-		} else if ( s->data[i]=='}' ) {
-			nbrackets--;
-			newstr_addchar( &currtok, '}' );
-		} else if ( s->data[i]=='#' && !nbrackets ) {
-			if ( currtok.len ) list_add( tokens, currtok.data );
-			newstr_empty( &currtok );
-		} else if ( !is_ws( s->data[i] ) || nbrackets ) {
-			newstr_addchar( &currtok, s->data[i] );
-		} else if ( is_ws( s->data[i] ) ) {
-			if ( currtok.len ) list_add( tokens, currtok.data );
-			newstr_empty( &currtok );
-		}
-	}
-	if ( currtok.len ) list_add( tokens, currtok.data );
-	for ( i=0; i<tokens->n; ++i ) {
-		newstr_trimstartingws( list_get( tokens, i ) );
-		newstr_trimendingws( list_get( tokens, i ) );
-	}
-	newstr_free( &currtok );
-}
-
-/* get reference type */
-static char*
-process_biblatextype( char *p, newstr *data )
-{
-	newstr tmp;
-	newstr_init( &tmp );
-
-	newstr_empty( data );
-
-	if ( *p=='@' ) p++; /* skip '@' character */
-	while ( *p && *p!='{' && *p!='(' ) newstr_addchar( &tmp, *p++ );
-	if ( *p=='{' || *p=='(' ) p++;
-	p = skip_ws( p );
-
-	if ( tmp.len ) {
-		/* add '{' and '}' to protect from string expansion */
-		newstr_addchar( data, '{' );
-		newstr_strcat( data, tmp.data );
-		newstr_addchar( data, '}' );
-	}
-	newstr_free( &tmp );
-	return p;
-}
-/* get reference name */
-static char*
-process_biblatexid( char *p, newstr *data )
-{
-	newstr tmp;
-	char *start_p = p;
-	newstr_init( &tmp );
-	newstr_empty( data );
-
-	while ( *p && *p!=',' ) newstr_addchar( &tmp, *p++ );
-	if ( *p==',' ) p++;
-	p = skip_ws( p ); /* skip ending newline/carriage return */
-
-	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;
-		} else {
-			/* add '{' and '}' to protect from string expansion */
-			newstr_addchar( data, '{' );
-			newstr_strcat( data, tmp.data );
-			newstr_addchar( data, '}' );
-		}
-	}
-
-	newstr_free( &tmp );
-	return p;
-}
-
-static void
-process_cite( fields *bibin, char *p, char *filename, long nref )
-{
-	newstr tag, data;
-	newstrs_init( &tag, &data, NULL );
-	p = process_biblatextype( p, &data );
-	if ( data.len ) fields_add( bibin, "INTERNAL_TYPE", data.data, 0 );
-	if ( *p ) p = process_biblatexid ( p, &data );
-	if ( data.len ) fields_add( bibin, "REFNUM", data.data, 0 );
-	newstr_empty( &data );
-	while ( *p ) {
-		p = process_biblatexline( p, &tag, &data );
-		/* no anonymous or empty fields allowed */
-		if ( tag.len && data.len )
-			fields_add( bibin, tag.data, data.data, 0 );
-		newstrs_empty( &tag, &data, NULL );
-	}
-	newstrs_free( &tag, &data, NULL );
-}
-
-static void
-biblatex_addstring( char *p )
-{
-	newstr s1, s2;
-	newstrs_init( &s1, &s2, NULL );
-	p = skip_ws( p );
-	if ( *p=='(' || *p=='{' ) p++;
-	p = process_biblatexline( p, &s1, &s2 );
-	newstr_findreplace( &s2, "\\ ", " " );
-	biblatex_cleantoken( &s2 );
-	if ( s1.data ) {
-		list_add( &find, s1.data );
-		if ( s2.data ) list_add( &replace, s2.data );
-		else list_add( &replace, "" );
-	}
-	newstrs_free( &s1, &s2, NULL );
-}
-
-static int
-biblatex_usestrings( newstr *s )
-{
-	int i;
-	for ( i=0; i<find.n; ++i ) {
-		if ( !strcasecmp( s->data, (find.str[i]).data ) ) {
-			newstr_findreplace( s, (find.str[i]).data, 
-					(replace.str[i]).data );
-			return 1;
-		}
-	}
-	return 0;
-}
-
-static void
-process_string( char *p )
-{
-	while ( *p && *p!='{' && *p!='(' ) p++;
-	biblatex_addstring( p );
-}
-
-int
-biblatexin_processf( fields *bibin, char *data, char *filename, long nref )
-{
-	if ( !strncasecmp( data, "@STRING", 7 ) ) {
-		process_string( data );
-		return 0;
-        } else {
-		process_cite( bibin, data, filename, nref );
-		return 1;
-	}
-}
-
-static void
-biblatex_addtitleurl( fields *info, newstr *in )
-{
-	newstr s;
-	char *p,*q;
-	newstr_init( &s );
-	q = p = in->data + 6; /*skip past \href{ */
-	while ( *q && *q!='}' ) q++;
-	newstr_segcpy( &s, p, q );
-	fields_add( info, "URL", s.data, 0 );
-	newstr_empty( &s );
-	if ( *q=='}' ) q++;
-	p = q;
-	while ( *q ) q++;
-	newstr_segcpy( &s, p, q );
-	newstr_swapstrings( &s, in );
-	newstr_free( &s );
-}
-
-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 void
-biblatex_cleandata( newstr *tag, newstr *s, fields *info, param *p )
-{
-	list tokens;
-	newstr *tok;
-	int i;
-	if ( !s->len ) return;
-	list_init( &tokens );
-	biblatex_split( &tokens, s );
-	for ( i=0; i<tokens.n; ++i ) {
-		biblatex_usestrings( &(tokens.str[i]) );
-		if (!strncasecmp(tokens.str[i].data,"\\href{", 6)) {
-			biblatex_addtitleurl( info, &(tokens.str[i]) );
-		}
-		if ( p && p->latexin && !is_name_tag( tag ) ) biblatex_cleantoken( &(tokens.str[i]) );
-	}
-	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 );
-	}
-	list_free( &tokens );
-}
-
-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 void
-biblatexin_crossref( bibl *bin, param *p )
-{
-	char booktitle[] = "booktitle";
-	long i, j, ncross;
-	char *nt, *nd, *type;
-	int n, ntype, nl;
-        for ( i=0; i<bin->nrefs; ++i ) {
-		n = fields_find( bin->ref[i], "CROSSREF", -1 );
-		if ( n==-1 ) continue;
-		ncross = biblatexin_findref( bin, bin->ref[i]->data[n].data );
-		if ( ncross==-1 ) {
-			biblatexin_nocrossref( bin, i, n, p );
-#if 0
-			int n1 = fields_find( bin->ref[i], "REFNUM", -1 );
-			fprintf( stderr, "%s: Cannot find cross-reference '%s'",
-				progname, bin->ref[i]->data[n].data);
-			if ( n1!=-1 )
-				fprintf( stderr, " for reference '%s'\n",
-					bin->ref[i]->data[n1].data );
-			fprintf( stderr, "\n" );
-#endif			
-			continue;
-		}
-		ntype = fields_find( bin->ref[i], "INTERNAL_TYPE", -1 );
-		type = bin->ref[i]->data[ntype].data;
-		fields_setused( bin->ref[i], n );
-/*		bin->ref[i]->used[n] = 1; */
-		for ( j=0; j<bin->ref[ncross]->n; ++j ) {
-			nt = bin->ref[ncross]->tag[j].data;
-			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 = bin->ref[ncross]->data[j].data;
-			nl = bin->ref[ncross]->level[j] + 1;
-			fields_add( bin->ref[i], nt, nd, nl );
-
-		}
-	}
-}
-
-static void
-biblatexin_cleanref( fields *bibin, param *p )
-{
-	newstr *t, *d;
-	int i, n;
-	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 );
-		biblatex_cleandata( t, d, bibin, p );
-		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", "" );
-		}
-	}
-}
-
-void
-biblatexin_cleanf( bibl *bin, param *p )
-{
-	long i;
-        for ( i=0; i<bin->nrefs; ++i )
-		biblatexin_cleanref( bin->ref[i], p );
-	biblatexin_crossref( bin, p );
-}
-
-/* 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 )
-{
-	newstr page;
-	char *p;
-	int ok;
-
-	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 ) {
-		ok = fields_add( info, "PAGESTART", page.data, level );
-		if ( !ok ) return 0;
-	}
-
-	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 ) {
-		ok = fields_add( info, "PAGEEND", page.data, level );
-		if ( !ok ) return 0;
-	}
-
-	newstr_free( &page );
-	return 1;
-}
-
-static int
-process_urlcore( fields *info, char *p, int level, char *default_tag )
-{
-	if ( !strncasecmp( p, "\\urllink", 8 ) )
-		return fields_add( info, "URL", p+8, level );
-	else if ( !strncasecmp( p, "\\url", 4 ) )
-		return fields_add( info, "URL", p+4, level );
-	else if ( !strncasecmp( p, "arXiv:", 6 ) )
-		return fields_add( info, "ARXIV", p+6, level ); 
-	else if ( !strncasecmp( p, "http://arxiv.org/abs/", 21 ) )
-		return fields_add( info, "ARXIV", p+21, level );
-	else if ( !strncasecmp( p, "http:", 5 ) )
-		return fields_add( info, "URL", p, level );
-	else return fields_add( info, default_tag, p, level );
-}
-
-static int
-process_url( fields *info, char *p, int level )
-{
-	return process_urlcore( info, p, level, "URL" );
-}
-
-/* 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 )
-{
-        if ( !strncasecmp( p, "Diplom", 6 ) )
-                return fields_replace_or_add( info, "NGENRE", "Diploma thesis", level );
-        else if ( !strncasecmp( p, "Habilitation", 13 ) )
-                return fields_replace_or_add( info, "NGENRE", "Habilitation thesis", level );
-        else
-		return fields_add( info, "PUBLISHER", p, level );
-}
-
-static int
-process_thesistype( fields *info, char *p, int level )
-{
-	/* type in the @thesis is used to distinguish Ph.D. and Master's thesis */
-	if ( !strncasecmp( p, "phdthesis", 9 ) ) {
-		return fields_replace_or_add( info, "NGENRE", "Ph.D. thesis", level );
-	} else if ( !strncasecmp( p, "mastersthesis", 13 ) || !strncasecmp( p, "masterthesis", 12 ) ) {
-		return fields_replace_or_add( info, "NGENRE", "Masters thesis", level );
-	} else if ( !strncasecmp( p, "mathesis", 8 ) ) {
-		return fields_replace_or_add( info, "NGENRE", "Masters thesis", level );
-	} else if ( !strncasecmp( p, "diploma", 7 ) ) {
-		return fields_replace_or_add( info, "NGENRE", "Diploma thesis", level );
-	} else if ( !strncasecmp( p, "habilitation", 12 ) ) {
-		return fields_replace_or_add( info, "NGENRE", "Habilitation thesis", level );
-	}
-	return 1;
-}
-
-/* biblatex drops school field if institution is present */
-static int
-process_school( fields *bibin, fields *info, char *tag, char *value, int level )
-{
-	if ( fields_find( bibin, "institution", LEVEL_ANY ) != -1 )
-		return 1;
-	else
-		return fields_add( info, tag, value, level );
-}
-
-/* biblatex drops school field if institution is present */
-static int
-process_subtype( fields *bibin, fields *info, char *tag, char *value, int level )
-{
-	int ok = 1;
-	if ( !strcasecmp( value, "magazine" ) ) {
-		ok = fields_add( info, "NGENRE", "magazine article", LEVEL_MAIN );
-		if ( !ok ) return 0;
-		ok = fields_add( info, "NGENRE", "magazine", LEVEL_HOST );
-	} else if ( !strcasecmp( value, "newspaper" ) ) {
-		ok = fields_add( info, "NGENRE", "newspaper article", LEVEL_MAIN );
-		if ( !ok ) return 0;
-		ok = fields_add( info, "GENRE", "newspaper", LEVEL_HOST );
-	}
-	return ok;
-}
-
-static int
-process_eprint( fields *bibin, fields *info, int level )
-{
-	int neprint, netype, ok;
-	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 ) ) {
-			ok = fields_add( info, "ARXIV", eprint, level );
-			if ( !ok ) return 0;
-		} else if ( !strncasecmp( etype, "jstor", 5 ) ) {
-			ok = fields_add( info, "JSTOR", eprint, level );
-			if ( !ok ) return 0;
-		} else if ( !strncasecmp( etype, "pubmed", 6 ) ) {
-			ok = fields_add( info, "PMID", eprint, level );
-			if ( !ok ) return 0;
-		} else if ( !strncasecmp( etype, "medline", 7 ) ) {
-			ok = fields_add( info, "MEDLINE", eprint, level );
-			if ( !ok ) return 0;
-		} else {
-			ok = fields_add( info, "EPRINT", eprint, level );
-			if ( !ok ) return 0;
-			ok = fields_add( info, "EPRINTTYPE", etype, level );
-			if ( !ok ) return 0;
-		}
-		fields_setused( bibin, neprint );
-		fields_setused( bibin, netype );
-	} else if ( eprint ) {
-		ok = fields_add( info, "EPRINT", eprint, level );
-		if ( !ok ) return 0;
-		fields_setused( bibin, neprint );
-	} else if ( etype ) {
-		ok = fields_add( info, "EPRINTTYPE", etype, level );
-		if ( !ok ) return 0;
-		fields_setused( bibin, netype );
-	}
-	return 1;
-}
-
-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;
-}
-
-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 )
-{
-	newstr combined;
-	int ok, ret = 1;
-	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 );
-	ok = fields_add( info, "TITLE", combined.data, currlevel );
-	if ( !ok ) ret = 0;
-	newstr_free( &combined );
-	return ret;
-}
-
-static int
-process_separated_title( fields *info, newstr *ttl, newstr *subttl, newstr *ttladdon, int currlevel )
-{
-	int ok;
-	if ( ttladdon->len ) {
-		if ( subttl->len ) attach_addon( subttl, ttladdon );
-		else attach_addon( ttl, ttladdon );
-	}
-	if ( ttl->len ) {
-		ok = fields_add( info, "TITLE", ttl->data, currlevel );
-		if ( !ok ) return 0;
-	}
-	if ( subttl->len ) {
-		ok = fields_add( info, "SUBTITLE", subttl->data, currlevel );
-		if ( !ok ) return 0;
-	}
-	return 1;
-}
-
-static int
-process_title_all( fields *bibin, fields *info, int reftype, param *p,
-	variants *all, int nall )
-{
-	int currlevel, ok, found, ret=1;
-	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 )
-			ok = process_combined_title( info, &ttl, &subttl, &ttladdon, currlevel );
-		else
-			ok = process_separated_title( info, &ttl, &subttl, &ttladdon, currlevel );
-		if ( !ok ) { ret = 0; goto out; }
-	}
-out:
-	newstrs_free( &ttl, &subttl, &ttladdon, NULL );
-	return ret;
-}
-
-static int
-biblatex_matches_asis_corps( fields *info, char *tag, newstr *data, int level,
-	list *asis, list *corps )
-{
-	newstr newtag;
-	int i;
-	for ( i=0; i<asis->n; ++i ) {
-		if ( !strcmp( data->data, list_getc( asis, i ) ) ) {
-			newstr_initstr( &newtag, tag );
-			newstr_strcat( &newtag, ":ASIS" );
-			fields_add( info, newtag.data, data->data, level );
-			newstr_free( &newtag );
-			return 1;
-		}
-	}
-	for ( i=0; i<corps->n; ++i ) {
-		if ( !strcmp( data->data, list_getc( corps, i ) ) ) {
-			newstr_initstr( &newtag, tag );
-			newstr_strcat( &newtag, ":CORP" );
-			fields_add( info, newtag.data, data->data, level );
-			newstr_free( &newtag );
-			return 1;
-		}
-	}
-	return 0;
-}
-
-static int
-biblatex_names( fields *info, char *tag, newstr *data, int level, list *asis, list *corps )
-{
-	int begin, end, ok, n, etal, i, ret = 1;
-	list tokens;
-
-	/* If we match the asis or corps list add and bail. */
-	if ( biblatex_matches_asis_corps( info, tag, data, level, asis, corps ) )
-		return 1;
-
-	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 ) { ret = 0; goto out; }
-		} else {
-			ok = name_addmultielement( info, tag, &tokens, begin, end, level );
-			if ( !ok ) { ret = 0; goto out; }
-		}
-
-		begin = end + 1;
-
-		/* Handle repeated 'and' errors */
-		while ( begin < n && !strcasecmp( list_getc( &tokens, begin ), "and" ) )
-			begin++;
-
-	}
-
-	if ( etal ) {
-		ret = name_addsingleelement( info, tag, "et al.", level, 0 );
-	}
-
-out:
-	list_free( &tokens );
-	return ret;
-}
-
-/*
- * 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 );
-}
-
-int
-biblatexin_convertf( fields *bibin, fields *info, int reftype, param *p,
-		variants *all, int nall )
-{
-	int process, level, i, n, nfields, 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:
-			ok = fields_add( info, newtag, d->data, level );
-			fields_setused( bibin, i );
-			break;
-
-		case PERSON:
-			ok = biblatex_names( info, newtag, d, level, &(p->asis), &(p->corps) );
-			fields_setused( bibin, i );
-			break;
-
-		case BLT_EDITOR:
-			ok = process_editor( bibin, info, t, d, level, &(p->asis), &(p->corps) );
-			fields_setused( bibin, i );
-			break;
-
-		case PAGES:
-			ok = process_pages( info, d, level);
-			fields_setused( bibin, i );
-			break;
-
-		case HOWPUBLISHED:
-			ok = process_howpublished( info, d->data, level );
-			fields_setused( bibin, i );
-			break;
-
-		case BT_URL:
-			ok = process_url( info, d->data, level );
-			fields_setused( bibin, i );
-			break;
-
-		case BT_GENRE:
-			ok = fields_add( info, "NGENRE", d->data, level );
-			fields_setused( bibin, i );
-			break;
-
-		case BT_EPRINT:
-			ok = process_eprint( bibin, info, level );
-			fields_setused( bibin, i );
-			break;
-
-		case BLT_THESIS_TYPE:
-			ok = process_thesistype( info, d->data, level );
-			fields_setused( bibin, i );
-			break;
-
-		case BLT_SCHOOL:
-			ok = process_school( bibin, info, newtag, d->data, level );
-			fields_setused( bibin, i );
-			break;
-
-		case BLT_SUBTYPE:
-			ok = process_subtype( bibin, info, newtag, d->data, level );
-			fields_setused( bibin, i );
-			break;
-
-		case BLT_SKIP:
-			ok = 1;
-			fields_setused( bibin, i );
-			break;
-
-		case TITLE:
-			ok = 1; /* delay title processing until later */
-			break;
-
-		default:
-			ok = 1;
-			break;
-
-		}
-		if ( !ok ) return BIBL_ERR_MEMERR;
-
-	}
-
-	ok = process_title_all( bibin, info, reftype, p, all, nall );
-	if ( !ok ) return BIBL_ERR_MEMERR;
-
-	if ( p->verbose ) report( info );
-
-	return BIBL_OK;
+ * 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 );
+
+	return status;
 }
 
diff --git a/bibutils/biblatexin.h b/bibutils/biblatexin.h
--- a/bibutils/biblatexin.h
+++ b/bibutils/biblatexin.h
@@ -1,7 +1,7 @@
 /*
  * biblatexin.h
  *
- * Copyright (c) Chris Putnam 2008-2013
+ * Copyright (c) Chris Putnam 2008-2014
  *
  * Source code released under the GPL version 2
  *
@@ -18,7 +18,7 @@
 
 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 void biblatexin_cleanf( bibl *bin, param *p );
+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 );
diff --git a/bibutils/bibtexin.c b/bibutils/bibtexin.c
--- a/bibutils/bibtexin.c
+++ b/bibutils/bibtexin.c
@@ -1,1055 +1,1375 @@
 /*
  * bibtexin.c
  *
- * Copyright (c) Chris Putnam 2003-2013
- *
- * 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, 0, NULL };
-static list replace = { 0, 0, 0, NULL };
-
-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 );
-}
-
-/*
- * 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;
-}
-
-static char *
-bibtex_item( char *p, newstr *s )
-{
-	int surrounding_quotes = 0;
-	int nbrackets = 0;
-	int nquotes = 0;
-	while ( *p ) {
-		if ( !nquotes && !nbrackets ) {
-			if ( *p==',' || *p=='=' || *p=='}' || *p==')' )
-				goto out;
-		}
-		if ( *p=='\"' && *(p-1)!='\\' && nbrackets==0 ) {
-			if ( s->len == 0 ) surrounding_quotes = 1;
-			else {
-				if ( !surrounding_quotes ) newstr_addchar( s, *p );
-				if ( nquotes ) surrounding_quotes = 0;
-			}
-			nquotes = ( nquotes==0 );
-		} else if ( *p=='{' ) {
-			if ( nbrackets>0 || nquotes ) newstr_addchar( s, *p );
-			nbrackets++;
-		} else if ( *p=='}' ) {
-			nbrackets--;
-			if ( nbrackets>0 || nquotes ) newstr_addchar( s, *p );
-		} else {
-			if ( !is_ws( *p ) ) newstr_addchar( s, *p );
-			else {
-				if ( s->len!=0 && *p!='\n' && *p!='\r' )
-					newstr_addchar( s, *p );
-				else if ( s->len!=0 && (*p=='\n' || *p=='\r')) {
-					newstr_addchar( s, ' ' );
-					while ( is_ws( *(p+1) ) ) p++;
-				}
-			}
-		}
-		p++;
-	}
-out:
-	newstr_trimendingws( s );
-	return p;
-}
-
-static char *
-process_bibtexline( char *p, newstr *tag, newstr *data )
-{
-	p = skip_ws( p );
-	p = bibtex_item( p, tag );
-	p = skip_ws( p );
-	if ( *p=='=' ) {
-		p++;
-		p = skip_ws( p );
-		p = bibtex_item( p, data );
-		p = skip_ws( p );
-	}
-	if ( *p==',' || *p=='}' || *p==')' ) p++;
-	p = skip_ws( p );
-	return p;
-}
-
-static void
-bibtex_process_tilde( newstr *s )
-{
-	char *p, *q;
-	int n = 0;
-
-	p = q = s->data;
-	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_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, "\\$", "$" );
-	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_tilde( s );
-
-}
-
-static void
-bibtex_addstring( char *p )
-{
-	newstr s1, s2;
-	newstrs_init( &s1, &s2, NULL );
-	p = skip_ws( p );
-	if ( *p=='(' || *p=='{' ) p++;
-	p = process_bibtexline( p, &s1, &s2 );
-	newstr_findreplace( &s2, "\\ ", " " );
-	bibtex_cleantoken( &s2 );
-	if ( s1.data ) {
-		list_add( &find, s1.data );
-		if ( s2.data ) list_add( &replace, s2.data );
-		else list_add( &replace, "" );
-	}
-	newstrs_free( &s1, &s2, NULL );
-}
-
-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 void
-bibtex_split( list *tokens, newstr *s )
-{
-	int i, n = s->len, nbrackets = 0;
-	newstr currtok;
-
-	newstr_init( &currtok );
-
-	for ( i=0; i<n; ++i ) {
-		if ( s->data[i]=='{' ) {
-			nbrackets++;
-			newstr_addchar( &currtok, '{' );
-		} else if ( s->data[i]=='}' ) {
-			nbrackets--;
-			newstr_addchar( &currtok, '}' );
-		} else if ( s->data[i]=='#' && !nbrackets ) {
-			if ( currtok.len ) list_add( tokens, currtok.data );
-			newstr_empty( &currtok );
-		} else if ( !is_ws( s->data[i] ) || nbrackets ) {
-			newstr_addchar( &currtok, s->data[i] );
-		} else if ( is_ws( s->data[i] ) ) {
-			if ( currtok.len ) list_add( tokens, currtok.data );
-			newstr_empty( &currtok );
-		}
-	}
-	if ( currtok.len ) list_add( tokens, currtok.data );
-	for ( i=0; i<tokens->n; ++i ) {
-		newstr_trimstartingws( list_get( tokens, i ) );
-		newstr_trimendingws( list_get( tokens, i ) );
-	}
-	newstr_free( &currtok );
-}
-
-static int
-bibtex_usestrings( newstr *s )
-{
-	char *p;
-	int i;
-	for ( i=0; i<find.n; ++i ) {
-		p = list_getc( &find, i );
-		if ( !strcasecmp( s->data, p ) ) {
-			newstr_findreplace( s, p, list_getc( &replace, i ) );
-			return 1;
-		}
-	}
-	return 0;
-}
-
-/* get reference type */
-static char*
-process_bibtextype( char *p, newstr *data )
-{
-	newstr tmp;
-	newstr_init( &tmp );
-
-	newstr_empty( data );
-
-	if ( *p=='@' ) p++; /* skip '@' character */
-	while ( *p && *p!='{' && *p!='(' && !is_ws( *p ) ) newstr_addchar( &tmp, *p++ );
-	p = skip_ws( p );
-	if ( *p=='{' || *p=='(' ) p++;
-	p = skip_ws( p );
-
-	if ( tmp.len ) {
-		/* add '{' and '}' to protect from string expansion */
-		newstr_addchar( data, '{' );
-		newstr_strcat( data, tmp.data );
-		newstr_addchar( data, '}' );
-	}
-	newstr_free( &tmp );
-	return p;
-}
-/* get reference name */
-static char*
-process_bibtexid( char *p, newstr *data )
-{
-	newstr tmp;
-	char *start_p = p;
-	newstr_init( &tmp );
-	newstr_empty( data );
-
-	while ( *p && *p!=',' ) newstr_addchar( &tmp, *p++ );
-	if ( *p==',' ) p++;
-	p = skip_ws( p ); /* skip ending newline/carriage return */
-
-	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;
-		} else {
-			/* add '{' and '}' to protect from string expansion */
-			newstr_addchar( data, '{' );
-			newstr_strcat( data, tmp.data );
-			newstr_addchar( data, '}' );
-		}
-	}
-
-	newstr_free( &tmp );
-	return p;
-}
-
-static void
-process_cite( fields *bibin, char *p, char *filename, long nref )
-{
-	newstr tag, data;
-	newstrs_init( &tag, &data, NULL );
-	p = process_bibtextype( p, &data );
-	if ( data.len ) fields_add( bibin, "INTERNAL_TYPE", data.data, 0 );
-	if ( *p ) p = process_bibtexid ( p, &data );
-	if ( data.len ) fields_add( bibin, "REFNUM", data.data, 0 );
-	newstr_empty( &data );
-	while ( *p ) {
-		p = process_bibtexline( p, &tag, &data );
-		/* no anonymous or empty fields allowed */
-		if ( tag.len && data.len )
-			fields_add( bibin, tag.data, data.data, 0 );
-		newstrs_empty( &tag, &data, NULL );
-	}
-	newstrs_free( &tag, &data, NULL );
-}
-
-static void
-process_string( char *p )
-{
-	while ( *p && *p!='{' && *p!='(' ) p++;
-	bibtex_addstring( p );
-}
-
-int
-bibtexin_processf( fields *bibin, char *data, char *filename, long nref )
-{
-	if ( !strncasecmp( data, "@STRING", 7 ) ) {
-		process_string( data );
-		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;
-	}
-}
-
-static void
-bibtex_addtitleurl( fields *info, newstr *in )
-{
-	newstr s;
-	char *p,*q;
-	newstr_init( &s );
-	q = p = in->data + 6; /*skip past \href{ */
-	while ( *q && *q!='}' ) q++;
-	newstr_segcpy( &s, p, q );
-	fields_add( info, "URL", s.data, 0 );
-	newstr_empty( &s );
-	if ( *q=='}' ) q++;
-	p = q;
-	while ( *q ) q++;
-	newstr_segcpy( &s, p, q );
-	newstr_swapstrings( &s, in );
-	newstr_free( &s );
-}
-
-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_cleandata( newstr *tag, newstr *s, fields *info, param *p )
-{
-	list tokens;
-	newstr *tok;
-	int i;
-	if ( !s->len ) return;
-	list_init( &tokens );
-	bibtex_split( &tokens, s );
-	for ( i=0; i<tokens.n; ++i ) {
-		tok = list_get( &tokens, i );
-		if ( !bibtex_protected( tok ) ) {
-			bibtex_usestrings( tok );
-		} else {
-			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 );
-	}
-	list_free( &tokens );
-}
-
-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 void
-bibtexin_crossref( bibl *bin, param *p )
-{
-	char booktitle[] = "booktitle";
-	long i, j, ncross;
-	char *nt, *nd, *type;
-	int n, ntype, nl;
-        for ( i=0; i<bin->nrefs; ++i ) {
-		n = fields_find( bin->ref[i], "CROSSREF", -1 );
-		if ( n==-1 ) continue;
-		ncross = bibtexin_findref( bin, bin->ref[i]->data[n].data );
-		if ( ncross==-1 ) {
-			bibtexin_nocrossref( bin, i, n, p );
-			continue;
-		}
-		ntype = fields_find( bin->ref[i], "INTERNAL_TYPE", -1 );
-		type = bin->ref[i]->data[ntype].data;
-		fields_setused( bin->ref[i], n );
-		for ( j=0; j<bin->ref[ncross]->n; ++j ) {
-			nt = bin->ref[ncross]->tag[j].data;
-			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 = bin->ref[ncross]->data[j].data;
-			nl = bin->ref[ncross]->level[j] + 1;
-			fields_add( bin->ref[i], nt, nd, nl );
-
-		}
-	}
-}
-
-static void
-bibtexin_cleanref( fields *bibin, param *p )
-{
-	newstr *t, *d;
-	int i, n;
-	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 );
-		bibtex_cleandata( t, d, bibin, p );
-	}
-}
-
-void
-bibtexin_cleanf( bibl *bin, param *p )
-{
-	long i;
-        for ( i=0; i<bin->nrefs; ++i )
-		bibtexin_cleanref( bin->ref[i], p );
-	bibtexin_crossref( bin, p );
-}
-
-static int
-bibtex_matches_asis_corps( fields *info, char *tag, newstr *data, int level,
-	list *asis, list *corps )
-{
-	newstr newtag;
-	int i;
-	for ( i=0; i<asis->n; ++i ) {
-		if ( !strcmp( data->data, list_getc( asis, i ) ) ) {
-			newstr_initstr( &newtag, tag );
-			newstr_strcat( &newtag, ":ASIS" );
-			fields_add( info, newtag.data, data->data, level );
-			newstr_free( &newtag );
-			return 1;
-		}
-	}
-	for ( i=0; i<corps->n; ++i ) {
-		if ( !strcmp( data->data, list_getc( corps, i ) ) ) {
-			newstr_initstr( &newtag, tag );
-			newstr_strcat( &newtag, ":CORP" );
-			fields_add( info, newtag.data, data->data, level );
-			newstr_free( &newtag );
-			return 1;
-		}
-	}
-	return 0;
-}
-
-/*
- * bibtex_names( info, newtag, field, level);
- *
- * split names in author list separated by and's (use '|' character)
- * and add names
- */
-static int
-bibtex_names( fields *info, char *tag, newstr *data, int level, list *asis,
-	list *corps )
-{
-	int begin, end, ok, n, etal, i, ret = 1;
-	list tokens;
-
-	/* If we match the asis or corps list add and bail. */
-	if ( bibtex_matches_asis_corps( info, tag, data, level, asis, corps ) )
-		return 1;
-
-	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 ) { ret = 0; goto out; }
-		} else {
-			ok = name_addmultielement( info, tag, &tokens, begin, end, level );
-			if ( !ok ) { ret = 0; goto out; }
-		}
-
-		begin = end + 1;
-
-		/* Handle repeated 'and' errors like: authors="G. F. Author and and B. K. Author" */
-		while ( begin < n && !strcasecmp( list_getc( &tokens, begin ), "and" ) )
-			begin++;
-	}
-
-	if ( etal ) {
-		ret = name_addsingleelement( info, tag, "et al.", level, 0 );
-	}
-
-out:
-	list_free( &tokens );
-	return ret;
-}
-
-/* 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 )
-{
-	newstr page;
-	char *p;
-	int ok;
-
-	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 ) {
-		ok = fields_add( info, "PAGESTART", page.data, level );
-		if ( !ok ) return 0;
-	}
-
-	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 ) {
-		ok = fields_add( info, "PAGEEND", page.data, level );
-		if ( !ok ) return 0;
-	}
-
-	newstr_free( &page );
-	return 1;
-}
-
-static int
-process_urlcore( fields *info, newstr *d, int level, char *default_tag )
-{
-	char *p = d->data;
-	if ( !strncasecmp( p, "\\urllink", 8 ) )
-		return fields_add( info, "URL", p+8, level );
-	else if ( !strncasecmp( p, "\\url", 4 ) )
-		return fields_add( info, "URL", p+4, level );
-	else if ( !strncasecmp( p, "arXiv:", 6 ) )
-		return fields_add( info, "ARXIV", p+6, level );
-	else if ( !strncasecmp( p, "http://arxiv.org/abs/", 21 ) )
-		return fields_add( info, "ARXIV", p+21, level );
-	else if ( !strncasecmp( p, "http:", 5 ) )
-		return fields_add( info, "URL", p, level );
-	else return fields_add( info, default_tag, p, level );
-}
-
-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"
- */
-static int
-process_keywords( fields *info, newstr *d, int level )
-{
-	newstr keyword;
-	char *p;
-	int ok;
-
-	if ( !d || d->len==0 ) return 1;
-
-	p = d->data;
-	newstr_init( &keyword );
-
-	while ( *p ) {
-		p = skip_ws( p );
-		while ( *p && *p!=';' ) newstr_addchar( &keyword, *p++ );
-		newstr_trimendingws( &keyword );
-		if ( keyword.len ) {
-			ok = fields_add( info, "KEYWORD", keyword.data, level );
-			if ( !ok ) return 0;
-			newstr_empty( &keyword );
-		}
-		if ( *p==';' ) p++;
-	}
-	newstr_free( &keyword );
-	return 1;
-}
-
-/* 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.
- */
-static int
-process_howpublished( fields *info, newstr *d, int level )
-{
-	char *p = d->data;
-	if ( !strncasecmp( p, "Diplom", 6 ) )
-		return fields_replace_or_add( info, "GENRE", "Diploma thesis", level );
-	else if ( !strncasecmp( p, "Habilitation", 13 ) )
-		return fields_replace_or_add( info, "GENRE", "Habilitation thesis", level );
-	else if ( !strncasecmp( d->data, "http:", 5 ) )
-		return process_url( info, d, level );
-	else if ( !strncasecmp( d->data, "arXiv:", 6 ) )
-		return process_url( info, d, level );
-	else 
-		return fields_add( info, "PUBLISHER", p, level );
-}
-
-/*
- * sentelink = {file://localhost/full/path/to/file.pdf,Sente,PDF}
- */
-static int
-process_sente( fields *info, newstr *d, int level )
-{
-	int ret = 1;
-	newstr link;
-	char *p = d->data;
-	newstr_init( &link );
-	while ( *p && *p!=',' ) newstr_addchar( &link, *p++ );
-	newstr_trimstartingws( &link );
-	newstr_trimendingws( &link );
-	if ( link.len ) ret = fields_add( info, "FILEATTACH", link.data, level );
-	newstr_free( &link );
-	return ret;
-}
-
-/*
- * 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;
-	n = fields_find( bibin, "publisher", LEVEL_ANY );
-	if ( n==-1 )
-		return fields_add( info, "PUBLISHER", d->data, level );
-	else
-		return fields_add( info, "ORGANIZER:CORP", d->data, level );
-}
-
-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 )
-{
-	char *p = d->data;
-	newstr link;
-	int i, n, n1, n2, ret = 1;
-
-	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 ( link.len ) ret = fields_add( info, "FILEATTACH", link.data, level );
-		newstr_free( &link );
-	} else {
-		/* This field isn't formatted properly, so just copy directly */
-		ret = fields_add( info, "FILEATTACH", p, level );
-	}
-	return ret;
-}
-
-static int
-process_note( fields *info, newstr *d, int level )
-{
-	if ( !strncasecmp( d->data, "http:", 5 ) ||
-	     !strncasecmp( d->data, "arXiv:", 6 ) ) {
-		return process_url( info, d, level );
-	} else {
-		return fields_add( info, "NOTES", d->data, level );
-	}
-}
-
-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;
-}
-
-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;
-	if ( bibtexin_titleinbook_isbooktitle( intag, bibin ) ) level=LEVEL_MAIN;
-	title_process( info, outtag, indata, level, nosplittitle );
-	return 1;
-}
-static int
-bibtex_simple( fields *info, char *outtag, newstr *d, int level )
-{
-	return fields_add( info, outtag, d->data, level );
-}
-
-int
-bibtexin_convertf( fields *bibin, fields *info, int reftype, param *p,
-		variants *all, int nall )
-{
-	int process, level, i, n, nfields, ok;
-	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:
-			ok = bibtex_simple( info, outtag, d, level );
-			break;
-
-		case TITLE:
-			ok = bibtexin_title_process( info, "TITLE", bibin, t, d, level, p->nosplittitle );
-			break;
-
-		case PERSON:
-			ok = bibtex_names( info, outtag, d, level, &(p->asis), &(p->corps) );
-			break;
-
-		case PAGES:
-			ok = process_pages( info, d, level );
-			break;
-
-		case KEYWORD:
-			ok = process_keywords( info, d, level );
-			break;
-
-		case HOWPUBLISHED:
-			ok = process_howpublished( info, d, level );
-			break;
-
-		case LINKEDFILE:
-			ok = process_file( info, d, level );
-			break;
-
-		case BT_NOTE:
-			ok = process_note( info, d, level );
-			break;
-
-		case BT_SENTE:
-			ok = process_sente( info, d, level );
-			break;
-
-		case BT_URL:
-			ok = process_url( info, d, level );
-			break;
-
-		case BT_ORG:
-			ok = process_organization( bibin, info, d, level );
-			break;
-
-		default:
-			ok = 1;
-			break;
-		}
-
-		if ( !ok ) return BIBL_ERR_MEMERR;
-	}
-	return BIBL_OK;
+ * 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;
 }
 
diff --git a/bibutils/bibtexin.h b/bibutils/bibtexin.h
--- a/bibutils/bibtexin.h
+++ b/bibutils/bibtexin.h
@@ -1,7 +1,7 @@
 /*
  * bibtexin.h
  *
- * Copyright (c) Chris Putnam 2003-2013
+ * Copyright (c) Chris Putnam 2003-2014
  *
  * Source code released under the GPL version 2
  *
@@ -18,7 +18,7 @@
 
 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 void bibtexin_cleanf( bibl *bin, param *p );
+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 );
diff --git a/bibutils/bibtexout.c b/bibutils/bibtexout.c
--- a/bibutils/bibtexout.c
+++ b/bibutils/bibtexout.c
@@ -1,7 +1,7 @@
 /*
  * bibtexout.c
  *
- * Copyright (c) Chris Putnam 2003-2013
+ * Copyright (c) Chris Putnam 2003-2014
  *
  * Program and source code released under the GPL version 2
  *
@@ -30,7 +30,7 @@
 	p->latexout         = 1;
 	p->utf8out          = BIBL_CHARSET_UTF8_DEFAULT;
 	p->utf8bom          = BIBL_CHARSET_BOM_DEFAULT;
-	p->xmlout           = 0;
+	p->xmlout           = BIBL_XMLOUT_FALSE;
 	p->nosplittitle     = 0;
 	p->verbose          = 0;
 	p->addcount         = 0;
diff --git a/bibutils/bibtextypes.c b/bibutils/bibtextypes.c
--- a/bibutils/bibtextypes.c
+++ b/bibutils/bibtextypes.c
@@ -664,6 +664,7 @@
 	REFTYPE( "manual", manual ),
 	REFTYPE( "mastersthesis", masters ),
 	REFTYPE( "misc", misc ),
+	REFTYPE( "online", misc ),
 	REFTYPE( "patent", patent ),
 	REFTYPE( "phdthesis", phds ),
 	REFTYPE( "periodical", periodical ),
diff --git a/bibutils/bibutils.h b/bibutils/bibutils.h
--- a/bibutils/bibutils.h
+++ b/bibutils/bibutils.h
@@ -1,7 +1,7 @@
 /*
  * bibutils.h
  *
- * Copyright (c) Chris Putnam 2005-2013
+ * Copyright (c) Chris Putnam 2005-2014
  *
  * Source code released under GPL version 2
  *
@@ -17,6 +17,7 @@
 #include "bibl.h"
 #include "list.h"
 #include "charsets.h"
+#include "newstr_conv.h"
 
 #define BIBL_OK           (0)
 #define BIBL_ERR_BADINPUT (-1)
@@ -63,6 +64,10 @@
 #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
+
 typedef unsigned char uchar;
 
 typedef struct param {
@@ -98,7 +103,7 @@
 
         int  (*readf)(FILE*,char*,int,int*,newstr*,newstr*,int*);
         int  (*processf)(fields*,char*,char*,long);
-        void (*cleanf)(bibl*,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);
         void (*headerf)(FILE*,struct param*);
@@ -113,12 +118,12 @@
 extern void bibl_initparams( param *p, int readmode, int writemode,
 	char *progname );
 extern void bibl_freeparams( param *p );
-extern void bibl_readasis( param *p, char *filename );
-extern void bibl_addtoasis( param *p, char *entry );
-extern void bibl_readcorps( param *p, char *filename );
-extern void bibl_addtocorps( param *p, char *entry );
-extern int bibl_read( bibl *b, FILE *fp, char *filename, param *p );
-extern int bibl_write( bibl *b, FILE *fp, param *p );
+extern int  bibl_readasis( param *p, char *filename );
+extern int  bibl_addtoasis( param *p, char *entry );
+extern int  bibl_readcorps( param *p, char *filename );
+extern int  bibl_addtocorps( param *p, char *entry );
+extern int  bibl_read( bibl *b, FILE *fp, char *filename, param *p );
+extern int  bibl_write( bibl *b, FILE *fp, param *p );
 extern void bibl_reporterr( int err );
 
 #ifdef __cplusplus
diff --git a/bibutils/bltypes.c b/bibutils/bltypes.c
--- a/bibutils/bltypes.c
+++ b/bibutils/bltypes.c
@@ -18,1038 +18,1044 @@
  * Article in a journal, newspaper, other periodical
  */
 static lookups article[] = {
-	{ "author",          "AUTHOR",                 PERSON,      LEVEL_MAIN   },
-	{ "editor",          "EDITOR",                 BLT_EDITOR,  LEVEL_MAIN   },
-	{ "editora",         "EDITOR",                 BLT_EDITOR,  LEVEL_MAIN   },
-	{ "editorb",         "EDITOR",                 BLT_EDITOR,  LEVEL_MAIN   },
-	{ "editorc",         "EDITOR",                 BLT_EDITOR,  LEVEL_MAIN   },
-	{ "editortype",      "",                       BLT_SKIP,    LEVEL_MAIN   },
-	{ "editoratype",     "",                       BLT_SKIP,    LEVEL_MAIN   },
-	{ "editorbtype",     "",                       BLT_SKIP,    LEVEL_MAIN   },
-	{ "editorctype",     "",                       BLT_SKIP,    LEVEL_MAIN   },
-	{ "director",        "DIRECTOR",               PERSON,      LEVEL_MAIN   },
-	{ "producer",        "PRODUCER",               PERSON,      LEVEL_MAIN   },
-	{ "execproducer",    "PRODUCER",               PERSON,      LEVEL_MAIN   },
-	{ "writer",          "AUTHOR",                 PERSON,      LEVEL_MAIN   },
-	{ "redactor",        "REDACTOR",               PERSON,      LEVEL_MAIN   },
-	{ "annotator",       "ANNOTATOR",              PERSON,      LEVEL_MAIN   },
-	{ "commentator",     "COMMENTATOR",            PERSON,      LEVEL_MAIN   },
-	{ "translator",      "TRANSLATOR",             PERSON,      LEVEL_MAIN   },
-	{ "title",           "TITLE",                  TITLE,       LEVEL_MAIN   },
-	{ "subtitle",        "SUBTITLE",               TITLE,       LEVEL_MAIN   },
-	{ "titleaddon",      "TITLEADDON",             TITLE,       LEVEL_MAIN   },
-	{ "shorttitle",      "SHORTITLE",              SIMPLE,      LEVEL_MAIN   },
-	{ "journal",         "TITLE",                  TITLE,       LEVEL_HOST   },
-	{ "journaltitle",    "TITLE",                  TITLE,       LEVEL_HOST   },
-	{ "journalsubtitle", "SUBTITLE",               TITLE,       LEVEL_HOST   },
-	{ "shortjournal",    "SHORTTITLE",             SIMPLE,      LEVEL_HOST   },
-	{ "issuetitle",      "TITLE",                  TITLE,       LEVEL_SERIES }, /*WRONG*/
-	{ "issuesubtitle",   "SUBTITLE",               TITLE,       LEVEL_SERIES }, /*WRONG*/
-	{ "language",        "LANGUAGE",               SIMPLE,      LEVEL_MAIN   },
-	{ "origlanguage",    "LANGUAGE",               SIMPLE,      LEVEL_ORIG   },
-	{ "origyear",        "YEAR",                   SIMPLE,      LEVEL_ORIG   },
-	{ "origdate",        "DATE",                   SIMPLE,      LEVEL_ORIG   },
-	{ "origtitle",       "TITLE",                  SIMPLE,      LEVEL_ORIG   },
-	{ "origlocation",    "ADDRESS",                SIMPLE,      LEVEL_ORIG   },
-	{ "origpublisher",   "PUBLISHER",              SIMPLE,      LEVEL_ORIG   },
-	{ "series",          "PARTTITLE",              SIMPLE,      LEVEL_HOST   },
-	{ "volume",          "VOLUME",                 SIMPLE,      LEVEL_MAIN   },
-	{ "number",          "NUMBER",                 SIMPLE,      LEVEL_MAIN   },
-	{ "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   },
-	{ "pages",           "PAGES",                  PAGES,       LEVEL_MAIN   },
-	{ "version",         "EDITION",                SIMPLE,      LEVEL_MAIN   },
-	{ "note",            "NOTES",                  SIMPLE,      LEVEL_MAIN   },
-	{ "annote",          "ANNOTATION",             SIMPLE,      LEVEL_MAIN   },
-	{ "annotation",      "ANNOTATION",             SIMPLE,      LEVEL_MAIN   },
-	{ "issn",            "ISSN",                   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   },
-	{ "urldate",         "URLDATE",                SIMPLE,      LEVEL_MAIN   },
-	{ "urlday",          "?urlday?",               SIMPLE,      LEVEL_MAIN   }, /* WRONG */
-	{ "urlmonth",        "?urlmonth?",             SIMPLE,      LEVEL_MAIN   }, /* WRONG */
-	{ "urlyear",         "?urlyear?",              SIMPLE,      LEVEL_MAIN   }, /* WRONG */
-	{ "address",         "ADDRESS",                SIMPLE,      LEVEL_MAIN   },
-	{ "refnum",          "REFNUM",                 SIMPLE,      LEVEL_MAIN   },
-	{ "hyphenation",     "LANGCATALOG",            SIMPLE,      LEVEL_MAIN   },
-	{ "entrysubtype",    "",                       BLT_SUBTYPE, LEVEL_MAIN   },
-	{ "",                "INTERNAL_TYPE|ARTICLE",  ALWAYS,      LEVEL_MAIN   },
-	{ "",                "ISSUANCE|continuing",    ALWAYS,      LEVEL_HOST   },
-	{ "",                "RESOURCE|text",          ALWAYS,      LEVEL_MAIN   },
-	{ "",                "NGENRE|journal article", DEFAULT,     LEVEL_MAIN   },
-	{ "",                "GENRE|periodical",       DEFAULT,     LEVEL_HOST   }
-};
-
-/* Book */
-
-static lookups book[] = {
-	{ "author",          "AUTHOR",               PERSON,     LEVEL_MAIN },
-	{ "editor",          "EDITOR",               BLT_EDITOR, LEVEL_MAIN },
-	{ "editora",         "EDITOR",               BLT_EDITOR, LEVEL_MAIN },
-	{ "editorb",         "EDITOR",               BLT_EDITOR, LEVEL_MAIN },
-	{ "editorc",         "EDITOR",               BLT_EDITOR, LEVEL_MAIN },
-	{ "editortype",      "",                     BLT_SKIP,   LEVEL_MAIN },
-	{ "editoratype",     "",                     BLT_SKIP,   LEVEL_MAIN },
-	{ "editorbtype",     "",                     BLT_SKIP,   LEVEL_MAIN },
-	{ "editorctype",     "",                     BLT_SKIP,   LEVEL_MAIN },
-	{ "director",        "DIRECTOR",             PERSON,     LEVEL_MAIN },
-	{ "producer",        "PRODUCER",             PERSON,     LEVEL_MAIN },
-	{ "execproducer",    "PRODUCER",             PERSON,     LEVEL_MAIN },
-	{ "writer",          "AUTHOR",               PERSON,     LEVEL_MAIN },
-	{ "redactor",        "REDACTOR",             PERSON,     LEVEL_MAIN },
-	{ "annotator",       "ANNOTATOR",            PERSON,     LEVEL_MAIN },
-	{ "commentator",     "COMMENTATOR",          PERSON,     LEVEL_MAIN },
-	{ "translator",      "TRANSLATOR",           PERSON,     LEVEL_MAIN },
-	{ "introduction",    "INTROAUTHOR",          PERSON,     LEVEL_MAIN },
-	{ "foreword",        "INTROAUTHOR",          PERSON,     LEVEL_MAIN },
-	{ "afterword",       "AFTERAUTHOR",          PERSON,     LEVEL_MAIN },
-	{ "title",           "TITLE",                TITLE,      LEVEL_MAIN },
-	{ "subtitle",        "SUBTITLE",             TITLE,      LEVEL_MAIN },
-	{ "titleaddon",      "TITLEADDON",           TITLE,      LEVEL_MAIN },
-	{ "shorttitle",      "SHORTITLE",            SIMPLE,     LEVEL_MAIN  },
-	{ "maintitle",       "TITLE",                TITLE,      LEVEL_HOST },
-	{ "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 },
-	{ "date",            "DATE",                 SIMPLE,     LEVEL_MAIN },   /*WRONG*/
-	{ "origlanguage",    "LANGUAGE",             SIMPLE,     LEVEL_ORIG },
-	{ "origyear",        "YEAR",                 SIMPLE,     LEVEL_ORIG },
-	{ "origdate",        "DATE",                 SIMPLE,     LEVEL_ORIG },
-	{ "origtitle",       "TITLE",                SIMPLE,     LEVEL_ORIG },
-	{ "origlocation",    "ADDRESS",              SIMPLE,     LEVEL_ORIG },
-	{ "origpublisher",   "PUBLISHER",            SIMPLE,     LEVEL_ORIG },
-	{ "volume",          "VOLUME",               SIMPLE,     LEVEL_HOST },
-	{ "part",            "PART",                 SIMPLE,     LEVEL_HOST },
-	{ "edition",         "EDITION",              SIMPLE,     LEVEL_MAIN },
-	{ "volumes",         "NUMVOLUMES",           SIMPLE,     LEVEL_HOST },
-	{ "series",          "TITLE",                SIMPLE,     LEVEL_HOST }, /* WRONG */
-	{ "number",          "NUMBER",               SIMPLE,     LEVEL_MAIN },
-	{ "note",            "NOTES",                SIMPLE,     LEVEL_MAIN },
-	{ "annote",          "ANNOTATION",           SIMPLE,     LEVEL_MAIN },
-	{ "annotation",      "ANNOTATION",           SIMPLE,     LEVEL_MAIN },
-	{ "publisher",       "PUBLISHER",            SIMPLE,     LEVEL_MAIN },
-	{ "location",        "ADDRESS",              SIMPLE,     LEVEL_MAIN },
-	{ "isbn",            "ISBN",                 SIMPLE,     LEVEL_MAIN },
-	{ "chapter",         "CHAPTER",              SIMPLE,     LEVEL_MAIN },
-	{ "pages",           "?pages?",              SIMPLE,     LEVEL_MAIN }, /* WRONG */
-	{ "pagetotal",       "?pagetotal?",          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 },
-	{ "urldate",         "URLDATE",              SIMPLE,     LEVEL_MAIN },
-	{ "urlday",          "?urlday?",             SIMPLE,     LEVEL_MAIN },
-	{ "urlmonth",        "?urlmonth?",           SIMPLE,     LEVEL_MAIN },
-	{ "urlyear",         "?urlyear?",            SIMPLE,     LEVEL_MAIN },
-	{ "address",         "ADDRESS",              SIMPLE,     LEVEL_MAIN },
-	{ "hyphenation",     "LANGCATALOG",            SIMPLE,      LEVEL_MAIN   },
-	{ "refnum",          "REFNUM",               SIMPLE,     LEVEL_MAIN },
-	{ "",                "INTERNAL_TYPE|BOOK",   ALWAYS,     LEVEL_MAIN },
-	{ "",                "RESOURCE|text",        ALWAYS,     LEVEL_MAIN },
-	{ "",                "ISSUANCE|monographic", ALWAYS,     LEVEL_MAIN },
-	{ "",                "GENRE|book",           ALWAYS,     LEVEL_MAIN }
-};
-
-/* Booklet */
-
-static lookups booklet[] = {
-	{ "author",          "AUTHOR",       PERSON, LEVEL_MAIN },
-	{ "editor",          "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editora",         "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editorb",         "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editorc",         "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editortype",      "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "editoratype",     "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "editorbtype",     "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "editorctype",     "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "director",        "DIRECTOR",     PERSON, LEVEL_MAIN },
-	{ "producer",        "PRODUCER",     PERSON, LEVEL_MAIN },
-	{ "execproducer",    "PRODUCER",     PERSON, LEVEL_MAIN },
-	{ "writer",          "AUTHOR",       PERSON, LEVEL_MAIN },
-	{ "title",           "TITLE",        TITLE,  LEVEL_MAIN },
-	{ "subtitle",        "SUBTITLE",     TITLE,  LEVEL_MAIN },
-	{ "titleaddon",      "TITLEADDON",   TITLE,  LEVEL_MAIN },
-	{ "shorttitle",      "SHORTITLE",    SIMPLE, LEVEL_MAIN },
-	{ "howpublished",    "",       HOWPUBLISHED, LEVEL_MAIN },
-	{ "year",            "YEAR",         SIMPLE, LEVEL_MAIN },
-	{ "month",           "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 },
-	{ "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?",      SIMPLE, LEVEL_MAIN }, /* WRONG */
-	{ "pagetotal",       "?pagetotal?",  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 },
-	{ "urldate",         "URLDATE",      SIMPLE, LEVEL_MAIN },
-	{ "urlday",          "?urlday?",    SIMPLE, LEVEL_MAIN },
-	{ "urlmonth",        "?urlmonth?",    SIMPLE, LEVEL_MAIN },
-	{ "urlyear",         "?urlyear?",    SIMPLE, LEVEL_MAIN },
-	{ "address",         "ADDRESS",      SIMPLE, LEVEL_MAIN },
-	{ "hyphenation",     "LANGCATALOG",            SIMPLE,      LEVEL_MAIN   },
-	{ "refnum",          "REFNUM",       SIMPLE, LEVEL_MAIN },
-	{ "",                "INTERNAL_TYPE|BOOK",    ALWAYS, LEVEL_MAIN },
-	{ "",                "RESOURCE|text",ALWAYS, LEVEL_MAIN },
-	{ "",                "ISSUANCE|monographic", ALWAYS, LEVEL_MAIN },
-	{ "",                "GENRE|book",   ALWAYS, LEVEL_MAIN }
-};
-
-static lookups collection[] = {
-	{ "editor",          "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editora",         "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editorb",         "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editorc",         "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editortype",      "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "editoratype",     "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "editorbtype",     "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "editorctype",     "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "director",        "DIRECTOR",     PERSON, LEVEL_MAIN },
-	{ "producer",        "PRODUCER",     PERSON, LEVEL_MAIN },
-	{ "execproducer",    "PRODUCER",     PERSON, LEVEL_MAIN },
-	{ "writer",          "AUTHOR",       PERSON, LEVEL_MAIN },
-	{ "redactor",        "REDACTOR",     PERSON, LEVEL_MAIN },
-	{ "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 },
-	{ "date",            "DATE",         SIMPLE, LEVEL_MAIN },   /*WRONG*/
-	{ "introduction",    "INTROAUTHOR",  PERSON, LEVEL_MAIN },
-	{ "foreword",        "INTROAUTHOR",  PERSON, LEVEL_MAIN },
-	{ "afterword",       "AFTERAUTHOR",  PERSON, LEVEL_MAIN },
-	{ "title",           "TITLE",        TITLE,  LEVEL_MAIN },
-	{ "subtitle",        "SUBTITLE",     TITLE,  LEVEL_MAIN },
-	{ "titleaddon",      "TITLEADDON",   TITLE,  LEVEL_MAIN },
-	{ "shorttitle",      "SHORTTITLE",   SIMPLE, LEVEL_MAIN },
-	{ "maintitle",       "TITLE",        TITLE,  LEVEL_HOST },
-	{ "mainsubtitle",    "SUBTITLE",     TITLE,  LEVEL_HOST },
-	{ "maintitleaddon",  "TITLEADDON",   TITLE,  LEVEL_HOST },
-	{ "language",        "LANGUAGE",     SIMPLE, LEVEL_MAIN },
-	{ "origlanguage",    "LANGUAGE",     SIMPLE, LEVEL_ORIG },
-	{ "origyear",        "YEAR",         SIMPLE, LEVEL_ORIG },
-	{ "origdate",        "DATE",         SIMPLE, LEVEL_ORIG },
-	{ "origtitle",       "TITLE",        SIMPLE, LEVEL_ORIG },
-	{ "origlocation",    "ADDRESS",      SIMPLE, LEVEL_ORIG },
-	{ "origpublisher",   "PUBLISHER",    SIMPLE, LEVEL_ORIG },
-	{ "volume",          "VOLUME",       SIMPLE, LEVEL_HOST },
-	{ "part",            "PART",         SIMPLE, LEVEL_HOST },
-	{ "edition",         "EDITION",      SIMPLE, LEVEL_MAIN },
-	{ "volumes",         "NUMVOLUMES",   SIMPLE, LEVEL_HOST },
-	{ "series",          "?series?",     SIMPLE, LEVEL_HOST }, /* WRONG */
-	{ "number",          "NUMBER",       SIMPLE, LEVEL_MAIN },
-	{ "note",            "NOTES",        SIMPLE, LEVEL_MAIN },
-	{ "annote",          "ANNOTATION",   SIMPLE, LEVEL_MAIN },
-	{ "annotation",      "ANNOTATION",   SIMPLE, LEVEL_MAIN },
-	{ "publisher",       "PUBLISHER",    SIMPLE, LEVEL_MAIN },
-	{ "location",        "ADDRESS",      SIMPLE, LEVEL_MAIN },
-	{ "isbn",            "ISBN",         SIMPLE, LEVEL_MAIN },
-	{ "chapter",         "CHAPTER",      SIMPLE, LEVEL_MAIN },
-	{ "pages",           "?pages?",      SIMPLE, LEVEL_MAIN }, /* WRONG */
-	{ "pagetotal",       "?pagetotal?",  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 },
-	{ "urldate",         "URLDATE",      SIMPLE, LEVEL_MAIN },
-	{ "urlday",          "?urlday?",    SIMPLE, LEVEL_MAIN },
-	{ "urlmonth",        "?urlmonth?",    SIMPLE, LEVEL_MAIN },
-	{ "urlyear",         "?urlyear?",    SIMPLE, LEVEL_MAIN },
-	{ "address",         "ADDRESS",      SIMPLE, LEVEL_MAIN },
-	{ "hyphenation",     "LANGCATALOG",            SIMPLE,      LEVEL_MAIN   },
-	{ "refnum",          "REFNUM",       SIMPLE, LEVEL_MAIN },
-	{ "",                "INTERNAL_TYPE|BOOK",    ALWAYS, LEVEL_MAIN },
-	{ "",                "RESOURCE|text",ALWAYS, LEVEL_MAIN },
-	{ "",                "ISSUANCE|monographic", ALWAYS, LEVEL_MAIN },
-	{ "",                "GENRE|book",   ALWAYS, LEVEL_MAIN }
-};
-
-/* Part of a book (e.g. chapter or section) */
-
-static lookups inbook[] = {
-	{ "author",          "AUTHOR",       PERSON, LEVEL_MAIN },
-	{ "editor",          "EDITOR",       BLT_EDITOR, LEVEL_HOST },
-	{ "editora",         "EDITOR",       BLT_EDITOR, LEVEL_HOST },
-	{ "editorb",         "EDITOR",       BLT_EDITOR, LEVEL_HOST },
-	{ "editorc",         "EDITOR",       BLT_EDITOR, LEVEL_HOST },
-	{ "editortype",      "",             BLT_SKIP,   LEVEL_HOST },
-	{ "editoratype",     "",             BLT_SKIP,   LEVEL_HOST },
-	{ "editorbtype",     "",             BLT_SKIP,   LEVEL_HOST },
-	{ "editorctype",     "",             BLT_SKIP,   LEVEL_HOST },
-	{ "director",        "DIRECTOR",     PERSON, LEVEL_HOST },
-	{ "producer",        "PRODUCER",     PERSON, LEVEL_HOST },
-	{ "execproducer",    "PRODUCER",     PERSON, LEVEL_HOST },
-	{ "writer",          "AUTHOR",       PERSON, LEVEL_HOST },
-	{ "redactor",        "REDACTOR",     PERSON, LEVEL_HOST },
-	{ "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 },
-	{ "date",            "DATE",         SIMPLE, LEVEL_MAIN },   /*WRONG*/
-	{ "introduction",    "INTROAUTHOR",  PERSON, LEVEL_HOST },
-	{ "foreword",        "INTROAUTHOR",  PERSON, LEVEL_HOST },
-	{ "afterword",       "AFTERAUTHOR",  PERSON, LEVEL_HOST },
-	{ "title",           "TITLE",        TITLE,  LEVEL_MAIN },
-	{ "subtitle",        "SUBTITLE",     TITLE,  LEVEL_MAIN },
-	{ "titleaddon",      "TITLEADDON",   TITLE,  LEVEL_MAIN },
-	{ "shorttitle",      "SHORTTITLE",   SIMPLE, LEVEL_MAIN },
-	{ "booktitle",       "TITLE",        TITLE,  LEVEL_HOST },
-	{ "booksubtitle",    "SUBTITLE",     TITLE,  LEVEL_HOST },
-	{ "booktitleaddon",  "TITLEADDON",   TITLE,  LEVEL_HOST },
-	{ "bookauthor",      "AUTHOR",       PERSON, LEVEL_HOST },
-	{ "maintitle",       "TITLE",        TITLE,  LEVEL_SERIES },
-	{ "mainsubtitle",    "SUBTITLE",     TITLE,  LEVEL_SERIES },
-	{ "maintitleaddon",  "TITLEADDON",   TITLE,  LEVEL_SERIES },
-	{ "language",        "LANGUAGE",     SIMPLE, LEVEL_MAIN },
-	{ "origlanguage",    "LANGUAGE",     SIMPLE, LEVEL_ORIG },
-	{ "origyear",        "YEAR",         SIMPLE, LEVEL_ORIG },
-	{ "origdate",        "DATE",         SIMPLE, LEVEL_ORIG },
-	{ "origtitle",       "TITLE",        SIMPLE, LEVEL_ORIG },
-	{ "origlocation",    "ADDRESS",      SIMPLE, LEVEL_ORIG },
-	{ "origpublisher",   "PUBLISHER",    SIMPLE, LEVEL_ORIG },
-	{ "volume",          "VOLUME",       SIMPLE, LEVEL_MAIN },
-	{ "pages",           "PAGES",        PAGES,  LEVEL_MAIN },
-	{ "part",            "PART",         SIMPLE, LEVEL_HOST },
-	{ "edition",         "EDITION",      SIMPLE, LEVEL_MAIN },
-	{ "volumes",         "NUMVOLUMES",   SIMPLE, LEVEL_HOST },
-	{ "series",          "TITLE",        SIMPLE, LEVEL_SERIES+1 }, /* WRONG */
-	{ "number",          "NUMBER",       SIMPLE, LEVEL_MAIN },
-	{ "note",            "NOTES",        SIMPLE, LEVEL_MAIN },
-	{ "annote",          "ANNOTATION",   SIMPLE, LEVEL_MAIN },
-	{ "annotation",      "ANNOTATION",   SIMPLE, LEVEL_MAIN },
-	{ "publisher",       "PUBLISHER",    SIMPLE, LEVEL_MAIN },
-	{ "location",        "ADDRESS",      SIMPLE, LEVEL_MAIN },
-	{ "isbn",            "ISBN",         SIMPLE, LEVEL_HOST },
-	{ "chapter",         "CHAPTER",      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 },
-	{ "urldate",         "URLDATE",      SIMPLE, LEVEL_MAIN },
-	{ "urlday",          "?urlday?",     SIMPLE, LEVEL_MAIN },
-	{ "urlmonth",        "?urlmonth?",   SIMPLE, LEVEL_MAIN },
-	{ "urlyear",         "?urlyear?",    SIMPLE, LEVEL_MAIN },
-	{ "address",         "ADDRESS",      SIMPLE, LEVEL_MAIN },
-	{ "hyphenation",     "LANGCATALOG",            SIMPLE,      LEVEL_MAIN   },
-	{ "refnum",          "REFNUM",       SIMPLE, 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 }
-};
-
-/* incollection */
-
-static lookups incollection[] = {
-
-	{ "author",          "AUTHOR",       PERSON, LEVEL_MAIN },
-	{ "year",            "YEAR",         SIMPLE, LEVEL_MAIN },
-	{ "month",           "MONTH",        SIMPLE, LEVEL_MAIN },
-	{ "date",            "DATE",         SIMPLE, LEVEL_MAIN },   /*WRONG*/
-	{ "title",           "TITLE",        TITLE,  LEVEL_MAIN },
-	{ "subtitle",        "SUBTITLE",     TITLE,  LEVEL_MAIN },
-	{ "titleaddon",      "TITLEADDON",   TITLE,  LEVEL_MAIN },
-	{ "shorttitle",      "SHORTTITLE",   SIMPLE, LEVEL_MAIN },
-	{ "language",        "LANGUAGE",     SIMPLE, LEVEL_MAIN },
-	{ "edition",         "EDITION",      SIMPLE, LEVEL_MAIN },
-	{ "number",          "NUMBER",       SIMPLE, LEVEL_MAIN },
-	{ "note",            "NOTES",        SIMPLE, LEVEL_MAIN },
-	{ "annote",          "ANNOTATION",   SIMPLE, LEVEL_MAIN },
-	{ "annotation",      "ANNOTATION",   SIMPLE, LEVEL_MAIN },
-	{ "introduction",    "INTROAUTHOR",  PERSON, LEVEL_HOST },
-	{ "foreword",        "INTROAUTHOR",  PERSON, LEVEL_HOST },
-	{ "afterword",       "AFTERAUTHOR",  PERSON, LEVEL_HOST },
-	{ "bookauthor",      "AUTHOR",       PERSON, LEVEL_HOST },
-	{ "booktitle",       "TITLE",        TITLE,  LEVEL_HOST },
-	{ "booksubtitle",    "SUBTITLE",     TITLE,  LEVEL_HOST },
-	{ "booktitleaddon",  "TITLEADDON",   TITLE,  LEVEL_HOST },
-	{ "editor",          "EDITOR",       BLT_EDITOR, LEVEL_HOST },
-	{ "editora",         "EDITOR",       BLT_EDITOR, LEVEL_HOST },
-	{ "editorb",         "EDITOR",       BLT_EDITOR, LEVEL_HOST },
-	{ "editorc",         "EDITOR",       BLT_EDITOR, LEVEL_HOST },
-	{ "editortype",      "",             BLT_SKIP,   LEVEL_HOST },
-	{ "editoratype",     "",             BLT_SKIP,   LEVEL_HOST },
-	{ "editorbtype",     "",             BLT_SKIP,   LEVEL_HOST },
-	{ "editorctype",     "",             BLT_SKIP,   LEVEL_HOST },
-	{ "director",        "DIRECTOR",     PERSON, LEVEL_HOST },
-	{ "producer",        "PRODUCER",     PERSON, LEVEL_HOST },
-	{ "execproducer",    "PRODUCER",     PERSON, LEVEL_HOST },
-	{ "writer",          "AUTHOR",       PERSON, LEVEL_HOST },
-	{ "redactor",        "REDACTOR",     PERSON, LEVEL_HOST },
-	{ "annotator",       "ANNOTATOR",    PERSON, LEVEL_HOST },
-	{ "commentator",     "COMMENTATOR",  PERSON, LEVEL_HOST },
-	{ "translator",      "TRANSLATOR",   PERSON, LEVEL_HOST },
-	{ "volume",          "VOLUME",       SIMPLE, LEVEL_HOST },
-	{ "part",            "PART",         SIMPLE, LEVEL_HOST },
-	{ "volumes",         "NUMVOLUMES",   SIMPLE, LEVEL_HOST },
-	
-	{ "maintitle",       "TITLE",        TITLE,  LEVEL_SERIES },
-	{ "mainsubtitle",    "SUBTITLE",     TITLE,  LEVEL_SERIES },
-	{ "maintitleaddon",  "TITLEADDON",   TITLE,  LEVEL_SERIES },
-
-	{ "series",          "TITLE",        SIMPLE, LEVEL_SERIES+1 }, /* WRONG */
-
-	{ "origlanguage",    "LANGUAGE",     SIMPLE, LEVEL_ORIG },
-	{ "origyear",        "YEAR",         SIMPLE, LEVEL_ORIG },
-	{ "origdate",        "DATE",         SIMPLE, LEVEL_ORIG },
-	{ "origtitle",       "TITLE",        SIMPLE, LEVEL_ORIG },
-	{ "origlocation",    "ADDRESS",      SIMPLE, LEVEL_ORIG },
-	{ "origpublisher",   "PUBLISHER",    SIMPLE, LEVEL_ORIG },
-
-	{ "publisher",       "PUBLISHER",    SIMPLE, LEVEL_HOST },
-	{ "location",        "ADDRESS",      SIMPLE, LEVEL_HOST },
-	{ "isbn",            "ISBN",         SIMPLE, LEVEL_MAIN },
-	{ "chapter",         "CHAPTER",      SIMPLE, LEVEL_MAIN },
-	{ "pages",           "PAGES",        PAGES,  LEVEL_MAIN }, /* WRONG */
-	{ "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 },
-	{ "urldate",         "URLDATE",      SIMPLE, LEVEL_MAIN },
-	{ "urlday",          "?urlday?",     SIMPLE, LEVEL_MAIN },
-	{ "urlmonth",        "?urlmonth?",   SIMPLE, LEVEL_MAIN },
-	{ "urlyear",         "?urlyear?",    SIMPLE, LEVEL_MAIN },
-	{ "address",         "ADDRESS",      SIMPLE, LEVEL_MAIN },
-	{ "hyphenation",     "LANGCATALOG",            SIMPLE,      LEVEL_MAIN   },
-	{ "refnum",          "REFNUM",       SIMPLE, LEVEL_MAIN },
-	{ "",                "INTERNAL_TYPE|INCOLLECTION",    ALWAYS, LEVEL_MAIN },
-	{ "",                "RESOURCE|text",ALWAYS, LEVEL_MAIN },
-	{ "",                "ISSUANCE|monographic", ALWAYS, LEVEL_MAIN },
-	{ "",                "GENRE|collection",   ALWAYS, LEVEL_HOST }
-};
-
-/* inproceedings */
-
-static lookups inproceedings[] = {
-	{ "author",          "AUTHOR",       PERSON, LEVEL_MAIN },
-	{ "editor",          "EDITOR",       BLT_EDITOR, LEVEL_HOST },
-	{ "editora",         "EDITOR",       BLT_EDITOR, LEVEL_HOST },
-	{ "editorb",         "EDITOR",       BLT_EDITOR, LEVEL_HOST },
-	{ "editorc",         "EDITOR",       BLT_EDITOR, LEVEL_HOST },
-	{ "editortype",      "",             BLT_SKIP,   LEVEL_HOST },
-	{ "editoratype",     "",             BLT_SKIP,   LEVEL_HOST },
-	{ "editorbtype",     "",             BLT_SKIP,   LEVEL_HOST },
-	{ "editorctype",     "",             BLT_SKIP,   LEVEL_HOST },
-	{ "director",        "DIRECTOR",     PERSON, LEVEL_HOST },
-	{ "producer",        "PRODUCER",     PERSON, LEVEL_HOST },
-	{ "execproducer",    "PRODUCER",     PERSON, LEVEL_HOST },
-	{ "writer",          "AUTHOR",       PERSON, LEVEL_HOST },
-	{ "redactor",        "REDACTOR",     PERSON, LEVEL_HOST },
-	{ "annotator",       "ANNOTATOR",    PERSON, LEVEL_HOST },
-	{ "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 },
-	{ "date",            "DATE",         SIMPLE, LEVEL_MAIN },   /*WRONG*/
-	{ "introduction",    "INTROAUTHOR",  PERSON, LEVEL_HOST },
-	{ "foreword",        "INTROAUTHOR",  PERSON, LEVEL_HOST },
-	{ "afterword",       "AFTERAUTHOR",  PERSON, LEVEL_HOST },
-	{ "title",           "TITLE",        TITLE,  LEVEL_MAIN },
-	{ "subtitle",        "SUBTITLE",     TITLE,  LEVEL_MAIN },
-	{ "titleaddon",      "TITLEADDON",   TITLE,  LEVEL_MAIN },
-	{ "shorttitle",      "SHORTTITLE",   SIMPLE, LEVEL_MAIN },
-
-	{ "booktitle",       "TITLE",        TITLE,  LEVEL_HOST },
-	{ "booksubtitle",    "SUBTITLE",     TITLE,  LEVEL_HOST },
-	{ "booktitleaddon",  "TITLEADDON",   TITLE,  LEVEL_HOST },
-
-	{ "maintitle",       "TITLE",        TITLE,  LEVEL_SERIES },
-	{ "mainsubtitle",    "SUBTITLE",     TITLE,  LEVEL_SERIES },
-	{ "maintitleaddon",  "TITLEADDON",   TITLE,  LEVEL_SERIES },
-
-	{ "series",          "TITLE",        SIMPLE, LEVEL_HOST+2 },
-
-	{ "venue",           "ADDRESS",      SIMPLE, LEVEL_MAIN },
-	{ "organization",    "ORGANIZER:CORP", SIMPLE, LEVEL_MAIN },
-	{ "language",        "LANGUAGE",     SIMPLE, LEVEL_MAIN },
-	{ "origlanguage",    "LANGUAGE",     SIMPLE, LEVEL_ORIG },
-	{ "origdate",        "DATE",         SIMPLE, LEVEL_ORIG },
-	{ "origyear",        "YEAR",         SIMPLE, LEVEL_ORIG },
-	{ "origtitle",       "TITLE",        SIMPLE, LEVEL_ORIG },
-	{ "origlocation",    "ADDRESS",      SIMPLE, LEVEL_ORIG },
-	{ "origpublisher",   "PUBLISHER",    SIMPLE, LEVEL_ORIG },
-	{ "volume",          "VOLUME",       SIMPLE, LEVEL_HOST },
-	{ "part",            "PART",         SIMPLE, LEVEL_HOST },
-	{ "edition",         "EDITION",      SIMPLE, LEVEL_MAIN },
-	{ "volumes",         "NUMVOLUMES",   SIMPLE, LEVEL_HOST },
-	{ "number",          "NUMBER",       SIMPLE, LEVEL_MAIN },
-	{ "note",            "NOTES",        SIMPLE, LEVEL_MAIN },
-	{ "annote",          "ANNOTATION",   SIMPLE, LEVEL_MAIN },
-	{ "annotation",      "ANNOTATION",   SIMPLE, LEVEL_MAIN },
-	{ "publisher",       "PUBLISHER",    SIMPLE, LEVEL_HOST },
-	{ "location",        "ADDRESS",      SIMPLE, LEVEL_HOST },
-	{ "isbn",            "ISBN",         SIMPLE, LEVEL_MAIN },
-	{ "chapter",         "CHAPTER",      SIMPLE, LEVEL_MAIN },
-	{ "pages",           "PAGES",        PAGES,  LEVEL_MAIN }, /* WRONG */
-	{ "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 },
-	{ "urldate",         "URLDATE",      SIMPLE, LEVEL_MAIN },
-	{ "urlday",          "?urlday?",     SIMPLE, LEVEL_MAIN },
-	{ "urlmonth",        "?urlmonth?",   SIMPLE, LEVEL_MAIN },
-	{ "urlyear",         "?urlyear?",    SIMPLE, LEVEL_MAIN },
-	{ "address",         "ADDRESS",      SIMPLE, LEVEL_MAIN },
-	{ "hyphenation",     "LANGCATALOG",            SIMPLE,      LEVEL_MAIN   },
-	{ "refnum",          "REFNUM",       SIMPLE, LEVEL_MAIN },
-	{ "",                "INTERNAL_TYPE|INPROCEEDINGS",    ALWAYS, LEVEL_MAIN },
-	{ "",                "RESOURCE|text",ALWAYS, LEVEL_MAIN },
-	{ "",                "ISSUANCE|monographic", ALWAYS, LEVEL_MAIN },
-	{ "",                "GENRE|conference publication",   ALWAYS, LEVEL_HOST }
-};
-
-static lookups manual[] = {
-	{ "author",          "AUTHOR",       PERSON, LEVEL_MAIN },
-	{ "editor",          "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editora",         "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editorb",         "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editorc",         "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editortype",      "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "editoratype",     "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "editorbtype",     "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "editorctype",     "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "director",        "DIRECTOR",     PERSON, LEVEL_MAIN },
-	{ "producer",        "PRODUCER",     PERSON, LEVEL_MAIN },
-	{ "execproducer",    "PRODUCER",     PERSON, LEVEL_MAIN },
-	{ "writer",          "AUTHOR",       PERSON, LEVEL_MAIN },
-	{ "redactor",        "REDACTOR",     PERSON, LEVEL_MAIN },
-	{ "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 },
-	{ "date",            "DATE",         SIMPLE, LEVEL_MAIN }, /*WRONG*/
-	{ "introduction",    "INTROAUTHOR",  PERSON, LEVEL_MAIN },
-	{ "foreword",        "INTROAUTHOR",  PERSON, LEVEL_MAIN },
-	{ "afterword",       "AFTERAUTHOR",  PERSON, LEVEL_MAIN },
-	{ "title",           "TITLE",        TITLE,  LEVEL_MAIN },
-	{ "subtitle",        "SUBTITLE",     TITLE,  LEVEL_MAIN },
-	{ "titleaddon",      "TITLEADDON",   TITLE,  LEVEL_MAIN },
-	{ "shorttitle",      "SHORTTITLE",   SIMPLE, LEVEL_MAIN },
-	{ "language",        "LANGUAGE",     SIMPLE, LEVEL_MAIN },
-	{ "edition",         "EDITION",      SIMPLE, LEVEL_MAIN },
-	{ "version",         "EDITION",      SIMPLE, LEVEL_MAIN },
-	{ "type",            "GENRE",  BT_GENRE, LEVEL_MAIN },
-	{ "series",          "TITLE",        SIMPLE, LEVEL_HOST },
-	{ "number",          "NUMBER",       SIMPLE, LEVEL_MAIN },
-	{ "note",            "NOTES",        SIMPLE, LEVEL_MAIN },
-	{ "annote",          "ANNOTATION",   SIMPLE, LEVEL_MAIN },
-	{ "annotation",      "ANNOTATION",   SIMPLE, LEVEL_MAIN },
-	{ "organization",    "ORGANIZER:CORP", SIMPLE, LEVEL_MAIN },
-	{ "publisher",       "PUBLISHER",    SIMPLE, LEVEL_MAIN },
-	{ "location",        "ADDRESS",      SIMPLE, LEVEL_MAIN },
-	{ "isbn",            "ISBN",         SIMPLE, LEVEL_MAIN },
-	{ "chapter",         "CHAPTER",      SIMPLE, LEVEL_MAIN },
-	{ "pages",           "?????????",    SIMPLE, LEVEL_MAIN }, /* WRONG */
-	{ "pagetotal",       "?????????",    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 },
-	{ "urldate",         "URLDATE",      SIMPLE, LEVEL_MAIN },
-	{ "urlday",          "?????????",    SIMPLE, LEVEL_MAIN },
-	{ "urlmonth",        "?????????",    SIMPLE, LEVEL_MAIN },
-	{ "urlyear",         "?????????",    SIMPLE, LEVEL_MAIN },
-	{ "address",         "ADDRESS",      SIMPLE, LEVEL_MAIN },
-	{ "hyphenation",     "LANGCATALOG",            SIMPLE,      LEVEL_MAIN   },
-	{ "refnum",          "REFNUM",       SIMPLE, LEVEL_MAIN },
-	{ "",                "INTERNAL_TYPE|REPORT",       ALWAYS, LEVEL_MAIN },
-	{ "",                "RESOURCE|text",     ALWAYS, LEVEL_MAIN },
-	{ "",                "GENRE|instruction", ALWAYS, LEVEL_MAIN }
-};
-
-static lookups misc[] = {
-	{ "author",          "AUTHOR",       PERSON, LEVEL_MAIN },
-	{ "editor",          "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editora",         "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editorb",         "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editorc",         "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editortype",      "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "editoratype",     "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "editorbtype",     "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "editorctype",     "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "director",        "DIRECTOR",     PERSON, LEVEL_MAIN },
-	{ "producer",        "PRODUCER",     PERSON, LEVEL_MAIN },
-	{ "execproducer",    "PRODUCER",     PERSON, LEVEL_MAIN },
-	{ "writer",          "AUTHOR",       PERSON, LEVEL_MAIN },
-	{ "title",           "TITLE",        TITLE,  LEVEL_MAIN },
-	{ "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 },
-	{ "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 },
-	{ "annote",          "ANNOTATION",   SIMPLE, LEVEL_MAIN },
-	{ "annotation",      "ANNOTATION",   SIMPLE, LEVEL_MAIN },
-	{ "organization",    "ORGANIZER:CORP",SIMPLE, LEVEL_MAIN },
-	{ "publisher",       "PUBLISHER",    SIMPLE, LEVEL_MAIN },
-	{ "location",        "ADDRESS",      SIMPLE, LEVEL_MAIN },
-	{ "addendum",        "ADDENDUM",     SIMPLE, LEVEL_MAIN },
-	{ "address",         "ADDRESS",      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 },
-	{ "urldate",         "URLDATE",      SIMPLE, LEVEL_MAIN },
-	{ "urlday",          "?????????",    SIMPLE, LEVEL_MAIN },
-	{ "urlmonth",        "?????????",    SIMPLE, LEVEL_MAIN },
-	{ "urlyear",         "?????????",    SIMPLE, LEVEL_MAIN },
-	{ "hyphenation",     "LANGCATALOG",            SIMPLE,      LEVEL_MAIN   },
-	{ "refnum",          "REFNUM",       SIMPLE, LEVEL_MAIN },
-	{ "",                "INTERNAL_TYPE|MISC",       ALWAYS, LEVEL_MAIN },
-};
-
-static lookups online[] = {
-	{ "author",          "AUTHOR",       PERSON, LEVEL_MAIN },
-	{ "editor",          "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editora",         "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editorb",         "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editorc",         "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editortype",      "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "editoratype",     "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "editorbtype",     "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "editorctype",     "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "director",        "DIRECTOR",     PERSON, LEVEL_MAIN },
-	{ "producer",        "PRODUCER",     PERSON, LEVEL_MAIN },
-	{ "execproducer",    "PRODUCER",     PERSON, LEVEL_MAIN },
-	{ "writer",          "AUTHOR",       PERSON, LEVEL_MAIN },
-	{ "title",           "TITLE",        TITLE,  LEVEL_MAIN },
-	{ "subtitle",        "SUBTITLE",     TITLE,  LEVEL_MAIN },
-	{ "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 },
-	{ "language",        "LANGUAGE",     SIMPLE, LEVEL_MAIN },
-	{ "version",         "EDITION",      SIMPLE, LEVEL_MAIN },
-	{ "type",            "GENRE",  BT_GENRE, LEVEL_MAIN },
-	{ "note",            "NOTES",        SIMPLE, LEVEL_MAIN },
-	{ "annote",          "ANNOTATION",   SIMPLE, LEVEL_MAIN },
-	{ "annotation",      "ANNOTATION",   SIMPLE, LEVEL_MAIN },
-	{ "organization",    "ORGANIZER:CORP",    SIMPLE, LEVEL_MAIN },
-	{ "publisher",       "PUBLISHER",    SIMPLE, LEVEL_MAIN },
-	{ "location",        "ADDRESS",      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 },
-	{ "urldate",         "URLDATE",      SIMPLE, LEVEL_MAIN },
-	{ "urlday",          "?????????",    SIMPLE, LEVEL_MAIN },
-	{ "urlmonth",        "?????????",    SIMPLE, LEVEL_MAIN },
-	{ "urlyear",         "?????????",    SIMPLE, LEVEL_MAIN },
-	{ "address",         "ADDRESS",      SIMPLE, LEVEL_MAIN },
-	{ "hyphenation",     "LANGCATALOG",            SIMPLE,      LEVEL_MAIN   },
-	{ "refnum",          "REFNUM",       SIMPLE, LEVEL_MAIN },
-        { "",                "RESOURCE|software, multimedia",    ALWAYS, LEVEL_MAIN },
-	{ "",                "NGENRE|web page",       ALWAYS, LEVEL_MAIN },
-};
-
-static lookups patent[] = {
-	{ "author",          "AUTHOR",       PERSON, LEVEL_MAIN },
-	{ "holder",          "ASSIGNEE",     PERSON, LEVEL_MAIN },
-	{ "title",           "TITLE",        TITLE,  LEVEL_MAIN },
-	{ "subtitle",        "SUBTITLE",     TITLE,  LEVEL_MAIN },
-	{ "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 },
-	{ "version",         "EDITION",      SIMPLE, LEVEL_MAIN },
-	{ "type",            "GENRE",  BT_GENRE, LEVEL_MAIN },
-	{ "note",            "NOTES",        SIMPLE, 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 },
-	{ "urldate",         "URLDATE",      SIMPLE, LEVEL_MAIN },
-	{ "urlday",          "?????????",    SIMPLE, LEVEL_MAIN },
-	{ "urlmonth",        "?????????",    SIMPLE, LEVEL_MAIN },
-	{ "urlyear",         "?????????",    SIMPLE, LEVEL_MAIN },
-	{ "address",         "ADDRESS",      SIMPLE, LEVEL_MAIN },
-	{ "hyphenation",     "LANGCATALOG",            SIMPLE,      LEVEL_MAIN   },
-	{ "pubstate",        "PUBSTATE",     SIMPLE, LEVEL_MAIN },
-	{ "refnum",          "REFNUM",       SIMPLE, LEVEL_MAIN },
-	{ "",                "RESOURCE|text",   ALWAYS, LEVEL_MAIN },
-	{ "",                "INTERNAL_TYPE|PATENT",    ALWAYS, LEVEL_MAIN },
-	{ "",                "GENRE|patent",    ALWAYS, LEVEL_MAIN },
-};
-
-/*
- * An entire issue of a periodical
- *
- * "The title of the periodical is given in the title field. If the issue has 
- * its own title in addition to the main title of the periodical, it goes in 
- * the issuetitle field. The editor is omissible..."
- */
-static lookups periodical[] = {
-	{ "editor",          "EDITOR",              BLT_EDITOR, LEVEL_MAIN   },
-	{ "editora",         "EDITOR",              BLT_EDITOR, LEVEL_MAIN   },
-	{ "editorb",         "EDITOR",              BLT_EDITOR, LEVEL_MAIN   },
-	{ "editorc",         "EDITOR",              BLT_EDITOR, LEVEL_MAIN   },
-	{ "editortype",      "",                    BLT_SKIP,   LEVEL_MAIN   },
-	{ "editoratype",     "",                    BLT_SKIP,   LEVEL_MAIN   },
-	{ "editorbtype",     "",                    BLT_SKIP,   LEVEL_MAIN   },
-	{ "editorctype",     "",                    BLT_SKIP,   LEVEL_MAIN   },
-	{ "director",        "DIRECTOR",            PERSON,     LEVEL_MAIN   },
-	{ "producer",        "PRODUCER",            PERSON,     LEVEL_MAIN   },
-	{ "execproducer",    "PRODUCER",            PERSON,     LEVEL_MAIN   },
-	{ "writer",          "AUTHOR",              PERSON,     LEVEL_MAIN   },
-	{ "title",           "TITLE",               TITLE,      LEVEL_HOST   },
-	{ "subtitle",        "SUBTITLE",            TITLE,      LEVEL_HOST   },
-	{ "titleaddon",      "TITLEADDON",          TITLE,      LEVEL_HOST   },
-	{ "shorttitle",      "SHORTTITLE",          SIMPLE,     LEVEL_HOST   },
-	{ "issuetitle",      "TITLE",               TITLE,      LEVEL_MAIN   },
-	{ "issuesubtitle",   "SUBTITLE",            TITLE,      LEVEL_MAIN   },
-	{ "issuetitleaddon", "TITLEADDON",          TITLE,      LEVEL_MAIN   },
-	{ "series",          "TITLE",               SIMPLE,     LEVEL_SERIES },
-	{ "volume",          "VOLUME",              SIMPLE,     LEVEL_MAIN   },
-	{ "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   },
-	{ "pages",           "PAGES",               PAGES,      LEVEL_MAIN   },
-	{ "note",            "NOTES",               SIMPLE,     LEVEL_MAIN   },
-	{ "annote",          "ANNOTATION",          SIMPLE,     LEVEL_MAIN   },
-	{ "annotation",      "ANNOTATION",          SIMPLE,     LEVEL_MAIN   },
-	{ "issn",            "ISSN",                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   },
-	{ "urldate",         "URLDATE",             SIMPLE,     LEVEL_MAIN   },
-	{ "urlday",          "?????",               SIMPLE,     LEVEL_MAIN   }, /* WRONG */
-	{ "urlmonth",        "?????",               SIMPLE,     LEVEL_MAIN   }, /* WRONG */
-	{ "urlyear",         "?????",               SIMPLE,     LEVEL_MAIN   }, /* WRONG */
-	{ "address",         "ADDRESS",             SIMPLE,     LEVEL_MAIN   },
-	{ "hyphenation",     "LANGCATALOG",            SIMPLE,      LEVEL_MAIN   },
-	{ "refnum",          "REFNUM",              SIMPLE,     LEVEL_MAIN   },
-	{ "",                "ISSUANCE|continuing", ALWAYS,     LEVEL_HOST   },
-	{ "",                "RESOURCE|text",       ALWAYS,     LEVEL_MAIN   },
-	{ "",                "GENRE|issue",         ALWAYS,     LEVEL_MAIN   },
-	{ "",                "GENRE|periodical",    ALWAYS,     LEVEL_HOST   }
-};
-
-static lookups proceedings[] = {
-	{ "editor",          "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editora",         "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editorb",         "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editorc",         "EDITOR",       BLT_EDITOR, LEVEL_MAIN },
-	{ "editortype",      "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "editoratype",     "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "editorbtype",     "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "editorctype",     "",             BLT_SKIP,   LEVEL_MAIN },
-	{ "director",        "DIRECTOR",     PERSON, LEVEL_MAIN },
-	{ "producer",        "PRODUCER",     PERSON, LEVEL_MAIN },
-	{ "execproducer",    "PRODUCER",     PERSON, LEVEL_MAIN },
-	{ "writer",          "AUTHOR",       PERSON, LEVEL_MAIN },
-	{ "redactor",        "REDACTOR",     PERSON, LEVEL_MAIN },
-	{ "annotator",       "ANNOTATOR",    PERSON, LEVEL_MAIN },
-	{ "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 },
-	{ "date",            "DATE",         SIMPLE, LEVEL_MAIN },   /*WRONG*/
-	{ "introduction",    "INTROAUTHOR",  PERSON, LEVEL_MAIN },
-	{ "foreword",        "INTROAUTHOR",  PERSON, LEVEL_MAIN },
-	{ "afterword",       "AFTERAUTHOR",  PERSON, LEVEL_MAIN },
-	{ "title",           "TITLE",        TITLE,  LEVEL_MAIN },
-	{ "subtitle",        "SUBTITLE",     TITLE,  LEVEL_MAIN },
-	{ "titleaddon",      "TITLEADDON",   TITLE,  LEVEL_MAIN },
-	{ "shorttitle",      "SHORTTITLE",   SIMPLE, LEVEL_MAIN },
-	{ "maintitle",       "TITLE",        TITLE,  LEVEL_HOST },
-	{ "mainsubtitle",    "SUBTITLE",     TITLE,  LEVEL_HOST },
-	{ "maintitleaddon",  "TITLEADDON",   TITLE,  LEVEL_HOST },
-	{ "language",        "LANGUAGE",     SIMPLE, LEVEL_MAIN },
-	{ "origlanguage",    "LANGUAGE",     SIMPLE, LEVEL_ORIG },
-	{ "origdate",        "DATE",         SIMPLE, LEVEL_ORIG },
-	{ "origyear",        "YEAR",         SIMPLE, LEVEL_ORIG },
-	{ "origtitle",       "TITLE",        SIMPLE, LEVEL_ORIG },
-	{ "origlocation",    "ADDRESS",      SIMPLE, LEVEL_ORIG },
-	{ "origpublisher",   "PUBLISHER",    SIMPLE, LEVEL_ORIG },
-	{ "volume",          "VOLUME",       SIMPLE, LEVEL_HOST },
-	{ "part",            "PART",         SIMPLE, LEVEL_HOST },
-	{ "edition",         "EDITION",      SIMPLE, LEVEL_MAIN },
-	{ "volumes",         "NUMVOLUMES",   SIMPLE, LEVEL_HOST },
-	{ "series",          "?????",        SIMPLE, LEVEL_HOST }, /* WRONG */
-	{ "number",          "NUMBER",       SIMPLE, LEVEL_MAIN },
-	{ "note",            "NOTES",        SIMPLE, LEVEL_MAIN },
-	{ "annote",          "ANNOTATION",   SIMPLE, LEVEL_MAIN },
-	{ "annotation",      "ANNOTATION",   SIMPLE, LEVEL_MAIN },
-	{ "organization",    "ORGANIZER:CORP",SIMPLE, LEVEL_MAIN },
-	{ "publisher",       "PUBLISHER",    SIMPLE, LEVEL_MAIN },
-	{ "location",        "ADDRESS",      SIMPLE, LEVEL_MAIN },
-	{ "isbn",            "ISBN",         SIMPLE, LEVEL_MAIN },
-	{ "chapter",         "CHAPTER",      SIMPLE, LEVEL_MAIN },
-	{ "pages",           "?????????",    SIMPLE, LEVEL_MAIN }, /* WRONG */
-	{ "pagetotal",       "?????????",    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 },
-	{ "urldate",         "URLDATE",      SIMPLE, LEVEL_MAIN },
-	{ "urlday",          "?????????",    SIMPLE, LEVEL_MAIN },
-	{ "urlmonth",        "?????????",    SIMPLE, LEVEL_MAIN },
-	{ "urlyear",         "?????????",    SIMPLE, LEVEL_MAIN },
-	{ "address",         "ADDRESS",      SIMPLE, LEVEL_MAIN },
-	{ "hyphenation",     "LANGCATALOG",            SIMPLE,      LEVEL_MAIN   },
-	{ "refnum",          "REFNUM",       SIMPLE, LEVEL_MAIN },
-	{ "",                "INTERNAL_TYPE|BOOK",    ALWAYS, LEVEL_MAIN },
-        { "",                "RESOURCE|text",       ALWAYS, LEVEL_MAIN },
-        { "",                "GENRE|conference publication",   ALWAYS, LEVEL_MAIN }
-};
-
-/* Technical reports */
-static lookups report[] = {
-	{ "author",      "AUTHOR",               PERSON,        LEVEL_MAIN },
-	{ "title",       "TITLE",                TITLE,         LEVEL_MAIN },
-	{ "subtitle",    "SUBTITLE",             TITLE,         LEVEL_MAIN },
-	{ "titleaddon",  "TITLEADDON",           TITLE,         LEVEL_MAIN },
-	{ "shorttitle",  "SHORTTITLE",           SIMPLE,        LEVEL_MAIN },
-	{ "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 },
-	{ "date",        "DATE",                 SIMPLE,        LEVEL_MAIN },   /*WRONG*/
-	{ "language",    "LANGUAGE",             SIMPLE,        LEVEL_MAIN },
-	{ "number",      "REPORTNUMBER",         SIMPLE,        LEVEL_MAIN },
-	{ "note",        "NOTES",                SIMPLE,        LEVEL_MAIN },
-	{ "annote",      "ANNOTATION",           SIMPLE,        LEVEL_MAIN },
-	{ "annotation",  "ANNOTATION",           SIMPLE,        LEVEL_MAIN },
-	{ "version",     "EDITION",              SIMPLE,        LEVEL_MAIN },
-	{ "location",    "ADDRESS",              SIMPLE,        LEVEL_MAIN },
-	{ "isrn",        "ISRN",                 SIMPLE,        LEVEL_MAIN },
-	{ "chapter",     "CHAPTER",              SIMPLE,        LEVEL_MAIN },
-	{ "pages",       "?????????",            SIMPLE,        LEVEL_MAIN }, /* WRONG */
-	{ "pagetotal",   "?????????",            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 },
-	{ "urldate",     "URLDATE",              SIMPLE,        LEVEL_MAIN },
-	{ "urlday",      "?????????",            SIMPLE,        LEVEL_MAIN },
-	{ "urlmonth",    "?????????",            SIMPLE,        LEVEL_MAIN },
-	{ "urlyear",     "?????????",            SIMPLE,        LEVEL_MAIN },
-	{ "address",     "ADDRESS",              SIMPLE,        LEVEL_MAIN },
-	{ "hyphenation", "LANGCATALOG",          SIMPLE,        LEVEL_MAIN },
-	{ "refnum",      "REFNUM",               SIMPLE,        LEVEL_MAIN },
-	{ "",            "INTERNAL_TYPE|REPORT", ALWAYS,        LEVEL_MAIN },
-	{ "",            "RESOURCE|text",        ALWAYS,        LEVEL_MAIN },
-	{ "",            "GENRE|report",         ALWAYS,        LEVEL_MAIN }
-};
-
-/* Unpublished */
-static lookups unpublished[] = {
-	{ "author",       "AUTHOR",       PERSON, LEVEL_MAIN },
-	{ "title",        "TITLE",        TITLE,  LEVEL_MAIN },
-	{ "subtitle",     "SUBTITLE",     TITLE,  LEVEL_MAIN },
-	{ "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 },
-	{ "date",         "DATE",         SIMPLE, LEVEL_MAIN },
-	{ "url",          "",         BT_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 },
-	{ "annote",       "ANNOTATION",   SIMPLE, LEVEL_MAIN },
-	{ "annotation",   "ANNOTATION",   SIMPLE, LEVEL_MAIN },
-	{ "addendum",     "ADDENDUM",     SIMPLE, LEVEL_MAIN },
-	{ "address",      "ADDRESS",      SIMPLE, LEVEL_MAIN },
-	{ "hyphenation",  "LANGCATALOG",  SIMPLE, LEVEL_MAIN   },
-	{ "pubstate",     "PUBSTATE",     SIMPLE, LEVEL_MAIN },
-	{ "refnum",       "REFNUM",       SIMPLE, LEVEL_MAIN },
-	{ "",             "INTERNAL_TYPE|BOOK",    ALWAYS, LEVEL_MAIN },
-	{ "",             "RESOURCE|text",ALWAYS, LEVEL_MAIN },
-	{ "",             "GENRE|unpublished",ALWAYS, LEVEL_MAIN }
-};
-
-static lookups thesis[] = {
-	{ "author",       "AUTHOR",               PERSON,          LEVEL_MAIN },
-	{ "title",        "TITLE",                TITLE,           LEVEL_MAIN },
-	{ "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 },
-	{ "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 },
-	{ "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 },
-	{ "annote",       "ANNOTATION",           SIMPLE,          LEVEL_MAIN },
-	{ "annotation",   "ANNOTATION",           SIMPLE,          LEVEL_MAIN },
-	{ "address",      "ADDRESS",              SIMPLE,          LEVEL_MAIN },
-	{ "hyphenation",  "LANGCATALOG",          SIMPLE,          LEVEL_MAIN },
-	{ "pubstate",     "PUBSTATE",             SIMPLE,          LEVEL_MAIN },
-	{ "refnum",       "REFNUM",               SIMPLE,          LEVEL_MAIN },
-	{ "",             "INTERNAL_TYPE|THESIS", ALWAYS,          LEVEL_MAIN },
-	{ "",             "RESOURCE|text",        ALWAYS,          LEVEL_MAIN },
-	{ "",             "GENRE|thesis",         ALWAYS,          LEVEL_MAIN },
-};
-
-static lookups phdthesis[] = {
-	{ "author",       "AUTHOR",               PERSON,          LEVEL_MAIN },
-	{ "title",        "TITLE",                TITLE,           LEVEL_MAIN },
-	{ "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 },
-	{ "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 },
-	{ "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 },
-	{ "annote",       "ANNOTATION",           SIMPLE,          LEVEL_MAIN },
-	{ "annotation",   "ANNOTATION",           SIMPLE,          LEVEL_MAIN },
-	{ "address",      "ADDRESS",              SIMPLE,          LEVEL_MAIN },
-	{ "hyphenation",  "LANGCATALOG",          SIMPLE,          LEVEL_MAIN },
-	{ "pubstate",     "PUBSTATE",             SIMPLE,          LEVEL_MAIN },
-	{ "refnum",       "REFNUM",               SIMPLE,          LEVEL_MAIN },
-	{ "",             "INTERNAL_TYPE|THESIS", ALWAYS,          LEVEL_MAIN },
-	{ "",             "RESOURCE|text",        ALWAYS,          LEVEL_MAIN },
-	{ "",             "GENRE|thesis",         ALWAYS,          LEVEL_MAIN },
-	{ "",             "NGENRE|Ph.D. thesis",  DEFAULT,         LEVEL_MAIN },
-};
-
-static lookups mastersthesis[] = {
-	{ "author",       "AUTHOR",                PERSON,          LEVEL_MAIN },
-	{ "title",        "TITLE",                 TITLE,           LEVEL_MAIN },
-	{ "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 },
-	{ "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 },
-	{ "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 },
-	{ "annote",       "ANNOTATION",            SIMPLE,          LEVEL_MAIN },
-	{ "annotation",   "ANNOTATION",            SIMPLE,          LEVEL_MAIN },
-	{ "address",      "ADDRESS",               SIMPLE,          LEVEL_MAIN },
-	{ "hyphenation",  "LANGCATALOG",           SIMPLE,          LEVEL_MAIN },
-	{ "pubstate",     "PUBSTATE",              SIMPLE,          LEVEL_MAIN },
-	{ "refnum",       "REFNUM",                SIMPLE,          LEVEL_MAIN },
-	{ "",             "INTERNAL_TYPE|THESIS",  ALWAYS,          LEVEL_MAIN },
-	{ "",             "RESOURCE|text",         ALWAYS,          LEVEL_MAIN },
-	{ "",             "GENRE|thesis",          ALWAYS,          LEVEL_MAIN },
-	{ "",             "NGENRE|Masters thesis", DEFAULT,         LEVEL_MAIN },
-};
-
-#define ORIG(a) ( &(a[0]) )
-#define SIZE(a) ( sizeof( a ) / sizeof( lookups ) )
-#define REFTYPE(a,b) { a, ORIG(b), SIZE(b) }
-
-variants biblatex_all[] = {
-	REFTYPE( "article", article ),
-	REFTYPE( "booklet", booklet ),
-	REFTYPE( "book", book ),
-	REFTYPE( "collection", collection ),
-	REFTYPE( "inbook", inbook ),
-	REFTYPE( "incollection", incollection ),
-	REFTYPE( "inproceedings", inproceedings ),
-	REFTYPE( "conference", inproceedings ), /* legacy */
-	REFTYPE( "manual", manual ),
-	REFTYPE( "misc", misc ),
-	REFTYPE( "online", online ),
-	REFTYPE( "electronic", online ), /* legacy */
-	REFTYPE( "www", online ),        /* jurabib compatibility */
-	REFTYPE( "patent", patent ),
-	REFTYPE( "periodical", periodical ),
-	REFTYPE( "proceedings", proceedings ),
+	{ "author",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "editor",          "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editora",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editorb",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editorc",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editortype",      "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editoratype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editorbtype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editorctype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "director",        "DIRECTOR",               PERSON,          LEVEL_MAIN   },
+	{ "producer",        "PRODUCER",               PERSON,          LEVEL_MAIN   },
+	{ "execproducer",    "PRODUCER",               PERSON,          LEVEL_MAIN   },
+	{ "writer",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "redactor",        "REDACTOR",               PERSON,          LEVEL_MAIN   },
+	{ "annotator",       "ANNOTATOR",              PERSON,          LEVEL_MAIN   },
+	{ "commentator",     "COMMENTATOR",            PERSON,          LEVEL_MAIN   },
+	{ "translator",      "TRANSLATOR",             PERSON,          LEVEL_MAIN   },
+	{ "title",           "TITLE",                  TITLE,           LEVEL_MAIN   },
+	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   },
+	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   },
+	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   },
+	{ "journal",         "TITLE",                  TITLE,           LEVEL_HOST   },
+	{ "journaltitle",    "TITLE",                  TITLE,           LEVEL_HOST   },
+	{ "journalsubtitle", "SUBTITLE",               TITLE,           LEVEL_HOST   },
+	{ "shortjournal",    "SHORTTITLE",             SIMPLE,          LEVEL_HOST   },
+	{ "issuetitle",      "TITLE",                  TITLE,           LEVEL_SERIES }, /*WRONG*/
+	{ "issuesubtitle",   "SUBTITLE",               TITLE,           LEVEL_SERIES }, /*WRONG*/
+	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
+	{ "origlanguage",    "LANGUAGE",               SIMPLE,          LEVEL_ORIG   },
+	{ "origyear",        "YEAR",                   SIMPLE,          LEVEL_ORIG   },
+	{ "origdate",        "DATE",                   SIMPLE,          LEVEL_ORIG   },
+	{ "origtitle",       "TITLE",                  SIMPLE,          LEVEL_ORIG   },
+	{ "origlocation",    "ADDRESS",                SIMPLE,          LEVEL_ORIG   },
+	{ "origpublisher",   "PUBLISHER",              SIMPLE,          LEVEL_ORIG   },
+	{ "series",          "PARTTITLE",              SIMPLE,          LEVEL_HOST   },
+	{ "volume",          "VOLUME",                 SIMPLE,          LEVEL_MAIN   },
+	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },
+	{ "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   },
+	{ "pages",           "PAGES",                  PAGES,           LEVEL_MAIN   },
+	{ "version",         "EDITION",                SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "issn",            "ISSN",                   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   },
+	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
+	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   }, /* WRONG */
+	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   }, /* WRONG */
+	{ "urlyear",         "?urlyear?",              SIMPLE,          LEVEL_MAIN   }, /* WRONG */
+	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "refnum",          "REFNUM",                 SIMPLE,          LEVEL_MAIN   },
+	{ "hyphenation",     "LANGCATALOG",            SIMPLE,          LEVEL_MAIN   },
+	{ "entrysubtype",    "",                       BLT_SUBTYPE,     LEVEL_MAIN   },
+	{ "",                "INTERNAL_TYPE|ARTICLE",  ALWAYS,          LEVEL_MAIN   },
+	{ "",                "ISSUANCE|continuing",    ALWAYS,          LEVEL_HOST   },
+	{ "",                "RESOURCE|text",          ALWAYS,          LEVEL_MAIN   },
+	{ "",                "NGENRE|journal article", DEFAULT,         LEVEL_MAIN   },
+	{ "",                "GENRE|periodical",       DEFAULT,         LEVEL_HOST   }
+};
+
+/* Book */
+
+static lookups book[] = {
+	{ "author",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "editor",          "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editora",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editorb",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editorc",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editortype",      "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editoratype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editorbtype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editorctype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "director",        "DIRECTOR",               PERSON,          LEVEL_MAIN   },
+	{ "producer",        "PRODUCER",               PERSON,          LEVEL_MAIN   },
+	{ "execproducer",    "PRODUCER",               PERSON,          LEVEL_MAIN   },
+	{ "writer",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "redactor",        "REDACTOR",               PERSON,          LEVEL_MAIN   },
+	{ "annotator",       "ANNOTATOR",              PERSON,          LEVEL_MAIN   },
+	{ "commentator",     "COMMENTATOR",            PERSON,          LEVEL_MAIN   },
+	{ "translator",      "TRANSLATOR",             PERSON,          LEVEL_MAIN   },
+	{ "introduction",    "INTROAUTHOR",            PERSON,          LEVEL_MAIN   },
+	{ "foreword",        "INTROAUTHOR",            PERSON,          LEVEL_MAIN   },
+	{ "afterword",       "AFTERAUTHOR",            PERSON,          LEVEL_MAIN   },
+	{ "title",           "TITLE",                  TITLE,           LEVEL_MAIN   },
+	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   },
+	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   },
+	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   },
+	{ "maintitle",       "TITLE",                  TITLE,           LEVEL_HOST   },
+	{ "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   },
+	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/
+	{ "origlanguage",    "LANGUAGE",               SIMPLE,          LEVEL_ORIG   },
+	{ "origyear",        "YEAR",                   SIMPLE,          LEVEL_ORIG   },
+	{ "origdate",        "DATE",                   SIMPLE,          LEVEL_ORIG   },
+	{ "origtitle",       "TITLE",                  SIMPLE,          LEVEL_ORIG   },
+	{ "origlocation",    "ADDRESS",                SIMPLE,          LEVEL_ORIG   },
+	{ "origpublisher",   "PUBLISHER",              SIMPLE,          LEVEL_ORIG   },
+	{ "volume",          "VOLUME",                 SIMPLE,          LEVEL_HOST   },
+	{ "part",            "PART",                   SIMPLE,          LEVEL_HOST   },
+	{ "edition",         "EDITION",                SIMPLE,          LEVEL_MAIN   },
+	{ "volumes",         "NUMVOLUMES",             SIMPLE,          LEVEL_HOST   },
+	{ "series",          "TITLE",                  SIMPLE,          LEVEL_HOST   }, /* WRONG */
+	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "publisher",       "PUBLISHER",              SIMPLE,          LEVEL_MAIN   },
+	{ "location",        "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "isbn",            "ISBN",                   SIMPLE,          LEVEL_MAIN   },
+	{ "chapter",         "CHAPTER",                SIMPLE,          LEVEL_MAIN   },
+	{ "pages",           "PAGES",                  PAGES,           LEVEL_MAIN   }, /* WRONG */
+	{ "pagetotal",       "TOTALPAGES",             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   },
+	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
+	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   },
+	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   },
+	{ "urlyear",         "?urlyear?",              SIMPLE,          LEVEL_MAIN   },
+	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "hyphenation",     "LANGCATALOG",            SIMPLE,          LEVEL_MAIN   },
+	{ "refnum",          "REFNUM",                 SIMPLE,          LEVEL_MAIN   },
+	{ "",                "INTERNAL_TYPE|BOOK",     ALWAYS,          LEVEL_MAIN   },
+	{ "",                "RESOURCE|text",          ALWAYS,          LEVEL_MAIN   },
+	{ "",                "ISSUANCE|monographic",   ALWAYS,          LEVEL_MAIN   },
+	{ "",                "GENRE|book",             ALWAYS,          LEVEL_MAIN   }
+};
+
+/* Booklet */
+
+static lookups booklet[] = {
+	{ "author",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "editor",          "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editora",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editorb",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editorc",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editortype",      "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editoratype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editorbtype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editorctype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "director",        "DIRECTOR",               PERSON,          LEVEL_MAIN   },
+	{ "producer",        "PRODUCER",               PERSON,          LEVEL_MAIN   },
+	{ "execproducer",    "PRODUCER",               PERSON,          LEVEL_MAIN   },
+	{ "writer",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "title",           "TITLE",                  TITLE,           LEVEL_MAIN   },
+	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   },
+	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   },
+	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   },
+	{ "howpublished",    "",                       HOWPUBLISHED,    LEVEL_MAIN   },
+	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },
+	{ "month",           "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   },
+	{ "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   },
+	{ "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   },
+	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
+	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   },
+	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   },
+	{ "urlyear",         "?urlyear?",              SIMPLE,          LEVEL_MAIN   },
+	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "hyphenation",     "LANGCATALOG",            SIMPLE,          LEVEL_MAIN   },
+	{ "refnum",          "REFNUM",                 SIMPLE,          LEVEL_MAIN   },
+	{ "",                "INTERNAL_TYPE|BOOK",     ALWAYS,          LEVEL_MAIN   },
+	{ "",                "RESOURCE|text",          ALWAYS,          LEVEL_MAIN   },
+	{ "",                "ISSUANCE|monographic",   ALWAYS,          LEVEL_MAIN   },
+	{ "",                "GENRE|book",             ALWAYS,          LEVEL_MAIN   }
+};
+
+static lookups collection[] = {
+	{ "editor",          "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editora",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editorb",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editorc",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editortype",      "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editoratype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editorbtype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editorctype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "director",        "DIRECTOR",               PERSON,          LEVEL_MAIN   },
+	{ "producer",        "PRODUCER",               PERSON,          LEVEL_MAIN   },
+	{ "execproducer",    "PRODUCER",               PERSON,          LEVEL_MAIN   },
+	{ "writer",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "redactor",        "REDACTOR",               PERSON,          LEVEL_MAIN   },
+	{ "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   },
+	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/
+	{ "introduction",    "INTROAUTHOR",            PERSON,          LEVEL_MAIN   },
+	{ "foreword",        "INTROAUTHOR",            PERSON,          LEVEL_MAIN   },
+	{ "afterword",       "AFTERAUTHOR",            PERSON,          LEVEL_MAIN   },
+	{ "title",           "TITLE",                  TITLE,           LEVEL_MAIN   },
+	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   },
+	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   },
+	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   },
+	{ "maintitle",       "TITLE",                  TITLE,           LEVEL_HOST   },
+	{ "mainsubtitle",    "SUBTITLE",               TITLE,           LEVEL_HOST   },
+	{ "maintitleaddon",  "TITLEADDON",             TITLE,           LEVEL_HOST   },
+	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
+	{ "origlanguage",    "LANGUAGE",               SIMPLE,          LEVEL_ORIG   },
+	{ "origyear",        "YEAR",                   SIMPLE,          LEVEL_ORIG   },
+	{ "origdate",        "DATE",                   SIMPLE,          LEVEL_ORIG   },
+	{ "origtitle",       "TITLE",                  SIMPLE,          LEVEL_ORIG   },
+	{ "origlocation",    "ADDRESS",                SIMPLE,          LEVEL_ORIG   },
+	{ "origpublisher",   "PUBLISHER",              SIMPLE,          LEVEL_ORIG   },
+	{ "volume",          "VOLUME",                 SIMPLE,          LEVEL_HOST   },
+	{ "part",            "PART",                   SIMPLE,          LEVEL_HOST   },
+	{ "edition",         "EDITION",                SIMPLE,          LEVEL_MAIN   },
+	{ "volumes",         "NUMVOLUMES",             SIMPLE,          LEVEL_HOST   },
+	{ "series",          "TITLE",                  SIMPLE,          LEVEL_HOST   },
+	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "publisher",       "PUBLISHER",              SIMPLE,          LEVEL_MAIN   },
+	{ "location",        "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "isbn",            "ISBN",                   SIMPLE,          LEVEL_MAIN   },
+	{ "chapter",         "CHAPTER",                SIMPLE,          LEVEL_MAIN   },
+	{ "pages",           "PAGES",                  PAGES,           LEVEL_MAIN   },
+	{ "pagetotal",       "TOTALPAGES",             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   },
+	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
+	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   },
+	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   },
+	{ "urlyear",         "?urlyear?",              SIMPLE,          LEVEL_MAIN   },
+	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "hyphenation",     "LANGCATALOG",            SIMPLE,          LEVEL_MAIN   },
+	{ "refnum",          "REFNUM",                 SIMPLE,          LEVEL_MAIN   },
+	{ "",                "INTERNAL_TYPE|BOOK",     ALWAYS,          LEVEL_MAIN   },
+	{ "",                "RESOURCE|text",          ALWAYS,          LEVEL_MAIN   },
+	{ "",                "ISSUANCE|monographic",   ALWAYS,          LEVEL_MAIN   },
+	{ "",                "GENRE|book",             ALWAYS,          LEVEL_MAIN   }
+};
+
+/* Part of a book (e.g. chapter or section) */
+
+static lookups inbook[] = {
+	{ "author",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "editor",          "EDITOR",                 BLT_EDITOR,      LEVEL_HOST   },
+	{ "editora",         "EDITOR",                 BLT_EDITOR,      LEVEL_HOST   },
+	{ "editorb",         "EDITOR",                 BLT_EDITOR,      LEVEL_HOST   },
+	{ "editorc",         "EDITOR",                 BLT_EDITOR,      LEVEL_HOST   },
+	{ "editortype",      "",                       BLT_SKIP,        LEVEL_HOST   },
+	{ "editoratype",     "",                       BLT_SKIP,        LEVEL_HOST   },
+	{ "editorbtype",     "",                       BLT_SKIP,        LEVEL_HOST   },
+	{ "editorctype",     "",                       BLT_SKIP,        LEVEL_HOST   },
+	{ "director",        "DIRECTOR",               PERSON,          LEVEL_HOST   },
+	{ "producer",        "PRODUCER",               PERSON,          LEVEL_HOST   },
+	{ "execproducer",    "PRODUCER",               PERSON,          LEVEL_HOST   },
+	{ "writer",          "AUTHOR",                 PERSON,          LEVEL_HOST   },
+	{ "redactor",        "REDACTOR",               PERSON,          LEVEL_HOST   },
+	{ "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   },
+	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/
+	{ "introduction",    "INTROAUTHOR",            PERSON,          LEVEL_HOST   },
+	{ "foreword",        "INTROAUTHOR",            PERSON,          LEVEL_HOST   },
+	{ "afterword",       "AFTERAUTHOR",            PERSON,          LEVEL_HOST   },
+	{ "title",           "TITLE",                  TITLE,           LEVEL_MAIN   },
+	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   },
+	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   },
+	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   },
+	{ "booktitle",       "TITLE",                  TITLE,           LEVEL_HOST   },
+	{ "booksubtitle",    "SUBTITLE",               TITLE,           LEVEL_HOST   },
+	{ "booktitleaddon",  "TITLEADDON",             TITLE,           LEVEL_HOST   },
+	{ "bookauthor",      "AUTHOR",                 PERSON,          LEVEL_HOST   },
+	{ "maintitle",       "TITLE",                  TITLE,           LEVEL_SERIES },
+	{ "mainsubtitle",    "SUBTITLE",               TITLE,           LEVEL_SERIES },
+	{ "maintitleaddon",  "TITLEADDON",             TITLE,           LEVEL_SERIES },
+	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
+	{ "origlanguage",    "LANGUAGE",               SIMPLE,          LEVEL_ORIG   },
+	{ "origyear",        "YEAR",                   SIMPLE,          LEVEL_ORIG   },
+	{ "origdate",        "DATE",                   SIMPLE,          LEVEL_ORIG   },
+	{ "origtitle",       "TITLE",                  SIMPLE,          LEVEL_ORIG   },
+	{ "origlocation",    "ADDRESS",                SIMPLE,          LEVEL_ORIG   },
+	{ "origpublisher",   "PUBLISHER",              SIMPLE,          LEVEL_ORIG   },
+	{ "volume",          "VOLUME",                 SIMPLE,          LEVEL_MAIN   },
+	{ "pages",           "PAGES",                  PAGES,           LEVEL_MAIN   },
+	{ "part",            "PART",                   SIMPLE,          LEVEL_HOST   },
+	{ "edition",         "EDITION",                SIMPLE,          LEVEL_MAIN   },
+	{ "volumes",         "NUMVOLUMES",             SIMPLE,          LEVEL_HOST   },
+	{ "series",          "TITLE",                  SIMPLE,          LEVEL_SERIES+1 }, /* WRONG */
+	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "publisher",       "PUBLISHER",              SIMPLE,          LEVEL_MAIN   },
+	{ "location",        "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "isbn",            "ISBN",                   SIMPLE,          LEVEL_HOST   },
+	{ "chapter",         "CHAPTER",                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   },
+	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
+	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   },
+	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   },
+	{ "urlyear",         "?urlyear?",              SIMPLE,          LEVEL_MAIN   },
+	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "hyphenation",     "LANGCATALOG",            SIMPLE,          LEVEL_MAIN   },
+	{ "refnum",          "REFNUM",                 SIMPLE,          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   }
+};
+
+/* incollection */
+
+static lookups incollection[] = {
+	{ "author",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },
+	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },
+	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/
+	{ "title",           "TITLE",                  TITLE,           LEVEL_MAIN   },
+	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   },
+	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   },
+	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   },
+	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
+	{ "edition",         "EDITION",                SIMPLE,          LEVEL_MAIN   },
+	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "introduction",    "INTROAUTHOR",            PERSON,          LEVEL_HOST   },
+	{ "foreword",        "INTROAUTHOR",            PERSON,          LEVEL_HOST   },
+	{ "afterword",       "AFTERAUTHOR",            PERSON,          LEVEL_HOST   },
+	{ "bookauthor",      "AUTHOR",                 PERSON,          LEVEL_HOST   },
+	{ "booktitle",       "TITLE",                  TITLE,           LEVEL_HOST   },
+	{ "booksubtitle",    "SUBTITLE",               TITLE,           LEVEL_HOST   },
+	{ "booktitleaddon",  "TITLEADDON",             TITLE,           LEVEL_HOST   },
+	{ "editor",          "EDITOR",                 BLT_EDITOR,      LEVEL_HOST   },
+	{ "editora",         "EDITOR",                 BLT_EDITOR,      LEVEL_HOST   },
+	{ "editorb",         "EDITOR",                 BLT_EDITOR,      LEVEL_HOST   },
+	{ "editorc",         "EDITOR",                 BLT_EDITOR,      LEVEL_HOST   },
+	{ "editortype",      "",                       BLT_SKIP,        LEVEL_HOST   },
+	{ "editoratype",     "",                       BLT_SKIP,        LEVEL_HOST   },
+	{ "editorbtype",     "",                       BLT_SKIP,        LEVEL_HOST   },
+	{ "editorctype",     "",                       BLT_SKIP,        LEVEL_HOST   },
+	{ "director",        "DIRECTOR",               PERSON,          LEVEL_HOST   },
+	{ "producer",        "PRODUCER",               PERSON,          LEVEL_HOST   },
+	{ "execproducer",    "PRODUCER",               PERSON,          LEVEL_HOST   },
+	{ "writer",          "AUTHOR",                 PERSON,          LEVEL_HOST   },
+	{ "redactor",        "REDACTOR",               PERSON,          LEVEL_HOST   },
+	{ "annotator",       "ANNOTATOR",              PERSON,          LEVEL_HOST   },
+	{ "commentator",     "COMMENTATOR",            PERSON,          LEVEL_HOST   },
+	{ "translator",      "TRANSLATOR",             PERSON,          LEVEL_HOST   },
+	{ "volume",          "VOLUME",                 SIMPLE,          LEVEL_HOST   },
+	{ "part",            "PART",                   SIMPLE,          LEVEL_HOST   },
+	{ "volumes",         "NUMVOLUMES",             SIMPLE,          LEVEL_HOST   },
+	
+	{ "maintitle",       "TITLE",                  TITLE,           LEVEL_SERIES },
+	{ "mainsubtitle",    "SUBTITLE",               TITLE,           LEVEL_SERIES },
+	{ "maintitleaddon",  "TITLEADDON",             TITLE,           LEVEL_SERIES },
+
+	{ "series",          "TITLE",                  SIMPLE,          LEVEL_SERIES+1 }, /* WRONG */
+
+	{ "origlanguage",    "LANGUAGE",               SIMPLE,          LEVEL_ORIG   },
+	{ "origyear",        "YEAR",                   SIMPLE,          LEVEL_ORIG   },
+	{ "origdate",        "DATE",                   SIMPLE,          LEVEL_ORIG   },
+	{ "origtitle",       "TITLE",                  SIMPLE,          LEVEL_ORIG   },
+	{ "origlocation",    "ADDRESS",                SIMPLE,          LEVEL_ORIG   },
+	{ "origpublisher",   "PUBLISHER",              SIMPLE,          LEVEL_ORIG   },
+
+	{ "publisher",       "PUBLISHER",              SIMPLE,          LEVEL_HOST   },
+	{ "location",        "ADDRESS",                SIMPLE,          LEVEL_HOST   },
+	{ "isbn",            "ISBN",                   SIMPLE,          LEVEL_MAIN   },
+	{ "chapter",         "CHAPTER",                SIMPLE,          LEVEL_MAIN   },
+	{ "pages",           "PAGES",                  PAGES,           LEVEL_MAIN   }, /* WRONG */
+	{ "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   },
+	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
+	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   },
+	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   },
+	{ "urlyear",         "?urlyear?",              SIMPLE,          LEVEL_MAIN   },
+	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "hyphenation",     "LANGCATALOG",            SIMPLE,          LEVEL_MAIN   },
+	{ "refnum",          "REFNUM",                 SIMPLE,          LEVEL_MAIN   },
+	{ "",                "INTERNAL_TYPE|INCOLLECTION", ALWAYS,      LEVEL_MAIN   },
+	{ "",                "RESOURCE|text",          ALWAYS,          LEVEL_MAIN   },
+	{ "",                "ISSUANCE|monographic",   ALWAYS,          LEVEL_MAIN   },
+	{ "",                "GENRE|collection",       ALWAYS,          LEVEL_HOST   }
+};
+
+/* inproceedings */
+
+static lookups inproceedings[] = {
+	{ "author",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "editor",          "EDITOR",                 BLT_EDITOR,      LEVEL_HOST   },
+	{ "editora",         "EDITOR",                 BLT_EDITOR,      LEVEL_HOST   },
+	{ "editorb",         "EDITOR",                 BLT_EDITOR,      LEVEL_HOST   },
+	{ "editorc",         "EDITOR",                 BLT_EDITOR,      LEVEL_HOST   },
+	{ "editortype",      "",                       BLT_SKIP,        LEVEL_HOST   },
+	{ "editoratype",     "",                       BLT_SKIP,        LEVEL_HOST   },
+	{ "editorbtype",     "",                       BLT_SKIP,        LEVEL_HOST   },
+	{ "editorctype",     "",                       BLT_SKIP,        LEVEL_HOST   },
+	{ "director",        "DIRECTOR",               PERSON,          LEVEL_HOST   },
+	{ "producer",        "PRODUCER",               PERSON,          LEVEL_HOST   },
+	{ "execproducer",    "PRODUCER",               PERSON,          LEVEL_HOST   },
+	{ "writer",          "AUTHOR",                 PERSON,          LEVEL_HOST   },
+	{ "redactor",        "REDACTOR",               PERSON,          LEVEL_HOST   },
+	{ "annotator",       "ANNOTATOR",              PERSON,          LEVEL_HOST   },
+	{ "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   },
+	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/
+	{ "introduction",    "INTROAUTHOR",            PERSON,          LEVEL_HOST   },
+	{ "foreword",        "INTROAUTHOR",            PERSON,          LEVEL_HOST   },
+	{ "afterword",       "AFTERAUTHOR",            PERSON,          LEVEL_HOST   },
+	{ "title",           "TITLE",                  TITLE,           LEVEL_MAIN   },
+	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   },
+	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   },
+	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   },
+
+	{ "booktitle",       "TITLE",                  TITLE,           LEVEL_HOST   },
+	{ "booksubtitle",    "SUBTITLE",               TITLE,           LEVEL_HOST   },
+	{ "booktitleaddon",  "TITLEADDON",             TITLE,           LEVEL_HOST   },
+
+	{ "maintitle",       "TITLE",                  TITLE,           LEVEL_SERIES },
+	{ "mainsubtitle",    "SUBTITLE",               TITLE,           LEVEL_SERIES },
+	{ "maintitleaddon",  "TITLEADDON",             TITLE,           LEVEL_SERIES },
+
+	{ "series",          "TITLE",                  SIMPLE,          LEVEL_SERIES+1 },
+
+	{ "venue",           "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "organization",    "ORGANIZER:CORP",         SIMPLE,          LEVEL_MAIN   },
+	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
+	{ "origlanguage",    "LANGUAGE",               SIMPLE,          LEVEL_ORIG   },
+	{ "origdate",        "DATE",                   SIMPLE,          LEVEL_ORIG   },
+	{ "origyear",        "YEAR",                   SIMPLE,          LEVEL_ORIG   },
+	{ "origtitle",       "TITLE",                  SIMPLE,          LEVEL_ORIG   },
+	{ "origlocation",    "ADDRESS",                SIMPLE,          LEVEL_ORIG   },
+	{ "origpublisher",   "PUBLISHER",              SIMPLE,          LEVEL_ORIG   },
+	{ "volume",          "VOLUME",                 SIMPLE,          LEVEL_HOST   },
+	{ "part",            "PART",                   SIMPLE,          LEVEL_HOST   },
+	{ "edition",         "EDITION",                SIMPLE,          LEVEL_MAIN   },
+	{ "volumes",         "NUMVOLUMES",             SIMPLE,          LEVEL_HOST   },
+	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "publisher",       "PUBLISHER",              SIMPLE,          LEVEL_HOST   },
+	{ "location",        "ADDRESS",                SIMPLE,          LEVEL_HOST   },
+	{ "isbn",            "ISBN",                   SIMPLE,          LEVEL_MAIN   },
+	{ "chapter",         "CHAPTER",                SIMPLE,          LEVEL_MAIN   },
+	{ "pages",           "PAGES",                  PAGES,           LEVEL_MAIN   }, /* WRONG */
+	{ "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   },
+	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
+	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   },
+	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   },
+	{ "urlyear",         "?urlyear?",              SIMPLE,          LEVEL_MAIN   },
+	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "hyphenation",     "LANGCATALOG",            SIMPLE,          LEVEL_MAIN   },
+	{ "refnum",          "REFNUM",                 SIMPLE,          LEVEL_MAIN   },
+	{ "",                "INTERNAL_TYPE|INPROCEEDINGS", ALWAYS,     LEVEL_MAIN   },
+	{ "",                "RESOURCE|text",          ALWAYS,          LEVEL_MAIN   },
+	{ "",                "ISSUANCE|monographic",   ALWAYS,          LEVEL_MAIN   },
+	{ "",                "GENRE|conference publication", ALWAYS,    LEVEL_HOST   }
+};
+
+static lookups manual[] = {
+	{ "author",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "editor",          "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editora",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editorb",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editorc",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editortype",      "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editoratype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editorbtype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editorctype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "director",        "DIRECTOR",               PERSON,          LEVEL_MAIN   },
+	{ "producer",        "PRODUCER",               PERSON,          LEVEL_MAIN   },
+	{ "execproducer",    "PRODUCER",               PERSON,          LEVEL_MAIN   },
+	{ "writer",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "redactor",        "REDACTOR",               PERSON,          LEVEL_MAIN   },
+	{ "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   },
+	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   }, /*WRONG*/
+	{ "introduction",    "INTROAUTHOR",            PERSON,          LEVEL_MAIN   },
+	{ "foreword",        "INTROAUTHOR",            PERSON,          LEVEL_MAIN   },
+	{ "afterword",       "AFTERAUTHOR",            PERSON,          LEVEL_MAIN   },
+	{ "title",           "TITLE",                  TITLE,           LEVEL_MAIN   },
+	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   },
+	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   },
+	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   },
+	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
+	{ "edition",         "EDITION",                SIMPLE,          LEVEL_MAIN   },
+	{ "version",         "EDITION",                SIMPLE,          LEVEL_MAIN   },
+	{ "type",            "GENRE",                  BT_GENRE,        LEVEL_MAIN   },
+	{ "series",          "TITLE",                  SIMPLE,          LEVEL_HOST   },
+	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "organization",    "ORGANIZER:CORP",         SIMPLE,          LEVEL_MAIN   },
+	{ "publisher",       "PUBLISHER",              SIMPLE,          LEVEL_MAIN   },
+	{ "location",        "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "isbn",            "ISBN",                   SIMPLE,          LEVEL_MAIN   },
+	{ "chapter",         "CHAPTER",                SIMPLE,          LEVEL_MAIN   },
+	{ "pages",           "PAGES",                  PAGES,           LEVEL_MAIN   },
+	{ "pagetotal",       "TOTALPAGES",             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   },
+	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
+	{ "urlday",          "?????????",              SIMPLE,          LEVEL_MAIN   },
+	{ "urlmonth",        "?????????",              SIMPLE,          LEVEL_MAIN   },
+	{ "urlyear",         "?????????",              SIMPLE,          LEVEL_MAIN   },
+	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "hyphenation",     "LANGCATALOG",            SIMPLE,          LEVEL_MAIN   },
+	{ "refnum",          "REFNUM",                 SIMPLE,          LEVEL_MAIN   },
+	{ "",                "INTERNAL_TYPE|REPORT",   ALWAYS,          LEVEL_MAIN   },
+	{ "",                "RESOURCE|text",          ALWAYS,          LEVEL_MAIN   },
+	{ "",                "GENRE|instruction",      ALWAYS,          LEVEL_MAIN   }
+};
+
+static lookups misc[] = {
+	{ "author",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "editor",          "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editora",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editorb",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editorc",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editortype",      "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editoratype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editorbtype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editorctype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "director",        "DIRECTOR",               PERSON,          LEVEL_MAIN   },
+	{ "producer",        "PRODUCER",               PERSON,          LEVEL_MAIN   },
+	{ "execproducer",    "PRODUCER",               PERSON,          LEVEL_MAIN   },
+	{ "writer",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "title",           "TITLE",                  TITLE,           LEVEL_MAIN   },
+	{ "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   },
+	{ "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   },
+	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "organization",    "ORGANIZER:CORP",         SIMPLE,          LEVEL_MAIN   },
+	{ "publisher",       "PUBLISHER",              SIMPLE,          LEVEL_MAIN   },
+	{ "location",        "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "addendum",        "ADDENDUM",               SIMPLE,          LEVEL_MAIN   },
+	{ "address",         "ADDRESS",                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   },
+	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
+	{ "urlday",          "?????????",              SIMPLE,          LEVEL_MAIN   },
+	{ "urlmonth",        "?????????",              SIMPLE,          LEVEL_MAIN   },
+	{ "urlyear",         "?????????",              SIMPLE,          LEVEL_MAIN   },
+	{ "hyphenation",     "LANGCATALOG",            SIMPLE,          LEVEL_MAIN   },
+	{ "refnum",          "REFNUM",                 SIMPLE,          LEVEL_MAIN   },
+	{ "",                "INTERNAL_TYPE|MISC",     ALWAYS,          LEVEL_MAIN   },
+};
+
+static lookups online[] = {
+	{ "author",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "editor",          "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editora",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editorb",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editorc",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editortype",      "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editoratype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editorbtype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editorctype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "director",        "DIRECTOR",               PERSON,          LEVEL_MAIN   },
+	{ "producer",        "PRODUCER",               PERSON,          LEVEL_MAIN   },
+	{ "execproducer",    "PRODUCER",               PERSON,          LEVEL_MAIN   },
+	{ "writer",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "title",           "TITLE",                  TITLE,           LEVEL_MAIN   },
+	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   },
+	{ "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   },
+	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
+	{ "version",         "EDITION",                SIMPLE,          LEVEL_MAIN   },
+	{ "type",            "GENRE",                  BT_GENRE,        LEVEL_MAIN   },
+	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "organization",    "ORGANIZER:CORP",         SIMPLE,          LEVEL_MAIN   },
+	{ "publisher",       "PUBLISHER",              SIMPLE,          LEVEL_MAIN   },
+	{ "location",        "ADDRESS",                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   },
+	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
+	{ "urlday",          "?????????",              SIMPLE,          LEVEL_MAIN   },
+	{ "urlmonth",        "?????????",              SIMPLE,          LEVEL_MAIN   },
+	{ "urlyear",         "?????????",              SIMPLE,          LEVEL_MAIN   },
+	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "hyphenation",     "LANGCATALOG",            SIMPLE,          LEVEL_MAIN   },
+	{ "refnum",          "REFNUM",                 SIMPLE,          LEVEL_MAIN   },
+        { "",                "RESOURCE|software, multimedia", ALWAYS,   LEVEL_MAIN   },
+	{ "",                "NGENRE|web page",        ALWAYS,          LEVEL_MAIN   },
+};
+
+static lookups patent[] = {
+	{ "author",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "holder",          "ASSIGNEE",               PERSON,          LEVEL_MAIN   },
+	{ "title",           "TITLE",                  TITLE,           LEVEL_MAIN   },
+	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   },
+	{ "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   },
+	{ "version",         "EDITION",                SIMPLE,          LEVEL_MAIN   },
+	{ "type",            "GENRE",                  BT_GENRE,        LEVEL_MAIN   },
+	{ "note",            "NOTES",                  SIMPLE,          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   },
+	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
+	{ "urlday",          "?????????",              SIMPLE,          LEVEL_MAIN   },
+	{ "urlmonth",        "?????????",              SIMPLE,          LEVEL_MAIN   },
+	{ "urlyear",         "?????????",              SIMPLE,          LEVEL_MAIN   },
+	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "hyphenation",     "LANGCATALOG",            SIMPLE,          LEVEL_MAIN   },
+	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   },
+	{ "refnum",          "REFNUM",                 SIMPLE,          LEVEL_MAIN   },
+	{ "",                "RESOURCE|text",          ALWAYS,          LEVEL_MAIN   },
+	{ "",                "INTERNAL_TYPE|PATENT",   ALWAYS,          LEVEL_MAIN   },
+	{ "",                "GENRE|patent",           ALWAYS,          LEVEL_MAIN   },
+};
+
+/*
+ * An entire issue of a periodical
+ *
+ * "The title of the periodical is given in the title field. If the issue has 
+ * its own title in addition to the main title of the periodical, it goes in 
+ * the issuetitle field. The editor is omissible..."
+ */
+static lookups periodical[] = {
+	{ "editor",          "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editora",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editorb",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editorc",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editortype",      "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editoratype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editorbtype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editorctype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "director",        "DIRECTOR",               PERSON,          LEVEL_MAIN   },
+	{ "producer",        "PRODUCER",               PERSON,          LEVEL_MAIN   },
+	{ "execproducer",    "PRODUCER",               PERSON,          LEVEL_MAIN   },
+	{ "writer",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "title",           "TITLE",                  TITLE,           LEVEL_HOST   },
+	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_HOST   },
+	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_HOST   },
+	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_HOST   },
+	{ "issuetitle",      "TITLE",                  TITLE,           LEVEL_MAIN   },
+	{ "issuesubtitle",   "SUBTITLE",               TITLE,           LEVEL_MAIN   },
+	{ "issuetitleaddon", "TITLEADDON",             TITLE,           LEVEL_MAIN   },
+	{ "series",          "TITLE",                  SIMPLE,          LEVEL_SERIES },
+	{ "volume",          "VOLUME",                 SIMPLE,          LEVEL_MAIN   },
+	{ "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   },
+	{ "pages",           "PAGES",                  PAGES,           LEVEL_MAIN   },
+	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "issn",            "ISSN",                   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   },
+	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
+	{ "urlday",          "?????",                  SIMPLE,          LEVEL_MAIN   }, /* WRONG */
+	{ "urlmonth",        "?????",                  SIMPLE,          LEVEL_MAIN   }, /* WRONG */
+	{ "urlyear",         "?????",                  SIMPLE,          LEVEL_MAIN   }, /* WRONG */
+	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "hyphenation",     "LANGCATALOG",            SIMPLE,          LEVEL_MAIN   },
+	{ "refnum",          "REFNUM",                 SIMPLE,          LEVEL_MAIN   },
+	{ "",                "ISSUANCE|continuing",    ALWAYS,          LEVEL_HOST   },
+	{ "",                "RESOURCE|text",          ALWAYS,          LEVEL_MAIN   },
+	{ "",                "GENRE|issue",            ALWAYS,          LEVEL_MAIN   },
+	{ "",                "GENRE|periodical",       ALWAYS,          LEVEL_HOST   }
+};
+
+static lookups proceedings[] = {
+	{ "editor",          "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editora",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editorb",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editorc",         "EDITOR",                 BLT_EDITOR,      LEVEL_MAIN   },
+	{ "editortype",      "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editoratype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editorbtype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "editorctype",     "",                       BLT_SKIP,        LEVEL_MAIN   },
+	{ "director",        "DIRECTOR",               PERSON,          LEVEL_MAIN   },
+	{ "producer",        "PRODUCER",               PERSON,          LEVEL_MAIN   },
+	{ "execproducer",    "PRODUCER",               PERSON,          LEVEL_MAIN   },
+	{ "writer",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "redactor",        "REDACTOR",               PERSON,          LEVEL_MAIN   },
+	{ "annotator",       "ANNOTATOR",              PERSON,          LEVEL_MAIN   },
+	{ "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   },
+	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/
+	{ "introduction",    "INTROAUTHOR",            PERSON,          LEVEL_MAIN   },
+	{ "foreword",        "INTROAUTHOR",            PERSON,          LEVEL_MAIN   },
+	{ "afterword",       "AFTERAUTHOR",            PERSON,          LEVEL_MAIN   },
+	{ "title",           "TITLE",                  TITLE,           LEVEL_MAIN   },
+	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   },
+	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   },
+	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   },
+	{ "maintitle",       "TITLE",                  TITLE,           LEVEL_HOST   },
+	{ "mainsubtitle",    "SUBTITLE",               TITLE,           LEVEL_HOST   },
+	{ "maintitleaddon",  "TITLEADDON",             TITLE,           LEVEL_HOST   },
+	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
+	{ "origlanguage",    "LANGUAGE",               SIMPLE,          LEVEL_ORIG   },
+	{ "origdate",        "DATE",                   SIMPLE,          LEVEL_ORIG   },
+	{ "origyear",        "YEAR",                   SIMPLE,          LEVEL_ORIG   },
+	{ "origtitle",       "TITLE",                  SIMPLE,          LEVEL_ORIG   },
+	{ "origlocation",    "ADDRESS",                SIMPLE,          LEVEL_ORIG   },
+	{ "origpublisher",   "PUBLISHER",              SIMPLE,          LEVEL_ORIG   },
+	{ "volume",          "VOLUME",                 SIMPLE,          LEVEL_HOST   },
+	{ "part",            "PART",                   SIMPLE,          LEVEL_HOST   },
+	{ "edition",         "EDITION",                SIMPLE,          LEVEL_MAIN   },
+	{ "volumes",         "NUMVOLUMES",             SIMPLE,          LEVEL_HOST   },
+	{ "series",          "TITLE",                  SIMPLE,          LEVEL_SERIES },
+	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "organization",    "ORGANIZER:CORP",         SIMPLE,          LEVEL_MAIN   },
+	{ "publisher",       "PUBLISHER",              SIMPLE,          LEVEL_MAIN   },
+	{ "location",        "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "isbn",            "ISBN",                   SIMPLE,          LEVEL_MAIN   },
+	{ "chapter",         "CHAPTER",                SIMPLE,          LEVEL_MAIN   },
+	{ "pages",           "PAGES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "pagetotal",       "TOTALPAGES",             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   },
+	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
+	{ "urlday",          "?????????",              SIMPLE,          LEVEL_MAIN   },
+	{ "urlmonth",        "?????????",              SIMPLE,          LEVEL_MAIN   },
+	{ "urlyear",         "?????????",              SIMPLE,          LEVEL_MAIN   },
+	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "hyphenation",     "LANGCATALOG",            SIMPLE,          LEVEL_MAIN   },
+	{ "refnum",          "REFNUM",                 SIMPLE,          LEVEL_MAIN   },
+	{ "",                "INTERNAL_TYPE|BOOK",     ALWAYS,          LEVEL_MAIN   },
+        { "",                "RESOURCE|text",          ALWAYS,          LEVEL_MAIN   },
+        { "",                "GENRE|conference publication", ALWAYS,    LEVEL_MAIN   }
+};
+
+/* Technical reports */
+static lookups report[] = {
+	{ "author",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "title",           "TITLE",                  TITLE,           LEVEL_MAIN   },
+	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   },
+	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   },
+	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   },
+	{ "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   },
+	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/
+	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
+	{ "number",          "REPORTNUMBER",           SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "version",         "EDITION",                SIMPLE,          LEVEL_MAIN   },
+	{ "location",        "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "isrn",            "ISRN",                   SIMPLE,          LEVEL_MAIN   },
+	{ "chapter",         "CHAPTER",                SIMPLE,          LEVEL_MAIN   },
+	{ "pages",           "PAGES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "pagetotal",       "TOTALPAGES",             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   },
+	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
+	{ "urlday",          "?????????",              SIMPLE,          LEVEL_MAIN   },
+	{ "urlmonth",        "?????????",              SIMPLE,          LEVEL_MAIN   },
+	{ "urlyear",         "?????????",              SIMPLE,          LEVEL_MAIN   },
+	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "hyphenation",     "LANGCATALOG",            SIMPLE,          LEVEL_MAIN   },
+	{ "refnum",          "REFNUM",                 SIMPLE,          LEVEL_MAIN   },
+	{ "",                "INTERNAL_TYPE|REPORT",   ALWAYS,          LEVEL_MAIN   },
+	{ "",                "RESOURCE|text",          ALWAYS,          LEVEL_MAIN   },
+	{ "",                "GENRE|report",           ALWAYS,          LEVEL_MAIN   }
+};
+
+/* Unpublished */
+static lookups unpublished[] = {
+	{ "author",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "title",           "TITLE",                  TITLE,           LEVEL_MAIN   },
+	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   },
+	{ "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   },
+	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },
+	{ "url",             "",                       BT_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   },
+	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "addendum",        "ADDENDUM",               SIMPLE,          LEVEL_MAIN   },
+	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "hyphenation",     "LANGCATALOG",            SIMPLE,          LEVEL_MAIN   },
+	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   },
+	{ "refnum",          "REFNUM",                 SIMPLE,          LEVEL_MAIN   },
+	{ "",                "INTERNAL_TYPE|BOOK",     ALWAYS,          LEVEL_MAIN   },
+	{ "",                "RESOURCE|text",          ALWAYS,          LEVEL_MAIN   },
+	{ "",                "GENRE|unpublished",      ALWAYS,          LEVEL_MAIN   }
+};
+
+static lookups thesis[] = {
+	{ "author",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "title",           "TITLE",                  TITLE,           LEVEL_MAIN   },
+	{ "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   },
+	{ "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   },
+	{ "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   },
+	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "hyphenation",     "LANGCATALOG",            SIMPLE,          LEVEL_MAIN   },
+	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   },
+	{ "refnum",          "REFNUM",                 SIMPLE,          LEVEL_MAIN   },
+	{ "",                "INTERNAL_TYPE|THESIS",   ALWAYS,          LEVEL_MAIN   },
+	{ "",                "RESOURCE|text",          ALWAYS,          LEVEL_MAIN   },
+	{ "",                "GENRE|thesis",           ALWAYS,          LEVEL_MAIN   },
+};
+
+static lookups phdthesis[] = {
+	{ "author",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "title",           "TITLE",                  TITLE,           LEVEL_MAIN   },
+	{ "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   },
+	{ "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   },
+	{ "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   },
+	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "hyphenation",     "LANGCATALOG",            SIMPLE,          LEVEL_MAIN   },
+	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   },
+	{ "refnum",          "REFNUM",                 SIMPLE,          LEVEL_MAIN   },
+	{ "",                "INTERNAL_TYPE|THESIS",   ALWAYS,          LEVEL_MAIN   },
+	{ "",                "RESOURCE|text",          ALWAYS,          LEVEL_MAIN   },
+	{ "",                "GENRE|thesis",           ALWAYS,          LEVEL_MAIN   },
+	{ "",                "NGENRE|Ph.D. thesis",    DEFAULT,         LEVEL_MAIN   },
+};
+
+static lookups mastersthesis[] = {
+	{ "author",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
+	{ "title",           "TITLE",                  TITLE,           LEVEL_MAIN   },
+	{ "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   },
+	{ "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   },
+	{ "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   },
+	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
+	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
+	{ "hyphenation",     "LANGCATALOG",            SIMPLE,          LEVEL_MAIN   },
+	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   },
+	{ "refnum",          "REFNUM",                 SIMPLE,          LEVEL_MAIN   },
+	{ "",                "INTERNAL_TYPE|THESIS",   ALWAYS,          LEVEL_MAIN   },
+	{ "",                "RESOURCE|text",          ALWAYS,          LEVEL_MAIN   },
+	{ "",                "GENRE|thesis",           ALWAYS,          LEVEL_MAIN   },
+	{ "",                "NGENRE|Masters thesis",  DEFAULT,         LEVEL_MAIN   },
+};
+
+#define ORIG(a) ( &(a[0]) )
+#define SIZE(a) ( sizeof( a ) / sizeof( lookups ) )
+#define REFTYPE(a,b) { a, ORIG(b), SIZE(b) }
+
+variants biblatex_all[] = {
+	REFTYPE( "article", article ),
+	REFTYPE( "suppperiodical", article ),
+	REFTYPE( "booklet", booklet ),
+	REFTYPE( "book", book ),
+	REFTYPE( "collection", collection ),
+	REFTYPE( "reference", collection ),
+	REFTYPE( "mvreference", collection ),
+	REFTYPE( "inbook", inbook ),
+	REFTYPE( "suppbook", inbook ),
+	REFTYPE( "incollection", incollection ),
+	REFTYPE( "inreference", incollection ),
+	REFTYPE( "suppcollection", incollection ),
+	REFTYPE( "inproceedings", inproceedings ),
+	REFTYPE( "conference", inproceedings ), /* legacy */
+	REFTYPE( "manual", manual ),
+	REFTYPE( "misc", misc ),
+	REFTYPE( "online", online ),
+	REFTYPE( "electronic", online ), /* legacy */
+	REFTYPE( "www", online ),        /* jurabib compatibility */
+	REFTYPE( "patent", patent ),
+	REFTYPE( "periodical", periodical ),
+	REFTYPE( "proceedings", proceedings ),
+	REFTYPE( "mvproceedings", proceedings ),
 	REFTYPE( "report", report ),
 	REFTYPE( "techreport", report ),
 /*	REFTYPE( "set", set ), */
diff --git a/bibutils/copacin.c b/bibutils/copacin.c
--- a/bibutils/copacin.c
+++ b/bibutils/copacin.c
@@ -1,7 +1,7 @@
 /*
  * copacin.c
  *
- * Copyright (c) Chris Putnam 2004-2013
+ * Copyright (c) Chris Putnam 2004-2014
  *
  * Program and source code released under the GPL version 2
  *
@@ -20,6 +20,9 @@
 #include "serialno.h"
 #include "copacin.h"
 
+/*****************************************************
+ PUBLIC: void copacin_initparams()
+*****************************************************/
 void
 copacin_initparams( param *p, const char *progname )
 {
@@ -49,6 +52,10 @@
 	else p->progname = strdup( progname );
 }
 
+/*****************************************************
+ PUBLIC: int copacin_readf()
+*****************************************************/
+
 /* Endnote-Refer/Copac tag definition:
     character 1 = alphabetic character
     character 2 = alphabetic character
@@ -114,6 +121,10 @@
 	return haveref;
 }
 
+/*****************************************************
+ PUBLIC: int copacin_processf()
+*****************************************************/
+
 static char*
 copacin_addtag2( char *p, newstr *tag, newstr *data )
 {
@@ -145,6 +156,7 @@
 copacin_processf( fields *copacin, char *p, char *filename, long nref )
 {
 	newstr tag, data;
+	int status;
 	newstr_init( &tag );
 	newstr_init( &data );
 	while ( *p ) {
@@ -152,8 +164,10 @@
 		if ( copacin_istag( p ) ) {
 			p = copacin_addtag2( p, &tag, &data );
 			/* don't add empty strings */
-			if ( tag.len && data.len )
-				fields_add( copacin, tag.data, data.data, 0 );
+			if ( tag.len && data.len ) {
+				status = fields_add( copacin, tag.data, data.data, 0 );
+				if ( status!=FIELDS_OK ) return 0;
+			}
 			newstr_empty( &tag );
 			newstr_empty( &data );
 		}
@@ -164,6 +178,10 @@
 	return 1;
 }
 
+/*****************************************************
+ PUBLIC: int copacin_convertf(), returns BIBL_OK or BIBL_ERR_MEMERR
+*****************************************************/
+
 /* copac names appear to always start with last name first, but don't
  * always seem to have a comma after the name
  *
@@ -176,17 +194,19 @@
 	char *usetag = tag, editor[]="EDITOR";
 	newstr usename, *s;
 	list tokens;
-	int comma = 0, i;
+	int comma = 0, i, ok;
 
 	if ( list_find( asis, name->data ) !=-1  ||
 	     list_find( corps, name->data ) !=-1 ) {
-		return name_add( info, tag, name->data, level, asis, corps );
+		ok = name_add( info, tag, name->data, level, asis, corps );
+		if ( ok ) return BIBL_OK;
+		else return BIBL_ERR_MEMERR;
 	}
 
 	list_init( &tokens );
 	newstr_init( &usename );
 
-	list_tokenize( &tokens, name, ' ', 1 );
+	list_tokenize( &tokens, name, " ", 1 );
 	for ( i=0; i<tokens.n; ++i ) {
 		s = list_get( &tokens, i );
 		if ( !strcmp( s->data, "[Editor]" ) ) {
@@ -207,90 +227,11 @@
 		newstr_newstrcat( &usename, list_get( &tokens, i ) );
 	}
 
-	return name_add( info, usetag, usename.data, level, asis, corps );
-}
-
-static int
-copacin_addpage( fields *info, char *p, int level )
-{
-	newstr page;
-	int ok;
-	newstr_init( &page );
-	p = skip_ws( p );
-	while ( *p && !is_ws(*p) && *p!='-' && *p!='\r' && *p!='\n' ) 
-		newstr_addchar( &page, *p++ );
-	if ( page.len>0 ) {
-		ok = fields_add( info, "PAGESTART", page.data, level );
-		if ( !ok ) return 0;
-	}
-	newstr_empty( &page );
-	while ( *p && (is_ws(*p) || *p=='-' ) ) p++;
-	while ( *p && !is_ws(*p) && *p!='-' && *p!='\r' && *p!='\n' ) 
-		newstr_addchar( &page, *p++ );
-	if ( page.len>0 ) {
-		ok = fields_add( info, "PAGEEND", page.data, level );
-		if ( !ok ) return 0;
-	}
-	newstr_free( &page );
-	return 1;
-}
+	list_free( &tokens );
 
-static int
-copacin_adddate( fields *info, char *tag, char *newtag, char *p, int level )
-{
-	char *months[12]={ "January", "February", "March", "April",
-		"May", "June", "July", "August", "September",
-		"October", "November", "December" };
-	char month[10];
-	int found,i,part,ok;
-	newstr date;
-	newstr_init( &date );
-	part = (!strncasecmp(newtag,"PART",4));
-	if ( !strcasecmp( tag, "%D" ) ) {
-		while ( *p ) newstr_addchar( &date, *p++ );
-		if ( date.len>0 ) {
-			if ( part ) 
-				ok = fields_add(info, "PARTYEAR", date.data, level);
-			else
-				ok = fields_add( info, "YEAR", date.data, level );
-			if ( !ok ) return 0;
-		}
-	} else if ( !strcasecmp( tag, "%8" ) ) {
-		while ( *p && *p!=' ' && *p!=',' ) newstr_addchar( &date, *p++ );
-		if ( date.len>0 ) {
-			found = -1;
-			for ( i=0; i<12 && found==-1; ++i )
-				if ( !strncasecmp( date.data, months[i], 3 ) )
-					found = i;
-			if ( found!=-1 ) {
-				if (found>8) sprintf( month, "%d", found+1 );
-				else sprintf( month, "0%d", found+1 );
-				if ( part ) 
-					ok = fields_add( info, "PARTMONTH", month, level );
-				else    ok = fields_add( info, "MONTH", month, level );
-				if ( !ok ) return 0;
-			} else {
-				if ( part )
-					ok = fields_add( info, "PARTMONTH", date.data, level );
-				else
-					ok = fields_add( info, "MONTH", date.data, level );
-				if ( !ok ) return 0;
-			}
-		}
-		newstr_empty( &date );
-		p = skip_ws( p );
-		while ( *p && *p!='\n' && *p!=',' )
-			newstr_addchar( &date, *p++ );
-		if ( date.len>0 && date.len<3 ) {
-			if ( part )
-				ok = fields_add( info, "PARTDAY", date.data, level );
-			else
-				ok = fields_add( info, "DAY", date.data, level );
-			if ( !ok ) return 0;
-		}
-	}
-	newstr_free( &date );
-	return 1;
+	ok = name_add( info, usetag, usename.data, level, asis, corps );
+	if ( ok ) return BIBL_OK;
+	else return BIBL_ERR_MEMERR;
 }
 
 static void
@@ -302,10 +243,18 @@
 	}
 }
 
+static int
+copacin_simple( fields *out, char *tag, char *value, int level )
+{
+	int fstatus = fields_add( out, tag, value, level );
+	if ( fstatus==FIELDS_OK ) return BIBL_OK;
+	else return BIBL_ERR_MEMERR;
+}
+
 int
 copacin_convertf( fields *copacin, fields *out, int reftype, param *p, variants *all, int nall )
 {
-	int  process, level, i, n, nfields, ok;
+	int  process, level, i, n, nfields, ok, status = BIBL_OK;
 	newstr *tag, *data;
 	char *newtag;
 
@@ -326,39 +275,35 @@
 		switch ( process ) {
 
 		case SIMPLE:
-			ok = fields_add( out, newtag, data->data, level );
+			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:
-			ok = copacin_addname( out, newtag, data, level, &(p->asis), &(p->corps) );
-			break;
-
-		case DATE:
-			ok = copacin_adddate(out,all[reftype].  tags[i].oldstr,newtag,data->data,level);
-			break;
-
-		case PAGES:
-			ok = copacin_addpage( out, data->data, level );
+			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 );
-			ok = 1;
+			status = BIBL_OK;
 			break;
 		}
 
-		if ( !ok ) return BIBL_ERR_MEMERR;
+		if ( status!=BIBL_OK ) return status;
 
 	}
 
-	return BIBL_OK;
+	return status;
 }
 
diff --git a/bibutils/copacin.h b/bibutils/copacin.h
--- a/bibutils/copacin.h
+++ b/bibutils/copacin.h
@@ -1,7 +1,7 @@
 /*
  * copacin.h
  *
- * Copyright (c) Chris Putnam 2004-2013
+ * Copyright (c) Chris Putnam 2004-2014
  *
  * Source code released under the GPL
  *
diff --git a/bibutils/copactypes.c b/bibutils/copactypes.c
--- a/bibutils/copactypes.c
+++ b/bibutils/copactypes.c
@@ -1,7 +1,7 @@
 /*
  * copactypes.c
  *
- * Copyright (c) Chris Putnam 2004-2013
+ * Copyright (c) Chris Putnam 2004-2014
  *
  * Program and source code released under the GPL version 2
  *
diff --git a/bibutils/ebiin.c b/bibutils/ebiin.c
--- a/bibutils/ebiin.c
+++ b/bibutils/ebiin.c
@@ -16,6 +16,9 @@
 #include "xml_encoding.h"
 #include "ebiin.h"
 
+/*****************************************************
+ PUBLIC: void ebiin_initparams()
+*****************************************************/
 void
 ebiin_initparams( param *p, const char *progname )
 {
@@ -46,6 +49,9 @@
 	else p->progname = strdup( progname );
 }
 
+/*****************************************************
+ PUBLIC: int ebiin_readf()
+*****************************************************/
 int
 ebiin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset )
 {
@@ -78,27 +84,9 @@
 	return haveref;
 }
 
-
-static inline int
-xml_hasdata( xml *node )
-{
-	if ( node && node->value && node->value->data ) return 1;
-	return 0;
-}
-
-static inline char *
-xml_data( xml *node )
-{
-	return node->value->data;
-}
-
-
-static inline int
-xml_tagwithdata( xml *node, char *tag )
-{
-	if ( !xml_hasdata( node ) ) return 0;
-	return xml_tagexact( node, tag );
-}
+/*****************************************************
+ PUBLIC: int ebiin_processf()
+*****************************************************/
 
 typedef struct xml_convert {
 	char *in;       /* The input tag */
@@ -108,72 +96,108 @@
 } xml_convert;
 
 static int
-ebiin_doconvert( xml *node, fields *info, xml_convert *c, int nc )
+ebiin_doconvert( xml *node, fields *info, xml_convert *c, int nc, int *found )
 {
-	int i, found = 0;
+	int i, status;
 	char *d;
-	if ( !xml_hasdata( node ) ) return 0;
+
+	if ( !xml_hasdata( node ) ) goto out;
+
 	d = xml_data( node );
-	for ( i=0; i<nc && found==0; ++i ) {
+	for ( i=0; i<nc; ++i ) {
 		if ( c[i].a==NULL ) {
 			if ( xml_tagexact( node, c[i].in ) ) {
-				found = 1;
-				fields_add( info, c[i].out, d, c[i].level );
+				*found = 1;
+				status = fields_add( info, c[i].out, d, c[i].level );
+				if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+				else return BIBL_OK;
 			}
 		} else {
 			if ( xml_tag_attrib( node, c[i].in, c[i].a, c[i].aval)){
-				found = 1;
-				fields_add( info, c[i].out, d, c[i].level );
+				*found = 1;
+				status = fields_add( info, c[i].out, d, c[i].level );
+				if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+				else return BIBL_OK;
 			}
 		}
 	
 	}
-	return found;
+out:
+	*found = 0;
+	return BIBL_OK;
 }
 
 /* <ArticleTitle>Mechanism and.....</ArticleTitle>
+ * and
  * <Title>Mechanism and....</Title>
  */
-static void
+static int
 ebiin_title( xml *node, fields *info, int title_level )
 {
-	if ( xml_hasdata( node ) )
-		fields_add( info, "TITLE", xml_data( node ), title_level );
+	int status;
+	if ( xml_hasdata( node ) ) {
+		status = fields_add( info, "TITLE", xml_data( node ), title_level );
+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	}
+	return BIBL_OK;
 }
 
-/*            <MedlineDate>2003 Jan-Feb</MedlineDate> */
-static void
-ebiin_medlinedate( fields *info, char *string, int level )
+/* ebiin_medlinedate()
+ *
+ *   - extract medline information from entries like:
+ *             <MedlineDate>2003 Jan-Feb</MedlineDate>
+ */
+static int
+ebiin_medlinedate_year( fields *info, char *p, newstr *s, int level, char **end )
 {
-	newstr tmp;
-	char *p, *q;
-	newstr_init( &tmp );
-	/* extract year */
-	p = string;
-	q = skip_notws( string );
-	newstr_segcpy( &tmp, p, q );
-	fields_add( info, "PARTYEAR", tmp.data, level );
-	q = skip_ws( q );
-	/* extract month */
-	if ( q ) {
-		p = q;
-		newstr_empty( &tmp );
-		q = skip_notws( q );
-		newstr_segcpy( &tmp, p, q );
-		newstr_findreplace( &tmp, "-", "/" );
-		fields_add( info, "PARTMONTH", tmp.data, level );
-		q = skip_ws( q );
+	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 );
+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
-	/* extract day */
-	if ( q ) {
-		p = q;
-		newstr_empty( &tmp );
-		q = skip_notws( q );
-		newstr_segcpy( &tmp, p, q );
-		fields_add( info, "PARTDAY", tmp.data, level );
+	return BIBL_OK;
+}
+static int
+ebiin_medlinedate_month( fields *info, char *p, newstr *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 );
+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
-	newstr_free( &tmp );
+	return BIBL_OK;
 }
+static int
+ebiin_medlinedate_day( fields *info, char *p, newstr *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 );
+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	}
+	return BIBL_OK;
+}
+static int
+ebiin_medlinedate( fields *info, char *p, int level )
+{
+	int status;
+	newstr s;
+	newstr_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 );
+	return status;
+}
 
 /* <Journal>
  *    <ISSN>0027-8424</ISSN>
@@ -203,7 +227,7 @@
  *    <ISOAbbreviation>Alcohol Alcohol.</ISOAbbreviation>
  * </Journal>
  */
-static void
+static int
 ebiin_journal1( xml *node, fields *info )
 {
 	xml_convert c[] = {
@@ -215,59 +239,112 @@
 		{ "Day",      NULL, NULL, "PARTDAY",   1 },
 		{ "Language", NULL, NULL, "LANGUAGE",  1 },
 	};
-	int nc = sizeof( c ) / sizeof( c[0] );;
-	if ( xml_hasdata( node ) && !ebiin_doconvert( node, info, c, nc ) ) {
-		if ( xml_tagexact( node, "MedlineDate" ) )
-			ebiin_medlinedate( info, xml_data( node ), 1 );
+	int nc = sizeof( c ) / sizeof( c[0] ), status, found;
+	if ( xml_hasdata( 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 );
+				if ( status!=BIBL_OK ) return status;
+			}
+		}
 	}
-	if ( node->down ) ebiin_journal1( node->down, info );
-	if ( node->next ) ebiin_journal1( node->next, info );
+	if ( node->down ) {
+		status = ebiin_journal1( node->down, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->next ) {
+		status = ebiin_journal1( node->next, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	return BIBL_OK;
 }
 
-
 /* <Pagination>
  *    <MedlinePgn>12111-6</MedlinePgn>
  * </Pagination>
  */
-static void
+static int
+ebiin_pages( fields *info, char *p )
+{
+	int i, status, ret = BIBL_OK;
+	const int level = 1;
+	newstr sp, ep, *up;
+
+	newstrs_init( &sp, &ep, NULL );
+
+	/* ...start page */
+	p = newstr_cpytodelim( &sp, skip_ws( p ), "-", 1 );
+	if ( newstr_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 ) ) {
+		ret = BIBL_ERR_MEMERR;
+		goto out;
+	}
+
+	if ( sp.len ) {
+		status = fields_add( info, "PAGESTART", sp.data, level );
+		if ( status!=FIELDS_OK ) {
+			ret = BIBL_ERR_MEMERR;
+			goto out;
+		}
+	}
+	if ( ep.len ) {
+		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];
+				up = &(sp);
+		} else up = &(ep);
+		status = fields_add( info, "PAGEEND", up->data, level );
+		if ( status!=FIELDS_OK ) ret = BIBL_ERR_MEMERR;
+	}
+
+out:
+	newstrs_free( &sp, &ep, NULL );
+	return ret;
+}
+static int
 ebiin_pagination( xml *node, fields *info )
 {
-	newstr sp, ep;
-	char *p;
-	int i;
+	int status;
 	if ( xml_tagexact( node, "Pages" ) && node->value ) {
-		newstrs_init( &sp, &ep, NULL );
-		p = xml_data( node );
-		while ( *p && *p!='-' )
-			newstr_addchar( &sp, *p++ );
-		if ( *p=='-' ) p++;
-		while ( *p )
-			newstr_addchar( &ep, *p++ );
-		if ( sp.len ) fields_add( info, "PAGESTART", sp.data, 1 );
-		if ( ep.len ) {
-			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];
-				fields_add( info, "PAGEEND", sp.data, 1 );
-			} else
-				fields_add( info, "PAGEEND", ep.data, 1 );
-		}
-		newstrs_free( &sp, &ep, NULL );
+		status = ebiin_pages( info, xml_data( node ) );
+		if ( status!=BIBL_OK ) return status;
 	}
-	if ( node->down ) ebiin_pagination( node->down, info );
-	if ( node->next ) ebiin_pagination( node->next, info );
+	if ( node->down ) {
+		status = ebiin_pagination( node->down, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->next ) {
+		status = ebiin_pagination( node->next, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	return BIBL_OK;
 }
 
 /* <Abstract>
  *    <AbstractText>ljwejrelr</AbstractText>
  * </Abstract>
  */
-static void
+static int
 ebiin_abstract( xml *node, fields *info )
 {
-	if ( xml_hasdata( node ) && xml_tagexact( node, "AbstractText" ) )
-		fields_add( info, "ABSTRACT", xml_data( node ), 0 );
-	else if ( node->next ) ebiin_abstract( node->next, info );
+	int status;
+	if ( xml_hasdata( node ) && xml_tagexact( node, "AbstractText" ) ) {
+		status = fields_add( info, "ABSTRACT", xml_data( node ), 0 );
+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	}
+	else if ( node->next ) {
+		status = ebiin_abstract( node->next, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	return BIBL_OK;
 }
 
 /* <AuthorList CompleteYN="Y">
@@ -279,9 +356,10 @@
  *    </Author>
  * </AuthorList>
  */
-static void
+static int
 ebiin_author( xml *node, newstr *name )
 {
+	int status;
 	char *p;
 	if ( xml_tagexact( node, "LastName" ) ) {
 		if ( name->len ) {
@@ -304,28 +382,42 @@
 			if ( !is_ws(*p ) ) newstr_addchar( name, *p++ );
 		}
 	}
+	if ( newstr_memerr( name ) ) return BIBL_ERR_MEMERR;
 		 
-	if ( node->down ) ebiin_author( node->down, name );
-	if ( node->next ) ebiin_author( node->next, name );
-}
+	if ( node->down ) {
+		status = ebiin_author( node->down, name );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->next ) {
+		status = ebiin_author( node->next, name );
+		if ( status!=BIBL_OK ) return status;
+	}
 
-static void
+	return BIBL_OK;
+}
+static int
 ebiin_authorlist( xml *node, fields *info, int level )
 {
+	int fstatus, status = BIBL_OK;
 	newstr name;
+
 	newstr_init( &name );
 	node = node->down;
 	while ( node ) {
 		if ( xml_tagexact( node, "Author" ) && node->down ) {
-			ebiin_author( node->down, &name );
+			status = ebiin_author( node->down, &name );
+			if ( status!=BIBL_OK ) goto out;
 			if ( name.len ) {
-				fields_add(info,"AUTHOR",name.data,level);
+				fstatus = fields_add(info,"AUTHOR",name.data,level);
+				if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }
 				newstr_empty( &name );
 			}
 		}
 		node = node->next;
 	}
+out:
 	newstr_free( &name );
+	return status;
 }
 
 /* <PublicationTypeList>
@@ -340,13 +432,23 @@
  * </MedlineJournalInfo>
  */
 
-static void
+static int
 ebiin_journal2( xml *node, fields *info )
 {
-	if ( xml_tagwithdata( node, "TitleAbbreviation" ) )
-		fields_add( info, "TITLE", xml_data( node ), 1 );
-	if ( node->down ) ebiin_journal2( node->down, info );
-	if ( node->next ) ebiin_journal2( node->next, info );
+	int status;
+	if ( xml_tagwithdata( node, "TitleAbbreviation" ) ) {
+		status = fields_add( info, "TITLE", xml_data( node ), 1 );
+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	}
+	if ( node->down ) {
+		status = ebiin_journal2( node->down, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->next ) {
+		status = ebiin_journal2( node->next, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	return BIBL_OK;
 }
 
 /*
@@ -359,23 +461,37 @@
  *   </MeshHeading>
  * </MeshHeadingList>
 */
-static void
+static int
 ebiin_meshheading( xml *node, fields *info )
 {
-	if ( xml_tagwithdata( node, "DescriptorName" ) )
-		fields_add( info, "KEYWORD", xml_data( node ), 0 );
-	if ( node->next ) ebiin_meshheading( node->next, info );
+	int status;
+	if ( xml_tagwithdata( node, "DescriptorName" ) ) {
+		status = fields_add( info, "KEYWORD", xml_data( node ), 0 );
+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	}
+	if ( node->next ) {
+		status = ebiin_meshheading( node->next, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	return BIBL_OK;
 }
 
-static void
+static int
 ebiin_meshheadinglist( xml *node, fields *info )
 {
-	if ( xml_tagexact( node, "MeshHeading" ) && node->down )
-		ebiin_meshheading( node->down, info );
-	if ( node->next ) ebiin_meshheadinglist( node->next, info );
+	int status;
+	if ( xml_tagexact( node, "MeshHeading" ) && node->down ) {
+		status = ebiin_meshheading( node->down, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->next ) {
+		status = ebiin_meshheadinglist( node->next, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	return BIBL_OK;
 }
 
-static void
+static int
 ebiin_book( xml *node, fields *info, int book_level )
 {
 	xml_convert book[] = {
@@ -409,101 +525,175 @@
 	};
 	int ninbook = sizeof( inbook ) / sizeof( inbook[0] );
 	xml_convert *c;
-	int nc;
+	int nc, status, found;
 	if ( book_level==0 ) { c = book; nc = nbook; }
 	else { c = inbook; nc = ninbook; }
-	if ( xml_hasdata( node ) && !ebiin_doconvert( node, info, c, nc ) ) {
-		if ( xml_tagexact( node, "MedlineDate" ) )
-			ebiin_medlinedate( info, xml_data( node ), book_level);
-		else if ( xml_tagexact( node, "Title" ) )
-			ebiin_title( node, info, book_level );
-		else if ( xml_tagexact( node, "Pagination" ) && node->down )
-			ebiin_pagination( node->down, info );
-		else if ( xml_tagexact( node, "Abstract" ) && node->down )
-			ebiin_abstract( node->down, info );
-		else if ( xml_tagexact( node, "AuthorList" ) ) 
-			ebiin_authorlist( node, info, book_level );
-		else if ( xml_tagexact( node, "PubDate" ) && node->down)
-			ebiin_book( node->down, info, book_level );
+	if ( xml_hasdata( 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);
+			else if ( xml_tagexact( node, "Title" ) )
+				status = ebiin_title( node, info, book_level );
+			else if ( xml_tagexact( node, "Pagination" ) && node->down )
+				status = ebiin_pagination( node->down, info );
+			else if ( xml_tagexact( node, "Abstract" ) && node->down )
+				status = ebiin_abstract( node->down, info );
+			else if ( xml_tagexact( node, "AuthorList" ) )
+				status = ebiin_authorlist( node, info, book_level );
+			else if ( xml_tagexact( node, "PubDate" ) && node->down)
+				status = ebiin_book( node->down, info, book_level );
+			if ( status!=BIBL_OK ) return status;
+		}
 	}
-	if ( node->next ) ebiin_book( node->next, info, book_level );
+	if ( node->next ) {
+		status = ebiin_book( node->next, info, book_level );
+		if ( status!=BIBL_OK ) return status;
+	}
+	return BIBL_OK;
 }
 
-static void
+static int
 ebiin_article( xml *node, fields *info )
 {
+	int status = BIBL_OK;
+
 	if ( xml_tagexact( node, "Journal" ) ) 
-		ebiin_journal1( node, info );
+		status = ebiin_journal1( node, info );
 	else if ( node->down && ( xml_tagexact( node, "Book" ) || 
 			xml_tagexact(node, "Report") )) 
-		ebiin_book( node->down, info, 1 );
+		status = ebiin_book( node->down, info, 1 );
 	else if ( xml_tagexact( node, "ArticleTitle" ) )
-		ebiin_title( node, info, 0 );
+		status = ebiin_title( node, info, 0 );
 	else if ( xml_tagexact( node, "Pagination" ) && node->down )
-		ebiin_pagination( node->down, info );
+		status = ebiin_pagination( node->down, info );
 	else if ( xml_tagexact( node, "Abstract" ) && node->down )
-		ebiin_abstract( node->down, info );
+		status = ebiin_abstract( node->down, info );
 	else if ( xml_tagexact( node, "AuthorList" ) )
-		ebiin_authorlist( node, info, 0 );
-	if ( node->next ) ebiin_article( node->next, info );
+		status = ebiin_authorlist( node, info, 0 );
+	if ( status!=BIBL_OK ) return status;
+
+	if ( node->next ) {
+		status = ebiin_article( node->next, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+
+	return BIBL_OK;
 }
 
-static void
+static int
 ebiin_publication( xml *node, fields *info )
 {
+	int status;
 	if ( node->down ) {
 		if ( xml_tagexact( node, "Article" ) )
-			ebiin_article( node->down, info );
+			status = ebiin_article( node->down, info );
 		else if ( xml_tagexact( node, "Book" ) )
-			ebiin_book( node->down, info, 0 );
+			status = ebiin_book( node->down, info, 0 );
 		else if ( xml_tagexact( node, "Report" ) )
-			ebiin_book( node->down, info, 0 );
+			status = ebiin_book( node->down, info, 0 );
 		else if ( xml_tagexact( node, "JournalInfo" ) )
-			ebiin_journal2( node->down, info );
+			status = ebiin_journal2( node->down, info );
 		else if ( xml_tagexact( node, "MeshHeadingList" ) )
-			ebiin_meshheadinglist( node->down, info );
+			status = ebiin_meshheadinglist( node->down, info );
+		if ( status!=BIBL_OK ) return status;
 	}
-	if ( node->next ) ebiin_publication( node->next, info );
+	if ( node->next ) {
+		status = ebiin_publication( node->next, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	return BIBL_OK;
 }
 
 /* Call with the "Publication" node */
-static void
+static int
 ebiin_fixtype( xml *node, fields *info )
 {
+	char *resource = NULL, *issuance = NULL, *genre1 = NULL, *genre2 = NULL;
 	newstr *type;
-	fields_add( info, "RESOURCE", "text", 0 );
+	int reslvl, isslvl, gen1lvl, gen2lvl;
+	int status;
+
 	type = xml_getattrib( node, "Type" );
-	if ( !type || type->len==0 ) return;
+	if ( !type || type->len==0 ) return BIBL_OK;
+
 	if ( !strcmp( type->data, "JournalArticle" ) ) {
-		fields_add( info, "ISSUANCE", "continuing", 1 );
-		fields_add( info, "GENRE", "periodical", 1 );
-		fields_add( info, "GENRE", "academic journal", 1 );
+		resource = "text";
+		issuance = "continuing";
+		genre1   = "periodical";
+		genre2   = "academic journal";
+		reslvl   = 0;
+		isslvl   = 1;
+		gen1lvl  = 1;
+		gen2lvl  = 1;
 	} else if ( !strcmp( type->data, "Book" ) ) {
-		fields_add( info, "GENRE", "book", 0 );
-		fields_add( info, "ISSUANCE", "monographic", 0 );
+		resource = "text";
+		issuance = "monographic";
+		genre1   = "book";
+		reslvl   = 0;
+		isslvl   = 0;
+		gen1lvl  = 0;
 	} else if ( !strcmp( type->data, "BookArticle" ) ) {
-		fields_add( info, "GENRE", "book", 1 );
-		fields_add( info, "ISSUANCE", "monographic", 1 );
+		resource = "text";
+		issuance = "monographic";
+		genre1   = "book";
+		reslvl   = 0;
+		isslvl   = 1;
+		gen1lvl  = 1;
 	}
+
+	if ( resource ) {
+		status = fields_add( info, "RESOURCE", resource, reslvl );
+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	}
+	if ( issuance ) {
+		status = fields_add( info, "ISSUANCE", issuance, isslvl );
+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	}
+	if ( genre1 ) {
+		status = fields_add( info, "GENRE", genre1, gen1lvl );
+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	}
+	if ( genre2 ) {
+		status = fields_add( info, "GENRE", genre2, gen2lvl );
+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	}
+
+	return BIBL_OK;
 }
 
-static void
+static int
 ebiin_assembleref( xml *node, fields *info )
 {
-	if ( xml_tagexact( node, "Publication" ) && node->down) {
-		ebiin_fixtype( node, info );
-		ebiin_publication( node->down, info );
-	} else if ( node->down ) ebiin_assembleref( node->down, info );
-	if ( node->next ) ebiin_assembleref( node->next, info );
+	int status;
+	if ( xml_tagexact( node, "Publication" ) && node->down ) {
+		status = ebiin_fixtype( node, info );
+		if ( status!=BIBL_OK ) return status;
+		status = ebiin_publication( node->down, info );
+		if ( status!=BIBL_OK ) return status;
+	} else if ( node->down ) {
+		status = ebiin_assembleref( node->down, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->next ) {
+		status = ebiin_assembleref( node->next, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	return BIBL_OK;
 }
 
 int
 ebiin_processf( fields *ebiin, char *data, char *filename, long nref )
 {
+	int status;
 	xml top;
+
 	xml_init( &top );
 	xml_tree( data, &top );
-	ebiin_assembleref( &top, ebiin );
+	status = ebiin_assembleref( &top, ebiin );
 	xml_free( &top );
-	return 1;
+
+	return ( status==BIBL_OK ) ? 1 : 0;
 }
diff --git a/bibutils/endin.c b/bibutils/endin.c
--- a/bibutils/endin.c
+++ b/bibutils/endin.c
@@ -1,7 +1,7 @@
 /*
  * endin.c
  *
- * Copyright (c) Chris Putnam 2003-2013
+ * Copyright (c) Chris Putnam 2003-2014
  *
  * Program and source code released under the GPL version 2
  *
@@ -21,6 +21,9 @@
 #include "reftypes.h"
 #include "endin.h"
 
+/*****************************************************
+ PUBLIC: void endin_initparams()
+*****************************************************/
 void
 endin_initparams( param *p, const char *progname )
 {
@@ -50,6 +53,11 @@
 	else p->progname = strdup( progname );
 }
 
+
+/*****************************************************
+ PUBLIC: int endin_readf()
+*****************************************************/
+
 /* Endnote tag definition:
     character 1 = '%'
     character 2 = alphabetic character or digit (or other characters)
@@ -113,6 +121,9 @@
 	return haveref;
 }
 
+/*****************************************************
+ PUBLIC: int endin_processf()
+*****************************************************/
 static char*
 process_endline( newstr *tag, newstr *data, char *p )
 {
@@ -149,159 +160,37 @@
 endin_processf( fields *endin, char *p, char *filename, long nref )
 {
 	newstr tag, data;
-	int n;
+	int status, n;
 	newstrs_init( &tag, &data, NULL );
 	while ( *p ) {
+		newstrs_empty( &tag, &data, NULL );
 		if ( endin_istag( p ) ) {
 			p = process_endline( &tag, &data, p );
-			/* no empty fields allowed */
-			if ( data.len ) {
-				fields_add( endin, tag.data, data.data, 0 );
-			}
+			if ( data.len==0 ) continue;
+			status = fields_add( endin, tag.data, data.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 ( !strncmp( endin->tag[n-1].data, "%K", 2 ) ) {
-				fields_add( endin, "%K", data.data, 0 );
+				status = fields_add( endin, "%K", data.data, 0 );
+				if ( status!=FIELDS_OK ) return 0;
 			} else {
 				newstr_addchar( &(endin->data[n-1]), ' ' );
 				newstr_strcat( &(endin->data[n-1]), data.data );
 			}
 			}
 		}
-		newstrs_empty( &tag, &data, NULL );
 	}
 	newstrs_free( &tag, &data, NULL );
 	return 1;
 }
 
-static int
-endin_addtype( fields *info, char *data, int level )
-{
-	lookups types[] = {
-		{ "GENERIC", "ARTICLE" },
-		{ "BOOK", "BOOK" }, 
-		{ "MANUSCRIPT", "MANUSCRIPT" },
-		{ "CONFERENCE PROCEEDINGS", "INPROCEEDINGS"},
-		{ "REPORT", "REPORT" },
-		{ "COMPUTER PROGRAM", "BOOK" },
-		{ "AUDIOVISUAL MATERIAL", "AUDIOVISUAL" },
-		{ "ARTWORK", "BOOK" },
-		{ "PATENT", "BOOK" },
-		{ "BILL", "BILL" },
-		{ "CASE", "CASE" },
-		{ "JOURNAL ARTICLE", "ARTICLE" }, 
-		{ "MAGAZINE ARTICLE", "ARTICLE" }, 
-		{ "BOOK SECTION", "INBOOK" },
-		{ "EDITED BOOK", "BOOK" },
-       		{ "NEWSPAPER ARTICLE",  "NEWSARTICLE" },
-		{ "THESIS", "PHDTHESIS" },
-		{ "PERSONAL COMMUNICATION", "COMMUNICATION" },
-		{ "ELECTRONIC SOURCE", "TEXT" },
-		{ "FILM OR BROADCAST", "AUDIOVISUAL" },
-		{ "MAP", "MAP" },
-		{ "HEARING", "HEARING" },
-		{ "STATUTE", "STATUTE" },
-		{ "CHART OR TABLE", "CHART" },
-		{ "WEB PAGE", "WEBPAGE" },
-	};
-	int  ntypes = sizeof( types ) / sizeof( lookups );
-	int  i, ok, found=0;
-	for ( i=0; i<ntypes; ++i ) {
-		if ( !strcasecmp( types[i].oldstr, data ) ) {
-			found = 1;
-			ok = fields_add( info, "INTERNAL_TYPE", types[i].newstr, level );
-			if ( !ok ) return 0;
-		}
-	}
-	if ( !found ) {
-		fprintf( stderr, "Did not identify reference type '%s'\n",
-			data );
-		fprintf( stderr, "Defaulting to journal article type\n");
-		ok = fields_add( info, "INTERNAL_TYPE", types[0].newstr, level );
-		if ( !ok ) return 0;
-	}
-	return 1;
-}
-
-static int
-endin_addpage( fields *info, char *p, int level )
-{
-	newstr page;
-	int ok;
-	newstr_init( &page );
-	p = skip_ws( p );
-	while ( *p && !is_ws(*p) && *p!='-' && *p!='\r' && *p!='\n' ) 
-		newstr_addchar( &page, *p++ );
-	if ( page.len>0 ) {
-		ok = fields_add( info, "PAGESTART", page.data, level );
-		if ( !ok ) return 0;
-	}
-	newstr_empty( &page );
-	while ( *p && (is_ws(*p) || *p=='-' ) ) p++;
-	while ( *p && !is_ws(*p) && *p!='-' && *p!='\r' && *p!='\n' ) 
-		newstr_addchar( &page, *p++ );
-	if ( page.len>0 ) {
-		ok = fields_add( info, "PAGEEND", page.data, level );
-		if ( !ok ) return 0;
-	}
-	newstr_free( &page );
-	return 1;
-}
-
-static int
-endin_adddate( fields *info, char *tag, char *newtag, char *p, int level )
-{
-	char *months[12]={ "January", "February", "March", "April",
-		"May", "June", "July", "August", "September",
-		"October", "November", "December" };
-	char month[10];
-	int found,i,part, ok;
-	newstr date;
-	newstr_init( &date );
-	part = (!strncasecmp(newtag,"PART",4));
-	if ( !strcasecmp( tag, "%D" ) ) {
-		while ( *p ) newstr_addchar( &date, *p++ );
-		if ( date.len>0 ) {
-			if ( part ) ok = fields_add( info, "PARTYEAR", date.data, level );
-			else        ok = fields_add( info, "YEAR",     date.data, level );
-			if ( !ok ) return 0;
-		}
-	} else if ( !strcasecmp( tag, "%8" ) ) {
-		while ( *p && *p!=' ' && *p!=',' ) newstr_addchar( &date, *p++ );
-		if ( date.len>0 ) {
-			found = -1;
-			for ( i=0; i<12 && found==-1; ++i )
-				if ( !strncasecmp( date.data, months[i], 3 ) )
-					found = i;
-			if ( found!=-1 ) {
-				if (found>8) sprintf( month, "%d", found+1 );
-				else sprintf( month, "0%d", found+1 );
-				if ( part ) ok = fields_add( info, "PARTMONTH", month, level );
-				else        ok = fields_add( info, "MONTH",     month, level );
-				if ( !ok ) return 0;
-			} else {
-				if ( part )
-					ok = fields_add( info, "PARTMONTH", date.data, level );
-				else
-					ok = fields_add( info, "MONTH", date.data, level );
-				if ( !ok ) return 0;
-			}
-		}
-		newstr_empty( &date );
-		p = skip_ws( p );
-		while ( *p && *p!='\n' && *p!=',' ) newstr_addchar( &date, *p++ );
-		if ( date.len>0 && date.len<3 ) {
-			if ( part ) ok = fields_add( info, "PARTDAY", date.data, level );
-			else        ok = fields_add( info, "DAY",     date.data, level );
-			if ( !ok ) return 0;
-		}
-	}
-	newstr_free( &date );
-	return 1;
-}
+/*****************************************************
+ PUBLIC: int endin_typef()
+*****************************************************/
 
 /* Endnote defaults if no %0
  *
@@ -353,6 +242,10 @@
 	return reftype;
 }
 
+/*****************************************************
+ PUBLIC: void endin_cleanf()
+*****************************************************/
+
 /* Wiley puts multiple authors separated by commas on the %A lines.
  * We can detect this by finding the terminal comma in the data.
  *
@@ -370,51 +263,265 @@
 	return 1;
 }
 
-static void
+static int
 cleanup_wiley_author( fields *endin, int n )
 {	
-	newstr tmp, tmppart;
-	int i, nauthor = 0;
-	newstrs_init( &tmp, &tmppart, NULL );
-	newstr_newstrcpy( &tmp, &( endin->data[n] ) );
-	i = 0;
-	while ( i<tmp.len ) {
-		if ( tmp.data[i]==',' ) {
-			if ( nauthor==0 )
-				newstr_newstrcpy( &(endin->data[n]), &tmppart );
-			else
-				fields_add( endin, endin->tag[n].data,
-					tmppart.data, endin->level[n] );
-			newstr_empty( &tmppart );
+	newstr *instring, copy, name;
+	int status, nauthor = 0;
+	char *p;
+
+	newstrs_init( &copy, &name, NULL );
+
+	instring = &( endin->data[n] );
+	newstr_newstrcpy( &copy, instring );
+
+	p = copy.data;
+	while ( *p ) {
+		if ( *p==',' ) {
+			if ( newstr_memerr( &name ) )
+				return BIBL_ERR_MEMERR;
+			if ( nauthor==0 ) {
+				/* ...replace the first author in the field */
+				newstr_newstrcpy( instring, &name );
+				if ( newstr_memerr( instring ) )
+					return BIBL_ERR_MEMERR;
+			} else {
+				status = fields_add( endin, endin->tag[n].data,
+					name.data, endin->level[n] );
+				if ( status!=FIELDS_OK )
+					return BIBL_ERR_MEMERR;
+			}
+			newstr_empty( &name );
 			nauthor++;
-			while ( i<tmp.len && is_ws( tmp.data[i] ) ) i++;
+			p++;
+			while ( is_ws( *p ) ) p++;
 		} else {
-			newstr_addchar( &tmppart, tmp.data[i] );
+			newstr_addchar( &name, *p );
+			p++;
 		}
-		i++;
 	}
-	newstrs_free( &tmp, &tmppart, NULL );
+
+	newstrs_free( &copy, &name, NULL );
+	return BIBL_OK;
 }
 
-static void
+static int
 endin_cleanref( fields *endin )
 {
-	int i, n;
+	int i, n, status;
 	n = fields_num( endin );
 	for ( i=0; i<n; ++i ) {
-		if ( is_wiley_author( endin, i ) )
-			cleanup_wiley_author( endin, i );
+		if ( is_wiley_author( endin, i ) ) {
+			status = cleanup_wiley_author( endin, i );
+			if ( status!=BIBL_OK ) return status;
+		}
 	}
+	return BIBL_OK;
 }
 
-void
+int
 endin_cleanf( bibl *bin, param *p )
 {
         long i;
         for ( i=0; i<bin->nrefs; ++i )
                 endin_cleanref( bin->ref[i] );
+	return BIBL_OK;
 }
 
+/*****************************************************
+ 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
+ * otherwise return 0
+ */
+static int
+month_convert( char *in, char *out )
+{
+	char *month1[12]={
+		"January",   "February",
+		"March",     "April",
+		"May",       "June",
+		"July",      "August",
+		"September", "October",
+		"November",  "December"
+	};
+	char *month2[12]={
+		"Jan", "Feb",
+		"Mar", "Apr",
+		"May", "Jun",
+		"Jul", "Aug",
+		"Sep", "Oct",
+		"Nov", "Dec"
+	};
+	int i, found = -1;
+
+	for ( i=0; i<12 && found==-1; ++i ) {
+		if ( !strcasecmp( in, month1[i] ) ) found = i;
+		if ( !strcasecmp( in, month2[i] ) ) found = i;
+	}
+
+	if ( found==-1 ) return 0;
+
+	if ( found > 8 )
+		sprintf( out, "%d", found+1 );
+	else
+		sprintf( out, "0%d", found+1 );
+
+	return 1;
+}
+
+static int
+endin_adddate( fields *info, char *tag, char *newtag, char *p, int level )
+{
+	char *tags[3][2] = {
+		{ "YEAR",  "PARTYEAR" },
+		{ "MONTH", "PARTMONTH" },
+		{ "DAY",   "PARTDAY" }
+	};
+	char month[10], *m;
+	int part, status;
+	newstr date;
+
+	newstr_init( &date );
+
+	if ( !strncasecmp( newtag, "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 ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+		}
+	}
+
+	/* %8 MONTH DAY, YEAR */
+	/* %8 MONTH, YEAR */
+	/* %8 MONTH YEAR */
+	else if ( !strcasecmp( tag, "%8" ) ) {
+
+		/* ...get month */
+		p = newstr_cpytodelim( &date, skip_ws( p ), " ,\n", 0 );
+		if ( newstr_memerr( &date ) ) return BIBL_ERR_MEMERR;
+		if ( date.len>0 ) {
+			if ( month_convert( date.data, month ) ) m = month;
+			else m = date.data;
+			status = fields_add( info, tags[1][part], m, level );
+			if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+		}
+
+		p = skip_ws( p );
+		if ( *p==',' ) p++;
+
+		/* ...get days */
+		p = newstr_cpytodelim( &date, skip_ws( p ), ",\n", 0 );
+		if ( newstr_memerr( &date ) ) return BIBL_ERR_MEMERR;
+		if ( date.len>0 && date.len<3 ) {
+			status = fields_add( info, 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 );
+			if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+		}
+
+		p = skip_ws( p );
+		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 );
+			if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+		}
+	}
+	newstr_free( &date );
+	return BIBL_OK;
+}
+
+static int
+endin_addtype( fields *info, char *data, int level )
+{
+	lookups types[] = {
+		{ "GENERIC",                "ARTICLE" },
+		{ "BOOK",                   "BOOK" },
+		{ "MANUSCRIPT",             "MANUSCRIPT" },
+		{ "CONFERENCE PROCEEDINGS", "INPROCEEDINGS"},
+		{ "REPORT",                 "REPORT" },
+		{ "COMPUTER PROGRAM",       "BOOK" },
+		{ "AUDIOVISUAL MATERIAL",   "AUDIOVISUAL" },
+		{ "ARTWORK",                "BOOK" },
+		{ "PATENT",                 "BOOK" },
+		{ "BILL",                   "BILL" },
+		{ "CASE",                   "CASE" },
+		{ "JOURNAL ARTICLE",        "ARTICLE" },
+		{ "MAGAZINE ARTICLE",       "ARTICLE" },
+		{ "BOOK SECTION",           "INBOOK" },
+		{ "EDITED BOOK",            "BOOK" },
+		{ "NEWSPAPER ARTICLE",      "NEWSARTICLE" },
+		{ "THESIS",                 "PHDTHESIS" },
+		{ "PERSONAL COMMUNICATION", "COMMUNICATION" },
+		{ "ELECTRONIC SOURCE",      "TEXT" },
+		{ "FILM OR BROADCAST",      "AUDIOVISUAL" },
+		{ "MAP",                    "MAP" },
+		{ "HEARING",                "HEARING" },
+		{ "STATUTE",                "STATUTE" },
+		{ "CHART OR TABLE",         "CHART" },
+		{ "WEB PAGE",               "WEBPAGE" },
+	};
+	int  ntypes = sizeof( types ) / sizeof( lookups );
+	int  i, status, found=0;
+	for ( i=0; i<ntypes; ++i ) {
+		if ( !strcasecmp( types[i].oldstr, data ) ) {
+			found = 1;
+			status = fields_add( info, "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, "Defaulting to journal article type\n");
+		status = fields_add( info, "INTERNAL_TYPE", types[0].newstr, level );
+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	}
+	return BIBL_OK;
+}
+
 static void
 endin_notag( param *p, char *tag, char *data )
 {
@@ -426,19 +533,30 @@
 
 /* Wiley's EndNote download has DOI's in "%1" tag */
 static int
-endin_addnotes( fields *info, char *tag, char *data, int level )
+endin_addnotes( fields *info, char *tag, char *value, int level )
 {
-	int doi = is_doi( data );
+	int fstatus, doi;
+	doi = is_doi( value );
 	if ( doi!=-1 )
-		return fields_add( info, "DOI", &(data[doi]), level );
+		fstatus = fields_add( info, "DOI", &(value[doi]), level );
 	else
-		return fields_add( info, tag, data, level );
+		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 )
 {
-	int i, level, n, process, nfields, ok;
+	int i, level, n, process, nfields, ok, fstatus, status = BIBL_OK;
 	char *newtag, *t;
 	newstr *d;
 
@@ -457,7 +575,8 @@
 		 */
 		t = fields_tag( endin, i, FIELDS_CHRP );
 		if ( t[0]!='%' ) {
-			fields_add( info, t, d->data, endin->level[i] );
+			fstatus = fields_add( info, t, d->data, endin->level[i] );
+			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 			continue;
 		}
 
@@ -473,46 +592,52 @@
 		switch ( process ) {
 
 		case SIMPLE:
-			ok = fields_add( info, newtag, d->data, level );
+			status = endin_simple( info, newtag, d->data, level );
 			break;
 
 		case TYPE:
-			ok = endin_addtype( info, d->data, level );
+			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:
-			ok = endin_adddate( info, t, newtag,d->data,level);
+			status = endin_adddate( info, t, newtag,d->data,level);
 			break;
 
 		case PAGES:
-			ok = endin_addpage( info, d->data, level );
+			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:
-			ok = endin_addnotes( info, newtag, d->data, level );
+			status = endin_addnotes( info, newtag, d->data, level );
 			break;
 
 		default:
 			fprintf(stderr,"%s: internal error -- illegal process number %d\n", p->progname, process );
-			ok = 1;
+			status = BIBL_OK;
 			break;
 		}
 
-		if ( !ok ) return BIBL_ERR_MEMERR;
+		if ( status!=BIBL_OK ) return status;
 
 	}
 
-	return BIBL_OK;
+	return status;
 }
diff --git a/bibutils/endin.h b/bibutils/endin.h
--- a/bibutils/endin.h
+++ b/bibutils/endin.h
@@ -1,7 +1,7 @@
 /*
  * endin.h
  *
- * Copyright (c) Chris Putnam 2003-2013
+ * Copyright (c) Chris Putnam 2003-2014
  *
  * Source code released under the GPL version 2
  *
@@ -18,7 +18,7 @@
 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 void endin_cleanf( bibl *bin, param *p );
+extern int endin_cleanf( bibl *bin, param *p );
 
 extern void endin_initparams( param *p, const char *progname );
 
diff --git a/bibutils/endout.c b/bibutils/endout.c
--- a/bibutils/endout.c
+++ b/bibutils/endout.c
@@ -28,7 +28,7 @@
 	p->latexout         = 0;
 	p->utf8out          = BIBL_CHARSET_UTF8_DEFAULT;
 	p->utf8bom          = BIBL_CHARSET_BOM_DEFAULT;
-	p->xmlout           = 0;
+	p->xmlout           = BIBL_XMLOUT_FALSE;
 	p->nosplittitle     = 0;
 	p->verbose          = 0;
 	p->addcount         = 0;
@@ -87,13 +87,62 @@
 	TYPE_UNPUBLISHED,                 /* Unpublished Work */
 };
 
+static void
+write_type( FILE *fp, int type )
+{
+	switch( type ) {
+	case TYPE_UNKNOWN:           fprintf( fp, "TYPE_UNKNOWN" );            break;
+	case TYPE_GENERIC:           fprintf( fp, "TYPE_GENERIC" );            break;
+	case TYPE_ARTWORK:           fprintf( fp, "TYPE_ARTWORK" );            break;
+	case TYPE_AUDIOVISUAL:       fprintf( fp, "TYPE_AUDIOVISUAL" );        break;
+	case TYPE_BILL:              fprintf( fp, "TYPE_BILL" );               break;
+	case TYPE_BOOK:              fprintf( fp, "TYPE_BOOK" );               break;
+	case TYPE_INBOOK:            fprintf( fp, "TYPE_INBOOK" );             break;
+	case TYPE_CASE:              fprintf( fp, "TYPE_CASE" );               break;
+	case TYPE_CHARTTABLE:        fprintf( fp, "TYPE_CHARITABLE" );         break;
+	case TYPE_CLASSICALWORK:     fprintf( fp, "TYPE_CLASSICALWORK" );      break;
+	case TYPE_PROGRAM:           fprintf( fp, "TYPE_PROGRAM" );            break;
+	case TYPE_INPROCEEDINGS:     fprintf( fp, "TYPE_INPROCEEDINGS" );      break;
+	case TYPE_PROCEEDINGS:       fprintf( fp, "TYPE_PROCEEDINGS" );        break;
+	case TYPE_EDITEDBOOK:        fprintf( fp, "TYPE_EDITEDBOOK" );         break;
+	case TYPE_EQUATION:          fprintf( fp, "TYPE_EQUATION" );           break;
+	case TYPE_ELECTRONICARTICLE: fprintf( fp, "TYPE_ELECTRONICARTICLE" );  break;
+	case TYPE_ELECTRONICBOOK:    fprintf( fp, "TYPE_ELECTRONICBOOK" );     break;
+	case TYPE_ELECTRONIC:        fprintf( fp, "TYPE_ELECTRONIC" );         break;
+	case TYPE_FIGURE:            fprintf( fp, "TYPE_FIGURE" );             break;
+	case TYPE_FILMBROADCAST:     fprintf( fp, "TYPE_FILMBROADCAST" );      break;
+	case TYPE_GOVERNMENT:        fprintf( fp, "TYPE_GOVERNMENT" );         break;
+	case TYPE_HEARING:           fprintf( fp, "TYPE_HEARING" );            break;
+	case TYPE_ARTICLE:           fprintf( fp, "TYPE_ARTICLE" );            break;
+	case TYPE_LEGALRULE:         fprintf( fp, "TYPE_LEGALRULE" );          break;
+	case TYPE_MAGARTICLE:        fprintf( fp, "TYPE_MAGARTICLE" );         break;
+	case TYPE_MANUSCRIPT:        fprintf( fp, "TYPE_MANUSCRIPT" );         break;
+	case TYPE_MAP:               fprintf( fp, "TYPE_MAP" );                break;
+	case TYPE_NEWSARTICLE:       fprintf( fp, "TYPE_NEWSARTICLE" );        break;
+	case TYPE_ONLINEDATABASE:    fprintf( fp, "TYPE_ONLINEDATABASE" );     break;
+	case TYPE_ONLINEMULTIMEDIA:  fprintf( fp, "TYPE_ONLINEMULTIMEDIA" );   break;
+	case TYPE_PATENT:            fprintf( fp, "TYPE_PATENT" );             break;
+	case TYPE_COMMUNICATION:     fprintf( fp, "TYPE_COMMUNICATION" );      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_UNPUBLISHED:       fprintf( fp, "TYPE_UNPUBLISHED" );        break;
+	default:                     fprintf( fp, "Error - type not in enum" );break;
+	}
+}
+
 typedef struct match_type {
 	char *name;
 	int type;
 } match_type;
 
 static int
-get_type( fields *info )
+get_type( fields *info, param *p, unsigned long refnum )
 {
 	/* Comment out TYPE_GENERIC entries as that is default, but
          * keep in source as record of mapping decision. */
@@ -107,8 +156,10 @@
 /*		{ "bibliography",              TYPE_GENERIC },*/
 		{ "biography",                 TYPE_BOOK },
 		{ "book",                      TYPE_BOOK },
+/*		{ "calendar",                  TYPE_GENERIC },*/
 /*		{ "catalog",                   TYPE_GENERIC },*/
 		{ "chart",                     TYPE_CHARTTABLE },
+/*		{ "comic or graphic novel",    TYPE_GENERIC },*/
 /*		{ "comic strip",               TYPE_GENERIC },*/
 		{ "conference publication",    TYPE_PROCEEDINGS },
 		{ "database",                  TYPE_ONLINEDATABASE },
@@ -175,6 +226,7 @@
 /*		{ "slide",                     TYPE_GENERIC },*/
 		{ "sound",                     TYPE_AUDIOVISUAL },
 /*		{ "speech",                    TYPE_GENERIC },*/
+/*		{ "standard or specification", TYPE_GENERIC },*/
 /*		{ "statistics",                TYPE_GENERIC },*/
 /*		{ "survey of literature",      TYPE_GENERIC },*/
 		{ "technical drawing",         TYPE_ARTWORK },
@@ -201,9 +253,10 @@
 	};
 	int nmatch_genres = sizeof( match_genres ) / sizeof( match_genres[0] );
 
+	int i, j, n, maxlevel, type = TYPE_UNKNOWN;
 	char *tag, *data;
-	int i, j, type = TYPE_UNKNOWN;
 
+	/* Determine type from genre information */
 	for ( i=0; i<info->n; ++i ) {
 		tag = info->tag[i].data;
 		if ( strcasecmp( tag, "GENRE" )!=0 &&
@@ -215,6 +268,12 @@
 				fields_setused( info, 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 );
+			write_type( stderr, type );
+			fprintf( stderr, "\n" );
+		}
 		if ( type==TYPE_UNKNOWN ) {
 			if ( !strcasecmp( data, "periodical" ) )
 				type = TYPE_ARTICLE;
@@ -231,10 +290,16 @@
 			if ( type!=TYPE_UNKNOWN ) fields_setused( info, i );
 		}
 		/* the inbook type should be defined if 'book' in host */
-		if ( type==TYPE_BOOK && info->level[i]!=0 ) type = TYPE_INBOOK;
-		/* the article types should be defined if it's the host */
-		if ( ( type==TYPE_ARTICLE || type==TYPE_MAGARTICLE || type==TYPE_NEWSARTICLE ) && info->level[i]<1 ) type=TYPE_UNKNOWN;
+		if ( type==TYPE_BOOK && info->level[i]>0 ) type = TYPE_INBOOK;
 	}
+	if ( p->verbose ) {
+		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
+		fprintf( stderr, "Type from genre element: " );
+		write_type( stderr, type );
+		fprintf( stderr, "\n" );
+	}
+
+	/* Determine from resource information */
 	if ( type==TYPE_UNKNOWN ) {
 		for ( i=0; i<info->n; ++i ) {
 			if ( strcasecmp( info->tag[i].data, "RESOURCE" ) )
@@ -246,10 +311,54 @@
 				type = TYPE_PROGRAM;
 			if ( type!=TYPE_UNKNOWN ) fields_setused( info, i );
 		}
+		if ( p->verbose ) {
+			if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
+			fprintf( stderr, "Type from resource element: " );
+			write_type( stderr, type );
+			fprintf( stderr, "\n" );
+		}
 	}
 
-	/* default to generic */
-	if ( type==TYPE_UNKNOWN ) type = TYPE_GENERIC;
+	/* Determine from issuance information */
+	if ( type==TYPE_UNKNOWN ) {
+		for ( i=0; i<info->n; ++i ) {
+			if ( strcasecmp( info->tag[i].data, "ISSUANCE" ) )
+				continue;
+			data = info->data[i].data;
+			if ( !strcasecmp( data, "monographic" ) ) {
+				if ( info->level[i]==0 ) type = TYPE_BOOK;
+				else type = TYPE_INBOOK;
+			}
+		}
+		if ( p->verbose ) {
+			if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
+			fprintf( stderr, "Type from issuance element: " );
+			write_type( stderr, type );
+			fprintf( stderr, "\n" );
+		}
+	}
+
+	/* default to generic or book chapter, depending on maxlevel */
+	if ( type==TYPE_UNKNOWN ) {
+		maxlevel = fields_maxlevel( info );
+		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 );
+			if ( n!=-1 )
+				fprintf( stderr, " %s", info->data[n].data );
+			fprintf( stderr, " (defaulting to generic)\n" );
+			type = TYPE_GENERIC;
+		}
+	}
+
+	if ( p->verbose ) {
+		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
+		fprintf( stderr, "Final type: " );
+		write_type( stderr, type );
+		fprintf( stderr, "\n" );
+	}
 	
 	return type;
 }
@@ -524,7 +633,7 @@
 
 	fields_clearused( info );
 
-	type = get_type( info );
+	type = get_type( info, p, refnum );
 
 	output_type( fp, type, p );
 
@@ -597,6 +706,7 @@
 	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 );
diff --git a/bibutils/endxmlin.c b/bibutils/endxmlin.c
--- a/bibutils/endxmlin.c
+++ b/bibutils/endxmlin.c
@@ -1,7 +1,7 @@
 /*
  * endxmlin.c
  *
- * Copyright (c) Chris Putnam 2006-2013
+ * Copyright (c) Chris Putnam 2006-2014
  *
  * Program and source code released under the GPL version 2
  *
@@ -23,6 +23,9 @@
 	char *internal;
 } attribs;
 
+/*****************************************************
+ PUBLIC: void endxmlin_initparams()
+*****************************************************/
 void
 endxmlin_initparams( param *p, const char *progname )
 {
@@ -52,6 +55,10 @@
 	else p->progname = strdup( progname );
 }
 
+/*****************************************************
+ PUBLIC: int endxmlin_readf()
+*****************************************************/
+
 static int
 xml_readmore( FILE *fp, char *buf, int bufsize, int *bufpos )
 {
@@ -110,6 +117,10 @@
 	return haveref;
 }
 
+/*****************************************************
+ PUBLIC: int endxmlin_processf()
+*****************************************************/
+
 /*
  * add data to fields
  */
@@ -127,26 +138,39 @@
  *          <style>aaa</style><style>aaaa</style>
  *   </datatype>
  */
-void
+static int
 endxmlin_datar( xml *node, newstr *s )
 {
-	if ( node->value && node->value->len )
+	int status;
+	if ( node->value && node->value->len ) {
 		newstr_strcat( s, node->value->data );
-	if ( node->down && xml_tagexact( node->down, "style" ) )
-		endxmlin_datar( node->down, s );
-	if ( xml_tagexact( node, "style" ) && node->next )
-		endxmlin_datar( node->next, s );
+		if ( newstr_memerr( s ) ) return BIBL_ERR_MEMERR;
+	}
+	if ( node->down && xml_tagexact( node->down, "style" ) ) {
+		status = endxmlin_datar( node->down, s );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( xml_tagexact( node, "style" ) && node->next ) {
+		status = endxmlin_datar( node->next, s );
+		if ( status!=BIBL_OK ) return status;
+	}
+	return BIBL_OK;
 }
 
-void
+static int
 endxmlin_data( xml *node, char *inttag, fields *info, int level )
 {
+	int status;
 	newstr s;
 	newstr_init( &s );
-	endxmlin_datar( node, &s );
-	if ( s.len )
-		fields_add( info, inttag, s.data, level );
+	status = endxmlin_datar( node, &s );
+	if ( status!=BIBL_OK ) return status;
+	if ( s.len ) {
+		status = fields_add( info, inttag, s.data, level );
+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	}
 	newstr_free( &s );
+	return BIBL_OK;
 }
 
 /* <titles>
@@ -155,7 +179,7 @@
  *    </title>
  * </titles>
  */
-void
+static int
 endxmlin_titles( xml *node, fields *info )
 {
 	attribs a[] = {
@@ -165,20 +189,26 @@
 		{ "alt-title", "%!" },
 		{ "short-title", "SHORTTITLE" },
 	};
-	int i, n = sizeof( a ) / sizeof ( a[0] );
+	int i, status, n = sizeof( a ) / sizeof ( a[0] );
 	newstr title;
 	newstr_init( &title );
 	for ( i=0; i<n; ++i ) {
 		if ( xml_tagexact( node, a[i].attrib ) && node->down ) {
 			newstr_empty( &title );
-			endxmlin_datar( node, &title );
+			status = endxmlin_datar( node, &title );
+			if ( status!=BIBL_OK ) return BIBL_ERR_MEMERR;
 			newstr_trimstartingws( &title );
 			newstr_trimendingws( &title );
-			fields_add( info, a[i].internal, title.data, 0);
+			status = fields_add( info, a[i].internal, title.data, 0);
+			if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 		}
 	}
-	if ( node->next ) endxmlin_titles( node->next, info );
+	if ( node->next ) {
+		status = endxmlin_titles( node->next, info );
+		if ( status!=BIBL_OK ) return status;
+	}
 	newstr_free( &title );
+	return BIBL_OK;
 }
 
 /* <contributors>
@@ -202,65 +232,84 @@
  * >
  *
  */
-void
+static int
 endxmlin_contributor( xml *node, fields *info, char *int_tag, int level )
 {
-	endxmlin_data( node, int_tag, info, level );
-	if ( node->next )
-		endxmlin_contributor( node->next, info, int_tag, level );
+	int status;
+	status = endxmlin_data( node, int_tag, info, level );
+	if ( status!=BIBL_OK ) return status;
+	if ( node->next ) {
+		status = endxmlin_contributor( node->next, info, int_tag, level );
+		if ( status!=BIBL_OK ) return status;
+	}
+	return BIBL_OK;
 }
 
-static void
+static int
 endxmlin_contributors( xml *node, fields *info )
 {
-	attribs contrib[] = {
+	attribs a[] = {
 		{ "authors", "%A" },
 		{ "secondary-authors", "%E" },
 		{ "tertiary-authors", "%Y" },
 		{ "subsidiary-authors", "%?" },
 		{ "translated-authors", "%?" },
 	};
-	int i, n = sizeof( contrib ) / sizeof ( contrib[0] );
+	int i, status, n = sizeof( a ) / sizeof ( a[0] );
 	for ( i=0; i<n; ++i ) {
-		if ( xml_tagexact( node, contrib[i].attrib ) && node->down )
-			endxmlin_contributor( node->down, info, contrib[i].internal, 0 );
+		if ( xml_tagexact( node, a[i].attrib ) && node->down ) {
+			status = endxmlin_contributor( node->down, info, a[i].internal, 0 );
+			if ( status!=BIBL_OK ) return status;
+		}
 	}
-	if ( node->next )
-		endxmlin_contributors( node->next, info );
+	if ( node->next ) {
+		status = endxmlin_contributors( node->next, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	return BIBL_OK;
 }
 
-static void
+static int
 endxmlin_keyword( xml *node, fields *info )
 {
-	if ( xml_tagexact( node, "keyword" ) )
-		endxmlin_data( node, "%K", info, 0 );
-	if ( node->next )
-		endxmlin_keyword( node->next, info );
+	int status;
+	if ( xml_tagexact( node, "keyword" ) ) {
+		status = endxmlin_data( node, "%K", info, 0 );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->next ) {
+		status = endxmlin_keyword( node->next, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	return BIBL_OK;
 }
 
-static void
+static int
 endxmlin_keywords( xml *node, fields *info )
 {
 	if ( node->down && xml_tagexact( node->down, "keyword" ) )
-		endxmlin_keyword( node->down, info );
+		return endxmlin_keyword( node->down, info );
+	return BIBL_OK;
 }
 
 /*
  *<electronic-resource-num><style face="normal" font="default" 
  * size="100%">10.1007/BF00356334</style></electronic-resource-num>
  */
-static void
+static int
 endxmlin_ern( xml *node, fields *info )
 {
 	if ( xml_tagexact( node, "electronic-resource-num" ) )
-		endxmlin_data( node, "DOI", info, 0 );
+		return endxmlin_data( node, "DOI", info, 0 );
+	return BIBL_OK;
 }
 
-static void
+static int
 endxmlin_language( xml *node, fields *info )
 {
 	if ( xml_tagexact( node, "language" ) )
-		endxmlin_data( node, "%G", info, 0 );
+		return endxmlin_data( node, "%G", info, 0 );
+	return BIBL_OK;
 }
 
 /*
@@ -270,77 +319,108 @@
  *    </pdf-urls>
  * </urls>
  */
-static void
+static int
 endxmlin_fileattach( xml *node, fields *info )
 {
-	if ( xml_tagexact( node, "url" ) )
-		endxmlin_data( node, "FILEATTACH", info, 0 );
-	if ( node->down ) endxmlin_fileattach( node->down, info );
-	if ( node->next ) endxmlin_fileattach( node->next, info );
+	int status;
+	if ( xml_tagexact( node, "url" ) ) {
+		status = endxmlin_data( node, "FILEATTACH", info, 0 );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->down ) {
+		status = endxmlin_fileattach( node->down, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->next ) {
+		status = endxmlin_fileattach( node->next, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	return BIBL_OK;
 }
 
-static void
+static int
 endxmlin_urls( xml *node, fields *info )
 {
-	if ( xml_tagexact( node, "pdf-urls" ) && node->down )
-		endxmlin_fileattach( node->down, info );
-	else if ( xml_tagexact( node, "url" ) )
-		endxmlin_data( node, "%U", info, 0 );
-	else {
+	int status;
+	if ( xml_tagexact( node, "pdf-urls" ) && node->down ) {
+		status = endxmlin_fileattach( node->down, info );
+		if ( status!=BIBL_OK ) return status;
+	} else if ( xml_tagexact( node, "url" ) ) {
+		status = endxmlin_data( node, "%U", info, 0 );
+		if ( status!=BIBL_OK ) return status;
+	} else {
 		if ( node->down ) {
 			if ( xml_tagexact( node->down, "related-urls" ) ||
 			     xml_tagexact( node->down, "pdf-urls" ) ||
-			     xml_tagexact( node->down, "url" ) )
-				endxmlin_urls( node->down, info );
+			     xml_tagexact( node->down, "url" ) ) {
+				status = endxmlin_urls( node->down, info );
+				if ( status!=BIBL_OK ) return status;
+			}
 		}
 	}
-	if ( node->next )
-		endxmlin_urls( node->next, info );
+	if ( node->next ) {
+		status = endxmlin_urls( node->next, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	return BIBL_OK;
 }
 
-static void
+static int
 endxmlin_pubdates( xml *node, fields *info )
 {
 	if ( xml_tagexact( node, "date" ) )
-		endxmlin_data( node, "%8", info, 0 );
+		return endxmlin_data( node, "%8", info, 0 );
 	else {
 		if ( node->down && xml_tagexact( node->down, "date" ) )
-			endxmlin_pubdates( node->down, info );
+			return endxmlin_pubdates( node->down, info );
 	}
+	return BIBL_OK;
 }
 
-static void
+static int
 endxmlin_dates( xml *node, fields *info )
 {
-	if ( xml_tagexact( node, "year" ) )
-		endxmlin_data( node, "%D", info, 0 );
-	else {
+	int status;
+	if ( xml_tagexact( node, "year" ) ) {
+		status = endxmlin_data( node, "%D", info, 0 );
+		if ( status!=BIBL_OK ) return status;
+	} else {
 		if ( node->down ) {
-			if ( xml_tagexact( node->down, "year" ) )
-				endxmlin_dates( node->down, info );
-			if ( xml_tagexact( node->down, "pub-dates" ) )
-				endxmlin_pubdates( node->down, info );
+			if ( xml_tagexact( node->down, "year" ) ) {
+				status = endxmlin_dates( node->down, info );
+				if ( status!=BIBL_OK ) return status;
+			}
+			if ( xml_tagexact( node->down, "pub-dates" ) ) {
+				status = endxmlin_pubdates( node->down, info );
+				if ( status!=BIBL_OK );
+			}
 		}
 	}
-	if ( node->next )
-		endxmlin_dates( node->next, info );
+	if ( node->next ) {
+		status = endxmlin_dates( node->next, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	return BIBL_OK;
 }
 
 /*
  * <ref-type name="Journal Article">17</ref-type>
  */
-static void
+static int
 endxmlin_reftype( xml *node, fields *info )
 {
+	int status;
 	newstr *s;
 	s = xml_getattrib( node, "name" );
-	if ( s && s->dim ) {
-		fields_add( info, "%0", s->data, 0 );
+	if ( s && s->len ) {
+		status = fields_add( info, "%0", s->data, 0 );
 		newstr_free( s );
+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
+	return BIBL_OK;
 }
 
-static void
+static int
 endxmlin_record( xml *node, fields *info )
 {
 	attribs a[] = {
@@ -369,28 +449,35 @@
 		{ "custom5", "%#" },
 		{ "custom6", "%$" },
 	};
-	int i, n = sizeof ( a ) / sizeof( a[0] );
+	int i, status, n = sizeof ( a ) / sizeof( a[0] );
 	if ( xml_tagexact( node, "DATABASE" ) ) {
-/*		endxmlin_database( node, info );*/
 	} else if ( xml_tagexact( node, "SOURCE-APP" ) ) {
-/*		endxmlin_sourceapp( node, info );*/
 	} else if ( xml_tagexact( node, "REC-NUMBER" ) ) {
 	} else if ( xml_tagexact( node, "ref-type" ) ) {
-		endxmlin_reftype( node, info );
+		status = endxmlin_reftype( node, info );
+		if ( status!=BIBL_OK ) return status;
 	} else if ( xml_tagexact( node, "contributors" ) ) {
-		if ( node->down ) endxmlin_contributors( node->down, info );
+		if ( node->down ) {
+			status = endxmlin_contributors( node->down, info );
+			if ( status!=BIBL_OK ) return status;
+		}
 	} else if ( xml_tagexact( node, "titles" ) ) {
 		if ( node->down ) endxmlin_titles( node->down, info );
 	} else if ( xml_tagexact( node, "keywords" ) ) {
-		endxmlin_keywords( node, info );
+		status = endxmlin_keywords( node, info );
+		if ( status!=BIBL_OK ) return status;
 	} else if ( xml_tagexact( node, "urls" ) ) {
-		endxmlin_urls( node, info );
+		status = endxmlin_urls( node, info );
+		if ( status!=BIBL_OK ) return status;
 	} else if ( xml_tagexact( node, "electronic-resource-num" ) ) {
-		endxmlin_ern( node, info );
+		status = endxmlin_ern( node, info );
+		if ( status!=BIBL_OK ) return status;
 	} else if ( xml_tagexact( node, "dates" ) ) {
-		endxmlin_dates( node, info );
+		status = endxmlin_dates( node, info );
+		if ( status!=BIBL_OK ) return status;
 	} else if ( xml_tagexact( node, "language" ) ) {
-		endxmlin_language( node, info );
+		status = endxmlin_language( node, info );
+		if ( status!=BIBL_OK ) return status;
 	} else if ( xml_tagexact( node, "periodical" ) ) {
 	} else if ( xml_tagexact( node, "secondary-volume" ) ) {
 	} else if ( xml_tagexact( node, "secondary-issue" ) ) {
@@ -419,22 +506,33 @@
 	} else if ( xml_tagexact( node, "misc3" ) ) {
 	} else {
 		for ( i=0; i<n; ++i ) {
-			if ( xml_tagexact( node, a[i].attrib ) ) 
-				endxmlin_data( node, a[i].internal, info, 0 );
+			if ( xml_tagexact( node, a[i].attrib ) ) {
+				status = endxmlin_data( node, a[i].internal, info, 0 );
+				if ( status!=BIBL_OK ) return status;
+			}
 		}
 	}
-	if ( node->next ) endxmlin_record( node->next, info );
+	if ( node->next ) {
+		status = endxmlin_record( node->next, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	return BIBL_OK;
 }
 
-static void
+static int
 endxmlin_assembleref( xml *node, fields *info )
 {
+	int status;
 	if ( node->tag->len==0 ) {
-		if ( node->down ) endxmlin_assembleref( node->down, info );
-		return;
+		if ( node->down )
+			return endxmlin_assembleref( node->down, info );
 	} else if ( xml_tagexact( node, "RECORD" ) ) {
-		if ( node->down ) endxmlin_record( node->down, info );
+		if ( node->down ) {
+			status = endxmlin_record( node->down, info );
+			if ( status!=BIBL_OK ) return status;
+		}
 	}
+	return BIBL_OK;
 }
 
 /* endxmlin_processf first operates by converting to endnote input
@@ -446,10 +544,14 @@
 int
 endxmlin_processf( fields *fin, char *data, char *filename, long nref )
 {
+	int status;
 	xml top;
+
 	xml_init( &top );
 	xml_tree( data, &top );
-	endxmlin_assembleref( &top, fin );
+	status = endxmlin_assembleref( &top, fin );
 	xml_free( &top );
-	return 1;
+
+	if ( status==BIBL_OK ) return 1;
+	return 0;
 }
diff --git a/bibutils/endxmlin.h b/bibutils/endxmlin.h
--- a/bibutils/endxmlin.h
+++ b/bibutils/endxmlin.h
@@ -1,7 +1,7 @@
 /*
  * endxmlin.h
  *
- * Copyright (c) Chris Putnam 2006-2013
+ * Copyright (c) Chris Putnam 2006-2014
  *
  * Source code released under the GPL version 2
  *
diff --git a/bibutils/fields.c b/bibutils/fields.c
--- a/bibutils/fields.c
+++ b/bibutils/fields.c
@@ -10,7 +10,6 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <string.h>
-#include <assert.h>
 #include "fields.h"
 
 fields*
@@ -24,8 +23,6 @@
 void
 fields_init( fields *f )
 {
-	assert( f );
-
 	f->used  = NULL;
 	f->level = NULL;
 	f->tag   = NULL;
@@ -38,8 +35,6 @@
 {
 	int i;
 
-	assert( f );
-
 	for ( i=0; i<f->max; ++i ) {
 		newstr_free( &(f->tag[i]) );
 		newstr_free( &(f->data[i]) );
@@ -67,7 +62,7 @@
 		if ( f->used )  free( f->used );
 		if ( f->level ) free( f->level );
 		fields_init( f );
-		return 0;
+		return FIELDS_ERR;
 	}
 
 	f->max = alloc;
@@ -76,7 +71,7 @@
 		newstr_init( &(f->tag[i]) );
 		newstr_init( &(f->data[i]) );
 	}
-	return 1;
+	return FIELDS_OK;
 }
 
 static int
@@ -97,7 +92,7 @@
 	if ( newlevel ) f->level = newlevel;
 	
 	if ( !newtags || !newdata || !newused || !newlevel )
-		return 0;
+		return FIELDS_ERR;
 
 	f->max = alloc;
 
@@ -106,22 +101,22 @@
 		newstr_init( &(f->data[i]) );
 	}
 
-	return 1;
+	return FIELDS_OK;
 }
 
 int
 fields_add( fields *f, char *tag, char *data, int level )
 {
-	int i, found;
-
-	assert( f );
+	int i, status, found;
 
-	if ( !tag || !data ) return 1;
+	if ( !tag || !data ) return FIELDS_OK;
 
 	if ( f->max==0 ) {
-		if ( !fields_alloc( f ) ) return 0;
+		status = fields_alloc( f );
+		if ( status!=FIELDS_OK ) return status;
 	} else if ( f->n >= f->max ) {
-		if ( !fields_realloc( f ) ) return 0;
+		status = fields_realloc( f );
+		if ( status!=FIELDS_OK ) return status;
 	}
 
 	/* Don't duplicate identical entries */
@@ -132,13 +127,16 @@
 		     !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 );
-		f->used[ f->n ] = 0;
-		f->level[ f->n ] = level;
+		if ( newstr_memerr( &(f->tag[f->n]) ) ||
+		     newstr_memerr( &(f->data[f->n] ) ) )
+			return FIELDS_ERR;
 		f->n++;
 	}
-	return 1;
+	return FIELDS_OK;
 }
 
 int
@@ -148,44 +146,26 @@
 	newstr newtag;
 	int ret;
 
-	assert( f );
-	assert( tag );
-	assert( suffix );
-
 	newstr_init( &newtag );
 	newstr_mergestrs( &newtag, tag, suffix, NULL );
-	ret = fields_add( f, newtag.data, data, level );
+	if ( newstr_memerr( &newtag ) ) ret = FIELDS_ERR;
+	else ret = fields_add( f, newtag.data, data, level );
 	newstr_free( &newtag );
 
 	return ret;
 }
 
-/* fields_get_level()
- *
- */
-inline int
-fields_get_level( fields *f, int n )
-{
-	assert( f );
-	assert( n>=0 );
-	assert( n<f->n );
-
-	return f->level[n];
-}
-
 /* fields_match_level()
  *
  * returns 1 if level matched, 0 if not
  *
- * level==-1 is a special flag meaning any level can match
+ * level==LEVEL_ANY is a special flag meaning any level can match
  */
 inline int
 fields_match_level( fields *f, int n, int level )
 {
-	assert( f );
-
 	if ( level==LEVEL_ANY ) return 1;
-	if ( fields_get_level( f, n )==level ) return 1;
+	if ( fields_level( f, n )==level ) return 1;
 	return 0;
 }
 
@@ -232,9 +212,6 @@
 {
 	int i;
 
-	assert( f );
-	assert( tag );
-
 	for ( i=0; i<f->n; ++i ) {
 		if ( !fields_match_casetag_level( f, i, tag, level ) )
 			continue;
@@ -254,11 +231,12 @@
 {
 	int i, max = 0;
 
-	assert( f );
-
-	for ( i=0; i<f->n; ++i ) {
-		if ( f->level[i] > max )
-			max = f->level[i];
+	if ( f->n ) {
+		max = f->level[0];
+		for ( i=1; i<f->n; ++i ) {
+			if ( f->level[i] > max )
+				max = f->level[i];
+		}
 	}
 
 	return max;
@@ -269,8 +247,6 @@
 {
 	int i;
 
-	assert( f );
-
 	for ( i=0; i<f->n; ++i )
 		f->used[i] = 0;
 }
@@ -278,15 +254,13 @@
 void
 fields_setused( fields *f, int n )
 {
-	assert( f );
-
-	if ( n < f->n )
+	if ( n >= 0 && n < f->n )
 		f->used[n] = 1;
 }
 
 /* fields_replace_or_add()
  *
- * return 1 on success, 0 on memory error
+ * return FIELDS_OK on success, FIELDS_ERR on memory error
  */
 int
 fields_replace_or_add( fields *f, char *tag, char *data, int level )
@@ -295,7 +269,8 @@
 	if ( n==-1 ) return fields_add( f, tag, data, level );
 	else {
 		newstr_strcpy( &(f->data[n]), data );
-		return 1;
+		if ( newstr_memerr( &(f->data[n]) ) ) return FIELDS_ERR;
+		return FIELDS_OK;
 	}
 }
 
@@ -304,7 +279,7 @@
 inline int
 fields_used( fields *f, int n )
 {
-	if ( n < f->n ) return f->used[n];
+	if ( n >= 0 && n < f->n ) return f->used[n];
 	else return 0;
 }
 
@@ -312,7 +287,7 @@
 fields_nodata( fields *f, int n )
 {
 	newstr *d;
-	if ( n < f->n ) {
+	if ( n >= 0 && n < f->n ) {
 		d = &( f->data[n] );
 		if ( d->len > 0 ) return 0;
 		return 1;
@@ -324,7 +299,6 @@
 inline int
 fields_num( fields *f )
 {
-	assert( f );
 	return f->n;
 }
 
@@ -346,9 +320,7 @@
 {
 	intptr_t retn;
 
-	assert( f );
-	assert( n >= 0 );
-	assert( n < f->n );
+	if ( n<0 || n>= f->n ) return NULL;
 
 	if ( mode & FIELDS_SETUSE_FLAG )
 		fields_setused( f, n );
@@ -371,9 +343,7 @@
 {
 	intptr_t retn;
 
-	assert( f );
-	assert( n >= 0 );
-	assert( n < f->n );
+	if ( n<0 || n>= f->n ) return NULL;
 
 	if ( mode & FIELDS_STRP_FLAG )
 		return &(f->tag[n]);
@@ -391,10 +361,7 @@
 int
 fields_level( fields *f, int n )
 {
-	assert( f );
-	assert( n >= 0 );
-	assert( n < f->n );
-
+	if ( n<0 || n>= f->n ) return 0;
 	return f->level[n];
 }
 
@@ -404,9 +371,6 @@
 	int i, found = -1;
 	intptr_t retn;
 
-	assert( f );
-	assert( tag );
-
 	for ( i=0; i<f->n && found==-1; ++i ) {
 
 		if ( !fields_match_level( f, i, level ) ) continue;
@@ -442,8 +406,6 @@
 	char *tag, *value;
 	va_list argp;
 
-	assert( f );
-
 	va_start( argp, mode );
 	while ( ( tag = ( char * ) va_arg( argp, char * ) ) ) {
 		value = fields_findv( f, level, mode, tag );
@@ -462,10 +424,7 @@
 {
 	intptr_t retn;
 
-	assert( a );
-	assert( f );
-	assert( n >= 0 );
-	assert( n < f->n );
+	if ( n<0 || n>= f->n ) return;
 
 	if ( mode & FIELDS_SETUSE_FLAG )
 		fields_setused( f, n );
@@ -485,10 +444,6 @@
 {
 	int i;
 
-	assert( a );
-	assert( tag );
-	assert( f );
-
 	for ( i=0; i<f->n; ++i ) {
 
 		if ( !fields_match_level( f, i, level ) ) continue;
@@ -514,9 +469,6 @@
 	vplist tags;
 	char *tag;
 	int i, j, found;
-
-	assert( f );
-	assert( a );
 
 	vplist_init( &tags );
 
diff --git a/bibutils/fields.h b/bibutils/fields.h
--- a/bibutils/fields.h
+++ b/bibutils/fields.h
@@ -1,7 +1,7 @@
 /*
  * fields.h
  *
- * Copyright (c) Chris Putnam 2003-2013
+ * Copyright (c) Chris Putnam 2003-2014
  *
  * Source code released under the GPL version 2
  *
@@ -9,6 +9,9 @@
 #ifndef FIELDS_H
 #define FIELDS_H
 
+#define FIELDS_OK     (1)
+#define FIELDS_ERR    (0)
+
 #define LEVEL_ANY    (-1)
 #define LEVEL_MAIN    (0)
 #define LEVEL_HOST    (1)
@@ -45,7 +48,6 @@
 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 );
-extern inline int fields_get_level( fields *f, int n );
 
 extern inline int fields_match_level( fields *f, int n, int level );
 extern inline int fields_match_tag( fields *f, int n, char *tag );
diff --git a/bibutils/intlist.c b/bibutils/intlist.c
--- a/bibutils/intlist.c
+++ b/bibutils/intlist.c
@@ -3,6 +3,8 @@
  *
  * Copyright (c) Chris Putnam 2007-2013
  *
+ * Version 9/5/2013
+ *
  * Source code released under the GPL version 2
  *
  * Implements a simple managed array of ints
@@ -10,55 +12,75 @@
  */
 #include "intlist.h"
 
-static void
-memerr( const char *f )
-{
-	fprintf( stderr, "Memory error in %s\n", f );
-	exit( EXIT_FAILURE );
-}
-
-static void
+static int
 intlist_alloc( intlist *il )
 {
 	int alloc = 20, i;
 	il->data = ( int * ) malloc( sizeof( int ) * alloc );
-	if ( !(il->data) ) memerr( __FUNCTION__ );
+	if ( !(il->data) ) return 0;
 	for ( i=0; i<alloc; ++i )
 		il->data[i] = 0;
 	il->max = alloc;
 	il->n = 0;
+	return 1;
 }
 
-static void
+static int
 intlist_realloc( intlist *il )
 {
 	int *more;
 	int alloc = il->max * 2, i;
 	more = ( int * ) realloc( il->data, sizeof( int ) * alloc );
-	if ( !more ) memerr( __FUNCTION__ );
+	if ( !more ) return 0;
 	il->data = more;
 	for ( i=il->max; i<alloc; ++i )
 		il->data[i] = 0;
 	il->max = alloc;
+	return 1;
 }
 
+/* intlist_add()
+ *
+ * Returns position of newly added value in range [0,n), -1 on error
+ */
 int
 intlist_add( intlist *il, int value )
 {
-	if ( il->max==0 ) intlist_alloc( il );
-	else if ( il->n >= il->max ) intlist_realloc( il );
+	if ( il->max==0 ) {
+		if ( !intlist_alloc( il ) ) return -1;
+	} else if ( il->n >= il->max ) {
+		if ( !intlist_realloc( il ) ) return -1;
+	}
 	il->data[ il->n ] = value;
 	il->n++;
 	return il->n - 1;
 }
 
+/* intlist_add_unique()
+ *
+ * Returns position of newly added (or previously added) value
+ * Returns -1 on (memory) error
+ */
 int
 intlist_add_unique( intlist *il, int value )
 {
-	if ( intlist_find( il, value )!=-1 ) return il->n - 1;
-	else return intlist_add( il, value );
+	int n;
+	n = intlist_find( il, value );
+	if ( n==-1 )
+		n = intlist_add( il, value );
+	return n;
 }
+int
+intlist_find_or_add( intlist *il, int value )
+{
+	return intlist_add_unique( il, value );
+}
 
+/* intlist_find()
+ *
+ * Returns position of value in range [0,n), or -1 if
+ * value cannot be found
+ */
 int
 intlist_find( intlist *il, int value )
 {
@@ -68,7 +90,6 @@
 	return -1;
 }
 
-/* Here we know that pos is valid */
 static void
 intlist_remove_pos_core( intlist *il, int pos )
 {
@@ -78,32 +99,30 @@
 	il->n -= 1;
 }
 
-void
+/* intlist_remove_pos()
+ *
+ * Returns 1 on success, 0 on failure.
+ */
+int
 intlist_remove_pos( intlist *il, int pos )
 {
-	if ( pos < 0 || pos >= il->n ) return;
+	if ( pos < 0 || pos >= il->n ) return 0;
 	intlist_remove_pos_core( il, pos );
+	return 1;
 }
 
-void
+/* intlist_remove()
+ *
+ * Removes first instance of value from the intlist.
+ * Returns 1 on success, 0 on error.
+ */
+int
 intlist_remove( intlist *il, int value )
 {
 	int pos = intlist_find( il, value );
-	if ( pos==-1 ) return;
+	if ( pos==-1 ) return 0;
 	intlist_remove_pos_core( il, pos );
-}
-
-/* Return the index of searched-for string.
- * If cannot find string, add to list and then
- * return the index
- */
-int
-intlist_find_or_add( intlist *il, int value )
-{
-	int n = intlist_find( il, value );
-	if ( n==-1 )
-		n = intlist_add( il, value );
-	return n;
+	return 1;
 }
 
 /* don't actually free space, just reset counter */
@@ -121,6 +140,13 @@
 }
 
 void
+intlist_delete( intlist *il )
+{
+	intlist_free( il );
+	free( il );
+}
+
+void
 intlist_init( intlist *il  )
 {
 	il->data = NULL;
@@ -128,15 +154,28 @@
 	il->n = 0;
 }
 
-void
+/* intlist_init_range()
+ *
+ * Initializes intlist to values from [low,high) with step step.
+ * Returns -1 on failure, number of elements on success.
+ */
+int
 intlist_init_range( intlist *il, int low, int high, int step )
 {
-	int i;
+	int i, n;
 	intlist_init( il );
-	for ( i=low; i<high; i+= step )
-		intlist_add( il, i );
+	for ( i=low; i<high; i+= step ) {
+		n = intlist_add( il, i );
+		if ( n==-1 ) return -1;
+	}
+	return il->n;
 }
 
+/* intlist_new()
+ *
+ * Allocates an empty intlist.
+ * Returns pointer to intlist on success, NULL on memory error.
+ */
 intlist *
 intlist_new( void )
 {
@@ -145,11 +184,25 @@
 	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;
+ */
 intlist *
 intlist_new_range( int low, int high, int step )
 {
-	intlist *il = ( intlist * ) malloc( sizeof( intlist ) );
-	if ( il ) intlist_init_range( il, low, high, step );
+	intlist *il;
+	int n;
+	il = ( intlist * ) malloc( sizeof( intlist ) );
+	if ( il ) {
+		n = intlist_init_range( il, low, high, step );
+		if ( n==-1 ) {
+			intlist_free( il );
+			free( il );
+			il = NULL;
+		}
+	}
 	return il;
 }
 
@@ -198,47 +251,66 @@
 	}
 }
 
-void
+/* Returns 1 on success, 0 on error */
+int
 intlist_copy( intlist *to, intlist *from )
 {
 	int i;
 	intlist_free( to );
 	to->data = ( int* ) malloc( sizeof( int ) * from->n );
-	if ( !to->data ) return;
+	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;
 }
 
+/* Returns pointer on success, NULL on error */
 intlist *
 intlist_dup( intlist *il )
 {
 	intlist *l;
-	l = ( intlist* ) malloc( sizeof( intlist ) );
-	if ( !l ) goto err0;
-	intlist_copy( l, il );
-	return l;
-	free( l );
-err0:
+	int n;
+
+	l = intlist_new();
+	if ( l ) {
+		n = intlist_copy( l, il );
+		if ( !n ) {
+			intlist_delete( l );
+			l = NULL;
+		}
+	}
+
 	return l;
 }
 
-void
+int
 intlist_append( intlist *to, intlist *from )
 {
-	int i;
-	for ( i=0; i<from->n; ++i )
-		intlist_add( to, from->data[i] );
+	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;
+		}
+	}
+	return to->n;
 }
 
-void
+int
 intlist_append_unique( intlist *to, intlist *from )
 {
-	int i;
+	int i, n, nsave = to->n;
 	for ( i=0; i<from->n; ++i ) {
 		if ( intlist_find( to, from->data[i] )!=-1 ) continue;
-		intlist_add( to, from->data[i] );
+		n = intlist_add( to, from->data[i] );
+		if ( n==-1 ) {
+			to->n = nsave;
+			return -1;
+		}
 	}
+	return to->n;
 }
 
 int
@@ -248,3 +320,55 @@
 	else return il->data[pos];
 }
 
+/* intlist_set()
+ *
+ *   Returns 1 on success, 0 on failure
+ */
+int
+intlist_set( intlist *il, int pos, int value )
+{
+	if ( pos<0 || pos>=il->n ) return 0;
+	il->data[pos] = value;
+	return 1;
+}
+
+float
+intlist_median( intlist *il )
+{
+	intlist *tmp;
+	float median;
+	int m1, m2;
+
+	if ( il->n==0 ) return 0.0;
+
+	tmp = intlist_dup( il );
+	if ( !tmp ) return 0.0;
+
+	intlist_sort( tmp );
+
+	if ( tmp->n % 2 == 1 ) {
+		median = intlist_get( tmp, tmp->n / 2 );
+	} else {
+		m1 = intlist_get( tmp, tmp->n / 2 );
+		m2 = intlist_get( tmp, tmp->n / 2 + 1);
+		median = ( m1 + m2 ) / 2.0;
+	}
+
+	intlist_delete( tmp );
+
+	return median;
+}
+
+float
+intlist_mean( intlist *il )
+{
+	float sum = 0.0;
+	int i;
+
+	if ( il->n==0 ) return 0.0;
+
+	for ( i=0; i<il->n; ++i )
+		sum += intlist_get( il, i );
+
+	return sum / il->n;
+}
diff --git a/bibutils/intlist.h b/bibutils/intlist.h
--- a/bibutils/intlist.h
+++ b/bibutils/intlist.h
@@ -3,6 +3,8 @@
  *
  * Copyright (c) Chris Putnam 2007-2013
  *
+ * Version 9/5/2013
+ *
  * Source code released under the GPL version 2
  *
  */
@@ -18,23 +20,27 @@
 	int *data;
 } intlist;
 
-extern void intlist_init( intlist *info );
-extern void intlist_init_range( intlist *info, 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_sort( intlist *info );
-extern void intlist_randomize( intlist *info );
-extern int  intlist_add(  intlist *info, int value );
-extern int  intlist_add_unique(  intlist *info, int value );
-extern int  intlist_find( intlist *info, int searchvalue );
-extern int  intlist_find_or_add( intlist *info, int searchvalue );
-extern void intlist_empty( intlist *info );
-extern void intlist_free( intlist *info );
-extern void intlist_copy( intlist *to, intlist *from );
-extern int  intlist_get( intlist *info, int pos );
-extern void intlist_remove( intlist *info, int searchvalue );
-extern void intlist_remove_pos( intlist *info, int pos );
-extern void intlist_append( intlist *to, intlist *from );
-extern void intlist_append_unique( intlist *to, intlist *from );
+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 );
 
 #endif
diff --git a/bibutils/isiin.c b/bibutils/isiin.c
--- a/bibutils/isiin.c
+++ b/bibutils/isiin.c
@@ -19,6 +19,9 @@
 #include "reftypes.h"
 #include "isiin.h"
 
+/*****************************************************
+ PUBLIC: void isiin_initparams()
+*****************************************************/
 void
 isiin_initparams( param *p, const char *progname )
 {
@@ -48,6 +51,10 @@
 	else p->progname = strdup( progname );
 }
 
+/*****************************************************
+ PUBLIC: int isiin_readf()
+*****************************************************/
+
 /* ISI definition of a tag is strict:
  *   char 1 = uppercase alphabetic character
  *   char 2 = uppercase alphabetic character or digit
@@ -116,6 +123,10 @@
 	return haveref;
 }
 
+/*****************************************************
+ PUBLIC: int isiin_processf()
+*****************************************************/
+
 static char *
 process_isiline( newstr *tag, newstr *data, char *p )
 {
@@ -138,56 +149,48 @@
 int
 isiin_processf( fields *isiin, char *p, char *filename, long nref )
 {
+	int status, n, ret = 1;
 	newstr tag, data;
-	int n;
 	newstrs_init( &tag, &data, 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 ) ) {
-			fields_add( isiin, tag.data, data.data, 0 );
+			status = fields_add( isiin, tag.data, data.data, 0 );
+			if ( status!=FIELDS_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") ){
-					fields_add( isiin, "AU", data.data, 0);
+					status = fields_add( isiin, "AU", data.data, 0);
+					if ( status!=FIELDS_OK ) ret = 0;
 				} else if ( !strcmp( isiin->tag[n-1].data,"AF") ){
-					fields_add( isiin, "AF", data.data, 0);
+					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;
 			}
 		}
 	}
+out:
 	newstrs_free( &data, &tag, NULL );
-	return 1;
-}
-
-static int
-keyword_process( fields *info, char *newtag, char *p, int level )
-{
-	newstr keyword;
-	int ok;
-	newstr_init( &keyword );
-	while ( *p ) {
-		p = skip_ws( p );
-		while ( *p && *p!=';' ) newstr_addchar( &keyword, *p++ );
-		if ( keyword.len ) {
-			ok = fields_add( info, newtag, keyword.data, level );
-			if ( !ok ) return 0;
-			newstr_empty( &keyword );
-		}
-		if ( *p==';' ) p++;
-	}
-	newstr_free( &keyword );
-	return 1;
+	return ret;
 }
 
+/*****************************************************
+ PUBLIC: int isiin_typef()
+*****************************************************/
 int
 isiin_typef( fields *isiin, char *filename, int nref, param *p, variants *all, int nall )
 {
@@ -203,6 +206,29 @@
 	return reftype;
 }
 
+/*****************************************************
+ 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 )
@@ -228,9 +254,9 @@
 		level = ((all[reftype]).tags[n]).level;
 		newtag = all[reftype].tags[n].newstr;
 		ok = name_add( info, newtag, d->data, level, asis, corps );
-		if ( !ok ) return 0;
+		if ( !ok ) return BIBL_ERR_MEMERR;
 	}
-	return 1;
+	return BIBL_OK;
 }
 
 static void
@@ -242,15 +268,23 @@
 	}
 }
 
+static int
+isiin_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
 isiin_convertf( fields *isiin, fields *info, int reftype, param *p, variants *all, int nall )
 {
-	int process, level, i, n, nfields, ok;
+	int process, level, i, n, nfields, ok, status;
 	newstr *t, *d;
 	char *newtag;
 
-	ok = isiin_addauthors( isiin, info, reftype, all, nall, &(p->asis), &(p->corps) );
-	if ( !ok ) return BIBL_ERR_MEMERR;
+	status = isiin_addauthors( isiin, info, reftype, all, nall, &(p->asis), &(p->corps) );
+	if ( status!=BIBL_OK ) return status;
 
 	nfields = fields_num( isiin );
 	for ( i=0; i<nfields; ++i ) {
@@ -268,42 +302,46 @@
 
 		d = fields_value( isiin, i, FIELDS_STRP );
 
+		ok = 1;
+
 		switch ( process ) {
 
 		case SIMPLE:
-			ok = fields_add( info, newtag, d->data, level );
-			break;
-
 		case DATE:
-			ok = fields_add( info, newtag, d->data, level );
+			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:
-			ok = keyword_process( info, newtag, d->data, level );
+			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:
-			ok = 1;
+			status = BIBL_OK;
 			break;
 
 		}
 
-		/* do nothing if process==TYPE || process==ALWAYS */
-
-		if ( !ok ) return BIBL_ERR_MEMERR;
+		if ( status!=BIBL_OK ) return status;
 	}
 
-	return BIBL_OK;
+	return status;
 }
diff --git a/bibutils/isiout.c b/bibutils/isiout.c
--- a/bibutils/isiout.c
+++ b/bibutils/isiout.c
@@ -27,7 +27,7 @@
 	p->latexout         = 0;
 	p->utf8out          = BIBL_CHARSET_UTF8_DEFAULT;
 	p->utf8bom          = BIBL_CHARSET_BOM_DEFAULT;
-	p->xmlout           = 0;
+	p->xmlout           = BIBL_XMLOUT_FALSE;
 	p->nosplittitle     = 0;
 	p->verbose          = 0;
 	p->addcount         = 0;
diff --git a/bibutils/iso639_1.c b/bibutils/iso639_1.c
new file mode 100644
--- /dev/null
+++ b/bibutils/iso639_1.c
@@ -0,0 +1,211 @@
+/*
+ * iso639_1.c
+ */
+#include <string.h>
+#include "iso639_1.h"
+
+typedef struct {
+        char *code;
+        char *language;
+} iso639_1_t;
+
+static iso639_1_t iso639_1[] = {
+	{ "aa", "Afar" },
+	{ "ab", "Abkhazian" },
+	{ "ae", "Avestan" },
+	{ "af", "Afrikaans" },
+	{ "ak", "Akan" },
+	{ "am", "Amharic" },
+	{ "an", "Aragonese" },
+	{ "ar", "Arabic" },
+	{ "as", "Assamese" },
+	{ "av", "Avaric" },
+	{ "ay", "Aymara" },
+	{ "az", "Azerbaijani" },
+	{ "ba", "Bashkir" },
+	{ "be", "Belarusian" },
+	{ "bg", "Bulgarian" },
+	{ "bh", "Bihari languages" },
+	{ "bi", "Bislama" },
+	{ "bm", "Bambara" },
+	{ "bn", "Bengali" },
+	{ "bo", "Tibetan" },
+	{ "br", "Breton" },
+	{ "bs", "Bosnian" },
+	{ "ca", "Catalan" },
+	{ "ce", "Chechen" },
+	{ "ch", "Chamorro" },
+	{ "co", "Corsican" },
+	{ "cr", "Cree" },
+	{ "cs", "Czech" },
+	{ "cu", "Church Slavic" },
+	{ "cv", "Chuvash" },
+	{ "cy", "Welsh" },
+	{ "da", "Danish" },
+	{ "de", "German" },
+	{ "dv", "Dhivehi" },
+	{ "dz", "Dzongkha" },
+	{ "ee", "Ewe" },
+	{ "el", "Modern Greek" },
+	{ "en", "English" },
+	{ "eo", "Esperanto" },
+	{ "es", "Spanish" },
+	{ "et", "Estonian" },
+	{ "eu", "Basque" },
+	{ "fa", "Persian" },
+	{ "ff", "Fulah" },
+	{ "fi", "Finnish" },
+	{ "fj", "Fijian" },
+	{ "fo", "Faroese" },
+	{ "fr", "French" },
+	{ "fy", "Western Frisian" },
+	{ "ga", "Irish" },
+	{ "gd", "Scottish Gaelic" },
+	{ "gl", "Galician" },
+	{ "gn", "Guarani" },
+	{ "gu", "Gujarati" },
+	{ "gv", "Manx" },
+	{ "ha", "Hausa" },
+	{ "he", "Hebrew" },
+	{ "hi", "Hindi" },
+	{ "ho", "Hiri Motu" },
+	{ "hr", "Croatian" },
+	{ "ht", "Haitian" },
+	{ "hu", "Hungarian" },
+	{ "hy", "Armenian" },
+	{ "hz", "Herero" },
+	{ "ia", "Interlingua" },
+	{ "id", "Indonesian" },
+	{ "ie", "Interlingue" },
+	{ "ig", "Igbo" },
+	{ "ii", "Sichuan Yi" },
+	{ "ik", "Inupiaq" },
+	{ "io", "Ido" },
+	{ "is", "Icelandic" },
+	{ "it", "Italian" },
+	{ "iu", "Inuktitut" },
+	{ "ja", "Japanese" },
+	{ "jv", "Javanese" },
+	{ "ka", "Georgian" },
+	{ "kg", "Kongo" },
+	{ "ki", "Kikuyu" },
+	{ "kj", "Kuanyama" },
+	{ "kk", "Kazakh" },
+	{ "kl", "Kalaallisut" },
+	{ "km", "Central Khmer" },
+	{ "kn", "Kannada" },
+	{ "ko", "Korean" },
+	{ "kr", "Kanuri" },
+	{ "ks", "Kashmiri" },
+	{ "ku", "Kurdish" },
+	{ "kv", "Komi" },
+	{ "kw", "Cornish" },
+	{ "ky", "Kirghiz" },
+	{ "la", "Latin" },
+	{ "lb", "Luxembourgish" },
+	{ "lg", "Ganda" },
+	{ "li", "Limburgan" },
+	{ "ln", "Lingala" },
+	{ "lo", "Lao" },
+	{ "lt", "Lithuanian" },
+	{ "lu", "Luba-Katanga" },
+	{ "lv", "Latvian" },
+	{ "mg", "Malagasy" },
+	{ "mh", "Marshallese" },
+	{ "mi", "Maori" },
+	{ "mk", "Macedonian" },
+	{ "ml", "Malayalam" },
+	{ "mn", "Mongolian" },
+	{ "mr", "Marathi" },
+	{ "ms", "Malay" },
+	{ "mt", "Maltese" },
+	{ "my", "Burmese" },
+	{ "na", "Nauru" },
+	{ "nb", "Norwegian Bokmål" },
+	{ "nd", "North Ndebele" },
+	{ "ne", "Nepali" },
+	{ "ng", "Ndonga" },
+	{ "nl", "Dutch" },
+	{ "nn", "Norwegian Nynorsk" },
+	{ "no", "Norwegian" },
+	{ "nr", "South Ndebele" },
+	{ "nv", "Navajo" },
+	{ "ny", "Nyanja" },
+	{ "oc", "Occitan" },
+	{ "oj", "Ojibwa" },
+	{ "om", "Oromo" },
+	{ "or", "Oriya" },
+	{ "os", "Ossetian" },
+	{ "pa", "Panjabi" },
+	{ "pi", "Pali" },
+	{ "pl", "Polish" },
+	{ "ps", "Pushto" },
+	{ "pt", "Portuguese" },
+	{ "qu", "Quechua" },
+	{ "rm", "Romansh" },
+	{ "rn", "Rundi" },
+	{ "ro", "Romanian" },
+	{ "ru", "Russian" },
+	{ "rw", "Kinyarwanda" },
+	{ "sa", "Sanskrit" },
+	{ "sc", "Sardinian" },
+	{ "sd", "Sindhi" },
+	{ "se", "Northern Sami" },
+	{ "sg", "Sango" },
+	{ "sh", "Serbo-Croatian" },
+	{ "si", "Sinhala" },
+	{ "sk", "Slovak" },
+	{ "sl", "Slovenian" },
+	{ "sm", "Samoan" },
+	{ "sn", "Shona" },
+	{ "so", "Somali" },
+	{ "sq", "Albanian" },
+	{ "sr", "Serbian" },
+	{ "ss", "Swati" },
+	{ "st", "Southern Sotho" },
+	{ "su", "Sundanese" },
+	{ "sv", "Swedish" },
+	{ "sw", "Swahili" },
+	{ "ta", "Tamil" },
+	{ "te", "Telugu" },
+	{ "tg", "Tajik" },
+	{ "th", "Thai" },
+	{ "ti", "Tigrinya" },
+	{ "tk", "Turkmen" },
+	{ "tl", "Tagalog" },
+	{ "tn", "Tswana" },
+	{ "to", "Tonga" },
+	{ "tr", "Turkish" },
+	{ "ts", "Tsonga" },
+	{ "tt", "Tatar" },
+	{ "tw", "Twi" },
+	{ "ty", "Tahitian" },
+	{ "ug", "Uighur" },
+	{ "uk", "Ukrainian" },
+	{ "ur", "Urdu" },
+	{ "uz", "Uzbek" },
+	{ "ve", "Venda" },
+	{ "vi", "Vietnamese" },
+	{ "vo", "Volapük" },
+	{ "wa", "Walloon" },
+	{ "wo", "Wolof" },
+	{ "xh", "Xhosa" },
+	{ "yi", "Yiddish" },
+	{ "yo", "Yoruba" },
+	{ "za", "Zhuang" },
+	{ "zh", "Chinese" },
+	{ "zu", "Zulu" },
+};
+static int niso639_1= sizeof( iso639_1 ) / sizeof( iso639_1[0] );
+
+char *
+iso639_1_from_code( const char *code )
+{
+	int i;
+	for ( i=0; i<niso639_1; ++i ) {
+		if ( !strcasecmp( iso639_1[i].code, code ) )
+			return iso639_1[i].language;
+	}
+	return NULL;
+}
+
diff --git a/bibutils/iso639_1.h b/bibutils/iso639_1.h
new file mode 100644
--- /dev/null
+++ b/bibutils/iso639_1.h
@@ -0,0 +1,9 @@
+/*
+ * iso639_1.h
+ */
+#ifndef ISO639_1_H
+#define iSO639_1_H
+
+extern char * iso639_1_from_code( const char *code );
+
+#endif
diff --git a/bibutils/iso639_3.c b/bibutils/iso639_3.c
new file mode 100644
--- /dev/null
+++ b/bibutils/iso639_3.c
@@ -0,0 +1,8419 @@
+/*
+ * iso639_3.c
+ */
+#include <string.h>
+#include "iso639_3.h"
+
+typedef struct {
+        char *code;
+        char *language;
+} iso639_3_t;
+
+static iso639_3_t iso639_3[] = {
+	{ "aaa", "Ghotuo" },
+	{ "aab", "Alumu-Tesu" },
+	{ "aac", "Ari" },
+	{ "aad", "Amal" },
+	{ "aae", "Arbëreshë Albanian" },
+	{ "aaf", "Aranadan" },
+	{ "aag", "Ambrak" },
+	{ "aah", "Abu' Arapesh" },
+	{ "aai", "Arifama-Miniafia" },
+	{ "aak", "Ankave" },
+	{ "aal", "Afade" },
+	{ "aam", "Aramanik" },
+	{ "aan", "Anambé" },
+	{ "aao", "Algerian Saharan Arabic" },
+	{ "aap", "Pará Arára" },
+	{ "aaq", "Eastern Abnaki" },
+	{ "aar", "Afar" },
+	{ "aas", "Aasáx" },
+	{ "aat", "Arvanitika Albanian" },
+	{ "aau", "Abau" },
+	{ "aaw", "Solong" },
+	{ "aax", "Mandobo Atas" },
+	{ "aaz", "Amarasi" },
+	{ "aba", "Abé" },
+	{ "abb", "Bankon" },
+	{ "abc", "Ambala Ayta" },
+	{ "abd", "Manide" },
+	{ "abe", "Western Abnaki" },
+	{ "abf", "Abai Sungai" },
+	{ "abg", "Abaga" },
+	{ "abh", "Tajiki Arabic" },
+	{ "abi", "Abidji" },
+	{ "abj", "Aka-Bea" },
+	{ "abk", "Abkhazian" },
+	{ "abl", "Lampung Nyo" },
+	{ "abm", "Abanyom" },
+	{ "abn", "Abua" },
+	{ "abo", "Abon" },
+	{ "abp", "Abellen Ayta" },
+	{ "abq", "Abaza" },
+	{ "abr", "Abron" },
+	{ "abs", "Ambonese Malay" },
+	{ "abt", "Ambulas" },
+	{ "abu", "Abure" },
+	{ "abv", "Baharna Arabic" },
+	{ "abw", "Pal" },
+	{ "abx", "Inabaknon" },
+	{ "aby", "Aneme Wake" },
+	{ "abz", "Abui" },
+	{ "aca", "Achagua" },
+	{ "acb", "Áncá" },
+	{ "acd", "Gikyode" },
+	{ "ace", "Achinese" },
+	{ "acf", "Saint Lucian Creole French" },
+	{ "ach", "Acoli" },
+	{ "aci", "Aka-Cari" },
+	{ "ack", "Aka-Kora" },
+	{ "acl", "Akar-Bale" },
+	{ "acm", "Mesopotamian Arabic" },
+	{ "acn", "Achang" },
+	{ "acp", "Eastern Acipa" },
+	{ "acq", "Ta'izzi-Adeni Arabic" },
+	{ "acr", "Achi" },
+	{ "acs", "Acroá" },
+	{ "act", "Achterhoeks" },
+	{ "acu", "Achuar-Shiwiar" },
+	{ "acv", "Achumawi" },
+	{ "acw", "Hijazi Arabic" },
+	{ "acx", "Omani Arabic" },
+	{ "acy", "Cypriot Arabic" },
+	{ "acz", "Acheron" },
+	{ "ada", "Adangme" },
+	{ "adb", "Adabe" },
+	{ "add", "Dzodinka" },
+	{ "ade", "Adele" },
+	{ "adf", "Dhofari Arabic" },
+	{ "adg", "Andegerebinha" },
+	{ "adh", "Adhola" },
+	{ "adi", "Adi" },
+	{ "adj", "Adioukrou" },
+	{ "adl", "Galo" },
+	{ "adn", "Adang" },
+	{ "ado", "Abu" },
+	{ "adp", "Adap" },
+	{ "adq", "Adangbe" },
+	{ "adr", "Adonara" },
+	{ "ads", "Adamorobe Sign Language" },
+	{ "adt", "Adnyamathanha" },
+	{ "adu", "Aduge" },
+	{ "adw", "Amundava" },
+	{ "adx", "Amdo Tibetan" },
+	{ "ady", "Adyghe" },
+	{ "adz", "Adzera" },
+	{ "aea", "Areba" },
+	{ "aeb", "Tunisian Arabic" },
+	{ "aec", "Saidi Arabic" },
+	{ "aed", "Argentine Sign Language" },
+	{ "aee", "Northeast Pashayi" },
+	{ "aek", "Haeke" },
+	{ "ael", "Ambele" },
+	{ "aem", "Arem" },
+	{ "aen", "Armenian Sign Language" },
+	{ "aeq", "Aer" },
+	{ "aer", "Eastern Arrernte" },
+	{ "aes", "Alsea" },
+	{ "aeu", "Akeu" },
+	{ "aew", "Ambakich" },
+	{ "aey", "Amele" },
+	{ "aez", "Aeka" },
+	{ "afb", "Gulf Arabic" },
+	{ "afd", "Andai" },
+	{ "afe", "Putukwam" },
+	{ "afg", "Afghan Sign Language" },
+	{ "afh", "Afrihili" },
+	{ "afi", "Akrukay" },
+	{ "afk", "Nanubae" },
+	{ "afn", "Defaka" },
+	{ "afo", "Eloyi" },
+	{ "afp", "Tapei" },
+	{ "afr", "Afrikaans" },
+	{ "afs", "Afro-Seminole Creole" },
+	{ "aft", "Afitti" },
+	{ "afu", "Awutu" },
+	{ "afz", "Obokuitai" },
+	{ "aga", "Aguano" },
+	{ "agb", "Legbo" },
+	{ "agc", "Agatu" },
+	{ "agd", "Agarabi" },
+	{ "age", "Angal" },
+	{ "agf", "Arguni" },
+	{ "agg", "Angor" },
+	{ "agh", "Ngelima" },
+	{ "agi", "Agariya" },
+	{ "agj", "Argobba" },
+	{ "agk", "Isarog Agta" },
+	{ "agl", "Fembe" },
+	{ "agm", "Angaataha" },
+	{ "agn", "Agutaynen" },
+	{ "ago", "Tainae" },
+	{ "agq", "Aghem" },
+	{ "agr", "Aguaruna" },
+	{ "ags", "Esimbi" },
+	{ "agt", "Central Cagayan Agta" },
+	{ "agu", "Aguacateco" },
+	{ "agv", "Remontado Dumagat" },
+	{ "agw", "Kahua" },
+	{ "agx", "Aghul" },
+	{ "agy", "Southern Alta" },
+	{ "agz", "Mt. Iriga Agta" },
+	{ "aha", "Ahanta" },
+	{ "ahb", "Axamb" },
+	{ "ahg", "Qimant" },
+	{ "ahh", "Aghu" },
+	{ "ahi", "Tiagbamrin Aizi" },
+	{ "ahk", "Akha" },
+	{ "ahl", "Igo" },
+	{ "ahm", "Mobumrin Aizi" },
+	{ "ahn", "Àhàn" },
+	{ "aho", "Ahom" },
+	{ "ahp", "Aproumu Aizi" },
+	{ "ahr", "Ahirani" },
+	{ "ahs", "Ashe" },
+	{ "aht", "Ahtena" },
+	{ "aia", "Arosi" },
+	{ "aib", "Ainu (China)" },
+	{ "aic", "Ainbai" },
+	{ "aid", "Alngith" },
+	{ "aie", "Amara" },
+	{ "aif", "Agi" },
+	{ "aig", "Antigua and Barbuda Creole English" },
+	{ "aih", "Ai-Cham" },
+	{ "aii", "Assyrian Neo-Aramaic" },
+	{ "aij", "Lishanid Noshan" },
+	{ "aik", "Ake" },
+	{ "ail", "Aimele" },
+	{ "aim", "Aimol" },
+	{ "ain", "Ainu (Japan)" },
+	{ "aio", "Aiton" },
+	{ "aip", "Burumakok" },
+	{ "aiq", "Aimaq" },
+	{ "air", "Airoran" },
+	{ "ais", "Nataoran Amis" },
+	{ "ait", "Arikem" },
+	{ "aiw", "Aari" },
+	{ "aix", "Aighon" },
+	{ "aiy", "Ali" },
+	{ "aja", "Aja (Sudan)" },
+	{ "ajg", "Aja (Benin)" },
+	{ "aji", "Ajië" },
+	{ "ajn", "Andajin" },
+	{ "ajp", "South Levantine Arabic" },
+	{ "ajt", "Judeo-Tunisian Arabic" },
+	{ "aju", "Judeo-Moroccan Arabic" },
+	{ "ajw", "Ajawa" },
+	{ "ajz", "Amri Karbi" },
+	{ "aka", "Akan" },
+	{ "akb", "Batak Angkola" },
+	{ "akc", "Mpur" },
+	{ "akd", "Ukpet-Ehom" },
+	{ "ake", "Akawaio" },
+	{ "akf", "Akpa" },
+	{ "akg", "Anakalangu" },
+	{ "akh", "Angal Heneng" },
+	{ "aki", "Aiome" },
+	{ "akj", "Aka-Jeru" },
+	{ "akk", "Akkadian" },
+	{ "akl", "Aklanon" },
+	{ "akm", "Aka-Bo" },
+	{ "ako", "Akurio" },
+	{ "akp", "Siwu" },
+	{ "akq", "Ak" },
+	{ "akr", "Araki" },
+	{ "aks", "Akaselem" },
+	{ "akt", "Akolet" },
+	{ "aku", "Akum" },
+	{ "akv", "Akhvakh" },
+	{ "akw", "Akwa" },
+	{ "akx", "Aka-Kede" },
+	{ "aky", "Aka-Kol" },
+	{ "akz", "Alabama" },
+	{ "ala", "Alago" },
+	{ "alc", "Qawasqar" },
+	{ "ald", "Alladian" },
+	{ "ale", "Aleut" },
+	{ "alf", "Alege" },
+	{ "alh", "Alawa" },
+	{ "ali", "Amaimon" },
+	{ "alj", "Alangan" },
+	{ "alk", "Alak" },
+	{ "all", "Allar" },
+	{ "alm", "Amblong" },
+	{ "aln", "Gheg Albanian" },
+	{ "alo", "Larike-Wakasihu" },
+	{ "alp", "Alune" },
+	{ "alq", "Algonquin" },
+	{ "alr", "Alutor" },
+	{ "als", "Tosk Albanian" },
+	{ "alt", "Southern Altai" },
+	{ "alu", "'Are'are" },
+	{ "alw", "Alaba-K’abeena" },
+	{ "alx", "Amol" },
+	{ "aly", "Alyawarr" },
+	{ "alz", "Alur" },
+	{ "ama", "Amanayé" },
+	{ "amb", "Ambo" },
+	{ "amc", "Amahuaca" },
+	{ "ame", "Yanesha'" },
+	{ "amf", "Hamer-Banna" },
+	{ "amg", "Amurdak" },
+	{ "amh", "Amharic" },
+	{ "ami", "Amis" },
+	{ "amj", "Amdang" },
+	{ "amk", "Ambai" },
+	{ "aml", "War-Jaintia" },
+	{ "amm", "Ama (Papua New Guinea)" },
+	{ "amn", "Amanab" },
+	{ "amo", "Amo" },
+	{ "amp", "Alamblak" },
+	{ "amq", "Amahai" },
+	{ "amr", "Amarakaeri" },
+	{ "ams", "Southern Amami-Oshima" },
+	{ "amt", "Amto" },
+	{ "amu", "Guerrero Amuzgo" },
+	{ "amv", "Ambelau" },
+	{ "amw", "Western Neo-Aramaic" },
+	{ "amx", "Anmatyerre" },
+	{ "amy", "Ami" },
+	{ "amz", "Atampaya" },
+	{ "ana", "Andaqui" },
+	{ "anb", "Andoa" },
+	{ "anc", "Ngas" },
+	{ "and", "Ansus" },
+	{ "ane", "Xârâcùù" },
+	{ "anf", "Animere" },
+	{ "ang", "Old English (ca. 450-1100)" },
+	{ "anh", "Nend" },
+	{ "ani", "Andi" },
+	{ "anj", "Anor" },
+	{ "ank", "Goemai" },
+	{ "anl", "Anu-Hkongso Chin" },
+	{ "anm", "Anal" },
+	{ "ann", "Obolo" },
+	{ "ano", "Andoque" },
+	{ "anp", "Angika" },
+	{ "anq", "Jarawa (India)" },
+	{ "anr", "Andh" },
+	{ "ans", "Anserma" },
+	{ "ant", "Antakarinya" },
+	{ "anu", "Anuak" },
+	{ "anv", "Denya" },
+	{ "anw", "Anaang" },
+	{ "anx", "Andra-Hus" },
+	{ "any", "Anyin" },
+	{ "anz", "Anem" },
+	{ "aoa", "Angolar" },
+	{ "aob", "Abom" },
+	{ "aoc", "Pemon" },
+	{ "aod", "Andarum" },
+	{ "aoe", "Angal Enen" },
+	{ "aof", "Bragat" },
+	{ "aog", "Angoram" },
+	{ "aoh", "Arma" },
+	{ "aoi", "Anindilyakwa" },
+	{ "aoj", "Mufian" },
+	{ "aok", "Arhö" },
+	{ "aol", "Alor" },
+	{ "aom", "Ömie" },
+	{ "aon", "Bumbita Arapesh" },
+	{ "aor", "Aore" },
+	{ "aos", "Taikat" },
+	{ "aot", "A'tong" },
+	{ "aou", "A'ou" },
+	{ "aox", "Atorada" },
+	{ "aoz", "Uab Meto" },
+	{ "apb", "Sa'a" },
+	{ "apc", "North Levantine Arabic" },
+	{ "apd", "Sudanese Arabic" },
+	{ "ape", "Bukiyip" },
+	{ "apf", "Pahanan Agta" },
+	{ "apg", "Ampanang" },
+	{ "aph", "Athpariya" },
+	{ "api", "Apiaká" },
+	{ "apj", "Jicarilla Apache" },
+	{ "apk", "Kiowa Apache" },
+	{ "apl", "Lipan Apache" },
+	{ "apm", "Mescalero-Chiricahua Apache" },
+	{ "apn", "Apinayé" },
+	{ "apo", "Ambul" },
+	{ "app", "Apma" },
+	{ "apq", "A-Pucikwar" },
+	{ "apr", "Arop-Lokep" },
+	{ "aps", "Arop-Sissano" },
+	{ "apt", "Apatani" },
+	{ "apu", "Apurinã" },
+	{ "apv", "Alapmunte" },
+	{ "apw", "Western Apache" },
+	{ "apx", "Aputai" },
+	{ "apy", "Apalaí" },
+	{ "apz", "Safeyoka" },
+	{ "aqc", "Archi" },
+	{ "aqd", "Ampari Dogon" },
+	{ "aqg", "Arigidi" },
+	{ "aqm", "Atohwaim" },
+	{ "aqn", "Northern Alta" },
+	{ "aqp", "Atakapa" },
+	{ "aqr", "Arhâ" },
+	{ "aqz", "Akuntsu" },
+	{ "ara", "Arabic" },
+	{ "arb", "Standard Arabic" },
+	{ "arc", "Official Aramaic (700-300 BCE)" },
+	{ "ard", "Arabana" },
+	{ "are", "Western Arrarnta" },
+	{ "arg", "Aragonese" },
+	{ "arh", "Arhuaco" },
+	{ "ari", "Arikara" },
+	{ "arj", "Arapaso" },
+	{ "ark", "Arikapú" },
+	{ "arl", "Arabela" },
+	{ "arn", "Mapudungun" },
+	{ "aro", "Araona" },
+	{ "arp", "Arapaho" },
+	{ "arq", "Algerian Arabic" },
+	{ "arr", "Karo (Brazil)" },
+	{ "ars", "Najdi Arabic" },
+	{ "aru", "Aruá (Amazonas State)" },
+	{ "arv", "Arbore" },
+	{ "arw", "Arawak" },
+	{ "arx", "Aruá (Rodonia State)" },
+	{ "ary", "Moroccan Arabic" },
+	{ "arz", "Egyptian Arabic" },
+	{ "asa", "Asu (Tanzania)" },
+	{ "asb", "Assiniboine" },
+	{ "asc", "Casuarina Coast Asmat" },
+	{ "asd", "Asas" },
+	{ "ase", "American Sign Language" },
+	{ "asf", "Australian Sign Language" },
+	{ "asg", "Cishingini" },
+	{ "ash", "Abishira" },
+	{ "asi", "Buruwai" },
+	{ "asj", "Sari" },
+	{ "ask", "Ashkun" },
+	{ "asl", "Asilulu" },
+	{ "asm", "Assamese" },
+	{ "asn", "Xingú Asuriní" },
+	{ "aso", "Dano" },
+	{ "asp", "Algerian Sign Language" },
+	{ "asq", "Austrian Sign Language" },
+	{ "asr", "Asuri" },
+	{ "ass", "Ipulo" },
+	{ "ast", "Asturian" },
+	{ "asu", "Tocantins Asurini" },
+	{ "asv", "Asoa" },
+	{ "asw", "Australian Aborigines Sign Language" },
+	{ "asx", "Muratayak" },
+	{ "asy", "Yaosakor Asmat" },
+	{ "asz", "As" },
+	{ "ata", "Pele-Ata" },
+	{ "atb", "Zaiwa" },
+	{ "atc", "Atsahuaca" },
+	{ "atd", "Ata Manobo" },
+	{ "ate", "Atemble" },
+	{ "atg", "Ivbie North-Okpela-Arhe" },
+	{ "ati", "Attié" },
+	{ "atj", "Atikamekw" },
+	{ "atk", "Ati" },
+	{ "atl", "Mt. Iraya Agta" },
+	{ "atm", "Ata" },
+	{ "atn", "Ashtiani" },
+	{ "ato", "Atong" },
+	{ "atp", "Pudtol Atta" },
+	{ "atq", "Aralle-Tabulahan" },
+	{ "atr", "Waimiri-Atroari" },
+	{ "ats", "Gros Ventre" },
+	{ "att", "Pamplona Atta" },
+	{ "atu", "Reel" },
+	{ "atv", "Northern Altai" },
+	{ "atw", "Atsugewi" },
+	{ "atx", "Arutani" },
+	{ "aty", "Aneityum" },
+	{ "atz", "Arta" },
+	{ "aua", "Asumboa" },
+	{ "aub", "Alugu" },
+	{ "auc", "Waorani" },
+	{ "aud", "Anuta" },
+	{ "aue", "=Kx'au'ein" },
+	{ "aug", "Aguna" },
+	{ "auh", "Aushi" },
+	{ "aui", "Anuki" },
+	{ "auj", "Awjilah" },
+	{ "auk", "Heyo" },
+	{ "aul", "Aulua" },
+	{ "aum", "Asu (Nigeria)" },
+	{ "aun", "Molmo One" },
+	{ "auo", "Auyokawa" },
+	{ "aup", "Makayam" },
+	{ "auq", "Anus" },
+	{ "aur", "Aruek" },
+	{ "aut", "Austral" },
+	{ "auu", "Auye" },
+	{ "auw", "Awyi" },
+	{ "aux", "Aurá" },
+	{ "auy", "Awiyaana" },
+	{ "auz", "Uzbeki Arabic" },
+	{ "ava", "Avaric" },
+	{ "avb", "Avau" },
+	{ "avd", "Alviri-Vidari" },
+	{ "ave", "Avestan" },
+	{ "avi", "Avikam" },
+	{ "avk", "Kotava" },
+	{ "avl", "Eastern Egyptian Bedawi Arabic" },
+	{ "avm", "Angkamuthi" },
+	{ "avn", "Avatime" },
+	{ "avo", "Agavotaguerra" },
+	{ "avs", "Aushiri" },
+	{ "avt", "Au" },
+	{ "avu", "Avokaya" },
+	{ "avv", "Avá-Canoeiro" },
+	{ "awa", "Awadhi" },
+	{ "awb", "Awa (Papua New Guinea)" },
+	{ "awc", "Cicipu" },
+	{ "awe", "Awetí" },
+	{ "awg", "Anguthimri" },
+	{ "awh", "Awbono" },
+	{ "awi", "Aekyom" },
+	{ "awk", "Awabakal" },
+	{ "awm", "Arawum" },
+	{ "awn", "Awngi" },
+	{ "awo", "Awak" },
+	{ "awr", "Awera" },
+	{ "aws", "South Awyu" },
+	{ "awt", "Araweté" },
+	{ "awu", "Central Awyu" },
+	{ "awv", "Jair Awyu" },
+	{ "aww", "Awun" },
+	{ "awx", "Awara" },
+	{ "awy", "Edera Awyu" },
+	{ "axb", "Abipon" },
+	{ "axe", "Ayerrerenge" },
+	{ "axg", "Mato Grosso Arára" },
+	{ "axk", "Yaka (Central African Republic)" },
+	{ "axl", "Lower Southern Aranda" },
+	{ "axm", "Middle Armenian" },
+	{ "axx", "Xârâgurè" },
+	{ "aya", "Awar" },
+	{ "ayb", "Ayizo Gbe" },
+	{ "ayc", "Southern Aymara" },
+	{ "ayd", "Ayabadhu" },
+	{ "aye", "Ayere" },
+	{ "ayg", "Ginyanga" },
+	{ "ayh", "Hadrami Arabic" },
+	{ "ayi", "Leyigha" },
+	{ "ayk", "Akuku" },
+	{ "ayl", "Libyan Arabic" },
+	{ "aym", "Aymara" },
+	{ "ayn", "Sanaani Arabic" },
+	{ "ayo", "Ayoreo" },
+	{ "ayp", "North Mesopotamian Arabic" },
+	{ "ayq", "Ayi (Papua New Guinea)" },
+	{ "ayr", "Central Aymara" },
+	{ "ays", "Sorsogon Ayta" },
+	{ "ayt", "Magbukun Ayta" },
+	{ "ayu", "Ayu" },
+	{ "ayy", "Tayabas Ayta" },
+	{ "ayz", "Mai Brat" },
+	{ "aza", "Azha" },
+	{ "azb", "South Azerbaijani" },
+	{ "azd", "Eastern Durango Nahuatl" },
+	{ "aze", "Azerbaijani" },
+	{ "azg", "San Pedro Amuzgos Amuzgo" },
+	{ "azj", "North Azerbaijani" },
+	{ "azm", "Ipalapa Amuzgo" },
+	{ "azn", "Western Durango Nahuatl" },
+	{ "azo", "Awing" },
+	{ "azt", "Faire Atta" },
+	{ "azz", "Highland Puebla Nahuatl" },
+	{ "baa", "Babatana" },
+	{ "bab", "Bainouk-Gunyuño" },
+	{ "bac", "Badui" },
+	{ "bae", "Baré" },
+	{ "baf", "Nubaca" },
+	{ "bag", "Tuki" },
+	{ "bah", "Bahamas Creole English" },
+	{ "baj", "Barakai" },
+	{ "bak", "Bashkir" },
+	{ "bal", "Baluchi" },
+	{ "bam", "Bambara" },
+	{ "ban", "Balinese" },
+	{ "bao", "Waimaha" },
+	{ "bap", "Bantawa" },
+	{ "bar", "Bavarian" },
+	{ "bas", "Basa (Cameroon)" },
+	{ "bau", "Bada (Nigeria)" },
+	{ "bav", "Vengo" },
+	{ "baw", "Bambili-Bambui" },
+	{ "bax", "Bamun" },
+	{ "bay", "Batuley" },
+	{ "bba", "Baatonum" },
+	{ "bbb", "Barai" },
+	{ "bbc", "Batak Toba" },
+	{ "bbd", "Bau" },
+	{ "bbe", "Bangba" },
+	{ "bbf", "Baibai" },
+	{ "bbg", "Barama" },
+	{ "bbh", "Bugan" },
+	{ "bbi", "Barombi" },
+	{ "bbj", "Ghomálá'" },
+	{ "bbk", "Babanki" },
+	{ "bbl", "Bats" },
+	{ "bbm", "Babango" },
+	{ "bbn", "Uneapa" },
+	{ "bbo", "Northern Bobo Madaré" },
+	{ "bbp", "West Central Banda" },
+	{ "bbq", "Bamali" },
+	{ "bbr", "Girawa" },
+	{ "bbs", "Bakpinka" },
+	{ "bbt", "Mburku" },
+	{ "bbu", "Kulung (Nigeria)" },
+	{ "bbv", "Karnai" },
+	{ "bbw", "Baba" },
+	{ "bbx", "Bubia" },
+	{ "bby", "Befang" },
+	{ "bbz", "Babalia Creole Arabic" },
+	{ "bca", "Central Bai" },
+	{ "bcb", "Bainouk-Samik" },
+	{ "bcc", "Southern Balochi" },
+	{ "bcd", "North Babar" },
+	{ "bce", "Bamenyam" },
+	{ "bcf", "Bamu" },
+	{ "bcg", "Baga Binari" },
+	{ "bch", "Bariai" },
+	{ "bci", "Baoulé" },
+	{ "bcj", "Bardi" },
+	{ "bck", "Bunaba" },
+	{ "bcl", "Central Bikol" },
+	{ "bcm", "Bannoni" },
+	{ "bcn", "Bali (Nigeria)" },
+	{ "bco", "Kaluli" },
+	{ "bcp", "Bali (Democratic Republic of Congo)" },
+	{ "bcq", "Bench" },
+	{ "bcr", "Babine" },
+	{ "bcs", "Kohumono" },
+	{ "bct", "Bendi" },
+	{ "bcu", "Awad Bing" },
+	{ "bcv", "Shoo-Minda-Nye" },
+	{ "bcw", "Bana" },
+	{ "bcy", "Bacama" },
+	{ "bcz", "Bainouk-Gunyaamolo" },
+	{ "bda", "Bayot" },
+	{ "bdb", "Basap" },
+	{ "bdc", "Emberá-Baudó" },
+	{ "bdd", "Bunama" },
+	{ "bde", "Bade" },
+	{ "bdf", "Biage" },
+	{ "bdg", "Bonggi" },
+	{ "bdh", "Baka (Sudan)" },
+	{ "bdi", "Burun" },
+	{ "bdj", "Bai" },
+	{ "bdk", "Budukh" },
+	{ "bdl", "Indonesian Bajau" },
+	{ "bdm", "Buduma" },
+	{ "bdn", "Baldemu" },
+	{ "bdo", "Morom" },
+	{ "bdp", "Bende" },
+	{ "bdq", "Bahnar" },
+	{ "bdr", "West Coast Bajau" },
+	{ "bds", "Burunge" },
+	{ "bdt", "Bokoto" },
+	{ "bdu", "Oroko" },
+	{ "bdv", "Bodo Parja" },
+	{ "bdw", "Baham" },
+	{ "bdx", "Budong-Budong" },
+	{ "bdy", "Bandjalang" },
+	{ "bdz", "Badeshi" },
+	{ "bea", "Beaver" },
+	{ "beb", "Bebele" },
+	{ "bec", "Iceve-Maci" },
+	{ "bed", "Bedoanas" },
+	{ "bee", "Byangsi" },
+	{ "bef", "Benabena" },
+	{ "beg", "Belait" },
+	{ "beh", "Biali" },
+	{ "bei", "Bekati'" },
+	{ "bej", "Beja" },
+	{ "bek", "Bebeli" },
+	{ "bel", "Belarusian" },
+	{ "bem", "Bemba (Zambia)" },
+	{ "ben", "Bengali" },
+	{ "beo", "Beami" },
+	{ "bep", "Besoa" },
+	{ "beq", "Beembe" },
+	{ "bes", "Besme" },
+	{ "bet", "Guiberoua Béte" },
+	{ "beu", "Blagar" },
+	{ "bev", "Daloa Bété" },
+	{ "bew", "Betawi" },
+	{ "bex", "Jur Modo" },
+	{ "bey", "Beli (Papua New Guinea)" },
+	{ "bez", "Bena (Tanzania)" },
+	{ "bfa", "Bari" },
+	{ "bfb", "Pauri Bareli" },
+	{ "bfc", "Northern Bai" },
+	{ "bfd", "Bafut" },
+	{ "bfe", "Betaf" },
+	{ "bff", "Bofi" },
+	{ "bfg", "Busang Kayan" },
+	{ "bfh", "Blafe" },
+	{ "bfi", "British Sign Language" },
+	{ "bfj", "Bafanji" },
+	{ "bfk", "Ban Khor Sign Language" },
+	{ "bfl", "Banda-Ndélé" },
+	{ "bfm", "Mmen" },
+	{ "bfn", "Bunak" },
+	{ "bfo", "Malba Birifor" },
+	{ "bfp", "Beba" },
+	{ "bfq", "Badaga" },
+	{ "bfr", "Bazigar" },
+	{ "bfs", "Southern Bai" },
+	{ "bft", "Balti" },
+	{ "bfu", "Gahri" },
+	{ "bfw", "Bondo" },
+	{ "bfx", "Bantayanon" },
+	{ "bfy", "Bagheli" },
+	{ "bfz", "Mahasu Pahari" },
+	{ "bga", "Gwamhi-Wuri" },
+	{ "bgb", "Bobongko" },
+	{ "bgc", "Haryanvi" },
+	{ "bgd", "Rathwi Bareli" },
+	{ "bge", "Bauria" },
+	{ "bgf", "Bangandu" },
+	{ "bgg", "Bugun" },
+	{ "bgi", "Giangan" },
+	{ "bgj", "Bangolan" },
+	{ "bgk", "Bit" },
+	{ "bgl", "Bo (Laos)" },
+	{ "bgm", "Baga Mboteni" },
+	{ "bgn", "Western Balochi" },
+	{ "bgo", "Baga Koga" },
+	{ "bgp", "Eastern Balochi" },
+	{ "bgq", "Bagri" },
+	{ "bgr", "Bawm Chin" },
+	{ "bgs", "Tagabawa" },
+	{ "bgt", "Bughotu" },
+	{ "bgu", "Mbongno" },
+	{ "bgv", "Warkay-Bipim" },
+	{ "bgw", "Bhatri" },
+	{ "bgx", "Balkan Gagauz Turkish" },
+	{ "bgy", "Benggoi" },
+	{ "bgz", "Banggai" },
+	{ "bha", "Bharia" },
+	{ "bhb", "Bhili" },
+	{ "bhc", "Biga" },
+	{ "bhd", "Bhadrawahi" },
+	{ "bhe", "Bhaya" },
+	{ "bhf", "Odiai" },
+	{ "bhg", "Binandere" },
+	{ "bhh", "Bukharic" },
+	{ "bhi", "Bhilali" },
+	{ "bhj", "Bahing" },
+	{ "bhl", "Bimin" },
+	{ "bhm", "Bathari" },
+	{ "bhn", "Bohtan Neo-Aramaic" },
+	{ "bho", "Bhojpuri" },
+	{ "bhp", "Bima" },
+	{ "bhq", "Tukang Besi South" },
+	{ "bhr", "Bara Malagasy" },
+	{ "bhs", "Buwal" },
+	{ "bht", "Bhattiyali" },
+	{ "bhu", "Bhunjia" },
+	{ "bhv", "Bahau" },
+	{ "bhw", "Biak" },
+	{ "bhx", "Bhalay" },
+	{ "bhy", "Bhele" },
+	{ "bhz", "Bada (Indonesia)" },
+	{ "bia", "Badimaya" },
+	{ "bib", "Bissa" },
+	{ "bic", "Bikaru" },
+	{ "bid", "Bidiyo" },
+	{ "bie", "Bepour" },
+	{ "bif", "Biafada" },
+	{ "big", "Biangai" },
+	{ "bij", "Vaghat-Ya-Bijim-Legeri" },
+	{ "bik", "Bikol" },
+	{ "bil", "Bile" },
+	{ "bim", "Bimoba" },
+	{ "bin", "Bini" },
+	{ "bio", "Nai" },
+	{ "bip", "Bila" },
+	{ "biq", "Bipi" },
+	{ "bir", "Bisorio" },
+	{ "bis", "Bislama" },
+	{ "bit", "Berinomo" },
+	{ "biu", "Biete" },
+	{ "biv", "Southern Birifor" },
+	{ "biw", "Kol (Cameroon)" },
+	{ "bix", "Bijori" },
+	{ "biy", "Birhor" },
+	{ "biz", "Baloi" },
+	{ "bja", "Budza" },
+	{ "bjb", "Banggarla" },
+	{ "bjc", "Bariji" },
+	{ "bje", "Biao-Jiao Mien" },
+	{ "bjf", "Barzani Jewish Neo-Aramaic" },
+	{ "bjg", "Bidyogo" },
+	{ "bjh", "Bahinemo" },
+	{ "bji", "Burji" },
+	{ "bjj", "Kanauji" },
+	{ "bjk", "Barok" },
+	{ "bjl", "Bulu (Papua New Guinea)" },
+	{ "bjm", "Bajelani" },
+	{ "bjn", "Banjar" },
+	{ "bjo", "Mid-Southern Banda" },
+	{ "bjp", "Fanamaket" },
+	{ "bjr", "Binumarien" },
+	{ "bjs", "Bajan" },
+	{ "bjt", "Balanta-Ganja" },
+	{ "bju", "Busuu" },
+	{ "bjv", "Bedjond" },
+	{ "bjw", "Bakwé" },
+	{ "bjx", "Banao Itneg" },
+	{ "bjy", "Bayali" },
+	{ "bjz", "Baruga" },
+	{ "bka", "Kyak" },
+	{ "bkc", "Baka (Cameroon)" },
+	{ "bkd", "Binukid" },
+	{ "bkf", "Beeke" },
+	{ "bkg", "Buraka" },
+	{ "bkh", "Bakoko" },
+	{ "bki", "Baki" },
+	{ "bkj", "Pande" },
+	{ "bkk", "Brokskat" },
+	{ "bkl", "Berik" },
+	{ "bkm", "Kom (Cameroon)" },
+	{ "bkn", "Bukitan" },
+	{ "bko", "Kwa'" },
+	{ "bkp", "Boko (Democratic Republic of Congo)" },
+	{ "bkq", "Bakairí" },
+	{ "bkr", "Bakumpai" },
+	{ "bks", "Northern Sorsoganon" },
+	{ "bkt", "Boloki" },
+	{ "bku", "Buhid" },
+	{ "bkv", "Bekwarra" },
+	{ "bkw", "Bekwel" },
+	{ "bkx", "Baikeno" },
+	{ "bky", "Bokyi" },
+	{ "bkz", "Bungku" },
+	{ "bla", "Siksika" },
+	{ "blb", "Bilua" },
+	{ "blc", "Bella Coola" },
+	{ "bld", "Bolango" },
+	{ "ble", "Balanta-Kentohe" },
+	{ "blf", "Buol" },
+	{ "blg", "Balau" },
+	{ "blh", "Kuwaa" },
+	{ "bli", "Bolia" },
+	{ "blj", "Bolongan" },
+	{ "blk", "Pa'o Karen" },
+	{ "bll", "Biloxi" },
+	{ "blm", "Beli (Sudan)" },
+	{ "bln", "Southern Catanduanes Bikol" },
+	{ "blo", "Anii" },
+	{ "blp", "Blablanga" },
+	{ "blq", "Baluan-Pam" },
+	{ "blr", "Blang" },
+	{ "bls", "Balaesang" },
+	{ "blt", "Tai Dam" },
+	{ "blv", "Bolo" },
+	{ "blw", "Balangao" },
+	{ "blx", "Mag-Indi Ayta" },
+	{ "bly", "Notre" },
+	{ "blz", "Balantak" },
+	{ "bma", "Lame" },
+	{ "bmb", "Bembe" },
+	{ "bmc", "Biem" },
+	{ "bmd", "Baga Manduri" },
+	{ "bme", "Limassa" },
+	{ "bmf", "Bom" },
+	{ "bmg", "Bamwe" },
+	{ "bmh", "Kein" },
+	{ "bmi", "Bagirmi" },
+	{ "bmj", "Bote-Majhi" },
+	{ "bmk", "Ghayavi" },
+	{ "bml", "Bomboli" },
+	{ "bmm", "Northern Betsimisaraka Malagasy" },
+	{ "bmn", "Bina (Papua New Guinea)" },
+	{ "bmo", "Bambalang" },
+	{ "bmp", "Bulgebi" },
+	{ "bmq", "Bomu" },
+	{ "bmr", "Muinane" },
+	{ "bms", "Bilma Kanuri" },
+	{ "bmt", "Biao Mon" },
+	{ "bmu", "Somba-Siawari" },
+	{ "bmv", "Bum" },
+	{ "bmw", "Bomwali" },
+	{ "bmx", "Baimak" },
+	{ "bmy", "Bemba (Democratic Republic of Congo)" },
+	{ "bmz", "Baramu" },
+	{ "bna", "Bonerate" },
+	{ "bnb", "Bookan" },
+	{ "bnc", "Bontok" },
+	{ "bnd", "Banda (Indonesia)" },
+	{ "bne", "Bintauna" },
+	{ "bnf", "Masiwang" },
+	{ "bng", "Benga" },
+	{ "bni", "Bangi" },
+	{ "bnj", "Eastern Tawbuid" },
+	{ "bnk", "Bierebo" },
+	{ "bnl", "Boon" },
+	{ "bnm", "Batanga" },
+	{ "bnn", "Bunun" },
+	{ "bno", "Bantoanon" },
+	{ "bnp", "Bola" },
+	{ "bnq", "Bantik" },
+	{ "bnr", "Butmas-Tur" },
+	{ "bns", "Bundeli" },
+	{ "bnu", "Bentong" },
+	{ "bnv", "Bonerif" },
+	{ "bnw", "Bisis" },
+	{ "bnx", "Bangubangu" },
+	{ "bny", "Bintulu" },
+	{ "bnz", "Beezen" },
+	{ "boa", "Bora" },
+	{ "bob", "Aweer" },
+	{ "bod", "Tibetan" },
+	{ "boe", "Mundabli" },
+	{ "bof", "Bolon" },
+	{ "bog", "Bamako Sign Language" },
+	{ "boh", "Boma" },
+	{ "boi", "Barbareño" },
+	{ "boj", "Anjam" },
+	{ "bok", "Bonjo" },
+	{ "bol", "Bole" },
+	{ "bom", "Berom" },
+	{ "bon", "Bine" },
+	{ "boo", "Tiemacèwè Bozo" },
+	{ "bop", "Bonkiman" },
+	{ "boq", "Bogaya" },
+	{ "bor", "Borôro" },
+	{ "bos", "Bosnian" },
+	{ "bot", "Bongo" },
+	{ "bou", "Bondei" },
+	{ "bov", "Tuwuli" },
+	{ "bow", "Rema" },
+	{ "box", "Buamu" },
+	{ "boy", "Bodo (Central African Republic)" },
+	{ "boz", "Tiéyaxo Bozo" },
+	{ "bpa", "Daakaka" },
+	{ "bpb", "Barbacoas" },
+	{ "bpd", "Banda-Banda" },
+	{ "bpg", "Bonggo" },
+	{ "bph", "Botlikh" },
+	{ "bpi", "Bagupi" },
+	{ "bpj", "Binji" },
+	{ "bpk", "Orowe" },
+	{ "bpl", "Broome Pearling Lugger Pidgin" },
+	{ "bpm", "Biyom" },
+	{ "bpn", "Dzao Min" },
+	{ "bpo", "Anasi" },
+	{ "bpp", "Kaure" },
+	{ "bpq", "Banda Malay" },
+	{ "bpr", "Koronadal Blaan" },
+	{ "bps", "Sarangani Blaan" },
+	{ "bpt", "Barrow Point" },
+	{ "bpu", "Bongu" },
+	{ "bpv", "Bian Marind" },
+	{ "bpw", "Bo (Papua New Guinea)" },
+	{ "bpx", "Palya Bareli" },
+	{ "bpy", "Bishnupriya" },
+	{ "bpz", "Bilba" },
+	{ "bqa", "Tchumbuli" },
+	{ "bqb", "Bagusa" },
+	{ "bqc", "Boko (Benin)" },
+	{ "bqd", "Bung" },
+	{ "bqf", "Baga Kaloum" },
+	{ "bqg", "Bago-Kusuntu" },
+	{ "bqh", "Baima" },
+	{ "bqi", "Bakhtiari" },
+	{ "bqj", "Bandial" },
+	{ "bqk", "Banda-Mbrès" },
+	{ "bql", "Bilakura" },
+	{ "bqm", "Wumboko" },
+	{ "bqn", "Bulgarian Sign Language" },
+	{ "bqo", "Balo" },
+	{ "bqp", "Busa" },
+	{ "bqq", "Biritai" },
+	{ "bqr", "Burusu" },
+	{ "bqs", "Bosngun" },
+	{ "bqt", "Bamukumbit" },
+	{ "bqu", "Boguru" },
+	{ "bqv", "Koro Wachi" },
+	{ "bqw", "Buru (Nigeria)" },
+	{ "bqx", "Baangi" },
+	{ "bqy", "Bengkala Sign Language" },
+	{ "bqz", "Bakaka" },
+	{ "bra", "Braj" },
+	{ "brb", "Lave" },
+	{ "brc", "Berbice Creole Dutch" },
+	{ "brd", "Baraamu" },
+	{ "bre", "Breton" },
+	{ "brf", "Bera" },
+	{ "brg", "Baure" },
+	{ "brh", "Brahui" },
+	{ "bri", "Mokpwe" },
+	{ "brj", "Bieria" },
+	{ "brk", "Birked" },
+	{ "brl", "Birwa" },
+	{ "brm", "Barambu" },
+	{ "brn", "Boruca" },
+	{ "bro", "Brokkat" },
+	{ "brp", "Barapasi" },
+	{ "brq", "Breri" },
+	{ "brr", "Birao" },
+	{ "brs", "Baras" },
+	{ "brt", "Bitare" },
+	{ "bru", "Eastern Bru" },
+	{ "brv", "Western Bru" },
+	{ "brw", "Bellari" },
+	{ "brx", "Bodo (India)" },
+	{ "bry", "Burui" },
+	{ "brz", "Bilbil" },
+	{ "bsa", "Abinomn" },
+	{ "bsb", "Brunei Bisaya" },
+	{ "bsc", "Bassari" },
+	{ "bse", "Wushi" },
+	{ "bsf", "Bauchi" },
+	{ "bsg", "Bashkardi" },
+	{ "bsh", "Kati" },
+	{ "bsi", "Bassossi" },
+	{ "bsj", "Bangwinji" },
+	{ "bsk", "Burushaski" },
+	{ "bsl", "Basa-Gumna" },
+	{ "bsm", "Busami" },
+	{ "bsn", "Barasana-Eduria" },
+	{ "bso", "Buso" },
+	{ "bsp", "Baga Sitemu" },
+	{ "bsq", "Bassa" },
+	{ "bsr", "Bassa-Kontagora" },
+	{ "bss", "Akoose" },
+	{ "bst", "Basketo" },
+	{ "bsu", "Bahonsuai" },
+	{ "bsv", "Baga Sobané" },
+	{ "bsw", "Baiso" },
+	{ "bsx", "Yangkam" },
+	{ "bsy", "Sabah Bisaya" },
+	{ "bta", "Bata" },
+	{ "btc", "Bati (Cameroon)" },
+	{ "btd", "Batak Dairi" },
+	{ "bte", "Gamo-Ningi" },
+	{ "btf", "Birgit" },
+	{ "btg", "Gagnoa Bété" },
+	{ "bth", "Biatah Bidayuh" },
+	{ "bti", "Burate" },
+	{ "btj", "Bacanese Malay" },
+	{ "btl", "Bhatola" },
+	{ "btm", "Batak Mandailing" },
+	{ "btn", "Ratagnon" },
+	{ "bto", "Rinconada Bikol" },
+	{ "btp", "Budibud" },
+	{ "btq", "Batek" },
+	{ "btr", "Baetora" },
+	{ "bts", "Batak Simalungun" },
+	{ "btt", "Bete-Bendi" },
+	{ "btu", "Batu" },
+	{ "btv", "Bateri" },
+	{ "btw", "Butuanon" },
+	{ "btx", "Batak Karo" },
+	{ "bty", "Bobot" },
+	{ "btz", "Batak Alas-Kluet" },
+	{ "bua", "Buriat" },
+	{ "bub", "Bua" },
+	{ "buc", "Bushi" },
+	{ "bud", "Ntcham" },
+	{ "bue", "Beothuk" },
+	{ "buf", "Bushoong" },
+	{ "bug", "Buginese" },
+	{ "buh", "Younuo Bunu" },
+	{ "bui", "Bongili" },
+	{ "buj", "Basa-Gurmana" },
+	{ "buk", "Bugawac" },
+	{ "bul", "Bulgarian" },
+	{ "bum", "Bulu (Cameroon)" },
+	{ "bun", "Sherbro" },
+	{ "buo", "Terei" },
+	{ "bup", "Busoa" },
+	{ "buq", "Brem" },
+	{ "bus", "Bokobaru" },
+	{ "but", "Bungain" },
+	{ "buu", "Budu" },
+	{ "buv", "Bun" },
+	{ "buw", "Bubi" },
+	{ "bux", "Boghom" },
+	{ "buy", "Bullom So" },
+	{ "buz", "Bukwen" },
+	{ "bva", "Barein" },
+	{ "bvb", "Bube" },
+	{ "bvc", "Baelelea" },
+	{ "bvd", "Baeggu" },
+	{ "bve", "Berau Malay" },
+	{ "bvf", "Boor" },
+	{ "bvg", "Bonkeng" },
+	{ "bvh", "Bure" },
+	{ "bvi", "Belanda Viri" },
+	{ "bvj", "Baan" },
+	{ "bvk", "Bukat" },
+	{ "bvl", "Bolivian Sign Language" },
+	{ "bvm", "Bamunka" },
+	{ "bvn", "Buna" },
+	{ "bvo", "Bolgo" },
+	{ "bvp", "Bumang" },
+	{ "bvq", "Birri" },
+	{ "bvr", "Burarra" },
+	{ "bvt", "Bati (Indonesia)" },
+	{ "bvu", "Bukit Malay" },
+	{ "bvv", "Baniva" },
+	{ "bvw", "Boga" },
+	{ "bvx", "Dibole" },
+	{ "bvy", "Baybayanon" },
+	{ "bvz", "Bauzi" },
+	{ "bwa", "Bwatoo" },
+	{ "bwb", "Namosi-Naitasiri-Serua" },
+	{ "bwc", "Bwile" },
+	{ "bwd", "Bwaidoka" },
+	{ "bwe", "Bwe Karen" },
+	{ "bwf", "Boselewa" },
+	{ "bwg", "Barwe" },
+	{ "bwh", "Bishuo" },
+	{ "bwi", "Baniwa" },
+	{ "bwj", "Láá Láá Bwamu" },
+	{ "bwk", "Bauwaki" },
+	{ "bwl", "Bwela" },
+	{ "bwm", "Biwat" },
+	{ "bwn", "Wunai Bunu" },
+	{ "bwo", "Boro (Ethiopia)" },
+	{ "bwp", "Mandobo Bawah" },
+	{ "bwq", "Southern Bobo Madaré" },
+	{ "bwr", "Bura-Pabir" },
+	{ "bws", "Bomboma" },
+	{ "bwt", "Bafaw-Balong" },
+	{ "bwu", "Buli (Ghana)" },
+	{ "bww", "Bwa" },
+	{ "bwx", "Bu-Nao Bunu" },
+	{ "bwy", "Cwi Bwamu" },
+	{ "bwz", "Bwisi" },
+	{ "bxa", "Tairaha" },
+	{ "bxb", "Belanda Bor" },
+	{ "bxc", "Molengue" },
+	{ "bxd", "Pela" },
+	{ "bxe", "Birale" },
+	{ "bxf", "Bilur" },
+	{ "bxg", "Bangala" },
+	{ "bxh", "Buhutu" },
+	{ "bxi", "Pirlatapa" },
+	{ "bxj", "Bayungu" },
+	{ "bxk", "Bukusu" },
+	{ "bxl", "Jalkunan" },
+	{ "bxm", "Mongolia Buriat" },
+	{ "bxn", "Burduna" },
+	{ "bxo", "Barikanchi" },
+	{ "bxp", "Bebil" },
+	{ "bxq", "Beele" },
+	{ "bxr", "Russia Buriat" },
+	{ "bxs", "Busam" },
+	{ "bxu", "China Buriat" },
+	{ "bxv", "Berakou" },
+	{ "bxw", "Bankagooma" },
+	{ "bxx", "Borna (Democratic Republic of Congo)" },
+	{ "bxz", "Binahari" },
+	{ "bya", "Batak" },
+	{ "byb", "Bikya" },
+	{ "byc", "Ubaghara" },
+	{ "byd", "Benyadu'" },
+	{ "bye", "Pouye" },
+	{ "byf", "Bete" },
+	{ "byg", "Baygo" },
+	{ "byh", "Bhujel" },
+	{ "byi", "Buyu" },
+	{ "byj", "Bina (Nigeria)" },
+	{ "byk", "Biao" },
+	{ "byl", "Bayono" },
+	{ "bym", "Bidyara" },
+	{ "byn", "Bilin" },
+	{ "byo", "Biyo" },
+	{ "byp", "Bumaji" },
+	{ "byq", "Basay" },
+	{ "byr", "Baruya" },
+	{ "bys", "Burak" },
+	{ "byt", "Berti" },
+	{ "byv", "Medumba" },
+	{ "byw", "Belhariya" },
+	{ "byx", "Qaqet" },
+	{ "byy", "Buya" },
+	{ "byz", "Banaro" },
+	{ "bza", "Bandi" },
+	{ "bzb", "Andio" },
+	{ "bzc", "Southern Betsimisaraka Malagasy" },
+	{ "bzd", "Bribri" },
+	{ "bze", "Jenaama Bozo" },
+	{ "bzf", "Boikin" },
+	{ "bzg", "Babuza" },
+	{ "bzh", "Mapos Buang" },
+	{ "bzi", "Bisu" },
+	{ "bzj", "Belize Kriol English" },
+	{ "bzk", "Nicaragua Creole English" },
+	{ "bzl", "Boano (Sulawesi)" },
+	{ "bzm", "Bolondo" },
+	{ "bzn", "Boano (Maluku)" },
+	{ "bzo", "Bozaba" },
+	{ "bzp", "Kemberano" },
+	{ "bzq", "Buli (Indonesia)" },
+	{ "bzr", "Biri" },
+	{ "bzs", "Brazilian Sign Language" },
+	{ "bzt", "Brithenig" },
+	{ "bzu", "Burmeso" },
+	{ "bzv", "Naami" },
+	{ "bzw", "Basa (Nigeria)" },
+	{ "bzx", "Kɛlɛngaxo Bozo" },
+	{ "bzy", "Obanliku" },
+	{ "bzz", "Evant" },
+	{ "caa", "Chortí" },
+	{ "cab", "Garifuna" },
+	{ "cac", "Chuj" },
+	{ "cad", "Caddo" },
+	{ "cae", "Lehar" },
+	{ "caf", "Southern Carrier" },
+	{ "cag", "Nivaclé" },
+	{ "cah", "Cahuarano" },
+	{ "caj", "Chané" },
+	{ "cak", "Kaqchikel" },
+	{ "cal", "Carolinian" },
+	{ "cam", "Cemuhî" },
+	{ "can", "Chambri" },
+	{ "cao", "Chácobo" },
+	{ "cap", "Chipaya" },
+	{ "caq", "Car Nicobarese" },
+	{ "car", "Galibi Carib" },
+	{ "cas", "Tsimané" },
+	{ "cat", "Catalan" },
+	{ "cav", "Cavineña" },
+	{ "caw", "Callawalla" },
+	{ "cax", "Chiquitano" },
+	{ "cay", "Cayuga" },
+	{ "caz", "Canichana" },
+	{ "cbb", "Cabiyarí" },
+	{ "cbc", "Carapana" },
+	{ "cbd", "Carijona" },
+	{ "cbe", "Chipiajes" },
+	{ "cbg", "Chimila" },
+	{ "cbh", "Cagua" },
+	{ "cbi", "Chachi" },
+	{ "cbj", "Ede Cabe" },
+	{ "cbk", "Chavacano" },
+	{ "cbl", "Bualkhaw Chin" },
+	{ "cbn", "Nyahkur" },
+	{ "cbo", "Izora" },
+	{ "cbr", "Cashibo-Cacataibo" },
+	{ "cbs", "Cashinahua" },
+	{ "cbt", "Chayahuita" },
+	{ "cbu", "Candoshi-Shapra" },
+	{ "cbv", "Cacua" },
+	{ "cbw", "Kinabalian" },
+	{ "cby", "Carabayo" },
+	{ "cca", "Cauca" },
+	{ "ccc", "Chamicuro" },
+	{ "ccd", "Cafundo Creole" },
+	{ "cce", "Chopi" },
+	{ "ccg", "Samba Daka" },
+	{ "cch", "Atsam" },
+	{ "ccj", "Kasanga" },
+	{ "ccl", "Cutchi-Swahili" },
+	{ "ccm", "Malaccan Creole Malay" },
+	{ "cco", "Comaltepec Chinantec" },
+	{ "ccp", "Chakma" },
+	{ "ccr", "Cacaopera" },
+	{ "cda", "Choni" },
+	{ "cde", "Chenchu" },
+	{ "cdf", "Chiru" },
+	{ "cdg", "Chamari" },
+	{ "cdh", "Chambeali" },
+	{ "cdi", "Chodri" },
+	{ "cdj", "Churahi" },
+	{ "cdm", "Chepang" },
+	{ "cdn", "Chaudangsi" },
+	{ "cdo", "Min Dong Chinese" },
+	{ "cdr", "Cinda-Regi-Tiyal" },
+	{ "cds", "Chadian Sign Language" },
+	{ "cdy", "Chadong" },
+	{ "cdz", "Koda" },
+	{ "cea", "Lower Chehalis" },
+	{ "ceb", "Cebuano" },
+	{ "ceg", "Chamacoco" },
+	{ "cek", "Eastern Khumi Chin" },
+	{ "cen", "Cen" },
+	{ "ces", "Czech" },
+	{ "cet", "Centúúm" },
+	{ "cfa", "Dijim-Bwilim" },
+	{ "cfd", "Cara" },
+	{ "cfg", "Como Karim" },
+	{ "cfm", "Falam Chin" },
+	{ "cga", "Changriwa" },
+	{ "cgc", "Kagayanen" },
+	{ "cgg", "Chiga" },
+	{ "cgk", "Chocangacakha" },
+	{ "cha", "Chamorro" },
+	{ "chb", "Chibcha" },
+	{ "chc", "Catawba" },
+	{ "chd", "Highland Oaxaca Chontal" },
+	{ "che", "Chechen" },
+	{ "chf", "Tabasco Chontal" },
+	{ "chg", "Chagatai" },
+	{ "chh", "Chinook" },
+	{ "chj", "Ojitlán Chinantec" },
+	{ "chk", "Chuukese" },
+	{ "chl", "Cahuilla" },
+	{ "chm", "Mari (Russia)" },
+	{ "chn", "Chinook jargon" },
+	{ "cho", "Choctaw" },
+	{ "chp", "Chipewyan" },
+	{ "chq", "Quiotepec Chinantec" },
+	{ "chr", "Cherokee" },
+	{ "cht", "Cholón" },
+	{ "chu", "Church Slavic" },
+	{ "chv", "Chuvash" },
+	{ "chw", "Chuwabu" },
+	{ "chx", "Chantyal" },
+	{ "chy", "Cheyenne" },
+	{ "chz", "Ozumacín Chinantec" },
+	{ "cia", "Cia-Cia" },
+	{ "cib", "Ci Gbe" },
+	{ "cic", "Chickasaw" },
+	{ "cid", "Chimariko" },
+	{ "cie", "Cineni" },
+	{ "cih", "Chinali" },
+	{ "cik", "Chitkuli Kinnauri" },
+	{ "cim", "Cimbrian" },
+	{ "cin", "Cinta Larga" },
+	{ "cip", "Chiapanec" },
+	{ "cir", "Tiri" },
+	{ "ciw", "Chippewa" },
+	{ "ciy", "Chaima" },
+	{ "cja", "Western Cham" },
+	{ "cje", "Chru" },
+	{ "cjh", "Upper Chehalis" },
+	{ "cji", "Chamalal" },
+	{ "cjk", "Chokwe" },
+	{ "cjm", "Eastern Cham" },
+	{ "cjn", "Chenapian" },
+	{ "cjo", "Ashéninka Pajonal" },
+	{ "cjp", "Cabécar" },
+	{ "cjs", "Shor" },
+	{ "cjv", "Chuave" },
+	{ "cjy", "Jinyu Chinese" },
+	{ "ckb", "Central Kurdish" },
+	{ "ckh", "Chak" },
+	{ "ckl", "Cibak" },
+	{ "ckn", "Kaang Chin" },
+	{ "cko", "Anufo" },
+	{ "ckq", "Kajakse" },
+	{ "ckr", "Kairak" },
+	{ "cks", "Tayo" },
+	{ "ckt", "Chukot" },
+	{ "cku", "Koasati" },
+	{ "ckv", "Kavalan" },
+	{ "ckx", "Caka" },
+	{ "cky", "Cakfem-Mushere" },
+	{ "ckz", "Cakchiquel-Quiché Mixed Language" },
+	{ "cla", "Ron" },
+	{ "clc", "Chilcotin" },
+	{ "cld", "Chaldean Neo-Aramaic" },
+	{ "cle", "Lealao Chinantec" },
+	{ "clh", "Chilisso" },
+	{ "cli", "Chakali" },
+	{ "clj", "Laitu Chin" },
+	{ "clk", "Idu-Mishmi" },
+	{ "cll", "Chala" },
+	{ "clm", "Clallam" },
+	{ "clo", "Lowland Oaxaca Chontal" },
+	{ "clt", "Lautu Chin" },
+	{ "clu", "Caluyanun" },
+	{ "clw", "Chulym" },
+	{ "cly", "Eastern Highland Chatino" },
+	{ "cma", "Maa" },
+	{ "cme", "Cerma" },
+	{ "cmg", "Classical Mongolian" },
+	{ "cmi", "Emberá-Chamí" },
+	{ "cml", "Campalagian" },
+	{ "cmm", "Michigamea" },
+	{ "cmn", "Mandarin Chinese" },
+	{ "cmo", "Central Mnong" },
+	{ "cmr", "Mro-Khimi Chin" },
+	{ "cms", "Messapic" },
+	{ "cmt", "Camtho" },
+	{ "cna", "Changthang" },
+	{ "cnb", "Chinbon Chin" },
+	{ "cnc", "Côông" },
+	{ "cng", "Northern Qiang" },
+	{ "cnh", "Haka Chin" },
+	{ "cni", "Asháninka" },
+	{ "cnk", "Khumi Chin" },
+	{ "cnl", "Lalana Chinantec" },
+	{ "cno", "Con" },
+	{ "cns", "Central Asmat" },
+	{ "cnt", "Tepetotutla Chinantec" },
+	{ "cnu", "Chenoua" },
+	{ "cnw", "Ngawn Chin" },
+	{ "cnx", "Middle Cornish" },
+	{ "coa", "Cocos Islands Malay" },
+	{ "cob", "Chicomuceltec" },
+	{ "coc", "Cocopa" },
+	{ "cod", "Cocama-Cocamilla" },
+	{ "coe", "Koreguaje" },
+	{ "cof", "Colorado" },
+	{ "cog", "Chong" },
+	{ "coh", "Chonyi-Dzihana-Kauma" },
+	{ "coj", "Cochimi" },
+	{ "cok", "Santa Teresa Cora" },
+	{ "col", "Columbia-Wenatchi" },
+	{ "com", "Comanche" },
+	{ "con", "Cofán" },
+	{ "coo", "Comox" },
+	{ "cop", "Coptic" },
+	{ "coq", "Coquille" },
+	{ "cor", "Cornish" },
+	{ "cos", "Corsican" },
+	{ "cot", "Caquinte" },
+	{ "cou", "Wamey" },
+	{ "cov", "Cao Miao" },
+	{ "cow", "Cowlitz" },
+	{ "cox", "Nanti" },
+	{ "coy", "Coyaima" },
+	{ "coz", "Chochotec" },
+	{ "cpa", "Palantla Chinantec" },
+	{ "cpb", "Ucayali-Yurúa Ashéninka" },
+	{ "cpc", "Ajyíninka Apurucayali" },
+	{ "cpg", "Cappadocian Greek" },
+	{ "cpi", "Chinese Pidgin English" },
+	{ "cpn", "Cherepon" },
+	{ "cpo", "Kpeego" },
+	{ "cps", "Capiznon" },
+	{ "cpu", "Pichis Ashéninka" },
+	{ "cpx", "Pu-Xian Chinese" },
+	{ "cpy", "South Ucayali Ashéninka" },
+	{ "cqd", "Chuanqiandian Cluster Miao" },
+	{ "cqu", "Chilean Quechua" },
+	{ "cra", "Chara" },
+	{ "crb", "Island Carib" },
+	{ "crc", "Lonwolwol" },
+	{ "crd", "Coeur d'Alene" },
+	{ "cre", "Cree" },
+	{ "crf", "Caramanta" },
+	{ "crg", "Michif" },
+	{ "crh", "Crimean Tatar" },
+	{ "cri", "Sãotomense" },
+	{ "crj", "Southern East Cree" },
+	{ "crk", "Plains Cree" },
+	{ "crl", "Northern East Cree" },
+	{ "crm", "Moose Cree" },
+	{ "crn", "El Nayar Cora" },
+	{ "cro", "Crow" },
+	{ "crq", "Iyo'wujwa Chorote" },
+	{ "crr", "Carolina Algonquian" },
+	{ "crs", "Seselwa Creole French" },
+	{ "crt", "Iyojwa'ja Chorote" },
+	{ "crv", "Chaura" },
+	{ "crw", "Chrau" },
+	{ "crx", "Carrier" },
+	{ "cry", "Cori" },
+	{ "crz", "Cruzeño" },
+	{ "csa", "Chiltepec Chinantec" },
+	{ "csb", "Kashubian" },
+	{ "csc", "Catalan Sign Language" },
+	{ "csd", "Chiangmai Sign Language" },
+	{ "cse", "Czech Sign Language" },
+	{ "csf", "Cuba Sign Language" },
+	{ "csg", "Chilean Sign Language" },
+	{ "csh", "Asho Chin" },
+	{ "csi", "Coast Miwok" },
+	{ "csj", "Songlai Chin" },
+	{ "csk", "Jola-Kasa" },
+	{ "csl", "Chinese Sign Language" },
+	{ "csm", "Central Sierra Miwok" },
+	{ "csn", "Colombian Sign Language" },
+	{ "cso", "Sochiapam Chinantec" },
+	{ "csq", "Croatia Sign Language" },
+	{ "csr", "Costa Rican Sign Language" },
+	{ "css", "Southern Ohlone" },
+	{ "cst", "Northern Ohlone" },
+	{ "csv", "Sumtu Chin" },
+	{ "csw", "Swampy Cree" },
+	{ "csy", "Siyin Chin" },
+	{ "csz", "Coos" },
+	{ "cta", "Tataltepec Chatino" },
+	{ "ctc", "Chetco" },
+	{ "ctd", "Tedim Chin" },
+	{ "cte", "Tepinapa Chinantec" },
+	{ "ctg", "Chittagonian" },
+	{ "cth", "Thaiphum Chin" },
+	{ "ctl", "Tlacoatzintepec Chinantec" },
+	{ "ctm", "Chitimacha" },
+	{ "ctn", "Chhintange" },
+	{ "cto", "Emberá-Catío" },
+	{ "ctp", "Western Highland Chatino" },
+	{ "cts", "Northern Catanduanes Bikol" },
+	{ "ctt", "Wayanad Chetti" },
+	{ "ctu", "Chol" },
+	{ "ctz", "Zacatepec Chatino" },
+	{ "cua", "Cua" },
+	{ "cub", "Cubeo" },
+	{ "cuc", "Usila Chinantec" },
+	{ "cug", "Cung" },
+	{ "cuh", "Chuka" },
+	{ "cui", "Cuiba" },
+	{ "cuj", "Mashco Piro" },
+	{ "cuk", "San Blas Kuna" },
+	{ "cul", "Culina" },
+	{ "cum", "Cumeral" },
+	{ "cuo", "Cumanagoto" },
+	{ "cup", "Cupeño" },
+	{ "cuq", "Cun" },
+	{ "cur", "Chhulung" },
+	{ "cut", "Teutila Cuicatec" },
+	{ "cuu", "Tai Ya" },
+	{ "cuv", "Cuvok" },
+	{ "cuw", "Chukwa" },
+	{ "cux", "Tepeuxila Cuicatec" },
+	{ "cvg", "Chug" },
+	{ "cvn", "Valle Nacional Chinantec" },
+	{ "cwa", "Kabwa" },
+	{ "cwb", "Maindo" },
+	{ "cwd", "Woods Cree" },
+	{ "cwe", "Kwere" },
+	{ "cwg", "Chewong" },
+	{ "cwt", "Kuwaataay" },
+	{ "cya", "Nopala Chatino" },
+	{ "cyb", "Cayubaba" },
+	{ "cym", "Welsh" },
+	{ "cyo", "Cuyonon" },
+	{ "czh", "Huizhou Chinese" },
+	{ "czk", "Knaanic" },
+	{ "czn", "Zenzontepec Chatino" },
+	{ "czo", "Min Zhong Chinese" },
+	{ "czt", "Zotung Chin" },
+	{ "daa", "Dangaléat" },
+	{ "dac", "Dambi" },
+	{ "dad", "Marik" },
+	{ "dae", "Duupa" },
+	{ "dag", "Dagbani" },
+	{ "dah", "Gwahatike" },
+	{ "dai", "Day" },
+	{ "daj", "Dar Fur Daju" },
+	{ "dak", "Dakota" },
+	{ "dal", "Dahalo" },
+	{ "dam", "Damakawa" },
+	{ "dan", "Danish" },
+	{ "dao", "Daai Chin" },
+	{ "daq", "Dandami Maria" },
+	{ "dar", "Dargwa" },
+	{ "das", "Daho-Doo" },
+	{ "dau", "Dar Sila Daju" },
+	{ "dav", "Taita" },
+	{ "daw", "Davawenyo" },
+	{ "dax", "Dayi" },
+	{ "daz", "Dao" },
+	{ "dba", "Bangime" },
+	{ "dbb", "Deno" },
+	{ "dbd", "Dadiya" },
+	{ "dbe", "Dabe" },
+	{ "dbf", "Edopi" },
+	{ "dbg", "Dogul Dom Dogon" },
+	{ "dbi", "Doka" },
+	{ "dbj", "Ida'an" },
+	{ "dbl", "Dyirbal" },
+	{ "dbm", "Duguri" },
+	{ "dbn", "Duriankere" },
+	{ "dbo", "Dulbu" },
+	{ "dbp", "Duwai" },
+	{ "dbq", "Daba" },
+	{ "dbr", "Dabarre" },
+	{ "dbt", "Ben Tey Dogon" },
+	{ "dbu", "Bondum Dom Dogon" },
+	{ "dbv", "Dungu" },
+	{ "dbw", "Bankan Tey Dogon" },
+	{ "dby", "Dibiyaso" },
+	{ "dcc", "Deccan" },
+	{ "dcr", "Negerhollands" },
+	{ "dda", "Dadi Dadi" },
+	{ "ddd", "Dongotono" },
+	{ "dde", "Doondo" },
+	{ "ddg", "Fataluku" },
+	{ "ddi", "West Goodenough" },
+	{ "ddj", "Jaru" },
+	{ "ddn", "Dendi (Benin)" },
+	{ "ddo", "Dido" },
+	{ "ddr", "Dhudhuroa" },
+	{ "dds", "Donno So Dogon" },
+	{ "ddw", "Dawera-Daweloor" },
+	{ "dec", "Dagik" },
+	{ "ded", "Dedua" },
+	{ "dee", "Dewoin" },
+	{ "def", "Dezfuli" },
+	{ "deg", "Degema" },
+	{ "deh", "Dehwari" },
+	{ "dei", "Demisa" },
+	{ "dek", "Dek" },
+	{ "del", "Delaware" },
+	{ "dem", "Dem" },
+	{ "den", "Slave (Athapascan)" },
+	{ "dep", "Pidgin Delaware" },
+	{ "deq", "Dendi (Central African Republic)" },
+	{ "der", "Deori" },
+	{ "des", "Desano" },
+	{ "deu", "German" },
+	{ "dev", "Domung" },
+	{ "dez", "Dengese" },
+	{ "dga", "Southern Dagaare" },
+	{ "dgb", "Bunoge Dogon" },
+	{ "dgc", "Casiguran Dumagat Agta" },
+	{ "dgd", "Dagaari Dioula" },
+	{ "dge", "Degenan" },
+	{ "dgg", "Doga" },
+	{ "dgh", "Dghwede" },
+	{ "dgi", "Northern Dagara" },
+	{ "dgk", "Dagba" },
+	{ "dgl", "Andaandi" },
+	{ "dgn", "Dagoman" },
+	{ "dgo", "Dogri (individual language)" },
+	{ "dgr", "Dogrib" },
+	{ "dgs", "Dogoso" },
+	{ "dgt", "Ndra'ngith" },
+	{ "dgu", "Degaru" },
+	{ "dgw", "Daungwurrung" },
+	{ "dgx", "Doghoro" },
+	{ "dgz", "Daga" },
+	{ "dhd", "Dhundari" },
+	{ "dhg", "Djangu" },
+	{ "dhi", "Dhimal" },
+	{ "dhl", "Dhalandji" },
+	{ "dhm", "Zemba" },
+	{ "dhn", "Dhanki" },
+	{ "dho", "Dhodia" },
+	{ "dhr", "Dhargari" },
+	{ "dhs", "Dhaiso" },
+	{ "dhu", "Dhurga" },
+	{ "dhv", "Dehu" },
+	{ "dhw", "Dhanwar (Nepal)" },
+	{ "dhx", "Dhungaloo" },
+	{ "dia", "Dia" },
+	{ "dib", "South Central Dinka" },
+	{ "dic", "Lakota Dida" },
+	{ "did", "Didinga" },
+	{ "dif", "Dieri" },
+	{ "dig", "Digo" },
+	{ "dih", "Kumiai" },
+	{ "dii", "Dimbong" },
+	{ "dij", "Dai" },
+	{ "dik", "Southwestern Dinka" },
+	{ "dil", "Dilling" },
+	{ "dim", "Dime" },
+	{ "din", "Dinka" },
+	{ "dio", "Dibo" },
+	{ "dip", "Northeastern Dinka" },
+	{ "diq", "Dimli (individual language)" },
+	{ "dir", "Dirim" },
+	{ "dis", "Dimasa" },
+	{ "dit", "Dirari" },
+	{ "diu", "Diriku" },
+	{ "div", "Dhivehi" },
+	{ "diw", "Northwestern Dinka" },
+	{ "dix", "Dixon Reef" },
+	{ "diy", "Diuwe" },
+	{ "diz", "Ding" },
+	{ "dja", "Djadjawurrung" },
+	{ "djb", "Djinba" },
+	{ "djc", "Dar Daju Daju" },
+	{ "djd", "Djamindjung" },
+	{ "dje", "Zarma" },
+	{ "djf", "Djangun" },
+	{ "dji", "Djinang" },
+	{ "djj", "Djeebbana" },
+	{ "djk", "Eastern Maroon Creole" },
+	{ "djm", "Jamsay Dogon" },
+	{ "djn", "Djauan" },
+	{ "djo", "Jangkang" },
+	{ "djr", "Djambarrpuyngu" },
+	{ "dju", "Kapriman" },
+	{ "djw", "Djawi" },
+	{ "dka", "Dakpakha" },
+	{ "dkk", "Dakka" },
+	{ "dkr", "Kuijau" },
+	{ "dks", "Southeastern Dinka" },
+	{ "dkx", "Mazagway" },
+	{ "dlg", "Dolgan" },
+	{ "dlk", "Dahalik" },
+	{ "dlm", "Dalmatian" },
+	{ "dln", "Darlong" },
+	{ "dma", "Duma" },
+	{ "dmb", "Mombo Dogon" },
+	{ "dmc", "Gavak" },
+	{ "dmd", "Madhi Madhi" },
+	{ "dme", "Dugwor" },
+	{ "dmg", "Upper Kinabatangan" },
+	{ "dmk", "Domaaki" },
+	{ "dml", "Dameli" },
+	{ "dmm", "Dama" },
+	{ "dmo", "Kemedzung" },
+	{ "dmr", "East Damar" },
+	{ "dms", "Dampelas" },
+	{ "dmu", "Dubu" },
+	{ "dmv", "Dumpas" },
+	{ "dmw", "Mudburra" },
+	{ "dmx", "Dema" },
+	{ "dmy", "Demta" },
+	{ "dna", "Upper Grand Valley Dani" },
+	{ "dnd", "Daonda" },
+	{ "dne", "Ndendeule" },
+	{ "dng", "Dungan" },
+	{ "dni", "Lower Grand Valley Dani" },
+	{ "dnj", "Dan" },
+	{ "dnk", "Dengka" },
+	{ "dnn", "Dzùùngoo" },
+	{ "dnr", "Danaru" },
+	{ "dnt", "Mid Grand Valley Dani" },
+	{ "dnu", "Danau" },
+	{ "dnv", "Danu" },
+	{ "dnw", "Western Dani" },
+	{ "dny", "Dení" },
+	{ "doa", "Dom" },
+	{ "dob", "Dobu" },
+	{ "doc", "Northern Dong" },
+	{ "doe", "Doe" },
+	{ "dof", "Domu" },
+	{ "doh", "Dong" },
+	{ "doi", "Dogri (macrolanguage)" },
+	{ "dok", "Dondo" },
+	{ "dol", "Doso" },
+	{ "don", "Toura (Papua New Guinea)" },
+	{ "doo", "Dongo" },
+	{ "dop", "Lukpa" },
+	{ "doq", "Dominican Sign Language" },
+	{ "dor", "Dori'o" },
+	{ "dos", "Dogosé" },
+	{ "dot", "Dass" },
+	{ "dov", "Dombe" },
+	{ "dow", "Doyayo" },
+	{ "dox", "Bussa" },
+	{ "doy", "Dompo" },
+	{ "doz", "Dorze" },
+	{ "dpp", "Papar" },
+	{ "drb", "Dair" },
+	{ "drc", "Minderico" },
+	{ "drd", "Darmiya" },
+	{ "dre", "Dolpo" },
+	{ "drg", "Rungus" },
+	{ "dri", "C'lela" },
+	{ "drl", "Paakantyi" },
+	{ "drn", "West Damar" },
+	{ "dro", "Daro-Matu Melanau" },
+	{ "drq", "Dura" },
+	{ "drr", "Dororo" },
+	{ "drs", "Gedeo" },
+	{ "drt", "Drents" },
+	{ "dru", "Rukai" },
+	{ "dry", "Darai" },
+	{ "dsb", "Lower Sorbian" },
+	{ "dse", "Dutch Sign Language" },
+	{ "dsh", "Daasanach" },
+	{ "dsi", "Disa" },
+	{ "dsl", "Danish Sign Language" },
+	{ "dsn", "Dusner" },
+	{ "dso", "Desiya" },
+	{ "dsq", "Tadaksahak" },
+	{ "dta", "Daur" },
+	{ "dtb", "Labuk-Kinabatangan Kadazan" },
+	{ "dtd", "Ditidaht" },
+	{ "dth", "Adithinngithigh" },
+	{ "dti", "Ana Tinga Dogon" },
+	{ "dtk", "Tene Kan Dogon" },
+	{ "dtm", "Tomo Kan Dogon" },
+	{ "dto", "Tommo So Dogon" },
+	{ "dtp", "Central Dusun" },
+	{ "dtr", "Lotud" },
+	{ "dts", "Toro So Dogon" },
+	{ "dtt", "Toro Tegu Dogon" },
+	{ "dtu", "Tebul Ure Dogon" },
+	{ "dty", "Dotyali" },
+	{ "dua", "Duala" },
+	{ "dub", "Dubli" },
+	{ "duc", "Duna" },
+	{ "dud", "Hun-Saare" },
+	{ "due", "Umiray Dumaget Agta" },
+	{ "duf", "Dumbea" },
+	{ "dug", "Duruma" },
+	{ "duh", "Dungra Bhil" },
+	{ "dui", "Dumun" },
+	{ "duj", "Dhuwal" },
+	{ "duk", "Uyajitaya" },
+	{ "dul", "Alabat Island Agta" },
+	{ "dum", "Middle Dutch (ca. 1050-1350)" },
+	{ "dun", "Dusun Deyah" },
+	{ "duo", "Dupaninan Agta" },
+	{ "dup", "Duano" },
+	{ "duq", "Dusun Malang" },
+	{ "dur", "Dii" },
+	{ "dus", "Dumi" },
+	{ "duu", "Drung" },
+	{ "duv", "Duvle" },
+	{ "duw", "Dusun Witu" },
+	{ "dux", "Duungooma" },
+	{ "duy", "Dicamay Agta" },
+	{ "duz", "Duli" },
+	{ "dva", "Duau" },
+	{ "dwa", "Diri" },
+	{ "dwr", "Dawro" },
+	{ "dws", "Dutton World Speedwords" },
+	{ "dww", "Dawawa" },
+	{ "dya", "Dyan" },
+	{ "dyb", "Dyaberdyaber" },
+	{ "dyd", "Dyugun" },
+	{ "dyg", "Villa Viciosa Agta" },
+	{ "dyi", "Djimini Senoufo" },
+	{ "dym", "Yanda Dom Dogon" },
+	{ "dyn", "Dyangadi" },
+	{ "dyo", "Jola-Fonyi" },
+	{ "dyu", "Dyula" },
+	{ "dyy", "Dyaabugay" },
+	{ "dza", "Tunzu" },
+	{ "dzd", "Daza" },
+	{ "dze", "Djiwarli" },
+	{ "dzg", "Dazaga" },
+	{ "dzl", "Dzalakha" },
+	{ "dzn", "Dzando" },
+	{ "dzo", "Dzongkha" },
+	{ "eaa", "Karenggapa" },
+	{ "ebg", "Ebughu" },
+	{ "ebk", "Eastern Bontok" },
+	{ "ebo", "Teke-Ebo" },
+	{ "ebr", "Ebrié" },
+	{ "ebu", "Embu" },
+	{ "ecr", "Eteocretan" },
+	{ "ecs", "Ecuadorian Sign Language" },
+	{ "ecy", "Eteocypriot" },
+	{ "eee", "E" },
+	{ "efa", "Efai" },
+	{ "efe", "Efe" },
+	{ "efi", "Efik" },
+	{ "ega", "Ega" },
+	{ "egl", "Emilian" },
+	{ "ego", "Eggon" },
+	{ "egy", "Egyptian (Ancient)" },
+	{ "ehu", "Ehueun" },
+	{ "eip", "Eipomek" },
+	{ "eit", "Eitiep" },
+	{ "eiv", "Askopan" },
+	{ "eja", "Ejamat" },
+	{ "eka", "Ekajuk" },
+	{ "ekc", "Eastern Karnic" },
+	{ "eke", "Ekit" },
+	{ "ekg", "Ekari" },
+	{ "eki", "Eki" },
+	{ "ekk", "Standard Estonian" },
+	{ "ekl", "Kol (Bangladesh)" },
+	{ "ekm", "Elip" },
+	{ "eko", "Koti" },
+	{ "ekp", "Ekpeye" },
+	{ "ekr", "Yace" },
+	{ "eky", "Eastern Kayah" },
+	{ "ele", "Elepi" },
+	{ "elh", "El Hugeirat" },
+	{ "eli", "Nding" },
+	{ "elk", "Elkei" },
+	{ "ell", "Modern Greek (1453-)" },
+	{ "elm", "Eleme" },
+	{ "elo", "El Molo" },
+	{ "elu", "Elu" },
+	{ "elx", "Elamite" },
+	{ "ema", "Emai-Iuleha-Ora" },
+	{ "emb", "Embaloh" },
+	{ "eme", "Emerillon" },
+	{ "emg", "Eastern Meohang" },
+	{ "emi", "Mussau-Emira" },
+	{ "emk", "Eastern Maninkakan" },
+	{ "emm", "Mamulique" },
+	{ "emn", "Eman" },
+	{ "emo", "Emok" },
+	{ "emp", "Northern Emberá" },
+	{ "ems", "Pacific Gulf Yupik" },
+	{ "emu", "Eastern Muria" },
+	{ "emw", "Emplawas" },
+	{ "emx", "Erromintxela" },
+	{ "emy", "Epigraphic Mayan" },
+	{ "ena", "Apali" },
+	{ "enb", "Markweeta" },
+	{ "enc", "En" },
+	{ "end", "Ende" },
+	{ "enf", "Forest Enets" },
+	{ "eng", "English" },
+	{ "enh", "Tundra Enets" },
+	{ "enm", "Middle English (1100-1500)" },
+	{ "enn", "Engenni" },
+	{ "eno", "Enggano" },
+	{ "enq", "Enga" },
+	{ "enr", "Emumu" },
+	{ "enu", "Enu" },
+	{ "env", "Enwan (Edu State)" },
+	{ "enw", "Enwan (Akwa Ibom State)" },
+	{ "eot", "Beti (Côte d'Ivoire)" },
+	{ "epi", "Epie" },
+	{ "epo", "Esperanto" },
+	{ "era", "Eravallan" },
+	{ "erg", "Sie" },
+	{ "erh", "Eruwa" },
+	{ "eri", "Ogea" },
+	{ "erk", "South Efate" },
+	{ "ero", "Horpa" },
+	{ "err", "Erre" },
+	{ "ers", "Ersu" },
+	{ "ert", "Eritai" },
+	{ "erw", "Erokwanas" },
+	{ "ese", "Ese Ejja" },
+	{ "esh", "Eshtehardi" },
+	{ "esi", "North Alaskan Inupiatun" },
+	{ "esk", "Northwest Alaska Inupiatun" },
+	{ "esl", "Egypt Sign Language" },
+	{ "esm", "Esuma" },
+	{ "esn", "Salvadoran Sign Language" },
+	{ "eso", "Estonian Sign Language" },
+	{ "esq", "Esselen" },
+	{ "ess", "Central Siberian Yupik" },
+	{ "est", "Estonian" },
+	{ "esu", "Central Yupik" },
+	{ "etb", "Etebi" },
+	{ "etc", "Etchemin" },
+	{ "eth", "Ethiopian Sign Language" },
+	{ "etn", "Eton (Vanuatu)" },
+	{ "eto", "Eton (Cameroon)" },
+	{ "etr", "Edolo" },
+	{ "ets", "Yekhee" },
+	{ "ett", "Etruscan" },
+	{ "etu", "Ejagham" },
+	{ "etx", "Eten" },
+	{ "etz", "Semimi" },
+	{ "eus", "Basque" },
+	{ "eve", "Even" },
+	{ "evh", "Uvbie" },
+	{ "evn", "Evenki" },
+	{ "ewe", "Ewe" },
+	{ "ewo", "Ewondo" },
+	{ "ext", "Extremaduran" },
+	{ "eya", "Eyak" },
+	{ "eyo", "Keiyo" },
+	{ "eza", "Ezaa" },
+	{ "eze", "Uzekwe" },
+	{ "faa", "Fasu" },
+	{ "fab", "Fa d'Ambu" },
+	{ "fad", "Wagi" },
+	{ "faf", "Fagani" },
+	{ "fag", "Finongan" },
+	{ "fah", "Baissa Fali" },
+	{ "fai", "Faiwol" },
+	{ "faj", "Faita" },
+	{ "fak", "Fang (Cameroon)" },
+	{ "fal", "South Fali" },
+	{ "fam", "Fam" },
+	{ "fan", "Fang (Equatorial Guinea)" },
+	{ "fao", "Faroese" },
+	{ "fap", "Palor" },
+	{ "far", "Fataleka" },
+	{ "fas", "Persian" },
+	{ "fat", "Fanti" },
+	{ "fau", "Fayu" },
+	{ "fax", "Fala" },
+	{ "fay", "Southwestern Fars" },
+	{ "faz", "Northwestern Fars" },
+	{ "fbl", "West Albay Bikol" },
+	{ "fcs", "Quebec Sign Language" },
+	{ "fer", "Feroge" },
+	{ "ffi", "Foia Foia" },
+	{ "ffm", "Maasina Fulfulde" },
+	{ "fgr", "Fongoro" },
+	{ "fia", "Nobiin" },
+	{ "fie", "Fyer" },
+	{ "fij", "Fijian" },
+	{ "fil", "Filipino" },
+	{ "fin", "Finnish" },
+	{ "fip", "Fipa" },
+	{ "fir", "Firan" },
+	{ "fit", "Tornedalen Finnish" },
+	{ "fiw", "Fiwaga" },
+	{ "fkk", "Kirya-Konzəl" },
+	{ "fkv", "Kven Finnish" },
+	{ "fla", "Kalispel-Pend d'Oreille" },
+	{ "flh", "Foau" },
+	{ "fli", "Fali" },
+	{ "fll", "North Fali" },
+	{ "fln", "Flinders Island" },
+	{ "flr", "Fuliiru" },
+	{ "fly", "Tsotsitaal" },
+	{ "fmp", "Fe'fe'" },
+	{ "fmu", "Far Western Muria" },
+	{ "fng", "Fanagalo" },
+	{ "fni", "Fania" },
+	{ "fod", "Foodo" },
+	{ "foi", "Foi" },
+	{ "fom", "Foma" },
+	{ "fon", "Fon" },
+	{ "for", "Fore" },
+	{ "fos", "Siraya" },
+	{ "fpe", "Fernando Po Creole English" },
+	{ "fqs", "Fas" },
+	{ "fra", "French" },
+	{ "frc", "Cajun French" },
+	{ "frd", "Fordata" },
+	{ "frk", "Frankish" },
+	{ "frm", "Middle French (ca. 1400-1600)" },
+	{ "fro", "Old French (842-ca. 1400)" },
+	{ "frp", "Arpitan" },
+	{ "frq", "Forak" },
+	{ "frr", "Northern Frisian" },
+	{ "frs", "Eastern Frisian" },
+	{ "frt", "Fortsenal" },
+	{ "fry", "Western Frisian" },
+	{ "fse", "Finnish Sign Language" },
+	{ "fsl", "French Sign Language" },
+	{ "fss", "Finland-Swedish Sign Language" },
+	{ "fub", "Adamawa Fulfulde" },
+	{ "fuc", "Pulaar" },
+	{ "fud", "East Futuna" },
+	{ "fue", "Borgu Fulfulde" },
+	{ "fuf", "Pular" },
+	{ "fuh", "Western Niger Fulfulde" },
+	{ "fui", "Bagirmi Fulfulde" },
+	{ "fuj", "Ko" },
+	{ "ful", "Fulah" },
+	{ "fum", "Fum" },
+	{ "fun", "Fulniô" },
+	{ "fuq", "Central-Eastern Niger Fulfulde" },
+	{ "fur", "Friulian" },
+	{ "fut", "Futuna-Aniwa" },
+	{ "fuu", "Furu" },
+	{ "fuv", "Nigerian Fulfulde" },
+	{ "fuy", "Fuyug" },
+	{ "fvr", "Fur" },
+	{ "fwa", "Fwâi" },
+	{ "fwe", "Fwe" },
+	{ "gaa", "Ga" },
+	{ "gab", "Gabri" },
+	{ "gac", "Mixed Great Andamanese" },
+	{ "gad", "Gaddang" },
+	{ "gae", "Guarequena" },
+	{ "gaf", "Gende" },
+	{ "gag", "Gagauz" },
+	{ "gah", "Alekano" },
+	{ "gai", "Borei" },
+	{ "gaj", "Gadsup" },
+	{ "gak", "Gamkonora" },
+	{ "gal", "Galolen" },
+	{ "gam", "Kandawo" },
+	{ "gan", "Gan Chinese" },
+	{ "gao", "Gants" },
+	{ "gap", "Gal" },
+	{ "gaq", "Gata'" },
+	{ "gar", "Galeya" },
+	{ "gas", "Adiwasi Garasia" },
+	{ "gat", "Kenati" },
+	{ "gau", "Mudhili Gadaba" },
+	{ "gaw", "Nobonob" },
+	{ "gax", "Borana-Arsi-Guji Oromo" },
+	{ "gay", "Gayo" },
+	{ "gaz", "West Central Oromo" },
+	{ "gba", "Gbaya (Central African Republic)" },
+	{ "gbb", "Kaytetye" },
+	{ "gbd", "Karadjeri" },
+	{ "gbe", "Niksek" },
+	{ "gbf", "Gaikundi" },
+	{ "gbg", "Gbanziri" },
+	{ "gbh", "Defi Gbe" },
+	{ "gbi", "Galela" },
+	{ "gbj", "Bodo Gadaba" },
+	{ "gbk", "Gaddi" },
+	{ "gbl", "Gamit" },
+	{ "gbm", "Garhwali" },
+	{ "gbn", "Mo'da" },
+	{ "gbo", "Northern Grebo" },
+	{ "gbp", "Gbaya-Bossangoa" },
+	{ "gbq", "Gbaya-Bozoum" },
+	{ "gbr", "Gbagyi" },
+	{ "gbs", "Gbesi Gbe" },
+	{ "gbu", "Gagadu" },
+	{ "gbv", "Gbanu" },
+	{ "gbw", "Gabi-Gabi" },
+	{ "gbx", "Eastern Xwla Gbe" },
+	{ "gby", "Gbari" },
+	{ "gbz", "Zoroastrian Dari" },
+	{ "gcc", "Mali" },
+	{ "gcd", "Ganggalida" },
+	{ "gce", "Galice" },
+	{ "gcf", "Guadeloupean Creole French" },
+	{ "gcl", "Grenadian Creole English" },
+	{ "gcn", "Gaina" },
+	{ "gcr", "Guianese Creole French" },
+	{ "gct", "Colonia Tovar German" },
+	{ "gda", "Gade Lohar" },
+	{ "gdb", "Pottangi Ollar Gadaba" },
+	{ "gdc", "Gugu Badhun" },
+	{ "gdd", "Gedaged" },
+	{ "gde", "Gude" },
+	{ "gdf", "Guduf-Gava" },
+	{ "gdg", "Ga'dang" },
+	{ "gdh", "Gadjerawang" },
+	{ "gdi", "Gundi" },
+	{ "gdj", "Gurdjar" },
+	{ "gdk", "Gadang" },
+	{ "gdl", "Dirasha" },
+	{ "gdm", "Laal" },
+	{ "gdn", "Umanakaina" },
+	{ "gdo", "Ghodoberi" },
+	{ "gdq", "Mehri" },
+	{ "gdr", "Wipi" },
+	{ "gds", "Ghandruk Sign Language" },
+	{ "gdt", "Kungardutyi" },
+	{ "gdu", "Gudu" },
+	{ "gdx", "Godwari" },
+	{ "gea", "Geruma" },
+	{ "geb", "Kire" },
+	{ "gec", "Gboloo Grebo" },
+	{ "ged", "Gade" },
+	{ "geg", "Gengle" },
+	{ "geh", "Hutterite German" },
+	{ "gei", "Gebe" },
+	{ "gej", "Gen" },
+	{ "gek", "Yiwom" },
+	{ "gel", "ut-Ma'in" },
+	{ "geq", "Geme" },
+	{ "ges", "Geser-Gorom" },
+	{ "gew", "Gera" },
+	{ "gex", "Garre" },
+	{ "gey", "Enya" },
+	{ "gez", "Geez" },
+	{ "gfk", "Patpatar" },
+	{ "gft", "Gafat" },
+	{ "gfx", "Mangetti Dune !Xung" },
+	{ "gga", "Gao" },
+	{ "ggb", "Gbii" },
+	{ "ggd", "Gugadj" },
+	{ "gge", "Guragone" },
+	{ "ggg", "Gurgula" },
+	{ "ggk", "Kungarakany" },
+	{ "ggl", "Ganglau" },
+	{ "ggm", "Gugu Mini" },
+	{ "ggn", "Eastern Gurung" },
+	{ "ggo", "Southern Gondi" },
+	{ "ggt", "Gitua" },
+	{ "ggu", "Gagu" },
+	{ "ggw", "Gogodala" },
+	{ "gha", "Ghadamès" },
+	{ "ghc", "Hiberno-Scottish Gaelic" },
+	{ "ghe", "Southern Ghale" },
+	{ "ghh", "Northern Ghale" },
+	{ "ghk", "Geko Karen" },
+	{ "ghl", "Ghulfan" },
+	{ "ghn", "Ghanongga" },
+	{ "gho", "Ghomara" },
+	{ "ghr", "Ghera" },
+	{ "ghs", "Guhu-Samane" },
+	{ "ght", "Kuke" },
+	{ "gia", "Kitja" },
+	{ "gib", "Gibanawa" },
+	{ "gic", "Gail" },
+	{ "gid", "Gidar" },
+	{ "gig", "Goaria" },
+	{ "gih", "Githabul" },
+	{ "gil", "Gilbertese" },
+	{ "gim", "Gimi (Eastern Highlands)" },
+	{ "gin", "Hinukh" },
+	{ "gip", "Gimi (West New Britain)" },
+	{ "giq", "Green Gelao" },
+	{ "gir", "Red Gelao" },
+	{ "gis", "North Giziga" },
+	{ "git", "Gitxsan" },
+	{ "giu", "Mulao" },
+	{ "giw", "White Gelao" },
+	{ "gix", "Gilima" },
+	{ "giy", "Giyug" },
+	{ "giz", "South Giziga" },
+	{ "gji", "Geji" },
+	{ "gjk", "Kachi Koli" },
+	{ "gjm", "Gunditjmara" },
+	{ "gjn", "Gonja" },
+	{ "gju", "Gujari" },
+	{ "gka", "Guya" },
+	{ "gke", "Ndai" },
+	{ "gkn", "Gokana" },
+	{ "gko", "Kok-Nar" },
+	{ "gkp", "Guinea Kpelle" },
+	{ "gla", "Scottish Gaelic" },
+	{ "glc", "Bon Gula" },
+	{ "gld", "Nanai" },
+	{ "gle", "Irish" },
+	{ "glg", "Galician" },
+	{ "glh", "Northwest Pashayi" },
+	{ "gli", "Guliguli" },
+	{ "glj", "Gula Iro" },
+	{ "glk", "Gilaki" },
+	{ "gll", "Garlali" },
+	{ "glo", "Galambu" },
+	{ "glr", "Glaro-Twabo" },
+	{ "glu", "Gula (Chad)" },
+	{ "glv", "Manx" },
+	{ "glw", "Glavda" },
+	{ "gly", "Gule" },
+	{ "gma", "Gambera" },
+	{ "gmb", "Gula'alaa" },
+	{ "gmd", "Mághdì" },
+	{ "gmh", "Middle High German (ca. 1050-1500)" },
+	{ "gml", "Middle Low German" },
+	{ "gmm", "Gbaya-Mbodomo" },
+	{ "gmn", "Gimnime" },
+	{ "gmu", "Gumalu" },
+	{ "gmv", "Gamo" },
+	{ "gmx", "Magoma" },
+	{ "gmy", "Mycenaean Greek" },
+	{ "gmz", "Mgbolizhia" },
+	{ "gna", "Kaansa" },
+	{ "gnb", "Gangte" },
+	{ "gnc", "Guanche" },
+	{ "gnd", "Zulgo-Gemzek" },
+	{ "gne", "Ganang" },
+	{ "gng", "Ngangam" },
+	{ "gnh", "Lere" },
+	{ "gni", "Gooniyandi" },
+	{ "gnk", "Gana" },
+	{ "gnl", "Gangulu" },
+	{ "gnm", "Ginuman" },
+	{ "gnn", "Gumatj" },
+	{ "gno", "Northern Gondi" },
+	{ "gnq", "Gana" },
+	{ "gnr", "Gureng Gureng" },
+	{ "gnt", "Guntai" },
+	{ "gnu", "Gnau" },
+	{ "gnw", "Western Bolivian Guaraní" },
+	{ "gnz", "Ganzi" },
+	{ "goa", "Guro" },
+	{ "gob", "Playero" },
+	{ "goc", "Gorakor" },
+	{ "god", "Godié" },
+	{ "goe", "Gongduk" },
+	{ "gof", "Gofa" },
+	{ "gog", "Gogo" },
+	{ "goh", "Old High German (ca. 750-1050)" },
+	{ "goi", "Gobasi" },
+	{ "goj", "Gowlan" },
+	{ "gok", "Gowli" },
+	{ "gol", "Gola" },
+	{ "gom", "Goan Konkani" },
+	{ "gon", "Gondi" },
+	{ "goo", "Gone Dau" },
+	{ "gop", "Yeretuar" },
+	{ "goq", "Gorap" },
+	{ "gor", "Gorontalo" },
+	{ "gos", "Gronings" },
+	{ "got", "Gothic" },
+	{ "gou", "Gavar" },
+	{ "gow", "Gorowa" },
+	{ "gox", "Gobu" },
+	{ "goy", "Goundo" },
+	{ "goz", "Gozarkhani" },
+	{ "gpa", "Gupa-Abawa" },
+	{ "gpe", "Ghanaian Pidgin English" },
+	{ "gpn", "Taiap" },
+	{ "gqa", "Ga'anda" },
+	{ "gqi", "Guiqiong" },
+	{ "gqn", "Guana (Brazil)" },
+	{ "gqr", "Gor" },
+	{ "gqu", "Qau" },
+	{ "gra", "Rajput Garasia" },
+	{ "grb", "Grebo" },
+	{ "grc", "Ancient Greek (to 1453)" },
+	{ "grd", "Guruntum-Mbaaru" },
+	{ "grg", "Madi" },
+	{ "grh", "Gbiri-Niragu" },
+	{ "gri", "Ghari" },
+	{ "grj", "Southern Grebo" },
+	{ "grm", "Kota Marudu Talantang" },
+	{ "grn", "Guarani" },
+	{ "gro", "Groma" },
+	{ "grq", "Gorovu" },
+	{ "grr", "Taznatit" },
+	{ "grs", "Gresi" },
+	{ "grt", "Garo" },
+	{ "gru", "Kistane" },
+	{ "grv", "Central Grebo" },
+	{ "grw", "Gweda" },
+	{ "grx", "Guriaso" },
+	{ "gry", "Barclayville Grebo" },
+	{ "grz", "Guramalum" },
+	{ "gse", "Ghanaian Sign Language" },
+	{ "gsg", "German Sign Language" },
+	{ "gsl", "Gusilay" },
+	{ "gsm", "Guatemalan Sign Language" },
+	{ "gsn", "Gusan" },
+	{ "gso", "Southwest Gbaya" },
+	{ "gsp", "Wasembo" },
+	{ "gss", "Greek Sign Language" },
+	{ "gsw", "Swiss German" },
+	{ "gta", "Guató" },
+	{ "gti", "Gbati-ri" },
+	{ "gtu", "Aghu-Tharnggala" },
+	{ "gua", "Shiki" },
+	{ "gub", "Guajajára" },
+	{ "guc", "Wayuu" },
+	{ "gud", "Yocoboué Dida" },
+	{ "gue", "Gurinji" },
+	{ "guf", "Gupapuyngu" },
+	{ "gug", "Paraguayan Guaraní" },
+	{ "guh", "Guahibo" },
+	{ "gui", "Eastern Bolivian Guaraní" },
+	{ "guj", "Gujarati" },
+	{ "guk", "Gumuz" },
+	{ "gul", "Sea Island Creole English" },
+	{ "gum", "Guambiano" },
+	{ "gun", "Mbyá Guaraní" },
+	{ "guo", "Guayabero" },
+	{ "gup", "Gunwinggu" },
+	{ "guq", "Aché" },
+	{ "gur", "Farefare" },
+	{ "gus", "Guinean Sign Language" },
+	{ "gut", "Maléku Jaíka" },
+	{ "guu", "Yanomamö" },
+	{ "guv", "Gey" },
+	{ "guw", "Gun" },
+	{ "gux", "Gourmanchéma" },
+	{ "guz", "Gusii" },
+	{ "gva", "Guana (Paraguay)" },
+	{ "gvc", "Guanano" },
+	{ "gve", "Duwet" },
+	{ "gvf", "Golin" },
+	{ "gvj", "Guajá" },
+	{ "gvl", "Gulay" },
+	{ "gvm", "Gurmana" },
+	{ "gvn", "Kuku-Yalanji" },
+	{ "gvo", "Gavião Do Jiparaná" },
+	{ "gvp", "Pará Gavião" },
+	{ "gvr", "Western Gurung" },
+	{ "gvs", "Gumawana" },
+	{ "gvy", "Guyani" },
+	{ "gwa", "Mbato" },
+	{ "gwb", "Gwa" },
+	{ "gwc", "Kalami" },
+	{ "gwd", "Gawwada" },
+	{ "gwe", "Gweno" },
+	{ "gwf", "Gowro" },
+	{ "gwg", "Moo" },
+	{ "gwi", "Gwichʼin" },
+	{ "gwj", "Gwi" },
+	{ "gwm", "Awngthim" },
+	{ "gwn", "Gwandara" },
+	{ "gwr", "Gwere" },
+	{ "gwt", "Gawar-Bati" },
+	{ "gwu", "Guwamu" },
+	{ "gww", "Kwini" },
+	{ "gwx", "Gua" },
+	{ "gxx", "Wè Southern" },
+	{ "gya", "Northwest Gbaya" },
+	{ "gyb", "Garus" },
+	{ "gyd", "Kayardild" },
+	{ "gye", "Gyem" },
+	{ "gyf", "Gungabula" },
+	{ "gyg", "Gbayi" },
+	{ "gyi", "Gyele" },
+	{ "gyl", "Gayil" },
+	{ "gym", "Ngäbere" },
+	{ "gyn", "Guyanese Creole English" },
+	{ "gyr", "Guarayu" },
+	{ "gyy", "Gunya" },
+	{ "gza", "Ganza" },
+	{ "gzi", "Gazi" },
+	{ "gzn", "Gane" },
+	{ "haa", "Han" },
+	{ "hab", "Hanoi Sign Language" },
+	{ "hac", "Gurani" },
+	{ "had", "Hatam" },
+	{ "hae", "Eastern Oromo" },
+	{ "haf", "Haiphong Sign Language" },
+	{ "hag", "Hanga" },
+	{ "hah", "Hahon" },
+	{ "hai", "Haida" },
+	{ "haj", "Hajong" },
+	{ "hak", "Hakka Chinese" },
+	{ "hal", "Halang" },
+	{ "ham", "Hewa" },
+	{ "han", "Hangaza" },
+	{ "hao", "Hakö" },
+	{ "hap", "Hupla" },
+	{ "haq", "Ha" },
+	{ "har", "Harari" },
+	{ "has", "Haisla" },
+	{ "hat", "Haitian" },
+	{ "hau", "Hausa" },
+	{ "hav", "Havu" },
+	{ "haw", "Hawaiian" },
+	{ "hax", "Southern Haida" },
+	{ "hay", "Haya" },
+	{ "haz", "Hazaragi" },
+	{ "hba", "Hamba" },
+	{ "hbb", "Huba" },
+	{ "hbn", "Heiban" },
+	{ "hbo", "Ancient Hebrew" },
+	{ "hbs", "Serbo-Croatian" },
+	{ "hbu", "Habu" },
+	{ "hca", "Andaman Creole Hindi" },
+	{ "hch", "Huichol" },
+	{ "hdn", "Northern Haida" },
+	{ "hds", "Honduras Sign Language" },
+	{ "hdy", "Hadiyya" },
+	{ "hea", "Northern Qiandong Miao" },
+	{ "heb", "Hebrew" },
+	{ "hed", "Herdé" },
+	{ "heg", "Helong" },
+	{ "heh", "Hehe" },
+	{ "hei", "Heiltsuk" },
+	{ "hem", "Hemba" },
+	{ "her", "Herero" },
+	{ "hgm", "Haiom" },
+	{ "hgw", "Haigwai" },
+	{ "hhi", "Hoia Hoia" },
+	{ "hhr", "Kerak" },
+	{ "hhy", "Hoyahoya" },
+	{ "hia", "Lamang" },
+	{ "hib", "Hibito" },
+	{ "hid", "Hidatsa" },
+	{ "hif", "Fiji Hindi" },
+	{ "hig", "Kamwe" },
+	{ "hih", "Pamosu" },
+	{ "hii", "Hinduri" },
+	{ "hij", "Hijuk" },
+	{ "hik", "Seit-Kaitetu" },
+	{ "hil", "Hiligaynon" },
+	{ "hin", "Hindi" },
+	{ "hio", "Tsoa" },
+	{ "hir", "Himarimã" },
+	{ "hit", "Hittite" },
+	{ "hiw", "Hiw" },
+	{ "hix", "Hixkaryána" },
+	{ "hji", "Haji" },
+	{ "hka", "Kahe" },
+	{ "hke", "Hunde" },
+	{ "hkk", "Hunjara-Kaina Ke" },
+	{ "hks", "Hong Kong Sign Language" },
+	{ "hla", "Halia" },
+	{ "hlb", "Halbi" },
+	{ "hld", "Halang Doan" },
+	{ "hle", "Hlersu" },
+	{ "hlt", "Matu Chin" },
+	{ "hlu", "Hieroglyphic Luwian" },
+	{ "hma", "Southern Mashan Hmong" },
+	{ "hmb", "Humburi Senni Songhay" },
+	{ "hmc", "Central Huishui Hmong" },
+	{ "hmd", "Large Flowery Miao" },
+	{ "hme", "Eastern Huishui Hmong" },
+	{ "hmf", "Hmong Don" },
+	{ "hmg", "Southwestern Guiyang Hmong" },
+	{ "hmh", "Southwestern Huishui Hmong" },
+	{ "hmi", "Northern Huishui Hmong" },
+	{ "hmj", "Ge" },
+	{ "hmk", "Maek" },
+	{ "hml", "Luopohe Hmong" },
+	{ "hmm", "Central Mashan Hmong" },
+	{ "hmn", "Hmong" },
+	{ "hmo", "Hiri Motu" },
+	{ "hmp", "Northern Mashan Hmong" },
+	{ "hmq", "Eastern Qiandong Miao" },
+	{ "hmr", "Hmar" },
+	{ "hms", "Southern Qiandong Miao" },
+	{ "hmt", "Hamtai" },
+	{ "hmu", "Hamap" },
+	{ "hmv", "Hmong Dô" },
+	{ "hmw", "Western Mashan Hmong" },
+	{ "hmy", "Southern Guiyang Hmong" },
+	{ "hmz", "Hmong Shua" },
+	{ "hna", "Mina (Cameroon)" },
+	{ "hnd", "Southern Hindko" },
+	{ "hne", "Chhattisgarhi" },
+	{ "hnh", "Ani" },
+	{ "hni", "Hani" },
+	{ "hnj", "Hmong Njua" },
+	{ "hnn", "Hanunoo" },
+	{ "hno", "Northern Hindko" },
+	{ "hns", "Caribbean Hindustani" },
+	{ "hnu", "Hung" },
+	{ "hoa", "Hoava" },
+	{ "hob", "Mari (Madang Province)" },
+	{ "hoc", "Ho" },
+	{ "hod", "Holma" },
+	{ "hoe", "Horom" },
+	{ "hoh", "Hobyót" },
+	{ "hoi", "Holikachuk" },
+	{ "hoj", "Hadothi" },
+	{ "hol", "Holu" },
+	{ "hom", "Homa" },
+	{ "hoo", "Holoholo" },
+	{ "hop", "Hopi" },
+	{ "hor", "Horo" },
+	{ "hos", "Ho Chi Minh City Sign Language" },
+	{ "hot", "Hote" },
+	{ "hov", "Hovongan" },
+	{ "how", "Honi" },
+	{ "hoy", "Holiya" },
+	{ "hoz", "Hozo" },
+	{ "hpo", "Hpon" },
+	{ "hps", "Hawai'i Pidgin Sign Language" },
+	{ "hra", "Hrangkhol" },
+	{ "hrc", "Niwer Mil" },
+	{ "hre", "Hre" },
+	{ "hrk", "Haruku" },
+	{ "hrm", "Horned Miao" },
+	{ "hro", "Haroi" },
+	{ "hrp", "Nhirrpi" },
+	{ "hrt", "Hértevin" },
+	{ "hru", "Hruso" },
+	{ "hrv", "Croatian" },
+	{ "hrw", "Warwar Feni" },
+	{ "hrx", "Hunsrik" },
+	{ "hrz", "Harzani" },
+	{ "hsb", "Upper Sorbian" },
+	{ "hsh", "Hungarian Sign Language" },
+	{ "hsl", "Hausa Sign Language" },
+	{ "hsn", "Xiang Chinese" },
+	{ "hss", "Harsusi" },
+	{ "hti", "Hoti" },
+	{ "hto", "Minica Huitoto" },
+	{ "hts", "Hadza" },
+	{ "htu", "Hitu" },
+	{ "htx", "Middle Hittite" },
+	{ "hub", "Huambisa" },
+	{ "huc", "=Hua" },
+	{ "hud", "Huaulu" },
+	{ "hue", "San Francisco Del Mar Huave" },
+	{ "huf", "Humene" },
+	{ "hug", "Huachipaeri" },
+	{ "huh", "Huilliche" },
+	{ "hui", "Huli" },
+	{ "huj", "Northern Guiyang Hmong" },
+	{ "huk", "Hulung" },
+	{ "hul", "Hula" },
+	{ "hum", "Hungana" },
+	{ "hun", "Hungarian" },
+	{ "huo", "Hu" },
+	{ "hup", "Hupa" },
+	{ "huq", "Tsat" },
+	{ "hur", "Halkomelem" },
+	{ "hus", "Huastec" },
+	{ "hut", "Humla" },
+	{ "huu", "Murui Huitoto" },
+	{ "huv", "San Mateo Del Mar Huave" },
+	{ "huw", "Hukumina" },
+	{ "hux", "Nüpode Huitoto" },
+	{ "huy", "Hulaulá" },
+	{ "huz", "Hunzib" },
+	{ "hvc", "Haitian Vodoun Culture Language" },
+	{ "hve", "San Dionisio Del Mar Huave" },
+	{ "hvk", "Haveke" },
+	{ "hvn", "Sabu" },
+	{ "hvv", "Santa María Del Mar Huave" },
+	{ "hwa", "Wané" },
+	{ "hwc", "Hawai'i Creole English" },
+	{ "hwo", "Hwana" },
+	{ "hya", "Hya" },
+	{ "hye", "Armenian" },
+	{ "iai", "Iaai" },
+	{ "ian", "Iatmul" },
+	{ "iap", "Iapama" },
+	{ "iar", "Purari" },
+	{ "iba", "Iban" },
+	{ "ibb", "Ibibio" },
+	{ "ibd", "Iwaidja" },
+	{ "ibe", "Akpes" },
+	{ "ibg", "Ibanag" },
+	{ "ibl", "Ibaloi" },
+	{ "ibm", "Agoi" },
+	{ "ibn", "Ibino" },
+	{ "ibo", "Igbo" },
+	{ "ibr", "Ibuoro" },
+	{ "ibu", "Ibu" },
+	{ "iby", "Ibani" },
+	{ "ica", "Ede Ica" },
+	{ "ich", "Etkywan" },
+	{ "icl", "Icelandic Sign Language" },
+	{ "icr", "Islander Creole English" },
+	{ "ida", "Idakho-Isukha-Tiriki" },
+	{ "idb", "Indo-Portuguese" },
+	{ "idc", "Idon" },
+	{ "idd", "Ede Idaca" },
+	{ "ide", "Idere" },
+	{ "idi", "Idi" },
+	{ "ido", "Ido" },
+	{ "idr", "Indri" },
+	{ "ids", "Idesa" },
+	{ "idt", "Idaté" },
+	{ "idu", "Idoma" },
+	{ "ifa", "Amganad Ifugao" },
+	{ "ifb", "Batad Ifugao" },
+	{ "ife", "Ifè" },
+	{ "iff", "Ifo" },
+	{ "ifk", "Tuwali Ifugao" },
+	{ "ifm", "Teke-Fuumu" },
+	{ "ifu", "Mayoyao Ifugao" },
+	{ "ify", "Keley-I Kallahan" },
+	{ "igb", "Ebira" },
+	{ "ige", "Igede" },
+	{ "igg", "Igana" },
+	{ "igl", "Igala" },
+	{ "igm", "Kanggape" },
+	{ "ign", "Ignaciano" },
+	{ "igo", "Isebe" },
+	{ "igs", "Interglossa" },
+	{ "igw", "Igwe" },
+	{ "ihb", "Iha Based Pidgin" },
+	{ "ihi", "Ihievbe" },
+	{ "ihp", "Iha" },
+	{ "ihw", "Bidhawal" },
+	{ "iii", "Sichuan Yi" },
+	{ "iin", "Thiin" },
+	{ "ijc", "Izon" },
+	{ "ije", "Biseni" },
+	{ "ijj", "Ede Ije" },
+	{ "ijn", "Kalabari" },
+	{ "ijs", "Southeast Ijo" },
+	{ "ike", "Eastern Canadian Inuktitut" },
+	{ "iki", "Iko" },
+	{ "ikk", "Ika" },
+	{ "ikl", "Ikulu" },
+	{ "iko", "Olulumo-Ikom" },
+	{ "ikp", "Ikpeshi" },
+	{ "ikr", "Ikaranggal" },
+	{ "ikt", "Inuinnaqtun" },
+	{ "iku", "Inuktitut" },
+	{ "ikv", "Iku-Gora-Ankwa" },
+	{ "ikw", "Ikwere" },
+	{ "ikx", "Ik" },
+	{ "ikz", "Ikizu" },
+	{ "ila", "Ile Ape" },
+	{ "ilb", "Ila" },
+	{ "ile", "Interlingue" },
+	{ "ilg", "Garig-Ilgar" },
+	{ "ili", "Ili Turki" },
+	{ "ilk", "Ilongot" },
+	{ "ill", "Iranun" },
+	{ "ilo", "Iloko" },
+	{ "ils", "International Sign" },
+	{ "ilu", "Ili'uun" },
+	{ "ilv", "Ilue" },
+	{ "ima", "Mala Malasar" },
+	{ "ime", "Imeraguen" },
+	{ "imi", "Anamgura" },
+	{ "iml", "Miluk" },
+	{ "imn", "Imonda" },
+	{ "imo", "Imbongu" },
+	{ "imr", "Imroing" },
+	{ "ims", "Marsian" },
+	{ "imy", "Milyan" },
+	{ "ina", "Interlingua (International Auxiliary Language Association)" },
+	{ "inb", "Inga" },
+	{ "ind", "Indonesian" },
+	{ "ing", "Degexit'an" },
+	{ "inh", "Ingush" },
+	{ "inj", "Jungle Inga" },
+	{ "inl", "Indonesian Sign Language" },
+	{ "inm", "Minaean" },
+	{ "inn", "Isinai" },
+	{ "ino", "Inoke-Yate" },
+	{ "inp", "Iñapari" },
+	{ "ins", "Indian Sign Language" },
+	{ "int", "Intha" },
+	{ "inz", "Ineseño" },
+	{ "ior", "Inor" },
+	{ "iou", "Tuma-Irumu" },
+	{ "iow", "Iowa-Oto" },
+	{ "ipi", "Ipili" },
+	{ "ipk", "Inupiaq" },
+	{ "ipo", "Ipiko" },
+	{ "iqu", "Iquito" },
+	{ "iqw", "Ikwo" },
+	{ "ire", "Iresim" },
+	{ "irh", "Irarutu" },
+	{ "iri", "Irigwe" },
+	{ "irk", "Iraqw" },
+	{ "irn", "Irántxe" },
+	{ "irr", "Ir" },
+	{ "iru", "Irula" },
+	{ "irx", "Kamberau" },
+	{ "iry", "Iraya" },
+	{ "isa", "Isabi" },
+	{ "isc", "Isconahua" },
+	{ "isd", "Isnag" },
+	{ "ise", "Italian Sign Language" },
+	{ "isg", "Irish Sign Language" },
+	{ "ish", "Esan" },
+	{ "isi", "Nkem-Nkum" },
+	{ "isk", "Ishkashimi" },
+	{ "isl", "Icelandic" },
+	{ "ism", "Masimasi" },
+	{ "isn", "Isanzu" },
+	{ "iso", "Isoko" },
+	{ "isr", "Israeli Sign Language" },
+	{ "ist", "Istriot" },
+	{ "isu", "Isu (Menchum Division)" },
+	{ "ita", "Italian" },
+	{ "itb", "Binongan Itneg" },
+	{ "ite", "Itene" },
+	{ "iti", "Inlaod Itneg" },
+	{ "itk", "Judeo-Italian" },
+	{ "itl", "Itelmen" },
+	{ "itm", "Itu Mbon Uzo" },
+	{ "ito", "Itonama" },
+	{ "itr", "Iteri" },
+	{ "its", "Isekiri" },
+	{ "itt", "Maeng Itneg" },
+	{ "itv", "Itawit" },
+	{ "itw", "Ito" },
+	{ "itx", "Itik" },
+	{ "ity", "Moyadan Itneg" },
+	{ "itz", "Itzá" },
+	{ "ium", "Iu Mien" },
+	{ "ivb", "Ibatan" },
+	{ "ivv", "Ivatan" },
+	{ "iwk", "I-Wak" },
+	{ "iwm", "Iwam" },
+	{ "iwo", "Iwur" },
+	{ "iws", "Sepik Iwam" },
+	{ "ixc", "Ixcatec" },
+	{ "ixl", "Ixil" },
+	{ "iya", "Iyayu" },
+	{ "iyo", "Mesaka" },
+	{ "iyx", "Yaka (Congo)" },
+	{ "izh", "Ingrian" },
+	{ "izr", "Izere" },
+	{ "izz", "Izii" },
+	{ "jaa", "Jamamadí" },
+	{ "jab", "Hyam" },
+	{ "jac", "Popti'" },
+	{ "jad", "Jahanka" },
+	{ "jae", "Yabem" },
+	{ "jaf", "Jara" },
+	{ "jah", "Jah Hut" },
+	{ "jaj", "Zazao" },
+	{ "jak", "Jakun" },
+	{ "jal", "Yalahatan" },
+	{ "jam", "Jamaican Creole English" },
+	{ "jan", "Jandai" },
+	{ "jao", "Yanyuwa" },
+	{ "jaq", "Yaqay" },
+	{ "jas", "New Caledonian Javanese" },
+	{ "jat", "Jakati" },
+	{ "jau", "Yaur" },
+	{ "jav", "Javanese" },
+	{ "jax", "Jambi Malay" },
+	{ "jay", "Yan-nhangu" },
+	{ "jaz", "Jawe" },
+	{ "jbe", "Judeo-Berber" },
+	{ "jbi", "Badjiri" },
+	{ "jbj", "Arandai" },
+	{ "jbk", "Barikewa" },
+	{ "jbn", "Nafusi" },
+	{ "jbo", "Lojban" },
+	{ "jbr", "Jofotek-Bromnya" },
+	{ "jbt", "Jabutí" },
+	{ "jbu", "Jukun Takum" },
+	{ "jbw", "Yawijibaya" },
+	{ "jcs", "Jamaican Country Sign Language" },
+	{ "jct", "Krymchak" },
+	{ "jda", "Jad" },
+	{ "jdg", "Jadgali" },
+	{ "jdt", "Judeo-Tat" },
+	{ "jeb", "Jebero" },
+	{ "jee", "Jerung" },
+	{ "jeg", "Jeng" },
+	{ "jeh", "Jeh" },
+	{ "jei", "Yei" },
+	{ "jek", "Jeri Kuo" },
+	{ "jel", "Yelmek" },
+	{ "jen", "Dza" },
+	{ "jer", "Jere" },
+	{ "jet", "Manem" },
+	{ "jeu", "Jonkor Bourmataguil" },
+	{ "jgb", "Ngbee" },
+	{ "jge", "Judeo-Georgian" },
+	{ "jgk", "Gwak" },
+	{ "jgo", "Ngomba" },
+	{ "jhi", "Jehai" },
+	{ "jhs", "Jhankot Sign Language" },
+	{ "jia", "Jina" },
+	{ "jib", "Jibu" },
+	{ "jic", "Tol" },
+	{ "jid", "Bu" },
+	{ "jie", "Jilbe" },
+	{ "jig", "Djingili" },
+	{ "jih", "sTodsde" },
+	{ "jii", "Jiiddu" },
+	{ "jil", "Jilim" },
+	{ "jim", "Jimi (Cameroon)" },
+	{ "jio", "Jiamao" },
+	{ "jiq", "Guanyinqiao" },
+	{ "jit", "Jita" },
+	{ "jiu", "Youle Jinuo" },
+	{ "jiv", "Shuar" },
+	{ "jiy", "Buyuan Jinuo" },
+	{ "jjr", "Bankal" },
+	{ "jkm", "Mobwa Karen" },
+	{ "jko", "Kubo" },
+	{ "jkp", "Paku Karen" },
+	{ "jkr", "Koro (India)" },
+	{ "jku", "Labir" },
+	{ "jle", "Ngile" },
+	{ "jls", "Jamaican Sign Language" },
+	{ "jma", "Dima" },
+	{ "jmb", "Zumbun" },
+	{ "jmc", "Machame" },
+	{ "jmd", "Yamdena" },
+	{ "jmi", "Jimi (Nigeria)" },
+	{ "jml", "Jumli" },
+	{ "jmn", "Makuri Naga" },
+	{ "jmr", "Kamara" },
+	{ "jms", "Mashi (Nigeria)" },
+	{ "jmw", "Mouwase" },
+	{ "jmx", "Western Juxtlahuaca Mixtec" },
+	{ "jna", "Jangshung" },
+	{ "jnd", "Jandavra" },
+	{ "jng", "Yangman" },
+	{ "jni", "Janji" },
+	{ "jnj", "Yemsa" },
+	{ "jnl", "Rawat" },
+	{ "jns", "Jaunsari" },
+	{ "job", "Joba" },
+	{ "jod", "Wojenaka" },
+	{ "jor", "Jorá" },
+	{ "jos", "Jordanian Sign Language" },
+	{ "jow", "Jowulu" },
+	{ "jpa", "Jewish Palestinian Aramaic" },
+	{ "jpn", "Japanese" },
+	{ "jpr", "Judeo-Persian" },
+	{ "jqr", "Jaqaru" },
+	{ "jra", "Jarai" },
+	{ "jrb", "Judeo-Arabic" },
+	{ "jrr", "Jiru" },
+	{ "jrt", "Jorto" },
+	{ "jru", "Japrería" },
+	{ "jsl", "Japanese Sign Language" },
+	{ "jua", "Júma" },
+	{ "jub", "Wannu" },
+	{ "juc", "Jurchen" },
+	{ "jud", "Worodougou" },
+	{ "juh", "Hõne" },
+	{ "jui", "Ngadjuri" },
+	{ "juk", "Wapan" },
+	{ "jul", "Jirel" },
+	{ "jum", "Jumjum" },
+	{ "jun", "Juang" },
+	{ "juo", "Jiba" },
+	{ "jup", "Hupdë" },
+	{ "jur", "Jurúna" },
+	{ "jus", "Jumla Sign Language" },
+	{ "jut", "Jutish" },
+	{ "juu", "Ju" },
+	{ "juw", "Wãpha" },
+	{ "juy", "Juray" },
+	{ "jvd", "Javindo" },
+	{ "jvn", "Caribbean Javanese" },
+	{ "jwi", "Jwira-Pepesa" },
+	{ "jya", "Jiarong" },
+	{ "jye", "Judeo-Yemeni Arabic" },
+	{ "jyy", "Jaya" },
+	{ "kaa", "Kara-Kalpak" },
+	{ "kab", "Kabyle" },
+	{ "kac", "Kachin" },
+	{ "kad", "Adara" },
+	{ "kae", "Ketangalan" },
+	{ "kaf", "Katso" },
+	{ "kag", "Kajaman" },
+	{ "kah", "Kara (Central African Republic)" },
+	{ "kai", "Karekare" },
+	{ "kaj", "Jju" },
+	{ "kak", "Kayapa Kallahan" },
+	{ "kal", "Kalaallisut" },
+	{ "kam", "Kamba (Kenya)" },
+	{ "kan", "Kannada" },
+	{ "kao", "Xaasongaxango" },
+	{ "kap", "Bezhta" },
+	{ "kaq", "Capanahua" },
+	{ "kas", "Kashmiri" },
+	{ "kat", "Georgian" },
+	{ "kau", "Kanuri" },
+	{ "kav", "Katukína" },
+	{ "kaw", "Kawi" },
+	{ "kax", "Kao" },
+	{ "kay", "Kamayurá" },
+	{ "kaz", "Kazakh" },
+	{ "kba", "Kalarko" },
+	{ "kbb", "Kaxuiâna" },
+	{ "kbc", "Kadiwéu" },
+	{ "kbd", "Kabardian" },
+	{ "kbe", "Kanju" },
+	{ "kbf", "Kakauhua" },
+	{ "kbg", "Khamba" },
+	{ "kbh", "Camsá" },
+	{ "kbi", "Kaptiau" },
+	{ "kbj", "Kari" },
+	{ "kbk", "Grass Koiari" },
+	{ "kbl", "Kanembu" },
+	{ "kbm", "Iwal" },
+	{ "kbn", "Kare (Central African Republic)" },
+	{ "kbo", "Keliko" },
+	{ "kbp", "Kabiyè" },
+	{ "kbq", "Kamano" },
+	{ "kbr", "Kafa" },
+	{ "kbs", "Kande" },
+	{ "kbt", "Abadi" },
+	{ "kbu", "Kabutra" },
+	{ "kbv", "Dera (Indonesia)" },
+	{ "kbw", "Kaiep" },
+	{ "kbx", "Ap Ma" },
+	{ "kby", "Manga Kanuri" },
+	{ "kbz", "Duhwa" },
+	{ "kca", "Khanty" },
+	{ "kcb", "Kawacha" },
+	{ "kcc", "Lubila" },
+	{ "kcd", "Ngkâlmpw Kanum" },
+	{ "kce", "Kaivi" },
+	{ "kcf", "Ukaan" },
+	{ "kcg", "Tyap" },
+	{ "kch", "Vono" },
+	{ "kci", "Kamantan" },
+	{ "kcj", "Kobiana" },
+	{ "kck", "Kalanga" },
+	{ "kcl", "Kela (Papua New Guinea)" },
+	{ "kcm", "Gula (Central African Republic)" },
+	{ "kcn", "Nubi" },
+	{ "kco", "Kinalakna" },
+	{ "kcp", "Kanga" },
+	{ "kcq", "Kamo" },
+	{ "kcr", "Katla" },
+	{ "kcs", "Koenoem" },
+	{ "kct", "Kaian" },
+	{ "kcu", "Kami (Tanzania)" },
+	{ "kcv", "Kete" },
+	{ "kcw", "Kabwari" },
+	{ "kcx", "Kachama-Ganjule" },
+	{ "kcy", "Korandje" },
+	{ "kcz", "Konongo" },
+	{ "kda", "Worimi" },
+	{ "kdc", "Kutu" },
+	{ "kdd", "Yankunytjatjara" },
+	{ "kde", "Makonde" },
+	{ "kdf", "Mamusi" },
+	{ "kdg", "Seba" },
+	{ "kdh", "Tem" },
+	{ "kdi", "Kumam" },
+	{ "kdj", "Karamojong" },
+	{ "kdk", "Numèè" },
+	{ "kdl", "Tsikimba" },
+	{ "kdm", "Kagoma" },
+	{ "kdn", "Kunda" },
+	{ "kdp", "Kaningdon-Nindem" },
+	{ "kdq", "Koch" },
+	{ "kdr", "Karaim" },
+	{ "kdt", "Kuy" },
+	{ "kdu", "Kadaru" },
+	{ "kdw", "Koneraw" },
+	{ "kdx", "Kam" },
+	{ "kdy", "Keder" },
+	{ "kdz", "Kwaja" },
+	{ "kea", "Kabuverdianu" },
+	{ "keb", "Kélé" },
+	{ "kec", "Keiga" },
+	{ "ked", "Kerewe" },
+	{ "kee", "Eastern Keres" },
+	{ "kef", "Kpessi" },
+	{ "keg", "Tese" },
+	{ "keh", "Keak" },
+	{ "kei", "Kei" },
+	{ "kej", "Kadar" },
+	{ "kek", "Kekchí" },
+	{ "kel", "Kela (Democratic Republic of Congo)" },
+	{ "kem", "Kemak" },
+	{ "ken", "Kenyang" },
+	{ "keo", "Kakwa" },
+	{ "kep", "Kaikadi" },
+	{ "keq", "Kamar" },
+	{ "ker", "Kera" },
+	{ "kes", "Kugbo" },
+	{ "ket", "Ket" },
+	{ "keu", "Akebu" },
+	{ "kev", "Kanikkaran" },
+	{ "kew", "West Kewa" },
+	{ "kex", "Kukna" },
+	{ "key", "Kupia" },
+	{ "kez", "Kukele" },
+	{ "kfa", "Kodava" },
+	{ "kfb", "Northwestern Kolami" },
+	{ "kfc", "Konda-Dora" },
+	{ "kfd", "Korra Koraga" },
+	{ "kfe", "Kota (India)" },
+	{ "kff", "Koya" },
+	{ "kfg", "Kudiya" },
+	{ "kfh", "Kurichiya" },
+	{ "kfi", "Kannada Kurumba" },
+	{ "kfj", "Kemiehua" },
+	{ "kfk", "Kinnauri" },
+	{ "kfl", "Kung" },
+	{ "kfm", "Khunsari" },
+	{ "kfn", "Kuk" },
+	{ "kfo", "Koro (Côte d'Ivoire)" },
+	{ "kfp", "Korwa" },
+	{ "kfq", "Korku" },
+	{ "kfr", "Kachchi" },
+	{ "kfs", "Bilaspuri" },
+	{ "kft", "Kanjari" },
+	{ "kfu", "Katkari" },
+	{ "kfv", "Kurmukar" },
+	{ "kfw", "Kharam Naga" },
+	{ "kfx", "Kullu Pahari" },
+	{ "kfy", "Kumaoni" },
+	{ "kfz", "Koromfé" },
+	{ "kga", "Koyaga" },
+	{ "kgb", "Kawe" },
+	{ "kgc", "Kasseng" },
+	{ "kgd", "Kataang" },
+	{ "kge", "Komering" },
+	{ "kgf", "Kube" },
+	{ "kgg", "Kusunda" },
+	{ "kgi", "Selangor Sign Language" },
+	{ "kgj", "Gamale Kham" },
+	{ "kgk", "Kaiwá" },
+	{ "kgl", "Kunggari" },
+	{ "kgm", "Karipúna" },
+	{ "kgn", "Karingani" },
+	{ "kgo", "Krongo" },
+	{ "kgp", "Kaingang" },
+	{ "kgq", "Kamoro" },
+	{ "kgr", "Abun" },
+	{ "kgs", "Kumbainggar" },
+	{ "kgt", "Somyev" },
+	{ "kgu", "Kobol" },
+	{ "kgv", "Karas" },
+	{ "kgw", "Karon Dori" },
+	{ "kgx", "Kamaru" },
+	{ "kgy", "Kyerung" },
+	{ "kha", "Khasi" },
+	{ "khb", "Lü" },
+	{ "khc", "Tukang Besi North" },
+	{ "khd", "Bädi Kanum" },
+	{ "khe", "Korowai" },
+	{ "khf", "Khuen" },
+	{ "khg", "Khams Tibetan" },
+	{ "khh", "Kehu" },
+	{ "khj", "Kuturmi" },
+	{ "khk", "Halh Mongolian" },
+	{ "khl", "Lusi" },
+	{ "khm", "Central Khmer" },
+	{ "khn", "Khandesi" },
+	{ "kho", "Khotanese" },
+	{ "khp", "Kapori" },
+	{ "khq", "Koyra Chiini Songhay" },
+	{ "khr", "Kharia" },
+	{ "khs", "Kasua" },
+	{ "kht", "Khamti" },
+	{ "khu", "Nkhumbi" },
+	{ "khv", "Khvarshi" },
+	{ "khw", "Khowar" },
+	{ "khx", "Kanu" },
+	{ "khy", "Kele (Democratic Republic of Congo)" },
+	{ "khz", "Keapara" },
+	{ "kia", "Kim" },
+	{ "kib", "Koalib" },
+	{ "kic", "Kickapoo" },
+	{ "kid", "Koshin" },
+	{ "kie", "Kibet" },
+	{ "kif", "Eastern Parbate Kham" },
+	{ "kig", "Kimaama" },
+	{ "kih", "Kilmeri" },
+	{ "kii", "Kitsai" },
+	{ "kij", "Kilivila" },
+	{ "kik", "Kikuyu" },
+	{ "kil", "Kariya" },
+	{ "kim", "Karagas" },
+	{ "kin", "Kinyarwanda" },
+	{ "kio", "Kiowa" },
+	{ "kip", "Sheshi Kham" },
+	{ "kiq", "Kosadle" },
+	{ "kir", "Kirghiz" },
+	{ "kis", "Kis" },
+	{ "kit", "Agob" },
+	{ "kiu", "Kirmanjki (individual language)" },
+	{ "kiv", "Kimbu" },
+	{ "kiw", "Northeast Kiwai" },
+	{ "kix", "Khiamniungan Naga" },
+	{ "kiy", "Kirikiri" },
+	{ "kiz", "Kisi" },
+	{ "kja", "Mlap" },
+	{ "kjb", "Q'anjob'al" },
+	{ "kjc", "Coastal Konjo" },
+	{ "kjd", "Southern Kiwai" },
+	{ "kje", "Kisar" },
+	{ "kjf", "Khalaj" },
+	{ "kjg", "Khmu" },
+	{ "kjh", "Khakas" },
+	{ "kji", "Zabana" },
+	{ "kjj", "Khinalugh" },
+	{ "kjk", "Highland Konjo" },
+	{ "kjl", "Western Parbate Kham" },
+	{ "kjm", "Kháng" },
+	{ "kjn", "Kunjen" },
+	{ "kjo", "Harijan Kinnauri" },
+	{ "kjp", "Pwo Eastern Karen" },
+	{ "kjq", "Western Keres" },
+	{ "kjr", "Kurudu" },
+	{ "kjs", "East Kewa" },
+	{ "kjt", "Phrae Pwo Karen" },
+	{ "kju", "Kashaya" },
+	{ "kjx", "Ramopa" },
+	{ "kjy", "Erave" },
+	{ "kjz", "Bumthangkha" },
+	{ "kka", "Kakanda" },
+	{ "kkb", "Kwerisa" },
+	{ "kkc", "Odoodee" },
+	{ "kkd", "Kinuku" },
+	{ "kke", "Kakabe" },
+	{ "kkf", "Kalaktang Monpa" },
+	{ "kkg", "Mabaka Valley Kalinga" },
+	{ "kkh", "Khün" },
+	{ "kki", "Kagulu" },
+	{ "kkj", "Kako" },
+	{ "kkk", "Kokota" },
+	{ "kkl", "Kosarek Yale" },
+	{ "kkm", "Kiong" },
+	{ "kkn", "Kon Keu" },
+	{ "kko", "Karko" },
+	{ "kkp", "Gugubera" },
+	{ "kkq", "Kaiku" },
+	{ "kkr", "Kir-Balar" },
+	{ "kks", "Giiwo" },
+	{ "kkt", "Koi" },
+	{ "kku", "Tumi" },
+	{ "kkv", "Kangean" },
+	{ "kkw", "Teke-Kukuya" },
+	{ "kkx", "Kohin" },
+	{ "kky", "Guguyimidjir" },
+	{ "kkz", "Kaska" },
+	{ "kla", "Klamath-Modoc" },
+	{ "klb", "Kiliwa" },
+	{ "klc", "Kolbila" },
+	{ "kld", "Gamilaraay" },
+	{ "kle", "Kulung (Nepal)" },
+	{ "klf", "Kendeje" },
+	{ "klg", "Tagakaulo" },
+	{ "klh", "Weliki" },
+	{ "kli", "Kalumpang" },
+	{ "klj", "Turkic Khalaj" },
+	{ "klk", "Kono (Nigeria)" },
+	{ "kll", "Kagan Kalagan" },
+	{ "klm", "Migum" },
+	{ "kln", "Kalenjin" },
+	{ "klo", "Kapya" },
+	{ "klp", "Kamasa" },
+	{ "klq", "Rumu" },
+	{ "klr", "Khaling" },
+	{ "kls", "Kalasha" },
+	{ "klt", "Nukna" },
+	{ "klu", "Klao" },
+	{ "klv", "Maskelynes" },
+	{ "klw", "Lindu" },
+	{ "klx", "Koluwawa" },
+	{ "kly", "Kalao" },
+	{ "klz", "Kabola" },
+	{ "kma", "Konni" },
+	{ "kmb", "Kimbundu" },
+	{ "kmc", "Southern Dong" },
+	{ "kmd", "Majukayang Kalinga" },
+	{ "kme", "Bakole" },
+	{ "kmf", "Kare (Papua New Guinea)" },
+	{ "kmg", "Kâte" },
+	{ "kmh", "Kalam" },
+	{ "kmi", "Kami (Nigeria)" },
+	{ "kmj", "Kumarbhag Paharia" },
+	{ "kmk", "Limos Kalinga" },
+	{ "kml", "Tanudan Kalinga" },
+	{ "kmm", "Kom (India)" },
+	{ "kmn", "Awtuw" },
+	{ "kmo", "Kwoma" },
+	{ "kmp", "Gimme" },
+	{ "kmq", "Kwama" },
+	{ "kmr", "Northern Kurdish" },
+	{ "kms", "Kamasau" },
+	{ "kmt", "Kemtuik" },
+	{ "kmu", "Kanite" },
+	{ "kmv", "Karipúna Creole French" },
+	{ "kmw", "Komo (Democratic Republic of Congo)" },
+	{ "kmx", "Waboda" },
+	{ "kmy", "Koma" },
+	{ "kmz", "Khorasani Turkish" },
+	{ "kna", "Dera (Nigeria)" },
+	{ "knb", "Lubuagan Kalinga" },
+	{ "knc", "Central Kanuri" },
+	{ "knd", "Konda" },
+	{ "kne", "Kankanaey" },
+	{ "knf", "Mankanya" },
+	{ "kng", "Koongo" },
+	{ "kni", "Kanufi" },
+	{ "knj", "Western Kanjobal" },
+	{ "knk", "Kuranko" },
+	{ "knl", "Keninjal" },
+	{ "knm", "Kanamarí" },
+	{ "knn", "Konkani (individual language)" },
+	{ "kno", "Kono (Sierra Leone)" },
+	{ "knp", "Kwanja" },
+	{ "knq", "Kintaq" },
+	{ "knr", "Kaningra" },
+	{ "kns", "Kensiu" },
+	{ "knt", "Panoan Katukína" },
+	{ "knu", "Kono (Guinea)" },
+	{ "knv", "Tabo" },
+	{ "knw", "Kung-Ekoka" },
+	{ "knx", "Kendayan" },
+	{ "kny", "Kanyok" },
+	{ "knz", "Kalamsé" },
+	{ "koa", "Konomala" },
+	{ "koc", "Kpati" },
+	{ "kod", "Kodi" },
+	{ "koe", "Kacipo-Balesi" },
+	{ "kof", "Kubi" },
+	{ "kog", "Cogui" },
+	{ "koh", "Koyo" },
+	{ "koi", "Komi-Permyak" },
+	{ "koj", "Sara Dunjo" },
+	{ "kok", "Konkani (macrolanguage)" },
+	{ "kol", "Kol (Papua New Guinea)" },
+	{ "kom", "Komi" },
+	{ "kon", "Kongo" },
+	{ "koo", "Konzo" },
+	{ "kop", "Waube" },
+	{ "koq", "Kota (Gabon)" },
+	{ "kor", "Korean" },
+	{ "kos", "Kosraean" },
+	{ "kot", "Lagwan" },
+	{ "kou", "Koke" },
+	{ "kov", "Kudu-Camo" },
+	{ "kow", "Kugama" },
+	{ "kox", "Coxima" },
+	{ "koy", "Koyukon" },
+	{ "koz", "Korak" },
+	{ "kpa", "Kutto" },
+	{ "kpb", "Mullu Kurumba" },
+	{ "kpc", "Curripaco" },
+	{ "kpd", "Koba" },
+	{ "kpe", "Kpelle" },
+	{ "kpf", "Komba" },
+	{ "kpg", "Kapingamarangi" },
+	{ "kph", "Kplang" },
+	{ "kpi", "Kofei" },
+	{ "kpj", "Karajá" },
+	{ "kpk", "Kpan" },
+	{ "kpl", "Kpala" },
+	{ "kpm", "Koho" },
+	{ "kpn", "Kepkiriwát" },
+	{ "kpo", "Ikposo" },
+	{ "kpq", "Korupun-Sela" },
+	{ "kpr", "Korafe-Yegha" },
+	{ "kps", "Tehit" },
+	{ "kpt", "Karata" },
+	{ "kpu", "Kafoa" },
+	{ "kpv", "Komi-Zyrian" },
+	{ "kpw", "Kobon" },
+	{ "kpx", "Mountain Koiali" },
+	{ "kpy", "Koryak" },
+	{ "kpz", "Kupsabiny" },
+	{ "kqa", "Mum" },
+	{ "kqb", "Kovai" },
+	{ "kqc", "Doromu-Koki" },
+	{ "kqd", "Koy Sanjaq Surat" },
+	{ "kqe", "Kalagan" },
+	{ "kqf", "Kakabai" },
+	{ "kqg", "Khe" },
+	{ "kqh", "Kisankasa" },
+	{ "kqi", "Koitabu" },
+	{ "kqj", "Koromira" },
+	{ "kqk", "Kotafon Gbe" },
+	{ "kql", "Kyenele" },
+	{ "kqm", "Khisa" },
+	{ "kqn", "Kaonde" },
+	{ "kqo", "Eastern Krahn" },
+	{ "kqp", "Kimré" },
+	{ "kqq", "Krenak" },
+	{ "kqr", "Kimaragang" },
+	{ "kqs", "Northern Kissi" },
+	{ "kqt", "Klias River Kadazan" },
+	{ "kqu", "Seroa" },
+	{ "kqv", "Okolod" },
+	{ "kqw", "Kandas" },
+	{ "kqx", "Mser" },
+	{ "kqy", "Koorete" },
+	{ "kqz", "Korana" },
+	{ "kra", "Kumhali" },
+	{ "krb", "Karkin" },
+	{ "krc", "Karachay-Balkar" },
+	{ "krd", "Kairui-Midiki" },
+	{ "kre", "Panará" },
+	{ "krf", "Koro (Vanuatu)" },
+	{ "krh", "Kurama" },
+	{ "kri", "Krio" },
+	{ "krj", "Kinaray-A" },
+	{ "krk", "Kerek" },
+	{ "krl", "Karelian" },
+	{ "krm", "Krim" },
+	{ "krn", "Sapo" },
+	{ "krp", "Korop" },
+	{ "krr", "Kru'ng 2" },
+	{ "krs", "Gbaya (Sudan)" },
+	{ "krt", "Tumari Kanuri" },
+	{ "kru", "Kurukh" },
+	{ "krv", "Kavet" },
+	{ "krw", "Western Krahn" },
+	{ "krx", "Karon" },
+	{ "kry", "Kryts" },
+	{ "krz", "Sota Kanum" },
+	{ "ksa", "Shuwa-Zamani" },
+	{ "ksb", "Shambala" },
+	{ "ksc", "Southern Kalinga" },
+	{ "ksd", "Kuanua" },
+	{ "kse", "Kuni" },
+	{ "ksf", "Bafia" },
+	{ "ksg", "Kusaghe" },
+	{ "ksh", "Kölsch" },
+	{ "ksi", "Krisa" },
+	{ "ksj", "Uare" },
+	{ "ksk", "Kansa" },
+	{ "ksl", "Kumalu" },
+	{ "ksm", "Kumba" },
+	{ "ksn", "Kasiguranin" },
+	{ "kso", "Kofa" },
+	{ "ksp", "Kaba" },
+	{ "ksq", "Kwaami" },
+	{ "ksr", "Borong" },
+	{ "kss", "Southern Kisi" },
+	{ "kst", "Winyé" },
+	{ "ksu", "Khamyang" },
+	{ "ksv", "Kusu" },
+	{ "ksw", "S'gaw Karen" },
+	{ "ksx", "Kedang" },
+	{ "ksy", "Kharia Thar" },
+	{ "ksz", "Kodaku" },
+	{ "kta", "Katua" },
+	{ "ktb", "Kambaata" },
+	{ "ktc", "Kholok" },
+	{ "ktd", "Kokata" },
+	{ "kte", "Nubri" },
+	{ "ktf", "Kwami" },
+	{ "ktg", "Kalkutung" },
+	{ "kth", "Karanga" },
+	{ "kti", "North Muyu" },
+	{ "ktj", "Plapo Krumen" },
+	{ "ktk", "Kaniet" },
+	{ "ktl", "Koroshi" },
+	{ "ktm", "Kurti" },
+	{ "ktn", "Karitiâna" },
+	{ "kto", "Kuot" },
+	{ "ktp", "Kaduo" },
+	{ "ktq", "Katabaga" },
+	{ "ktr", "Kota Marudu Tinagas" },
+	{ "kts", "South Muyu" },
+	{ "ktt", "Ketum" },
+	{ "ktu", "Kituba (Democratic Republic of Congo)" },
+	{ "ktv", "Eastern Katu" },
+	{ "ktw", "Kato" },
+	{ "ktx", "Kaxararí" },
+	{ "kty", "Kango (Bas-Uélé District)" },
+	{ "ktz", "Ju'hoan" },
+	{ "kua", "Kuanyama" },
+	{ "kub", "Kutep" },
+	{ "kuc", "Kwinsu" },
+	{ "kud", "'Auhelawa" },
+	{ "kue", "Kuman" },
+	{ "kuf", "Western Katu" },
+	{ "kug", "Kupa" },
+	{ "kuh", "Kushi" },
+	{ "kui", "Kuikúro-Kalapálo" },
+	{ "kuj", "Kuria" },
+	{ "kuk", "Kepo'" },
+	{ "kul", "Kulere" },
+	{ "kum", "Kumyk" },
+	{ "kun", "Kunama" },
+	{ "kuo", "Kumukio" },
+	{ "kup", "Kunimaipa" },
+	{ "kuq", "Karipuna" },
+	{ "kur", "Kurdish" },
+	{ "kus", "Kusaal" },
+	{ "kut", "Kutenai" },
+	{ "kuu", "Upper Kuskokwim" },
+	{ "kuv", "Kur" },
+	{ "kuw", "Kpagua" },
+	{ "kux", "Kukatja" },
+	{ "kuy", "Kuuku-Ya'u" },
+	{ "kuz", "Kunza" },
+	{ "kva", "Bagvalal" },
+	{ "kvb", "Kubu" },
+	{ "kvc", "Kove" },
+	{ "kvd", "Kui (Indonesia)" },
+	{ "kve", "Kalabakan" },
+	{ "kvf", "Kabalai" },
+	{ "kvg", "Kuni-Boazi" },
+	{ "kvh", "Komodo" },
+	{ "kvi", "Kwang" },
+	{ "kvj", "Psikye" },
+	{ "kvk", "Korean Sign Language" },
+	{ "kvl", "Kayaw" },
+	{ "kvm", "Kendem" },
+	{ "kvn", "Border Kuna" },
+	{ "kvo", "Dobel" },
+	{ "kvp", "Kompane" },
+	{ "kvq", "Geba Karen" },
+	{ "kvr", "Kerinci" },
+	{ "kvs", "Kunggara" },
+	{ "kvt", "Lahta Karen" },
+	{ "kvu", "Yinbaw Karen" },
+	{ "kvv", "Kola" },
+	{ "kvw", "Wersing" },
+	{ "kvx", "Parkari Koli" },
+	{ "kvy", "Yintale Karen" },
+	{ "kvz", "Tsakwambo" },
+	{ "kwa", "Dâw" },
+	{ "kwb", "Kwa" },
+	{ "kwc", "Likwala" },
+	{ "kwd", "Kwaio" },
+	{ "kwe", "Kwerba" },
+	{ "kwf", "Kwara'ae" },
+	{ "kwg", "Sara Kaba Deme" },
+	{ "kwh", "Kowiai" },
+	{ "kwi", "Awa-Cuaiquer" },
+	{ "kwj", "Kwanga" },
+	{ "kwk", "Kwakiutl" },
+	{ "kwl", "Kofyar" },
+	{ "kwm", "Kwambi" },
+	{ "kwn", "Kwangali" },
+	{ "kwo", "Kwomtari" },
+	{ "kwp", "Kodia" },
+	{ "kwq", "Kwak" },
+	{ "kwr", "Kwer" },
+	{ "kws", "Kwese" },
+	{ "kwt", "Kwesten" },
+	{ "kwu", "Kwakum" },
+	{ "kwv", "Sara Kaba Náà" },
+	{ "kww", "Kwinti" },
+	{ "kwx", "Khirwar" },
+	{ "kwy", "San Salvador Kongo" },
+	{ "kwz", "Kwadi" },
+	{ "kxa", "Kairiru" },
+	{ "kxb", "Krobu" },
+	{ "kxc", "Konso" },
+	{ "kxd", "Brunei" },
+	{ "kxe", "Kakihum" },
+	{ "kxf", "Manumanaw Karen" },
+	{ "kxh", "Karo (Ethiopia)" },
+	{ "kxi", "Keningau Murut" },
+	{ "kxj", "Kulfa" },
+	{ "kxk", "Zayein Karen" },
+	{ "kxl", "Nepali Kurux" },
+	{ "kxm", "Northern Khmer" },
+	{ "kxn", "Kanowit-Tanjong Melanau" },
+	{ "kxo", "Kanoé" },
+	{ "kxp", "Wadiyara Koli" },
+	{ "kxq", "Smärky Kanum" },
+	{ "kxr", "Koro (Papua New Guinea)" },
+	{ "kxs", "Kangjia" },
+	{ "kxt", "Koiwat" },
+	{ "kxu", "Kui (India)" },
+	{ "kxv", "Kuvi" },
+	{ "kxw", "Konai" },
+	{ "kxx", "Likuba" },
+	{ "kxy", "Kayong" },
+	{ "kxz", "Kerewo" },
+	{ "kya", "Kwaya" },
+	{ "kyb", "Butbut Kalinga" },
+	{ "kyc", "Kyaka" },
+	{ "kyd", "Karey" },
+	{ "kye", "Krache" },
+	{ "kyf", "Kouya" },
+	{ "kyg", "Keyagana" },
+	{ "kyh", "Karok" },
+	{ "kyi", "Kiput" },
+	{ "kyj", "Karao" },
+	{ "kyk", "Kamayo" },
+	{ "kyl", "Kalapuya" },
+	{ "kym", "Kpatili" },
+	{ "kyn", "Northern Binukidnon" },
+	{ "kyo", "Kelon" },
+	{ "kyp", "Kang" },
+	{ "kyq", "Kenga" },
+	{ "kyr", "Kuruáya" },
+	{ "kys", "Baram Kayan" },
+	{ "kyt", "Kayagar" },
+	{ "kyu", "Western Kayah" },
+	{ "kyv", "Kayort" },
+	{ "kyw", "Kudmali" },
+	{ "kyx", "Rapoisi" },
+	{ "kyy", "Kambaira" },
+	{ "kyz", "Kayabí" },
+	{ "kza", "Western Karaboro" },
+	{ "kzb", "Kaibobo" },
+	{ "kzc", "Bondoukou Kulango" },
+	{ "kzd", "Kadai" },
+	{ "kze", "Kosena" },
+	{ "kzf", "Da'a Kaili" },
+	{ "kzg", "Kikai" },
+	{ "kzi", "Kelabit" },
+	{ "kzj", "Coastal Kadazan" },
+	{ "kzk", "Kazukuru" },
+	{ "kzl", "Kayeli" },
+	{ "kzm", "Kais" },
+	{ "kzn", "Kokola" },
+	{ "kzo", "Kaningi" },
+	{ "kzp", "Kaidipang" },
+	{ "kzq", "Kaike" },
+	{ "kzr", "Karang" },
+	{ "kzs", "Sugut Dusun" },
+	{ "kzt", "Tambunan Dusun" },
+	{ "kzu", "Kayupulau" },
+	{ "kzv", "Komyandaret" },
+	{ "kzw", "Karirí-Xocó" },
+	{ "kzx", "Kamarian" },
+	{ "kzy", "Kango (Tshopo District)" },
+	{ "kzz", "Kalabra" },
+	{ "laa", "Southern Subanen" },
+	{ "lab", "Linear A" },
+	{ "lac", "Lacandon" },
+	{ "lad", "Ladino" },
+	{ "lae", "Pattani" },
+	{ "laf", "Lafofa" },
+	{ "lag", "Langi" },
+	{ "lah", "Lahnda" },
+	{ "lai", "Lambya" },
+	{ "laj", "Lango (Uganda)" },
+	{ "lak", "Laka (Nigeria)" },
+	{ "lal", "Lalia" },
+	{ "lam", "Lamba" },
+	{ "lan", "Laru" },
+	{ "lao", "Lao" },
+	{ "lap", "Laka (Chad)" },
+	{ "laq", "Qabiao" },
+	{ "lar", "Larteh" },
+	{ "las", "Lama (Togo)" },
+	{ "lat", "Latin" },
+	{ "lau", "Laba" },
+	{ "lav", "Latvian" },
+	{ "law", "Lauje" },
+	{ "lax", "Tiwa" },
+	{ "lay", "Lama (Myanmar)" },
+	{ "laz", "Aribwatsa" },
+	{ "lba", "Lui" },
+	{ "lbb", "Label" },
+	{ "lbc", "Lakkia" },
+	{ "lbe", "Lak" },
+	{ "lbf", "Tinani" },
+	{ "lbg", "Laopang" },
+	{ "lbi", "La'bi" },
+	{ "lbj", "Ladakhi" },
+	{ "lbk", "Central Bontok" },
+	{ "lbl", "Libon Bikol" },
+	{ "lbm", "Lodhi" },
+	{ "lbn", "Lamet" },
+	{ "lbo", "Laven" },
+	{ "lbq", "Wampar" },
+	{ "lbr", "Lohorung" },
+	{ "lbs", "Libyan Sign Language" },
+	{ "lbt", "Lachi" },
+	{ "lbu", "Labu" },
+	{ "lbv", "Lavatbura-Lamusong" },
+	{ "lbw", "Tolaki" },
+	{ "lbx", "Lawangan" },
+	{ "lby", "Lamu-Lamu" },
+	{ "lbz", "Lardil" },
+	{ "lcc", "Legenyem" },
+	{ "lcd", "Lola" },
+	{ "lce", "Loncong" },
+	{ "lcf", "Lubu" },
+	{ "lch", "Luchazi" },
+	{ "lcl", "Lisela" },
+	{ "lcm", "Tungag" },
+	{ "lcp", "Western Lawa" },
+	{ "lcq", "Luhu" },
+	{ "lcs", "Lisabata-Nuniali" },
+	{ "lda", "Kla-Dan" },
+	{ "ldb", "Dũya" },
+	{ "ldd", "Luri" },
+	{ "ldg", "Lenyima" },
+	{ "ldh", "Lamja-Dengsa-Tola" },
+	{ "ldi", "Laari" },
+	{ "ldj", "Lemoro" },
+	{ "ldk", "Leelau" },
+	{ "ldl", "Kaan" },
+	{ "ldm", "Landoma" },
+	{ "ldn", "Láadan" },
+	{ "ldo", "Loo" },
+	{ "ldp", "Tso" },
+	{ "ldq", "Lufu" },
+	{ "lea", "Lega-Shabunda" },
+	{ "leb", "Lala-Bisa" },
+	{ "lec", "Leco" },
+	{ "led", "Lendu" },
+	{ "lee", "Lyélé" },
+	{ "lef", "Lelemi" },
+	{ "leg", "Lengua" },
+	{ "leh", "Lenje" },
+	{ "lei", "Lemio" },
+	{ "lej", "Lengola" },
+	{ "lek", "Leipon" },
+	{ "lel", "Lele (Democratic Republic of Congo)" },
+	{ "lem", "Nomaande" },
+	{ "len", "Lenca" },
+	{ "leo", "Leti (Cameroon)" },
+	{ "lep", "Lepcha" },
+	{ "leq", "Lembena" },
+	{ "ler", "Lenkau" },
+	{ "les", "Lese" },
+	{ "let", "Lesing-Gelimi" },
+	{ "leu", "Kara (Papua New Guinea)" },
+	{ "lev", "Lamma" },
+	{ "lew", "Ledo Kaili" },
+	{ "lex", "Luang" },
+	{ "ley", "Lemolang" },
+	{ "lez", "Lezghian" },
+	{ "lfa", "Lefa" },
+	{ "lfn", "Lingua Franca Nova" },
+	{ "lga", "Lungga" },
+	{ "lgb", "Laghu" },
+	{ "lgg", "Lugbara" },
+	{ "lgh", "Laghuu" },
+	{ "lgi", "Lengilu" },
+	{ "lgk", "Lingarak" },
+	{ "lgl", "Wala" },
+	{ "lgm", "Lega-Mwenga" },
+	{ "lgn", "Opuuo" },
+	{ "lgq", "Logba" },
+	{ "lgr", "Lengo" },
+	{ "lgt", "Pahi" },
+	{ "lgu", "Longgu" },
+	{ "lgz", "Ligenza" },
+	{ "lha", "Laha (Viet Nam)" },
+	{ "lhh", "Laha (Indonesia)" },
+	{ "lhi", "Lahu Shi" },
+	{ "lhl", "Lahul Lohar" },
+	{ "lhm", "Lhomi" },
+	{ "lhn", "Lahanan" },
+	{ "lhp", "Lhokpu" },
+	{ "lhs", "Mlahsö" },
+	{ "lht", "Lo-Toga" },
+	{ "lhu", "Lahu" },
+	{ "lia", "West-Central Limba" },
+	{ "lib", "Likum" },
+	{ "lic", "Hlai" },
+	{ "lid", "Nyindrou" },
+	{ "lie", "Likila" },
+	{ "lif", "Limbu" },
+	{ "lig", "Ligbi" },
+	{ "lih", "Lihir" },
+	{ "lii", "Lingkhim" },
+	{ "lij", "Ligurian" },
+	{ "lik", "Lika" },
+	{ "lil", "Lillooet" },
+	{ "lim", "Limburgan" },
+	{ "lin", "Lingala" },
+	{ "lio", "Liki" },
+	{ "lip", "Sekpele" },
+	{ "liq", "Libido" },
+	{ "lir", "Liberian English" },
+	{ "lis", "Lisu" },
+	{ "lit", "Lithuanian" },
+	{ "liu", "Logorik" },
+	{ "liv", "Liv" },
+	{ "liw", "Col" },
+	{ "lix", "Liabuku" },
+	{ "liy", "Banda-Bambari" },
+	{ "liz", "Libinza" },
+	{ "lja", "Golpa" },
+	{ "lje", "Rampi" },
+	{ "lji", "Laiyolo" },
+	{ "ljl", "Li'o" },
+	{ "ljp", "Lampung Api" },
+	{ "ljw", "Yirandali" },
+	{ "ljx", "Yuru" },
+	{ "lka", "Lakalei" },
+	{ "lkb", "Kabras" },
+	{ "lkc", "Kucong" },
+	{ "lkd", "Lakondê" },
+	{ "lke", "Kenyi" },
+	{ "lkh", "Lakha" },
+	{ "lki", "Laki" },
+	{ "lkj", "Remun" },
+	{ "lkl", "Laeko-Libuat" },
+	{ "lkm", "Kalaamaya" },
+	{ "lkn", "Lakon" },
+	{ "lko", "Khayo" },
+	{ "lkr", "Päri" },
+	{ "lks", "Kisa" },
+	{ "lkt", "Lakota" },
+	{ "lku", "Kungkari" },
+	{ "lky", "Lokoya" },
+	{ "lla", "Lala-Roba" },
+	{ "llb", "Lolo" },
+	{ "llc", "Lele (Guinea)" },
+	{ "lld", "Ladin" },
+	{ "lle", "Lele (Papua New Guinea)" },
+	{ "llf", "Hermit" },
+	{ "llg", "Lole" },
+	{ "llh", "Lamu" },
+	{ "lli", "Teke-Laali" },
+	{ "llj", "Ladji Ladji" },
+	{ "llk", "Lelak" },
+	{ "lll", "Lilau" },
+	{ "llm", "Lasalimu" },
+	{ "lln", "Lele (Chad)" },
+	{ "llo", "Khlor" },
+	{ "llp", "North Efate" },
+	{ "llq", "Lolak" },
+	{ "lls", "Lithuanian Sign Language" },
+	{ "llu", "Lau" },
+	{ "llx", "Lauan" },
+	{ "lma", "East Limba" },
+	{ "lmb", "Merei" },
+	{ "lmc", "Limilngan" },
+	{ "lmd", "Lumun" },
+	{ "lme", "Pévé" },
+	{ "lmf", "South Lembata" },
+	{ "lmg", "Lamogai" },
+	{ "lmh", "Lambichhong" },
+	{ "lmi", "Lombi" },
+	{ "lmj", "West Lembata" },
+	{ "lmk", "Lamkang" },
+	{ "lml", "Hano" },
+	{ "lmm", "Lamam" },
+	{ "lmn", "Lambadi" },
+	{ "lmo", "Lombard" },
+	{ "lmp", "Limbum" },
+	{ "lmq", "Lamatuka" },
+	{ "lmr", "Lamalera" },
+	{ "lmu", "Lamenu" },
+	{ "lmv", "Lomaiviti" },
+	{ "lmw", "Lake Miwok" },
+	{ "lmx", "Laimbue" },
+	{ "lmy", "Lamboya" },
+	{ "lmz", "Lumbee" },
+	{ "lna", "Langbashe" },
+	{ "lnb", "Mbalanhu" },
+	{ "lnd", "Lundayeh" },
+	{ "lng", "Langobardic" },
+	{ "lnh", "Lanoh" },
+	{ "lni", "Daantanai'" },
+	{ "lnj", "Leningitij" },
+	{ "lnl", "South Central Banda" },
+	{ "lnm", "Langam" },
+	{ "lnn", "Lorediakarkar" },
+	{ "lno", "Lango (Sudan)" },
+	{ "lns", "Lamnso'" },
+	{ "lnu", "Longuda" },
+	{ "lnw", "Lanima" },
+	{ "lnz", "Lonzo" },
+	{ "loa", "Loloda" },
+	{ "lob", "Lobi" },
+	{ "loc", "Inonhan" },
+	{ "loe", "Saluan" },
+	{ "lof", "Logol" },
+	{ "log", "Logo" },
+	{ "loh", "Narim" },
+	{ "loi", "Loma (Côte d'Ivoire)" },
+	{ "loj", "Lou" },
+	{ "lok", "Loko" },
+	{ "lol", "Mongo" },
+	{ "lom", "Loma (Liberia)" },
+	{ "lon", "Malawi Lomwe" },
+	{ "loo", "Lombo" },
+	{ "lop", "Lopa" },
+	{ "loq", "Lobala" },
+	{ "lor", "Téén" },
+	{ "los", "Loniu" },
+	{ "lot", "Otuho" },
+	{ "lou", "Louisiana Creole French" },
+	{ "lov", "Lopi" },
+	{ "low", "Tampias Lobu" },
+	{ "lox", "Loun" },
+	{ "loy", "Loke" },
+	{ "loz", "Lozi" },
+	{ "lpa", "Lelepa" },
+	{ "lpe", "Lepki" },
+	{ "lpn", "Long Phuri Naga" },
+	{ "lpo", "Lipo" },
+	{ "lpx", "Lopit" },
+	{ "lra", "Rara Bakati'" },
+	{ "lrc", "Northern Luri" },
+	{ "lre", "Laurentian" },
+	{ "lrg", "Laragia" },
+	{ "lri", "Marachi" },
+	{ "lrk", "Loarki" },
+	{ "lrl", "Lari" },
+	{ "lrm", "Marama" },
+	{ "lrn", "Lorang" },
+	{ "lro", "Laro" },
+	{ "lrr", "Southern Yamphu" },
+	{ "lrt", "Larantuka Malay" },
+	{ "lrv", "Larevat" },
+	{ "lrz", "Lemerig" },
+	{ "lsa", "Lasgerdi" },
+	{ "lsd", "Lishana Deni" },
+	{ "lse", "Lusengo" },
+	{ "lsg", "Lyons Sign Language" },
+	{ "lsh", "Lish" },
+	{ "lsi", "Lashi" },
+	{ "lsl", "Latvian Sign Language" },
+	{ "lsm", "Saamia" },
+	{ "lso", "Laos Sign Language" },
+	{ "lsp", "Panamanian Sign Language" },
+	{ "lsr", "Aruop" },
+	{ "lss", "Lasi" },
+	{ "lst", "Trinidad and Tobago Sign Language" },
+	{ "lsy", "Mauritian Sign Language" },
+	{ "ltc", "Late Middle Chinese" },
+	{ "ltg", "Latgalian" },
+	{ "lti", "Leti (Indonesia)" },
+	{ "ltn", "Latundê" },
+	{ "lto", "Tsotso" },
+	{ "lts", "Tachoni" },
+	{ "ltu", "Latu" },
+	{ "ltz", "Luxembourgish" },
+	{ "lua", "Luba-Lulua" },
+	{ "lub", "Luba-Katanga" },
+	{ "luc", "Aringa" },
+	{ "lud", "Ludian" },
+	{ "lue", "Luvale" },
+	{ "luf", "Laua" },
+	{ "lug", "Ganda" },
+	{ "lui", "Luiseno" },
+	{ "luj", "Luna" },
+	{ "luk", "Lunanakha" },
+	{ "lul", "Olu'bo" },
+	{ "lum", "Luimbi" },
+	{ "lun", "Lunda" },
+	{ "luo", "Luo (Kenya and Tanzania)" },
+	{ "lup", "Lumbu" },
+	{ "luq", "Lucumi" },
+	{ "lur", "Laura" },
+	{ "lus", "Lushai" },
+	{ "lut", "Lushootseed" },
+	{ "luu", "Lumba-Yakkha" },
+	{ "luv", "Luwati" },
+	{ "luw", "Luo (Cameroon)" },
+	{ "luy", "Luyia" },
+	{ "luz", "Southern Luri" },
+	{ "lva", "Maku'a" },
+	{ "lvk", "Lavukaleve" },
+	{ "lvs", "Standard Latvian" },
+	{ "lvu", "Levuka" },
+	{ "lwa", "Lwalu" },
+	{ "lwe", "Lewo Eleng" },
+	{ "lwg", "Wanga" },
+	{ "lwh", "White Lachi" },
+	{ "lwl", "Eastern Lawa" },
+	{ "lwm", "Laomian" },
+	{ "lwo", "Luwo" },
+	{ "lwt", "Lewotobi" },
+	{ "lwu", "Lawu" },
+	{ "lww", "Lewo" },
+	{ "lya", "Layakha" },
+	{ "lyg", "Lyngngam" },
+	{ "lyn", "Luyana" },
+	{ "lzh", "Literary Chinese" },
+	{ "lzl", "Litzlitz" },
+	{ "lzn", "Leinong Naga" },
+	{ "lzz", "Laz" },
+	{ "maa", "San Jerónimo Tecóatl Mazatec" },
+	{ "mab", "Yutanduchi Mixtec" },
+	{ "mad", "Madurese" },
+	{ "mae", "Bo-Rukul" },
+	{ "maf", "Mafa" },
+	{ "mag", "Magahi" },
+	{ "mah", "Marshallese" },
+	{ "mai", "Maithili" },
+	{ "maj", "Jalapa De Díaz Mazatec" },
+	{ "mak", "Makasar" },
+	{ "mal", "Malayalam" },
+	{ "mam", "Mam" },
+	{ "man", "Mandingo" },
+	{ "maq", "Chiquihuitlán Mazatec" },
+	{ "mar", "Marathi" },
+	{ "mas", "Masai" },
+	{ "mat", "San Francisco Matlatzinca" },
+	{ "mau", "Huautla Mazatec" },
+	{ "mav", "Sateré-Mawé" },
+	{ "maw", "Mampruli" },
+	{ "max", "North Moluccan Malay" },
+	{ "maz", "Central Mazahua" },
+	{ "mba", "Higaonon" },
+	{ "mbb", "Western Bukidnon Manobo" },
+	{ "mbc", "Macushi" },
+	{ "mbd", "Dibabawon Manobo" },
+	{ "mbe", "Molale" },
+	{ "mbf", "Baba Malay" },
+	{ "mbh", "Mangseng" },
+	{ "mbi", "Ilianen Manobo" },
+	{ "mbj", "Nadëb" },
+	{ "mbk", "Malol" },
+	{ "mbl", "Maxakalí" },
+	{ "mbm", "Ombamba" },
+	{ "mbn", "Macaguán" },
+	{ "mbo", "Mbo (Cameroon)" },
+	{ "mbp", "Malayo" },
+	{ "mbq", "Maisin" },
+	{ "mbr", "Nukak Makú" },
+	{ "mbs", "Sarangani Manobo" },
+	{ "mbt", "Matigsalug Manobo" },
+	{ "mbu", "Mbula-Bwazza" },
+	{ "mbv", "Mbulungish" },
+	{ "mbw", "Maring" },
+	{ "mbx", "Mari (East Sepik Province)" },
+	{ "mby", "Memoni" },
+	{ "mbz", "Amoltepec Mixtec" },
+	{ "mca", "Maca" },
+	{ "mcb", "Machiguenga" },
+	{ "mcc", "Bitur" },
+	{ "mcd", "Sharanahua" },
+	{ "mce", "Itundujia Mixtec" },
+	{ "mcf", "Matsés" },
+	{ "mcg", "Mapoyo" },
+	{ "mch", "Maquiritari" },
+	{ "mci", "Mese" },
+	{ "mcj", "Mvanip" },
+	{ "mck", "Mbunda" },
+	{ "mcl", "Macaguaje" },
+	{ "mcm", "Malaccan Creole Portuguese" },
+	{ "mcn", "Masana" },
+	{ "mco", "Coatlán Mixe" },
+	{ "mcp", "Makaa" },
+	{ "mcq", "Ese" },
+	{ "mcr", "Menya" },
+	{ "mcs", "Mambai" },
+	{ "mct", "Mengisa" },
+	{ "mcu", "Cameroon Mambila" },
+	{ "mcv", "Minanibai" },
+	{ "mcw", "Mawa (Chad)" },
+	{ "mcx", "Mpiemo" },
+	{ "mcy", "South Watut" },
+	{ "mcz", "Mawan" },
+	{ "mda", "Mada (Nigeria)" },
+	{ "mdb", "Morigi" },
+	{ "mdc", "Male (Papua New Guinea)" },
+	{ "mdd", "Mbum" },
+	{ "mde", "Maba (Chad)" },
+	{ "mdf", "Moksha" },
+	{ "mdg", "Massalat" },
+	{ "mdh", "Maguindanaon" },
+	{ "mdi", "Mamvu" },
+	{ "mdj", "Mangbetu" },
+	{ "mdk", "Mangbutu" },
+	{ "mdl", "Maltese Sign Language" },
+	{ "mdm", "Mayogo" },
+	{ "mdn", "Mbati" },
+	{ "mdp", "Mbala" },
+	{ "mdq", "Mbole" },
+	{ "mdr", "Mandar" },
+	{ "mds", "Maria (Papua New Guinea)" },
+	{ "mdt", "Mbere" },
+	{ "mdu", "Mboko" },
+	{ "mdv", "Santa Lucía Monteverde Mixtec" },
+	{ "mdw", "Mbosi" },
+	{ "mdx", "Dizin" },
+	{ "mdy", "Male (Ethiopia)" },
+	{ "mdz", "Suruí Do Pará" },
+	{ "mea", "Menka" },
+	{ "meb", "Ikobi" },
+	{ "mec", "Mara" },
+	{ "med", "Melpa" },
+	{ "mee", "Mengen" },
+	{ "mef", "Megam" },
+	{ "meh", "Southwestern Tlaxiaco Mixtec" },
+	{ "mei", "Midob" },
+	{ "mej", "Meyah" },
+	{ "mek", "Mekeo" },
+	{ "mel", "Central Melanau" },
+	{ "mem", "Mangala" },
+	{ "men", "Mende (Sierra Leone)" },
+	{ "meo", "Kedah Malay" },
+	{ "mep", "Miriwung" },
+	{ "meq", "Merey" },
+	{ "mer", "Meru" },
+	{ "mes", "Masmaje" },
+	{ "met", "Mato" },
+	{ "meu", "Motu" },
+	{ "mev", "Mano" },
+	{ "mew", "Maaka" },
+	{ "mey", "Hassaniyya" },
+	{ "mez", "Menominee" },
+	{ "mfa", "Pattani Malay" },
+	{ "mfb", "Bangka" },
+	{ "mfc", "Mba" },
+	{ "mfd", "Mendankwe-Nkwen" },
+	{ "mfe", "Morisyen" },
+	{ "mff", "Naki" },
+	{ "mfg", "Mogofin" },
+	{ "mfh", "Matal" },
+	{ "mfi", "Wandala" },
+	{ "mfj", "Mefele" },
+	{ "mfk", "North Mofu" },
+	{ "mfl", "Putai" },
+	{ "mfm", "Marghi South" },
+	{ "mfn", "Cross River Mbembe" },
+	{ "mfo", "Mbe" },
+	{ "mfp", "Makassar Malay" },
+	{ "mfq", "Moba" },
+	{ "mfr", "Marithiel" },
+	{ "mfs", "Mexican Sign Language" },
+	{ "mft", "Mokerang" },
+	{ "mfu", "Mbwela" },
+	{ "mfv", "Mandjak" },
+	{ "mfw", "Mulaha" },
+	{ "mfx", "Melo" },
+	{ "mfy", "Mayo" },
+	{ "mfz", "Mabaan" },
+	{ "mga", "Middle Irish (900-1200)" },
+	{ "mgb", "Mararit" },
+	{ "mgc", "Morokodo" },
+	{ "mgd", "Moru" },
+	{ "mge", "Mango" },
+	{ "mgf", "Maklew" },
+	{ "mgg", "Mpumpong" },
+	{ "mgh", "Makhuwa-Meetto" },
+	{ "mgi", "Lijili" },
+	{ "mgj", "Abureni" },
+	{ "mgk", "Mawes" },
+	{ "mgl", "Maleu-Kilenge" },
+	{ "mgm", "Mambae" },
+	{ "mgn", "Mbangi" },
+	{ "mgo", "Meta'" },
+	{ "mgp", "Eastern Magar" },
+	{ "mgq", "Malila" },
+	{ "mgr", "Mambwe-Lungu" },
+	{ "mgs", "Manda (Tanzania)" },
+	{ "mgt", "Mongol" },
+	{ "mgu", "Mailu" },
+	{ "mgv", "Matengo" },
+	{ "mgw", "Matumbi" },
+	{ "mgy", "Mbunga" },
+	{ "mgz", "Mbugwe" },
+	{ "mha", "Manda (India)" },
+	{ "mhb", "Mahongwe" },
+	{ "mhc", "Mocho" },
+	{ "mhd", "Mbugu" },
+	{ "mhe", "Besisi" },
+	{ "mhf", "Mamaa" },
+	{ "mhg", "Margu" },
+	{ "mhh", "Maskoy Pidgin" },
+	{ "mhi", "Ma'di" },
+	{ "mhj", "Mogholi" },
+	{ "mhk", "Mungaka" },
+	{ "mhl", "Mauwake" },
+	{ "mhm", "Makhuwa-Moniga" },
+	{ "mhn", "Mócheno" },
+	{ "mho", "Mashi (Zambia)" },
+	{ "mhp", "Balinese Malay" },
+	{ "mhq", "Mandan" },
+	{ "mhr", "Eastern Mari" },
+	{ "mhs", "Buru (Indonesia)" },
+	{ "mht", "Mandahuaca" },
+	{ "mhu", "Digaro-Mishmi" },
+	{ "mhw", "Mbukushu" },
+	{ "mhx", "Maru" },
+	{ "mhy", "Ma'anyan" },
+	{ "mhz", "Mor (Mor Islands)" },
+	{ "mia", "Miami" },
+	{ "mib", "Atatláhuca Mixtec" },
+	{ "mic", "Mi'kmaq" },
+	{ "mid", "Mandaic" },
+	{ "mie", "Ocotepec Mixtec" },
+	{ "mif", "Mofu-Gudur" },
+	{ "mig", "San Miguel El Grande Mixtec" },
+	{ "mih", "Chayuco Mixtec" },
+	{ "mii", "Chigmecatitlán Mixtec" },
+	{ "mij", "Abar" },
+	{ "mik", "Mikasuki" },
+	{ "mil", "Peñoles Mixtec" },
+	{ "mim", "Alacatlatzala Mixtec" },
+	{ "min", "Minangkabau" },
+	{ "mio", "Pinotepa Nacional Mixtec" },
+	{ "mip", "Apasco-Apoala Mixtec" },
+	{ "miq", "Mískito" },
+	{ "mir", "Isthmus Mixe" },
+	{ "mis", "Uncoded languages" },
+	{ "mit", "Southern Puebla Mixtec" },
+	{ "miu", "Cacaloxtepec Mixtec" },
+	{ "miw", "Akoye" },
+	{ "mix", "Mixtepec Mixtec" },
+	{ "miy", "Ayutla Mixtec" },
+	{ "miz", "Coatzospan Mixtec" },
+	{ "mjc", "San Juan Colorado Mixtec" },
+	{ "mjd", "Northwest Maidu" },
+	{ "mje", "Muskum" },
+	{ "mjg", "Tu" },
+	{ "mjh", "Mwera (Nyasa)" },
+	{ "mji", "Kim Mun" },
+	{ "mjj", "Mawak" },
+	{ "mjk", "Matukar" },
+	{ "mjl", "Mandeali" },
+	{ "mjm", "Medebur" },
+	{ "mjn", "Ma (Papua New Guinea)" },
+	{ "mjo", "Malankuravan" },
+	{ "mjp", "Malapandaram" },
+	{ "mjq", "Malaryan" },
+	{ "mjr", "Malavedan" },
+	{ "mjs", "Miship" },
+	{ "mjt", "Sauria Paharia" },
+	{ "mju", "Manna-Dora" },
+	{ "mjv", "Mannan" },
+	{ "mjw", "Karbi" },
+	{ "mjx", "Mahali" },
+	{ "mjy", "Mahican" },
+	{ "mjz", "Majhi" },
+	{ "mka", "Mbre" },
+	{ "mkb", "Mal Paharia" },
+	{ "mkc", "Siliput" },
+	{ "mkd", "Macedonian" },
+	{ "mke", "Mawchi" },
+	{ "mkf", "Miya" },
+	{ "mkg", "Mak (China)" },
+	{ "mki", "Dhatki" },
+	{ "mkj", "Mokilese" },
+	{ "mkk", "Byep" },
+	{ "mkl", "Mokole" },
+	{ "mkm", "Moklen" },
+	{ "mkn", "Kupang Malay" },
+	{ "mko", "Mingang Doso" },
+	{ "mkp", "Moikodi" },
+	{ "mkq", "Bay Miwok" },
+	{ "mkr", "Malas" },
+	{ "mks", "Silacayoapan Mixtec" },
+	{ "mkt", "Vamale" },
+	{ "mku", "Konyanka Maninka" },
+	{ "mkv", "Mafea" },
+	{ "mkw", "Kituba (Congo)" },
+	{ "mkx", "Kinamiging Manobo" },
+	{ "mky", "East Makian" },
+	{ "mkz", "Makasae" },
+	{ "mla", "Malo" },
+	{ "mlb", "Mbule" },
+	{ "mlc", "Cao Lan" },
+	{ "mle", "Manambu" },
+	{ "mlf", "Mal" },
+	{ "mlg", "Malagasy" },
+	{ "mlh", "Mape" },
+	{ "mli", "Malimpung" },
+	{ "mlj", "Miltu" },
+	{ "mlk", "Ilwana" },
+	{ "mll", "Malua Bay" },
+	{ "mlm", "Mulam" },
+	{ "mln", "Malango" },
+	{ "mlo", "Mlomp" },
+	{ "mlp", "Bargam" },
+	{ "mlq", "Western Maninkakan" },
+	{ "mlr", "Vame" },
+	{ "mls", "Masalit" },
+	{ "mlt", "Maltese" },
+	{ "mlu", "To'abaita" },
+	{ "mlv", "Motlav" },
+	{ "mlw", "Moloko" },
+	{ "mlx", "Malfaxal" },
+	{ "mlz", "Malaynon" },
+	{ "mma", "Mama" },
+	{ "mmb", "Momina" },
+	{ "mmc", "Michoacán Mazahua" },
+	{ "mmd", "Maonan" },
+	{ "mme", "Mae" },
+	{ "mmf", "Mundat" },
+	{ "mmg", "North Ambrym" },
+	{ "mmh", "Mehináku" },
+	{ "mmi", "Musar" },
+	{ "mmj", "Majhwar" },
+	{ "mmk", "Mukha-Dora" },
+	{ "mml", "Man Met" },
+	{ "mmm", "Maii" },
+	{ "mmn", "Mamanwa" },
+	{ "mmo", "Mangga Buang" },
+	{ "mmp", "Siawi" },
+	{ "mmq", "Musak" },
+	{ "mmr", "Western Xiangxi Miao" },
+	{ "mmt", "Malalamai" },
+	{ "mmu", "Mmaala" },
+	{ "mmv", "Miriti" },
+	{ "mmw", "Emae" },
+	{ "mmx", "Madak" },
+	{ "mmy", "Migaama" },
+	{ "mmz", "Mabaale" },
+	{ "mna", "Mbula" },
+	{ "mnb", "Muna" },
+	{ "mnc", "Manchu" },
+	{ "mnd", "Mondé" },
+	{ "mne", "Naba" },
+	{ "mnf", "Mundani" },
+	{ "mng", "Eastern Mnong" },
+	{ "mnh", "Mono (Democratic Republic of Congo)" },
+	{ "mni", "Manipuri" },
+	{ "mnj", "Munji" },
+	{ "mnk", "Mandinka" },
+	{ "mnl", "Tiale" },
+	{ "mnm", "Mapena" },
+	{ "mnn", "Southern Mnong" },
+	{ "mnp", "Min Bei Chinese" },
+	{ "mnq", "Minriq" },
+	{ "mnr", "Mono (USA)" },
+	{ "mns", "Mansi" },
+	{ "mnu", "Mer" },
+	{ "mnv", "Rennell-Bellona" },
+	{ "mnw", "Mon" },
+	{ "mnx", "Manikion" },
+	{ "mny", "Manyawa" },
+	{ "mnz", "Moni" },
+	{ "moa", "Mwan" },
+	{ "moc", "Mocoví" },
+	{ "mod", "Mobilian" },
+	{ "moe", "Montagnais" },
+	{ "mog", "Mongondow" },
+	{ "moh", "Mohawk" },
+	{ "moi", "Mboi" },
+	{ "moj", "Monzombo" },
+	{ "mok", "Morori" },
+	{ "mom", "Mangue" },
+	{ "mon", "Mongolian" },
+	{ "moo", "Monom" },
+	{ "mop", "Mopán Maya" },
+	{ "moq", "Mor (Bomberai Peninsula)" },
+	{ "mor", "Moro" },
+	{ "mos", "Mossi" },
+	{ "mot", "Barí" },
+	{ "mou", "Mogum" },
+	{ "mov", "Mohave" },
+	{ "mow", "Moi (Congo)" },
+	{ "mox", "Molima" },
+	{ "moy", "Shekkacho" },
+	{ "moz", "Mukulu" },
+	{ "mpa", "Mpoto" },
+	{ "mpb", "Mullukmulluk" },
+	{ "mpc", "Mangarayi" },
+	{ "mpd", "Machinere" },
+	{ "mpe", "Majang" },
+	{ "mpg", "Marba" },
+	{ "mph", "Maung" },
+	{ "mpi", "Mpade" },
+	{ "mpj", "Martu Wangka" },
+	{ "mpk", "Mbara (Chad)" },
+	{ "mpl", "Middle Watut" },
+	{ "mpm", "Yosondúa Mixtec" },
+	{ "mpn", "Mindiri" },
+	{ "mpo", "Miu" },
+	{ "mpp", "Migabac" },
+	{ "mpq", "Matís" },
+	{ "mpr", "Vangunu" },
+	{ "mps", "Dadibi" },
+	{ "mpt", "Mian" },
+	{ "mpu", "Makuráp" },
+	{ "mpv", "Mungkip" },
+	{ "mpw", "Mapidian" },
+	{ "mpx", "Misima-Panaeati" },
+	{ "mpy", "Mapia" },
+	{ "mpz", "Mpi" },
+	{ "mqa", "Maba (Indonesia)" },
+	{ "mqb", "Mbuko" },
+	{ "mqc", "Mangole" },
+	{ "mqe", "Matepi" },
+	{ "mqf", "Momuna" },
+	{ "mqg", "Kota Bangun Kutai Malay" },
+	{ "mqh", "Tlazoyaltepec Mixtec" },
+	{ "mqi", "Mariri" },
+	{ "mqj", "Mamasa" },
+	{ "mqk", "Rajah Kabunsuwan Manobo" },
+	{ "mql", "Mbelime" },
+	{ "mqm", "South Marquesan" },
+	{ "mqn", "Moronene" },
+	{ "mqo", "Modole" },
+	{ "mqp", "Manipa" },
+	{ "mqq", "Minokok" },
+	{ "mqr", "Mander" },
+	{ "mqs", "West Makian" },
+	{ "mqt", "Mok" },
+	{ "mqu", "Mandari" },
+	{ "mqv", "Mosimo" },
+	{ "mqw", "Murupi" },
+	{ "mqx", "Mamuju" },
+	{ "mqy", "Manggarai" },
+	{ "mqz", "Pano" },
+	{ "mra", "Mlabri" },
+	{ "mrb", "Marino" },
+	{ "mrc", "Maricopa" },
+	{ "mrd", "Western Magar" },
+	{ "mre", "Martha's Vineyard Sign Language" },
+	{ "mrf", "Elseng" },
+	{ "mrg", "Mising" },
+	{ "mrh", "Mara Chin" },
+	{ "mri", "Maori" },
+	{ "mrj", "Western Mari" },
+	{ "mrk", "Hmwaveke" },
+	{ "mrl", "Mortlockese" },
+	{ "mrm", "Merlav" },
+	{ "mrn", "Cheke Holo" },
+	{ "mro", "Mru" },
+	{ "mrp", "Morouas" },
+	{ "mrq", "North Marquesan" },
+	{ "mrr", "Maria (India)" },
+	{ "mrs", "Maragus" },
+	{ "mrt", "Marghi Central" },
+	{ "mru", "Mono (Cameroon)" },
+	{ "mrv", "Mangareva" },
+	{ "mrw", "Maranao" },
+	{ "mrx", "Maremgi" },
+	{ "mry", "Mandaya" },
+	{ "mrz", "Marind" },
+	{ "msa", "Malay (macrolanguage)" },
+	{ "msb", "Masbatenyo" },
+	{ "msc", "Sankaran Maninka" },
+	{ "msd", "Yucatec Maya Sign Language" },
+	{ "mse", "Musey" },
+	{ "msf", "Mekwei" },
+	{ "msg", "Moraid" },
+	{ "msh", "Masikoro Malagasy" },
+	{ "msi", "Sabah Malay" },
+	{ "msj", "Ma (Democratic Republic of Congo)" },
+	{ "msk", "Mansaka" },
+	{ "msl", "Molof" },
+	{ "msm", "Agusan Manobo" },
+	{ "msn", "Vurës" },
+	{ "mso", "Mombum" },
+	{ "msp", "Maritsauá" },
+	{ "msq", "Caac" },
+	{ "msr", "Mongolian Sign Language" },
+	{ "mss", "West Masela" },
+	{ "msu", "Musom" },
+	{ "msv", "Maslam" },
+	{ "msw", "Mansoanka" },
+	{ "msx", "Moresada" },
+	{ "msy", "Aruamu" },
+	{ "msz", "Momare" },
+	{ "mta", "Cotabato Manobo" },
+	{ "mtb", "Anyin Morofo" },
+	{ "mtc", "Munit" },
+	{ "mtd", "Mualang" },
+	{ "mte", "Mono (Solomon Islands)" },
+	{ "mtf", "Murik (Papua New Guinea)" },
+	{ "mtg", "Una" },
+	{ "mth", "Munggui" },
+	{ "mti", "Maiwa (Papua New Guinea)" },
+	{ "mtj", "Moskona" },
+	{ "mtk", "Mbe'" },
+	{ "mtl", "Montol" },
+	{ "mtm", "Mator" },
+	{ "mtn", "Matagalpa" },
+	{ "mto", "Totontepec Mixe" },
+	{ "mtp", "Wichí Lhamtés Nocten" },
+	{ "mtq", "Muong" },
+	{ "mtr", "Mewari" },
+	{ "mts", "Yora" },
+	{ "mtt", "Mota" },
+	{ "mtu", "Tututepec Mixtec" },
+	{ "mtv", "Asaro'o" },
+	{ "mtw", "Southern Binukidnon" },
+	{ "mtx", "Tidaá Mixtec" },
+	{ "mty", "Nabi" },
+	{ "mua", "Mundang" },
+	{ "mub", "Mubi" },
+	{ "muc", "Ajumbu" },
+	{ "mud", "Mednyj Aleut" },
+	{ "mue", "Media Lengua" },
+	{ "mug", "Musgu" },
+	{ "muh", "Mündü" },
+	{ "mui", "Musi" },
+	{ "muj", "Mabire" },
+	{ "muk", "Mugom" },
+	{ "mul", "Multiple languages" },
+	{ "mum", "Maiwala" },
+	{ "muo", "Nyong" },
+	{ "mup", "Malvi" },
+	{ "muq", "Eastern Xiangxi Miao" },
+	{ "mur", "Murle" },
+	{ "mus", "Creek" },
+	{ "mut", "Western Muria" },
+	{ "muu", "Yaaku" },
+	{ "muv", "Muthuvan" },
+	{ "mux", "Bo-Ung" },
+	{ "muy", "Muyang" },
+	{ "muz", "Mursi" },
+	{ "mva", "Manam" },
+	{ "mvb", "Mattole" },
+	{ "mvd", "Mamboru" },
+	{ "mve", "Marwari (Pakistan)" },
+	{ "mvf", "Peripheral Mongolian" },
+	{ "mvg", "Yucuañe Mixtec" },
+	{ "mvh", "Mulgi" },
+	{ "mvi", "Miyako" },
+	{ "mvk", "Mekmek" },
+	{ "mvl", "Mbara (Australia)" },
+	{ "mvm", "Muya" },
+	{ "mvn", "Minaveha" },
+	{ "mvo", "Marovo" },
+	{ "mvp", "Duri" },
+	{ "mvq", "Moere" },
+	{ "mvr", "Marau" },
+	{ "mvs", "Massep" },
+	{ "mvt", "Mpotovoro" },
+	{ "mvu", "Marfa" },
+	{ "mvv", "Tagal Murut" },
+	{ "mvw", "Machinga" },
+	{ "mvx", "Meoswar" },
+	{ "mvy", "Indus Kohistani" },
+	{ "mvz", "Mesqan" },
+	{ "mwa", "Mwatebu" },
+	{ "mwb", "Juwal" },
+	{ "mwc", "Are" },
+	{ "mwe", "Mwera (Chimwera)" },
+	{ "mwf", "Murrinh-Patha" },
+	{ "mwg", "Aiklep" },
+	{ "mwh", "Mouk-Aria" },
+	{ "mwi", "Labo" },
+	{ "mwj", "Maligo" },
+	{ "mwk", "Kita Maninkakan" },
+	{ "mwl", "Mirandese" },
+	{ "mwm", "Sar" },
+	{ "mwn", "Nyamwanga" },
+	{ "mwo", "Central Maewo" },
+	{ "mwp", "Kala Lagaw Ya" },
+	{ "mwq", "Mün Chin" },
+	{ "mwr", "Marwari" },
+	{ "mws", "Mwimbi-Muthambi" },
+	{ "mwt", "Moken" },
+	{ "mwu", "Mittu" },
+	{ "mwv", "Mentawai" },
+	{ "mww", "Hmong Daw" },
+	{ "mwx", "Mediak" },
+	{ "mwy", "Mosiro" },
+	{ "mwz", "Moingi" },
+	{ "mxa", "Northwest Oaxaca Mixtec" },
+	{ "mxb", "Tezoatlán Mixtec" },
+	{ "mxc", "Manyika" },
+	{ "mxd", "Modang" },
+	{ "mxe", "Mele-Fila" },
+	{ "mxf", "Malgbe" },
+	{ "mxg", "Mbangala" },
+	{ "mxh", "Mvuba" },
+	{ "mxi", "Mozarabic" },
+	{ "mxj", "Miju-Mishmi" },
+	{ "mxk", "Monumbo" },
+	{ "mxl", "Maxi Gbe" },
+	{ "mxm", "Meramera" },
+	{ "mxn", "Moi (Indonesia)" },
+	{ "mxo", "Mbowe" },
+	{ "mxp", "Tlahuitoltepec Mixe" },
+	{ "mxq", "Juquila Mixe" },
+	{ "mxr", "Murik (Malaysia)" },
+	{ "mxs", "Huitepec Mixtec" },
+	{ "mxt", "Jamiltepec Mixtec" },
+	{ "mxu", "Mada (Cameroon)" },
+	{ "mxv", "Metlatónoc Mixtec" },
+	{ "mxw", "Namo" },
+	{ "mxx", "Mahou" },
+	{ "mxy", "Southeastern Nochixtlán Mixtec" },
+	{ "mxz", "Central Masela" },
+	{ "mya", "Burmese" },
+	{ "myb", "Mbay" },
+	{ "myc", "Mayeka" },
+	{ "myd", "Maramba" },
+	{ "mye", "Myene" },
+	{ "myf", "Bambassi" },
+	{ "myg", "Manta" },
+	{ "myh", "Makah" },
+	{ "myi", "Mina (India)" },
+	{ "myj", "Mangayat" },
+	{ "myk", "Mamara Senoufo" },
+	{ "myl", "Moma" },
+	{ "mym", "Me'en" },
+	{ "myo", "Anfillo" },
+	{ "myp", "Pirahã" },
+	{ "myr", "Muniche" },
+	{ "mys", "Mesmes" },
+	{ "myu", "Mundurukú" },
+	{ "myv", "Erzya" },
+	{ "myw", "Muyuw" },
+	{ "myx", "Masaaba" },
+	{ "myy", "Macuna" },
+	{ "myz", "Classical Mandaic" },
+	{ "mza", "Santa María Zacatepec Mixtec" },
+	{ "mzb", "Tumzabt" },
+	{ "mzc", "Madagascar Sign Language" },
+	{ "mzd", "Malimba" },
+	{ "mze", "Morawa" },
+	{ "mzg", "Monastic Sign Language" },
+	{ "mzh", "Wichí Lhamtés Güisnay" },
+	{ "mzi", "Ixcatlán Mazatec" },
+	{ "mzj", "Manya" },
+	{ "mzk", "Nigeria Mambila" },
+	{ "mzl", "Mazatlán Mixe" },
+	{ "mzm", "Mumuye" },
+	{ "mzn", "Mazanderani" },
+	{ "mzo", "Matipuhy" },
+	{ "mzp", "Movima" },
+	{ "mzq", "Mori Atas" },
+	{ "mzr", "Marúbo" },
+	{ "mzs", "Macanese" },
+	{ "mzt", "Mintil" },
+	{ "mzu", "Inapang" },
+	{ "mzv", "Manza" },
+	{ "mzw", "Deg" },
+	{ "mzx", "Mawayana" },
+	{ "mzy", "Mozambican Sign Language" },
+	{ "mzz", "Maiadomu" },
+	{ "naa", "Namla" },
+	{ "nab", "Southern Nambikuára" },
+	{ "nac", "Narak" },
+	{ "nad", "Nijadali" },
+	{ "nae", "Naka'ela" },
+	{ "naf", "Nabak" },
+	{ "nag", "Naga Pidgin" },
+	{ "naj", "Nalu" },
+	{ "nak", "Nakanai" },
+	{ "nal", "Nalik" },
+	{ "nam", "Ngan'gityemerri" },
+	{ "nan", "Min Nan Chinese" },
+	{ "nao", "Naaba" },
+	{ "nap", "Neapolitan" },
+	{ "naq", "Nama (Namibia)" },
+	{ "nar", "Iguta" },
+	{ "nas", "Naasioi" },
+	{ "nat", "Hungworo" },
+	{ "nau", "Nauru" },
+	{ "nav", "Navajo" },
+	{ "naw", "Nawuri" },
+	{ "nax", "Nakwi" },
+	{ "nay", "Narrinyeri" },
+	{ "naz", "Coatepec Nahuatl" },
+	{ "nba", "Nyemba" },
+	{ "nbb", "Ndoe" },
+	{ "nbc", "Chang Naga" },
+	{ "nbd", "Ngbinda" },
+	{ "nbe", "Konyak Naga" },
+	{ "nbg", "Nagarchal" },
+	{ "nbh", "Ngamo" },
+	{ "nbi", "Mao Naga" },
+	{ "nbj", "Ngarinman" },
+	{ "nbk", "Nake" },
+	{ "nbl", "South Ndebele" },
+	{ "nbm", "Ngbaka Ma'bo" },
+	{ "nbn", "Kuri" },
+	{ "nbo", "Nkukoli" },
+	{ "nbp", "Nnam" },
+	{ "nbq", "Nggem" },
+	{ "nbr", "Numana-Nunku-Gbantu-Numbu" },
+	{ "nbs", "Namibian Sign Language" },
+	{ "nbt", "Na" },
+	{ "nbu", "Rongmei Naga" },
+	{ "nbv", "Ngamambo" },
+	{ "nbw", "Southern Ngbandi" },
+	{ "nby", "Ningera" },
+	{ "nca", "Iyo" },
+	{ "ncb", "Central Nicobarese" },
+	{ "ncc", "Ponam" },
+	{ "ncd", "Nachering" },
+	{ "nce", "Yale" },
+	{ "ncf", "Notsi" },
+	{ "ncg", "Nisga'a" },
+	{ "nch", "Central Huasteca Nahuatl" },
+	{ "nci", "Classical Nahuatl" },
+	{ "ncj", "Northern Puebla Nahuatl" },
+	{ "nck", "Nakara" },
+	{ "ncl", "Michoacán Nahuatl" },
+	{ "ncm", "Nambo" },
+	{ "ncn", "Nauna" },
+	{ "nco", "Sibe" },
+	{ "ncp", "Ndaktup" },
+	{ "ncr", "Ncane" },
+	{ "ncs", "Nicaraguan Sign Language" },
+	{ "nct", "Chothe Naga" },
+	{ "ncu", "Chumburung" },
+	{ "ncx", "Central Puebla Nahuatl" },
+	{ "ncz", "Natchez" },
+	{ "nda", "Ndasa" },
+	{ "ndb", "Kenswei Nsei" },
+	{ "ndc", "Ndau" },
+	{ "ndd", "Nde-Nsele-Nta" },
+	{ "nde", "North Ndebele" },
+	{ "ndf", "Nadruvian" },
+	{ "ndg", "Ndengereko" },
+	{ "ndh", "Ndali" },
+	{ "ndi", "Samba Leko" },
+	{ "ndj", "Ndamba" },
+	{ "ndk", "Ndaka" },
+	{ "ndl", "Ndolo" },
+	{ "ndm", "Ndam" },
+	{ "ndn", "Ngundi" },
+	{ "ndo", "Ndonga" },
+	{ "ndp", "Ndo" },
+	{ "ndq", "Ndombe" },
+	{ "ndr", "Ndoola" },
+	{ "nds", "Low German" },
+	{ "ndt", "Ndunga" },
+	{ "ndu", "Dugun" },
+	{ "ndv", "Ndut" },
+	{ "ndw", "Ndobo" },
+	{ "ndx", "Nduga" },
+	{ "ndy", "Lutos" },
+	{ "ndz", "Ndogo" },
+	{ "nea", "Eastern Ngad'a" },
+	{ "neb", "Toura (Côte d'Ivoire)" },
+	{ "nec", "Nedebang" },
+	{ "ned", "Nde-Gbite" },
+	{ "nee", "Nêlêmwa-Nixumwak" },
+	{ "nef", "Nefamese" },
+	{ "neg", "Negidal" },
+	{ "neh", "Nyenkha" },
+	{ "nei", "Neo-Hittite" },
+	{ "nej", "Neko" },
+	{ "nek", "Neku" },
+	{ "nem", "Nemi" },
+	{ "nen", "Nengone" },
+	{ "neo", "Ná-Meo" },
+	{ "nep", "Nepali (macrolanguage)" },
+	{ "neq", "North Central Mixe" },
+	{ "ner", "Yahadian" },
+	{ "nes", "Bhoti Kinnauri" },
+	{ "net", "Nete" },
+	{ "neu", "Neo" },
+	{ "nev", "Nyaheun" },
+	{ "new", "Newari" },
+	{ "nex", "Neme" },
+	{ "ney", "Neyo" },
+	{ "nez", "Nez Perce" },
+	{ "nfa", "Dhao" },
+	{ "nfd", "Ahwai" },
+	{ "nfl", "Ayiwo" },
+	{ "nfr", "Nafaanra" },
+	{ "nfu", "Mfumte" },
+	{ "nga", "Ngbaka" },
+	{ "ngb", "Northern Ngbandi" },
+	{ "ngc", "Ngombe (Democratic Republic of Congo)" },
+	{ "ngd", "Ngando (Central African Republic)" },
+	{ "nge", "Ngemba" },
+	{ "ngg", "Ngbaka Manza" },
+	{ "ngh", "Nu" },
+	{ "ngi", "Ngizim" },
+	{ "ngj", "Ngie" },
+	{ "ngk", "Dalabon" },
+	{ "ngl", "Lomwe" },
+	{ "ngm", "Ngatik Men's Creole" },
+	{ "ngn", "Ngwo" },
+	{ "ngo", "Ngoni" },
+	{ "ngp", "Ngulu" },
+	{ "ngq", "Ngurimi" },
+	{ "ngr", "Engdewu" },
+	{ "ngs", "Gvoko" },
+	{ "ngt", "Ngeq" },
+	{ "ngu", "Guerrero Nahuatl" },
+	{ "ngv", "Nagumi" },
+	{ "ngw", "Ngwaba" },
+	{ "ngx", "Nggwahyi" },
+	{ "ngy", "Tibea" },
+	{ "ngz", "Ngungwel" },
+	{ "nha", "Nhanda" },
+	{ "nhb", "Beng" },
+	{ "nhc", "Tabasco Nahuatl" },
+	{ "nhd", "Chiripá" },
+	{ "nhe", "Eastern Huasteca Nahuatl" },
+	{ "nhf", "Nhuwala" },
+	{ "nhg", "Tetelcingo Nahuatl" },
+	{ "nhh", "Nahari" },
+	{ "nhi", "Zacatlán-Ahuacatlán-Tepetzintla Nahuatl" },
+	{ "nhk", "Isthmus-Cosoleacaque Nahuatl" },
+	{ "nhm", "Morelos Nahuatl" },
+	{ "nhn", "Central Nahuatl" },
+	{ "nho", "Takuu" },
+	{ "nhp", "Isthmus-Pajapan Nahuatl" },
+	{ "nhq", "Huaxcaleca Nahuatl" },
+	{ "nhr", "Naro" },
+	{ "nht", "Ometepec Nahuatl" },
+	{ "nhu", "Noone" },
+	{ "nhv", "Temascaltepec Nahuatl" },
+	{ "nhw", "Western Huasteca Nahuatl" },
+	{ "nhx", "Isthmus-Mecayapan Nahuatl" },
+	{ "nhy", "Northern Oaxaca Nahuatl" },
+	{ "nhz", "Santa María La Alta Nahuatl" },
+	{ "nia", "Nias" },
+	{ "nib", "Nakame" },
+	{ "nid", "Ngandi" },
+	{ "nie", "Niellim" },
+	{ "nif", "Nek" },
+	{ "nig", "Ngalakan" },
+	{ "nih", "Nyiha (Tanzania)" },
+	{ "nii", "Nii" },
+	{ "nij", "Ngaju" },
+	{ "nik", "Southern Nicobarese" },
+	{ "nil", "Nila" },
+	{ "nim", "Nilamba" },
+	{ "nin", "Ninzo" },
+	{ "nio", "Nganasan" },
+	{ "niq", "Nandi" },
+	{ "nir", "Nimboran" },
+	{ "nis", "Nimi" },
+	{ "nit", "Southeastern Kolami" },
+	{ "niu", "Niuean" },
+	{ "niv", "Gilyak" },
+	{ "niw", "Nimo" },
+	{ "nix", "Hema" },
+	{ "niy", "Ngiti" },
+	{ "niz", "Ningil" },
+	{ "nja", "Nzanyi" },
+	{ "njb", "Nocte Naga" },
+	{ "njd", "Ndonde Hamba" },
+	{ "njh", "Lotha Naga" },
+	{ "nji", "Gudanji" },
+	{ "njj", "Njen" },
+	{ "njl", "Njalgulgule" },
+	{ "njm", "Angami Naga" },
+	{ "njn", "Liangmai Naga" },
+	{ "njo", "Ao Naga" },
+	{ "njr", "Njerep" },
+	{ "njs", "Nisa" },
+	{ "njt", "Ndyuka-Trio Pidgin" },
+	{ "nju", "Ngadjunmaya" },
+	{ "njx", "Kunyi" },
+	{ "njy", "Njyem" },
+	{ "njz", "Nyishi" },
+	{ "nka", "Nkoya" },
+	{ "nkb", "Khoibu Naga" },
+	{ "nkc", "Nkongho" },
+	{ "nkd", "Koireng" },
+	{ "nke", "Duke" },
+	{ "nkf", "Inpui Naga" },
+	{ "nkg", "Nekgini" },
+	{ "nkh", "Khezha Naga" },
+	{ "nki", "Thangal Naga" },
+	{ "nkj", "Nakai" },
+	{ "nkk", "Nokuku" },
+	{ "nkm", "Namat" },
+	{ "nkn", "Nkangala" },
+	{ "nko", "Nkonya" },
+	{ "nkp", "Niuatoputapu" },
+	{ "nkq", "Nkami" },
+	{ "nkr", "Nukuoro" },
+	{ "nks", "North Asmat" },
+	{ "nkt", "Nyika (Tanzania)" },
+	{ "nku", "Bouna Kulango" },
+	{ "nkv", "Nyika (Malawi and Zambia)" },
+	{ "nkw", "Nkutu" },
+	{ "nkx", "Nkoroo" },
+	{ "nkz", "Nkari" },
+	{ "nla", "Ngombale" },
+	{ "nlc", "Nalca" },
+	{ "nld", "Dutch" },
+	{ "nle", "East Nyala" },
+	{ "nlg", "Gela" },
+	{ "nli", "Grangali" },
+	{ "nlj", "Nyali" },
+	{ "nlk", "Ninia Yali" },
+	{ "nll", "Nihali" },
+	{ "nlo", "Ngul" },
+	{ "nlq", "Lao Naga" },
+	{ "nlu", "Nchumbulu" },
+	{ "nlv", "Orizaba Nahuatl" },
+	{ "nlw", "Walangama" },
+	{ "nlx", "Nahali" },
+	{ "nly", "Nyamal" },
+	{ "nlz", "Nalögo" },
+	{ "nma", "Maram Naga" },
+	{ "nmb", "Big Nambas" },
+	{ "nmc", "Ngam" },
+	{ "nmd", "Ndumu" },
+	{ "nme", "Mzieme Naga" },
+	{ "nmf", "Tangkhul Naga (India)" },
+	{ "nmg", "Kwasio" },
+	{ "nmh", "Monsang Naga" },
+	{ "nmi", "Nyam" },
+	{ "nmj", "Ngombe (Central African Republic)" },
+	{ "nmk", "Namakura" },
+	{ "nml", "Ndemli" },
+	{ "nmm", "Manangba" },
+	{ "nmn", "!Xóõ" },
+	{ "nmo", "Moyon Naga" },
+	{ "nmp", "Nimanbur" },
+	{ "nmq", "Nambya" },
+	{ "nmr", "Nimbari" },
+	{ "nms", "Letemboi" },
+	{ "nmt", "Namonuito" },
+	{ "nmu", "Northeast Maidu" },
+	{ "nmv", "Ngamini" },
+	{ "nmw", "Nimoa" },
+	{ "nmx", "Nama (Papua New Guinea)" },
+	{ "nmy", "Namuyi" },
+	{ "nmz", "Nawdm" },
+	{ "nna", "Nyangumarta" },
+	{ "nnb", "Nande" },
+	{ "nnc", "Nancere" },
+	{ "nnd", "West Ambae" },
+	{ "nne", "Ngandyera" },
+	{ "nnf", "Ngaing" },
+	{ "nng", "Maring Naga" },
+	{ "nnh", "Ngiemboon" },
+	{ "nni", "North Nuaulu" },
+	{ "nnj", "Nyangatom" },
+	{ "nnk", "Nankina" },
+	{ "nnl", "Northern Rengma Naga" },
+	{ "nnm", "Namia" },
+	{ "nnn", "Ngete" },
+	{ "nno", "Norwegian Nynorsk" },
+	{ "nnp", "Wancho Naga" },
+	{ "nnq", "Ngindo" },
+	{ "nnr", "Narungga" },
+	{ "nns", "Ningye" },
+	{ "nnt", "Nanticoke" },
+	{ "nnu", "Dwang" },
+	{ "nnv", "Nugunu (Australia)" },
+	{ "nnw", "Southern Nuni" },
+	{ "nnx", "Ngong" },
+	{ "nny", "Nyangga" },
+	{ "nnz", "Nda'nda'" },
+	{ "noa", "Woun Meu" },
+	{ "nob", "Norwegian Bokmål" },
+	{ "noc", "Nuk" },
+	{ "nod", "Northern Thai" },
+	{ "noe", "Nimadi" },
+	{ "nof", "Nomane" },
+	{ "nog", "Nogai" },
+	{ "noh", "Nomu" },
+	{ "noi", "Noiri" },
+	{ "noj", "Nonuya" },
+	{ "nok", "Nooksack" },
+	{ "nol", "Nomlaki" },
+	{ "nom", "Nocamán" },
+	{ "non", "Old Norse" },
+	{ "nop", "Numanggang" },
+	{ "noq", "Ngongo" },
+	{ "nor", "Norwegian" },
+	{ "nos", "Eastern Nisu" },
+	{ "not", "Nomatsiguenga" },
+	{ "nou", "Ewage-Notu" },
+	{ "nov", "Novial" },
+	{ "now", "Nyambo" },
+	{ "noy", "Noy" },
+	{ "noz", "Nayi" },
+	{ "npa", "Nar Phu" },
+	{ "npb", "Nupbikha" },
+	{ "npg", "Ponyo-Gongwang Naga" },
+	{ "nph", "Phom Naga" },
+	{ "npi", "Nepali (individual language)" },
+	{ "npl", "Southeastern Puebla Nahuatl" },
+	{ "npn", "Mondropolon" },
+	{ "npo", "Pochuri Naga" },
+	{ "nps", "Nipsan" },
+	{ "npu", "Puimei Naga" },
+	{ "npy", "Napu" },
+	{ "nqg", "Southern Nago" },
+	{ "nqk", "Kura Ede Nago" },
+	{ "nqm", "Ndom" },
+	{ "nqn", "Nen" },
+	{ "nqo", "N'Ko" },
+	{ "nqq", "Kyan-Karyaw Naga" },
+	{ "nqy", "Akyaung Ari Naga" },
+	{ "nra", "Ngom" },
+	{ "nrb", "Nara" },
+	{ "nrc", "Noric" },
+	{ "nre", "Southern Rengma Naga" },
+	{ "nrg", "Narango" },
+	{ "nri", "Chokri Naga" },
+	{ "nrk", "Ngarla" },
+	{ "nrl", "Ngarluma" },
+	{ "nrm", "Narom" },
+	{ "nrn", "Norn" },
+	{ "nrp", "North Picene" },
+	{ "nrr", "Norra" },
+	{ "nrt", "Northern Kalapuya" },
+	{ "nru", "Narua" },
+	{ "nrx", "Ngurmbur" },
+	{ "nrz", "Lala" },
+	{ "nsa", "Sangtam Naga" },
+	{ "nsc", "Nshi" },
+	{ "nsd", "Southern Nisu" },
+	{ "nse", "Nsenga" },
+	{ "nsf", "Northwestern Nisu" },
+	{ "nsg", "Ngasa" },
+	{ "nsh", "Ngoshie" },
+	{ "nsi", "Nigerian Sign Language" },
+	{ "nsk", "Naskapi" },
+	{ "nsl", "Norwegian Sign Language" },
+	{ "nsm", "Sumi Naga" },
+	{ "nsn", "Nehan" },
+	{ "nso", "Pedi" },
+	{ "nsp", "Nepalese Sign Language" },
+	{ "nsq", "Northern Sierra Miwok" },
+	{ "nsr", "Maritime Sign Language" },
+	{ "nss", "Nali" },
+	{ "nst", "Tase Naga" },
+	{ "nsu", "Sierra Negra Nahuatl" },
+	{ "nsv", "Southwestern Nisu" },
+	{ "nsw", "Navut" },
+	{ "nsx", "Nsongo" },
+	{ "nsy", "Nasal" },
+	{ "nsz", "Nisenan" },
+	{ "nte", "Nathembo" },
+	{ "ntg", "Ngantangarra" },
+	{ "nti", "Natioro" },
+	{ "ntj", "Ngaanyatjarra" },
+	{ "ntk", "Ikoma-Nata-Isenye" },
+	{ "ntm", "Nateni" },
+	{ "nto", "Ntomba" },
+	{ "ntp", "Northern Tepehuan" },
+	{ "ntr", "Delo" },
+	{ "nts", "Natagaimas" },
+	{ "ntu", "Natügu" },
+	{ "ntw", "Nottoway" },
+	{ "ntx", "Tangkhul Naga (Myanmar)" },
+	{ "nty", "Mantsi" },
+	{ "ntz", "Natanzi" },
+	{ "nua", "Yuanga" },
+	{ "nuc", "Nukuini" },
+	{ "nud", "Ngala" },
+	{ "nue", "Ngundu" },
+	{ "nuf", "Nusu" },
+	{ "nug", "Nungali" },
+	{ "nuh", "Ndunda" },
+	{ "nui", "Ngumbi" },
+	{ "nuj", "Nyole" },
+	{ "nuk", "Nuu-chah-nulth" },
+	{ "nul", "Nusa Laut" },
+	{ "num", "Niuafo'ou" },
+	{ "nun", "Anong" },
+	{ "nuo", "Nguôn" },
+	{ "nup", "Nupe-Nupe-Tako" },
+	{ "nuq", "Nukumanu" },
+	{ "nur", "Nukuria" },
+	{ "nus", "Nuer" },
+	{ "nut", "Nung (Viet Nam)" },
+	{ "nuu", "Ngbundu" },
+	{ "nuv", "Northern Nuni" },
+	{ "nuw", "Nguluwan" },
+	{ "nux", "Mehek" },
+	{ "nuy", "Nunggubuyu" },
+	{ "nuz", "Tlamacazapa Nahuatl" },
+	{ "nvh", "Nasarian" },
+	{ "nvm", "Namiae" },
+	{ "nvo", "Nyokon" },
+	{ "nwa", "Nawathinehena" },
+	{ "nwb", "Nyabwa" },
+	{ "nwc", "Classical Newari" },
+	{ "nwe", "Ngwe" },
+	{ "nwg", "Ngayawung" },
+	{ "nwi", "Southwest Tanna" },
+	{ "nwm", "Nyamusa-Molo" },
+	{ "nwo", "Nauo" },
+	{ "nwr", "Nawaru" },
+	{ "nwx", "Middle Newar" },
+	{ "nwy", "Nottoway-Meherrin" },
+	{ "nxa", "Nauete" },
+	{ "nxd", "Ngando (Democratic Republic of Congo)" },
+	{ "nxe", "Nage" },
+	{ "nxg", "Ngad'a" },
+	{ "nxi", "Nindi" },
+	{ "nxk", "Koki Naga" },
+	{ "nxl", "South Nuaulu" },
+	{ "nxm", "Numidian" },
+	{ "nxn", "Ngawun" },
+	{ "nxq", "Naxi" },
+	{ "nxr", "Ninggerum" },
+	{ "nxu", "Narau" },
+	{ "nxx", "Nafri" },
+	{ "nya", "Nyanja" },
+	{ "nyb", "Nyangbo" },
+	{ "nyc", "Nyanga-li" },
+	{ "nyd", "Nyore" },
+	{ "nye", "Nyengo" },
+	{ "nyf", "Giryama" },
+	{ "nyg", "Nyindu" },
+	{ "nyh", "Nyigina" },
+	{ "nyi", "Ama (Sudan)" },
+	{ "nyj", "Nyanga" },
+	{ "nyk", "Nyaneka" },
+	{ "nyl", "Nyeu" },
+	{ "nym", "Nyamwezi" },
+	{ "nyn", "Nyankole" },
+	{ "nyo", "Nyoro" },
+	{ "nyp", "Nyang'i" },
+	{ "nyq", "Nayini" },
+	{ "nyr", "Nyiha (Malawi)" },
+	{ "nys", "Nyunga" },
+	{ "nyt", "Nyawaygi" },
+	{ "nyu", "Nyungwe" },
+	{ "nyv", "Nyulnyul" },
+	{ "nyw", "Nyaw" },
+	{ "nyx", "Nganyaywana" },
+	{ "nyy", "Nyakyusa-Ngonde" },
+	{ "nza", "Tigon Mbembe" },
+	{ "nzb", "Njebi" },
+	{ "nzi", "Nzima" },
+	{ "nzk", "Nzakara" },
+	{ "nzm", "Zeme Naga" },
+	{ "nzs", "New Zealand Sign Language" },
+	{ "nzu", "Teke-Nzikou" },
+	{ "nzy", "Nzakambay" },
+	{ "nzz", "Nanga Dama Dogon" },
+	{ "oaa", "Orok" },
+	{ "oac", "Oroch" },
+	{ "oar", "Old Aramaic (up to 700 BCE)" },
+	{ "oav", "Old Avar" },
+	{ "obi", "Obispeño" },
+	{ "obk", "Southern Bontok" },
+	{ "obl", "Oblo" },
+	{ "obm", "Moabite" },
+	{ "obo", "Obo Manobo" },
+	{ "obr", "Old Burmese" },
+	{ "obt", "Old Breton" },
+	{ "obu", "Obulom" },
+	{ "oca", "Ocaina" },
+	{ "och", "Old Chinese" },
+	{ "oci", "Occitan (post 1500)" },
+	{ "oco", "Old Cornish" },
+	{ "ocu", "Atzingo Matlatzinca" },
+	{ "oda", "Odut" },
+	{ "odk", "Od" },
+	{ "odt", "Old Dutch" },
+	{ "odu", "Odual" },
+	{ "ofo", "Ofo" },
+	{ "ofs", "Old Frisian" },
+	{ "ofu", "Efutop" },
+	{ "ogb", "Ogbia" },
+	{ "ogc", "Ogbah" },
+	{ "oge", "Old Georgian" },
+	{ "ogg", "Ogbogolo" },
+	{ "ogo", "Khana" },
+	{ "ogu", "Ogbronuagum" },
+	{ "oht", "Old Hittite" },
+	{ "ohu", "Old Hungarian" },
+	{ "oia", "Oirata" },
+	{ "oin", "Inebu One" },
+	{ "ojb", "Northwestern Ojibwa" },
+	{ "ojc", "Central Ojibwa" },
+	{ "ojg", "Eastern Ojibwa" },
+	{ "oji", "Ojibwa" },
+	{ "ojp", "Old Japanese" },
+	{ "ojs", "Severn Ojibwa" },
+	{ "ojv", "Ontong Java" },
+	{ "ojw", "Western Ojibwa" },
+	{ "oka", "Okanagan" },
+	{ "okb", "Okobo" },
+	{ "okd", "Okodia" },
+	{ "oke", "Okpe (Southwestern Edo)" },
+	{ "okg", "Koko Babangk" },
+	{ "okh", "Koresh-e Rostam" },
+	{ "oki", "Okiek" },
+	{ "okj", "Oko-Juwoi" },
+	{ "okk", "Kwamtim One" },
+	{ "okl", "Old Kentish Sign Language" },
+	{ "okm", "Middle Korean (10th-16th cent.)" },
+	{ "okn", "Oki-No-Erabu" },
+	{ "oko", "Old Korean (3rd-9th cent.)" },
+	{ "okr", "Kirike" },
+	{ "oks", "Oko-Eni-Osayen" },
+	{ "oku", "Oku" },
+	{ "okv", "Orokaiva" },
+	{ "okx", "Okpe (Northwestern Edo)" },
+	{ "ola", "Walungge" },
+	{ "old", "Mochi" },
+	{ "ole", "Olekha" },
+	{ "olk", "Olkol" },
+	{ "olm", "Oloma" },
+	{ "olo", "Livvi" },
+	{ "olr", "Olrat" },
+	{ "oma", "Omaha-Ponca" },
+	{ "omb", "East Ambae" },
+	{ "omc", "Mochica" },
+	{ "ome", "Omejes" },
+	{ "omg", "Omagua" },
+	{ "omi", "Omi" },
+	{ "omk", "Omok" },
+	{ "oml", "Ombo" },
+	{ "omn", "Minoan" },
+	{ "omo", "Utarmbung" },
+	{ "omp", "Old Manipuri" },
+	{ "omr", "Old Marathi" },
+	{ "omt", "Omotik" },
+	{ "omu", "Omurano" },
+	{ "omw", "South Tairora" },
+	{ "omx", "Old Mon" },
+	{ "ona", "Ona" },
+	{ "onb", "Lingao" },
+	{ "one", "Oneida" },
+	{ "ong", "Olo" },
+	{ "oni", "Onin" },
+	{ "onj", "Onjob" },
+	{ "onk", "Kabore One" },
+	{ "onn", "Onobasulu" },
+	{ "ono", "Onondaga" },
+	{ "onp", "Sartang" },
+	{ "onr", "Northern One" },
+	{ "ons", "Ono" },
+	{ "ont", "Ontenu" },
+	{ "onu", "Unua" },
+	{ "onw", "Old Nubian" },
+	{ "onx", "Onin Based Pidgin" },
+	{ "ood", "Tohono O'odham" },
+	{ "oog", "Ong" },
+	{ "oon", "Önge" },
+	{ "oor", "Oorlams" },
+	{ "oos", "Old Ossetic" },
+	{ "opa", "Okpamheri" },
+	{ "opk", "Kopkaka" },
+	{ "opm", "Oksapmin" },
+	{ "opo", "Opao" },
+	{ "opt", "Opata" },
+	{ "opy", "Ofayé" },
+	{ "ora", "Oroha" },
+	{ "orc", "Orma" },
+	{ "ore", "Orejón" },
+	{ "org", "Oring" },
+	{ "orh", "Oroqen" },
+	{ "ori", "Oriya (macrolanguage)" },
+	{ "orm", "Oromo" },
+	{ "orn", "Orang Kanaq" },
+	{ "oro", "Orokolo" },
+	{ "orr", "Oruma" },
+	{ "ors", "Orang Seletar" },
+	{ "ort", "Adivasi Oriya" },
+	{ "oru", "Ormuri" },
+	{ "orv", "Old Russian" },
+	{ "orw", "Oro Win" },
+	{ "orx", "Oro" },
+	{ "ory", "Oriya (individual language)" },
+	{ "orz", "Ormu" },
+	{ "osa", "Osage" },
+	{ "osc", "Oscan" },
+	{ "osi", "Osing" },
+	{ "oso", "Ososo" },
+	{ "osp", "Old Spanish" },
+	{ "oss", "Ossetian" },
+	{ "ost", "Osatu" },
+	{ "osu", "Southern One" },
+	{ "osx", "Old Saxon" },
+	{ "ota", "Ottoman Turkish (1500-1928)" },
+	{ "otb", "Old Tibetan" },
+	{ "otd", "Ot Danum" },
+	{ "ote", "Mezquital Otomi" },
+	{ "oti", "Oti" },
+	{ "otk", "Old Turkish" },
+	{ "otl", "Tilapa Otomi" },
+	{ "otm", "Eastern Highland Otomi" },
+	{ "otn", "Tenango Otomi" },
+	{ "otq", "Querétaro Otomi" },
+	{ "otr", "Otoro" },
+	{ "ots", "Estado de México Otomi" },
+	{ "ott", "Temoaya Otomi" },
+	{ "otu", "Otuke" },
+	{ "otw", "Ottawa" },
+	{ "otx", "Texcatepec Otomi" },
+	{ "oty", "Old Tamil" },
+	{ "otz", "Ixtenco Otomi" },
+	{ "oua", "Tagargrent" },
+	{ "oub", "Glio-Oubi" },
+	{ "oue", "Oune" },
+	{ "oui", "Old Uighur" },
+	{ "oum", "Ouma" },
+	{ "oun", "!O!ung" },
+	{ "owi", "Owiniga" },
+	{ "owl", "Old Welsh" },
+	{ "oyb", "Oy" },
+	{ "oyd", "Oyda" },
+	{ "oym", "Wayampi" },
+	{ "oyy", "Oya'oya" },
+	{ "ozm", "Koonzime" },
+	{ "pab", "Parecís" },
+	{ "pac", "Pacoh" },
+	{ "pad", "Paumarí" },
+	{ "pae", "Pagibete" },
+	{ "paf", "Paranawát" },
+	{ "pag", "Pangasinan" },
+	{ "pah", "Tenharim" },
+	{ "pai", "Pe" },
+	{ "pak", "Parakanã" },
+	{ "pal", "Pahlavi" },
+	{ "pam", "Pampanga" },
+	{ "pan", "Panjabi" },
+	{ "pao", "Northern Paiute" },
+	{ "pap", "Papiamento" },
+	{ "paq", "Parya" },
+	{ "par", "Panamint" },
+	{ "pas", "Papasena" },
+	{ "pat", "Papitalai" },
+	{ "pau", "Palauan" },
+	{ "pav", "Pakaásnovos" },
+	{ "paw", "Pawnee" },
+	{ "pax", "Pankararé" },
+	{ "pay", "Pech" },
+	{ "paz", "Pankararú" },
+	{ "pbb", "Páez" },
+	{ "pbc", "Patamona" },
+	{ "pbe", "Mezontla Popoloca" },
+	{ "pbf", "Coyotepec Popoloca" },
+	{ "pbg", "Paraujano" },
+	{ "pbh", "E'ñapa Woromaipu" },
+	{ "pbi", "Parkwa" },
+	{ "pbl", "Mak (Nigeria)" },
+	{ "pbn", "Kpasam" },
+	{ "pbo", "Papel" },
+	{ "pbp", "Badyara" },
+	{ "pbr", "Pangwa" },
+	{ "pbs", "Central Pame" },
+	{ "pbt", "Southern Pashto" },
+	{ "pbu", "Northern Pashto" },
+	{ "pbv", "Pnar" },
+	{ "pby", "Pyu" },
+	{ "pca", "Santa Inés Ahuatempan Popoloca" },
+	{ "pcb", "Pear" },
+	{ "pcc", "Bouyei" },
+	{ "pcd", "Picard" },
+	{ "pce", "Ruching Palaung" },
+	{ "pcf", "Paliyan" },
+	{ "pcg", "Paniya" },
+	{ "pch", "Pardhan" },
+	{ "pci", "Duruwa" },
+	{ "pcj", "Parenga" },
+	{ "pck", "Paite Chin" },
+	{ "pcl", "Pardhi" },
+	{ "pcm", "Nigerian Pidgin" },
+	{ "pcn", "Piti" },
+	{ "pcp", "Pacahuara" },
+	{ "pcw", "Pyapun" },
+	{ "pda", "Anam" },
+	{ "pdc", "Pennsylvania German" },
+	{ "pdi", "Pa Di" },
+	{ "pdn", "Podena" },
+	{ "pdo", "Padoe" },
+	{ "pdt", "Plautdietsch" },
+	{ "pdu", "Kayan" },
+	{ "pea", "Peranakan Indonesian" },
+	{ "peb", "Eastern Pomo" },
+	{ "ped", "Mala (Papua New Guinea)" },
+	{ "pee", "Taje" },
+	{ "pef", "Northeastern Pomo" },
+	{ "peg", "Pengo" },
+	{ "peh", "Bonan" },
+	{ "pei", "Chichimeca-Jonaz" },
+	{ "pej", "Northern Pomo" },
+	{ "pek", "Penchal" },
+	{ "pel", "Pekal" },
+	{ "pem", "Phende" },
+	{ "peo", "Old Persian (ca. 600-400 B.C.)" },
+	{ "pep", "Kunja" },
+	{ "peq", "Southern Pomo" },
+	{ "pes", "Iranian Persian" },
+	{ "pev", "Pémono" },
+	{ "pex", "Petats" },
+	{ "pey", "Petjo" },
+	{ "pez", "Eastern Penan" },
+	{ "pfa", "Pááfang" },
+	{ "pfe", "Peere" },
+	{ "pfl", "Pfaelzisch" },
+	{ "pga", "Sudanese Creole Arabic" },
+	{ "pgg", "Pangwali" },
+	{ "pgi", "Pagi" },
+	{ "pgk", "Rerep" },
+	{ "pgl", "Primitive Irish" },
+	{ "pgn", "Paelignian" },
+	{ "pgs", "Pangseng" },
+	{ "pgu", "Pagu" },
+	{ "pha", "Pa-Hng" },
+	{ "phd", "Phudagi" },
+	{ "phg", "Phuong" },
+	{ "phh", "Phukha" },
+	{ "phk", "Phake" },
+	{ "phl", "Phalura" },
+	{ "phm", "Phimbi" },
+	{ "phn", "Phoenician" },
+	{ "pho", "Phunoi" },
+	{ "phq", "Phana'" },
+	{ "phr", "Pahari-Potwari" },
+	{ "pht", "Phu Thai" },
+	{ "phu", "Phuan" },
+	{ "phv", "Pahlavani" },
+	{ "phw", "Phangduwali" },
+	{ "pia", "Pima Bajo" },
+	{ "pib", "Yine" },
+	{ "pic", "Pinji" },
+	{ "pid", "Piaroa" },
+	{ "pie", "Piro" },
+	{ "pif", "Pingelapese" },
+	{ "pig", "Pisabo" },
+	{ "pih", "Pitcairn-Norfolk" },
+	{ "pii", "Pini" },
+	{ "pij", "Pijao" },
+	{ "pil", "Yom" },
+	{ "pim", "Powhatan" },
+	{ "pin", "Piame" },
+	{ "pio", "Piapoco" },
+	{ "pip", "Pero" },
+	{ "pir", "Piratapuyo" },
+	{ "pis", "Pijin" },
+	{ "pit", "Pitta Pitta" },
+	{ "piu", "Pintupi-Luritja" },
+	{ "piv", "Pileni" },
+	{ "piw", "Pimbwe" },
+	{ "pix", "Piu" },
+	{ "piy", "Piya-Kwonci" },
+	{ "piz", "Pije" },
+	{ "pjt", "Pitjantjatjara" },
+	{ "pka", "Ardhamāgadhī Prākrit" },
+	{ "pkb", "Pokomo" },
+	{ "pkc", "Paekche" },
+	{ "pkg", "Pak-Tong" },
+	{ "pkh", "Pankhu" },
+	{ "pkn", "Pakanha" },
+	{ "pko", "Pökoot" },
+	{ "pkp", "Pukapuka" },
+	{ "pkr", "Attapady Kurumba" },
+	{ "pks", "Pakistan Sign Language" },
+	{ "pkt", "Maleng" },
+	{ "pku", "Paku" },
+	{ "pla", "Miani" },
+	{ "plb", "Polonombauk" },
+	{ "plc", "Central Palawano" },
+	{ "pld", "Polari" },
+	{ "ple", "Palu'e" },
+	{ "plg", "Pilagá" },
+	{ "plh", "Paulohi" },
+	{ "pli", "Pali" },
+	{ "plj", "Polci" },
+	{ "plk", "Kohistani Shina" },
+	{ "pll", "Shwe Palaung" },
+	{ "pln", "Palenquero" },
+	{ "plo", "Oluta Popoluca" },
+	{ "plp", "Palpa" },
+	{ "plq", "Palaic" },
+	{ "plr", "Palaka Senoufo" },
+	{ "pls", "San Marcos Tlalcoyalco Popoloca" },
+	{ "plt", "Plateau Malagasy" },
+	{ "plu", "Palikúr" },
+	{ "plv", "Southwest Palawano" },
+	{ "plw", "Brooke's Point Palawano" },
+	{ "ply", "Bolyu" },
+	{ "plz", "Paluan" },
+	{ "pma", "Paama" },
+	{ "pmb", "Pambia" },
+	{ "pmc", "Palumata" },
+	{ "pmd", "Pallanganmiddang" },
+	{ "pme", "Pwaamei" },
+	{ "pmf", "Pamona" },
+	{ "pmh", "Māhārāṣṭri Prākrit" },
+	{ "pmi", "Northern Pumi" },
+	{ "pmj", "Southern Pumi" },
+	{ "pmk", "Pamlico" },
+	{ "pml", "Lingua Franca" },
+	{ "pmm", "Pomo" },
+	{ "pmn", "Pam" },
+	{ "pmo", "Pom" },
+	{ "pmq", "Northern Pame" },
+	{ "pmr", "Paynamar" },
+	{ "pms", "Piemontese" },
+	{ "pmt", "Tuamotuan" },
+	{ "pmu", "Mirpur Panjabi" },
+	{ "pmw", "Plains Miwok" },
+	{ "pmx", "Poumei Naga" },
+	{ "pmy", "Papuan Malay" },
+	{ "pmz", "Southern Pame" },
+	{ "pna", "Punan Bah-Biau" },
+	{ "pnb", "Western Panjabi" },
+	{ "pnc", "Pannei" },
+	{ "pne", "Western Penan" },
+	{ "png", "Pongu" },
+	{ "pnh", "Penrhyn" },
+	{ "pni", "Aoheng" },
+	{ "pnj", "Pinjarup" },
+	{ "pnk", "Paunaka" },
+	{ "pnl", "Paleni" },
+	{ "pnm", "Punan Batu 1" },
+	{ "pnn", "Pinai-Hagahai" },
+	{ "pno", "Panobo" },
+	{ "pnp", "Pancana" },
+	{ "pnq", "Pana (Burkina Faso)" },
+	{ "pnr", "Panim" },
+	{ "pns", "Ponosakan" },
+	{ "pnt", "Pontic" },
+	{ "pnu", "Jiongnai Bunu" },
+	{ "pnv", "Pinigura" },
+	{ "pnw", "Panytyima" },
+	{ "pnx", "Phong-Kniang" },
+	{ "pny", "Pinyin" },
+	{ "pnz", "Pana (Central African Republic)" },
+	{ "poc", "Poqomam" },
+	{ "pod", "Ponares" },
+	{ "poe", "San Juan Atzingo Popoloca" },
+	{ "pof", "Poke" },
+	{ "pog", "Potiguára" },
+	{ "poh", "Poqomchi'" },
+	{ "poi", "Highland Popoluca" },
+	{ "pok", "Pokangá" },
+	{ "pol", "Polish" },
+	{ "pom", "Southeastern Pomo" },
+	{ "pon", "Pohnpeian" },
+	{ "poo", "Central Pomo" },
+	{ "pop", "Pwapwâ" },
+	{ "poq", "Texistepec Popoluca" },
+	{ "por", "Portuguese" },
+	{ "pos", "Sayula Popoluca" },
+	{ "pot", "Potawatomi" },
+	{ "pov", "Upper Guinea Crioulo" },
+	{ "pow", "San Felipe Otlaltepec Popoloca" },
+	{ "pox", "Polabian" },
+	{ "poy", "Pogolo" },
+	{ "ppa", "Pao" },
+	{ "ppe", "Papi" },
+	{ "ppi", "Paipai" },
+	{ "ppk", "Uma" },
+	{ "ppl", "Pipil" },
+	{ "ppm", "Papuma" },
+	{ "ppn", "Papapana" },
+	{ "ppo", "Folopa" },
+	{ "ppp", "Pelende" },
+	{ "ppq", "Pei" },
+	{ "pps", "San Luís Temalacayuca Popoloca" },
+	{ "ppt", "Pare" },
+	{ "ppu", "Papora" },
+	{ "pqa", "Pa'a" },
+	{ "pqm", "Malecite-Passamaquoddy" },
+	{ "prb", "Lua'" },
+	{ "prc", "Parachi" },
+	{ "prd", "Parsi-Dari" },
+	{ "pre", "Principense" },
+	{ "prf", "Paranan" },
+	{ "prg", "Prussian" },
+	{ "prh", "Porohanon" },
+	{ "pri", "Paicî" },
+	{ "prk", "Parauk" },
+	{ "prl", "Peruvian Sign Language" },
+	{ "prm", "Kibiri" },
+	{ "prn", "Prasuni" },
+	{ "pro", "Old Provençal (to 1500)" },
+	{ "prp", "Parsi" },
+	{ "prq", "Ashéninka Perené" },
+	{ "prr", "Puri" },
+	{ "prs", "Dari" },
+	{ "prt", "Phai" },
+	{ "pru", "Puragi" },
+	{ "prw", "Parawen" },
+	{ "prx", "Purik" },
+	{ "pry", "Pray 3" },
+	{ "prz", "Providencia Sign Language" },
+	{ "psa", "Asue Awyu" },
+	{ "psc", "Persian Sign Language" },
+	{ "psd", "Plains Indian Sign Language" },
+	{ "pse", "Central Malay" },
+	{ "psg", "Penang Sign Language" },
+	{ "psh", "Southwest Pashayi" },
+	{ "psi", "Southeast Pashayi" },
+	{ "psl", "Puerto Rican Sign Language" },
+	{ "psm", "Pauserna" },
+	{ "psn", "Panasuan" },
+	{ "pso", "Polish Sign Language" },
+	{ "psp", "Philippine Sign Language" },
+	{ "psq", "Pasi" },
+	{ "psr", "Portuguese Sign Language" },
+	{ "pss", "Kaulong" },
+	{ "pst", "Central Pashto" },
+	{ "psu", "Sauraseni Prākrit" },
+	{ "psw", "Port Sandwich" },
+	{ "psy", "Piscataway" },
+	{ "pta", "Pai Tavytera" },
+	{ "pth", "Pataxó Hã-Ha-Hãe" },
+	{ "pti", "Pintiini" },
+	{ "ptn", "Patani" },
+	{ "pto", "Zo'é" },
+	{ "ptp", "Patep" },
+	{ "ptr", "Piamatsina" },
+	{ "ptt", "Enrekang" },
+	{ "ptu", "Bambam" },
+	{ "ptv", "Port Vato" },
+	{ "ptw", "Pentlatch" },
+	{ "pty", "Pathiya" },
+	{ "pua", "Western Highland Purepecha" },
+	{ "pub", "Purum" },
+	{ "puc", "Punan Merap" },
+	{ "pud", "Punan Aput" },
+	{ "pue", "Puelche" },
+	{ "puf", "Punan Merah" },
+	{ "pug", "Phuie" },
+	{ "pui", "Puinave" },
+	{ "puj", "Punan Tubu" },
+	{ "puk", "Pu Ko" },
+	{ "pum", "Puma" },
+	{ "puo", "Puoc" },
+	{ "pup", "Pulabu" },
+	{ "puq", "Puquina" },
+	{ "pur", "Puruborá" },
+	{ "pus", "Pushto" },
+	{ "put", "Putoh" },
+	{ "puu", "Punu" },
+	{ "puw", "Puluwatese" },
+	{ "pux", "Puare" },
+	{ "puy", "Purisimeño" },
+	{ "puz", "Purum Naga" },
+	{ "pwa", "Pawaia" },
+	{ "pwb", "Panawa" },
+	{ "pwg", "Gapapaiwa" },
+	{ "pwi", "Patwin" },
+	{ "pwm", "Molbog" },
+	{ "pwn", "Paiwan" },
+	{ "pwo", "Pwo Western Karen" },
+	{ "pwr", "Powari" },
+	{ "pww", "Pwo Northern Karen" },
+	{ "pxm", "Quetzaltepec Mixe" },
+	{ "pye", "Pye Krumen" },
+	{ "pym", "Fyam" },
+	{ "pyn", "Poyanáwa" },
+	{ "pys", "Paraguayan Sign Language" },
+	{ "pyu", "Puyuma" },
+	{ "pyx", "Pyu (Myanmar)" },
+	{ "pyy", "Pyen" },
+	{ "pzn", "Para Naga" },
+	{ "qaa", "Reserved for local use" },
+	{ "qab", "Reserved for local use" },
+	{ "qac", "Reserved for local use" },
+	{ "qad", "Reserved for local use" },
+	{ "qae", "Reserved for local use" },
+	{ "qaf", "Reserved for local use" },
+	{ "qag", "Reserved for local use" },
+	{ "qah", "Reserved for local use" },
+	{ "qai", "Reserved for local use" },
+	{ "qaj", "Reserved for local use" },
+	{ "qak", "Reserved for local use" },
+	{ "qal", "Reserved for local use" },
+	{ "qam", "Reserved for local use" },
+	{ "qan", "Reserved for local use" },
+	{ "qao", "Reserved for local use" },
+	{ "qap", "Reserved for local use" },
+	{ "qaq", "Reserved for local use" },
+	{ "qar", "Reserved for local use" },
+	{ "qas", "Reserved for local use" },
+	{ "qat", "Reserved for local use" },
+	{ "qau", "Reserved for local use" },
+	{ "qav", "Reserved for local use" },
+	{ "qaw", "Reserved for local use" },
+	{ "qax", "Reserved for local use" },
+	{ "qay", "Reserved for local use" },
+	{ "qaz", "Reserved for local use" },
+	{ "qba", "Reserved for local use" },
+	{ "qbb", "Reserved for local use" },
+	{ "qbc", "Reserved for local use" },
+	{ "qbd", "Reserved for local use" },
+	{ "qbe", "Reserved for local use" },
+	{ "qbf", "Reserved for local use" },
+	{ "qbg", "Reserved for local use" },
+	{ "qbh", "Reserved for local use" },
+	{ "qbi", "Reserved for local use" },
+	{ "qbj", "Reserved for local use" },
+	{ "qbk", "Reserved for local use" },
+	{ "qbl", "Reserved for local use" },
+	{ "qbm", "Reserved for local use" },
+	{ "qbn", "Reserved for local use" },
+	{ "qbo", "Reserved for local use" },
+	{ "qbp", "Reserved for local use" },
+	{ "qbq", "Reserved for local use" },
+	{ "qbr", "Reserved for local use" },
+	{ "qbs", "Reserved for local use" },
+	{ "qbt", "Reserved for local use" },
+	{ "qbu", "Reserved for local use" },
+	{ "qbv", "Reserved for local use" },
+	{ "qbw", "Reserved for local use" },
+	{ "qbx", "Reserved for local use" },
+	{ "qby", "Reserved for local use" },
+	{ "qbz", "Reserved for local use" },
+	{ "qca", "Reserved for local use" },
+	{ "qcb", "Reserved for local use" },
+	{ "qcc", "Reserved for local use" },
+	{ "qcd", "Reserved for local use" },
+	{ "qce", "Reserved for local use" },
+	{ "qcf", "Reserved for local use" },
+	{ "qcg", "Reserved for local use" },
+	{ "qch", "Reserved for local use" },
+	{ "qci", "Reserved for local use" },
+	{ "qcj", "Reserved for local use" },
+	{ "qck", "Reserved for local use" },
+	{ "qcl", "Reserved for local use" },
+	{ "qcm", "Reserved for local use" },
+	{ "qcn", "Reserved for local use" },
+	{ "qco", "Reserved for local use" },
+	{ "qcp", "Reserved for local use" },
+	{ "qcq", "Reserved for local use" },
+	{ "qcr", "Reserved for local use" },
+	{ "qcs", "Reserved for local use" },
+	{ "qct", "Reserved for local use" },
+	{ "qcu", "Reserved for local use" },
+	{ "qcv", "Reserved for local use" },
+	{ "qcw", "Reserved for local use" },
+	{ "qcx", "Reserved for local use" },
+	{ "qcy", "Reserved for local use" },
+	{ "qcz", "Reserved for local use" },
+	{ "qda", "Reserved for local use" },
+	{ "qdb", "Reserved for local use" },
+	{ "qdc", "Reserved for local use" },
+	{ "qdd", "Reserved for local use" },
+	{ "qde", "Reserved for local use" },
+	{ "qdf", "Reserved for local use" },
+	{ "qdg", "Reserved for local use" },
+	{ "qdh", "Reserved for local use" },
+	{ "qdi", "Reserved for local use" },
+	{ "qdj", "Reserved for local use" },
+	{ "qdk", "Reserved for local use" },
+	{ "qdl", "Reserved for local use" },
+	{ "qdm", "Reserved for local use" },
+	{ "qdn", "Reserved for local use" },
+	{ "qdo", "Reserved for local use" },
+	{ "qdp", "Reserved for local use" },
+	{ "qdq", "Reserved for local use" },
+	{ "qdr", "Reserved for local use" },
+	{ "qds", "Reserved for local use" },
+	{ "qdt", "Reserved for local use" },
+	{ "qdu", "Reserved for local use" },
+	{ "qdv", "Reserved for local use" },
+	{ "qdw", "Reserved for local use" },
+	{ "qdx", "Reserved for local use" },
+	{ "qdy", "Reserved for local use" },
+	{ "qdz", "Reserved for local use" },
+	{ "qea", "Reserved for local use" },
+	{ "qeb", "Reserved for local use" },
+	{ "qec", "Reserved for local use" },
+	{ "qed", "Reserved for local use" },
+	{ "qee", "Reserved for local use" },
+	{ "qef", "Reserved for local use" },
+	{ "qeg", "Reserved for local use" },
+	{ "qeh", "Reserved for local use" },
+	{ "qei", "Reserved for local use" },
+	{ "qej", "Reserved for local use" },
+	{ "qek", "Reserved for local use" },
+	{ "qel", "Reserved for local use" },
+	{ "qem", "Reserved for local use" },
+	{ "qen", "Reserved for local use" },
+	{ "qeo", "Reserved for local use" },
+	{ "qep", "Reserved for local use" },
+	{ "qeq", "Reserved for local use" },
+	{ "qer", "Reserved for local use" },
+	{ "qes", "Reserved for local use" },
+	{ "qet", "Reserved for local use" },
+	{ "qeu", "Reserved for local use" },
+	{ "qev", "Reserved for local use" },
+	{ "qew", "Reserved for local use" },
+	{ "qex", "Reserved for local use" },
+	{ "qey", "Reserved for local use" },
+	{ "qez", "Reserved for local use" },
+	{ "qfa", "Reserved for local use" },
+	{ "qfb", "Reserved for local use" },
+	{ "qfc", "Reserved for local use" },
+	{ "qfd", "Reserved for local use" },
+	{ "qfe", "Reserved for local use" },
+	{ "qff", "Reserved for local use" },
+	{ "qfg", "Reserved for local use" },
+	{ "qfh", "Reserved for local use" },
+	{ "qfi", "Reserved for local use" },
+	{ "qfj", "Reserved for local use" },
+	{ "qfk", "Reserved for local use" },
+	{ "qfl", "Reserved for local use" },
+	{ "qfm", "Reserved for local use" },
+	{ "qfn", "Reserved for local use" },
+	{ "qfo", "Reserved for local use" },
+	{ "qfp", "Reserved for local use" },
+	{ "qfq", "Reserved for local use" },
+	{ "qfr", "Reserved for local use" },
+	{ "qfs", "Reserved for local use" },
+	{ "qft", "Reserved for local use" },
+	{ "qfu", "Reserved for local use" },
+	{ "qfv", "Reserved for local use" },
+	{ "qfw", "Reserved for local use" },
+	{ "qfx", "Reserved for local use" },
+	{ "qfy", "Reserved for local use" },
+	{ "qfz", "Reserved for local use" },
+	{ "qga", "Reserved for local use" },
+	{ "qgb", "Reserved for local use" },
+	{ "qgc", "Reserved for local use" },
+	{ "qgd", "Reserved for local use" },
+	{ "qge", "Reserved for local use" },
+	{ "qgf", "Reserved for local use" },
+	{ "qgg", "Reserved for local use" },
+	{ "qgh", "Reserved for local use" },
+	{ "qgi", "Reserved for local use" },
+	{ "qgj", "Reserved for local use" },
+	{ "qgk", "Reserved for local use" },
+	{ "qgl", "Reserved for local use" },
+	{ "qgm", "Reserved for local use" },
+	{ "qgn", "Reserved for local use" },
+	{ "qgo", "Reserved for local use" },
+	{ "qgp", "Reserved for local use" },
+	{ "qgq", "Reserved for local use" },
+	{ "qgr", "Reserved for local use" },
+	{ "qgs", "Reserved for local use" },
+	{ "qgt", "Reserved for local use" },
+	{ "qgu", "Reserved for local use" },
+	{ "qgv", "Reserved for local use" },
+	{ "qgw", "Reserved for local use" },
+	{ "qgx", "Reserved for local use" },
+	{ "qgy", "Reserved for local use" },
+	{ "qgz", "Reserved for local use" },
+	{ "qha", "Reserved for local use" },
+	{ "qhb", "Reserved for local use" },
+	{ "qhc", "Reserved for local use" },
+	{ "qhd", "Reserved for local use" },
+	{ "qhe", "Reserved for local use" },
+	{ "qhf", "Reserved for local use" },
+	{ "qhg", "Reserved for local use" },
+	{ "qhh", "Reserved for local use" },
+	{ "qhi", "Reserved for local use" },
+	{ "qhj", "Reserved for local use" },
+	{ "qhk", "Reserved for local use" },
+	{ "qhl", "Reserved for local use" },
+	{ "qhm", "Reserved for local use" },
+	{ "qhn", "Reserved for local use" },
+	{ "qho", "Reserved for local use" },
+	{ "qhp", "Reserved for local use" },
+	{ "qhq", "Reserved for local use" },
+	{ "qhr", "Reserved for local use" },
+	{ "qhs", "Reserved for local use" },
+	{ "qht", "Reserved for local use" },
+	{ "qhu", "Reserved for local use" },
+	{ "qhv", "Reserved for local use" },
+	{ "qhw", "Reserved for local use" },
+	{ "qhx", "Reserved for local use" },
+	{ "qhy", "Reserved for local use" },
+	{ "qhz", "Reserved for local use" },
+	{ "qia", "Reserved for local use" },
+	{ "qib", "Reserved for local use" },
+	{ "qic", "Reserved for local use" },
+	{ "qid", "Reserved for local use" },
+	{ "qie", "Reserved for local use" },
+	{ "qif", "Reserved for local use" },
+	{ "qig", "Reserved for local use" },
+	{ "qih", "Reserved for local use" },
+	{ "qii", "Reserved for local use" },
+	{ "qij", "Reserved for local use" },
+	{ "qik", "Reserved for local use" },
+	{ "qil", "Reserved for local use" },
+	{ "qim", "Reserved for local use" },
+	{ "qin", "Reserved for local use" },
+	{ "qio", "Reserved for local use" },
+	{ "qip", "Reserved for local use" },
+	{ "qiq", "Reserved for local use" },
+	{ "qir", "Reserved for local use" },
+	{ "qis", "Reserved for local use" },
+	{ "qit", "Reserved for local use" },
+	{ "qiu", "Reserved for local use" },
+	{ "qiv", "Reserved for local use" },
+	{ "qiw", "Reserved for local use" },
+	{ "qix", "Reserved for local use" },
+	{ "qiy", "Reserved for local use" },
+	{ "qiz", "Reserved for local use" },
+	{ "qja", "Reserved for local use" },
+	{ "qjb", "Reserved for local use" },
+	{ "qjc", "Reserved for local use" },
+	{ "qjd", "Reserved for local use" },
+	{ "qje", "Reserved for local use" },
+	{ "qjf", "Reserved for local use" },
+	{ "qjg", "Reserved for local use" },
+	{ "qjh", "Reserved for local use" },
+	{ "qji", "Reserved for local use" },
+	{ "qjj", "Reserved for local use" },
+	{ "qjk", "Reserved for local use" },
+	{ "qjl", "Reserved for local use" },
+	{ "qjm", "Reserved for local use" },
+	{ "qjn", "Reserved for local use" },
+	{ "qjo", "Reserved for local use" },
+	{ "qjp", "Reserved for local use" },
+	{ "qjq", "Reserved for local use" },
+	{ "qjr", "Reserved for local use" },
+	{ "qjs", "Reserved for local use" },
+	{ "qjt", "Reserved for local use" },
+	{ "qju", "Reserved for local use" },
+	{ "qjv", "Reserved for local use" },
+	{ "qjw", "Reserved for local use" },
+	{ "qjx", "Reserved for local use" },
+	{ "qjy", "Reserved for local use" },
+	{ "qjz", "Reserved for local use" },
+	{ "qka", "Reserved for local use" },
+	{ "qkb", "Reserved for local use" },
+	{ "qkc", "Reserved for local use" },
+	{ "qkd", "Reserved for local use" },
+	{ "qke", "Reserved for local use" },
+	{ "qkf", "Reserved for local use" },
+	{ "qkg", "Reserved for local use" },
+	{ "qkh", "Reserved for local use" },
+	{ "qki", "Reserved for local use" },
+	{ "qkj", "Reserved for local use" },
+	{ "qkk", "Reserved for local use" },
+	{ "qkl", "Reserved for local use" },
+	{ "qkm", "Reserved for local use" },
+	{ "qkn", "Reserved for local use" },
+	{ "qko", "Reserved for local use" },
+	{ "qkp", "Reserved for local use" },
+	{ "qkq", "Reserved for local use" },
+	{ "qkr", "Reserved for local use" },
+	{ "qks", "Reserved for local use" },
+	{ "qkt", "Reserved for local use" },
+	{ "qku", "Reserved for local use" },
+	{ "qkv", "Reserved for local use" },
+	{ "qkw", "Reserved for local use" },
+	{ "qkx", "Reserved for local use" },
+	{ "qky", "Reserved for local use" },
+	{ "qkz", "Reserved for local use" },
+	{ "qla", "Reserved for local use" },
+	{ "qlb", "Reserved for local use" },
+	{ "qlc", "Reserved for local use" },
+	{ "qld", "Reserved for local use" },
+	{ "qle", "Reserved for local use" },
+	{ "qlf", "Reserved for local use" },
+	{ "qlg", "Reserved for local use" },
+	{ "qlh", "Reserved for local use" },
+	{ "qli", "Reserved for local use" },
+	{ "qlj", "Reserved for local use" },
+	{ "qlk", "Reserved for local use" },
+	{ "qll", "Reserved for local use" },
+	{ "qlm", "Reserved for local use" },
+	{ "qln", "Reserved for local use" },
+	{ "qlo", "Reserved for local use" },
+	{ "qlp", "Reserved for local use" },
+	{ "qlq", "Reserved for local use" },
+	{ "qlr", "Reserved for local use" },
+	{ "qls", "Reserved for local use" },
+	{ "qlt", "Reserved for local use" },
+	{ "qlu", "Reserved for local use" },
+	{ "qlv", "Reserved for local use" },
+	{ "qlw", "Reserved for local use" },
+	{ "qlx", "Reserved for local use" },
+	{ "qly", "Reserved for local use" },
+	{ "qlz", "Reserved for local use" },
+	{ "qma", "Reserved for local use" },
+	{ "qmb", "Reserved for local use" },
+	{ "qmc", "Reserved for local use" },
+	{ "qmd", "Reserved for local use" },
+	{ "qme", "Reserved for local use" },
+	{ "qmf", "Reserved for local use" },
+	{ "qmg", "Reserved for local use" },
+	{ "qmh", "Reserved for local use" },
+	{ "qmi", "Reserved for local use" },
+	{ "qmj", "Reserved for local use" },
+	{ "qmk", "Reserved for local use" },
+	{ "qml", "Reserved for local use" },
+	{ "qmm", "Reserved for local use" },
+	{ "qmn", "Reserved for local use" },
+	{ "qmo", "Reserved for local use" },
+	{ "qmp", "Reserved for local use" },
+	{ "qmq", "Reserved for local use" },
+	{ "qmr", "Reserved for local use" },
+	{ "qms", "Reserved for local use" },
+	{ "qmt", "Reserved for local use" },
+	{ "qmu", "Reserved for local use" },
+	{ "qmv", "Reserved for local use" },
+	{ "qmw", "Reserved for local use" },
+	{ "qmx", "Reserved for local use" },
+	{ "qmy", "Reserved for local use" },
+	{ "qmz", "Reserved for local use" },
+	{ "qna", "Reserved for local use" },
+	{ "qnb", "Reserved for local use" },
+	{ "qnc", "Reserved for local use" },
+	{ "qnd", "Reserved for local use" },
+	{ "qne", "Reserved for local use" },
+	{ "qnf", "Reserved for local use" },
+	{ "qng", "Reserved for local use" },
+	{ "qnh", "Reserved for local use" },
+	{ "qni", "Reserved for local use" },
+	{ "qnj", "Reserved for local use" },
+	{ "qnk", "Reserved for local use" },
+	{ "qnl", "Reserved for local use" },
+	{ "qnm", "Reserved for local use" },
+	{ "qnn", "Reserved for local use" },
+	{ "qno", "Reserved for local use" },
+	{ "qnp", "Reserved for local use" },
+	{ "qnq", "Reserved for local use" },
+	{ "qnr", "Reserved for local use" },
+	{ "qns", "Reserved for local use" },
+	{ "qnt", "Reserved for local use" },
+	{ "qnu", "Reserved for local use" },
+	{ "qnv", "Reserved for local use" },
+	{ "qnw", "Reserved for local use" },
+	{ "qnx", "Reserved for local use" },
+	{ "qny", "Reserved for local use" },
+	{ "qnz", "Reserved for local use" },
+	{ "qoa", "Reserved for local use" },
+	{ "qob", "Reserved for local use" },
+	{ "qoc", "Reserved for local use" },
+	{ "qod", "Reserved for local use" },
+	{ "qoe", "Reserved for local use" },
+	{ "qof", "Reserved for local use" },
+	{ "qog", "Reserved for local use" },
+	{ "qoh", "Reserved for local use" },
+	{ "qoi", "Reserved for local use" },
+	{ "qoj", "Reserved for local use" },
+	{ "qok", "Reserved for local use" },
+	{ "qol", "Reserved for local use" },
+	{ "qom", "Reserved for local use" },
+	{ "qon", "Reserved for local use" },
+	{ "qoo", "Reserved for local use" },
+	{ "qop", "Reserved for local use" },
+	{ "qoq", "Reserved for local use" },
+	{ "qor", "Reserved for local use" },
+	{ "qos", "Reserved for local use" },
+	{ "qot", "Reserved for local use" },
+	{ "qou", "Reserved for local use" },
+	{ "qov", "Reserved for local use" },
+	{ "qow", "Reserved for local use" },
+	{ "qox", "Reserved for local use" },
+	{ "qoy", "Reserved for local use" },
+	{ "qoz", "Reserved for local use" },
+	{ "qpa", "Reserved for local use" },
+	{ "qpb", "Reserved for local use" },
+	{ "qpc", "Reserved for local use" },
+	{ "qpd", "Reserved for local use" },
+	{ "qpe", "Reserved for local use" },
+	{ "qpf", "Reserved for local use" },
+	{ "qpg", "Reserved for local use" },
+	{ "qph", "Reserved for local use" },
+	{ "qpi", "Reserved for local use" },
+	{ "qpj", "Reserved for local use" },
+	{ "qpk", "Reserved for local use" },
+	{ "qpl", "Reserved for local use" },
+	{ "qpm", "Reserved for local use" },
+	{ "qpn", "Reserved for local use" },
+	{ "qpo", "Reserved for local use" },
+	{ "qpp", "Reserved for local use" },
+	{ "qpq", "Reserved for local use" },
+	{ "qpr", "Reserved for local use" },
+	{ "qps", "Reserved for local use" },
+	{ "qpt", "Reserved for local use" },
+	{ "qpu", "Reserved for local use" },
+	{ "qpv", "Reserved for local use" },
+	{ "qpw", "Reserved for local use" },
+	{ "qpx", "Reserved for local use" },
+	{ "qpy", "Reserved for local use" },
+	{ "qpz", "Reserved for local use" },
+	{ "qqa", "Reserved for local use" },
+	{ "qqb", "Reserved for local use" },
+	{ "qqc", "Reserved for local use" },
+	{ "qqd", "Reserved for local use" },
+	{ "qqe", "Reserved for local use" },
+	{ "qqf", "Reserved for local use" },
+	{ "qqg", "Reserved for local use" },
+	{ "qqh", "Reserved for local use" },
+	{ "qqi", "Reserved for local use" },
+	{ "qqj", "Reserved for local use" },
+	{ "qqk", "Reserved for local use" },
+	{ "qql", "Reserved for local use" },
+	{ "qqm", "Reserved for local use" },
+	{ "qqn", "Reserved for local use" },
+	{ "qqo", "Reserved for local use" },
+	{ "qqp", "Reserved for local use" },
+	{ "qqq", "Reserved for local use" },
+	{ "qqr", "Reserved for local use" },
+	{ "qqs", "Reserved for local use" },
+	{ "qqt", "Reserved for local use" },
+	{ "qqu", "Reserved for local use" },
+	{ "qqv", "Reserved for local use" },
+	{ "qqw", "Reserved for local use" },
+	{ "qqx", "Reserved for local use" },
+	{ "qqy", "Reserved for local use" },
+	{ "qqz", "Reserved for local use" },
+	{ "qra", "Reserved for local use" },
+	{ "qrb", "Reserved for local use" },
+	{ "qrc", "Reserved for local use" },
+	{ "qrd", "Reserved for local use" },
+	{ "qre", "Reserved for local use" },
+	{ "qrf", "Reserved for local use" },
+	{ "qrg", "Reserved for local use" },
+	{ "qrh", "Reserved for local use" },
+	{ "qri", "Reserved for local use" },
+	{ "qrj", "Reserved for local use" },
+	{ "qrk", "Reserved for local use" },
+	{ "qrl", "Reserved for local use" },
+	{ "qrm", "Reserved for local use" },
+	{ "qrn", "Reserved for local use" },
+	{ "qro", "Reserved for local use" },
+	{ "qrp", "Reserved for local use" },
+	{ "qrq", "Reserved for local use" },
+	{ "qrr", "Reserved for local use" },
+	{ "qrs", "Reserved for local use" },
+	{ "qrt", "Reserved for local use" },
+	{ "qru", "Reserved for local use" },
+	{ "qrv", "Reserved for local use" },
+	{ "qrw", "Reserved for local use" },
+	{ "qrx", "Reserved for local use" },
+	{ "qry", "Reserved for local use" },
+	{ "qrz", "Reserved for local use" },
+	{ "qsa", "Reserved for local use" },
+	{ "qsb", "Reserved for local use" },
+	{ "qsc", "Reserved for local use" },
+	{ "qsd", "Reserved for local use" },
+	{ "qse", "Reserved for local use" },
+	{ "qsf", "Reserved for local use" },
+	{ "qsg", "Reserved for local use" },
+	{ "qsh", "Reserved for local use" },
+	{ "qsi", "Reserved for local use" },
+	{ "qsj", "Reserved for local use" },
+	{ "qsk", "Reserved for local use" },
+	{ "qsl", "Reserved for local use" },
+	{ "qsm", "Reserved for local use" },
+	{ "qsn", "Reserved for local use" },
+	{ "qso", "Reserved for local use" },
+	{ "qsp", "Reserved for local use" },
+	{ "qsq", "Reserved for local use" },
+	{ "qsr", "Reserved for local use" },
+	{ "qss", "Reserved for local use" },
+	{ "qst", "Reserved for local use" },
+	{ "qsu", "Reserved for local use" },
+	{ "qsv", "Reserved for local use" },
+	{ "qsw", "Reserved for local use" },
+	{ "qsx", "Reserved for local use" },
+	{ "qsy", "Reserved for local use" },
+	{ "qsz", "Reserved for local use" },
+	{ "qta", "Reserved for local use" },
+	{ "qtb", "Reserved for local use" },
+	{ "qtc", "Reserved for local use" },
+	{ "qtd", "Reserved for local use" },
+	{ "qte", "Reserved for local use" },
+	{ "qtf", "Reserved for local use" },
+	{ "qtg", "Reserved for local use" },
+	{ "qth", "Reserved for local use" },
+	{ "qti", "Reserved for local use" },
+	{ "qtj", "Reserved for local use" },
+	{ "qtk", "Reserved for local use" },
+	{ "qtl", "Reserved for local use" },
+	{ "qtm", "Reserved for local use" },
+	{ "qtn", "Reserved for local use" },
+	{ "qto", "Reserved for local use" },
+	{ "qtp", "Reserved for local use" },
+	{ "qtq", "Reserved for local use" },
+	{ "qtr", "Reserved for local use" },
+	{ "qts", "Reserved for local use" },
+	{ "qtt", "Reserved for local use" },
+	{ "qtu", "Reserved for local use" },
+	{ "qtv", "Reserved for local use" },
+	{ "qtw", "Reserved for local use" },
+	{ "qtx", "Reserved for local use" },
+	{ "qty", "Reserved for local use" },
+	{ "qtz", "Reserved for local use" },
+	{ "qua", "Quapaw" },
+	{ "qub", "Huallaga Huánuco Quechua" },
+	{ "quc", "K'iche'" },
+	{ "qud", "Calderón Highland Quichua" },
+	{ "que", "Quechua" },
+	{ "quf", "Lambayeque Quechua" },
+	{ "qug", "Chimborazo Highland Quichua" },
+	{ "quh", "South Bolivian Quechua" },
+	{ "qui", "Quileute" },
+	{ "quk", "Chachapoyas Quechua" },
+	{ "qul", "North Bolivian Quechua" },
+	{ "qum", "Sipacapense" },
+	{ "qun", "Quinault" },
+	{ "qup", "Southern Pastaza Quechua" },
+	{ "quq", "Quinqui" },
+	{ "qur", "Yanahuanca Pasco Quechua" },
+	{ "qus", "Santiago del Estero Quichua" },
+	{ "quv", "Sacapulteco" },
+	{ "quw", "Tena Lowland Quichua" },
+	{ "qux", "Yauyos Quechua" },
+	{ "quy", "Ayacucho Quechua" },
+	{ "quz", "Cusco Quechua" },
+	{ "qva", "Ambo-Pasco Quechua" },
+	{ "qvc", "Cajamarca Quechua" },
+	{ "qve", "Eastern Apurímac Quechua" },
+	{ "qvh", "Huamalíes-Dos de Mayo Huánuco Quechua" },
+	{ "qvi", "Imbabura Highland Quichua" },
+	{ "qvj", "Loja Highland Quichua" },
+	{ "qvl", "Cajatambo North Lima Quechua" },
+	{ "qvm", "Margos-Yarowilca-Lauricocha Quechua" },
+	{ "qvn", "North Junín Quechua" },
+	{ "qvo", "Napo Lowland Quechua" },
+	{ "qvp", "Pacaraos Quechua" },
+	{ "qvs", "San Martín Quechua" },
+	{ "qvw", "Huaylla Wanca Quechua" },
+	{ "qvy", "Queyu" },
+	{ "qvz", "Northern Pastaza Quichua" },
+	{ "qwa", "Corongo Ancash Quechua" },
+	{ "qwc", "Classical Quechua" },
+	{ "qwh", "Huaylas Ancash Quechua" },
+	{ "qwm", "Kuman (Russia)" },
+	{ "qws", "Sihuas Ancash Quechua" },
+	{ "qwt", "Kwalhioqua-Tlatskanai" },
+	{ "qxa", "Chiquián Ancash Quechua" },
+	{ "qxc", "Chincha Quechua" },
+	{ "qxh", "Panao Huánuco Quechua" },
+	{ "qxl", "Salasaca Highland Quichua" },
+	{ "qxn", "Northern Conchucos Ancash Quechua" },
+	{ "qxo", "Southern Conchucos Ancash Quechua" },
+	{ "qxp", "Puno Quechua" },
+	{ "qxq", "Qashqa'i" },
+	{ "qxr", "Cañar Highland Quichua" },
+	{ "qxs", "Southern Qiang" },
+	{ "qxt", "Santa Ana de Tusi Pasco Quechua" },
+	{ "qxu", "Arequipa-La Unión Quechua" },
+	{ "qxw", "Jauja Wanca Quechua" },
+	{ "qya", "Quenya" },
+	{ "qyp", "Quiripi" },
+	{ "raa", "Dungmali" },
+	{ "rab", "Camling" },
+	{ "rac", "Rasawa" },
+	{ "rad", "Rade" },
+	{ "raf", "Western Meohang" },
+	{ "rag", "Logooli" },
+	{ "rah", "Rabha" },
+	{ "rai", "Ramoaaina" },
+	{ "raj", "Rajasthani" },
+	{ "rak", "Tulu-Bohuai" },
+	{ "ral", "Ralte" },
+	{ "ram", "Canela" },
+	{ "ran", "Riantana" },
+	{ "rao", "Rao" },
+	{ "rap", "Rapanui" },
+	{ "raq", "Saam" },
+	{ "rar", "Rarotongan" },
+	{ "ras", "Tegali" },
+	{ "rat", "Razajerdi" },
+	{ "rau", "Raute" },
+	{ "rav", "Sampang" },
+	{ "raw", "Rawang" },
+	{ "rax", "Rang" },
+	{ "ray", "Rapa" },
+	{ "raz", "Rahambuu" },
+	{ "rbb", "Rumai Palaung" },
+	{ "rbk", "Northern Bontok" },
+	{ "rbl", "Miraya Bikol" },
+	{ "rbp", "Barababaraba" },
+	{ "rcf", "Réunion Creole French" },
+	{ "rdb", "Rudbari" },
+	{ "rea", "Rerau" },
+	{ "reb", "Rembong" },
+	{ "ree", "Rejang Kayan" },
+	{ "reg", "Kara (Tanzania)" },
+	{ "rei", "Reli" },
+	{ "rej", "Rejang" },
+	{ "rel", "Rendille" },
+	{ "rem", "Remo" },
+	{ "ren", "Rengao" },
+	{ "rer", "Rer Bare" },
+	{ "res", "Reshe" },
+	{ "ret", "Retta" },
+	{ "rey", "Reyesano" },
+	{ "rga", "Roria" },
+	{ "rge", "Romano-Greek" },
+	{ "rgk", "Rangkas" },
+	{ "rgn", "Romagnol" },
+	{ "rgr", "Resígaro" },
+	{ "rgs", "Southern Roglai" },
+	{ "rgu", "Ringgou" },
+	{ "rhg", "Rohingya" },
+	{ "rhp", "Yahang" },
+	{ "ria", "Riang (India)" },
+	{ "rie", "Rien" },
+	{ "rif", "Tarifit" },
+	{ "ril", "Riang (Myanmar)" },
+	{ "rim", "Nyaturu" },
+	{ "rin", "Nungu" },
+	{ "rir", "Ribun" },
+	{ "rit", "Ritarungo" },
+	{ "riu", "Riung" },
+	{ "rjg", "Rajong" },
+	{ "rji", "Raji" },
+	{ "rjs", "Rajbanshi" },
+	{ "rka", "Kraol" },
+	{ "rkb", "Rikbaktsa" },
+	{ "rkh", "Rakahanga-Manihiki" },
+	{ "rki", "Rakhine" },
+	{ "rkm", "Marka" },
+	{ "rkt", "Rangpuri" },
+	{ "rkw", "Arakwal" },
+	{ "rma", "Rama" },
+	{ "rmb", "Rembarunga" },
+	{ "rmc", "Carpathian Romani" },
+	{ "rmd", "Traveller Danish" },
+	{ "rme", "Angloromani" },
+	{ "rmf", "Kalo Finnish Romani" },
+	{ "rmg", "Traveller Norwegian" },
+	{ "rmh", "Murkim" },
+	{ "rmi", "Lomavren" },
+	{ "rmk", "Romkun" },
+	{ "rml", "Baltic Romani" },
+	{ "rmm", "Roma" },
+	{ "rmn", "Balkan Romani" },
+	{ "rmo", "Sinte Romani" },
+	{ "rmp", "Rempi" },
+	{ "rmq", "Caló" },
+	{ "rms", "Romanian Sign Language" },
+	{ "rmt", "Domari" },
+	{ "rmu", "Tavringer Romani" },
+	{ "rmv", "Romanova" },
+	{ "rmw", "Welsh Romani" },
+	{ "rmx", "Romam" },
+	{ "rmy", "Vlax Romani" },
+	{ "rmz", "Marma" },
+	{ "rna", "Runa" },
+	{ "rnd", "Ruund" },
+	{ "rng", "Ronga" },
+	{ "rnl", "Ranglong" },
+	{ "rnn", "Roon" },
+	{ "rnp", "Rongpo" },
+	{ "rnr", "Nari Nari" },
+	{ "rnw", "Rungwa" },
+	{ "rob", "Tae'" },
+	{ "roc", "Cacgia Roglai" },
+	{ "rod", "Rogo" },
+	{ "roe", "Ronji" },
+	{ "rof", "Rombo" },
+	{ "rog", "Northern Roglai" },
+	{ "roh", "Romansh" },
+	{ "rol", "Romblomanon" },
+	{ "rom", "Romany" },
+	{ "ron", "Romanian" },
+	{ "roo", "Rotokas" },
+	{ "rop", "Kriol" },
+	{ "ror", "Rongga" },
+	{ "rou", "Runga" },
+	{ "row", "Dela-Oenale" },
+	{ "rpn", "Repanbitip" },
+	{ "rpt", "Rapting" },
+	{ "rri", "Ririo" },
+	{ "rro", "Waima" },
+	{ "rrt", "Arritinngithigh" },
+	{ "rsb", "Romano-Serbian" },
+	{ "rsi", "Rennellese Sign Language" },
+	{ "rsl", "Russian Sign Language" },
+	{ "rtc", "Rungtu Chin" },
+	{ "rth", "Ratahan" },
+	{ "rtm", "Rotuman" },
+	{ "rtw", "Rathawi" },
+	{ "rub", "Gungu" },
+	{ "ruc", "Ruuli" },
+	{ "rue", "Rusyn" },
+	{ "ruf", "Luguru" },
+	{ "rug", "Roviana" },
+	{ "ruh", "Ruga" },
+	{ "rui", "Rufiji" },
+	{ "ruk", "Che" },
+	{ "run", "Rundi" },
+	{ "ruo", "Istro Romanian" },
+	{ "rup", "Macedo-Romanian" },
+	{ "ruq", "Megleno Romanian" },
+	{ "rus", "Russian" },
+	{ "rut", "Rutul" },
+	{ "ruu", "Lanas Lobu" },
+	{ "ruy", "Mala (Nigeria)" },
+	{ "ruz", "Ruma" },
+	{ "rwa", "Rawo" },
+	{ "rwk", "Rwa" },
+	{ "rwm", "Amba (Uganda)" },
+	{ "rwo", "Rawa" },
+	{ "rwr", "Marwari (India)" },
+	{ "rxd", "Ngardi" },
+	{ "rxw", "Karuwali" },
+	{ "ryn", "Northern Amami-Oshima" },
+	{ "rys", "Yaeyama" },
+	{ "ryu", "Central Okinawan" },
+	{ "saa", "Saba" },
+	{ "sab", "Buglere" },
+	{ "sac", "Meskwaki" },
+	{ "sad", "Sandawe" },
+	{ "sae", "Sabanê" },
+	{ "saf", "Safaliba" },
+	{ "sag", "Sango" },
+	{ "sah", "Yakut" },
+	{ "saj", "Sahu" },
+	{ "sak", "Sake" },
+	{ "sam", "Samaritan Aramaic" },
+	{ "san", "Sanskrit" },
+	{ "sao", "Sause" },
+	{ "sap", "Sanapaná" },
+	{ "saq", "Samburu" },
+	{ "sar", "Saraveca" },
+	{ "sas", "Sasak" },
+	{ "sat", "Santali" },
+	{ "sau", "Saleman" },
+	{ "sav", "Saafi-Saafi" },
+	{ "saw", "Sawi" },
+	{ "sax", "Sa" },
+	{ "say", "Saya" },
+	{ "saz", "Saurashtra" },
+	{ "sba", "Ngambay" },
+	{ "sbb", "Simbo" },
+	{ "sbc", "Kele (Papua New Guinea)" },
+	{ "sbd", "Southern Samo" },
+	{ "sbe", "Saliba" },
+	{ "sbf", "Shabo" },
+	{ "sbg", "Seget" },
+	{ "sbh", "Sori-Harengan" },
+	{ "sbi", "Seti" },
+	{ "sbj", "Surbakhal" },
+	{ "sbk", "Safwa" },
+	{ "sbl", "Botolan Sambal" },
+	{ "sbm", "Sagala" },
+	{ "sbn", "Sindhi Bhil" },
+	{ "sbo", "Sabüm" },
+	{ "sbp", "Sangu (Tanzania)" },
+	{ "sbq", "Sileibi" },
+	{ "sbr", "Sembakung Murut" },
+	{ "sbs", "Subiya" },
+	{ "sbt", "Kimki" },
+	{ "sbu", "Stod Bhoti" },
+	{ "sbv", "Sabine" },
+	{ "sbw", "Simba" },
+	{ "sbx", "Seberuang" },
+	{ "sby", "Soli" },
+	{ "sbz", "Sara Kaba" },
+	{ "scb", "Chut" },
+	{ "sce", "Dongxiang" },
+	{ "scf", "San Miguel Creole French" },
+	{ "scg", "Sanggau" },
+	{ "sch", "Sakachep" },
+	{ "sci", "Sri Lankan Creole Malay" },
+	{ "sck", "Sadri" },
+	{ "scl", "Shina" },
+	{ "scn", "Sicilian" },
+	{ "sco", "Scots" },
+	{ "scp", "Helambu Sherpa" },
+	{ "scq", "Sa'och" },
+	{ "scs", "North Slavey" },
+	{ "scu", "Shumcho" },
+	{ "scv", "Sheni" },
+	{ "scw", "Sha" },
+	{ "scx", "Sicel" },
+	{ "sda", "Toraja-Sa'dan" },
+	{ "sdb", "Shabak" },
+	{ "sdc", "Sassarese Sardinian" },
+	{ "sde", "Surubu" },
+	{ "sdf", "Sarli" },
+	{ "sdg", "Savi" },
+	{ "sdh", "Southern Kurdish" },
+	{ "sdj", "Suundi" },
+	{ "sdk", "Sos Kundi" },
+	{ "sdl", "Saudi Arabian Sign Language" },
+	{ "sdm", "Semandang" },
+	{ "sdn", "Gallurese Sardinian" },
+	{ "sdo", "Bukar-Sadung Bidayuh" },
+	{ "sdp", "Sherdukpen" },
+	{ "sdr", "Oraon Sadri" },
+	{ "sds", "Sened" },
+	{ "sdt", "Shuadit" },
+	{ "sdu", "Sarudu" },
+	{ "sdx", "Sibu Melanau" },
+	{ "sdz", "Sallands" },
+	{ "sea", "Semai" },
+	{ "seb", "Shempire Senoufo" },
+	{ "sec", "Sechelt" },
+	{ "sed", "Sedang" },
+	{ "see", "Seneca" },
+	{ "sef", "Cebaara Senoufo" },
+	{ "seg", "Segeju" },
+	{ "seh", "Sena" },
+	{ "sei", "Seri" },
+	{ "sej", "Sene" },
+	{ "sek", "Sekani" },
+	{ "sel", "Selkup" },
+	{ "sen", "Nanerigé Sénoufo" },
+	{ "seo", "Suarmin" },
+	{ "sep", "Sìcìté Sénoufo" },
+	{ "seq", "Senara Sénoufo" },
+	{ "ser", "Serrano" },
+	{ "ses", "Koyraboro Senni Songhai" },
+	{ "set", "Sentani" },
+	{ "seu", "Serui-Laut" },
+	{ "sev", "Nyarafolo Senoufo" },
+	{ "sew", "Sewa Bay" },
+	{ "sey", "Secoya" },
+	{ "sez", "Senthang Chin" },
+	{ "sfb", "Langue des signes de Belgique Francophone" },
+	{ "sfe", "Eastern Subanen" },
+	{ "sfm", "Small Flowery Miao" },
+	{ "sfs", "South African Sign Language" },
+	{ "sfw", "Sehwi" },
+	{ "sga", "Old Irish (to 900)" },
+	{ "sgb", "Mag-antsi Ayta" },
+	{ "sgc", "Kipsigis" },
+	{ "sgd", "Surigaonon" },
+	{ "sge", "Segai" },
+	{ "sgg", "Swiss-German Sign Language" },
+	{ "sgh", "Shughni" },
+	{ "sgi", "Suga" },
+	{ "sgj", "Surgujia" },
+	{ "sgk", "Sangkong" },
+	{ "sgm", "Singa" },
+	{ "sgo", "Songa" },
+	{ "sgp", "Singpho" },
+	{ "sgr", "Sangisari" },
+	{ "sgs", "Samogitian" },
+	{ "sgt", "Brokpake" },
+	{ "sgu", "Salas" },
+	{ "sgw", "Sebat Bet Gurage" },
+	{ "sgx", "Sierra Leone Sign Language" },
+	{ "sgy", "Sanglechi" },
+	{ "sgz", "Sursurunga" },
+	{ "sha", "Shall-Zwall" },
+	{ "shb", "Ninam" },
+	{ "shc", "Sonde" },
+	{ "shd", "Kundal Shahi" },
+	{ "she", "Sheko" },
+	{ "shg", "Shua" },
+	{ "shh", "Shoshoni" },
+	{ "shi", "Tachelhit" },
+	{ "shj", "Shatt" },
+	{ "shk", "Shilluk" },
+	{ "shl", "Shendu" },
+	{ "shm", "Shahrudi" },
+	{ "shn", "Shan" },
+	{ "sho", "Shanga" },
+	{ "shp", "Shipibo-Conibo" },
+	{ "shq", "Sala" },
+	{ "shr", "Shi" },
+	{ "shs", "Shuswap" },
+	{ "sht", "Shasta" },
+	{ "shu", "Chadian Arabic" },
+	{ "shv", "Shehri" },
+	{ "shw", "Shwai" },
+	{ "shx", "She" },
+	{ "shy", "Tachawit" },
+	{ "shz", "Syenara Senoufo" },
+	{ "sia", "Akkala Sami" },
+	{ "sib", "Sebop" },
+	{ "sid", "Sidamo" },
+	{ "sie", "Simaa" },
+	{ "sif", "Siamou" },
+	{ "sig", "Paasaal" },
+	{ "sih", "Zire" },
+	{ "sii", "Shom Peng" },
+	{ "sij", "Numbami" },
+	{ "sik", "Sikiana" },
+	{ "sil", "Tumulung Sisaala" },
+	{ "sim", "Mende (Papua New Guinea)" },
+	{ "sin", "Sinhala" },
+	{ "sip", "Sikkimese" },
+	{ "siq", "Sonia" },
+	{ "sir", "Siri" },
+	{ "sis", "Siuslaw" },
+	{ "siu", "Sinagen" },
+	{ "siv", "Sumariup" },
+	{ "siw", "Siwai" },
+	{ "six", "Sumau" },
+	{ "siy", "Sivandi" },
+	{ "siz", "Siwi" },
+	{ "sja", "Epena" },
+	{ "sjb", "Sajau Basap" },
+	{ "sjd", "Kildin Sami" },
+	{ "sje", "Pite Sami" },
+	{ "sjg", "Assangori" },
+	{ "sjk", "Kemi Sami" },
+	{ "sjl", "Sajalong" },
+	{ "sjm", "Mapun" },
+	{ "sjn", "Sindarin" },
+	{ "sjo", "Xibe" },
+	{ "sjp", "Surjapuri" },
+	{ "sjr", "Siar-Lak" },
+	{ "sjs", "Senhaja De Srair" },
+	{ "sjt", "Ter Sami" },
+	{ "sju", "Ume Sami" },
+	{ "sjw", "Shawnee" },
+	{ "ska", "Skagit" },
+	{ "skb", "Saek" },
+	{ "skc", "Ma Manda" },
+	{ "skd", "Southern Sierra Miwok" },
+	{ "ske", "Seke (Vanuatu)" },
+	{ "skf", "Sakirabiá" },
+	{ "skg", "Sakalava Malagasy" },
+	{ "skh", "Sikule" },
+	{ "ski", "Sika" },
+	{ "skj", "Seke (Nepal)" },
+	{ "skk", "Sok" },
+	{ "skm", "Kutong" },
+	{ "skn", "Kolibugan Subanon" },
+	{ "sko", "Seko Tengah" },
+	{ "skp", "Sekapan" },
+	{ "skq", "Sininkere" },
+	{ "skr", "Seraiki" },
+	{ "sks", "Maia" },
+	{ "skt", "Sakata" },
+	{ "sku", "Sakao" },
+	{ "skv", "Skou" },
+	{ "skw", "Skepi Creole Dutch" },
+	{ "skx", "Seko Padang" },
+	{ "sky", "Sikaiana" },
+	{ "skz", "Sekar" },
+	{ "slc", "Sáliba" },
+	{ "sld", "Sissala" },
+	{ "sle", "Sholaga" },
+	{ "slf", "Swiss-Italian Sign Language" },
+	{ "slg", "Selungai Murut" },
+	{ "slh", "Southern Puget Sound Salish" },
+	{ "sli", "Lower Silesian" },
+	{ "slj", "Salumá" },
+	{ "slk", "Slovak" },
+	{ "sll", "Salt-Yui" },
+	{ "slm", "Pangutaran Sama" },
+	{ "sln", "Salinan" },
+	{ "slp", "Lamaholot" },
+	{ "slq", "Salchuq" },
+	{ "slr", "Salar" },
+	{ "sls", "Singapore Sign Language" },
+	{ "slt", "Sila" },
+	{ "slu", "Selaru" },
+	{ "slv", "Slovenian" },
+	{ "slw", "Sialum" },
+	{ "slx", "Salampasu" },
+	{ "sly", "Selayar" },
+	{ "slz", "Ma'ya" },
+	{ "sma", "Southern Sami" },
+	{ "smb", "Simbari" },
+	{ "smc", "Som" },
+	{ "smd", "Sama" },
+	{ "sme", "Northern Sami" },
+	{ "smf", "Auwe" },
+	{ "smg", "Simbali" },
+	{ "smh", "Samei" },
+	{ "smj", "Lule Sami" },
+	{ "smk", "Bolinao" },
+	{ "sml", "Central Sama" },
+	{ "smm", "Musasa" },
+	{ "smn", "Inari Sami" },
+	{ "smo", "Samoan" },
+	{ "smp", "Samaritan" },
+	{ "smq", "Samo" },
+	{ "smr", "Simeulue" },
+	{ "sms", "Skolt Sami" },
+	{ "smt", "Simte" },
+	{ "smu", "Somray" },
+	{ "smv", "Samvedi" },
+	{ "smw", "Sumbawa" },
+	{ "smx", "Samba" },
+	{ "smy", "Semnani" },
+	{ "smz", "Simeku" },
+	{ "sna", "Shona" },
+	{ "snb", "Sebuyau" },
+	{ "snc", "Sinaugoro" },
+	{ "snd", "Sindhi" },
+	{ "sne", "Bau Bidayuh" },
+	{ "snf", "Noon" },
+	{ "sng", "Sanga (Democratic Republic of Congo)" },
+	{ "snh", "Shinabo" },
+	{ "sni", "Sensi" },
+	{ "snj", "Riverain Sango" },
+	{ "snk", "Soninke" },
+	{ "snl", "Sangil" },
+	{ "snm", "Southern Ma'di" },
+	{ "snn", "Siona" },
+	{ "sno", "Snohomish" },
+	{ "snp", "Siane" },
+	{ "snq", "Sangu (Gabon)" },
+	{ "snr", "Sihan" },
+	{ "sns", "South West Bay" },
+	{ "snu", "Senggi" },
+	{ "snv", "Sa'ban" },
+	{ "snw", "Selee" },
+	{ "snx", "Sam" },
+	{ "sny", "Saniyo-Hiyewe" },
+	{ "snz", "Sinsauru" },
+	{ "soa", "Thai Song" },
+	{ "sob", "Sobei" },
+	{ "soc", "So (Democratic Republic of Congo)" },
+	{ "sod", "Songoora" },
+	{ "soe", "Songomeno" },
+	{ "sog", "Sogdian" },
+	{ "soh", "Aka" },
+	{ "soi", "Sonha" },
+	{ "soj", "Soi" },
+	{ "sok", "Sokoro" },
+	{ "sol", "Solos" },
+	{ "som", "Somali" },
+	{ "soo", "Songo" },
+	{ "sop", "Songe" },
+	{ "soq", "Kanasi" },
+	{ "sor", "Somrai" },
+	{ "sos", "Seeku" },
+	{ "sot", "Southern Sotho" },
+	{ "sou", "Southern Thai" },
+	{ "sov", "Sonsorol" },
+	{ "sow", "Sowanda" },
+	{ "sox", "Swo" },
+	{ "soy", "Miyobe" },
+	{ "soz", "Temi" },
+	{ "spa", "Spanish" },
+	{ "spb", "Sepa (Indonesia)" },
+	{ "spc", "Sapé" },
+	{ "spd", "Saep" },
+	{ "spe", "Sepa (Papua New Guinea)" },
+	{ "spg", "Sian" },
+	{ "spi", "Saponi" },
+	{ "spk", "Sengo" },
+	{ "spl", "Selepet" },
+	{ "spm", "Akukem" },
+	{ "spo", "Spokane" },
+	{ "spp", "Supyire Senoufo" },
+	{ "spq", "Loreto-Ucayali Spanish" },
+	{ "spr", "Saparua" },
+	{ "sps", "Saposa" },
+	{ "spt", "Spiti Bhoti" },
+	{ "spu", "Sapuan" },
+	{ "spv", "Sambalpuri" },
+	{ "spx", "South Picene" },
+	{ "spy", "Sabaot" },
+	{ "sqa", "Shama-Sambuga" },
+	{ "sqh", "Shau" },
+	{ "sqi", "Albanian" },
+	{ "sqk", "Albanian Sign Language" },
+	{ "sqm", "Suma" },
+	{ "sqn", "Susquehannock" },
+	{ "sqo", "Sorkhei" },
+	{ "sqq", "Sou" },
+	{ "sqr", "Siculo Arabic" },
+	{ "sqs", "Sri Lankan Sign Language" },
+	{ "sqt", "Soqotri" },
+	{ "squ", "Squamish" },
+	{ "sra", "Saruga" },
+	{ "srb", "Sora" },
+	{ "src", "Logudorese Sardinian" },
+	{ "srd", "Sardinian" },
+	{ "sre", "Sara" },
+	{ "srf", "Nafi" },
+	{ "srg", "Sulod" },
+	{ "srh", "Sarikoli" },
+	{ "sri", "Siriano" },
+	{ "srk", "Serudung Murut" },
+	{ "srl", "Isirawa" },
+	{ "srm", "Saramaccan" },
+	{ "srn", "Sranan Tongo" },
+	{ "sro", "Campidanese Sardinian" },
+	{ "srp", "Serbian" },
+	{ "srq", "Sirionó" },
+	{ "srr", "Serer" },
+	{ "srs", "Sarsi" },
+	{ "srt", "Sauri" },
+	{ "sru", "Suruí" },
+	{ "srv", "Southern Sorsoganon" },
+	{ "srw", "Serua" },
+	{ "srx", "Sirmauri" },
+	{ "sry", "Sera" },
+	{ "srz", "Shahmirzadi" },
+	{ "ssb", "Southern Sama" },
+	{ "ssc", "Suba-Simbiti" },
+	{ "ssd", "Siroi" },
+	{ "sse", "Balangingi" },
+	{ "ssf", "Thao" },
+	{ "ssg", "Seimat" },
+	{ "ssh", "Shihhi Arabic" },
+	{ "ssi", "Sansi" },
+	{ "ssj", "Sausi" },
+	{ "ssk", "Sunam" },
+	{ "ssl", "Western Sisaala" },
+	{ "ssm", "Semnam" },
+	{ "ssn", "Waata" },
+	{ "sso", "Sissano" },
+	{ "ssp", "Spanish Sign Language" },
+	{ "ssq", "So'a" },
+	{ "ssr", "Swiss-French Sign Language" },
+	{ "sss", "Sô" },
+	{ "sst", "Sinasina" },
+	{ "ssu", "Susuami" },
+	{ "ssv", "Shark Bay" },
+	{ "ssw", "Swati" },
+	{ "ssx", "Samberigi" },
+	{ "ssy", "Saho" },
+	{ "ssz", "Sengseng" },
+	{ "sta", "Settla" },
+	{ "stb", "Northern Subanen" },
+	{ "std", "Sentinel" },
+	{ "ste", "Liana-Seti" },
+	{ "stf", "Seta" },
+	{ "stg", "Trieng" },
+	{ "sth", "Shelta" },
+	{ "sti", "Bulo Stieng" },
+	{ "stj", "Matya Samo" },
+	{ "stk", "Arammba" },
+	{ "stl", "Stellingwerfs" },
+	{ "stm", "Setaman" },
+	{ "stn", "Owa" },
+	{ "sto", "Stoney" },
+	{ "stp", "Southeastern Tepehuan" },
+	{ "stq", "Saterfriesisch" },
+	{ "str", "Straits Salish" },
+	{ "sts", "Shumashti" },
+	{ "stt", "Budeh Stieng" },
+	{ "stu", "Samtao" },
+	{ "stv", "Silt'e" },
+	{ "stw", "Satawalese" },
+	{ "sty", "Siberian Tatar" },
+	{ "sua", "Sulka" },
+	{ "sub", "Suku" },
+	{ "suc", "Western Subanon" },
+	{ "sue", "Suena" },
+	{ "sug", "Suganga" },
+	{ "sui", "Suki" },
+	{ "suj", "Shubi" },
+	{ "suk", "Sukuma" },
+	{ "sun", "Sundanese" },
+	{ "suq", "Suri" },
+	{ "sur", "Mwaghavul" },
+	{ "sus", "Susu" },
+	{ "sut", "Subtiaba" },
+	{ "suv", "Puroik" },
+	{ "suw", "Sumbwa" },
+	{ "sux", "Sumerian" },
+	{ "suy", "Suyá" },
+	{ "suz", "Sunwar" },
+	{ "sva", "Svan" },
+	{ "svb", "Ulau-Suain" },
+	{ "svc", "Vincentian Creole English" },
+	{ "sve", "Serili" },
+	{ "svk", "Slovakian Sign Language" },
+	{ "svm", "Slavomolisano" },
+	{ "svr", "Savara" },
+	{ "svs", "Savosavo" },
+	{ "svx", "Skalvian" },
+	{ "swa", "Swahili (macrolanguage)" },
+	{ "swb", "Maore Comorian" },
+	{ "swc", "Congo Swahili" },
+	{ "swe", "Swedish" },
+	{ "swf", "Sere" },
+	{ "swg", "Swabian" },
+	{ "swh", "Swahili (individual language)" },
+	{ "swi", "Sui" },
+	{ "swj", "Sira" },
+	{ "swk", "Malawi Sena" },
+	{ "swl", "Swedish Sign Language" },
+	{ "swm", "Samosa" },
+	{ "swn", "Sawknah" },
+	{ "swo", "Shanenawa" },
+	{ "swp", "Suau" },
+	{ "swq", "Sharwa" },
+	{ "swr", "Saweru" },
+	{ "sws", "Seluwasan" },
+	{ "swt", "Sawila" },
+	{ "swu", "Suwawa" },
+	{ "swv", "Shekhawati" },
+	{ "sww", "Sowa" },
+	{ "swx", "Suruahá" },
+	{ "swy", "Sarua" },
+	{ "sxb", "Suba" },
+	{ "sxc", "Sicanian" },
+	{ "sxe", "Sighu" },
+	{ "sxg", "Shixing" },
+	{ "sxk", "Southern Kalapuya" },
+	{ "sxl", "Selian" },
+	{ "sxm", "Samre" },
+	{ "sxn", "Sangir" },
+	{ "sxo", "Sorothaptic" },
+	{ "sxr", "Saaroa" },
+	{ "sxs", "Sasaru" },
+	{ "sxu", "Upper Saxon" },
+	{ "sxw", "Saxwe Gbe" },
+	{ "sya", "Siang" },
+	{ "syb", "Central Subanen" },
+	{ "syc", "Classical Syriac" },
+	{ "syi", "Seki" },
+	{ "syk", "Sukur" },
+	{ "syl", "Sylheti" },
+	{ "sym", "Maya Samo" },
+	{ "syn", "Senaya" },
+	{ "syo", "Suoy" },
+	{ "syr", "Syriac" },
+	{ "sys", "Sinyar" },
+	{ "syw", "Kagate" },
+	{ "syy", "Al-Sayyid Bedouin Sign Language" },
+	{ "sza", "Semelai" },
+	{ "szb", "Ngalum" },
+	{ "szc", "Semaq Beri" },
+	{ "szd", "Seru" },
+	{ "sze", "Seze" },
+	{ "szg", "Sengele" },
+	{ "szl", "Silesian" },
+	{ "szn", "Sula" },
+	{ "szp", "Suabo" },
+	{ "szv", "Isu (Fako Division)" },
+	{ "szw", "Sawai" },
+	{ "taa", "Lower Tanana" },
+	{ "tab", "Tabassaran" },
+	{ "tac", "Lowland Tarahumara" },
+	{ "tad", "Tause" },
+	{ "tae", "Tariana" },
+	{ "taf", "Tapirapé" },
+	{ "tag", "Tagoi" },
+	{ "tah", "Tahitian" },
+	{ "taj", "Eastern Tamang" },
+	{ "tak", "Tala" },
+	{ "tal", "Tal" },
+	{ "tam", "Tamil" },
+	{ "tan", "Tangale" },
+	{ "tao", "Yami" },
+	{ "tap", "Taabwa" },
+	{ "taq", "Tamasheq" },
+	{ "tar", "Central Tarahumara" },
+	{ "tas", "Tay Boi" },
+	{ "tat", "Tatar" },
+	{ "tau", "Upper Tanana" },
+	{ "tav", "Tatuyo" },
+	{ "taw", "Tai" },
+	{ "tax", "Tamki" },
+	{ "tay", "Atayal" },
+	{ "taz", "Tocho" },
+	{ "tba", "Aikanã" },
+	{ "tbb", "Tapeba" },
+	{ "tbc", "Takia" },
+	{ "tbd", "Kaki Ae" },
+	{ "tbe", "Tanimbili" },
+	{ "tbf", "Mandara" },
+	{ "tbg", "North Tairora" },
+	{ "tbh", "Thurawal" },
+	{ "tbi", "Gaam" },
+	{ "tbj", "Tiang" },
+	{ "tbk", "Calamian Tagbanwa" },
+	{ "tbl", "Tboli" },
+	{ "tbm", "Tagbu" },
+	{ "tbn", "Barro Negro Tunebo" },
+	{ "tbo", "Tawala" },
+	{ "tbp", "Taworta" },
+	{ "tbr", "Tumtum" },
+	{ "tbs", "Tanguat" },
+	{ "tbt", "Tembo (Kitembo)" },
+	{ "tbu", "Tubar" },
+	{ "tbv", "Tobo" },
+	{ "tbw", "Tagbanwa" },
+	{ "tbx", "Kapin" },
+	{ "tby", "Tabaru" },
+	{ "tbz", "Ditammari" },
+	{ "tca", "Ticuna" },
+	{ "tcb", "Tanacross" },
+	{ "tcc", "Datooga" },
+	{ "tcd", "Tafi" },
+	{ "tce", "Southern Tutchone" },
+	{ "tcf", "Malinaltepec Me'phaa" },
+	{ "tcg", "Tamagario" },
+	{ "tch", "Turks And Caicos Creole English" },
+	{ "tci", "Wára" },
+	{ "tck", "Tchitchege" },
+	{ "tcl", "Taman (Myanmar)" },
+	{ "tcm", "Tanahmerah" },
+	{ "tcn", "Tichurong" },
+	{ "tco", "Taungyo" },
+	{ "tcp", "Tawr Chin" },
+	{ "tcq", "Kaiy" },
+	{ "tcs", "Torres Strait Creole" },
+	{ "tct", "T'en" },
+	{ "tcu", "Southeastern Tarahumara" },
+	{ "tcw", "Tecpatlán Totonac" },
+	{ "tcx", "Toda" },
+	{ "tcy", "Tulu" },
+	{ "tcz", "Thado Chin" },
+	{ "tda", "Tagdal" },
+	{ "tdb", "Panchpargania" },
+	{ "tdc", "Emberá-Tadó" },
+	{ "tdd", "Tai Nüa" },
+	{ "tde", "Tiranige Diga Dogon" },
+	{ "tdf", "Talieng" },
+	{ "tdg", "Western Tamang" },
+	{ "tdh", "Thulung" },
+	{ "tdi", "Tomadino" },
+	{ "tdj", "Tajio" },
+	{ "tdk", "Tambas" },
+	{ "tdl", "Sur" },
+	{ "tdn", "Tondano" },
+	{ "tdo", "Teme" },
+	{ "tdq", "Tita" },
+	{ "tdr", "Todrah" },
+	{ "tds", "Doutai" },
+	{ "tdt", "Tetun Dili" },
+	{ "tdu", "Tempasuk Dusun" },
+	{ "tdv", "Toro" },
+	{ "tdx", "Tandroy-Mahafaly Malagasy" },
+	{ "tdy", "Tadyawan" },
+	{ "tea", "Temiar" },
+	{ "teb", "Tetete" },
+	{ "tec", "Terik" },
+	{ "ted", "Tepo Krumen" },
+	{ "tee", "Huehuetla Tepehua" },
+	{ "tef", "Teressa" },
+	{ "teg", "Teke-Tege" },
+	{ "teh", "Tehuelche" },
+	{ "tei", "Torricelli" },
+	{ "tek", "Ibali Teke" },
+	{ "tel", "Telugu" },
+	{ "tem", "Timne" },
+	{ "ten", "Tama (Colombia)" },
+	{ "teo", "Teso" },
+	{ "tep", "Tepecano" },
+	{ "teq", "Temein" },
+	{ "ter", "Tereno" },
+	{ "tes", "Tengger" },
+	{ "tet", "Tetum" },
+	{ "teu", "Soo" },
+	{ "tev", "Teor" },
+	{ "tew", "Tewa (USA)" },
+	{ "tex", "Tennet" },
+	{ "tey", "Tulishi" },
+	{ "tfi", "Tofin Gbe" },
+	{ "tfn", "Tanaina" },
+	{ "tfo", "Tefaro" },
+	{ "tfr", "Teribe" },
+	{ "tft", "Ternate" },
+	{ "tga", "Sagalla" },
+	{ "tgb", "Tobilung" },
+	{ "tgc", "Tigak" },
+	{ "tgd", "Ciwogai" },
+	{ "tge", "Eastern Gorkha Tamang" },
+	{ "tgf", "Chalikha" },
+	{ "tgh", "Tobagonian Creole English" },
+	{ "tgi", "Lawunuia" },
+	{ "tgj", "Tagin" },
+	{ "tgk", "Tajik" },
+	{ "tgl", "Tagalog" },
+	{ "tgn", "Tandaganon" },
+	{ "tgo", "Sudest" },
+	{ "tgp", "Tangoa" },
+	{ "tgq", "Tring" },
+	{ "tgr", "Tareng" },
+	{ "tgs", "Nume" },
+	{ "tgt", "Central Tagbanwa" },
+	{ "tgu", "Tanggu" },
+	{ "tgv", "Tingui-Boto" },
+	{ "tgw", "Tagwana Senoufo" },
+	{ "tgx", "Tagish" },
+	{ "tgy", "Togoyo" },
+	{ "tgz", "Tagalaka" },
+	{ "tha", "Thai" },
+	{ "thc", "Tai Hang Tong" },
+	{ "thd", "Thayore" },
+	{ "the", "Chitwania Tharu" },
+	{ "thf", "Thangmi" },
+	{ "thh", "Northern Tarahumara" },
+	{ "thi", "Tai Long" },
+	{ "thk", "Tharaka" },
+	{ "thl", "Dangaura Tharu" },
+	{ "thm", "Aheu" },
+	{ "thn", "Thachanadan" },
+	{ "thp", "Thompson" },
+	{ "thq", "Kochila Tharu" },
+	{ "thr", "Rana Tharu" },
+	{ "ths", "Thakali" },
+	{ "tht", "Tahltan" },
+	{ "thu", "Thuri" },
+	{ "thv", "Tahaggart Tamahaq" },
+	{ "thw", "Thudam" },
+	{ "thx", "The" },
+	{ "thy", "Tha" },
+	{ "thz", "Tayart Tamajeq" },
+	{ "tia", "Tidikelt Tamazight" },
+	{ "tic", "Tira" },
+	{ "tid", "Tidong" },
+	{ "tif", "Tifal" },
+	{ "tig", "Tigre" },
+	{ "tih", "Timugon Murut" },
+	{ "tii", "Tiene" },
+	{ "tij", "Tilung" },
+	{ "tik", "Tikar" },
+	{ "til", "Tillamook" },
+	{ "tim", "Timbe" },
+	{ "tin", "Tindi" },
+	{ "tio", "Teop" },
+	{ "tip", "Trimuris" },
+	{ "tiq", "Tiéfo" },
+	{ "tir", "Tigrinya" },
+	{ "tis", "Masadiit Itneg" },
+	{ "tit", "Tinigua" },
+	{ "tiu", "Adasen" },
+	{ "tiv", "Tiv" },
+	{ "tiw", "Tiwi" },
+	{ "tix", "Southern Tiwa" },
+	{ "tiy", "Tiruray" },
+	{ "tiz", "Tai Hongjin" },
+	{ "tja", "Tajuasohn" },
+	{ "tjg", "Tunjung" },
+	{ "tji", "Northern Tujia" },
+	{ "tjl", "Tai Laing" },
+	{ "tjm", "Timucua" },
+	{ "tjn", "Tonjon" },
+	{ "tjo", "Temacine Tamazight" },
+	{ "tjs", "Southern Tujia" },
+	{ "tju", "Tjurruru" },
+	{ "tjw", "Djabwurrung" },
+	{ "tka", "Truká" },
+	{ "tkb", "Buksa" },
+	{ "tkd", "Tukudede" },
+	{ "tke", "Takwane" },
+	{ "tkf", "Tukumanféd" },
+	{ "tkg", "Tesaka Malagasy" },
+	{ "tkl", "Tokelau" },
+	{ "tkm", "Takelma" },
+	{ "tkn", "Toku-No-Shima" },
+	{ "tkp", "Tikopia" },
+	{ "tkq", "Tee" },
+	{ "tkr", "Tsakhur" },
+	{ "tks", "Takestani" },
+	{ "tkt", "Kathoriya Tharu" },
+	{ "tku", "Upper Necaxa Totonac" },
+	{ "tkw", "Teanu" },
+	{ "tkx", "Tangko" },
+	{ "tkz", "Takua" },
+	{ "tla", "Southwestern Tepehuan" },
+	{ "tlb", "Tobelo" },
+	{ "tlc", "Yecuatla Totonac" },
+	{ "tld", "Talaud" },
+	{ "tlf", "Telefol" },
+	{ "tlg", "Tofanma" },
+	{ "tlh", "Klingon" },
+	{ "tli", "Tlingit" },
+	{ "tlj", "Talinga-Bwisi" },
+	{ "tlk", "Taloki" },
+	{ "tll", "Tetela" },
+	{ "tlm", "Tolomako" },
+	{ "tln", "Talondo'" },
+	{ "tlo", "Talodi" },
+	{ "tlp", "Filomena Mata-Coahuitlán Totonac" },
+	{ "tlq", "Tai Loi" },
+	{ "tlr", "Talise" },
+	{ "tls", "Tambotalo" },
+	{ "tlt", "Teluti" },
+	{ "tlu", "Tulehu" },
+	{ "tlv", "Taliabu" },
+	{ "tlx", "Khehek" },
+	{ "tly", "Talysh" },
+	{ "tma", "Tama (Chad)" },
+	{ "tmb", "Katbol" },
+	{ "tmc", "Tumak" },
+	{ "tmd", "Haruai" },
+	{ "tme", "Tremembé" },
+	{ "tmf", "Toba-Maskoy" },
+	{ "tmg", "Ternateño" },
+	{ "tmh", "Tamashek" },
+	{ "tmi", "Tutuba" },
+	{ "tmj", "Samarokena" },
+	{ "tmk", "Northwestern Tamang" },
+	{ "tml", "Tamnim Citak" },
+	{ "tmm", "Tai Thanh" },
+	{ "tmn", "Taman (Indonesia)" },
+	{ "tmo", "Temoq" },
+	{ "tmp", "Tai Mène" },
+	{ "tmq", "Tumleo" },
+	{ "tmr", "Jewish Babylonian Aramaic (ca. 200-1200 CE)" },
+	{ "tms", "Tima" },
+	{ "tmt", "Tasmate" },
+	{ "tmu", "Iau" },
+	{ "tmv", "Tembo (Motembo)" },
+	{ "tmw", "Temuan" },
+	{ "tmy", "Tami" },
+	{ "tmz", "Tamanaku" },
+	{ "tna", "Tacana" },
+	{ "tnb", "Western Tunebo" },
+	{ "tnc", "Tanimuca-Retuarã" },
+	{ "tnd", "Angosturas Tunebo" },
+	{ "tne", "Tinoc Kallahan" },
+	{ "tng", "Tobanga" },
+	{ "tnh", "Maiani" },
+	{ "tni", "Tandia" },
+	{ "tnk", "Kwamera" },
+	{ "tnl", "Lenakel" },
+	{ "tnm", "Tabla" },
+	{ "tnn", "North Tanna" },
+	{ "tno", "Toromono" },
+	{ "tnp", "Whitesands" },
+	{ "tnq", "Taino" },
+	{ "tnr", "Ménik" },
+	{ "tns", "Tenis" },
+	{ "tnt", "Tontemboan" },
+	{ "tnu", "Tay Khang" },
+	{ "tnv", "Tangchangya" },
+	{ "tnw", "Tonsawang" },
+	{ "tnx", "Tanema" },
+	{ "tny", "Tongwe" },
+	{ "tnz", "Tonga (Thailand)" },
+	{ "tob", "Toba" },
+	{ "toc", "Coyutla Totonac" },
+	{ "tod", "Toma" },
+	{ "toe", "Tomedes" },
+	{ "tof", "Gizrra" },
+	{ "tog", "Tonga (Nyasa)" },
+	{ "toh", "Gitonga" },
+	{ "toi", "Tonga (Zambia)" },
+	{ "toj", "Tojolabal" },
+	{ "tol", "Tolowa" },
+	{ "tom", "Tombulu" },
+	{ "ton", "Tonga (Tonga Islands)" },
+	{ "too", "Xicotepec De Juárez Totonac" },
+	{ "top", "Papantla Totonac" },
+	{ "toq", "Toposa" },
+	{ "tor", "Togbo-Vara Banda" },
+	{ "tos", "Highland Totonac" },
+	{ "tou", "Tho" },
+	{ "tov", "Upper Taromi" },
+	{ "tow", "Jemez" },
+	{ "tox", "Tobian" },
+	{ "toy", "Topoiyo" },
+	{ "toz", "To" },
+	{ "tpa", "Taupota" },
+	{ "tpc", "Azoyú Me'phaa" },
+	{ "tpe", "Tippera" },
+	{ "tpf", "Tarpia" },
+	{ "tpg", "Kula" },
+	{ "tpi", "Tok Pisin" },
+	{ "tpj", "Tapieté" },
+	{ "tpk", "Tupinikin" },
+	{ "tpl", "Tlacoapa Me'phaa" },
+	{ "tpm", "Tampulma" },
+	{ "tpn", "Tupinambá" },
+	{ "tpo", "Tai Pao" },
+	{ "tpp", "Pisaflores Tepehua" },
+	{ "tpq", "Tukpa" },
+	{ "tpr", "Tuparí" },
+	{ "tpt", "Tlachichilco Tepehua" },
+	{ "tpu", "Tampuan" },
+	{ "tpv", "Tanapag" },
+	{ "tpw", "Tupí" },
+	{ "tpx", "Acatepec Me'phaa" },
+	{ "tpy", "Trumai" },
+	{ "tpz", "Tinputz" },
+	{ "tqb", "Tembé" },
+	{ "tql", "Lehali" },
+	{ "tqm", "Turumsa" },
+	{ "tqn", "Tenino" },
+	{ "tqo", "Toaripi" },
+	{ "tqp", "Tomoip" },
+	{ "tqq", "Tunni" },
+	{ "tqr", "Torona" },
+	{ "tqt", "Western Totonac" },
+	{ "tqu", "Touo" },
+	{ "tqw", "Tonkawa" },
+	{ "tra", "Tirahi" },
+	{ "trb", "Terebu" },
+	{ "trc", "Copala Triqui" },
+	{ "trd", "Turi" },
+	{ "tre", "East Tarangan" },
+	{ "trf", "Trinidadian Creole English" },
+	{ "trg", "Lishán Didán" },
+	{ "trh", "Turaka" },
+	{ "tri", "Trió" },
+	{ "trj", "Toram" },
+	{ "trl", "Traveller Scottish" },
+	{ "trm", "Tregami" },
+	{ "trn", "Trinitario" },
+	{ "tro", "Tarao Naga" },
+	{ "trp", "Kok Borok" },
+	{ "trq", "San Martín Itunyoso Triqui" },
+	{ "trr", "Taushiro" },
+	{ "trs", "Chicahuaxtla Triqui" },
+	{ "trt", "Tunggare" },
+	{ "tru", "Turoyo" },
+	{ "trv", "Taroko" },
+	{ "trw", "Torwali" },
+	{ "trx", "Tringgus-Sembaan Bidayuh" },
+	{ "try", "Turung" },
+	{ "trz", "Torá" },
+	{ "tsa", "Tsaangi" },
+	{ "tsb", "Tsamai" },
+	{ "tsc", "Tswa" },
+	{ "tsd", "Tsakonian" },
+	{ "tse", "Tunisian Sign Language" },
+	{ "tsf", "Southwestern Tamang" },
+	{ "tsg", "Tausug" },
+	{ "tsh", "Tsuvan" },
+	{ "tsi", "Tsimshian" },
+	{ "tsj", "Tshangla" },
+	{ "tsk", "Tseku" },
+	{ "tsl", "Ts'ün-Lao" },
+	{ "tsm", "Turkish Sign Language" },
+	{ "tsn", "Tswana" },
+	{ "tso", "Tsonga" },
+	{ "tsp", "Northern Toussian" },
+	{ "tsq", "Thai Sign Language" },
+	{ "tsr", "Akei" },
+	{ "tss", "Taiwan Sign Language" },
+	{ "tst", "Tondi Songway Kiini" },
+	{ "tsu", "Tsou" },
+	{ "tsv", "Tsogo" },
+	{ "tsw", "Tsishingini" },
+	{ "tsx", "Mubami" },
+	{ "tsy", "Tebul Sign Language" },
+	{ "tsz", "Purepecha" },
+	{ "tta", "Tutelo" },
+	{ "ttb", "Gaa" },
+	{ "ttc", "Tektiteko" },
+	{ "ttd", "Tauade" },
+	{ "tte", "Bwanabwana" },
+	{ "ttf", "Tuotomb" },
+	{ "ttg", "Tutong" },
+	{ "tth", "Upper Ta'oih" },
+	{ "tti", "Tobati" },
+	{ "ttj", "Tooro" },
+	{ "ttk", "Totoro" },
+	{ "ttl", "Totela" },
+	{ "ttm", "Northern Tutchone" },
+	{ "ttn", "Towei" },
+	{ "tto", "Lower Ta'oih" },
+	{ "ttp", "Tombelala" },
+	{ "ttq", "Tawallammat Tamajaq" },
+	{ "ttr", "Tera" },
+	{ "tts", "Northeastern Thai" },
+	{ "ttt", "Muslim Tat" },
+	{ "ttu", "Torau" },
+	{ "ttv", "Titan" },
+	{ "ttw", "Long Wat" },
+	{ "tty", "Sikaritai" },
+	{ "ttz", "Tsum" },
+	{ "tua", "Wiarumus" },
+	{ "tub", "Tübatulabal" },
+	{ "tuc", "Mutu" },
+	{ "tud", "Tuxá" },
+	{ "tue", "Tuyuca" },
+	{ "tuf", "Central Tunebo" },
+	{ "tug", "Tunia" },
+	{ "tuh", "Taulil" },
+	{ "tui", "Tupuri" },
+	{ "tuj", "Tugutil" },
+	{ "tuk", "Turkmen" },
+	{ "tul", "Tula" },
+	{ "tum", "Tumbuka" },
+	{ "tun", "Tunica" },
+	{ "tuo", "Tucano" },
+	{ "tuq", "Tedaga" },
+	{ "tur", "Turkish" },
+	{ "tus", "Tuscarora" },
+	{ "tuu", "Tututni" },
+	{ "tuv", "Turkana" },
+	{ "tux", "Tuxináwa" },
+	{ "tuy", "Tugen" },
+	{ "tuz", "Turka" },
+	{ "tva", "Vaghua" },
+	{ "tvd", "Tsuvadi" },
+	{ "tve", "Te'un" },
+	{ "tvk", "Southeast Ambrym" },
+	{ "tvl", "Tuvalu" },
+	{ "tvm", "Tela-Masbuar" },
+	{ "tvn", "Tavoyan" },
+	{ "tvo", "Tidore" },
+	{ "tvs", "Taveta" },
+	{ "tvt", "Tutsa Naga" },
+	{ "tvu", "Tunen" },
+	{ "tvw", "Sedoa" },
+	{ "tvy", "Timor Pidgin" },
+	{ "twa", "Twana" },
+	{ "twb", "Western Tawbuid" },
+	{ "twc", "Teshenawa" },
+	{ "twd", "Twents" },
+	{ "twe", "Tewa (Indonesia)" },
+	{ "twf", "Northern Tiwa" },
+	{ "twg", "Tereweng" },
+	{ "twh", "Tai Dón" },
+	{ "twi", "Twi" },
+	{ "twl", "Tawara" },
+	{ "twm", "Tawang Monpa" },
+	{ "twn", "Twendi" },
+	{ "two", "Tswapong" },
+	{ "twp", "Ere" },
+	{ "twq", "Tasawaq" },
+	{ "twr", "Southwestern Tarahumara" },
+	{ "twt", "Turiwára" },
+	{ "twu", "Termanu" },
+	{ "tww", "Tuwari" },
+	{ "twx", "Tewe" },
+	{ "twy", "Tawoyan" },
+	{ "txa", "Tombonuo" },
+	{ "txb", "Tokharian B" },
+	{ "txc", "Tsetsaut" },
+	{ "txe", "Totoli" },
+	{ "txg", "Tangut" },
+	{ "txh", "Thracian" },
+	{ "txi", "Ikpeng" },
+	{ "txm", "Tomini" },
+	{ "txn", "West Tarangan" },
+	{ "txo", "Toto" },
+	{ "txq", "Tii" },
+	{ "txr", "Tartessian" },
+	{ "txs", "Tonsea" },
+	{ "txt", "Citak" },
+	{ "txu", "Kayapó" },
+	{ "txx", "Tatana" },
+	{ "txy", "Tanosy Malagasy" },
+	{ "tya", "Tauya" },
+	{ "tye", "Kyanga" },
+	{ "tyh", "O'du" },
+	{ "tyi", "Teke-Tsaayi" },
+	{ "tyj", "Tai Do" },
+	{ "tyl", "Thu Lao" },
+	{ "tyn", "Kombai" },
+	{ "typ", "Thaypan" },
+	{ "tyr", "Tai Daeng" },
+	{ "tys", "Tày Sa Pa" },
+	{ "tyt", "Tày Tac" },
+	{ "tyu", "Kua" },
+	{ "tyv", "Tuvinian" },
+	{ "tyx", "Teke-Tyee" },
+	{ "tyz", "Tày" },
+	{ "tza", "Tanzanian Sign Language" },
+	{ "tzh", "Tzeltal" },
+	{ "tzj", "Tz'utujil" },
+	{ "tzl", "Talossan" },
+	{ "tzm", "Central Atlas Tamazight" },
+	{ "tzn", "Tugun" },
+	{ "tzo", "Tzotzil" },
+	{ "tzx", "Tabriak" },
+	{ "uam", "Uamué" },
+	{ "uan", "Kuan" },
+	{ "uar", "Tairuma" },
+	{ "uba", "Ubang" },
+	{ "ubi", "Ubi" },
+	{ "ubl", "Buhi'non Bikol" },
+	{ "ubr", "Ubir" },
+	{ "ubu", "Umbu-Ungu" },
+	{ "uby", "Ubykh" },
+	{ "uda", "Uda" },
+	{ "ude", "Udihe" },
+	{ "udg", "Muduga" },
+	{ "udi", "Udi" },
+	{ "udj", "Ujir" },
+	{ "udl", "Wuzlam" },
+	{ "udm", "Udmurt" },
+	{ "udu", "Uduk" },
+	{ "ues", "Kioko" },
+	{ "ufi", "Ufim" },
+	{ "uga", "Ugaritic" },
+	{ "ugb", "Kuku-Ugbanh" },
+	{ "uge", "Ughele" },
+	{ "ugn", "Ugandan Sign Language" },
+	{ "ugo", "Ugong" },
+	{ "ugy", "Uruguayan Sign Language" },
+	{ "uha", "Uhami" },
+	{ "uhn", "Damal" },
+	{ "uig", "Uighur" },
+	{ "uis", "Uisai" },
+	{ "uiv", "Iyive" },
+	{ "uji", "Tanjijili" },
+	{ "uka", "Kaburi" },
+	{ "ukg", "Ukuriguma" },
+	{ "ukh", "Ukhwejo" },
+	{ "ukl", "Ukrainian Sign Language" },
+	{ "ukp", "Ukpe-Bayobiri" },
+	{ "ukq", "Ukwa" },
+	{ "ukr", "Ukrainian" },
+	{ "uks", "Urubú-Kaapor Sign Language" },
+	{ "uku", "Ukue" },
+	{ "ukw", "Ukwuani-Aboh-Ndoni" },
+	{ "uky", "Kuuk-Yak" },
+	{ "ula", "Fungwa" },
+	{ "ulb", "Ulukwumi" },
+	{ "ulc", "Ulch" },
+	{ "ule", "Lule" },
+	{ "ulf", "Usku" },
+	{ "uli", "Ulithian" },
+	{ "ulk", "Meriam" },
+	{ "ull", "Ullatan" },
+	{ "ulm", "Ulumanda'" },
+	{ "uln", "Unserdeutsch" },
+	{ "ulu", "Uma' Lung" },
+	{ "ulw", "Ulwa" },
+	{ "uma", "Umatilla" },
+	{ "umb", "Umbundu" },
+	{ "umc", "Marrucinian" },
+	{ "umd", "Umbindhamu" },
+	{ "umg", "Umbuygamu" },
+	{ "umi", "Ukit" },
+	{ "umm", "Umon" },
+	{ "umn", "Makyan Naga" },
+	{ "umo", "Umotína" },
+	{ "ump", "Umpila" },
+	{ "umr", "Umbugarla" },
+	{ "ums", "Pendau" },
+	{ "umu", "Munsee" },
+	{ "una", "North Watut" },
+	{ "und", "Undetermined" },
+	{ "une", "Uneme" },
+	{ "ung", "Ngarinyin" },
+	{ "unk", "Enawené-Nawé" },
+	{ "unm", "Unami" },
+	{ "unn", "Kurnai" },
+	{ "unr", "Mundari" },
+	{ "unu", "Unubahe" },
+	{ "unx", "Munda" },
+	{ "unz", "Unde Kaili" },
+	{ "uok", "Uokha" },
+	{ "upi", "Umeda" },
+	{ "upv", "Uripiv-Wala-Rano-Atchin" },
+	{ "ura", "Urarina" },
+	{ "urb", "Urubú-Kaapor" },
+	{ "urc", "Urningangg" },
+	{ "urd", "Urdu" },
+	{ "ure", "Uru" },
+	{ "urf", "Uradhi" },
+	{ "urg", "Urigina" },
+	{ "urh", "Urhobo" },
+	{ "uri", "Urim" },
+	{ "urk", "Urak Lawoi'" },
+	{ "url", "Urali" },
+	{ "urm", "Urapmin" },
+	{ "urn", "Uruangnirin" },
+	{ "uro", "Ura (Papua New Guinea)" },
+	{ "urp", "Uru-Pa-In" },
+	{ "urr", "Lehalurup" },
+	{ "urt", "Urat" },
+	{ "uru", "Urumi" },
+	{ "urv", "Uruava" },
+	{ "urw", "Sop" },
+	{ "urx", "Urimo" },
+	{ "ury", "Orya" },
+	{ "urz", "Uru-Eu-Wau-Wau" },
+	{ "usa", "Usarufa" },
+	{ "ush", "Ushojo" },
+	{ "usi", "Usui" },
+	{ "usk", "Usaghade" },
+	{ "usp", "Uspanteco" },
+	{ "usu", "Uya" },
+	{ "uta", "Otank" },
+	{ "ute", "Ute-Southern Paiute" },
+	{ "utp", "Amba (Solomon Islands)" },
+	{ "utr", "Etulo" },
+	{ "utu", "Utu" },
+	{ "uum", "Urum" },
+	{ "uun", "Kulon-Pazeh" },
+	{ "uur", "Ura (Vanuatu)" },
+	{ "uuu", "U" },
+	{ "uve", "West Uvean" },
+	{ "uvh", "Uri" },
+	{ "uvl", "Lote" },
+	{ "uwa", "Kuku-Uwanh" },
+	{ "uya", "Doko-Uyanga" },
+	{ "uzb", "Uzbek" },
+	{ "uzn", "Northern Uzbek" },
+	{ "uzs", "Southern Uzbek" },
+	{ "vaa", "Vaagri Booli" },
+	{ "vae", "Vale" },
+	{ "vaf", "Vafsi" },
+	{ "vag", "Vagla" },
+	{ "vah", "Varhadi-Nagpuri" },
+	{ "vai", "Vai" },
+	{ "vaj", "Vasekela Bushman" },
+	{ "val", "Vehes" },
+	{ "vam", "Vanimo" },
+	{ "van", "Valman" },
+	{ "vao", "Vao" },
+	{ "vap", "Vaiphei" },
+	{ "var", "Huarijio" },
+	{ "vas", "Vasavi" },
+	{ "vau", "Vanuma" },
+	{ "vav", "Varli" },
+	{ "vay", "Wayu" },
+	{ "vbb", "Southeast Babar" },
+	{ "vbk", "Southwestern Bontok" },
+	{ "vec", "Venetian" },
+	{ "ved", "Veddah" },
+	{ "vel", "Veluws" },
+	{ "vem", "Vemgo-Mabas" },
+	{ "ven", "Venda" },
+	{ "veo", "Ventureño" },
+	{ "vep", "Veps" },
+	{ "ver", "Mom Jango" },
+	{ "vgr", "Vaghri" },
+	{ "vgt", "Vlaamse Gebarentaal" },
+	{ "vic", "Virgin Islands Creole English" },
+	{ "vid", "Vidunda" },
+	{ "vie", "Vietnamese" },
+	{ "vif", "Vili" },
+	{ "vig", "Viemo" },
+	{ "vil", "Vilela" },
+	{ "vin", "Vinza" },
+	{ "vis", "Vishavan" },
+	{ "vit", "Viti" },
+	{ "viv", "Iduna" },
+	{ "vka", "Kariyarra" },
+	{ "vki", "Ija-Zuba" },
+	{ "vkj", "Kujarge" },
+	{ "vkk", "Kaur" },
+	{ "vkl", "Kulisusu" },
+	{ "vkm", "Kamakan" },
+	{ "vko", "Kodeoha" },
+	{ "vkp", "Korlai Creole Portuguese" },
+	{ "vkt", "Tenggarong Kutai Malay" },
+	{ "vku", "Kurrama" },
+	{ "vlp", "Valpei" },
+	{ "vls", "Vlaams" },
+	{ "vma", "Martuyhunira" },
+	{ "vmb", "Barbaram" },
+	{ "vmc", "Juxtlahuaca Mixtec" },
+	{ "vmd", "Mudu Koraga" },
+	{ "vme", "East Masela" },
+	{ "vmf", "Mainfränkisch" },
+	{ "vmg", "Lungalunga" },
+	{ "vmh", "Maraghei" },
+	{ "vmi", "Miwa" },
+	{ "vmj", "Ixtayutla Mixtec" },
+	{ "vmk", "Makhuwa-Shirima" },
+	{ "vml", "Malgana" },
+	{ "vmm", "Mitlatongo Mixtec" },
+	{ "vmp", "Soyaltepec Mazatec" },
+	{ "vmq", "Soyaltepec Mixtec" },
+	{ "vmr", "Marenje" },
+	{ "vms", "Moksela" },
+	{ "vmu", "Muluridyi" },
+	{ "vmv", "Valley Maidu" },
+	{ "vmw", "Makhuwa" },
+	{ "vmx", "Tamazola Mixtec" },
+	{ "vmy", "Ayautla Mazatec" },
+	{ "vmz", "Mazatlán Mazatec" },
+	{ "vnk", "Vano" },
+	{ "vnm", "Vinmavis" },
+	{ "vnp", "Vunapu" },
+	{ "vol", "Volapük" },
+	{ "vor", "Voro" },
+	{ "vot", "Votic" },
+	{ "vra", "Vera'a" },
+	{ "vro", "Võro" },
+	{ "vrs", "Varisi" },
+	{ "vrt", "Burmbar" },
+	{ "vsi", "Moldova Sign Language" },
+	{ "vsl", "Venezuelan Sign Language" },
+	{ "vsv", "Valencian Sign Language" },
+	{ "vto", "Vitou" },
+	{ "vum", "Vumbu" },
+	{ "vun", "Vunjo" },
+	{ "vut", "Vute" },
+	{ "vwa", "Awa (China)" },
+	{ "waa", "Walla Walla" },
+	{ "wab", "Wab" },
+	{ "wac", "Wasco-Wishram" },
+	{ "wad", "Wandamen" },
+	{ "wae", "Walser" },
+	{ "waf", "Wakoná" },
+	{ "wag", "Wa'ema" },
+	{ "wah", "Watubela" },
+	{ "wai", "Wares" },
+	{ "waj", "Waffa" },
+	{ "wal", "Wolaytta" },
+	{ "wam", "Wampanoag" },
+	{ "wan", "Wan" },
+	{ "wao", "Wappo" },
+	{ "wap", "Wapishana" },
+	{ "waq", "Wageman" },
+	{ "war", "Waray (Philippines)" },
+	{ "was", "Washo" },
+	{ "wat", "Kaninuwa" },
+	{ "wau", "Waurá" },
+	{ "wav", "Waka" },
+	{ "waw", "Waiwai" },
+	{ "wax", "Watam" },
+	{ "way", "Wayana" },
+	{ "waz", "Wampur" },
+	{ "wba", "Warao" },
+	{ "wbb", "Wabo" },
+	{ "wbe", "Waritai" },
+	{ "wbf", "Wara" },
+	{ "wbh", "Wanda" },
+	{ "wbi", "Vwanji" },
+	{ "wbj", "Alagwa" },
+	{ "wbk", "Waigali" },
+	{ "wbl", "Wakhi" },
+	{ "wbm", "Wa" },
+	{ "wbp", "Warlpiri" },
+	{ "wbq", "Waddar" },
+	{ "wbr", "Wagdi" },
+	{ "wbt", "Wanman" },
+	{ "wbv", "Wajarri" },
+	{ "wbw", "Woi" },
+	{ "wca", "Yanomámi" },
+	{ "wci", "Waci Gbe" },
+	{ "wdd", "Wandji" },
+	{ "wdg", "Wadaginam" },
+	{ "wdj", "Wadjiginy" },
+	{ "wdk", "Wadikali" },
+	{ "wdu", "Wadjigu" },
+	{ "wdy", "Wadjabangayi" },
+	{ "wea", "Wewaw" },
+	{ "wec", "Wè Western" },
+	{ "wed", "Wedau" },
+	{ "weg", "Wergaia" },
+	{ "weh", "Weh" },
+	{ "wei", "Kiunum" },
+	{ "wem", "Weme Gbe" },
+	{ "weo", "Wemale" },
+	{ "wep", "Westphalien" },
+	{ "wer", "Weri" },
+	{ "wes", "Cameroon Pidgin" },
+	{ "wet", "Perai" },
+	{ "weu", "Rawngtu Chin" },
+	{ "wew", "Wejewa" },
+	{ "wfg", "Yafi" },
+	{ "wga", "Wagaya" },
+	{ "wgb", "Wagawaga" },
+	{ "wgg", "Wangganguru" },
+	{ "wgi", "Wahgi" },
+	{ "wgo", "Waigeo" },
+	{ "wgu", "Wirangu" },
+	{ "wgy", "Warrgamay" },
+	{ "wha", "Manusela" },
+	{ "whg", "North Wahgi" },
+	{ "whk", "Wahau Kenyah" },
+	{ "whu", "Wahau Kayan" },
+	{ "wib", "Southern Toussian" },
+	{ "wic", "Wichita" },
+	{ "wie", "Wik-Epa" },
+	{ "wif", "Wik-Keyangan" },
+	{ "wig", "Wik-Ngathana" },
+	{ "wih", "Wik-Me'anha" },
+	{ "wii", "Minidien" },
+	{ "wij", "Wik-Iiyanh" },
+	{ "wik", "Wikalkan" },
+	{ "wil", "Wilawila" },
+	{ "wim", "Wik-Mungkan" },
+	{ "win", "Ho-Chunk" },
+	{ "wir", "Wiraféd" },
+	{ "wiu", "Wiru" },
+	{ "wiv", "Vitu" },
+	{ "wiy", "Wiyot" },
+	{ "wja", "Waja" },
+	{ "wji", "Warji" },
+	{ "wka", "Kw'adza" },
+	{ "wkb", "Kumbaran" },
+	{ "wkd", "Wakde" },
+	{ "wkl", "Kalanadi" },
+	{ "wku", "Kunduvadi" },
+	{ "wkw", "Wakawaka" },
+	{ "wky", "Wangkayutyuru" },
+	{ "wla", "Walio" },
+	{ "wlc", "Mwali Comorian" },
+	{ "wle", "Wolane" },
+	{ "wlg", "Kunbarlang" },
+	{ "wli", "Waioli" },
+	{ "wlk", "Wailaki" },
+	{ "wll", "Wali (Sudan)" },
+	{ "wlm", "Middle Welsh" },
+	{ "wln", "Walloon" },
+	{ "wlo", "Wolio" },
+	{ "wlr", "Wailapa" },
+	{ "wls", "Wallisian" },
+	{ "wlu", "Wuliwuli" },
+	{ "wlv", "Wichí Lhamtés Vejoz" },
+	{ "wlw", "Walak" },
+	{ "wlx", "Wali (Ghana)" },
+	{ "wly", "Waling" },
+	{ "wma", "Mawa (Nigeria)" },
+	{ "wmb", "Wambaya" },
+	{ "wmc", "Wamas" },
+	{ "wmd", "Mamaindé" },
+	{ "wme", "Wambule" },
+	{ "wmh", "Waima'a" },
+	{ "wmi", "Wamin" },
+	{ "wmm", "Maiwa (Indonesia)" },
+	{ "wmn", "Waamwang" },
+	{ "wmo", "Wom (Papua New Guinea)" },
+	{ "wms", "Wambon" },
+	{ "wmt", "Walmajarri" },
+	{ "wmw", "Mwani" },
+	{ "wmx", "Womo" },
+	{ "wnb", "Wanambre" },
+	{ "wnc", "Wantoat" },
+	{ "wnd", "Wandarang" },
+	{ "wne", "Waneci" },
+	{ "wng", "Wanggom" },
+	{ "wni", "Ndzwani Comorian" },
+	{ "wnk", "Wanukaka" },
+	{ "wnm", "Wanggamala" },
+	{ "wnn", "Wunumara" },
+	{ "wno", "Wano" },
+	{ "wnp", "Wanap" },
+	{ "wnu", "Usan" },
+	{ "wnw", "Wintu" },
+	{ "wny", "Wanyi" },
+	{ "woa", "Tyaraity" },
+	{ "wob", "Wè Northern" },
+	{ "woc", "Wogeo" },
+	{ "wod", "Wolani" },
+	{ "woe", "Woleaian" },
+	{ "wof", "Gambian Wolof" },
+	{ "wog", "Wogamusin" },
+	{ "woi", "Kamang" },
+	{ "wok", "Longto" },
+	{ "wol", "Wolof" },
+	{ "wom", "Wom (Nigeria)" },
+	{ "won", "Wongo" },
+	{ "woo", "Manombai" },
+	{ "wor", "Woria" },
+	{ "wos", "Hanga Hundi" },
+	{ "wow", "Wawonii" },
+	{ "woy", "Weyto" },
+	{ "wpc", "Maco" },
+	{ "wra", "Warapu" },
+	{ "wrb", "Warluwara" },
+	{ "wrd", "Warduji" },
+	{ "wrg", "Warungu" },
+	{ "wrh", "Wiradhuri" },
+	{ "wri", "Wariyangga" },
+	{ "wrk", "Garrwa" },
+	{ "wrl", "Warlmanpa" },
+	{ "wrm", "Warumungu" },
+	{ "wrn", "Warnang" },
+	{ "wro", "Worrorra" },
+	{ "wrp", "Waropen" },
+	{ "wrr", "Wardaman" },
+	{ "wrs", "Waris" },
+	{ "wru", "Waru" },
+	{ "wrv", "Waruna" },
+	{ "wrw", "Gugu Warra" },
+	{ "wrx", "Wae Rana" },
+	{ "wry", "Merwari" },
+	{ "wrz", "Waray (Australia)" },
+	{ "wsa", "Warembori" },
+	{ "wsi", "Wusi" },
+	{ "wsk", "Waskia" },
+	{ "wsr", "Owenia" },
+	{ "wss", "Wasa" },
+	{ "wsu", "Wasu" },
+	{ "wsv", "Wotapuri-Katarqalai" },
+	{ "wtf", "Watiwa" },
+	{ "wth", "Wathawurrung" },
+	{ "wti", "Berta" },
+	{ "wtk", "Watakataui" },
+	{ "wtm", "Mewati" },
+	{ "wtw", "Wotu" },
+	{ "wua", "Wikngenchera" },
+	{ "wub", "Wunambal" },
+	{ "wud", "Wudu" },
+	{ "wuh", "Wutunhua" },
+	{ "wul", "Silimo" },
+	{ "wum", "Wumbvu" },
+	{ "wun", "Bungu" },
+	{ "wur", "Wurrugu" },
+	{ "wut", "Wutung" },
+	{ "wuu", "Wu Chinese" },
+	{ "wuv", "Wuvulu-Aua" },
+	{ "wux", "Wulna" },
+	{ "wuy", "Wauyai" },
+	{ "wwa", "Waama" },
+	{ "wwb", "Wakabunga" },
+	{ "wwo", "Wetamut" },
+	{ "wwr", "Warrwa" },
+	{ "www", "Wawa" },
+	{ "wxa", "Waxianghua" },
+	{ "wxw", "Wardandi" },
+	{ "wya", "Wyandot" },
+	{ "wyb", "Wangaaybuwan-Ngiyambaa" },
+	{ "wyi", "Woiwurrung" },
+	{ "wym", "Wymysorys" },
+	{ "wyr", "Wayoró" },
+	{ "wyy", "Western Fijian" },
+	{ "xaa", "Andalusian Arabic" },
+	{ "xab", "Sambe" },
+	{ "xac", "Kachari" },
+	{ "xad", "Adai" },
+	{ "xae", "Aequian" },
+	{ "xag", "Aghwan" },
+	{ "xai", "Kaimbé" },
+	{ "xal", "Kalmyk" },
+	{ "xam", "Xam" },
+	{ "xan", "Xamtanga" },
+	{ "xao", "Khao" },
+	{ "xap", "Apalachee" },
+	{ "xaq", "Aquitanian" },
+	{ "xar", "Karami" },
+	{ "xas", "Kamas" },
+	{ "xat", "Katawixi" },
+	{ "xau", "Kauwera" },
+	{ "xav", "Xavánte" },
+	{ "xaw", "Kawaiisu" },
+	{ "xay", "Kayan Mahakam" },
+	{ "xba", "Kamba (Brazil)" },
+	{ "xbb", "Lower Burdekin" },
+	{ "xbc", "Bactrian" },
+	{ "xbd", "Bindal" },
+	{ "xbe", "Bigambal" },
+	{ "xbg", "Bunganditj" },
+	{ "xbi", "Kombio" },
+	{ "xbj", "Birrpayi" },
+	{ "xbm", "Middle Breton" },
+	{ "xbn", "Kenaboi" },
+	{ "xbo", "Bolgarian" },
+	{ "xbp", "Bibbulman" },
+	{ "xbr", "Kambera" },
+	{ "xbw", "Kambiwá" },
+	{ "xbx", "Kabixí" },
+	{ "xby", "Batyala" },
+	{ "xcb", "Cumbric" },
+	{ "xcc", "Camunic" },
+	{ "xce", "Celtiberian" },
+	{ "xcg", "Cisalpine Gaulish" },
+	{ "xch", "Chemakum" },
+	{ "xcl", "Classical Armenian" },
+	{ "xcm", "Comecrudo" },
+	{ "xcn", "Cotoname" },
+	{ "xco", "Chorasmian" },
+	{ "xcr", "Carian" },
+	{ "xct", "Classical Tibetan" },
+	{ "xcu", "Curonian" },
+	{ "xcv", "Chuvantsy" },
+	{ "xcw", "Coahuilteco" },
+	{ "xcy", "Cayuse" },
+	{ "xda", "Darkinyung" },
+	{ "xdc", "Dacian" },
+	{ "xdk", "Dharuk" },
+	{ "xdm", "Edomite" },
+	{ "xdy", "Malayic Dayak" },
+	{ "xeb", "Eblan" },
+	{ "xed", "Hdi" },
+	{ "xeg", "Xegwi" },
+	{ "xel", "Kelo" },
+	{ "xem", "Kembayan" },
+	{ "xep", "Epi-Olmec" },
+	{ "xer", "Xerénte" },
+	{ "xes", "Kesawai" },
+	{ "xet", "Xetá" },
+	{ "xeu", "Keoru-Ahia" },
+	{ "xfa", "Faliscan" },
+	{ "xga", "Galatian" },
+	{ "xgb", "Gbin" },
+	{ "xgd", "Gudang" },
+	{ "xgf", "Gabrielino-Fernandeño" },
+	{ "xgg", "Goreng" },
+	{ "xgi", "Garingbal" },
+	{ "xgl", "Galindan" },
+	{ "xgm", "Guwinmal" },
+	{ "xgr", "Garza" },
+	{ "xgu", "Unggumi" },
+	{ "xgw", "Guwa" },
+	{ "xha", "Harami" },
+	{ "xhc", "Hunnic" },
+	{ "xhd", "Hadrami" },
+	{ "xhe", "Khetrani" },
+	{ "xho", "Xhosa" },
+	{ "xhr", "Hernican" },
+	{ "xht", "Hattic" },
+	{ "xhu", "Hurrian" },
+	{ "xhv", "Khua" },
+	{ "xib", "Iberian" },
+	{ "xii", "Xiri" },
+	{ "xil", "Illyrian" },
+	{ "xin", "Xinca" },
+	{ "xip", "Xipináwa" },
+	{ "xir", "Xiriâna" },
+	{ "xiv", "Indus Valley Language" },
+	{ "xiy", "Xipaya" },
+	{ "xjb", "Minjungbal" },
+	{ "xjt", "Jaitmatang" },
+	{ "xka", "Kalkoti" },
+	{ "xkb", "Northern Nago" },
+	{ "xkc", "Kho'ini" },
+	{ "xkd", "Mendalam Kayan" },
+	{ "xke", "Kereho" },
+	{ "xkf", "Khengkha" },
+	{ "xkg", "Kagoro" },
+	{ "xkh", "Karahawyana" },
+	{ "xki", "Kenyan Sign Language" },
+	{ "xkj", "Kajali" },
+	{ "xkk", "Kaco'" },
+	{ "xkl", "Mainstream Kenyah" },
+	{ "xkn", "Kayan River Kayan" },
+	{ "xko", "Kiorr" },
+	{ "xkp", "Kabatei" },
+	{ "xkq", "Koroni" },
+	{ "xkr", "Xakriabá" },
+	{ "xks", "Kumbewaha" },
+	{ "xkt", "Kantosi" },
+	{ "xku", "Kaamba" },
+	{ "xkv", "Kgalagadi" },
+	{ "xkw", "Kembra" },
+	{ "xkx", "Karore" },
+	{ "xky", "Uma' Lasan" },
+	{ "xkz", "Kurtokha" },
+	{ "xla", "Kamula" },
+	{ "xlb", "Loup B" },
+	{ "xlc", "Lycian" },
+	{ "xld", "Lydian" },
+	{ "xle", "Lemnian" },
+	{ "xlg", "Ligurian (Ancient)" },
+	{ "xli", "Liburnian" },
+	{ "xln", "Alanic" },
+	{ "xlo", "Loup A" },
+	{ "xlp", "Lepontic" },
+	{ "xls", "Lusitanian" },
+	{ "xlu", "Cuneiform Luwian" },
+	{ "xly", "Elymian" },
+	{ "xma", "Mushungulu" },
+	{ "xmb", "Mbonga" },
+	{ "xmc", "Makhuwa-Marrevone" },
+	{ "xmd", "Mbudum" },
+	{ "xme", "Median" },
+	{ "xmf", "Mingrelian" },
+	{ "xmg", "Mengaka" },
+	{ "xmh", "Kuku-Muminh" },
+	{ "xmj", "Majera" },
+	{ "xmk", "Ancient Macedonian" },
+	{ "xml", "Malaysian Sign Language" },
+	{ "xmm", "Manado Malay" },
+	{ "xmn", "Manichaean Middle Persian" },
+	{ "xmo", "Morerebi" },
+	{ "xmp", "Kuku-Mu'inh" },
+	{ "xmq", "Kuku-Mangk" },
+	{ "xmr", "Meroitic" },
+	{ "xms", "Moroccan Sign Language" },
+	{ "xmt", "Matbat" },
+	{ "xmu", "Kamu" },
+	{ "xmv", "Antankarana Malagasy" },
+	{ "xmw", "Tsimihety Malagasy" },
+	{ "xmx", "Maden" },
+	{ "xmy", "Mayaguduna" },
+	{ "xmz", "Mori Bawah" },
+	{ "xna", "Ancient North Arabian" },
+	{ "xnb", "Kanakanabu" },
+	{ "xng", "Middle Mongolian" },
+	{ "xnh", "Kuanhua" },
+	{ "xni", "Ngarigu" },
+	{ "xnk", "Nganakarti" },
+	{ "xnn", "Northern Kankanay" },
+	{ "xno", "Anglo-Norman" },
+	{ "xnr", "Kangri" },
+	{ "xns", "Kanashi" },
+	{ "xnt", "Narragansett" },
+	{ "xnu", "Nukunul" },
+	{ "xny", "Nyiyaparli" },
+	{ "xnz", "Kenzi" },
+	{ "xoc", "O'chi'chi'" },
+	{ "xod", "Kokoda" },
+	{ "xog", "Soga" },
+	{ "xoi", "Kominimung" },
+	{ "xok", "Xokleng" },
+	{ "xom", "Komo (Sudan)" },
+	{ "xon", "Konkomba" },
+	{ "xoo", "Xukurú" },
+	{ "xop", "Kopar" },
+	{ "xor", "Korubo" },
+	{ "xow", "Kowaki" },
+	{ "xpa", "Pirriya" },
+	{ "xpc", "Pecheneg" },
+	{ "xpe", "Liberia Kpelle" },
+	{ "xpg", "Phrygian" },
+	{ "xpi", "Pictish" },
+	{ "xpj", "Mpalitjanh" },
+	{ "xpk", "Kulina Pano" },
+	{ "xpm", "Pumpokol" },
+	{ "xpn", "Kapinawá" },
+	{ "xpo", "Pochutec" },
+	{ "xpp", "Puyo-Paekche" },
+	{ "xpq", "Mohegan-Pequot" },
+	{ "xpr", "Parthian" },
+	{ "xps", "Pisidian" },
+	{ "xpt", "Punthamara" },
+	{ "xpu", "Punic" },
+	{ "xpy", "Puyo" },
+	{ "xqa", "Karakhanid" },
+	{ "xqt", "Qatabanian" },
+	{ "xra", "Krahô" },
+	{ "xrb", "Eastern Karaboro" },
+	{ "xrd", "Gundungurra" },
+	{ "xre", "Kreye" },
+	{ "xrg", "Minang" },
+	{ "xri", "Krikati-Timbira" },
+	{ "xrm", "Armazic" },
+	{ "xrn", "Arin" },
+	{ "xrq", "Karranga" },
+	{ "xrr", "Raetic" },
+	{ "xrt", "Aranama-Tamique" },
+	{ "xru", "Marriammu" },
+	{ "xrw", "Karawa" },
+	{ "xsa", "Sabaean" },
+	{ "xsb", "Sambal" },
+	{ "xsc", "Scythian" },
+	{ "xsd", "Sidetic" },
+	{ "xse", "Sempan" },
+	{ "xsh", "Shamang" },
+	{ "xsi", "Sio" },
+	{ "xsj", "Subi" },
+	{ "xsl", "South Slavey" },
+	{ "xsm", "Kasem" },
+	{ "xsn", "Sanga (Nigeria)" },
+	{ "xso", "Solano" },
+	{ "xsp", "Silopi" },
+	{ "xsq", "Makhuwa-Saka" },
+	{ "xsr", "Sherpa" },
+	{ "xss", "Assan" },
+	{ "xsu", "Sanumá" },
+	{ "xsv", "Sudovian" },
+	{ "xsy", "Saisiyat" },
+	{ "xta", "Alcozauca Mixtec" },
+	{ "xtb", "Chazumba Mixtec" },
+	{ "xtc", "Katcha-Kadugli-Miri" },
+	{ "xtd", "Diuxi-Tilantongo Mixtec" },
+	{ "xte", "Ketengban" },
+	{ "xtg", "Transalpine Gaulish" },
+	{ "xth", "Yitha Yitha" },
+	{ "xti", "Sinicahua Mixtec" },
+	{ "xtj", "San Juan Teita Mixtec" },
+	{ "xtl", "Tijaltepec Mixtec" },
+	{ "xtm", "Magdalena Peñasco Mixtec" },
+	{ "xtn", "Northern Tlaxiaco Mixtec" },
+	{ "xto", "Tokharian A" },
+	{ "xtp", "San Miguel Piedras Mixtec" },
+	{ "xtq", "Tumshuqese" },
+	{ "xtr", "Early Tripuri" },
+	{ "xts", "Sindihui Mixtec" },
+	{ "xtt", "Tacahua Mixtec" },
+	{ "xtu", "Cuyamecalco Mixtec" },
+	{ "xtv", "Thawa" },
+	{ "xtw", "Tawandê" },
+	{ "xty", "Yoloxochitl Mixtec" },
+	{ "xtz", "Tasmanian" },
+	{ "xua", "Alu Kurumba" },
+	{ "xub", "Betta Kurumba" },
+	{ "xud", "Umiida" },
+	{ "xug", "Kunigami" },
+	{ "xuj", "Jennu Kurumba" },
+	{ "xul", "Ngunawal" },
+	{ "xum", "Umbrian" },
+	{ "xun", "Unggaranggu" },
+	{ "xuo", "Kuo" },
+	{ "xup", "Upper Umpqua" },
+	{ "xur", "Urartian" },
+	{ "xut", "Kuthant" },
+	{ "xuu", "Kxoe" },
+	{ "xve", "Venetic" },
+	{ "xvi", "Kamviri" },
+	{ "xvn", "Vandalic" },
+	{ "xvo", "Volscian" },
+	{ "xvs", "Vestinian" },
+	{ "xwa", "Kwaza" },
+	{ "xwc", "Woccon" },
+	{ "xwd", "Wadi Wadi" },
+	{ "xwe", "Xwela Gbe" },
+	{ "xwg", "Kwegu" },
+	{ "xwj", "Wajuk" },
+	{ "xwk", "Wangkumara" },
+	{ "xwl", "Western Xwla Gbe" },
+	{ "xwo", "Written Oirat" },
+	{ "xwr", "Kwerba Mamberamo" },
+	{ "xwt", "Wotjobaluk" },
+	{ "xww", "Wemba Wemba" },
+	{ "xxb", "Boro (Ghana)" },
+	{ "xxk", "Ke'o" },
+	{ "xxm", "Minkin" },
+	{ "xxr", "Koropó" },
+	{ "xxt", "Tambora" },
+	{ "xya", "Yaygir" },
+	{ "xyb", "Yandjibara" },
+	{ "xyj", "Mayi-Yapi" },
+	{ "xyk", "Mayi-Kulan" },
+	{ "xyl", "Yalakalore" },
+	{ "xyt", "Mayi-Thakurti" },
+	{ "xyy", "Yorta Yorta" },
+	{ "xzh", "Zhang-Zhung" },
+	{ "xzm", "Zemgalian" },
+	{ "xzp", "Ancient Zapotec" },
+	{ "yaa", "Yaminahua" },
+	{ "yab", "Yuhup" },
+	{ "yac", "Pass Valley Yali" },
+	{ "yad", "Yagua" },
+	{ "yae", "Pumé" },
+	{ "yaf", "Yaka (Democratic Republic of Congo)" },
+	{ "yag", "Yámana" },
+	{ "yah", "Yazgulyam" },
+	{ "yai", "Yagnobi" },
+	{ "yaj", "Banda-Yangere" },
+	{ "yak", "Yakama" },
+	{ "yal", "Yalunka" },
+	{ "yam", "Yamba" },
+	{ "yan", "Mayangna" },
+	{ "yao", "Yao" },
+	{ "yap", "Yapese" },
+	{ "yaq", "Yaqui" },
+	{ "yar", "Yabarana" },
+	{ "yas", "Nugunu (Cameroon)" },
+	{ "yat", "Yambeta" },
+	{ "yau", "Yuwana" },
+	{ "yav", "Yangben" },
+	{ "yaw", "Yawalapití" },
+	{ "yax", "Yauma" },
+	{ "yay", "Agwagwune" },
+	{ "yaz", "Lokaa" },
+	{ "yba", "Yala" },
+	{ "ybb", "Yemba" },
+	{ "ybe", "West Yugur" },
+	{ "ybh", "Yakha" },
+	{ "ybi", "Yamphu" },
+	{ "ybj", "Hasha" },
+	{ "ybk", "Bokha" },
+	{ "ybl", "Yukuben" },
+	{ "ybm", "Yaben" },
+	{ "ybn", "Yabaâna" },
+	{ "ybo", "Yabong" },
+	{ "ybx", "Yawiyo" },
+	{ "yby", "Yaweyuha" },
+	{ "ych", "Chesu" },
+	{ "ycl", "Lolopo" },
+	{ "ycn", "Yucuna" },
+	{ "ycp", "Chepya" },
+	{ "yda", "Yanda" },
+	{ "ydd", "Eastern Yiddish" },
+	{ "yde", "Yangum Dey" },
+	{ "ydg", "Yidgha" },
+	{ "ydk", "Yoidik" },
+	{ "yds", "Yiddish Sign Language" },
+	{ "yea", "Ravula" },
+	{ "yec", "Yeniche" },
+	{ "yee", "Yimas" },
+	{ "yei", "Yeni" },
+	{ "yej", "Yevanic" },
+	{ "yel", "Yela" },
+	{ "yer", "Tarok" },
+	{ "yes", "Nyankpa" },
+	{ "yet", "Yetfa" },
+	{ "yeu", "Yerukula" },
+	{ "yev", "Yapunda" },
+	{ "yey", "Yeyi" },
+	{ "yga", "Malyangapa" },
+	{ "ygi", "Yiningayi" },
+	{ "ygl", "Yangum Gel" },
+	{ "ygm", "Yagomi" },
+	{ "ygp", "Gepo" },
+	{ "ygr", "Yagaria" },
+	{ "ygu", "Yugul" },
+	{ "ygw", "Yagwoia" },
+	{ "yha", "Baha Buyang" },
+	{ "yhd", "Judeo-Iraqi Arabic" },
+	{ "yhl", "Hlepho Phowa" },
+	{ "yia", "Yinggarda" },
+	{ "yid", "Yiddish" },
+	{ "yif", "Ache" },
+	{ "yig", "Wusa Nasu" },
+	{ "yih", "Western Yiddish" },
+	{ "yii", "Yidiny" },
+	{ "yij", "Yindjibarndi" },
+	{ "yik", "Dongshanba Lalo" },
+	{ "yil", "Yindjilandji" },
+	{ "yim", "Yimchungru Naga" },
+	{ "yin", "Yinchia" },
+	{ "yip", "Pholo" },
+	{ "yiq", "Miqie" },
+	{ "yir", "North Awyu" },
+	{ "yis", "Yis" },
+	{ "yit", "Eastern Lalu" },
+	{ "yiu", "Awu" },
+	{ "yiv", "Northern Nisu" },
+	{ "yix", "Axi Yi" },
+	{ "yiz", "Azhe" },
+	{ "yka", "Yakan" },
+	{ "ykg", "Northern Yukaghir" },
+	{ "yki", "Yoke" },
+	{ "ykk", "Yakaikeke" },
+	{ "ykl", "Khlula" },
+	{ "ykm", "Kap" },
+	{ "ykn", "Kua-nsi" },
+	{ "yko", "Yasa" },
+	{ "ykr", "Yekora" },
+	{ "ykt", "Kathu" },
+	{ "yku", "Kuamasi" },
+	{ "yky", "Yakoma" },
+	{ "yla", "Yaul" },
+	{ "ylb", "Yaleba" },
+	{ "yle", "Yele" },
+	{ "ylg", "Yelogu" },
+	{ "yli", "Angguruk Yali" },
+	{ "yll", "Yil" },
+	{ "ylm", "Limi" },
+	{ "yln", "Langnian Buyang" },
+	{ "ylo", "Naluo Yi" },
+	{ "ylr", "Yalarnnga" },
+	{ "ylu", "Aribwaung" },
+	{ "yly", "Nyâlayu" },
+	{ "ymb", "Yambes" },
+	{ "ymc", "Southern Muji" },
+	{ "ymd", "Muda" },
+	{ "yme", "Yameo" },
+	{ "ymg", "Yamongeri" },
+	{ "ymh", "Mili" },
+	{ "ymi", "Moji" },
+	{ "ymk", "Makwe" },
+	{ "yml", "Iamalele" },
+	{ "ymm", "Maay" },
+	{ "ymn", "Yamna" },
+	{ "ymo", "Yangum Mon" },
+	{ "ymp", "Yamap" },
+	{ "ymq", "Qila Muji" },
+	{ "ymr", "Malasar" },
+	{ "yms", "Mysian" },
+	{ "ymt", "Mator-Taygi-Karagas" },
+	{ "ymx", "Northern Muji" },
+	{ "ymz", "Muzi" },
+	{ "yna", "Aluo" },
+	{ "ynd", "Yandruwandha" },
+	{ "yne", "Lang'e" },
+	{ "yng", "Yango" },
+	{ "ynh", "Yangho" },
+	{ "ynk", "Naukan Yupik" },
+	{ "ynl", "Yangulam" },
+	{ "ynn", "Yana" },
+	{ "yno", "Yong" },
+	{ "ynq", "Yendang" },
+	{ "yns", "Yansi" },
+	{ "ynu", "Yahuna" },
+	{ "yob", "Yoba" },
+	{ "yog", "Yogad" },
+	{ "yoi", "Yonaguni" },
+	{ "yok", "Yokuts" },
+	{ "yol", "Yola" },
+	{ "yom", "Yombe" },
+	{ "yon", "Yongkom" },
+	{ "yor", "Yoruba" },
+	{ "yot", "Yotti" },
+	{ "yox", "Yoron" },
+	{ "yoy", "Yoy" },
+	{ "ypa", "Phala" },
+	{ "ypb", "Labo Phowa" },
+	{ "ypg", "Phola" },
+	{ "yph", "Phupha" },
+	{ "ypm", "Phuma" },
+	{ "ypn", "Ani Phowa" },
+	{ "ypo", "Alo Phola" },
+	{ "ypp", "Phupa" },
+	{ "ypz", "Phuza" },
+	{ "yra", "Yerakai" },
+	{ "yrb", "Yareba" },
+	{ "yre", "Yaouré" },
+	{ "yri", "Yarí" },
+	{ "yrk", "Nenets" },
+	{ "yrl", "Nhengatu" },
+	{ "yrm", "Yirrk-Mel" },
+	{ "yrn", "Yerong" },
+	{ "yrs", "Yarsun" },
+	{ "yrw", "Yarawata" },
+	{ "yry", "Yarluyandi" },
+	{ "ysc", "Yassic" },
+	{ "ysd", "Samatao" },
+	{ "ysg", "Sonaga" },
+	{ "ysl", "Yugoslavian Sign Language" },
+	{ "ysn", "Sani" },
+	{ "yso", "Nisi (China)" },
+	{ "ysp", "Southern Lolopo" },
+	{ "ysr", "Sirenik Yupik" },
+	{ "yss", "Yessan-Mayo" },
+	{ "ysy", "Sanie" },
+	{ "yta", "Talu" },
+	{ "ytl", "Tanglang" },
+	{ "ytp", "Thopho" },
+	{ "ytw", "Yout Wam" },
+	{ "yty", "Yatay" },
+	{ "yua", "Yucateco" },
+	{ "yub", "Yugambal" },
+	{ "yuc", "Yuchi" },
+	{ "yud", "Judeo-Tripolitanian Arabic" },
+	{ "yue", "Yue Chinese" },
+	{ "yuf", "Havasupai-Walapai-Yavapai" },
+	{ "yug", "Yug" },
+	{ "yui", "Yurutí" },
+	{ "yuj", "Karkar-Yuri" },
+	{ "yuk", "Yuki" },
+	{ "yul", "Yulu" },
+	{ "yum", "Quechan" },
+	{ "yun", "Bena (Nigeria)" },
+	{ "yup", "Yukpa" },
+	{ "yuq", "Yuqui" },
+	{ "yur", "Yurok" },
+	{ "yut", "Yopno" },
+	{ "yuu", "Yugh" },
+	{ "yuw", "Yau (Morobe Province)" },
+	{ "yux", "Southern Yukaghir" },
+	{ "yuy", "East Yugur" },
+	{ "yuz", "Yuracare" },
+	{ "yva", "Yawa" },
+	{ "yvt", "Yavitero" },
+	{ "ywa", "Kalou" },
+	{ "ywg", "Yinhawangka" },
+	{ "ywl", "Western Lalu" },
+	{ "ywn", "Yawanawa" },
+	{ "ywq", "Wuding-Luquan Yi" },
+	{ "ywr", "Yawuru" },
+	{ "ywt", "Xishanba Lalo" },
+	{ "ywu", "Wumeng Nasu" },
+	{ "yww", "Yawarawarga" },
+	{ "yxa", "Mayawali" },
+	{ "yxg", "Yagara" },
+	{ "yxl", "Yardliyawarra" },
+	{ "yxm", "Yinwum" },
+	{ "yxu", "Yuyu" },
+	{ "yxy", "Yabula Yabula" },
+	{ "yyr", "Yir Yoront" },
+	{ "yyu", "Yau (Sandaun Province)" },
+	{ "yyz", "Ayizi" },
+	{ "yzg", "E'ma Buyang" },
+	{ "yzk", "Zokhuo" },
+	{ "zaa", "Sierra de Juárez Zapotec" },
+	{ "zab", "San Juan Guelavía Zapotec" },
+	{ "zac", "Ocotlán Zapotec" },
+	{ "zad", "Cajonos Zapotec" },
+	{ "zae", "Yareni Zapotec" },
+	{ "zaf", "Ayoquesco Zapotec" },
+	{ "zag", "Zaghawa" },
+	{ "zah", "Zangwal" },
+	{ "zai", "Isthmus Zapotec" },
+	{ "zaj", "Zaramo" },
+	{ "zak", "Zanaki" },
+	{ "zal", "Zauzou" },
+	{ "zam", "Miahuatlán Zapotec" },
+	{ "zao", "Ozolotepec Zapotec" },
+	{ "zap", "Zapotec" },
+	{ "zaq", "Aloápam Zapotec" },
+	{ "zar", "Rincón Zapotec" },
+	{ "zas", "Santo Domingo Albarradas Zapotec" },
+	{ "zat", "Tabaa Zapotec" },
+	{ "zau", "Zangskari" },
+	{ "zav", "Yatzachi Zapotec" },
+	{ "zaw", "Mitla Zapotec" },
+	{ "zax", "Xadani Zapotec" },
+	{ "zay", "Zayse-Zergulla" },
+	{ "zaz", "Zari" },
+	{ "zbc", "Central Berawan" },
+	{ "zbe", "East Berawan" },
+	{ "zbl", "Blissymbols" },
+	{ "zbt", "Batui" },
+	{ "zbw", "West Berawan" },
+	{ "zca", "Coatecas Altas Zapotec" },
+	{ "zch", "Central Hongshuihe Zhuang" },
+	{ "zdj", "Ngazidja Comorian" },
+	{ "zea", "Zeeuws" },
+	{ "zeg", "Zenag" },
+	{ "zeh", "Eastern Hongshuihe Zhuang" },
+	{ "zen", "Zenaga" },
+	{ "zga", "Kinga" },
+	{ "zgb", "Guibei Zhuang" },
+	{ "zgh", "Standard Moroccan Tamazight" },
+	{ "zgm", "Minz Zhuang" },
+	{ "zgn", "Guibian Zhuang" },
+	{ "zgr", "Magori" },
+	{ "zha", "Zhuang" },
+	{ "zhb", "Zhaba" },
+	{ "zhd", "Dai Zhuang" },
+	{ "zhi", "Zhire" },
+	{ "zhn", "Nong Zhuang" },
+	{ "zho", "Chinese" },
+	{ "zhw", "Zhoa" },
+	{ "zia", "Zia" },
+	{ "zib", "Zimbabwe Sign Language" },
+	{ "zik", "Zimakani" },
+	{ "zil", "Zialo" },
+	{ "zim", "Mesme" },
+	{ "zin", "Zinza" },
+	{ "zir", "Ziriya" },
+	{ "ziw", "Zigula" },
+	{ "ziz", "Zizilivakan" },
+	{ "zka", "Kaimbulawa" },
+	{ "zkb", "Koibal" },
+	{ "zkd", "Kadu" },
+	{ "zkg", "Koguryo" },
+	{ "zkh", "Khorezmian" },
+	{ "zkk", "Karankawa" },
+	{ "zkn", "Kanan" },
+	{ "zko", "Kott" },
+	{ "zkp", "São Paulo Kaingáng" },
+	{ "zkr", "Zakhring" },
+	{ "zkt", "Kitan" },
+	{ "zku", "Kaurna" },
+	{ "zkv", "Krevinian" },
+	{ "zkz", "Khazar" },
+	{ "zlj", "Liujiang Zhuang" },
+	{ "zlm", "Malay (individual language)" },
+	{ "zln", "Lianshan Zhuang" },
+	{ "zlq", "Liuqian Zhuang" },
+	{ "zma", "Manda (Australia)" },
+	{ "zmb", "Zimba" },
+	{ "zmc", "Margany" },
+	{ "zmd", "Maridan" },
+	{ "zme", "Mangerr" },
+	{ "zmf", "Mfinu" },
+	{ "zmg", "Marti Ke" },
+	{ "zmh", "Makolkol" },
+	{ "zmi", "Negeri Sembilan Malay" },
+	{ "zmj", "Maridjabin" },
+	{ "zmk", "Mandandanyi" },
+	{ "zml", "Madngele" },
+	{ "zmm", "Marimanindji" },
+	{ "zmn", "Mbangwe" },
+	{ "zmo", "Molo" },
+	{ "zmp", "Mpuono" },
+	{ "zmq", "Mituku" },
+	{ "zmr", "Maranunggu" },
+	{ "zms", "Mbesa" },
+	{ "zmt", "Maringarr" },
+	{ "zmu", "Muruwari" },
+	{ "zmv", "Mbariman-Gudhinma" },
+	{ "zmw", "Mbo (Democratic Republic of Congo)" },
+	{ "zmx", "Bomitaba" },
+	{ "zmy", "Mariyedi" },
+	{ "zmz", "Mbandja" },
+	{ "zna", "Zan Gula" },
+	{ "zne", "Zande (individual language)" },
+	{ "zng", "Mang" },
+	{ "znk", "Manangkari" },
+	{ "zns", "Mangas" },
+	{ "zoc", "Copainalá Zoque" },
+	{ "zoh", "Chimalapa Zoque" },
+	{ "zom", "Zou" },
+	{ "zoo", "Asunción Mixtepec Zapotec" },
+	{ "zoq", "Tabasco Zoque" },
+	{ "zor", "Rayón Zoque" },
+	{ "zos", "Francisco León Zoque" },
+	{ "zpa", "Lachiguiri Zapotec" },
+	{ "zpb", "Yautepec Zapotec" },
+	{ "zpc", "Choapan Zapotec" },
+	{ "zpd", "Southeastern Ixtlán Zapotec" },
+	{ "zpe", "Petapa Zapotec" },
+	{ "zpf", "San Pedro Quiatoni Zapotec" },
+	{ "zpg", "Guevea De Humboldt Zapotec" },
+	{ "zph", "Totomachapan Zapotec" },
+	{ "zpi", "Santa María Quiegolani Zapotec" },
+	{ "zpj", "Quiavicuzas Zapotec" },
+	{ "zpk", "Tlacolulita Zapotec" },
+	{ "zpl", "Lachixío Zapotec" },
+	{ "zpm", "Mixtepec Zapotec" },
+	{ "zpn", "Santa Inés Yatzechi Zapotec" },
+	{ "zpo", "Amatlán Zapotec" },
+	{ "zpp", "El Alto Zapotec" },
+	{ "zpq", "Zoogocho Zapotec" },
+	{ "zpr", "Santiago Xanica Zapotec" },
+	{ "zps", "Coatlán Zapotec" },
+	{ "zpt", "San Vicente Coatlán Zapotec" },
+	{ "zpu", "Yalálag Zapotec" },
+	{ "zpv", "Chichicapan Zapotec" },
+	{ "zpw", "Zaniza Zapotec" },
+	{ "zpx", "San Baltazar Loxicha Zapotec" },
+	{ "zpy", "Mazaltepec Zapotec" },
+	{ "zpz", "Texmelucan Zapotec" },
+	{ "zqe", "Qiubei Zhuang" },
+	{ "zra", "Kara (Korea)" },
+	{ "zrg", "Mirgan" },
+	{ "zrn", "Zerenkel" },
+	{ "zro", "Záparo" },
+	{ "zrp", "Zarphatic" },
+	{ "zrs", "Mairasi" },
+	{ "zsa", "Sarasira" },
+	{ "zsk", "Kaskean" },
+	{ "zsl", "Zambian Sign Language" },
+	{ "zsm", "Standard Malay" },
+	{ "zsr", "Southern Rincon Zapotec" },
+	{ "zsu", "Sukurum" },
+	{ "zte", "Elotepec Zapotec" },
+	{ "ztg", "Xanaguía Zapotec" },
+	{ "ztl", "Lapaguía-Guivini Zapotec" },
+	{ "ztm", "San Agustín Mixtepec Zapotec" },
+	{ "ztn", "Santa Catarina Albarradas Zapotec" },
+	{ "ztp", "Loxicha Zapotec" },
+	{ "ztq", "Quioquitani-Quierí Zapotec" },
+	{ "zts", "Tilquiapan Zapotec" },
+	{ "ztt", "Tejalapan Zapotec" },
+	{ "ztu", "Güilá Zapotec" },
+	{ "ztx", "Zaachila Zapotec" },
+	{ "zty", "Yatee Zapotec" },
+	{ "zua", "Zeem" },
+	{ "zuh", "Tokano" },
+	{ "zul", "Zulu" },
+	{ "zum", "Kumzari" },
+	{ "zun", "Zuni" },
+	{ "zuy", "Zumaya" },
+	{ "zwa", "Zay" },
+	{ "zxx", "No linguistic content" },
+	{ "zyb", "Yongbei Zhuang" },
+	{ "zyg", "Yang Zhuang" },
+	{ "zyj", "Youjiang Zhuang" },
+	{ "zyn", "Yongnan Zhuang" },
+	{ "zyp", "Zyphe Chin" },
+	{ "zza", "Zaza" },
+	{ "zzj", "Zuojiang Zhuang" },
+};
+static int niso639_3= sizeof( iso639_3 ) / sizeof( iso639_3[0] );
+
+char *
+iso639_3_from_code( const char *code )
+{
+	int i;
+	for ( i=0; i<niso639_3; ++i ) {
+		if ( !strcasecmp( iso639_3[i].code, code ) )
+			return iso639_3[i].language;
+	}
+	return NULL;
+}
diff --git a/bibutils/iso639_3.h b/bibutils/iso639_3.h
new file mode 100644
--- /dev/null
+++ b/bibutils/iso639_3.h
@@ -0,0 +1,9 @@
+/*
+ * iso639_3.h
+ */
+#ifndef ISO639_3_H
+#define iSO639_3_H
+
+extern char * iso639_3_from_code( const char *code );
+
+#endif
diff --git a/bibutils/latex.c b/bibutils/latex.c
--- a/bibutils/latex.c
+++ b/bibutils/latex.c
@@ -63,14 +63,14 @@
    { 230, "{\\ae}",  "\\ae",    ""      }, /* Latin Small ae */
 
                                            /* Latin Capital C */
-   { 199, "{\\c{C}}","\\c{C}",  ""      }, /*               with cedilla */
+   { 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) */
 
                                            /* Latin Small c */
-   { 231, "{\\c{c}}","\\c{c}",  ""      }, /*               with cedilla*/
+   { 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 */
@@ -512,6 +512,8 @@
 	if ( value=='{' || value=='\\' || value=='~' || 
 	     value=='$' || value=='\'' || value=='`' || 
 	     value=='-' || value=='^' ) {
+		if ( *p=='\\' && ( *p=='{' || *p=='}' ) ) {
+		} else {
 		for ( i=0; i<nlatex_chars; ++i ) {
 			q[0] = latex_chars[i].bib1;
 			l[0] = strlen( q[0] );
@@ -526,6 +528,7 @@
 					return latex_chars[i].unicode;
 				}
 			}
+		}
 		}
 	}
 	*unicode = 0;
diff --git a/bibutils/list.c b/bibutils/list.c
--- a/bibutils/list.c
+++ b/bibutils/list.c
@@ -1,9 +1,9 @@
 /*
  * list.c
  *
- * version: 2013-04-02
+ * version: 2014-11-15
  *
- * Copyright (c) Chris Putnam 2004-2013
+ * Copyright (c) Chris Putnam 2004-2014
  *
  * Source code released under the GPL version 2
  *
@@ -18,7 +18,7 @@
 	a->str = NULL;
 	a->max = 0;
 	a->n = 0;
-	a->sorted = 0;
+	a->sorted = 1;
 }
 
 void
@@ -66,27 +66,71 @@
 	return 1;
 }
 
-/*
- * return pointer to newstr 'n', list_getstr() is deprecated
- */
+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_get( list *a, int n )
+list_set( list *a, int n, newstr *s )
 {
 	if ( !list_valid_num( a, n ) ) return NULL;
-	else return &(a->str[n]);
+	newstr_newstrcpy( &(a->str[n]), s );
+	return list_set_cleanup( a, n );
 }
+
 newstr *
-list_getstr( list *a, int n )
+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', list_getstr_char() is deprecated
+ * return pointer to C string 'n'
  *
- * Ensure that a pointer is returned even if the newstr doesn't
- * point to data. Thus we can convert loops like:
+ * 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 );
@@ -113,23 +157,18 @@
 	if ( p ) return p;
 	else return empty;
 }
-char *
-list_getstr_char( list *a, int n )
-{
-	return list_getc( a, n );
-}
 
 static int
 list_alloc( list *a )
 {
 	int i, alloc = 20;
 	a->str = ( newstr* ) malloc( sizeof( newstr ) * alloc );
-	if ( !(a->str) ) return 0;
+	if ( !(a->str) ) return LIST_ERR;
 	a->max = alloc;
 	a->n = 0;
 	for ( i=0; i<alloc; ++i )
 		newstr_init( &(a->str[i]) );
-	return 1;
+	return LIST_OK;
 }
 
 static int
@@ -138,94 +177,122 @@
 	newstr *more;
 	int i, alloc = a->max * 2;
 	more = ( newstr* ) realloc( a->str, sizeof( newstr ) * alloc );
-	if ( !more ) return 0;
+	if ( !more ) return LIST_ERR;
 	a->str = more;
 	for ( i=a->max; i<alloc; ++i )
 		newstr_init( &(a->str[i]) );
 	a->max = alloc;
-	return 1;
+	return LIST_OK;
 }
 
+
 static int
 list_ensure_space( list *a )
 {
-	int ok = 1;
-	if ( a->max==0 ) ok = list_alloc( a );
-	else if ( a->n >= a->max ) ok = list_realloc( a );
-	return ok;
+	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, void *vp, unsigned char mode )
+list_addvp( list *a, unsigned char mode, void *vp )
 {
 	newstr *s = NULL;
-	int ok;
-	ok = list_ensure_space( a );
-	if ( ok ) {
+	int status;
+	status = list_ensure_space( a );
+	if ( status==LIST_OK ) {
 		s = &( a->str[a->n] );
 		if ( mode==LIST_CHR )
-			newstr_strcpy( s, (char*) vp );
+			newstr_strcpy( s, (const char*) vp );
 		else if ( mode==LIST_STR )
 			newstr_newstrcpy( s, (newstr*) vp );
 		else
 			return NULL;
-		a->sorted = 0;
+		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_add( list *a, char *s )
+list_addc( list *a, const char *s )
 {
-	return list_addvp( a, (void*)s, LIST_CHR );
+	return list_addvp( a, LIST_CHR, (void*)s );
 }
 newstr *
-list_addstr( list *a, newstr *s )
+list_add( list *a, newstr *s )
 {
-	return list_addvp( a, (void*)s, LIST_STR );
+	return list_addvp( a, LIST_STR, (void*)s );
 }
 
 newstr *
-list_addvp_unique( list *a, void *vp, unsigned char mode )
+list_addvp_unique( list *a, unsigned char mode, void *vp )
 {
 	newstr *s;
 	int n;
 	if ( mode==LIST_CHR )
-		n = list_find( a, (char*) vp );
+		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, vp, mode );
+	else {
+		s = list_addvp( a, mode, vp );
+	}
 	return s;
 }
 newstr *
-list_add_unique( list *a, char *s )
+list_addc_unique( list *a, const char *s )
 {
-	return list_addvp_unique( a, (void*) s, LIST_CHR );
+	return list_addvp_unique( a, LIST_CHR, (void*)s );
 }
 newstr *
-list_addstr_unique( list *a, newstr *s )
+list_add_unique( list *a, newstr *s )
 {
-	return list_addvp_unique( a, (void*) s, LIST_STR );
+	return list_addvp_unique( a, LIST_STR, (void*)s );
 }
 
 int
-list_adds( list *a, ... )
+list_addvp_all( list *a, unsigned char mode, ... )
 {
-	int ret = 1;
+	int ret = LIST_OK;
 	va_list ap;
 	newstr *s;
-	char *v;
+	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, char * );
+		v = va_arg( ap, newstr * );
 		if ( v ) {
-			s = list_addvp( a, (void*) v, LIST_CHR );
-			if ( s==NULL ) { ret = 0; goto out; }
+			s = list_addvp( a, LIST_STR, (void*)v );
+			if ( s==NULL ) { ret = LIST_ERR; goto out; }
 		}
 	} while ( v );
 out:
@@ -233,43 +300,67 @@
 	return ret;
 }
 
-void
+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 ) {
-		list_addstr( a, &(toadd->str[i]) );
+		s = list_add( a, &(toadd->str[i]) );
+		if ( !s ) return LIST_ERR;
 	}
+	return LIST_OK;
 }
 
-void
+int
 list_append_unique( list *a, list *toadd )
 {
+	newstr *s;
 	int i;
 	for ( i=0; i<toadd->n; ++i ) {
-		list_addstr_unique( a, &(toadd->str[i]) );
+		s = list_add_unique( a, &(toadd->str[i]) );
+		if ( !s ) return LIST_ERR;
 	}
+	return LIST_OK;
 }
 
-void
+int
 list_remove( list *a, int n )
 {
 	int i;
-	if ( !list_valid_num( a, n ) ) return;
-	for ( i=n+1; i<a->n; ++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;
 }
 
-static int
-list_comp( const void *v1, const void *v2 )
+void
+list_swap( list *a, int n1, int n2 )
 {
-	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 );
+	newstr_swapstrings( &(a->str[n1]), &(a->str[n2]) );
 }
 
 void
@@ -280,11 +371,10 @@
 }
 
 static int
-list_find_sorted( list *a, char *searchstr )
+list_find_sorted( list *a, const char *searchstr )
 {
 	int min, max, mid, comp;
 	newstr s, *cs;
-	if ( a->n==0 ) return -1;
 	newstr_init( &s );
 	newstr_strcpy( &s, searchstr );
 	min = 0;
@@ -293,7 +383,10 @@
 		mid = ( min + max ) / 2;
 		cs = list_get( a, mid );
 		comp = list_comp( (void*)cs, (void*) (&s) );
-		if ( comp==0 ) return mid;
+		if ( comp==0 ) {
+			newstr_free( &s );
+			return mid;
+		}
 		else if ( comp > 0 ) max = mid - 1;
 		else if ( comp < 0 ) min = mid + 1;
 	}
@@ -302,7 +395,7 @@
 }
 
 static int
-list_find_simple( list *a, char *searchstr, int nocase )
+list_find_simple( list *a, const char *searchstr, int nocase )
 {
 	int i;
 	if ( nocase ) {
@@ -311,15 +404,16 @@
 				return i;
 	} else {
 		for ( i=0; i<a->n; ++i )
-			if ( !strcmp(a->str[i].data,searchstr) ) 
+			if ( !strcmp(a->str[i].data,searchstr) )
 				return i;
 	}
 	return -1;
 }
 
 int
-list_find( list *a, char *searchstr )
+list_find( list *a, const char *searchstr )
 {
+	if ( a->n==0 ) return -1;
 	if ( a->sorted )
 		return list_find_sorted( a, searchstr );
 	else
@@ -327,86 +421,90 @@
 }
 
 int
-list_findnocase( list *a, char *searchstr )
+list_findnocase( list *a, const char *searchstr )
 {
 	return list_find_simple( a, searchstr, 1 );
 }
 
-/* Return the index of searched-for string.
- * If cannot find string, add to list and then
- * return the index
- */
 int
-list_find_or_add( list *a, char *searchstr )
-{
-	int n = list_find( a, searchstr );
-	if ( n==-1 ) {
-		list_add( a, searchstr );
-		n = a->n - 1;
-	}
-	return n;
-}
-
-void
-list_fillfp( list *a, FILE *fp )
+list_fillfp( list *a, FILE *fp, unsigned char skip_blank_lines )
 {
+	int bufpos = 0, ret = LIST_OK;
+	char buf[512]="";
 	newstr line;
-	char *p, buf[512]="";
-	int  bufpos = 0;
 
-	list_init( a );
+	list_empty( a );
 	newstr_init( &line );
 	while ( newstr_fget( fp, buf, sizeof(buf), &bufpos, &line ) ) {
-		p = &(line.data[0]);
-		if ( *p=='\0' ) continue;
-		if ( !list_add( a, line.data ) ) return;
+		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, char *filename )
+list_fill( list *a, const char *filename, unsigned char skip_blank_lines )
 {
-	FILE *fp = fopen( filename, "r" );
-	if ( !fp ) return 0;
-	list_fillfp( a, fp );
+	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 1;
+
+	return ret;
 }
 
-void
+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 ) return;
-	to->n = to->max = from->n;
-	for ( i=0; i<from->n; ++i ) {
+	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]) );
-		newstr_strcpy( &(to->str[i]), from->str[i].data );
+
+	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 *aold )
+list_dup( list *from )
 {
-	list *anew;
-	int i;
-	anew = ( list* ) malloc( sizeof( list ) );
-	if ( !anew ) goto err0;
-	anew->str = ( newstr* ) malloc( sizeof( newstr ) * aold->n );
-	if ( !anew->str ) goto err1;
-	anew->n = anew->max = aold->n;
-	for ( i=0; i<aold->n; ++i ) {
-		newstr_init( &(anew->str[i]) );
-		newstr_strcpy( &(anew->str[i]), aold->str[i].data );
+	list *to;
+	int ok;
+
+	to = list_new();
+	if ( to ) {
+		ok = list_copy( to, from );
+		if ( !ok ) {
+			list_delete( to );
+			to = NULL;
+		}
 	}
-	return anew;
-err1:
-	free( anew );
-err0:
-	return NULL;
+
+	return to;
 }
 
 int
@@ -431,44 +529,38 @@
 	}
 }
 
-void
-list_tokenize( list *tokens, newstr *in, char delim, int merge_delim )
+int
+list_tokenizec( list *tokens, char *p, const char *delim, int merge_delim )
 {
-	newstr s;
-	char *p;
+	int ret = LIST_OK;
+	newstr s, *t;
+	char *q;
 	list_empty( tokens );
-	p = in->data;
 	newstr_init( &s );
 	while ( p && *p ) {
-		while ( *p && *p!=delim ) newstr_addchar( &s, *p++ );
-		if ( s.len ) list_add( tokens, s.data );
-		else if ( !merge_delim ) list_add( tokens, "" );
-		newstr_empty( &s );
-		if ( *p==delim ) 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;
 }
 
-void
-list_newstrtok( list *t, newstr *s, char *sep )
+int
+list_tokenize( list *tokens, newstr *in, const char *delim, int merge_delim )
 {
-	newstr tmp;
-	char *p;
-	list_empty( t );
-	if ( !s->len ) return;
-	newstr_init( &tmp );
-	p = s->data;
-	while ( *p ) {
-		if ( strchr( sep, *p ) ) {
-			if ( tmp.len ) {
-				list_add( t, tmp.data );
-				newstr_empty( &tmp );
-			}
-		} else newstr_addchar( &tmp, *p );
-		p++;
-	}
-	if ( tmp.len ) list_add( t, tmp.data );
-	newstr_free( &tmp );
+	return list_tokenizec( tokens, in->data, delim, merge_delim );
 }
 
 void
diff --git a/bibutils/list.h b/bibutils/list.h
--- a/bibutils/list.h
+++ b/bibutils/list.h
@@ -1,9 +1,9 @@
 /*
  * list.h
  *
- * version: 2013-04-02
+ * version: 2014-11-15
  *
- * Copyright (c) Chris Putnam 2004-2013
+ * Copyright (c) Chris Putnam 2004-2014
  *
  * Source code released under the GPL version 2
  *
@@ -18,13 +18,17 @@
 #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;
-	int sorted;
 	newstr *str;
+	unsigned char sorted;
 } list;
 
 
@@ -41,40 +45,43 @@
 extern void    list_delete( list * );
 
 extern list*   list_dup( list *a );
-extern void    list_copy( list *to, list *from );
+extern int     list_copy( list *to, list *from );
 
-extern newstr * list_add( list *a, char *value );
-extern newstr * list_addstr( list *a, newstr *value );
-extern newstr * list_addvp( list *a, void *vp, unsigned char mode );
+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_adds( list *a, ... );
+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_add_unique( list *a, char *value );
-extern newstr * list_addstr_unique( list *a, newstr *value );
-extern newstr * list_addvp_unique( list *a, void *vp, unsigned char mode );
+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 void    list_append( list *a, list *toadd );
-extern void    list_append_unique( list *a, list *toadd );
+extern int     list_append( list *a, list *toadd );
+extern int     list_append_unique( list *a, list *toadd );
 
-extern void    list_remove( list *a, int n );
+extern int     list_remove( list *a, int n );
 
 extern newstr* list_get( list *a, int n );
-extern newstr* list_getstr( list *a, int n );
 extern char*   list_getc( list *a, int n );
-extern char*   list_getstr_char( 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 int     list_find( list *a, char *searchstr );
-extern int     list_findnocase( list *a, char *searchstr );
-extern int     list_find_or_add( list *a, char *searchstr );
+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, char *filename );
-extern void    list_fillfp( list *a, FILE *fp );
-extern void    list_tokenize( list *tokens, newstr *in, char delim, int merge_delim );
-extern void    list_newstrtok( list *t, newstr *s, char *sep );
-
+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
diff --git a/bibutils/marc.c b/bibutils/marc.c
--- a/bibutils/marc.c
+++ b/bibutils/marc.c
@@ -1,7 +1,7 @@
 /*
  * marc.c
  *
- * Copyright (c) Chris Putnam 2004-2013
+ * Copyright (c) Chris Putnam 2004-2014
  *
  * Source code released under the GPL version 2
  *
@@ -22,8 +22,10 @@
 		"bibliography",
 		"biography",
 		"book",
+		"calendar",
 		"catalog", 
 		"chart",
+		"comic or graphic novel",
 		"comic strip",
 		"conference publication",
 		"database",
@@ -49,9 +51,12 @@
 		"handbook",
 		"history",
 		"humor, satire",
+		"hymnal",
 		"index",
 		"instruction",
 		"interview",
+		"issue",
+		"journal",
 		"kit",
 		"language instruction",
 		"law report or digest",
@@ -86,6 +91,7 @@
 		"slide",
 		"sound",
 		"speech",
+		"standard or specification",
 		"statistics",
 		"survey of literature",
 		"technical drawing",
@@ -95,7 +101,8 @@
 		"transparency",
 		"treaty",
 		"videorecording",
-		"web site" 
+		"web site",
+		"yearbook",
 	};
 	int nmarc = sizeof( marc ) / sizeof( char* );
 	int i;
@@ -110,11 +117,14 @@
 {
 	char *marc[] = { 
 		"cartographic",
+		"kit",
 		"mixed material",
 		"moving image",
 		"notated music",
 		"software, multimedia",
 		"sound recording",
+		"sound recording - musical",
+		"sound recording - nonmusical",
 		"still image",
 		"text",
 		"three dimensional object"
diff --git a/bibutils/medin.c b/bibutils/medin.c
--- a/bibutils/medin.c
+++ b/bibutils/medin.c
@@ -1,7 +1,7 @@
 /*
  * medin.c
  *
- * Copyright (c) Chris Putnam 2004-2013
+ * Copyright (c) Chris Putnam 2004-2014
  *
  * Source code released under the GPL version 2
  *
@@ -18,6 +18,9 @@
 #include "iso639_2.h"
 #include "bibutils.h"
 
+/*****************************************************
+ PUBLIC: void medin_initparams()
+*****************************************************/
 void
 medin_initparams( param *p, const char *progname )
 {
@@ -48,6 +51,10 @@
 	else p->progname = strdup( progname );
 }
 
+/*****************************************************
+ PUBLIC: int medin_readf()
+*****************************************************/
+
 /*
  * The only difference between MEDLINE and PUBMED in format is
  * that the entire library is wrapped in <MedlineCitationSet>
@@ -108,25 +115,9 @@
 	return haveref;
 }
 
-static inline int
-xml_hasdata( xml *node )
-{
-	if ( node && node->value && node->value->data ) return 1;
-	return 0;
-}
-
-static inline char *
-xml_data( xml *node )
-{
-	return node->value->data;
-}
-
-static inline int
-xml_tagwithdata( xml *node, char *tag )
-{
-	if ( !xml_hasdata( node ) ) return 0;
-	return xml_tagexact( node, tag );
-}
+/*****************************************************
+ PUBLIC: int medin_processf()
+*****************************************************/
 
 typedef struct xml_convert {
 	char *in;       /* The input tag */
@@ -136,75 +127,79 @@
 } xml_convert;
 
 static int
-medin_doconvert( xml *node, fields *info, xml_convert *c, int nc )
+medin_doconvert( xml *node, fields *info, xml_convert *c, int nc, int *found )
 {
-	int i, found = 0;
+	int i, fstatus;
 	char *d;
-	if ( !xml_hasdata( node ) ) return 0;
+	*found = 0;
+	if ( !xml_hasdata( node ) ) return BIBL_OK;
 	d = xml_data( node );
-	for ( i=0; i<nc && found==0; ++i ) {
+	for ( i=0; i<nc && *found==0; ++i ) {
 		if ( c[i].a==NULL ) {
 			if ( xml_tagexact( node, c[i].in ) ) {
-				found = 1;
-				fields_add( info, c[i].out, d, c[i].level );
+				*found = 1;
+				fstatus = fields_add( info, c[i].out, d, c[i].level );
+				if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 			}
 		} else {
 			if ( xml_tag_attrib( node, c[i].in, c[i].a, c[i].aval)){
-				found = 1;
-				fields_add( info, c[i].out, d, c[i].level );
+				*found = 1;
+				fstatus = fields_add( info, c[i].out, d, c[i].level );
+				if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 			}
 		}
 	
 	}
-	return found;
+	return BIBL_OK;
 }
 
 /* <ArticleTitle>Mechanism and.....</ArticleTitle>
  */
-static void
+static int
 medin_articletitle( xml *node, fields *info )
 {
-	if ( xml_hasdata( node ) )
-		fields_add( info, "TITLE", xml_data( node ), 0 );
+	int fstatus, status = BIBL_OK;
+	if ( xml_hasdata( node ) ) {
+		fstatus = fields_add( info, "TITLE", xml_data( node ), 0 );
+		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;
+	}
+	return status;
 }
 
 /*            <MedlineDate>2003 Jan-Feb</MedlineDate> */
-static void
-medin_medlinedate( fields *info, char *string, int level )
+static int
+medin_medlinedate( fields *info, char *p, int level )
 {
+	int fstatus;
 	newstr tmp;
-	char *p, *q;
 
 	newstr_init( &tmp );
 
-	/* extract year */
-	p = string;
-	q = skip_notws( string );
-	newstr_segcpy( &tmp, p, q );
-	fields_add( info, "PARTYEAR", tmp.data, level );
-	q = skip_ws( q );
+	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 );
+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	}
 
-	/* extract month */
-	if ( q ) {
-		p = q;
-		newstr_empty( &tmp );
-		q = skip_notws( q );
-		newstr_segcpy( &tmp, p, q );
+	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, "-", "/" );
-		fields_add( info, "PARTMONTH", tmp.data, level );
-		q = skip_ws( q );
+		fstatus = fields_add( info, "PARTMONTH", tmp.data, level );
+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
 
-	/* extract day */
-	if ( q ) {
-		p = q;
-		newstr_empty( &tmp );
-		q = skip_notws( q );
-		newstr_segcpy( &tmp, p, q );
-		fields_add( info, "PARTDAY", tmp.data, level );
+	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 );
+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
 
 	newstr_free( &tmp );
+
+	return BIBL_OK;
 }
 
 /* <Langauge>eng</Language>
@@ -213,13 +208,16 @@
 medin_language( xml *node, fields *info, int level )
 {
 	char *code, *language;
-	int ok;
+	int fstatus;
 	code = xml_data( node );
-	if ( !code ) return 1;
+	if ( !code ) return BIBL_OK;
 	language = iso639_2_from_code( code );
-	if ( language ) ok = fields_add( info, "LANGUAGE", language, level );
-	else ok = fields_add( info, "LANGUAGE", code, level );
-	return ok;
+	if ( language )
+		fstatus = fields_add( info, "LANGUAGE", language, level );
+	else
+		fstatus = fields_add( info, "LANGUAGE", code, level );
+	if ( fstatus==FIELDS_OK ) return BIBL_OK;
+	else return BIBL_ERR_MEMERR;
 }
 
 /* <Journal>
@@ -250,7 +248,7 @@
  *    <ISOAbbreviation>Alcohol Alcohol.</ISOAbbreviation>
  * </Journal>
  */
-static void
+static int
 medin_journal1( xml *node, fields *info )
 {
 	xml_convert c[] = {
@@ -263,60 +261,87 @@
 		{ "Month",           NULL, NULL, "PARTMONTH",  1 },
 		{ "Day",             NULL, NULL, "PARTDAY",    1 },
 	};
-	int nc = sizeof( c ) / sizeof( c[0] );;
-	if ( xml_hasdata( node ) && !medin_doconvert( node, info, c, nc ) ) {
-		if ( xml_tagexact( node, "MedlineDate" ) )
-			medin_medlinedate( info, xml_data( node ), 1 );
-		if ( xml_tagexact( node, "Language" ) )
-			medin_language( node, info, 1 );
+	int nc = sizeof( c ) / sizeof( c[0] ), status, found;
+	if ( xml_hasdata( 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 );
+				if ( status!=BIBL_OK ) return status;
+			}
+			if ( xml_tagexact( node, "Language" ) ) {
+				status = medin_language( node, info, 1 );
+				if ( status!=BIBL_OK ) return status;
+			}
+		}
 	}
-	if ( node->down ) medin_journal1( node->down, info );
-	if ( node->next ) medin_journal1( node->next, info );
+	if ( node->down ) {
+		status = medin_journal1( node->down, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->next ) {
+		status = medin_journal1( node->next, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	return BIBL_OK;
 }
 
 /* <Pagination>
  *    <MedlinePgn>12111-6</MedlinePgn>
  * </Pagination>
  */
-static void
+static int
 medin_pagination( xml *node, fields *info )
 {
+	int i, fstatus, status;
 	newstr sp, ep;
-	char *p;
-	int i;
+	char *p, *pp;
 	if ( xml_tagexact( node, "MedlinePgn" ) && node->value ) {
 		newstrs_init( &sp, &ep, NULL );
-		p = xml_data( node );
-		while ( *p && *p!='-' )
-			newstr_addchar( &sp, *p++ );
-		if ( *p=='-' ) p++;
-		while ( *p )
-			newstr_addchar( &ep, *p++ );
-		if ( sp.len ) fields_add( info, "PAGESTART", sp.data, 1 );
+		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 );
+			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 ) {
 			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];
-				fields_add( info, "PAGEEND", sp.data, 1 );
-			} else
-				fields_add( info, "PAGEEND", ep.data, 1 );
+				pp = sp.data;
+			} else  pp = ep.data;
+			fstatus = fields_add( info, "PAGEEND", pp, 1 );
+			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 		}
 		newstrs_free( &sp, &ep, NULL );
 	}
-	if ( node->down ) medin_pagination( node->down, info );
-	if ( node->next ) medin_pagination( node->next, info );
+	if ( node->down ) {
+		status = medin_pagination( node->down, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->next ) {
+		status = medin_pagination( node->next, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	return BIBL_OK;
 }
 
 /* <Abstract>
  *    <AbstractText>ljwejrelr</AbstractText>
  * </Abstract>
  */
-static void
+static int
 medin_abstract( xml *node, fields *info )
 {
-	if ( xml_tagwithdata( node, "AbstractText" ) )
-		fields_add( info, "ABSTRACT", xml_data( node ), 0 );
-	else if ( node->next ) medin_abstract( node->next, info );
+	int fstatus;
+	if ( xml_tagwithdata( node, "AbstractText" ) ) {
+		fstatus = fields_add( info, "ABSTRACT", xml_data( node ), 0 );
+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	} else if ( node->next ) return medin_abstract( node->next, info );
+	return BIBL_OK;
 }
 
 /* <AuthorList CompleteYN="Y">
@@ -331,7 +356,7 @@
  *    </Author>
  * </AuthorList>
  */
-static void
+static int
 medin_author( xml *node, newstr *name )
 {
 	char *p;
@@ -357,37 +382,45 @@
 		}
 	}
 	if ( node->next ) medin_author( node->next, name );
+	return BIBL_OK;
 }
 
-static void
+static int
 medin_corpauthor( xml *node, newstr *name )
 {
 	if ( xml_tagexact( node, "CollectiveName" ) ) {
 		newstr_strcpy( name, xml_data( node ) );
 	} else if ( node->next ) medin_corpauthor( node->next, name );
+	return BIBL_OK;
 }
 
-static void
+static int
 medin_authorlist( xml *node, fields *info )
 {
+	int fstatus, status;
 	newstr name;
+	char *tag;
 	newstr_init( &name );
 	node = node->down;
 	while ( node ) {
 		if ( xml_tagexact( node, "Author" ) && node->down ) {
-			medin_author( node->down, &name );
+			status = medin_author( node->down, &name );
+			tag = "AUTHOR";
+			if ( !name.len ) {
+				status = medin_corpauthor( node->down, &name );
+				tag = "AUTHOR:CORP";
+			}
+			if ( newstr_memerr( &name ) || status!=BIBL_OK ) return BIBL_ERR_MEMERR;
 			if ( name.len ) {
-				fields_add(info,"AUTHOR",name.data,0);
-			} else {
-				medin_corpauthor( node->down, &name );
-				if ( name.len )
-					fields_add(info,"AUTHOR:CORP",name.data,0);
+				fstatus = fields_add(info,tag,name.data,0);
+				if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 			}
 			newstr_empty( &name );
 		}
 		node = node->next;
 	}
 	newstr_free( &name );
+	return BIBL_OK;
 }
 
 /* <PublicationTypeList>
@@ -402,13 +435,20 @@
  * </MedlineJournalInfo>
  */
 
-static void
+static int
 medin_journal2( xml *node, fields *info )
 {
-	if ( xml_tagwithdata( node, "MedlineTA" ) && fields_find( info, "TITLE", 1 )==-1 )
-		fields_add( info, "TITLE", xml_data( node ), 1 );
-	if ( node->down ) medin_journal2( node->down, info );
-	if ( node->next ) medin_journal2( node->next, 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 ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	}
+	if ( node->down ) {
+		status = medin_journal2( node->down, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->next ) status = medin_journal2( node->next, info );
+	return status;
 }
 
 /*
@@ -421,20 +461,28 @@
 </MeshHeading>
 </MeshHeadingList>
 */
-static void
+static int
 medin_meshheading( xml *node, fields *info )
 {
-	if ( xml_tagwithdata( node, "DescriptorName" ) )
-		fields_add( info, "KEYWORD", xml_data( node ), 0 );
-	if ( node->next ) medin_meshheading( node->next, info );
+	int fstatus, status = BIBL_OK;
+	if ( xml_tagwithdata( node, "DescriptorName" ) ) {
+		fstatus = fields_add( info, "KEYWORD", xml_data( node ), 0 );
+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	}
+	if ( node->next ) status = medin_meshheading( node->next, info );
+	return status;
 }
 
-static void
+static int
 medin_meshheadinglist( xml *node, fields *info )
 {
-	if ( xml_tagexact( node, "MeshHeading" ) && node->down )
-		medin_meshheading( node->down, info );
-	if ( node->next ) medin_meshheadinglist( node->next, info );
+	int status = BIBL_OK;
+	if ( xml_tagexact( node, "MeshHeading" ) && node->down ) {
+		status = medin_meshheading( node->down, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->next ) status = medin_meshheadinglist( node->next, info );
+	return status;
 }
 
 /* <PubmedData>
@@ -449,8 +497,7 @@
  *
  * I think "pii" is "Publisher Item Identifier"
  */
-
-static void
+static int
 medin_pubmeddata( xml *node, fields *info )
 {
 	xml_convert c[] = {
@@ -459,88 +506,127 @@
 		{ "ArticleId", "IdType", "medline", "MEDLINE", 0 },
 		{ "ArticleId", "IdType", "pii",     "PII",     0 },
 	};
-	int nc = sizeof( c ) / sizeof( c[0] );
-	medin_doconvert( node, info, c, nc );
-	if ( node->next ) medin_pubmeddata( node->next, info );
-	if ( node->down ) medin_pubmeddata( node->down, info );
+	int nc = sizeof( c ) / sizeof( c[0] ), found, status;
+	status = medin_doconvert( node, info, c, nc, &found );
+	if ( status!=BIBL_OK ) return status;
+	if ( node->next ) {
+		status = medin_pubmeddata( node->next, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->down ) {
+		medin_pubmeddata( node->down, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	return BIBL_OK;
 }
 
-static void
+static int
 medin_article( xml *node, fields *info )
 {
-	if ( xml_tagexact( node, "Journal" ) ) 
-		medin_journal1( node, info );
+	int fstatus, status = BIBL_OK;
+	if ( xml_tagexact( node, "Journal" ) )
+		status = medin_journal1( node, info );
 	else if ( xml_tagexact( node, "ArticleTitle" ) )
-		medin_articletitle( node, info );
+		status = medin_articletitle( node, info );
 	else if ( xml_tagexact( node, "Pagination" ) && node->down )
-		medin_pagination( node->down, info );
+		status = medin_pagination( node->down, info );
 	else if ( xml_tagexact( node, "Abstract" ) && node->down )
-		medin_abstract( node->down, info );
+		status = medin_abstract( node->down, info );
 	else if ( xml_tagexact( node, "AuthorList" ) )
-		medin_authorlist( node, info );
+		status = medin_authorlist( node, info );
 	else if ( xml_tagexact( node, "Language" ) )
-		medin_language( node, info, 0 );
-	else if ( xml_tagexact( node, "Affiliation" ) )
-		fields_add( info, "ADDRESS", xml_data( node ), 0 );
-	if ( node->next ) medin_article( node->next, info );
+		status = medin_language( node, info, 0 );
+	else if ( xml_tagexact( node, "Affiliation" ) ) {
+		fstatus = fields_add( info, "ADDRESS", xml_data( 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;
 }
 
-static void
+static int
 medin_medlinecitation( xml *node, fields *info )
 {
-	if ( xml_tagexact( node, "PMID" ) && node->value->data )
-		fields_add( info, "PMID", node->value->data, 0 );
+	int fstatus, status = BIBL_OK;
+	if ( xml_tagexact( node, "PMID" ) && node->value->data ) {
+		fstatus = fields_add( info, "PMID", node->value->data, 0 );
+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	}
 	if ( node->down ) {
-		if ( xml_tagexact( node, "Article" ) )
-			medin_article( node->down, info );
-		else if ( xml_tagexact( node, "MedlineJournalInfo" ) )
-			medin_journal2( node->down, info );
-		else if ( xml_tagexact( node, "MeshHeadingList" ) )
-			medin_meshheadinglist( node->down, info );
+		if ( xml_tagexact( node, "Article" ) ) {
+			status = medin_article( node->down, info );
+		} else if ( xml_tagexact( node, "MedlineJournalInfo" ) ) {
+			status = medin_journal2( node->down, info );
+		} else if ( xml_tagexact( node, "MeshHeadingList" ) )
+			status = medin_meshheadinglist( node->down, info );
+		if ( status!=BIBL_OK ) return status;
 	}
-	if ( node->next ) medin_medlinecitation( node->next, info );
+	if ( node->next ) status = medin_medlinecitation( node->next, info );
+	return status;
 }
 
-static void
+static int
 medin_pubmedarticle( xml *node, fields *info )
 {
+	int status = BIBL_OK;
 	if ( node->down ) {
 		if ( xml_tagexact( node, "MedlineCitation" ) )
-			medin_medlinecitation( node->down, info );
+			status = medin_medlinecitation( node->down, info );
 		else if ( xml_tagexact( node, "PubmedData" ) )
-			medin_pubmeddata( node->down, info );
+			status = medin_pubmeddata( node->down, info );
+		if ( status!=BIBL_OK ) return status;
 	}
-	if ( node->next ) medin_pubmedarticle( node->next, info );
+	if ( node->next ) status = medin_pubmedarticle( node->next, info );
+	return status;
 }
 
-static void
+static int
 medin_assembleref( xml *node, fields *info )
 {
+	int status = BIBL_OK;
 	if ( node->down ) {
 		if ( xml_tagexact( node, "PubmedArticle" ) )
-			medin_pubmedarticle( node->down, info );
+			status = medin_pubmedarticle( node->down, info );
 		else if ( xml_tagexact( node, "MedlineCitation" ) )
-			medin_medlinecitation( node->down, info );
-		else medin_assembleref( node->down, info );
+			status = medin_medlinecitation( node->down, info );
+		else
+			status = medin_assembleref( node->down, info );
 	}
+	if ( status!=BIBL_OK ) return status;
 
-	if ( node->next ) medin_assembleref( node->next, info );
+	if ( node->next ) {
+		status = medin_assembleref( node->next, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+
 	/* assume everything is a journal article */
 	if ( fields_num( info ) ) {
-		fields_add( info, "RESOURCE", "text", 0 );
-		fields_add( info, "ISSUANCE", "continuing", 1 );
-		fields_add( info, "GENRE", "periodical", 1 );
-		fields_add( info, "GENRE", "academic journal", 1 );
+		status = fields_add( info, "RESOURCE", "text", 0 );
+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+		status = fields_add( info, "ISSUANCE", "continuing", 1 );
+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+		status = fields_add( info, "GENRE", "periodical", 1 );
+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+		status = fields_add( info, "GENRE", "academic journal", 1 );
+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+		status = BIBL_OK;
 	}
+
+	return status;
 }
 
 int
 medin_processf( fields *medin, char *data, char *filename, long nref )
 {
+	int status;
 	xml top;
+
 	xml_init( &top );
 	xml_tree( data, &top );
-	medin_assembleref( &top, medin );
+	status = medin_assembleref( &top, medin );
 	xml_free( &top );
-	return 1;
+
+	if ( status==BIBL_OK ) return 1;
+	return 0;
 }
diff --git a/bibutils/medin.h b/bibutils/medin.h
--- a/bibutils/medin.h
+++ b/bibutils/medin.h
@@ -1,7 +1,7 @@
 /*
  * medin.h
  *
- * Copyright (c) Chris Putnam 2004-2013
+ * Copyright (c) Chris Putnam 2004-2014
  *
  * Source code released under the GPL version 2
  *
diff --git a/bibutils/modsin.c b/bibutils/modsin.c
--- a/bibutils/modsin.c
+++ b/bibutils/modsin.c
@@ -1,7 +1,7 @@
 /*
  * modsin.c
  *
- * Copyright (c) Chris Putnam 2004-2013
+ * Copyright (c) Chris Putnam 2004-2014
  *
  * Source code released under the GPL version 2
  *
@@ -10,6 +10,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
+#include "is_ws.h"
 #include "newstr.h"
 #include "newstr_conv.h"
 #include "xml.h"
@@ -19,9 +20,15 @@
 #include "reftypes.h"
 #include "modstypes.h"
 #include "marc.h"
+#include "iso639_1.h"
+#include "iso639_2.h"
+#include "iso639_3.h"
 #include "bibutils.h"
 #include "modsin.h"
 
+/*****************************************************
+ PUBLIC: void modsin_initparams()
+*****************************************************/
 void
 modsin_initparams( param *p, const char *progname )
 {
@@ -55,113 +62,162 @@
 	else p->progname = strdup( progname );
 }
 
+/*****************************************************
+ PUBLIC: int modsin_processf()
+*****************************************************/
+
 static char modsns[]="mods";
 
-static void
+static int
 modsin_detailr( xml *node, newstr *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 ( node->down ) modsin_detailr( node->down, value );
-	if ( node->next ) modsin_detailr( node->next, value );
+	if ( node->down ) {
+		status = modsin_detailr( node->down, value );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->next )
+		status = modsin_detailr( node->next, value );
+	return status;
 }
 
-static void
+static int
 modsin_detail( xml *node, fields *info, int level )
 {
 	newstr type, value, *tp;
+	int fstatus, status = BIBL_OK;
 	if ( node->down ) {
 		newstrs_init( &type, &value, NULL );
 		tp = xml_getattrib( node, "type" );
 		if ( tp ) {
 			newstr_newstrcpy( &type, tp );
 			newstr_toupper( &type );
+			if ( newstr_memerr( &type ) ) goto out;
 		}
-		modsin_detailr( node->down, &value );
+		status = modsin_detailr( node->down, &value );
+		if ( status!=BIBL_OK ) goto out;
 		if ( type.data && !strcasecmp( type.data, "PAGE" ) ) {
-			fields_add( info, "PAGESTART", value.data, level );
-		} else fields_add( info, type.data, value.data, level );
+			fstatus = fields_add( info, "PAGESTART", 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 );
 	}
+	return status;
 }
 
-static void
+static int
 modsin_date( xml *node, fields *info, int level, int part )
 {
-/*	char *month[12] = { "January", "February", "March", "April",
-		"May", "June", "July", "August", "September", "October",
-		"November", "December" };*/
+	int fstatus, status = BIBL_OK;
+	char *tag, *p = NULL;
 	newstr s;
-	char *p = NULL;
-/*	int m;*/
 	if ( node->value ) p = node->value->data;
 	if ( p ) {
 		newstr_init( &s );
-		while ( *p && *p!='-' ) newstr_addchar( &s, *p++ );
-		if ( !part ) fields_add( info, "YEAR", s.data, level );
-		else fields_add( info, "PARTYEAR", s.data, level );
-		if ( *p=='-' ) p++;
-		newstr_empty( &s );
-		while ( *p && *p!='-' ) newstr_addchar( &s, *p++ );
-/*		m = atoi( s.data );*/
-/*		if ( m > 0 && m < 13 )  {
-			if ( !part ) fields_add( info, "MONTH", month[m-1], level );
-			else fields_add( info, "PARTMONTH", month[m-1], level );
-		} else {*/
-			if ( !part ) fields_add( info, "MONTH", s.data, level );
-			else fields_add( info, "PARTMONTH", s.data, level );
-/*		}*/
-		if ( *p=='-' ) p++;
-		newstr_empty( &s );
-		while ( *p ) newstr_addchar( &s, *p++ );
-		if ( !part ) fields_add( info, "DAY", s.data, level );
-		else fields_add( info, "PARTDAY", s.data, level );
+
+		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 );
+			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 );
+			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 );
+			if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }
+		}
+out:
 		newstr_free( &s );
 	}
+	return status;
 }
 
-static void
+static int
 modsin_pager( xml *node, newstr *sp, newstr *ep, newstr *tp, newstr *lp )
 {
+	int status = BIBL_OK;
 	if ( xml_tagexact( node, "start" ) ) {
 		newstr_newstrcpy( sp, node->value );
+		if ( newstr_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;
 	} else if ( xml_tagexact( node, "total" ) ) {
 		newstr_newstrcpy( tp, node->value );
+		if ( newstr_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;
 	}
-	if ( node->down ) modsin_pager( node->down, sp, ep, tp, lp );
-	if ( node->next ) modsin_pager( node->next, sp, ep, tp, lp );
+	if ( node->down ) {
+		status = modsin_pager( node->down, sp, ep, tp, lp );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->next )
+		status = modsin_pager( node->next, sp, ep, tp, lp );
+	return status;
 }
 
-static void
+static int
 modsin_page( xml *node, fields *info, int level )
 {
+	int fstatus, status = BIBL_OK;
 	newstr sp, ep, tp, lp;
-	if ( node->down ) {
-		newstrs_init( &sp, &ep, &tp, &lp, NULL );
-		modsin_pager( node->down, &sp, &ep, &tp, &lp );
-		if ( sp.len || ep.len ) {
-			if ( sp.len )
-				fields_add( info, "PAGESTART", sp.data, level );
-			if ( ep.len )
-				fields_add( info, "PAGEEND", ep.data, level );
-		} else if ( lp.len ) {
-			fields_add( info, "PAGESTART", lp.data, level );
+	xml *dnode = node->down;
+
+	if ( !dnode ) return BIBL_OK;
+
+	newstrs_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 ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }
 		}
-		if ( tp.len )
-			fields_add( info, "TOTALPAGES", tp.data, level );
-		newstrs_free( &sp, &ep, &tp, &lp, NULL );
+		if ( ep.len ) {
+			fstatus = fields_add( info, "PAGEEND", ep.data, level );
+			if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }
+		}
+	} else if ( lp.len ) {
+		fstatus = fields_add( info, "PAGESTART", lp.data, level );
+		if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }
 	}
+	if ( tp.len ) {
+		fstatus = fields_add( info, "TOTALPAGES", tp.data, level );
+		if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }
+	}
+out:
+	newstrs_free( &sp, &ep, &tp, &lp, NULL );
+	return BIBL_OK;
 }
 
-static void
+static int
 modsin_titler( xml *node, newstr *title, newstr *subtitle )
 {
+	int status = BIBL_OK;
 	if ( xml_tagexact( node, "title" ) ) {
 		if ( title->len ) {
 			newstr_strcat( title, " : " );
@@ -169,34 +225,54 @@
 		} else {
 			newstr_newstrcat( title, node->value );
 		}
-	} else if ( xml_tagexact( node, "subTitle" ) )
+		if ( newstr_memerr( title ) ) return BIBL_ERR_MEMERR;
+	} else if ( xml_tagexact( node, "subTitle" ) ) {
 		newstr_newstrcat( subtitle, node->value );
-	if ( node->down ) modsin_titler( node->down, title, subtitle );
-	if ( node->next ) modsin_titler( node->next, title, subtitle );
+		if ( newstr_memerr( subtitle ) ) return BIBL_ERR_MEMERR;
+	}
+	if ( node->down ) {
+		status = modsin_titler( node->down, title, subtitle );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->next )
+		status = modsin_titler( node->next, title, subtitle );
+	return status;
 }
 
-static void
+static int
 modsin_title( xml *node, fields *info, int level )
 {
+	char *titletag[2][2] = {
+		{ "TITLE",    "SHORTTITLE" },
+		{ "SUBTITLE", "SHORTSUBTITLE" },
+	};
+	int fstatus, status = BIBL_OK;
 	newstr title, subtitle;
-	int abbr = xml_tag_attrib( node, "titleInfo", "type", "abbreviated" );
-	if ( node->down ) {
-		newstrs_init( &title, &subtitle, NULL );
-		modsin_titler( node->down, &title, &subtitle );
-		if ( title.len ) {
-			if ( abbr )
-				fields_add( info, "SHORTTITLE", title.data, level );
-			else
-				fields_add( info, "TITLE", title.data, level );
-		}
-		if ( subtitle.len ) {
-			if ( abbr )
-				fields_add( info, "SHORTSUBTITLE", subtitle.data, level );
-			else
-				fields_add( info, "SUBTITLE", subtitle.data, level );
-		}
-		newstrs_free( &title, &subtitle, NULL );
+	xml *dnode = node->down;
+	int abbr;
+
+	dnode = node->down;
+	if ( !dnode ) return status;
+
+	newstrs_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 ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }
 	}
+
+	if ( subtitle.len ) {
+		fstatus = fields_add( info, titletag[1][abbr], subtitle.data, level );
+		if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }
+	}
+
+out:
+	newstrs_free( &title, &subtitle, NULL );
+	return status;
 }
 
 /* modsin_marcrole_convert()
@@ -207,7 +283,7 @@
  * Take input strings with roles separated by '|' characters, e.g.
  * "author" or "author|creator" or "edt" or "editor|edt".
  */
-static void
+static int
 modsin_marcrole_convert( newstr *s, char *suffix, newstr *out )
 {
 	convert roles[] = {
@@ -228,7 +304,7 @@
 		{ "pth",                 "ASSIGNEE" }
 	};
 	int nroles = sizeof( roles ) / sizeof( roles[0] );
-	int i, nmismatch, n = -1;
+	int i, nmismatch, n = -1, status = BIBL_OK;
 	char *p, *q;
 
 	if ( s->len == 0 ) {
@@ -259,25 +335,36 @@
 	} else {
 		newstr_strcpy( out, s->data );
 	}
+	if ( newstr_memerr( out ) ) status = BIBL_ERR_MEMERR;
+	return status;
 }
 
-static void
+static int
 modsin_asis_corp_r( xml *node, newstr *name, newstr *role )
 {
-	if ( xml_tagexact( node, "namePart" ) )
+	int status = BIBL_OK;
+	if ( xml_tagexact( node, "namePart" ) ) {
 		newstr_newstrcpy( name, node->value );
-	else if ( xml_tagexact( node, "roleTerm" ) ) {
+		if ( newstr_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 ( node->down ) modsin_asis_corp_r( node->down, name, role );
-	if ( node->next ) modsin_asis_corp_r( node->next, name, role );
+	if ( node->down ) {
+		status = modsin_asis_corp_r( node->down, name, role );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->next )
+		status = modsin_asis_corp_r( node->next, name, role );
+	return status;
 }
 
-static void
+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" ) ) {
@@ -297,150 +384,242 @@
 		if ( roles->len ) newstr_addchar( roles, '|' );
 		newstr_newstrcat( roles, node->value );
 	}
-	if ( node->down ) modsin_personr( node->down, name, suffix, roles );
-	if ( node->next ) modsin_personr( node->next, name, suffix, roles );
+	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 void
+static int
 modsin_asis_corp( xml *node, fields *info, int level, char *suffix )
 {
+	int fstatus, status = BIBL_OK;
 	newstr name, roles, role_out;
 	xml *dnode = node->down;
 	if ( dnode ) {
 		newstrs_init( &name, &roles, &role_out, NULL );
-		modsin_asis_corp_r( dnode, &name, &roles );
-		modsin_marcrole_convert( &roles, suffix, &role_out );
-		fields_add( info, role_out.data, name.data, level );
+		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 );
+		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;
+out:
 		newstrs_free( &name, &roles, &role_out, NULL );
 	}
+	return status;
 }
 
-static void
+static int
 modsin_person( xml *node, fields *info, int level )
 {
-	newstr name, suffix, roles, role, role_out;
+	newstr name, suffix, roles, role_out;
+	int fstatus, status = BIBL_OK;
 	xml *dnode = node->down;
 	if ( dnode ) {
-		newstrs_init( &name, &suffix, &role, &roles, &role_out, NULL );
-		modsin_personr( dnode, &name, &suffix, &roles );
-		modsin_marcrole_convert( &roles, NULL, &role_out );
+		newstrs_init( &name, &suffix, &roles, &role_out, NULL );
+
+		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; }
 		}
-		fields_add( info, role_out.data, name.data, level );
-		newstrs_free( &name, &suffix, &role, &roles, NULL );
+
+		status = modsin_marcrole_convert( &roles, NULL, &role_out );
+		if ( status!=BIBL_OK ) goto out;
+
+		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 );
 	}
+	return status;
 }
 
-static void
-modsin_placeterm( xml *node, fields *info, int level, int school )
+static int
+modsin_placeterm_text( xml *node, fields *info, int level, int school )
 {
-	char address_tag[] = "ADDRESS",
-	     addresscode_tag[] = "CODEDADDRESS",
-	     school_tag[] = "SCHOOL",
-	     *newtag;
-	newstr *type, s;
+	char address_tag[] = "ADDRESS";
+	char school_tag[]  = "SCHOOL";
+	char *tag;
+	int fstatus;
 
-	newtag = ( school ) ? school_tag : address_tag;
+	tag = ( school ) ? school_tag : address_tag;
 
+	fstatus = fields_add( info, tag, xml_data( node ), level );
+	if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+
+	return BIBL_OK;
+}
+
+static int
+modsin_placeterm_code( xml *node, fields *info, int level )
+{
+	int fstatus, status = BIBL_OK;
+	newstr s, *auth;
+
+	newstr_init( &s );
+
+	auth = xml_getattrib( node, "authority" );
+	if ( auth && auth->len ) {
+		newstr_newstrcpy( &s, auth );
+		newstr_addchar( &s, '|' );
+	}
+	newstr_newstrcat( &s, node->value );
+
+	if ( newstr_memerr( &s ) ) {
+		status = BIBL_ERR_MEMERR;
+		goto out;
+	}
+
+	fstatus = fields_add( info, "CODEDADDRESS", s.data, level );
+	if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;
+out:
+	newstr_free( &s );
+	return status;
+}
+
+static int
+modsin_placeterm( xml *node, fields *info, int level, int school )
+{
+	int status = BIBL_OK;
+	newstr *type;
+
 	type = xml_getattrib( node, "type" );
 	if ( type && type->len ) {
-		if ( !strcmp( type->data, "text" ) ) {
-			fields_add( info, newtag, node->value->data, level );
-		} else if ( !strcmp( type->data, "code" ) ) {
-			newstr_init( &s );
-			type = xml_getattrib( node, "authority" );
-			if ( type && type->len ) newstr_newstrcpy(&s, type);
-			newstr_addchar( &s, '|' );
-			newstr_newstrcat( &s, node->value );
-			fields_add( info, addresscode_tag, s.data, level );
-			newstr_free( &s );
-		}
+		if ( !strcmp( type->data, "text" ) )
+			status = modsin_placeterm_text( node, info, level, school );
+		else if ( !strcmp( type->data, "code" ) )
+			status = modsin_placeterm_code( node, info, level );
 	}
+
+	return status;
 }
 
-static void
+static int
 modsin_placer( xml *node, fields *info, int level, int school )
 {
+	int status = BIBL_OK;
 	if ( xml_tag_attrib( node, "place", "type", "school" ) ) {
 		school = 1;
 	} else if ( xml_tagexact( node, "placeTerm" ) ) {
-		modsin_placeterm( node, info, level, school );
+		status = modsin_placeterm( node, info, level, school );
 	}
-	if ( node->down ) modsin_placer( node->down, info, level, school );
-	if ( node->next ) modsin_placer( node->next, info, level, school );
+	if ( node->down ) {
+		status = modsin_placer( node->down, info, level, school );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->next ) status = modsin_placer( node->next, info, level, school );
+	return status;
 }
 
-static void
+static int
 modsin_origininfor( xml *node, fields *info, int level, newstr *pub, newstr *add, newstr *addc, newstr *ed, newstr *iss )
 {
+	int status = BIBL_OK;
 	if ( xml_tagexact( node, "dateIssued" ) )
-		modsin_date( node, info, level, 0 );
-	else if ( xml_tagexact( node, "publisher" ) )
+		status = modsin_date( node, info, level, 0 );
+	else if ( xml_tagexact( node, "publisher" ) && xml_hasdata( node ) ) {
 		newstr_newstrcat( pub, node->value );
-	else if ( xml_tagexact( node, "edition" ) )
+		if ( newstr_memerr( pub ) ) return BIBL_ERR_MEMERR;
+	} else if ( xml_tagexact( node, "edition" ) && xml_hasdata( node ) ) {
 		newstr_newstrcat( ed, node->value );
-	else if ( xml_tagexact( node, "issuance" ) )
+		if( newstr_memerr( ed ) ) return BIBL_ERR_MEMERR;
+	} else if ( xml_tagexact( node, "issuance" ) && xml_hasdata( node ) ) {
 		newstr_newstrcat( iss, node->value );
-	else if ( xml_tagexact( node, "place" ) )
-		modsin_placer( node, info, level, 0 );
-	if ( node->down )
-		modsin_origininfor( node->down, info, level, pub, add, 
-				addc, ed, iss );
-	if ( node->next ) modsin_origininfor( node->next, info, level, pub, add, addc, ed, iss );
+		if ( newstr_memerr( iss ) ) return BIBL_ERR_MEMERR;
+	} else if ( xml_tagexact( node, "place" ) && xml_hasdata( node ) )
+		status = modsin_placer( node, info, level, 0 );
+	if ( status!=BIBL_OK ) return status;
+	if ( node->down ) {
+		status = modsin_origininfor( node->down, info, level, pub, add, addc, ed, iss );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->next )
+		status = modsin_origininfor( node->next, info, level, pub, add, addc, ed, iss );
+	return status;
 }
 
-static void
+static int
 modsin_origininfo( xml *node, fields *info, int level )
 {
 	newstr publisher, address, addcode, edition, issuance;
+	int fstatus, status = BIBL_OK;
 	if ( node->down ) {
 		newstrs_init( &publisher, &address, &addcode, &edition, &issuance, NULL );
-		modsin_origininfor( node->down, info, level, &publisher, 
+		status = modsin_origininfor( node->down, info, level, &publisher, 
 				&address, &addcode, &edition, &issuance );
-		if ( publisher.len )
-			fields_add( info, "PUBLISHER", publisher.data, level );
-		if ( address.len )
-			fields_add( info, "ADDRESS", address.data, level );
-		if ( addcode.len )
-			fields_add( info, "CODEDADDRESS", addcode.data, level );
-		if ( edition.len )
-			fields_add( info, "EDITION", edition.data, level );
-		if ( issuance.len ) 
-			fields_add( info, "ISSUANCE", issuance.data, level );
+		if ( status!=BIBL_OK ) goto out;
+		if ( publisher.len ) {
+			fstatus = fields_add( info, "PUBLISHER", publisher.data, level );
+			if ( fstatus!=FIELDS_OK ) { status=BIBL_ERR_MEMERR; goto out; }
+		}
+		if ( address.len ) {
+			fstatus = fields_add( info, "ADDRESS", address.data, level );
+			if ( fstatus!=FIELDS_OK ) { status=BIBL_ERR_MEMERR; goto out; }
+		}
+		if ( addcode.len ) {
+			fstatus = fields_add( info, "CODEDADDRESS", addcode.data, level );
+			if ( fstatus!=FIELDS_OK ) { status=BIBL_ERR_MEMERR; goto out; }
+		}
+		if ( edition.len ) {
+			fstatus = fields_add( info, "EDITION", edition.data, level );
+			if ( fstatus!=FIELDS_OK ) { status=BIBL_ERR_MEMERR; goto out; }
+		}
+		if ( issuance.len ) {
+			fstatus = fields_add( info, "ISSUANCE", issuance.data, level );
+			if ( fstatus!=FIELDS_OK ) { status=BIBL_ERR_MEMERR; goto out; }
+		}
+out:
 		newstrs_free( &publisher, &address, &addcode, &edition, &issuance, NULL );
 	}
+	return status;
 }
 
-static void
+static int
 modsin_subjectr( xml *node, fields *info, int level )
 {
+	int fstatus, status = BIBL_OK;
 	if ( xml_tagexact( node, "topic" ) || xml_tagexact( node, "geographic" )) {
-		fields_add( info, "KEYWORD", node->value->data, level );
+		fstatus = fields_add( info, "KEYWORD", node->value->data, level );
+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
-	if ( node->down ) modsin_subjectr( node->down, info, level );
-	if ( node->next ) modsin_subjectr( node->next, info, level );
+	if ( node->down ) {
+		status = modsin_subjectr( node->down, info, level );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->next ) status = modsin_subjectr( node->next, info, level );
+	return status;
 }
 
-static void
+static int
 modsin_subject( xml *node, fields *info, int level )
 {
-	if ( node->down ) modsin_subjectr( node->down, info, level );
+	int status = BIBL_OK;
+	if ( node->down ) status = modsin_subjectr( node->down, info, level );
+	return status;
 }
 
-static void
+static int
 modsin_id1( xml *node, fields *info, int level )
 {
+	int fstatus;
 	newstr *ns;
 	ns = xml_getattrib( node, "ID" );
-	if ( ns ) {
-		fields_add( info, "REFNUM", ns->data, level );
+	if ( ns && ns->len ) {
+		fstatus = fields_add( info, "REFNUM", ns->data, level );
+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
+	return BIBL_OK;
 }
 
-static void
+static int
 modsin_genre( xml *node, fields *info, int level )
 {
 	char *added[] = { "manuscript", "academic journal", "magazine",
@@ -451,181 +630,234 @@
 		"press release", "television broadcast", "electronic"
 	};
 	int nadded = sizeof( added ) /sizeof( char *);
-	int j, ismarc = 0, isadded = 0;
-	if ( node->value && node->value->len ) {
-		if ( marc_findgenre( node->value->data )!=-1 ) ismarc = 1;
-		for ( j=0; j<nadded && ismarc==0 && isadded==0; ++j ) {
-			if ( !strcasecmp( node->value->data, added[j] ) )
-				isadded = 1;
-		}
-		if ( ismarc || isadded ) 
-			fields_add( info, "GENRE", node->value->data, level );
-		else
-			fields_add( info, "NGENRE", node->value->data, level );
+	int i, ismarc = 0, isadded = 0, fstatus;
+	char *d;
+
+	if ( !xml_hasdata( node ) ) return BIBL_OK;
+	d = xml_data( node );
+	if ( marc_findgenre( d )!=-1 ) ismarc = 1;
+	if ( !ismarc ) {
+		for ( i=0; i<nadded && ismarc==0 && isadded==0; ++i )
+			if ( !strcasecmp( d, added[i] ) ) isadded = 1;
 	}
-}
 
-static void
-modsin_resource( xml *node, fields *info, int level )
-{
-	if ( node->value && node->value->len )
-		fields_add( info, "RESOURCE", node->value->data, level );
+	if ( ismarc || isadded ) 
+		fstatus = fields_add( info, "GENRE", d, level );
+	else
+		fstatus = fields_add( info, "NGENRE", d, level );
+	if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+
+	return BIBL_OK;
 }
 
-static void
+/* in MODS version 3.5
+ * <languageTerm type="text">....</languageTerm>
+ * <languageTerm type="code" authority="xxx">...</languageTerm>
+ * xxx = rfc3066
+ * xxx = iso639-2b
+ * xxx = iso639-3
+ * xxx = rfc4646
+ * xxx = rfc5646
+ */
+static int
 modsin_languager( xml *node, fields *info, int level )
 {
-	if ( xml_tag_attrib( node, "languageTerm", "type", "text" ) ) {
-		if ( node->value && node->value->len )
-			fields_add( info, "LANGUAGE", node->value->data, level );
+	int fstatus, status = BIBL_OK;
+	char *d = NULL;
+	if ( xml_tagexact( node, "languageTerm" ) ) {
+		if ( xml_hasdata( node ) ) {
+			if ( xml_hasattrib( node, "type", "code" ) ) {
+				if ( xml_hasattrib( node, "authority", "iso639-1" ) )
+					d = iso639_1_from_code( xml_data( node ) );
+				else if ( xml_hasattrib( node, "authority", "iso639-2b" ) )
+					d = iso639_2_from_code( xml_data( node ) );
+				else if ( xml_hasattrib( node, "authority", "iso639-3" ))
+					d = iso639_3_from_code( xml_data( node ) );
+			}
+			if ( !d ) d  = xml_data( node );
+			fstatus = fields_add( info, "LANGUAGE", d, level );
+			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+		}
 	}
-	if ( node->next ) modsin_languager( node->next, info, level );
+	if ( node->next ) status = modsin_languager( node->next, info, level );
+	return status;
 }
 
-static void
+static int
 modsin_language( xml *node, fields *info, int level )
 {
+	int fstatus, status = BIBL_OK;
 	/* Old versions of MODS had <language>English</language> */
-	if ( node->value && node->value->len )
-		fields_add( info, "LANGUAGE", node->value->data, level );
+	if ( xml_hasdata( node ) ) {
+		fstatus = fields_add( info, "LANGUAGE", xml_data( node ), level );
+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	}
 
 	/* New versions of MODS have <language><languageTerm>English</languageTerm></language> */
-	if ( node->down ) modsin_languager( node->down, info, level );
-}
-
-static void
-modsin_toc( xml *node, fields *info, int level )
-{
-	if ( node->value && node->value->len )
-		fields_add( info, "CONTENTS", node->value->data, level );
-}
-
-static void
-modsin_note( xml *node, fields *info, int level )
-{
-	if ( node->value && node->value->len )
-		fields_add( info, "NOTES", node->value->data, level );
-}
-
-static void
-modsin_annote( xml *node, fields *info, int level )
-{
-	if ( node->value && node->value->len )
-		fields_add( info, "ANNOTE", node->value->data, level );
+	if ( node->down ) status = modsin_languager( node->down, info, level );
+	return status;
 }
 
-static void
-modsin_abstract( xml *node, fields *info, int level )
+static int
+modsin_simple( xml *node, fields *info, char *tag, int level )
 {
-	if ( node->value && node->value->len )
-		fields_add( info, "ABSTRACT", node->value->data, level );
+	int fstatus;
+	if ( xml_hasdata( node ) ) {
+		fstatus = fields_add( info, tag, xml_data( node ), level );
+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	}
+	return BIBL_OK;
 }
 
-static void
+static int
 modsin_locationr( xml *node, fields *info, int level )
 {
-	char url[]="URL", school[]="SCHOOL", loc[]="LOCATION";
-	char fileattach[]="FILEATTACH", *tag=NULL;
-
-	if ( xml_tag_attrib( node, "url", "access", "raw object" ) ) {
-		tag = fileattach;
-	} else if ( xml_tagexact( node, "url" ) ) {
-		tag = url;
-	}
+	int fstatus, status = BIBL_OK;
+	char *tag=NULL;
 
-	if ( xml_tag_attrib( node, "physicalLocation", "type", "school" ) ) {
-		tag = school;
+	if ( xml_tagexact( node, "url" ) ) {
+		if ( xml_hasattrib( node, "access", "raw object" ) )
+			tag = "FILEATTACH";
+		else
+			tag = "URL";
 	} else if ( xml_tagexact( node, "physicalLocation" ) ) {
-		tag = loc;
+		if ( xml_hasattrib( node, "type", "school" ) )
+			tag = "SCHOOL";
+		else
+			tag = "LOCATION";
 	}
 
-	if ( tag ) fields_add( info, tag, node->value->data, level );
+	if ( tag ) {
+		fstatus = fields_add( info, tag, node->value->data, level );
+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	}
 
-	if ( node->down ) modsin_locationr( node->down, info, level );
-	if ( node->next ) modsin_locationr( node->next, info, level );
+	if ( node->down ) {
+		status = modsin_locationr( node->down, info, level );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->next ) status = modsin_locationr( node->next, info, level );
+	return status;
 }
 
-static void
+static int
 modsin_location( xml *node, fields *info, int level )
 {
-	if ( node->down ) modsin_locationr( node->down, info, level );
+	int status = BIBL_OK;
+	if ( node->down ) status = modsin_locationr( node->down, info, level );
+	return status;
 }
 
-static void
+static int
 modsin_descriptionr( xml *node, newstr *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;
 	}
-	if ( node->down ) modsin_descriptionr( node->down, s );
-	if ( node->next ) modsin_descriptionr( node->next, s );
+	if ( node->down ) {
+		status = modsin_descriptionr( node->down, s );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->next ) status = modsin_descriptionr( node->next, s );
+	return status;
 }
 
-static void
+static int
 modsin_description( xml *node, fields *info, int level )
 {
+	int fstatus, status = BIBL_OK;
 	newstr s;
 	newstr_init( &s );
-	if ( node->down ) modsin_descriptionr( node->down, &s );
-	else {
-		if ( node->value && node->value->data );
-		newstr_newstrcpy( &s, node->value );
+	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 ) ) {
+			status = BIBL_ERR_MEMERR;
+			goto out;
+		}
 	}
-	if ( s.len ) fields_add( info, "DESCRIPTION", s.data, level );
+	if ( s.len ) {
+		fstatus = fields_add( info, "DESCRIPTION", s.data, level );
+		if ( fstatus!=FIELDS_OK ) {
+			status = BIBL_ERR_MEMERR;
+			goto out;
+		}
+	}
+out:
 	newstr_free( &s );
+	return BIBL_OK;
 }
 
-static void
+static int
 modsin_partr( xml *node, fields *info, int level )
 {
+	int status = BIBL_OK;
 	if ( xml_tagexact( node, "detail" ) )
-		modsin_detail( node, info, level );
+		status = modsin_detail( node, info, level );
 	else if ( xml_tag_attrib( node, "extent", "unit", "page" ) )
-		modsin_page( node, info, level );
+		status = modsin_page( node, info, level );
 	else if ( xml_tag_attrib( node, "extent", "unit", "pages" ) )
-		modsin_page( node, info, level );
+		status = modsin_page( node, info, level );
 	else if ( xml_tagexact( node, "date" ) )
-		modsin_date( node, info, level, 1 );
-	if ( node->next ) modsin_partr( node->next, info, level );
+		status = modsin_date( node, info, level, 1 );
+	if ( status!=BIBL_OK ) return status;
+	if ( node->next ) status = modsin_partr( node->next, info, level );
+	return status;
 }
 
-static void
+static int
 modsin_part( xml *node, fields *info, int level )
 {
-	if ( node->down ) modsin_partr( node->down, info, level );
+	if ( node->down ) return modsin_partr( node->down, info, level );
+	return BIBL_OK;
 }
 
 /* <classification authority="lcc">Q3 .A65</classification> */
-static void
+static int
 modsin_classification( xml *node, fields *info, int level )
 {
-	if ( node->value && node->value->len ) {
-		if (xml_tag_attrib(node, "classification", "authority", "lcc")){
-			fields_add( info, "LCC", node->value->data, level );
-		} else
-		 fields_add( info, "CLASSIFICATION", node->value->data, level );
+	int fstatus, status = BIBL_OK;
+	char *tag, *d;
+	if ( xml_hasdata( node ) ) {
+		d = xml_data( node );
+		if ( xml_tag_attrib( node, "classification", "authority", "lcc" ) )
+			tag = "LCC";
+		else
+			tag = "CLASSIFICATION";
+		fstatus = fields_add( info, tag, d, level );
+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
-	if ( node->down ) modsin_classification( node->down, info, level );
+	if ( node->down ) status = modsin_classification( node->down, info, level );
+	return status;
 }
 
-static void
+static int
 modsin_recordinfo( xml *node, fields *info, int level )
 {
+	int fstatus;
 	xml *curr;
+	char *d;
 
 	/* extract recordIdentifier */
 	curr = node;
 	while ( curr ) {
-		if ( xml_tagexact( curr, "recordIdentifier" ) ) {
-			fields_add( info, "REFNUM", curr->value->data, level );
+		if ( xml_tagexact( curr, "recordIdentifier" ) && xml_hasdata( curr ) ) {
+			d = xml_data( curr );
+			fstatus = fields_add( info, "REFNUM", d, level );
+			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 		}
 		curr = curr->next;
 	}
-
+	return BIBL_OK;
 }
 
-static void
+static int
 modsin_identifier( xml *node, fields *info, int level )
 {
 	convert ids[] = {
@@ -645,87 +877,118 @@
 		{ "accessnum",     "ACCESSNUM"    },
 		{ "jstor",         "JSTOR"        },
 	};
-	int i , n = sizeof( ids ) / sizeof( ids[0] );
-	if ( !node->value || !node->value->data ) return;
+	int i, fstatus, n = sizeof( ids ) / sizeof( ids[0] );
+	if ( !node->value || node->value->len==0 ) return BIBL_OK;
 	for ( i=0; i<n; ++i ) {
-		if ( xml_tag_attrib( node, "identifier", "type", ids[i].mods ) )
-			fields_add( info, ids[i].internal, node->value->data, level );
+		if ( xml_tag_attrib( node, "identifier", "type", ids[i].mods ) ) {
+			fstatus = fields_add( info, ids[i].internal, node->value->data, level );
+			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+		}
 	}
+	return BIBL_OK;
 }
 
-static void
+static int
 modsin_mods( xml *node, fields *info, int level )
 {
-	if ( xml_tagexact( node, "titleInfo" ) )
-		modsin_title( node, info, level );
-	else if ( xml_tag_attrib( node, "name", "type", "personal" ) )
-		modsin_person( node, info, level );
-	else if ( xml_tag_attrib( node, "name", "type", "corporate" ) )
-		modsin_asis_corp( node, info, level, ":CORP" );
-	else if ( xml_tagexact( node, "name" ) )
-		modsin_asis_corp( node, info, level, ":ASIS" );
-	else if ( xml_tagexact( node, "recordInfo" ) && node->down )
-		modsin_recordinfo( node->down, info, level );
-	else if  ( xml_tagexact( node, "part" ) )
-		modsin_part( node, info, level );
-	else if ( xml_tagexact( node, "identifier" ) )
-		modsin_identifier( node, info, level );
-	else if ( xml_tagexact( node, "originInfo" ) )
-		modsin_origininfo( node, info, level );
-	else if ( xml_tagexact( node, "typeOfResource" ) )
-		modsin_resource( node, info, level );
-	else if ( xml_tagexact( node, "language" ) )
-		modsin_language( node, info, level );
-	else if ( xml_tagexact( node, "tableOfContents" ) )
-		modsin_toc( node, info, level );
-	else if ( xml_tagexact( node, "genre" ) )
-		modsin_genre( node, info, level );
-	else if ( xml_tagexact( node, "date" ) )
-		modsin_date( node, info, level, 0 );
-	else if ( xml_tagexact( node, "note" ) )
-		modsin_note( node, info, level );
-	else if ( xml_tagexact( node, "bibtex-annote" ) )
-		modsin_annote( node, info, level );
-	else if ( xml_tagexact( node, "abstract" ) )
-		modsin_abstract( node, info, level );
-	else if ( xml_tagexact( node, "subject" ) )
-		modsin_subject( node, info, level );
-	else if ( xml_tagexact( node, "classification" ) )
-		modsin_classification( node, info, level );
-	else if ( xml_tagexact( node, "location" ) )
-		modsin_location( node, info, level );
-	else if ( xml_tagexact( node, "physicalDescription" ) )
-		modsin_description( node, info, level );
-	else if ( xml_tag_attrib( node, "relatedItem", "type", "host" ) ||
-		  xml_tag_attrib( node, "relatedItem", "type", "series" ) ) {
-		if ( node->down ) modsin_mods( node->down, info, level+1 );
+	convert simple[] = {
+		{ "note",            "NOTES" },
+		{ "abstract",        "ABSTRACT" },
+		{ "bibtex-annote",   "ANNOTE" },
+		{ "typeOfResource",  "RESOURCE" },
+		{ "tableOfContents", "CONTENTS" },
+	};
+	int nsimple = sizeof( simple ) / sizeof( simple[0] );
+	int i, found = 0, status = BIBL_OK;
+
+	for ( i=0; i<nsimple && found==0; i++ ) {
+		if ( xml_tagexact( node, simple[i].mods ) ) {
+			status = modsin_simple( node, info, simple[i].internal, level );
+			if ( status!=BIBL_OK ) return status;
+			found = 1;
+		}
 	}
 
-	if ( node->next ) modsin_mods( node->next, info, level );
+	if ( !found ) {
+		if ( xml_tagexact( node, "titleInfo" ) )
+			modsin_title( node, info, level );
+		else if ( xml_tag_attrib( node, "name", "type", "personal" ) )
+			status = modsin_person( node, info, level );
+		else if ( xml_tag_attrib( node, "name", "type", "corporate" ) )
+			status = modsin_asis_corp( node, info, level, ":CORP" );
+		else if ( xml_tagexact( node, "name" ) )
+			status = modsin_asis_corp( node, info, level, ":ASIS" );
+		else if ( xml_tagexact( node, "recordInfo" ) && node->down )
+			status = modsin_recordinfo( node->down, info, level );
+		else if  ( xml_tagexact( node, "part" ) )
+			modsin_part( node, info, level );
+		else if ( xml_tagexact( node, "identifier" ) )
+			status = modsin_identifier( node, info, level );
+		else if ( xml_tagexact( node, "originInfo" ) )
+			status = modsin_origininfo( node, info, level );
+		else if ( xml_tagexact( node, "language" ) )
+			status = modsin_language( node, info, level );
+		else if ( xml_tagexact( node, "genre" ) )
+			status = modsin_genre( node, info, level );
+		else if ( xml_tagexact( node, "date" ) )
+			status = modsin_date( node, info, level, 0 );
+		else if ( xml_tagexact( node, "subject" ) )
+			status = modsin_subject( node, info, level );
+		else if ( xml_tagexact( node, "classification" ) )
+			status = modsin_classification( node, info, level );
+		else if ( xml_tagexact( node, "location" ) )
+			status = modsin_location( node, info, level );
+		else if ( xml_tagexact( node, "physicalDescription" ) )
+			status = modsin_description( node, info, level );
+		else if ( xml_tag_attrib( node, "relatedItem", "type", "host" ) ||
+			  xml_tag_attrib( node, "relatedItem", "type", "series" ) ) {
+			if ( node->down ) status = modsin_mods( node->down, info, level+1 );
+		}
+		if ( status!=BIBL_OK ) return status;
+	}
 
+	if ( node->next ) status = modsin_mods( node->next, info, level );
+
+	return status;
 }
 
-static void
+static int
 modsin_assembleref( xml *node, fields *info )
 {
+	int status = BIBL_OK;
 	if ( xml_tagexact( node, "mods" ) ) {
-		modsin_id1( node, info, 0 );
-		if ( node->down ) modsin_mods( node->down, info, 0 );
-	} else if ( node->down ) modsin_assembleref( node->down, info );
-	if ( node->next ) modsin_assembleref( node->next, info );
+		status = modsin_id1( node, info, 0 );
+		if ( status!=BIBL_OK ) return status;
+		if ( node->down ) {
+			status = modsin_mods( node->down, info, 0 );
+			if ( status!=BIBL_OK ) return status;
+		}
+	} else if ( node->down ) {
+		status = modsin_assembleref( node->down, info );
+		if ( status!=BIBL_OK ) return status;
+	}
+	if ( node->next ) status = modsin_assembleref( node->next, info );
+	return status;
 }
 
 int
 modsin_processf( fields *modsin, char *data, char *filename, long nref )
 {
+	int status;
 	xml top;
+
 	xml_init( &top );
 	xml_tree( data, &top );
-	modsin_assembleref( &top, modsin );
+	status = modsin_assembleref( &top, modsin );
 	xml_free( &top );
-	return 1;
+
+	if ( status==BIBL_OK ) return 1;
+	else return 0;
 }
 
+/*****************************************************
+ PUBLIC: int modsin_readf()
+*****************************************************/
 
 static char *
 modsin_startptr( char *p )
diff --git a/bibutils/modsin.h b/bibutils/modsin.h
--- a/bibutils/modsin.h
+++ b/bibutils/modsin.h
@@ -1,7 +1,7 @@
 /*
  * modsin.h
  *
- * Copyright (c) Chris Putnam 2004-2013
+ * Copyright (c) Chris Putnam 2004-2014
  *
  * Source code released under the GPL version 2
  *
diff --git a/bibutils/modsout.c b/bibutils/modsout.c
--- a/bibutils/modsout.c
+++ b/bibutils/modsout.c
@@ -1,7 +1,7 @@
 /*
  * modsout.c
  *
- * Copyright (c) Chris Putnam 2003-2013
+ * Copyright (c) Chris Putnam 2003-2014
  *
  * Source code released under the GPL version 2
  *
@@ -30,7 +30,7 @@
 	p->latexout         = 0;
 	p->utf8out          = 1;
 	p->utf8bom          = 1;
-	p->xmlout           = 1;
+	p->xmlout           = BIBL_XMLOUT_TRUE;
 	p->nosplittitle     = 0;
 	p->verbose          = 0;
 	p->addcount         = 0;
@@ -386,6 +386,7 @@
 		{ "issuance",	  "ISSUANCE",	0 },
 		{ "publisher",	  "PUBLISHER",	0 },
 		{ "place",	  "ADDRESS",	1 },
+		{ "place",	  "AUTHORADDRESS",	0 },
 		{ "edition",	  "EDITION",	0 },
 		{ "dateCaptured", "URLDATE",    0 }
 	};
@@ -571,9 +572,10 @@
 static int
 output_partpages( fields *f, FILE *outptr, int level, int wrote_header )
 {
-	convert parts[3] = {
+	convert parts[4] = {
 		{ "",  "PAGESTART",                -1 },
 		{ "",  "PAGEEND",                  -1 },
+		{ "",  "PAGES",                    -1 },
 		{ "",  "TOTALPAGES",               -1 }
 	};
 	int nparts = sizeof(parts)/sizeof(parts[0]);
@@ -591,13 +593,16 @@
 			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[2].code, "page", level ); 
+					parts[3].code, "page", level );
 	}
 	/* If both PAGESTART and PAGEEND are defined */
 	else {
 		mods_output_extents( f, outptr, parts[0].code, 
-			parts[1].code, parts[2].code, "page", level ); 
+			parts[1].code, parts[3].code, "page", level );
 	}
 
 	return 1;
@@ -763,6 +768,7 @@
 {
 	convert sn_types[] = {
 		{ "isbn",      "ISBN",      0 },
+		{ "isbn",      "ISBN13",    0 },
 		{ "lccn",      "LCCN",      0 },
 		{ "issn",      "ISSN",      0 },
 		{ "citekey",   "REFNUM",    0 },
diff --git a/bibutils/modsout.h b/bibutils/modsout.h
--- a/bibutils/modsout.h
+++ b/bibutils/modsout.h
@@ -1,7 +1,7 @@
 /*
  * modsout.h
  *
- * Copyright (c) Chris Putnam 2003-2013
+ * Copyright (c) Chris Putnam 2003-2014
  *
  * Source code released under the GPL version 2
  *
diff --git a/bibutils/name.c b/bibutils/name.c
--- a/bibutils/name.c
+++ b/bibutils/name.c
@@ -3,7 +3,7 @@
  *
  * mangle names w/ and w/o commas
  *
- * Copyright (c) Chris Putnam 2004-2013
+ * Copyright (c) Chris Putnam 2004-2014
  *
  * Source code released under the GPL version 2
  *
@@ -363,13 +363,14 @@
 int
 name_addmultielement( fields *info, char *tag, list *tokens, int begin, int end, int level )
 {
+	int status, ok = 1;
 	newstr name;
-	int ok;
 
 	newstr_init( &name );
 
 	name_construct_multi( &name, tokens, begin, end );
-	ok = fields_add( info, tag, name.data, level );
+	status = fields_add( info, tag, name.data, level );
+	if ( status!=FIELDS_OK ) ok = 0;
 
 	newstr_free( &name );
 
@@ -386,13 +387,14 @@
 int
 name_addsingleelement( fields *info, char *tag, char *name, int level, int corp )
 {
+	int status, ok = 1;
 	newstr outtag;
-	int ok;
 	newstr_init( &outtag );
 	newstr_strcpy( &outtag, tag );
 	if ( !corp ) newstr_strcat( &outtag, ":ASIS" );
 	else newstr_strcat( &outtag, ":CORP" );
-	ok = fields_add( info, outtag.data, name, level );
+	status = fields_add( info, outtag.data, name, level );
+	if ( status!=FIELDS_OK ) ok = 0;
 	newstr_free( &outtag );
 	return ok;
 }
@@ -428,7 +430,7 @@
 	}
 
 	newstr_findreplace( inname, ",", ", " );
-	list_tokenize( &tokens, inname, ' ', 1 );
+	list_tokenize( &tokens, inname, " ", 1 );
 
 	if ( tokens.n==1 ) {
 		newstr_newstrcpy( outname, inname );
@@ -486,7 +488,7 @@
 int
 name_add( fields *info, char *tag, char *q, int level, list *asis, list *corps )
 {
-	int ok, nametype, ret = 1;
+	int ok, status, nametype, ret = 1;
 	newstr inname, outname;
 	list tokens;
 
@@ -500,10 +502,12 @@
 		q = name_copy( &inname, q );
 
 		nametype = name_parse( &outname, &inname, asis, corps );
-		if ( !nametype ) return 0;
+		if ( !nametype ) { ret = 0; goto out; }
 
-		if ( nametype==1 )
-			ok = fields_add( info, tag, outname.data, level );
+		if ( nametype==1 ) {
+			status = fields_add( info, tag, outname.data, level );
+			ok = ( status==FIELDS_OK ) ? 1 : 0;
+		}
 		else if ( nametype==2 )
 			ok = name_addsingleelement( info, tag, outname.data, level, 0 );
 		else
@@ -515,7 +519,7 @@
 
 out:
 	newstrs_free( &inname, &outname, NULL );
-	newstr_free( &outname );
+	list_free( &tokens );
 
 	return ret;
 }
diff --git a/bibutils/name.h b/bibutils/name.h
--- a/bibutils/name.h
+++ b/bibutils/name.h
@@ -3,7 +3,7 @@
  *
  * mangle names w/ and w/o commas
  *
- * Copyright (c) Chris Putnam 2004-2013
+ * Copyright (c) Chris Putnam 2004-2014
  *
  * Source code released under the GPL version 2
  *
diff --git a/bibutils/newstr.c b/bibutils/newstr.c
--- a/bibutils/newstr.c
+++ b/bibutils/newstr.c
@@ -1,9 +1,9 @@
 /*
  * newstr.c
  *
- * Version: 04/21/13
+ * Version: 04/27/14
  *
- * Copyright (c) Chris Putnam 1999-2013
+ * Copyright (c) Chris Putnam 1999-2014
  *
  * Source code released under the GPL version 2
  *
@@ -20,10 +20,17 @@
 #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 
@@ -43,11 +50,8 @@
 	s->dim = size;
 }
 
-/* define as no-op */
-static inline void
-newstr_nullify( newstr *s )
-{
-}
+/* define as a no-op */
+#define newstr_nullify( s )
 
 #else
 
@@ -91,7 +95,7 @@
 }
 
 void
-newstr_initstr( newstr *s, char *initstr )
+newstr_initstr( newstr *s, const char *initstr )
 {
 	assert( s );
 	assert( initstr );
@@ -113,15 +117,27 @@
 	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;
-	char *cp;
+	const char *cp;
 	newstr_empty( s );
 	va_start( ap, s );
 	do {
-		cp = va_arg( ap, char * );
+		cp = va_arg( ap, const char * );
 		if ( cp ) newstr_strcat( s, cp );
 	} while ( cp );
 	va_end( ap );
@@ -180,6 +196,14 @@
 }
 
 void
+newstr_delete( newstr *s )
+{
+	assert( s );
+	newstr_free( s );
+	free( s );
+}
+
+void
 newstr_empty( newstr *s )
 {
 	assert( s );
@@ -208,10 +232,11 @@
 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 );
+		newstr_realloc( s, s->len*2 );
 	s->data[s->len++] = newchar;
 	s->data[s->len] = '\0';
 }
@@ -224,8 +249,8 @@
  * Since we can progress more than one byte at p, return the
  * properly updated pointer p.
  */
-char *
-newstr_addutf8( newstr *s, char *p )
+const char *
+newstr_addutf8( newstr *s, const char *p )
 {
 	if ( ! ((*p) & 128 ) ) {
 		newstr_addchar( s, *p );
@@ -247,11 +272,12 @@
 }
 
 void
-newstr_prepend( newstr *s, char *addstr )
+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 {
@@ -276,7 +302,7 @@
 }
 
 static inline void 
-newstr_strcat_internal( newstr *s, char *addstr, unsigned long n )
+newstr_strcat_internal( newstr *s, const char *addstr, unsigned long n )
 {
 	newstr_strcat_ensurespace( s, n );
 	strncat( &(s->data[s->len]), addstr, n );
@@ -293,7 +319,7 @@
 }
 
 void
-newstr_strcat( newstr *s, char *addstr )
+newstr_strcat( newstr *s, const char *addstr )
 {
 	unsigned long n;
 	assert( s && addstr );
@@ -304,41 +330,78 @@
 void
 newstr_segcat( newstr *s, char *startat, char *endat )
 {
-	size_t seglength;
-	char *p, *q;
+	unsigned long n;
+	char *p;
 
 	assert( s && startat && endat );
 	assert( (size_t) startat < (size_t) endat );
 
-	seglength=(size_t) endat - (size_t) startat;
-	if ( !s->data || !s->dim )
-		newstr_initalloc( s, seglength+1 );
-	else {
-		if ( s->len + seglength + 1 > s->dim )
-			newstr_realloc( s, s->len + seglength+1 );
-	}
-	q = &(s->data[s->len]);
+	if ( startat==endat ) return;
+
+	n = 0;
 	p = startat;
-	while ( *p && p!=endat ) *q++ = *p++;
-	*q = '\0';
-	s->len += seglength;
+	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 ( n+1 > s->dim ) 
+	else if ( m > s->dim )
 		newstr_realloc( s, m );
 }
 
 static inline void
-newstr_strcpy_internal( newstr *s, char *p, unsigned long n )
+newstr_strcpy_internal( newstr *s, const char *p, unsigned long n )
 {
 	newstr_strcpy_ensurespace( s, n );
-	strcpy( s->data, p );
+	strncpy( s->data, p, n );
+	s->data[n] = '\0';
 	s->len = n;
 }
 
@@ -352,7 +415,7 @@
 }
 
 void 
-newstr_strcpy( newstr *s, char *addstr )
+newstr_strcpy( newstr *s, const char *addstr )
 {
 	unsigned long n;
 	assert( s && addstr );
@@ -360,65 +423,63 @@
 	newstr_strcpy_internal( s, addstr, n );
 }
 
-newstr *
-newstr_strdup( char *s1 )
+/* newstr_segcpy( s, start, end );
+ *
+ * copies [start,end) into s
+ */
+void
+newstr_segcpy( newstr *s, char *startat, char *endat )
 {
-	newstr *s2 = newstr_new();
-	if ( s2 )
-		newstr_strcpy( s2, s1 );
-	return s2;
+	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] to in[stop] (includes stop) into s
+ * copies in[start,stop) (excludes stop) into s
  */
 void
-newstr_indxcpy( newstr *s, char *p, int start, int stop )
+newstr_indxcpy( newstr *s, char *p, unsigned long start, unsigned long stop )
 {
-	int i;
-	assert( s );
-	assert( p );
+	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 )
+	for ( i=start; i<stop; ++i )
 		s->data[i-start] = p[i];
-	s->data[i] = '\0';
-	s->len = stop-start+1;
-}
-
-void
-newstr_indxcat( newstr *s, char *p, int start, int stop )
-{
-	int i;
-	assert( s );
-	assert( p );
-	assert( start <= stop );
-	for ( i=start; i<=stop; ++i )
-		newstr_addchar( s, p[i] );
+	s->len = stop-start;
+	s->data[s->len] = '\0';
 }
 
-/* newstr_segcpy( s, start, end );
- *
- * copies [start,end) into s
- */
-void
-newstr_segcpy( newstr *s, char *startat, char *endat )
+newstr *
+newstr_strdup( const char *s1 )
 {
-	size_t n;
-	char *p, *q;
-
-	assert( s && startat && endat );
-	assert( ((size_t) startat) <= ((size_t) endat) );
-
-	n = (size_t) endat - (size_t) startat;
-	newstr_strcpy_ensurespace( s, n );
-	q = s->data;
-	p = startat;
-	while ( *p && p!=endat ) *q++ = *p++;
-	*q = '\0';
-	s->len = n;
+	newstr *s2 = newstr_new();
+	if ( s2 )
+		newstr_strcpy( s2, s1 );
+	return s2;
 }
 
 void
@@ -446,7 +507,7 @@
  */
 
 int
-newstr_findreplace( newstr *s, char *find, char *replace )
+newstr_findreplace( newstr *s, const char *find, const char *replace )
 {
 	long diff;
 	size_t findstart, searchstart;
@@ -503,6 +564,7 @@
 {
 	int  bufpos = *pbufpos, done = 0;
 	char *ok;
+	assert( fp && outs );
 	newstr_empty( outs );
 	while ( !done ) {
 		while ( buf[bufpos] && buf[bufpos]!='\r' && buf[bufpos]!='\n' )
@@ -573,29 +635,26 @@
 void
 newstr_trimstartingws( newstr *s )
 {
-	unsigned char still_ws;
-	unsigned long n, m;
+	char *p, *q;
+	int n;
 
 	assert( s );
 
 	if ( s->len==0 || !is_ws( s->data[0] ) ) return;
 
-	m = n = 0;
-	still_ws = 1;
-	while ( m <= s->len ) {
-		if ( still_ws && !is_ws( s->data[ m ] ) ) {
-			still_ws = 0;
-		}
-		if ( !still_ws ) {
-			s->data[ n ] = s->data[ m ];
-			n++;
-		}
-		m++;
+	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 )
@@ -610,6 +669,7 @@
 int
 newstr_match_first( newstr *s, char ch )
 {
+	assert( s );
 	if ( !s->len ) return 0;
 	if ( s->data[0] == ch ) return 1;
 	return 0;
@@ -618,37 +678,81 @@
 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, int n )
+newstr_trimbegin( newstr *s, unsigned long n )
 {
-	int i;
+	char *p, *q;
+
 	assert( s );
-	if ( s->len - n < 1 ) newstr_empty( s );
-	for ( i=1; i<=s->len; ++i ) /* pick up '\0' with '<=' */
-		s->data[i-1] = s->data[i];
-	s->len -= n;
+
+	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, int n )
+newstr_trimend( newstr *s, unsigned long n )
 {
 	assert( s );
-	if ( s->len - n < 1 ) newstr_empty( s );
-	else {
-		s->len -= n;
-		s->data[ s->len ] = '\0';
+
+	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;
@@ -709,31 +813,28 @@
 }
 
 int
-newstr_newstrcmp( newstr *s, newstr *t )
+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 )
 {
-	newstr ns;
-	unsigned long i;
-
+	unsigned long i, max;
+	char tmp;
 	assert( s );
-
-	if ( s->len==0 ) return;
-	newstr_init( &ns );
-	i = s->len;
-	do {
-		i--;
-		newstr_addchar( &ns, s->data[i] );
-	} while ( i>0 );
-	newstr_swapstrings( s, &ns );
-	newstr_free( &ns );
+	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
@@ -741,11 +842,15 @@
 {
 	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 ) eol = 1;
+		if ( ch == EOF ) {
+			if ( s->len ) return 1;
+			else return 0;
+		}
 		else if ( ch == '\n' ) eol = 1;
 		else if ( ch == '\r' ) {
 			ch = fgetc( fp );
@@ -761,14 +866,15 @@
 /*
  * s = "Hi!\0", s.len = 3
  *
- * newstr_char( s, 0 ) = 'H'  newstr_revchar( s, 0 ) = '\0'
- * newstr_char( s, 1 ) = 'i'  newstr_revchar( s, 1 ) = '!'
- * newstr_char( s, 2 ) = '!'  newstr_revchar( s, 2 ) = 'i'
- * newstr_char( s, 3 ) = '\0' newstr_revchar( s, 3 ) = 'H'
+ * 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 ];
 }
@@ -776,6 +882,20 @@
 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 ];
+	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 );
 }
diff --git a/bibutils/newstr.h b/bibutils/newstr.h
--- a/bibutils/newstr.h
+++ b/bibutils/newstr.h
@@ -1,9 +1,9 @@
 /*
  * newstr.h
  *
- * Version: 04/21/13
+ * Version: 04/27/14
  *
- * Copyright (c) Chris Putnam 1999-2013
+ * Copyright (c) Chris Putnam 1999-2014
  *
  * Source code released under the GPL version 2
  *
@@ -20,9 +20,10 @@
 }  newstr;
 
 newstr *newstr_new         ( void ); 
+void    newstr_delete      ( newstr *s );
 
 void    newstr_init        ( newstr *s );
-void    newstr_initstr     ( newstr *s, char *initstr );
+void    newstr_initstr     ( newstr *s, const char *initstr );
 void    newstr_empty       ( newstr *s );
 void    newstr_free        ( newstr *s );
 
@@ -31,52 +32,70 @@
 void    newstrs_free       ( newstr *s, ... );
 
 void newstr_mergestrs   ( newstr *s, ... );
-newstr *newstr_strdup   ( char *buf );
+newstr *newstr_strdup   ( const char *p );
 void newstr_addchar     ( newstr *s, char newchar );
 void newstr_reverse     ( newstr *s );
-char *newstr_addutf8    ( newstr *s, char *p );
-void newstr_strcat      ( newstr *s, char *addstr );
+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 );
-void newstr_prepend     ( newstr *s, char *addstr );
-void newstr_strcpy      ( newstr *s, char *addstr );
+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, int start, int stop );
-void newstr_indxcat     ( newstr *s, char *p, int start, int stop );
+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, char *find, char *replace );
+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, int n );
-void newstr_trimend     ( newstr *s, int n );
+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    ( newstr *s, newstr *t );
+int  newstr_newstrcmp    ( const newstr *s, const newstr *t );
 
-/* NEWSTR_PARANOIA
+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
  */
 
-#undef NEWSTR_PARANOIA
+/* #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
 
diff --git a/bibutils/newstr_conv.c b/bibutils/newstr_conv.c
--- a/bibutils/newstr_conv.c
+++ b/bibutils/newstr_conv.c
@@ -1,7 +1,7 @@
 /*
  * newstr_conv.c
  *
- * Copyright (c) Chris Putnam 1999-2013
+ * Copyright (c) Chris Putnam 1999-2014
  *
  * Source code released under the GPL version 2
  *
@@ -50,13 +50,13 @@
 }
 
 static void
-addutf8char( newstr *s, unsigned int ch, int xmlout, int utf8out )
+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 > 1 )
+		if ( ch > 127 && xmlout == NEWSTR_CONV_XMLOUT_ENTITIES )
 			{ addentity( s, ch ); return; }
 	}
 	nc = utf8_encode( ch, code );
@@ -65,13 +65,13 @@
 }
 
 static void
-addgb18030char( newstr *s, unsigned int ch, int xmlout, int utf8out )
+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 > 1 )
+		if ( ch > 127 && xmlout == NEWSTR_CONV_XMLOUT_ENTITIES )
 			{ addentity( s, ch ); return; }
 	}
 	nc = gb18030_encode( ch, code );
@@ -89,7 +89,7 @@
 	 * output the unicode.
 	 */
 	if ( utf8out && !strcmp( buf, "?" ) ) {
-		addutf8char( s, ch, xmlout, utf8out );
+		addutf8char( s, ch, xmlout );
 	} else {
 		newstr_strcat( s, buf );
 	}
@@ -151,9 +151,9 @@
 	if ( latexout ) {
 		addlatexchar( s, ch, xmlout, utf8out );
 	} else if ( utf8out ) {
-		addutf8char( s, ch, xmlout, utf8out );
+		addutf8char( s, ch, xmlout );
 	} else if ( charsetout==CHARSET_GB18030 ) {
-		addgb18030char( s, ch, xmlout, utf8out );
+		addgb18030char( s, ch, xmlout );
 	} else {
 		c = charset_lookupuni( charsetout, ch );
 		if ( xmlout ) addxmlchar( s, c );
@@ -173,9 +173,9 @@
 	unsigned int pos = 0;
 	unsigned int ch;
 	newstr ns;
-	int ok;
+	int ok = 1;
 
-	if ( !s || s->len==0 ) return 1;
+	if ( !s || s->len==0 ) return ok;
 
 	newstr_init( &ns );
 
@@ -185,13 +185,13 @@
 	while ( s->data[pos] ) {
 		ch = get_unicode( s, &pos, charsetin, latexin, utf8in, xmlin );
 		ok = write_unicode( &ns, ch, charsetout, latexout, utf8out, xmlout );
-		if ( !ok ) return 0;
+		if ( !ok ) goto out;
 	}
 
 	newstr_swapstrings( s, &ns );
-
+out:
 	newstr_free( &ns );
 
-	return 1;
+	return ok;
 }
 
diff --git a/bibutils/newstr_conv.h b/bibutils/newstr_conv.h
--- a/bibutils/newstr_conv.h
+++ b/bibutils/newstr_conv.h
@@ -1,13 +1,17 @@
 /*
  * newstring_conv.h
  *
- * Copyright (c) Chris Putnam 1999-2013
+ * 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"
 
diff --git a/bibutils/risin.c b/bibutils/risin.c
--- a/bibutils/risin.c
+++ b/bibutils/risin.c
@@ -1,7 +1,7 @@
 /*
  * risin.c
  *
- * Copyright (c) Chris Putnam 2003-2013
+ * Copyright (c) Chris Putnam 2003-2014
  *
  * Source code released under the GPL version 2
  *
@@ -20,6 +20,9 @@
 #include "doi.h"
 #include "risin.h"
 
+/*****************************************************
+ PUBLIC: void risin_initparams()
+*****************************************************/
 void
 risin_initparams( param *p, const char *progname )
 {
@@ -49,6 +52,10 @@
 	else p->progname = strdup( progname );
 }
 
+/*****************************************************
+ PUBLIC: int risin_readf()
+*****************************************************/
+
 /* RIS definition of a tag is strict:
     character 1 = uppercase alphabetic character
     character 2 = uppercase alphabetic character or digit
@@ -130,6 +137,10 @@
 	return haveref;
 }
 
+/*****************************************************
+ PUBLIC: int risin_processf()
+*****************************************************/
+
 static char*
 process_line2( newstr *tag, newstr *data, char *p )
 {
@@ -161,7 +172,7 @@
 risin_processf( fields *risin, char *p, char *filename, long nref )
 {
 	newstr tag, data;
-	int n;
+	int status, n;
 
 	newstrs_init( &tag, &data, NULL );
 
@@ -170,7 +181,8 @@
 		p = process_line( &tag, &data, p );
 		/* no anonymous fields allowed */
 		if ( tag.len )
-			fields_add( risin, tag.data, data.data, 0 );
+			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 );
@@ -188,15 +200,42 @@
 	return 1;
 }
 
+/*****************************************************
+ PUBLIC: int risin_typef()
+*****************************************************/
+
+int
+risin_typef( fields *risin, char *filename, int nref, param *p, variants *all, int nall )
+{
+	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;
+}
+
+/*****************************************************
+ 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 = is_doi( s->data );
+	int doi, status;
+	doi = is_doi( s->data );
 	if ( doi!=-1 )
-		return fields_add( f, "DOI", &(s->data[doi]), level );
+		status = fields_add( f, "DOI", &(s->data[doi]), level );
 	else
-		return fields_add( f, tag, s->data, level );
+		status = fields_add( f, tag, s->data, level );
+	if ( status==FIELDS_OK ) return BIBL_OK;
+	else return BIBL_ERR_MEMERR;
 }
 
 static int
@@ -221,35 +260,45 @@
 static int
 risin_addfile( fields *f, char *tag, newstr *s, int level )
 {
+	int status, n;
 	char *p;
-	int n;
 
 	/* if URL is file:///path/to/xyz.pdf, only store "///path/to/xyz.pdf" */
 	n = is_uri_file_scheme( s->data );
 	if ( n ) {
 		/* skip past "file:" and store only actual path */
 		p = s->data + n;
-		return fields_add( f, tag, p, level );
+		status = fields_add( f, tag, p, level );
+		if ( status==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 ) {
-		return fields_add( f, "URL", s->data, level );
+		status = fields_add( f, "URL", s->data, level );
+		if ( status==FIELDS_OK ) return BIBL_OK;
+		else return BIBL_ERR_MEMERR;
 	}
 
 	/* badly formed, RIS wants URI, but store value anyway */
-	return fields_add( f, tag, s->data, level );
+	status = fields_add( f, tag, s->data, level );
+	if ( status==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 )
 {
-	int doi = is_doi( s->data );
-	if ( doi!=-1 )
-		return fields_add( f, "DOI", &(s->data[doi]), level );
-	else return 1;
+	int status, doi;
+	doi = is_doi( s->data );
+	if ( doi!=-1 ) {
+		status = fields_add( f, "DOI", &(s->data[doi]), level );
+		if ( status==FIELDS_OK ) return BIBL_OK;
+		else return BIBL_ERR_MEMERR;
+	}
+	else return BIBL_OK;
 }
 
 static int
@@ -257,60 +306,46 @@
 {
 	char *p = d->data;
 	newstr date;
-	int part = ( !strncasecmp( tag, "PART", 4 ) ), ok;
+	int part, status;
 
+	part = ( !strncasecmp( tag, "PART", 4 ) );
+
 	newstr_init( &date );
 	while ( *p && *p!='/' ) newstr_addchar( &date, *p++ );
 	if ( *p=='/' ) p++;
 	if ( date.len>0 ) {
-		if ( part ) ok = fields_add( f, "PARTYEAR", date.data, level );
-		else        ok = fields_add( f, "YEAR",     date.data, level );
-		if ( !ok ) return 0;
+		if ( part ) status = fields_add( f, "PARTYEAR", date.data, level );
+		else        status = fields_add( f, "YEAR",     date.data, level );
+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
 
 	newstr_empty( &date );
 	while ( *p && *p!='/' ) newstr_addchar( &date, *p++ );
 	if ( *p=='/' ) p++;
 	if ( date.len>0 ) {
-		if ( part ) ok = fields_add( f, "PARTMONTH", date.data, level );
-		else        ok = fields_add( f, "MONTH",     date.data, level );
-		if ( !ok ) return 0;
+		if ( part ) status = fields_add( f, "PARTMONTH", date.data, level );
+		else        status = fields_add( f, "MONTH",     date.data, level );
+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
 
 	newstr_empty( &date );
 	while ( *p && *p!='/' ) newstr_addchar( &date, *p++ );
 	if ( *p=='/' ) p++;
 	if ( date.len>0 ) {
-		if ( part ) ok = fields_add( f, "PARTDAY", date.data, level );
-		else        ok = fields_add( f, "DAY",     date.data, level );
-		if ( !ok ) return 0;
+		if ( part ) status = fields_add( f, "PARTDAY", date.data, level );
+		else        status = fields_add( f, "DAY",     date.data, level );
+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
 
 	newstr_empty( &date );
 	while ( *p ) newstr_addchar( &date, *p++ );
 	if ( date.len>0 ) {
-		if ( part ) ok = fields_add( f, "PARTDATEOTHER", date.data,level);
-		else        ok = fields_add( f, "DATEOTHER", date.data, level );
-		if ( !ok ) return 0;
+		if ( part ) status = fields_add( f, "PARTDATEOTHER", date.data,level);
+		else        status = fields_add( f, "DATEOTHER", date.data, level );
+		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
 	newstr_free( &date );
-	return 1;
-}
-
-int
-risin_typef( fields *risin, char *filename, int nref, param *p, variants *all, int nall )
-{
-	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;
+	return BIBL_OK;
 }
 
 static void
@@ -322,10 +357,18 @@
 	}
 }
 
+static int
+risin_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
 risin_convertf( fields *risin, fields *f, int reftype, param *p, variants *all, int nall )
 {
-	int process, level, i, n, nfields, ok;
+	int process, level, i, n, nfields, ok, fstatus, status = BIBL_OK;
 	char *outtag, *tag, *value;
 	newstr *t, *d;
 
@@ -345,43 +388,49 @@
 		switch ( process ) {
 
 		case SIMPLE:
-			ok = fields_add( f, outtag, d->data, level );
+			status = risin_simple( f, outtag, d->data, level );
 			break;
 
 		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;
 
 		case SERIALNO:
 			ok = addsn( f, d->data, level );
+			if ( ok ) status = BIBL_OK;
+			else status = BIBL_ERR_MEMERR;
 			break;
 
 		case DATE:
-			ok = risin_adddate( f, outtag, d, level );
+			status = risin_adddate( f, outtag, d, level );
 			break;
 
 		case NOTES:
-			ok = risin_addnotes( f, outtag, d, level );
+			status = risin_addnotes( f, outtag, d, level );
 			break;
 
 		case DOI:
-			ok = risin_adddoi( f, outtag, d, level );
+			status = risin_adddoi( f, outtag, d, level );
 			break;
 
 		case LINKEDFILE:
-			ok = risin_addfile( f, outtag, d, level );
+			status = risin_addfile( f, outtag, d, level );
 			break;
 
 		default:
-			ok = 1;
+			status = BIBL_OK;
 			break;
 
 		}
-		if ( !ok ) return BIBL_ERR_MEMERR;
+		if ( status!=BIBL_OK ) return status;
 	}
 
 	/* look for thesis-type hint */
@@ -395,11 +444,11 @@
 			     !strcasecmp(value,"Diploma Thesis")||
 			     !strcasecmp(value,"Doctoral Thesis")||
 			     !strcasecmp(value,"Habilitation Thesis")) {
-				ok = fields_add( f, "GENRE", value, 0 );
-				if ( !ok ) return BIBL_ERR_MEMERR;
+				fstatus = fields_add( f, "GENRE", value, 0 );
+				if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 			}
 		}
 	}
 
-	return BIBL_OK;
+	return status;
 }
diff --git a/bibutils/risin.h b/bibutils/risin.h
--- a/bibutils/risin.h
+++ b/bibutils/risin.h
@@ -1,7 +1,7 @@
 /*
  * risin.h
  *
- * Copyright (c) Chris Putnam 2003-2013
+ * Copyright (c) Chris Putnam 2003-2014
  *
  * Source code released under the GPL version 2
  *
diff --git a/bibutils/risout.c b/bibutils/risout.c
--- a/bibutils/risout.c
+++ b/bibutils/risout.c
@@ -28,7 +28,7 @@
 	p->latexout         = 0;
 	p->utf8out          = BIBL_CHARSET_UTF8_DEFAULT;
 	p->utf8bom          = BIBL_CHARSET_BOM_DEFAULT;
-	p->xmlout           = 0;
+	p->xmlout           = BIBL_XMLOUT_FALSE;
 	p->nosplittitle     = 0;
 	p->verbose          = 0;
 	p->addcount         = 0;
@@ -73,6 +73,41 @@
 	TYPE_UNPUBLISHED,        /* unpublished */
 };
 
+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;
+	}
+}
+
 typedef struct match_type {
 	char *name;
 	int type;
@@ -82,10 +117,11 @@
  * <genre></genre>
  */
 static int
-get_type_genre( fields *f )
+get_type_genre( fields *f, param *p )
 {
 	match_type match_genres[] = {
 		{ "academic journal",          TYPE_ARTICLE },
+		{ "article",                   TYPE_ARTICLE },
 		{ "journal article",           TYPE_ARTICLE },
 		{ "magazine",                  TYPE_MAGARTICLE },
 		{ "conference publication",    TYPE_CONF },
@@ -109,18 +145,25 @@
 	};
 	int nmatch_genres = sizeof( match_genres ) / sizeof( match_genres[0] );
 	int type, i, j;
-	char *value;
+	char *tag, *value;
 
 	type = TYPE_UNKNOWN;
 
 	for ( i=0; i<fields_num( f ); ++i ) {
-		if ( !fields_match_tag( f, i,"GENRE" ) &&
-		     !fields_match_tag( f, i,"NGENRE" ) )
+		if ( !fields_match_tag( f, i, "GENRE" ) &&
+		     !fields_match_tag( f, i, "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 ( type==TYPE_UNKNOWN ) {
 			if ( !strcasecmp( value, "periodical" ) )
 				type = TYPE_ARTICLE;
@@ -138,6 +181,13 @@
 
 	}
 
+	if ( p->verbose ) {
+		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
+		fprintf( stderr, "Type from genre element: " );
+		write_type( stderr, type );
+		fprintf( stderr, "\n" );
+	}
+
 	return type;
 }
 
@@ -145,7 +195,7 @@
  * <TypeOfResource></TypeOfResource>
  */
 static int
-get_type_resource( fields *f )
+get_type_resource( fields *f, param *p )
 {
 	match_type match_res[] = {
 		{ "software, multimedia",      TYPE_PROGRAM },
@@ -167,8 +217,21 @@
 			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 ) {
+		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
+		fprintf( stderr, "Type from resource element: " );
+		write_type( stderr, type );
+		fprintf( stderr, "\n" );
+	}
+
 	vplist_free( &a );
 	return type;
 }
@@ -176,36 +239,58 @@
 /* Try to determine type of reference from <issuance></issuance> and */
 /* <typeOfReference></typeOfReference> */
 static int
-get_type_issuance( fields *f )
+get_type_issuance( fields *f, param *p )
 {
 	int type = TYPE_UNKNOWN;
-	int i, monographic = 0, text = 0, monographic_level = 0;
+	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" ) ){
 			monographic = 1;
 			monographic_level = f->level[i];
 		}
-		if ( !strcasecmp( f->tag[i].data, "typeOfResource" ) &&
-		     !strcasecmp( f->data[i].data,"text") ) {
-			text = 1;
-		}
+//		if ( !strcasecmp( f->tag[i].data, "typeOfResource" ) &&
+//		     !strcasecmp( f->data[i].data,"text") ) {
+//			text = 1;
+//		}
 	}
-	if ( monographic && text ) {
+//	if ( monographic && text ) {
+	if ( monographic ) {
 		if ( monographic_level==0 ) type=TYPE_BOOK;
 		else if ( monographic_level>0 ) type=TYPE_INBOOK;
 	}
+
+	if ( p->verbose ) {
+		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
+		fprintf( stderr, "Type from issuance/typeOfReference elements: " );
+		write_type( stderr, type );
+		fprintf( stderr, "\n" );
+	}
+
 	return type;
 }
 
 static int
-get_type( fields *f )
+get_type( fields *f, param *p )
 {
 	int type;
-	type = get_type_genre( f );
-	if ( type==TYPE_UNKNOWN ) type = get_type_resource( f );
-	if ( type==TYPE_UNKNOWN ) type = get_type_issuance( f );
-	if ( type==TYPE_UNKNOWN ) type = TYPE_STD;
+	type = get_type_genre( f, p );
+	if ( type==TYPE_UNKNOWN ) type = get_type_resource( f, p );
+	if ( type==TYPE_UNKNOWN ) type = get_type_issuance( f, p );
+	if ( type==TYPE_UNKNOWN ) {
+		if ( fields_maxlevel( f ) > 0 ) type = TYPE_INBOOK;
+		else type = TYPE_STD;
+	}
+
+	if ( p->verbose ) {
+		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
+		fprintf( stderr, "Final type: " );
+		write_type( stderr, type );
+		fprintf( stderr, "\n" );
+	}
+
+
 	return type;
 }
 
@@ -525,7 +610,7 @@
 risout_write( fields *f, FILE *fp, param *p, unsigned long refnum )
 {
 	int type;
-	type = get_type( f );
+	type = get_type( f, p );
 	output_type( fp, type, p );
 
 	output_allpeople( fp, f, type );
diff --git a/bibutils/serialno.c b/bibutils/serialno.c
--- a/bibutils/serialno.c
+++ b/bibutils/serialno.c
@@ -1,7 +1,7 @@
 /*
  * serialno.c
  *
- * Copyright (c) Chris Putnam 2005-2013
+ * Copyright (c) Chris Putnam 2005-2014
  *
  * Source code released under the GPL version 2
  *
@@ -12,25 +12,44 @@
 int
 addsn( fields *info, char *buf, int level )
 {
-	int ndigits=0, issn=0, isbn=0;
-	char *p = buf;
+	int ndigits, issn=0, isbn=0, isbn10=0, isbn13=0, status;
+	char *p = buf, *tag;
 
 	if ( !strncasecmp( p, "ISSN", 4 ) ) issn=1;
 	else if ( !strncasecmp( p, "ISBN", 4 ) ) isbn=1;
 
+	if ( isbn ) {
+		ndigits = 0;
+		while ( *p && !(ndigits && (*p==';'||*p==':')) ) {
+			if ( ( *p>='0' && *p<='9' ) || *p=='x' || *p=='X' )
+				ndigits++;
+			p++;
+		}
+		if ( ndigits==13 ) isbn13 = 1;
+		else /* ( ndigits==10) */ isbn10 = 1;
+	}
+
 	if ( !issn && !isbn ) {
 		/* a lot have semicolons between multiple ISBN's for
 		   paperbacks and hardbacks with different numbers */
+		ndigits = 0;
 		while ( *p && !(ndigits && (*p==';'||*p==':')) ) {
-			if ( ( *p>='0' && *p<='9' ) || *p=='x' || *p=='X' ) 
+			if ( ( *p>='0' && *p<='9' ) || *p=='x' || *p=='X' )
 				ndigits++;
 			p++;
 		}
 		if ( ndigits==8 ) issn = 1;
-		else if ( ndigits==10 || ndigits==13 ) isbn = 1;
+		else if ( ndigits==10 ) isbn10 = 1;
+		else if ( ndigits==13 ) isbn13 = 1;
 	}
 	
-	if ( issn ) return fields_add( info, "ISSN", buf, level );
-	else if ( isbn ) return fields_add( info, "ISBN", buf, level );
-	else return fields_add( info, "SERIALNUMBER", buf, level );
+	if ( issn ) tag = "ISSN";
+	else if ( isbn10 ) tag = "ISBN";
+	else if ( isbn13 ) tag = "ISBN13";
+	else tag = "SERIALNUMBER";
+
+	status = fields_add( info, tag, buf, level );
+
+	if ( status==FIELDS_OK ) return 1;
+	else return 0;
 }
diff --git a/bibutils/serialno.h b/bibutils/serialno.h
--- a/bibutils/serialno.h
+++ b/bibutils/serialno.h
@@ -1,7 +1,7 @@
 /*
  * serialno.h
  *
- * Copyright (c) Chris Putnam 2005-2013
+ * Copyright (c) Chris Putnam 2005-2014
  *
  * Source code released under the GPL version 2
  *
diff --git a/bibutils/title.c b/bibutils/title.c
--- a/bibutils/title.c
+++ b/bibutils/title.c
@@ -3,7 +3,7 @@
  *
  * process titles into title/subtitle pairs for MODS
  *
- * Copyright (c) Chris Putnam 2004-2013
+ * Copyright (c) Chris Putnam 2004-2014
  *
  * Source code released under the GPL version 2
  *
@@ -22,7 +22,7 @@
 {
 	newstr title, subtitle;
 	char *p, *q;
-	int ok;
+	int status;
 
 	newstr_init( &title );
 	newstr_init( &subtitle );
@@ -45,17 +45,17 @@
 
 	if ( strncasecmp( "SHORT", tag, 5 ) ) {
 		if ( title.len>0 ) {
-			ok = fields_add( info, "TITLE", title.data, level );
-			if ( !ok ) return 0;
+			status = fields_add( info, "TITLE", title.data, level );
+			if ( status!=FIELDS_OK ) return 0;
 		}
 		if ( subtitle.len>0 ) {
-			ok = fields_add( info, "SUBTITLE", subtitle.data, level );
-			if ( !ok ) return 0;
+			status = fields_add( info, "SUBTITLE", subtitle.data, level );
+			if ( status!=FIELDS_OK ) return 0;
 		}
 	} else {
 		if ( title.len>0 ) {
-			ok = fields_add( info, "SHORTTITLE", title.data, level );
-			if ( !ok ) return 0;
+			status = fields_add( info, "SHORTTITLE", title.data, level );
+			if ( status!=FIELDS_OK ) return 0;
 		}
 		/* no SHORT-SUBTITLE! */
 	}
diff --git a/bibutils/title.h b/bibutils/title.h
--- a/bibutils/title.h
+++ b/bibutils/title.h
@@ -3,7 +3,7 @@
  *
  * process titles into title/subtitle pairs for MODS
  *
- * Copyright (c) Chris Putnam 2004-2013
+ * Copyright (c) Chris Putnam 2004-2014
  *
  * Source code released under the GPL verison 2
  *
diff --git a/bibutils/wordin.c b/bibutils/wordin.c
--- a/bibutils/wordin.c
+++ b/bibutils/wordin.c
@@ -16,6 +16,10 @@
 #include "xml_encoding.h"
 #include "wordin.h"
 
+/*****************************************************
+ PUBLIC: void wordin_initparams()
+*****************************************************/
+
 void
 wordin_initparams( param *p, const char *progname )
 {
@@ -46,6 +50,10 @@
 	else p->progname = strdup( progname );
 }
 
+/*****************************************************
+ PUBLIC: int wordin_readf()
+*****************************************************/
+
 static char *
 wordin_findstartwrapper( char *buf, int *ntype )
 {
@@ -93,25 +101,9 @@
 	return haveref;
 }
 
-static inline int
-xml_hasdata( xml *node )
-{
-	if ( node && node->value && node->value->data ) return 1;
-	return 0;
-}
-
-static inline char *
-xml_data( xml *node )
-{
-	return node->value->data;
-}
-
-static inline int
-xml_tagwithdata( xml *node, char *tag )
-{
-	if ( !xml_hasdata( node ) ) return 0;
-	return xml_tagexact( node, tag );
-}
+/*****************************************************
+ PUBLIC: int wordin_processf()
+*****************************************************/
 
 typedef struct xml_convert {
 	char *in;       /* The input tag */
@@ -120,126 +112,204 @@
 	int level;
 } xml_convert;
 
-static void
+/* wordin_person_last()
+ *
+ * From an xml list, extract the value from the first entry
+ * of <b:Last>xxxx</b:Last> and copy into name
+ *
+ * Additional <b:Last>yyyyy</b:Last> will be ignored.
+ *
+ * Returns BIBL_ERR_MEMERR on memory error, BIBL_OK otherwise.
+ */
+static int
+wordin_person_last( xml *node, newstr *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;
+	}
+	return BIBL_OK;
+}
+
+/* wordin_person_first()
+ *
+ * From an xml list, extract the value of any
+ * <b:First>xxxx</b:First> and append "|xxxx" to name.
+ *
+ * Returns BIBL_ERR_MEMERR on memory error, BIBL_OK otherwise
+ */
+static int
+wordin_person_first( xml *node, newstr *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;
+		}
+	}
+	return BIBL_OK;
+}
+
+static int
 wordin_person( xml *node, fields *info, char *type )
 {
-	xml *last, *first;
+	int status, ret = BIBL_OK;
 	newstr name;
 
 	newstr_init( &name );
 
-	last = node;
-	while ( last && !xml_tagexact( last, "b:Last" ) )
-		last = last->next;
-	if ( last ) newstr_strcpy( &name, last->value->data );
-
-	first = node;
-	while ( first ) {
-		if ( xml_tagexact( first, "b:First" ) ) {
-			if ( name.len ) newstr_addchar( &name, '|' );
-			newstr_strcat( &name, first->value->data );
-		}
-		first = first->next;
+	status = wordin_person_last( node, &name );
+	if ( status!=BIBL_OK ) {
+		ret = status;
+		goto out;
 	}
 
-	fields_add( info, type, name.data, 0 );
+	status = wordin_person_first( node, &name );
+	if ( status!=BIBL_OK ) {
+		ret = status;
+		goto out;
+	}
 
+	status = fields_add( info, type, name.data, 0 );
+	if ( status != FIELDS_OK ) ret = BIBL_ERR_MEMERR;
+out:
 	newstr_free( &name );
+	return ret;
 }
 
-static void
+static int
 wordin_people( xml *node, fields *info, char *type )
 {
+	int ret = BIBL_OK;
 	if ( xml_tagexact( node, "b:Author" ) && node->down ) {
-		wordin_people( node->down, info, type );
+		ret = wordin_people( node->down, info, type );
 	} else if ( xml_tagexact( node, "b:NameList" ) && node->down ) {
-		wordin_people( node->down, info, type );
+		ret = wordin_people( node->down, info, type );
 	} else if ( xml_tagexact( node, "b:Person" ) ) {
-		if ( node->down ) wordin_person( node->down, info, type );
-		if ( node->next ) wordin_people( node->next, info, type );
+		if ( node->down ) ret = wordin_person( node->down, info, type );
+		if ( ret!=BIBL_OK ) return ret;
+		if ( node->next ) ret = wordin_people( node->next, info, type );
 	}
+	return ret;
 }
 
-static void
+static int
 wordin_pages( xml *node, fields *info )
 {
+	int i, status, ret = BIBL_OK;
 	newstr sp, ep;
 	char *p;
-	int i;
+
 	newstrs_init( &sp, &ep, NULL );
-/*
-	newstr_init( &sp );
-	newstr_init( &ep );
-*/
+
 	p = xml_data( node );
 	while ( *p && *p!='-' )
 		newstr_addchar( &sp, *p++ );
+	if ( newstr_memerr( &sp ) ) {
+		ret = BIBL_ERR_MEMERR;
+		goto out;
+	}
+
 	if ( *p=='-' ) p++;
 	while ( *p )
 		newstr_addchar( &ep, *p++ );
-	if ( sp.len ) fields_add( info, "PAGESTART", sp.data, 1 );
+	if ( newstr_memerr( &ep ) ) {
+		ret = BIBL_ERR_MEMERR;
+		goto out;
+	}
+
+	if ( sp.len ) {
+		status = fields_add( info, "PAGESTART", sp.data, 1 );
+		if ( status!=FIELDS_OK ) {
+			ret = BIBL_ERR_MEMERR;
+			goto out;
+		}
+	}
+
 	if ( ep.len ) {
 		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];
-			fields_add( info, "PAGEEND", sp.data, 1 );
+			status = fields_add( info, "PAGEEND", sp.data, 1 );
 		} else
-			fields_add( info, "PAGEEND", ep.data, 1 );
+			status = fields_add( info, "PAGEEND", ep.data, 1 );
+		if ( status!=FIELDS_OK ) {
+			ret = BIBL_ERR_MEMERR;
+			goto out;
+		}
 	}
+
+out:
 	newstrs_free( &sp, &ep, NULL );
-/*
-	newstr_free( &sp );
-	newstr_free( &ep );
-*/
+	return ret;
 }
 
-static void
+static int
 wordin_reference( xml *node, fields *info )
 {
+	int status, ret = BIBL_OK;
 	if ( xml_hasdata( node ) ) {
 		if ( xml_tagexact( node, "b:Tag" ) ) {
-			fields_add( info, "REFNUM", xml_data( node ), 0 );
+			status = fields_add( info, "REFNUM", xml_data( node ), 0 );
+			if ( status!=FIELDS_OK ) ret = BIBL_ERR_MEMERR;
 		} else if ( xml_tagexact( node, "b:SourceType" ) ) {
 		} else if ( xml_tagexact( node, "b:City" ) ) {
-			fields_add( info, "ADDRESS", xml_data( node ), 0 );
+			status = fields_add( info, "ADDRESS", xml_data( node ), 0 );
+			if ( status!=FIELDS_OK ) ret = BIBL_ERR_MEMERR;
 		} else if ( xml_tagexact( node, "b:Publisher" ) ) {
-			fields_add( info, "PUBLISHER", xml_data( node ), 0 );
+			status = fields_add( info, "PUBLISHER", xml_data( node ), 0 );
+			if ( status!=FIELDS_OK ) ret = BIBL_ERR_MEMERR;
 		} else if ( xml_tagexact( node, "b:Title" ) ) {
-			fields_add( info, "TITLE", xml_data( node ), 0 );
+			status = fields_add( info, "TITLE", xml_data( node ), 0 );
+			if ( status!=FIELDS_OK ) ret = BIBL_ERR_MEMERR;
 		} else if ( xml_tagexact( node, "b:JournalName" ) ) {
-			fields_add( info, "TITLE", xml_data( node ), 1 );
+			status = fields_add( info, "TITLE", xml_data( node ), 1 );
+			if ( status!=FIELDS_OK ) ret = BIBL_ERR_MEMERR;
 		} else if ( xml_tagexact( node, "b:Volume" ) ) {
-			fields_add( info, "VOLUME", xml_data( node ), 1 );
+			status = fields_add( info, "VOLUME", xml_data( node ), 1 );
+			if ( status!=FIELDS_OK ) ret = BIBL_ERR_MEMERR;
 		} else if ( xml_tagexact( node, "b:Comments" ) ) {
-			fields_add( info, "NOTES", xml_data( node ), 0 );
+			status = fields_add( info, "NOTES", xml_data( node ), 0 );
+			if ( status!=FIELDS_OK ) ret = BIBL_ERR_MEMERR;
 		} else if ( xml_tagexact( node, "b:Pages" ) ) {
-			wordin_pages( node, info );
+			ret = wordin_pages( node, info );
 		} else if ( xml_tagexact( node, "b:Author" ) && node->down ) {
-			wordin_people( node->down, info, "AUTHOR" );
+			ret = wordin_people( node->down, info, "AUTHOR" );
 		} else if ( xml_tagexact( node, "b:Editor" ) && node->down ) {
-			wordin_people( node->down, info, "EDITOR" );
+			ret = wordin_people( node->down, info, "EDITOR" );
 		}
 	}
-	if ( node->next ) wordin_reference( node->next, info );
+	if ( ret==BIBL_OK && node->next ) wordin_reference( node->next, info );
+	return ret;
 }
 
-static void
+static int
 wordin_assembleref( xml *node, fields *info )
 {
+	int ret = BIBL_OK;
 	if ( xml_tagexact( node, "b:Source" ) ) {
-		if ( node->down ) wordin_reference( node->down, info );
+		if ( node->down ) ret = wordin_reference( node->down, info );
 	} else if ( node->tag->len==0 && node->down ) {
-		wordin_assembleref( node->down, info );
+		ret = wordin_assembleref( node->down, info );
 	}
+	return ret;
 }
 
 int
 wordin_processf( fields *wordin, char *data, char *filename, long nref )
 {
+	int status, ret = 1;
 	xml top;
+
 	xml_init( &top );
 	xml_tree( data, &top );
-	wordin_assembleref( &top, wordin );
+	status = wordin_assembleref( &top, wordin );
 	xml_free( &top );
-	return 1;
+
+	if ( status==BIBL_ERR_MEMERR ) ret = 0;
+	return ret;
 }
diff --git a/bibutils/wordout.c b/bibutils/wordout.c
--- a/bibutils/wordout.c
+++ b/bibutils/wordout.c
@@ -3,7 +3,7 @@
  * 
  * (Word 2007 format)
  *
- * Copyright (c) Chris Putnam 2007-2013
+ * Copyright (c) Chris Putnam 2007-2014
  *
  * Source code released under the GPL version 2
  *
@@ -26,8 +26,10 @@
 	p->latexout         = 0;
 	p->utf8out          = BIBL_CHARSET_UTF8_DEFAULT;
 	p->utf8bom          = BIBL_CHARSET_BOM_DEFAULT;
-	if ( !p->utf8out ) p->xmlout = 3;
-	else p->xmlout = 1;
+	if ( !p->utf8out )
+		p->xmlout   = BIBL_XMLOUT_ENTITIES;
+	else
+		p->xmlout   = BIBL_XMLOUT_TRUE;
 	p->nosplittitle     = 0;
 	p->verbose          = 0;
 	p->addcount         = 0;
@@ -575,6 +577,7 @@
 		{ "NUMBER",          "b:Issue",   LEVEL_ANY },
 		{ "PUBLICLAWNUMBER", "b:Volume",  LEVEL_ANY },
 		{ "SESSION",         "b:Issue",   LEVEL_ANY },
+		{ "URL",             "b:Url",     LEVEL_ANY },
 	};
 	int nparts=sizeof(parts)/sizeof(convert);
 	
diff --git a/bibutils/xml.c b/bibutils/xml.c
--- a/bibutils/xml.c
+++ b/bibutils/xml.c
@@ -30,10 +30,10 @@
 static void
 xmlattrib_add( xml_attrib *a, char *attrib, char *value  )
 {
-	if ( attrib ) list_add( &(a->attrib), attrib );
-	else list_add( &(a->attrib), "" );
-	if ( value ) list_add( &(a->value), value );
-	else list_add( &(a->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), "" );
 }
 
 static void
@@ -238,10 +238,11 @@
 					p = xml_tree( p, nnode );
 			} else if ( type==XML_CLOSE ) {
 				/*check to see if it's closing for this one*/
-				return p; /* assume it's right for now*/
+				goto out; /* assume it's right for now */
 			}
 		}
 	}
+out:
 	newstr_free( &tag );
 	return p;
 }
@@ -335,24 +336,33 @@
 }
 
 int
-xml_tag_attrib( xml *node, char *s, char *attrib, char *value )
+xml_hasattrib( xml *node, char *attrib, char *value )
 {
 	xml_attrib *na = node->a;
 	int i;
 
-	if ( !na || !xml_tagexact( node, s ) ) return 0;
+	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 ) )
-			return 1;
+		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 ) )
+				return 1;
+		}
+
 	}
 
 	return 0;
 }
 
+int
+xml_tag_attrib( xml *node, char *s, char *attrib, char *value )
+{
+	if ( !xml_tagexact( node, s ) ) return 0;
+	return xml_hasattrib( node, attrib, value );
+}
+
 newstr *
 xml_getattrib( xml *node, char *attrib )
 {
@@ -366,5 +376,25 @@
 				ns = &(na->value.str[i]);
 	}
 	return ns;
+}
+
+int
+xml_hasdata( xml *node )
+{
+	if ( node && node->value && node->value->data ) return 1;
+	return 0;
+}
+
+char *
+xml_data( xml *node )
+{
+	return node->value->data;
+}
+
+int
+xml_tagwithdata( xml *node, char *tag )
+{
+	if ( !xml_hasdata( node ) ) return 0;
+	return xml_tagexact( node, tag );
 }
 
diff --git a/bibutils/xml.h b/bibutils/xml.h
--- a/bibutils/xml.h
+++ b/bibutils/xml.h
@@ -31,8 +31,12 @@
 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 );
 
 extern char *xml_pns; /* global Namespace */
 
diff --git a/cbits/stub.c b/cbits/stub.c
--- a/cbits/stub.c
+++ b/cbits/stub.c
@@ -9,3 +9,5 @@
 {
     return stdin;
 }
+
+const char progname[] = "hs-bibutils";
diff --git a/hs-bibutils.cabal b/hs-bibutils.cabal
--- a/hs-bibutils.cabal
+++ b/hs-bibutils.cabal
@@ -1,6 +1,6 @@
 name:               hs-bibutils
-version:            5.0
-homepage:           http://gorgias.mine.nu/repos/hs-bibutils/
+version:            5.5
+homepage:           http://istitutocolli.org/repos/hs-bibutils/
 
 synopsis:           Haskell bindings to bibutils, the bibliography
                     conversion utilities.
@@ -30,38 +30,41 @@
 cabal-version:      >= 1.4
 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/fields.c bibutils/fields.h bibutils/gb18030.c
-    bibutils/gb18030.h bibutils/gb18030_enumeration.c bibutils/is_ws.c
-    bibutils/intlis.h bibutils/intlis.c bibutils/is_ws.h
-    bibutils/isiin.c bibutils/isiin.h bibutils/isiout.c
-    bibutils/iso639_2.c bibutils/iso639_2.h bibutils/isiout.h
-    bibutils/isitypes.c 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/mycvout.c
-    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/ristypes.c bibutils/vplist.c bibutils/vplist.h
-    bibutils/serialno.c bibutils/serialno.h bibutils/strsearch.c
-    bibutils/strsearch.h bibutils/title.c bibutils/title.h
-    bibutils/unicode. bibutils/unicode.c bibutils/utf8.c
-    bibutils/utf8.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/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/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/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/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
 
 library
     exposed-modules:  Text.Bibutils
@@ -71,7 +74,7 @@
     hs-source-dirs:   src
     extensions:       ForeignFunctionInterface
     include-dirs:     bibutils
-    includes:         bibutils.h
+    includes: bibutils.h
     c-sources:
         cbits/stub.c
         bibutils/adsout.c bibutils/adsout_journals.c
@@ -83,15 +86,16 @@
         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_2.c
-        bibutils/latex.c bibutils/list.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/vplist.c
-        bibutils/serialno.c bibutils/strsearch.c bibutils/title.c
-        bibutils/unicode.c bibutils/utf8.c bibutils/wordin.c
-        bibutils/wordout.c bibutils/xml.c bibutils/xml_encoding.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/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
 
     if impl(ghc >= 6.10)
        build-depends: base >= 4, syb
