[bibutils] 01/01: Importing bibutils_5.11.orig.tar.gz

David Bremner bremner at debian.org
Sat Jul 1 12:44:48 UTC 2017


This is an automated email from the git hooks/post-receive script.

bremner pushed a commit to annotated tag upstream/5.11
in repository bibutils.

commit f97e2e14f7c90e33cda1dc31a258afeb00d4bb8e
Author: David Bremner <bremner at debian.org>
Date:   Sat Jul 1 09:13:38 2017 -0300

    Importing bibutils_5.11.orig.tar.gz
---
 ChangeLog                     |  68 ++++
 Makefile_start                |   5 +-
 bibutils.dbk                  |  11 +-
 bin/Makefile.dynamic          |   6 +-
 bin/Makefile.static           |  18 +-
 bin/args.c                    |   2 +-
 bin/args.h                    |   2 +-
 bin/bib2xml.c                 |   5 +-
 bin/biblatex2xml.c            |   5 +-
 bin/bibprog.c                 |   2 +-
 bin/bibprog.h                 |   2 +-
 bin/copac2xml.c               |   5 +-
 bin/ebi2xml.c                 |   5 +-
 bin/end2xml.c                 |   5 +-
 bin/endx2xml.c                |   5 +-
 bin/isi2xml.c                 |   5 +-
 bin/med2xml.c                 |   5 +-
 bin/modsclean.c               |   5 +-
 bin/{isi2xml.c => nbib2xml.c} |  15 +-
 bin/ris2xml.c                 |   5 +-
 bin/tomods.c                  |   5 +-
 bin/tomods.h                  |   2 +-
 bin/wordbib2xml.c             |   5 +-
 bin/xml2ads.c                 |   5 +-
 bin/xml2bib.c                 |  23 +-
 bin/xml2end.c                 |   5 +-
 bin/xml2isi.c                 |   5 +-
 bin/xml2ris.c                 |   7 +-
 bin/xml2wordbib.c             |   5 +-
 lib/Makefile.dynamic          |   6 +-
 lib/Makefile.static           |   6 +-
 lib/adsout.c                  | 431 ++++++++++++++-------
 lib/adsout.h                  |  22 --
 lib/bibcore.c                 |  63 +++-
 lib/bibformats.h              |  35 ++
 lib/bibl.c                    |   4 +-
 lib/bibl.h                    |   2 +-
 lib/biblatexin.c              | 611 ++++++++++++------------------
 lib/biblatexin.h              |  33 --
 lib/bibtexin.c                | 728 +++++++++++++++++-------------------
 lib/bibtexin.h                |  33 --
 lib/bibtexout.c               | 844 ++++++++++++++++++++++++-----------------
 lib/bibtexout.h               |  31 --
 lib/bibtextypes.c             | 677 ++++++++++++++++-----------------
 lib/bibutils.c                |  23 +-
 lib/bibutils.h                |  24 +-
 lib/bltypes.c                 | 194 +++++-----
 lib/charsets.c                |   2 +-
 lib/charsets.h                |   2 +-
 lib/copacin.c                 | 114 +++---
 lib/copacin.h                 |  30 --
 lib/copactypes.c              |  32 +-
 lib/doi.c                     | 115 ------
 lib/doi.h                     |  21 --
 lib/ebiin.c                   |  86 +++--
 lib/ebiin.h                   |  27 --
 lib/endin.c                   | 257 +++++--------
 lib/endin.h                   |  30 --
 lib/endout.c                  | 475 ++++++++++++-----------
 lib/endout.h                  |  22 --
 lib/endtypes.c                | 156 ++++----
 lib/endxmlin.c                |  21 +-
 lib/endxmlin.h                |  23 --
 lib/entities.c                |   2 +-
 lib/entities.h                |   2 +-
 lib/fields.c                  |  96 +++--
 lib/fields.h                  |  67 ++--
 lib/gb18030.h                 |   2 +-
 lib/generic.c                 |  77 ++++
 lib/generic.h                 |  23 ++
 lib/intlist.c                 |   2 +-
 lib/intlist.h                 |   2 +-
 lib/is_ws.c                   |   2 +-
 lib/is_ws.h                   |   2 +-
 lib/isiin.c                   | 174 ++++-----
 lib/isiin.h                   |  28 --
 lib/isiout.c                  | 334 ++++++++++-------
 lib/isiout.h                  |  21 --
 lib/isitypes.c                |  54 +--
 lib/latex.c                   | 851 ++++++++++++++++++++++--------------------
 lib/latex.h                   |   2 +-
 lib/list.c                    |  57 ++-
 lib/list.h                    |  79 ++--
 lib/marc.c                    |   2 +-
 lib/marc.h                    |   2 +-
 lib/medin.c                   |  45 ++-
 lib/medin.h                   |  26 --
 lib/modsin.c                  | 202 ++++++----
 lib/modsin.h                  |  20 -
 lib/modsout.c                 |  51 +--
 lib/modsout.h                 |  27 --
 lib/modstypes.c               |  29 +-
 lib/modstypes.h               |   2 +-
 lib/mycvout.c                 |  56 +--
 lib/name.c                    |   8 +-
 lib/name.h                    |   2 +-
 lib/nbibin.c                  | 482 ++++++++++++++++++++++++
 lib/nbibtypes.c               |  68 ++++
 lib/newstr.c                  |  55 ++-
 lib/newstr.h                  |  87 +++--
 lib/newstr_conv.c             |   2 +-
 lib/newstr_conv.h             |   2 +-
 lib/notes.c                   |  97 +++++
 lib/notes.h                   |  17 +
 lib/pages.c                   |  83 ++++
 lib/pages.h                   |  13 +
 lib/reftypes.c                |  26 +-
 lib/reftypes.h                |  37 +-
 lib/risin.c                   | 275 ++++++--------
 lib/risin.h                   |  28 --
 lib/risout.c                  | 671 +++++++++++++++++----------------
 lib/risout.h                  |  22 --
 lib/ristypes.c                | 346 ++++++++---------
 lib/serialno.c                |   2 +-
 lib/serialno.h                |   2 +-
 lib/strsearch.c               |   2 +-
 lib/strsearch.h               |   2 +-
 lib/title.c                   |  34 +-
 lib/title.h                   |   6 +-
 lib/unicode.h                 |   2 +-
 lib/url.c                     | 311 +++++++++++++++
 lib/url.h                     |  30 ++
 lib/utf8.c                    |  27 +-
 lib/utf8.h                    |  13 +-
 lib/vplist.c                  |  77 ++--
 lib/vplist.h                  |  14 +-
 lib/wordin.c                  |  20 +-
 lib/wordin.h                  |  23 --
 lib/wordout.c                 | 154 +++++---
 lib/wordout.h                 |  27 --
 lib/xml.c                     |   2 +-
 lib/xml.h                     |   2 +-
 lib/xml_encoding.c            |   2 +-
 lib/xml_encoding.h            |   2 +-
 test/Makefile.dynamic         |   9 +-
 test/Makefile.static          |   7 +-
 test/doi_test.c               | 120 ++++++
 test/entities_test.c          |   3 +
 test/list_test.c              |   5 +
 test/newstr_test.c            |   4 +
 test/utf8_test.c              |   5 +
 test/vplist_test.c            |   5 +
 142 files changed, 6184 insertions(+), 4811 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 7474aa4..d43332c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,74 @@
 
 BIBUTILS
 
+5.11
+11/8/16
+
+NBIB2XML
++ Add program
+
+BIBTEXOUT
++ Handle MRNUMBER
+
+5.10
+11/2/16
+
+BIBTEXIN
++ Handle MRNUMBER and CODEN tags
+
+5.9
+9/12/16
+
+GLOBAL
++ Allow bibutils to properly process references with several authors of the
+same name (reported by Jason Annadani).
+
+MODSIN
++ Fix processing of mods input files where given name information isn't as
+finely parsed as bibutils mods files are (reported by Dan Gildea).
+
+5.8
+5/23/16
+
+INTERNAL
++ Change xxx_convertf() functions to use tables of function pointers
++ Use generic function pointers whenever possible to decrease duplicated code
+
+ADSOUT
++ Improve URL handling
+
+BIBLATEXIN
++ Identify JSTOR
+
+BIBTEXOUT
++ Handle PMC identifiers
++ Fix chapter/title for @inbook references (reported by Vivek Botcha)
+
+RISOUT
++ Handle PMC identifiers
+
+
+5.7
+2/15/16
+
+MODSIN
++ Handle relatedItem original information (reported by John Vandenberg)
+
+BIBTEXOUT
++ Resolve INBOOK/MISC problems (reported by John Vandenberg)
++ Improve output of latex macros (reported by John Vandenberg)
+
+RISIN
++ Recognize URL's buried in the notes field
++ Properly propagate situation when journal name in RIS is under "T2"--short
+title, not "JF"--journal title (reported by Mary Martin)
+
+GLOBAL
++ Update library components to current versions
++ Improve error propagation
++ Lots of small fixes found by clang --analyze
+
+
 5.6
 1/26/15
 
diff --git a/Makefile_start b/Makefile_start
index 9e174ff..423ae20 100644
--- a/Makefile_start
+++ b/Makefile_start
@@ -10,9 +10,9 @@ INSTALLDIR    = REPLACE_INSTALLDIR
 LIBINSTALLDIR = REPLACE_LIBINSTALLDIR
 
 MAJORVERSION  = 5
-MINORVERSION  = 6
+MINORVERSION  = 11
 VERSION       = $(MAJORVERSION).$(MINORVERSION)
-DATE          = 2015-01-26
+DATE          = 2016-11-07
 
 PROGRAMS      = bib2xml \
                 biblatex2xml \
@@ -22,6 +22,7 @@ PROGRAMS      = bib2xml \
                 endx2xml \
                 isi2xml \
                 med2xml \
+                nbib2xml \
                 ris2xml \
                 wordbib2xml \
                 xml2ads \
diff --git a/bibutils.dbk b/bibutils.dbk
index f6bc944..31359ca 100644
--- a/bibutils.dbk
+++ b/bibutils.dbk
@@ -6,7 +6,7 @@
   <!ENTITY dhfirstname "<firstname>David</firstname>">
   <!ENTITY dhsurname   "<surname>Bremner</surname>">
   <!-- Please adjust the date whenever revising the manpage. -->
-  <!ENTITY dhdate      "<date>December 10, 2010</date>">
+  <!ENTITY dhdate      "<date>November 8, 2016</date>">
   <!-- SECTION should be 1-8, maybe w/ subsection other parameters are
        allowed: see man(7), man(1). -->
   <!ENTITY dhsection   "<manvolnum>1</manvolnum>">
@@ -18,14 +18,14 @@
   <!ENTITY debian      "<productname>Debian</productname>">
   <!ENTITY gnu         "<acronym>GNU</acronym>">
   <!ENTITY gpl         "&gnu; <acronym>GPL</acronym>">
-  <!ENTITY version	"5.6">
+  <!ENTITY version	"5.11">
 
   ]>
 <refentry>
   <refentryinfo>
     <address>&dhemail;</address>
     <copyright>
-      <year>2010</year>
+      <year>2016</year>
       <holder>&dhusername; (Manual)</holder>
     </copyright>
     <copyright>
@@ -56,6 +56,7 @@
     <refname>isi2xml</refname>
     <refname>med2xml</refname>
     <refname>modsclean</refname>
+    <refname>nbib2xml</refname>
     <refname>ris2xml</refname>
     <refname>xml2ads</refname>
     <refname>xml2bib</refname>
@@ -150,6 +151,10 @@
         <seg>convert Pubmed XML references to MODS</seg>
       </seglistitem>
       <seglistitem>
+        <seg>nbib2xml</seg>
+        <seg>convert Pubmed nbib format references to MODS</seg>
+      </seglistitem>
+      <seglistitem>
         <seg>modsclean</seg><seg>a MODS to MODS converter</seg>
       </seglistitem>
       <seglistitem>
diff --git a/bin/Makefile.dynamic b/bin/Makefile.dynamic
index c38fdcf..53283ea 100644
--- a/bin/Makefile.dynamic
+++ b/bin/Makefile.dynamic
@@ -19,6 +19,7 @@ ENDXIN     = endx2xml.o
 ISIIN      = isi2xml.o
 MEDIN      = med2xml.o
 MODSCLEAN  = modsclean.o
+NBIBIN     = nbib2xml.o
 RISIN      = ris2xml.o
 WORDIN     = wordbib2xml.o
 
@@ -32,7 +33,7 @@ RISOUT     = xml2ris.o
 WORDOUT    = xml2wordbib.o
 
 PROGS      = bib2xml biblatex2xml copac2xml end2xml endx2xml isi2xml med2xml \
-             ris2xml ebi2xml wordbib2xml \
+             nbib2xml ris2xml ebi2xml wordbib2xml \
              xml2ads xml2bib xml2end xml2isi xml2ris xml2wordbib modsclean
 
 all: $(PROGS)
@@ -64,6 +65,9 @@ isi2xml : $(TOMODS) $(ISIIN)
 med2xml : $(TOMODS) $(MEDIN)
 	$(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
 
+nbib2xml : $(TOMODS) $(NBIBIN)
+	$(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
+
 ris2xml : $(TOMODS) $(RISIN)
 	$(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
 
diff --git a/bin/Makefile.static b/bin/Makefile.static
index 3be44ac..559e936 100644
--- a/bin/Makefile.static
+++ b/bin/Makefile.static
@@ -6,16 +6,17 @@ CFLAGS     = -I ../lib $(CFLAGSIN)
 
 TOMODS     = args.o bibprog.o tomods.o ../lib/modsout.o
 
-BIBTEXIN   = bib2xml.o ../lib/bibtexin.o ../lib/bibtextypes.o
-BIBLATEXIN = biblatex2xml.o ../lib/biblatexin.o ../lib/bltypes.o
-COPACIN    = copac2xml.o ../lib/copacin.o ../lib/copactypes.o
+BIBTEXIN   = bib2xml.o ../lib/bibtexin.o ../lib/bibtextypes.o ../lib/generic.o
+BIBLATEXIN = biblatex2xml.o ../lib/biblatexin.o ../lib/bltypes.o ../lib/generic.o
+COPACIN    = copac2xml.o ../lib/copacin.o ../lib/copactypes.o ../lib/generic.o
 EBIIN      = ebi2xml.o ../lib/ebiin.o
-ENDIN      = end2xml.o ../lib/endin.o ../lib/endtypes.o
-ENDXIN     = endx2xml.o ../lib/endxmlin.o ../lib/endin.o ../lib/endtypes.o
-ISIIN      = isi2xml.o ../lib/isiin.o ../lib/isitypes.o
+ENDIN      = end2xml.o ../lib/endin.o ../lib/endtypes.o ../lib/generic.o
+ENDXIN     = endx2xml.o ../lib/endxmlin.o ../lib/endin.o ../lib/endtypes.o ../lib/generic.o
+ISIIN      = isi2xml.o ../lib/isiin.o ../lib/isitypes.o ../lib/generic.o
 MEDIN      = med2xml.o ../lib/medin.o
 MODSCLEAN  = modsclean.o ../lib/modsin.o
-RISIN      = ris2xml.o ../lib/risin.o ../lib/ristypes.o
+NBIBIN     = nbib2xml.o ../lib/nbibin.o ../lib/nbibtypes.o ../lib/generic.o
+RISIN      = ris2xml.o ../lib/risin.o ../lib/ristypes.o ../lib/generic.o
 WORDIN     = wordbib2xml.o ../lib/wordin.o
 
 FROMMODS   = bibprog.o args.o ../lib/modsin.o
@@ -61,6 +62,9 @@ med2xml : $(TOMODS) $(MEDIN) ../lib/libbibcore.a
 ris2xml : $(TOMODS) $(RISIN) ../lib/libbibcore.a
 	$(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
 
+nbib2xml : $(TOMODS) $(NBIBIN) ../lib/libbibcore.a
+	$(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
+
 wordbib2xml : $(TOMODS) $(WORDIN) ../lib/libbibcore.a
 	$(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
 
diff --git a/bin/args.c b/bin/args.c
index bc9ee9a..5066d48 100644
--- a/bin/args.c
+++ b/bin/args.c
@@ -1,7 +1,7 @@
 /*
  * args.c
  *
- * Copyright (c) 2004-2015
+ * Copyright (c) 2004-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/bin/args.h b/bin/args.h
index 01270e9..23e79eb 100644
--- a/bin/args.h
+++ b/bin/args.h
@@ -1,7 +1,7 @@
 /*
  * args.h
  *
- * Copyright (c) Chris Putnam 2012-2015
+ * Copyright (c) Chris Putnam 2012-2016
  *
  * Program and source code released under the GPL version 2
  *
diff --git a/bin/bib2xml.c b/bin/bib2xml.c
index 57d82f1..2eb52a3 100644
--- a/bin/bib2xml.c
+++ b/bin/bib2xml.c
@@ -1,7 +1,7 @@
 /*
  * bib2xml.c
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -9,8 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "bibutils.h"
-#include "bibtexin.h"
-#include "modsout.h"
+#include "bibformats.h"
 #include "tomods.h"
 #include "bibprog.h"
 
diff --git a/bin/biblatex2xml.c b/bin/biblatex2xml.c
index 2f13683..0830736 100644
--- a/bin/biblatex2xml.c
+++ b/bin/biblatex2xml.c
@@ -1,7 +1,7 @@
 /*
  * biblatex2xml.c
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -9,8 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "bibutils.h"
-#include "biblatexin.h"
-#include "modsout.h"
+#include "bibformats.h"
 #include "tomods.h"
 #include "bibprog.h"
 
diff --git a/bin/bibprog.c b/bin/bibprog.c
index 423c759..3c29540 100644
--- a/bin/bibprog.c
+++ b/bin/bibprog.c
@@ -1,7 +1,7 @@
 /*
  * bibprog.c
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/bin/bibprog.h b/bin/bibprog.h
index 5645a35..f5eca8c 100644
--- a/bin/bibprog.h
+++ b/bin/bibprog.h
@@ -1,7 +1,7 @@
 /*
  * bibprogs.h
  *
- * Copyright (c) Chris Putnam 2008-2015
+ * Copyright (c) Chris Putnam 2008-2016
  *
  * Program and source code released under the GPL version 2
  *
diff --git a/bin/copac2xml.c b/bin/copac2xml.c
index 38fc0f5..8141a04 100644
--- a/bin/copac2xml.c
+++ b/bin/copac2xml.c
@@ -1,7 +1,7 @@
 /*
  * copac2xml.c
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -9,8 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "bibutils.h"
-#include "copacin.h"
-#include "modsout.h"
+#include "bibformats.h"
 #include "tomods.h"
 #include "bibprog.h"
 
diff --git a/bin/ebi2xml.c b/bin/ebi2xml.c
index 01eb187..5fbb259 100644
--- a/bin/ebi2xml.c
+++ b/bin/ebi2xml.c
@@ -1,7 +1,7 @@
 /*
  * ebi2xml.c
  * 
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -9,8 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "bibutils.h"
-#include "ebiin.h"
-#include "modsout.h"
+#include "bibformats.h"
 #include "tomods.h"
 #include "bibprog.h"
 
diff --git a/bin/end2xml.c b/bin/end2xml.c
index bef39f7..67a05eb 100644
--- a/bin/end2xml.c
+++ b/bin/end2xml.c
@@ -1,7 +1,7 @@
 /*
  * end2xml.c
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -9,8 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "bibutils.h"
-#include "endin.h"
-#include "modsout.h"
+#include "bibformats.h"
 #include "tomods.h"
 #include "bibprog.h"
 
diff --git a/bin/endx2xml.c b/bin/endx2xml.c
index 03f7e7c..9ed9098 100644
--- a/bin/endx2xml.c
+++ b/bin/endx2xml.c
@@ -1,7 +1,7 @@
 /*
  * endx2xml.c
  * 
- * Copyright (c) Chris Putnam 2006-2015
+ * Copyright (c) Chris Putnam 2006-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -9,8 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "bibutils.h"
-#include "endxmlin.h"
-#include "modsout.h"
+#include "bibformats.h"
 #include "tomods.h"
 #include "bibprog.h"
 
diff --git a/bin/isi2xml.c b/bin/isi2xml.c
index 752f74b..3891193 100644
--- a/bin/isi2xml.c
+++ b/bin/isi2xml.c
@@ -1,7 +1,7 @@
 /*
  * isi2xml.c
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -9,8 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "bibutils.h"
-#include "isiin.h"
-#include "modsout.h"
+#include "bibformats.h"
 #include "tomods.h"
 #include "bibprog.h"
 
diff --git a/bin/med2xml.c b/bin/med2xml.c
index 3cbc02d..e595e41 100644
--- a/bin/med2xml.c
+++ b/bin/med2xml.c
@@ -1,7 +1,7 @@
 /*
  * med2xml.c
  * 
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -9,8 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "bibutils.h"
-#include "medin.h"
-#include "modsout.h"
+#include "bibformats.h"
 #include "tomods.h"
 #include "bibprog.h"
 
diff --git a/bin/modsclean.c b/bin/modsclean.c
index db9b536..723f2c5 100644
--- a/bin/modsclean.c
+++ b/bin/modsclean.c
@@ -1,7 +1,7 @@
 /*
  * modsclean.c
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -9,8 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "bibutils.h"
-#include "modsin.h"
-#include "modsout.h"
+#include "bibformats.h"
 #include "tomods.h"
 #include "bibprog.h"
 
diff --git a/bin/isi2xml.c b/bin/nbib2xml.c
similarity index 60%
copy from bin/isi2xml.c
copy to bin/nbib2xml.c
index 752f74b..85c0113 100644
--- a/bin/isi2xml.c
+++ b/bin/nbib2xml.c
@@ -1,7 +1,7 @@
 /*
- * isi2xml.c
+ * nbib2xml.c
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -9,21 +9,20 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "bibutils.h"
-#include "isiin.h"
-#include "modsout.h"
+#include "bibformats.h"
 #include "tomods.h"
 #include "bibprog.h"
 
-char help1[] = "Converts a ISI reference file into MODS XML\n\n";
-char help2[] = "isi_file";
+char help1[] = "Converts a NCBI NBIB reference file into MODS XML\n\n";
+char help2[] = "nbib_file";
 
-const char progname[] = "isi2xml";
+const char progname[] = "nbib2xml";
 
 int
 main( int argc, char *argv[] )
 {
 	param p;
-	isiin_initparams( &p, progname );
+	nbibin_initparams( &p, progname );
 	modsout_initparams( &p, progname );
 	tomods_processargs( &argc, argv, &p, help1, help2 );
 	bibprog( argc, argv, &p );
diff --git a/bin/ris2xml.c b/bin/ris2xml.c
index 690a5ef..3cd0306 100644
--- a/bin/ris2xml.c
+++ b/bin/ris2xml.c
@@ -1,7 +1,7 @@
 /*
  * ris2xml.c
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -9,8 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "bibutils.h"
-#include "risin.h"
-#include "modsout.h"
+#include "bibformats.h"
 #include "tomods.h"
 #include "bibprog.h"
 
diff --git a/bin/tomods.c b/bin/tomods.c
index 2542349..8b54004 100644
--- a/bin/tomods.c
+++ b/bin/tomods.c
@@ -1,7 +1,7 @@
 /*
  * tomods.c
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Source code released under the GPL version 2
  *
@@ -11,7 +11,6 @@
 #include <string.h>
 #include "list.h"
 #include "bibl.h"
-#include "modsout.h"
 #include "bibutils.h"
 #include "tomods.h"
 #include "args.h"
@@ -88,7 +87,7 @@ tomods_processargs( int *argc, char *argv[], param *p,
 			p->format_opts |= BIBL_FORMAT_VERBOSE;
 			subtract = 1;
 		} else if ( args_match( argv[i], "-d", "--drop-key" ) ) {
-			p->format_opts |= MODSOUT_DROPKEY;
+			p->format_opts |= BIBL_FORMAT_MODSOUT_DROPKEY;
 			subtract = 1;
 		} else if ( args_match( argv[i], "-s", "--single-refperfile" )){
 			p->singlerefperfile = 1;
diff --git a/bin/tomods.h b/bin/tomods.h
index d75b52f..09373d3 100644
--- a/bin/tomods.h
+++ b/bin/tomods.h
@@ -1,7 +1,7 @@
 /*
  * tomods.h
  *
- * Copyright (c) Chris Putnam 2012-2015
+ * Copyright (c) Chris Putnam 2012-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/bin/wordbib2xml.c b/bin/wordbib2xml.c
index 07789a2..99a9de7 100644
--- a/bin/wordbib2xml.c
+++ b/bin/wordbib2xml.c
@@ -1,7 +1,7 @@
 /*
  * wordbib2xml.c
  * 
- * Copyright (c) Chris Putnam 2009-2015
+ * Copyright (c) Chris Putnam 2009-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -9,8 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "bibutils.h"
-#include "wordin.h"
-#include "modsout.h"
+#include "bibformats.h"
 #include "tomods.h"
 #include "bibprog.h"
 
diff --git a/bin/xml2ads.c b/bin/xml2ads.c
index 8d59f37..45f1a50 100644
--- a/bin/xml2ads.c
+++ b/bin/xml2ads.c
@@ -1,7 +1,7 @@
 /*
  * xml2ads.c
  *
- * Copyright (c) Chris Putnam 2007-2015
+ * Copyright (c) Chris Putnam 2007-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -9,8 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "bibutils.h"
-#include "modsin.h"
-#include "adsout.h"
+#include "bibformats.h"
 #include "args.h"
 #include "bibprog.h"
 
diff --git a/bin/xml2bib.c b/bin/xml2bib.c
index 664e2b3..0515625 100644
--- a/bin/xml2bib.c
+++ b/bin/xml2bib.c
@@ -1,7 +1,7 @@
 /*
  * xml2bib.c
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -9,8 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "bibutils.h"
-#include "modsin.h"
-#include "bibtexout.h"
+#include "bibformats.h"
 #include "args.h"
 #include "bibprog.h"
 
@@ -65,28 +64,28 @@ process_args( int *argc, char *argv[], param *p )
 			args_tellversion( p->progname );
 			exit( EXIT_SUCCESS );
 		} else if ( args_match( argv[i], "-fc", "--finalcomma" ) ) {
-			p->format_opts |= BIBOUT_FINALCOMMA;
+			p->format_opts |= BIBL_FORMAT_BIBOUT_FINALCOMMA;
 			subtract = 1;
 		} else if ( args_match( argv[i], "-s", "--single-refperfile" )){
 			p->singlerefperfile = 1;
 			subtract = 1;
 		} else if ( args_match( argv[i], "-sd", "--singledash" ) ) {
-			p->format_opts |= BIBOUT_SINGLEDASH;
+			p->format_opts |= BIBL_FORMAT_BIBOUT_SINGLEDASH;
 			subtract = 1;
 		} else if ( args_match( argv[i], "-b", "--brackets" ) ) {
-			p->format_opts |= BIBOUT_BRACKETS;
+			p->format_opts |= BIBL_FORMAT_BIBOUT_BRACKETS;
 			subtract = 1;
 		} else if ( args_match( argv[i], "-w", "--whitespace" ) ) {
-			p->format_opts |= BIBOUT_WHITESPACE;
+			p->format_opts |= BIBL_FORMAT_BIBOUT_WHITESPACE;
 			subtract = 1;
 		} else if ( args_match( argv[i], "-sk", "--strictkey" ) ) {
-			p->format_opts |= BIBOUT_STRICTKEY;
+			p->format_opts |= BIBL_FORMAT_BIBOUT_STRICTKEY;
 			subtract = 1;
 		} else if ( args_match( argv[i], "-U", "--uppercase" ) ) {
-			p->format_opts |= BIBOUT_UPPERCASE;
+			p->format_opts |= BIBL_FORMAT_BIBOUT_UPPERCASE;
 			subtract = 1;
 		} else if ( args_match( argv[i], "-at", "--abbreviated-titles" ) ) {
-			p->format_opts |= BIBOUT_SHORTTITLE;
+			p->format_opts |= BIBL_FORMAT_BIBOUT_SHORTTITLE;
 			subtract = 1;
 		} else if ( args_match( argv[i], "-nl", "--no-latex" ) ) {
 			p->latexout = 0;
@@ -95,7 +94,7 @@ process_args( int *argc, char *argv[], param *p )
 			p->utf8bom = 0;
 			subtract = 1;
 		} else if ( args_match( argv[i], "-d", "--drop-key" ) ) {
-			p->format_opts |= BIBOUT_DROPKEY;
+			p->format_opts |= BIBL_FORMAT_BIBOUT_DROPKEY;
 			subtract = 1;
 		} else if ( args_match( argv[i], "--verbose", "" ) ) {
 			p->verbose = 1;
@@ -127,5 +126,3 @@ main( int argc, char *argv[] )
 	bibl_freeparams( &p );
 	return EXIT_SUCCESS;
 }
-
-
diff --git a/bin/xml2end.c b/bin/xml2end.c
index 7d15063..19d1073 100644
--- a/bin/xml2end.c
+++ b/bin/xml2end.c
@@ -1,7 +1,7 @@
 /*
  * xml2end.c
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -9,8 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "bibutils.h"
-#include "modsin.h"
-#include "endout.h"
+#include "bibformats.h"
 #include "args.h"
 #include "bibprog.h"
 
diff --git a/bin/xml2isi.c b/bin/xml2isi.c
index 202928c..7560163 100644
--- a/bin/xml2isi.c
+++ b/bin/xml2isi.c
@@ -1,7 +1,7 @@
 /*
  * xml2isi.c
  *
- * Copyright (c) Chris Putnam 2007-2015
+ * Copyright (c) Chris Putnam 2007-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -9,8 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "bibutils.h"
-#include "modsin.h"
-#include "isiout.h"
+#include "bibformats.h"
 #include "args.h"
 #include "bibprog.h"
 
diff --git a/bin/xml2ris.c b/bin/xml2ris.c
index 903b218..3e33fd9 100644
--- a/bin/xml2ris.c
+++ b/bin/xml2ris.c
@@ -1,7 +1,7 @@
 /*
  * xml2ris.c
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -9,8 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "bibutils.h"
-#include "modsin.h"
-#include "risout.h"
+#include "bibformats.h"
 #include "args.h"
 #include "bibprog.h"
 
@@ -89,5 +88,3 @@ main(int argc, char *argv[])
 	bibl_freeparams( &p );
 	return EXIT_SUCCESS;
 }
-
-
diff --git a/bin/xml2wordbib.c b/bin/xml2wordbib.c
index 668b26d..abc5b64 100644
--- a/bin/xml2wordbib.c
+++ b/bin/xml2wordbib.c
@@ -1,7 +1,7 @@
 /*
  * xml2wordbib.c
  *
- * Copyright (c) Chris Putnam 2007-2015
+ * Copyright (c) Chris Putnam 2007-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -9,8 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "bibutils.h"
-#include "modsin.h"
-#include "wordout.h"
+#include "bibformats.h"
 #include "args.h"
 #include "bibprog.h"
 
diff --git a/lib/Makefile.dynamic b/lib/Makefile.dynamic
index 9c630df..cff8620 100644
--- a/lib/Makefile.dynamic
+++ b/lib/Makefile.dynamic
@@ -21,15 +21,17 @@ CONTAIN_OBJS  = fields.o \
                 xml_encoding.o
 
 BIBL_OBJS     = bibl.o \
-                doi.o \
                 iso639_1.o \
                 iso639_2.o \
                 iso639_3.o \
                 marc.o \
                 name.o \
+                notes.o \
+                pages.o \
                 reftypes.o \
                 serialno.o \
-                title.o
+                title.o \
+                url.o
 
 INPUT_OBJS    = bibtexin.o bibtextypes.o \
 		biblatexin.o bltypes.o \
diff --git a/lib/Makefile.static b/lib/Makefile.static
index f0d6cb6..24be989 100644
--- a/lib/Makefile.static
+++ b/lib/Makefile.static
@@ -20,15 +20,17 @@ CONTAIN_OBJS  = fields.o \
                 xml_encoding.o
 
 BIBL_OBJS     = bibl.o \
-                doi.o \
                 iso639_1.o \
                 iso639_2.o \
                 iso639_3.o \
                 marc.o \
                 name.o \
+                notes.o \
+                pages.o \
                 reftypes.o \
                 serialno.o \
-                title.o
+                title.o \
+                url.o
 
 INPUT_OBJS    = bibtexin.o \
                 bibtextypes.o \
diff --git a/lib/adsout.c b/lib/adsout.c
index 372025a..0accac6 100644
--- a/lib/adsout.c
+++ b/lib/adsout.c
@@ -1,8 +1,8 @@
 /*
  * adsout.c
  *
- * Copyright (c) Richard Mathar 2007-2015
- * Copyright (c) Chris Putnam 2007-2015
+ * Copyright (c) Richard Mathar 2007-2016
+ * Copyright (c) Chris Putnam 2007-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -17,7 +17,13 @@
 #include "strsearch.h"
 #include "fields.h"
 #include "name.h"
-#include "adsout.h"
+#include "title.h"
+#include "url.h"
+#include "bibformats.h"
+
+static int  adsout_write( fields *in, FILE *fp, param *p, unsigned long refnum );
+static void adsout_writeheader( FILE *outptr, param *p );
+
 
 void
 adsout_initparams( param *p, const char *progname )
@@ -76,7 +82,7 @@ typedef struct match_type {
 } match_type;
 
 static int
-get_type( fields *info )
+get_type( fields *in )
 {
 	match_type match_genres[] = {
 		{ "academic journal",          TYPE_ARTICLE },
@@ -101,15 +107,15 @@ get_type( fields *info )
 	char *tag, *data;
 	int i, j, type = TYPE_UNKNOWN;
 
-	for ( i=0; i<info->n; ++i ) {
-		tag = info->tag[i].data;
+	for ( i=0; i<in->n; ++i ) {
+		tag = in->tag[i].data;
 		if ( strcasecmp( tag, "GENRE" )!=0 &&
 		     strcasecmp( tag, "NGENRE" )!=0 ) continue;
-		data = info->data[i].data;
+		data = in->data[i].data;
 		for ( j=0; j<nmatch_genres; ++j ) {
 			if ( !strcasecmp( data, match_genres[j].name ) ) {
 				type = match_genres[j].type;
-				fields_setused( info, i );
+				fields_setused( in, i );
 			}
 		}
 		if ( type==TYPE_UNKNOWN ) {
@@ -118,26 +124,26 @@ get_type( fields *info )
 			else if ( !strcasecmp( data, "thesis" ) )
 				type = TYPE_THESIS;
 			else if ( !strcasecmp( data, "book" ) ) {
-				if ( info->level[i]==0 ) type = TYPE_BOOK;
+				if ( in->level[i]==0 ) type = TYPE_BOOK;
 				else type = TYPE_INBOOK;
 			}
 			else if ( !strcasecmp( data, "collection" ) ) {
-				if ( info->level[i]==0 ) type = TYPE_BOOK;
+				if ( in->level[i]==0 ) type = TYPE_BOOK;
 				else type = TYPE_INBOOK;
 			}
-			if ( type!=TYPE_UNKNOWN ) fields_setused( info, i );
+			if ( type!=TYPE_UNKNOWN ) fields_setused( in, i );
 		}
 	}
 	if ( type==TYPE_UNKNOWN ) {
-		for ( i=0; i<info->n; ++i ) {
-			if ( strcasecmp( info->tag[i].data, "RESOURCE" ) )
+		for ( i=0; i<in->n; ++i ) {
+			if ( strcasecmp( in->tag[i].data, "RESOURCE" ) )
 				continue;
-			data = info->data[i].data;
+			data = in->data[i].data;
 			if ( !strcasecmp( data, "moving image" ) )
 				type = TYPE_BROADCAST;
 			else if ( !strcasecmp( data, "software, multimedia" ) )
 				type = TYPE_PROGRAM;
-			if ( type!=TYPE_UNKNOWN ) fields_setused( info, i );
+			if ( type!=TYPE_UNKNOWN ) fields_setused( in, i );
 		}
 	}
 
@@ -147,81 +153,136 @@ get_type( fields *info )
 	return type;
 }
 
-static void
-output_title( FILE *fp, fields *f, char *full, char *sub, char *adstag, int level )
+static int
+append_title( fields *in, char *ttl, char *sub, char *adstag, int level, fields *out, int *status )
 {
-	newstr *fulltitle, *subtitle, *vol, *iss, *sn, *en, *ar;
+	newstr fulltitle, *title, *subtitle, *vol, *iss, *sn, *en, *ar;
+	int fstatus, output = 0;
 
-	fulltitle = fields_findv( f, level, FIELDS_STRP, full );
-	subtitle  = fields_findv( f, level, FIELDS_STRP, sub );
+	newstr_init( &fulltitle );
 
-	if ( fulltitle && fulltitle->len ) {
+	title     = fields_findv( in, level, FIELDS_STRP, ttl );
+	subtitle  = fields_findv( in, level, FIELDS_STRP, sub );
 
-		fprintf( fp, "%s %s", adstag, fulltitle->data );
-		if ( subtitle && subtitle->len ) {
-			if ( fulltitle->data[ fulltitle->len - 1 ] != '?' )
-				fprintf( fp, ": " );
-			else fprintf( fp, " " );
-			fprintf( fp, "%s", subtitle->data );
-		}
+	if ( title && title->len ) {
+
+		output = 1;
 
-		vol = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "VOLUME" );
-		if ( vol && vol->len ) fprintf( fp, ", vol. %s", vol->data );
+		title_combine( &fulltitle, title, subtitle );
 
-		iss = fields_findv_firstof( f, LEVEL_ANY, FIELDS_STRP, "ISSUE",
+		vol = fields_findv( in, LEVEL_ANY, FIELDS_STRP, "VOLUME" );
+		if ( vol && vol->len ) {
+			newstr_strcat( &fulltitle, ", vol. " );
+			newstr_newstrcat( &fulltitle, vol );
+		}
+
+		iss = fields_findv_firstof( in, LEVEL_ANY, FIELDS_STRP, "ISSUE",
 			"NUMBER", NULL );
-		if ( iss && iss->len ) fprintf( fp, ", no. %s", iss->data );
+		if ( iss && iss->len ) {
+			newstr_strcat( &fulltitle, ", no. " );
+			newstr_newstrcat( &fulltitle, iss );
+		}
 
-		sn = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "PAGESTART" );
-		en = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "PAGEEND" );
-		ar = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "ARTICLENUMBER" );
+		sn = fields_findv( in, LEVEL_ANY, FIELDS_STRP, "PAGES:START" );
+		en = fields_findv( in, LEVEL_ANY, FIELDS_STRP, "PAGES:STOP" );
+		ar = fields_findv( in, LEVEL_ANY, FIELDS_STRP, "ARTICLENUMBER" );
 		if ( sn && sn->len ) {
-			if ( en && en->len )
-				fprintf( fp, ", pp." );
-			else
-				fprintf( fp, ", p." );
-			fprintf( fp, " %s", sn->data );
+			if ( en && en->len ) {
+				newstr_strcat( &fulltitle, ", pp. " );
+			} else {
+				newstr_strcat( &fulltitle, ", p. " );
+			}
+			newstr_newstrcat( &fulltitle, sn );
 		} else if ( ar && ar->len ) {
-			fprintf( fp, ", p. %s", ar->data );
+			newstr_strcat( &fulltitle, ", p. " );
+			newstr_newstrcat( &fulltitle, ar );
 		}
 		if ( en && en->len ) {
-			fprintf( fp, "-%s", en->data );
+			newstr_addchar( &fulltitle, '-' );
+			newstr_newstrcat( &fulltitle, en );
 		}
 
-		fprintf( fp, "\n" );
+		fstatus = fields_add( out, adstag, newstr_cstr( &fulltitle ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+
 	}
+
+	newstr_free( &fulltitle );
+
+	return output;
 }
 
 static void
-output_people( FILE *fp, fields *f, char *tag1, char *tag2, char *tag3, char *adstag, int level )
+append_titles( fields *in, int type, fields *out, int *status )
 {
-	newstr oneperson;
+	int added;
+	if ( type==TYPE_ARTICLE || type==TYPE_MAGARTICLE ) {
+		added = append_title( in, "TITLE", "SUBTITLE", "%J", LEVEL_HOST, out, status );
+		if ( added==0 )
+			(void) append_title( in, "SHORTTITLE", "SHORTSUBTITLE", "%J", LEVEL_HOST, out, status );
+	}
+}
+
+static void
+append_people( fields *in, char *tag1, char *tag2, char *tag3, char *adstag, int level, fields *out, int *status )
+{
+	newstr oneperson, allpeople;
 	vplist a;
-	int i;
+	int i, fstatus;
+
 	newstr_init( &oneperson );
+	newstr_init( &allpeople );
 	vplist_init( &a );
-	fields_findv_eachof( f, level, FIELDS_CHRP, &a, tag1, tag2, tag3, NULL );
-	extern void  fields_findv_eachof( fields *f, int level, int mode, vplist *a, ... );
+
+	fields_findv_eachof( in, level, FIELDS_CHRP, &a, tag1, tag2, tag3, NULL );
 	for ( i=0; i<a.n; ++i ) {
-		if ( i==0 ) fprintf( fp, "%s ", adstag );
-		else fprintf( fp, "; " );
+		if ( i!=0 ) newstr_strcat( &allpeople, "; " );
 		name_build_withcomma( &oneperson, (char *) vplist_get( &a, i) );
-		fprintf( fp, "%s", oneperson.data );
+		newstr_newstrcat( &allpeople, &oneperson );
+	}
+	if ( a.n ) {
+		fstatus = fields_add( out, adstag, newstr_cstr( &allpeople ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 	}
-	if ( a.n ) fprintf( fp, "\n" );
+
 	vplist_free( &a );
 	newstr_free( &oneperson );
+	newstr_free( &allpeople );
 }
 
 static void
-output_pages( FILE *fp, fields *f )
+append_pages( fields *in, fields *out, int *status )
 {
-	newstr *sn = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "PAGESTART" );
-	newstr *en = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "PAGEEND" );
-	newstr *ar = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "ARTICLENUMBER" );
-	if ( sn && sn->len!=0 ) fprintf( fp, "%%P %s\n", sn->data );
-	else if ( ar && ar->len!=0 ) fprintf( fp, "%%P %s\n", ar->data );
-	if ( en && en->len!=0 ) fprintf( fp, "%%L %s\n", en->data );
+	newstr *sn, *en, *ar;
+	int fstatus;
+
+	sn = fields_findv( in, LEVEL_ANY, FIELDS_STRP, "PAGES:START" );
+	en = fields_findv( in, LEVEL_ANY, FIELDS_STRP, "PAGES:STOP" );
+	ar = fields_findv( in, LEVEL_ANY, FIELDS_STRP, "ARTICLENUMBER" );
+
+	if ( sn && sn->len!=0 ) {
+		fstatus = fields_add( out, "%P", newstr_cstr( sn ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) {
+			*status = BIBL_ERR_MEMERR;
+			return;
+		}
+	}
+
+	else if ( ar && ar->len!=0 ) {
+		fstatus = fields_add( out, "%P", newstr_cstr( ar ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) {
+			*status = BIBL_ERR_MEMERR;
+			return;
+		}
+	}
+
+	if ( en && en->len!=0 ) {
+		fstatus = fields_add( out, "%L", newstr_cstr( en ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) {
+			*status = BIBL_ERR_MEMERR;
+			return;
+		}
+	}
 }
 
 static int
@@ -240,23 +301,28 @@ mont2mont( const char *m )
 }
 
 static int
-get_month( fields *f, int level )
+get_month( fields *in, int level )
 {
-	newstr *month = fields_findv_firstof( f, level, FIELDS_STRP,
-			"MONTH", "PARTMONTH", NULL );
+	newstr *month;
+
+	month = fields_findv_firstof( in, level, FIELDS_STRP, "DATE:MONTH", "PARTDATE:MONTH", NULL );
 	if ( month && month->len ) return mont2mont( month->data );
 	else return 0;
 }
 
 static void
-output_date( FILE *fp, fields *f, char *adstag, int level )
+append_date( fields *in, char *adstag, int level, fields *out, int *status )
 {
-	newstr *year = fields_findv_firstof( f, level, FIELDS_STRP,
-		"YEAR", "PARTYEAR", NULL );
-	int month;
+	int month, fstatus;
+	char outstr[1000];
+	newstr *year;
+
+	year = fields_findv_firstof( in, level, FIELDS_STRP, "DATE:YEAR", "PARTDATE:YEAR", NULL );
 	if ( year && year->len ) {
-		month = get_month( f, level );
-		fprintf( fp, "%s %02d/%s\n", adstag, month, year->data );
+		month = get_month( in, level );
+		sprintf( outstr, "%02d/%s", month, newstr_cstr( year ) );
+		fstatus = fields_add( out, adstag, outstr, LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 	}
 }
 
@@ -279,29 +345,29 @@ output_4digit_value( char *pos, long long n )
 }
 
 static char
-get_firstinitial( fields *f )
+get_firstinitial( fields *in )
 {
 	char *name;
 	int n;
 
-	n = fields_find( f, "AUTHOR", LEVEL_MAIN );
-	if ( n==-1 ) n = fields_find( f, "AUTHOR", LEVEL_ANY );
+	n = fields_find( in, "AUTHOR", LEVEL_MAIN );
+	if ( n==-1 ) n = fields_find( in, "AUTHOR", LEVEL_ANY );
 
 	if ( n!=-1 ) {
-		name = fields_value( f, n, FIELDS_CHRP );
+		name = fields_value( in, n, FIELDS_CHRP );
 		return name[0];
 	} else return '\0';
 }
 
 static int
-get_journalabbr( fields *f )
+get_journalabbr( fields *in )
 {
 	char *jrnl;
 	int n, j;
 
-	n = fields_find( f, "TITLE", LEVEL_HOST );
+	n = fields_find( in, "TITLE", LEVEL_HOST );
 	if ( n!=-1 ) {
-		jrnl = fields_value( f, n, FIELDS_CHRP );
+		jrnl = fields_value( in, n, FIELDS_CHRP );
 		for ( j=0; j<njournals; j++ ) {
 			if ( !strcasecmp( jrnl, journals[j]+6 ) )
 				return j;
@@ -311,121 +377,210 @@ get_journalabbr( fields *f )
 }
 
 static void
-output_Rtag( FILE *fp, fields *f, char *adstag, int type )
+append_Rtag( fields *in, char *adstag, int type, fields *out, int *status )
 {
-	char out[20], ch;
-	int n, i;
+	char outstr[20], ch;
+	int n, i, fstatus;
 	long long page;
 
-	strcpy( out, "..................." );
+	strcpy( outstr, "..................." );
 
 	/** YYYY */
-	n = fields_find( f, "YEAR", LEVEL_ANY );
-	if ( n==-1 ) n = fields_find( f, "PARTYEAR", LEVEL_ANY );
-	if ( n!=-1 ) output_4digit_value( out, atoi( fields_value( f, n, FIELDS_CHRP ) ) );
+	n = fields_find( in, "DATE:YEAR", LEVEL_ANY );
+	if ( n==-1 ) n = fields_find( in, "PARTDATE:YEAR", LEVEL_ANY );
+	if ( n!=-1 ) output_4digit_value( outstr, atoi( fields_value( in, n, FIELDS_CHRP ) ) );
 
 	/** JJJJ */
-	n = get_journalabbr( f );
+	n = get_journalabbr( in );
 	if ( n!=-1 ) {
 		i = 0;
 		while ( i<5 && journals[n][i]!=' ' && journals[n][i]!='\t' ) {
-			out[4+i] = journals[n][i];
+			outstr[4+i] = journals[n][i];
 			i++;
 		}
 	}
 
 	/** VVVV */
-	n = fields_find( f, "VOLUME", LEVEL_ANY );
-	if ( n!=-1 ) output_4digit_value( out+9, atoi( fields_value( f, n, FIELDS_CHRP ) ) );
+	n = fields_find( in, "VOLUME", LEVEL_ANY );
+	if ( n!=-1 ) output_4digit_value( outstr+9, atoi( fields_value( in, n, FIELDS_CHRP ) ) );
 
 	/** MPPPP */
-	n = fields_find( f, "PAGESTART", LEVEL_ANY );
-	if ( n==-1 ) n = fields_find( f, "ARTICLENUMBER", LEVEL_ANY );
+	n = fields_find( in, "PAGES:START", LEVEL_ANY );
+	if ( n==-1 ) n = fields_find( in, "ARTICLENUMBER", LEVEL_ANY );
 	if ( n!=-1 ) {
-		page = atoll( fields_value( f, n, FIELDS_CHRP ) );
-		output_4digit_value( out+14, page );
+		page = atoll( fields_value( in, n, FIELDS_CHRP ) );
+		output_4digit_value( outstr+14, page );
 		if ( page>=10000 ) {
 			ch = 'a' + (page/10000);
-			out[13] = ch;
+			outstr[13] = ch;
 		}
 	}
 
 	/** A */
-        ch = toupper( (unsigned char) get_firstinitial( f ) );
-	if ( ch!='\0' ) out[18] = ch;
+        ch = toupper( (unsigned char) get_firstinitial( in ) );
+	if ( ch!='\0' ) outstr[18] = ch;
 
-	fprintf( fp, "%s %s\n", adstag, out );
+	fstatus = fields_add( out, adstag, outstr, LEVEL_MAIN );
+	if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 }
 
 static void
-output_easyall( FILE *fp, fields *f, char *tag, char *adstag, int level )
+append_easyall( fields *in, char *tag, char *adstag, int level, fields *out, int *status )
 {
+	int i, fstatus;
 	vplist a;
-	int i;
+
 	vplist_init( &a );
-	fields_findv_each( f, level, FIELDS_CHRP, &a, tag );
-	for ( i=0; i<a.n; ++i )
-		fprintf( fp, "%s %s\n", adstag, (char *) vplist_get( &a, i ) );
+
+	fields_findv_each( in, level, FIELDS_CHRP, &a, tag );
+
+	for ( i=0; i<a.n; ++i ) {
+		fstatus = fields_add( out, adstag, (char*) vplist_get( &a, i ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) {
+			*status = BIBL_ERR_MEMERR;
+			goto out;
+		}
+	}
+out:
 	vplist_free( &a );
 }
 
 static void
-output_easy( FILE *fp, fields *f, char *tag, char *adstag, int level )
+append_easy( fields *in, char *tag, char *adstag, int level, fields *out, int *status )
 {
-	char *value = fields_findv( f, level, FIELDS_CHRP, tag );
-	if ( value && value[0]!='\0' ) fprintf( fp, "%s %s\n", adstag, value );
+	char *value;
+	int fstatus;
+
+	value = fields_findv( in, level, FIELDS_CHRP, tag );
+	if ( value && value[0]!='\0' ) {
+		fstatus = fields_add( out, adstag, value, LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
 }
 
 static void
-output_keys( FILE *fp, fields *f, char *tag, char *adstag, int level )
+append_keys( fields *in, char *tag, char *adstag, int level, fields *out, int *status )
 {
+	newstr allkeys;
+	int i, fstatus;
 	vplist a;
-	int i;
+
+	newstr_init( &allkeys );
 	vplist_init( &a );
-	fields_findv_each( f, level, FIELDS_CHRP, &a, tag );
+
+	fields_findv_each( in, level, FIELDS_CHRP, &a, tag );
+
 	for ( i=0; i<a.n; ++i ) {
-		if ( i==0 ) fprintf( fp, "%s ", adstag );
-		else fprintf( fp, ", " );
-		fprintf( fp, "%s", (char *) vplist_get( &a, i ) );
+		if ( i>0 ) newstr_strcat( &allkeys, ", " );
+		newstr_strcat( &allkeys, (char *) vplist_get( &a, i ) );
 	}
-	if ( a.n ) fprintf( fp, "\n" );
+
+	if ( a.n ) {
+		fstatus = fields_add( out, adstag, newstr_cstr( &allkeys ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
+
+	newstr_free( &allkeys );
 	vplist_free( &a );
 }
 
-void
-adsout_write( fields *f, FILE *fp, param *p, unsigned long refnum )
+static void
+append_urls( fields *in, fields *out, int *status )
 {
-	int type;
-	fields_clearused( f );
-	type = get_type( f );
-
-	output_people(  fp, f, "AUTHOR", "AUTHOR:ASIS", "AUTHOR:CORP", "%A", LEVEL_MAIN );
-	output_people(  fp, f, "EDITOR", "EDITOR:ASIS", "EDITOR:CORP", "%E", LEVEL_ANY );
-	output_easy(    fp, f, "TITLE",       "%T", LEVEL_ANY );
-
-	if ( type==TYPE_ARTICLE || type==TYPE_MAGARTICLE )
-		output_title( fp, f, "TITLE", "SUBTITLE", "%J", LEVEL_HOST );
-
-	output_date(    fp, f,               "%D", LEVEL_ANY );
-	output_easy(    fp, f, "VOLUME",     "%V", LEVEL_ANY );
-	output_easy(    fp, f, "ISSUE",      "%N", LEVEL_ANY );
-	output_easy(    fp, f, "NUMBER",     "%N", LEVEL_ANY );
-	output_easy(    fp, f, "LANGUAGE",   "%M", LEVEL_ANY );
-	output_easyall( fp, f, "NOTES",      "%X", LEVEL_ANY );
-	output_easy(    fp, f, "ABSTRACT",   "%B", LEVEL_ANY );
-	output_keys(    fp, f, "KEYWORD",    "%K", LEVEL_ANY );
-	output_easyall( fp, f, "URL",        "%U", LEVEL_ANY ); 
-	output_easyall( fp, f, "FILEATTACH", "%U", LEVEL_ANY ); 
-	output_easyall( fp, f, "FIGATTACH",  "%U", LEVEL_ANY ); 
-	output_pages( fp, f );
-	output_easyall( fp, f, "DOI",        "%Y", LEVEL_ANY );
-        fprintf( fp, "%%W PHY\n%%G AUTHOR\n" );
-	output_Rtag( fp, f, "%R", type );
+	int lstatus;
+	list types;
+
+	lstatus = list_init_valuesc( &types, "URL", "PMID", "PMC", "ARXIV", "JSTOR", "MRNUMBER", "FILEATTACH", "FIGATTACH", NULL );
+	if ( lstatus!=LIST_OK ) {
+		*status = BIBL_ERR_MEMERR;
+		return;
+	}
+
+	*status = urls_merge_and_add( in, LEVEL_ANY, out, "%U", LEVEL_MAIN, &types );
+
+	list_free( &types );
+}
+
+static void
+append_trailer( fields *out, int *status )
+{
+	int fstatus;
+
+	fstatus = fields_add( out, "%W", "PHY", LEVEL_MAIN );
+	if ( fstatus!=FIELDS_OK ) {
+		*status = BIBL_ERR_MEMERR;
+		return;
+	}
+
+	fstatus = fields_add( out, "%G", "AUTHOR", LEVEL_MAIN );
+	if ( fstatus!=FIELDS_OK ) {
+		*status = BIBL_ERR_MEMERR;
+		return;
+	}
+}
+
+static void
+output( FILE *fp, fields *out )
+{
+	char *tag, *value;
+	int i;
+
+	for ( i=0; i<out->n; ++i ) {
+		tag   = fields_tag( out, i, FIELDS_CHRP );
+		value = fields_value( out, i, FIELDS_CHRP );
+		fprintf( fp, "%s %s\n", tag, value );
+	}
+
 	fprintf( fp, "\n" );
 	fflush( fp );
 }
 
-void
+static int
+append_data( fields *in, fields *out )
+{
+	int type, status = BIBL_OK;
+
+	fields_clearused( in );
+	type = get_type( in );
+
+	append_people ( in, "AUTHOR", "AUTHOR:ASIS", "AUTHOR:CORP", "%A", LEVEL_MAIN, out, &status );
+	append_people ( in, "EDITOR", "EDITOR:ASIS", "EDITOR:CORP", "%E", LEVEL_ANY,  out, &status );
+	append_easy   ( in, "TITLE",       "%T", LEVEL_ANY, out, &status );
+	append_titles ( in, type, out, &status );
+	append_date   ( in,               "%D", LEVEL_ANY, out, &status );
+	append_easy   ( in, "VOLUME",     "%V", LEVEL_ANY, out, &status );
+	append_easy   ( in, "ISSUE",      "%N", LEVEL_ANY, out, &status );
+	append_easy   ( in, "NUMBER",     "%N", LEVEL_ANY, out, &status );
+	append_easy   ( in, "LANGUAGE",   "%M", LEVEL_ANY, out, &status );
+	append_easyall( in, "NOTES",      "%X", LEVEL_ANY, out, &status );
+	append_easy   ( in, "ABSTRACT",   "%B", LEVEL_ANY, out, &status );
+	append_keys   ( in, "KEYWORD",    "%K", LEVEL_ANY, out, &status );
+	append_urls   ( in, out, &status );
+	append_pages  ( in, out, &status );
+	append_easyall( in, "DOI",        "%Y", LEVEL_ANY, out, &status );
+	append_trailer( out, &status );
+	append_Rtag   ( in, "%R", type, out, &status );
+
+	return status;
+}
+
+static int
+adsout_write( fields *in, FILE *fp, param *p, unsigned long refnum )
+{
+	int status;
+	fields out;
+
+	fields_init( &out );
+
+	status = append_data( in, &out );
+	if ( status==BIBL_OK ) output( fp, &out );
+
+	fields_free( &out );
+
+	return status;
+}
+
+static void
 adsout_writeheader( FILE *outptr, param *p )
 {
 	if ( p->utf8bom ) utf8_writebom( outptr );
diff --git a/lib/adsout.h b/lib/adsout.h
deleted file mode 100644
index 2e548db..0000000
--- a/lib/adsout.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * adsout.h
- *
- * Copyright (c) Richard Mathar 2007-2015
- * Copyright (c) Chris Putnam 2007-2015
- *
- * Source code released under the GPL version 2
- *
- */
-#ifndef ADSOUT_H
-#define ADSOUT_H
-
-#include <stdio.h>
-#include "bibutils.h"
-
-extern void adsout_write( fields *info, FILE *fp, param *p,
-		unsigned long refnum );
-extern void adsout_writeheader( FILE *outptr, param *p );
-
-extern void adsout_initparams( param *p, const char *progname );
-
-#endif
diff --git a/lib/bibcore.c b/lib/bibcore.c
index 16ef5d2..059c58a 100644
--- a/lib/bibcore.c
+++ b/lib/bibcore.c
@@ -1,7 +1,7 @@
 /*
  * bibcore.c
  *
- * Copyright (c) Chris Putnam 2005-2015
+ * Copyright (c) Chris Putnam 2005-2016
  *
  * Source code released under the GPL version 2
  *
@@ -468,7 +468,7 @@ read_ref( FILE *fp, bibl *bin, char *filename, param *p )
 			bibl_free( bin );
 			goto out;
 		}
-		if ( p->processf( ref, reference.data, filename, nrefs+1 )){
+		if ( p->processf( ref, reference.data, filename, nrefs+1, p )){
 			ok = bibl_addref( bin, ref );
 			if ( !ok ) {
 				ret = BIBL_ERR_MEMERR;
@@ -570,10 +570,10 @@ build_refnum( fields *f, long nrefs, int *n )
 
 	newstr_init( &refnum );
 
-	year = fields_findv( f, LEVEL_MAIN, FIELDS_CHRP_NOUSE, "YEAR" );
+	year = fields_findv( f, LEVEL_MAIN, FIELDS_CHRP_NOUSE, "DATE:YEAR" );
 	if ( !year )
 		year = fields_findv_firstof( f, LEVEL_ANY, FIELDS_CHRP_NOUSE,
-			"YEAR", "PARTYEAR", NULL );
+			"DATE:YEAR", "PARTDATE:YEAR", NULL );
 
 	author = fields_findv( f, LEVEL_MAIN, FIELDS_CHRP_NOUSE, "AUTHOR" );
 	if ( !author )
@@ -643,10 +643,10 @@ generate_citekey( fields *f, int nref )
 
 	n1 = fields_find( f, "AUTHOR", 0 );
 	if ( n1==-1 ) n1 = fields_find( f, "AUTHOR", -1 );
-	n2 = fields_find( f, "YEAR", 0 );
-	if ( n2==-1 ) n2 = fields_find( f, "YEAR", -1 );
-	if ( n2==-1 ) n2 = fields_find( f, "PARTYEAR", 0 );
-	if ( n2==-1 ) n2 = fields_find( f, "PARTYEAR", -1 );
+	n2 = fields_find( f, "DATE:YEAR", 0 );
+	if ( n2==-1 ) n2 = fields_find( f, "DATE:YEAR", -1 );
+	if ( n2==-1 ) n2 = fields_find( f, "PARTDATE:YEAR", 0 );
+	if ( n2==-1 ) n2 = fields_find( f, "PARTDATE:YEAR", -1 );
 	if ( n1!=-1 && n2!=-1 ) {
 		p = f->data[n1].data;
 		while ( p && *p && *p!='|' ) {
@@ -803,8 +803,8 @@ convert_ref( bibl *bin, char *fname, bibl *bout, param *p )
 		rout = fields_new();
 		if ( !rout ) return BIBL_ERR_MEMERR;
 		if ( p->typef ) 
-			reftype = p->typef( rin, fname, i+1, p, p->all, p->nall );
-		status = p->convertf( rin, rout, reftype, p, p->all, p->nall );
+			reftype = p->typef( rin, fname, i+1, p );
+		status = p->convertf( rin, rout, reftype, p );
 		if ( status!=BIBL_OK ) return status;
 		if ( p->all ) {
 			status = process_alwaysadd( rout, reftype, p );
@@ -815,6 +815,13 @@ convert_ref( bibl *bin, char *fname, bibl *bout, param *p )
 		ok = bibl_addref( bout, rout );
 		if ( !ok ) return BIBL_ERR_MEMERR;
 	}
+	if ( debug_set( p ) ) {
+		fflush( stdout );
+		fprintf( stderr, "-------------------start for convert_ref\n");
+		bibl_verbose0( bout );
+		fprintf( stderr, "-------------------end for convert_ref\n" );
+		fflush( stderr );
+	}
 	status = uniqueify_citekeys( bout );
 	return status;
 }
@@ -838,7 +845,10 @@ bibl_read( bibl *b, FILE *fp, char *filename, param *p )
 	bibl_init( &bin );
 
 	status = read_ref( fp, &bin, filename, &lp );
-	if ( status!=BIBL_OK ) return status;
+	if ( status!=BIBL_OK ) {
+		bibl_freeparams( &lp );
+		return status;
+	}
 
 	if ( debug_set( p ) ) {
 		fflush( stdout );
@@ -884,13 +894,18 @@ bibl_read( bibl *b, FILE *fp, char *filename, param *p )
 			fflush( stderr );
 		}
 		ok = bibl_copy( b, &bin );
-		if ( !ok ) return BIBL_ERR_MEMERR;
+		if ( !ok ) {
+			bibl_freeparams( &lp );
+			return BIBL_ERR_MEMERR;
+		}
 	}
 	if ( !lp.output_raw || ( lp.output_raw & BIBL_RAW_WITHMAKEREFID ) )
 		bibl_checkrefid( b, &lp );
 
 	bibl_free( &bin );
 
+	bibl_freeparams( &lp );
+
 	return BIBL_OK;
 }
 
@@ -932,14 +947,16 @@ singlerefname( fields *reffields, long nref, int mode )
 static int
 bibl_writeeachfp( FILE *fp, bibl *b, param *p )
 {
+	int status;
 	long i;
 	for ( i=0; i<b->nrefs; ++i ) {
 		fp = singlerefname( b->ref[i], i, p->writeformat );
 		if ( !fp ) return BIBL_ERR_CANTOPEN;
 		if ( p->headerf ) p->headerf( fp, p );
-		p->writef( b->ref[i], fp, p, i );
+		status = p->writef( b->ref[i], fp, p, i );
 		if ( p->footerf ) p->footerf( fp );
 		fclose( fp );
+		if ( status!=BIBL_OK ) return status;
 	}
 	return BIBL_OK;
 }
@@ -947,12 +964,15 @@ bibl_writeeachfp( FILE *fp, bibl *b, param *p )
 static int
 bibl_writefp( FILE *fp, bibl *b, param *p )
 {
+	int status = BIBL_OK;
 	long i;
 	if ( p->headerf ) p->headerf( fp, p );
-	for ( i=0; i<b->nrefs; ++i )
-		p->writef( b->ref[i], fp, p, i );
+	for ( i=0; i<b->nrefs; ++i ) {
+		status = p->writef( b->ref[i], fp, p, i );
+		if ( status!=BIBL_OK ) break;
+	}
 	if ( p->footerf ) p->footerf( fp );
-	return BIBL_OK;
+	return status;
 }
 
 int
@@ -972,11 +992,20 @@ bibl_write( bibl *b, FILE *fp, param *p )
 	status = bibl_fixcharsets( b, &lp );
 	if ( status!=BIBL_OK ) return status;
 
-	if ( debug_set( p ) ) report_params( stderr, "bibl_write", &lp );
+	if ( debug_set( p ) ) {
+		report_params( stderr, "bibl_write", &lp );
+		fflush( stdout );
+		fprintf( stderr, "-------------------start for bibl_write\n");
+		bibl_verbose0( b );
+		fprintf( stderr, "-------------------end for bibl_write\n" );
+		fflush( stderr );
+	}
 
 	if ( p->singlerefperfile ) status = bibl_writeeachfp( fp, b, &lp );
 	else status = bibl_writefp( fp, b, &lp );
 
+	bibl_freeparams( &lp );
+
 	return status;
 }
 
diff --git a/lib/bibformats.h b/lib/bibformats.h
new file mode 100644
index 0000000..a50df67
--- /dev/null
+++ b/lib/bibformats.h
@@ -0,0 +1,35 @@
+/*
+ * bibformats.h
+ *
+ * Copyright (c) Chris Putnam 2007-2016
+ *
+ * Source code released under the GPL version 2
+ *
+ */
+#ifndef BIBFORMATS_H
+#define BIBFORMATS_H
+
+#include "bibutils.h"
+
+void adsout_initparams(     param *p, const char *progname );
+void biblatexin_initparams( param *p, const char *progname );
+void bibtexin_initparams(   param *p, const char *progname );
+void bibtexout_initparams(  param *p, const char *progname );
+void copacin_initparams(    param *p, const char *progname );
+void ebiin_initparams(      param *p, const char *progname );
+void endin_initparams(      param *p, const char *progname );
+void endout_initparams(     param *p, const char *progname );
+void endxmlin_initparams(   param *p, const char *progname );
+void isiin_initparams(      param *p, const char *progname );
+void isiout_initparams(     param *p, const char *progname );
+void medin_initparams(      param *p, const char *progname );
+void modsin_initparams(     param *p, const char *progname );
+void modsout_initparams(    param *p, const char *progname );
+void nbibin_initparams(      param *p, const char *progname );
+void risin_initparams(      param *p, const char *progname );
+void risout_initparams(     param *p, const char *progname );
+void wordin_initparams(     param *p, const char *progname );
+void wordout_initparams(    param *p, const char *progname );
+
+#endif
+
diff --git a/lib/bibl.c b/lib/bibl.c
index b5cefdb..903f0fc 100644
--- a/lib/bibl.c
+++ b/lib/bibl.c
@@ -1,7 +1,7 @@
 /*
  * bibl.c
  *
- * Copyright (c) Chris Putnam 2005-2015
+ * Copyright (c) Chris Putnam 2005-2016
  *
  * Source code released under the GPL version 2
  *
@@ -92,7 +92,7 @@ bibl_copy( bibl *bout, bibl *bin )
 			value = fields_value( refin, j, FIELDS_CHRP );
 			level = fields_level( refin, j );
 			if ( tag && value ) {
-				status = fields_add( refout, tag, value, level );
+				status = fields_add_can_dup( refout, tag, value, level );
 				if ( status!=FIELDS_OK ) return 0;
 			}
 		}
diff --git a/lib/bibl.h b/lib/bibl.h
index b1a700b..3f1e6a1 100644
--- a/lib/bibl.h
+++ b/lib/bibl.h
@@ -1,7 +1,7 @@
 /*
  * bibl.h
  *
- * Copyright (c) Chris Putnam 2005-2015
+ * Copyright (c) Chris Putnam 2005-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/lib/biblatexin.c b/lib/biblatexin.c
index 19ac5fd..c02879e 100644
--- a/lib/biblatexin.c
+++ b/lib/biblatexin.c
@@ -1,8 +1,8 @@
 /*
  * biblatexin.c
  *
- * Copyright (c) Chris Putnam 2008-2015
- * Copyright (c) Johannes Wilm 2010-2015
+ * Copyright (c) Chris Putnam 2008-2016
+ * Copyright (c) Johannes Wilm 2010-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -14,14 +14,17 @@
 #include "is_ws.h"
 #include "strsearch.h"
 #include "newstr.h"
+#include "utf8.h"
 #include "newstr_conv.h"
 #include "fields.h"
 #include "list.h"
 #include "name.h"
 #include "reftypes.h"
-#include "biblatexin.h"
+#include "bibformats.h"
+#include "generic.h"
 
-extern const char progname[];
+extern variants biblatex_all[];
+extern int biblatex_nall;
 
 static list find    = { 0, 0, NULL, 0 };
 static list replace = { 0, 0, NULL, 0 };
@@ -30,6 +33,12 @@ static list replace = { 0, 0, NULL, 0 };
  PUBLIC: void biblatexin_initparams()
 *****************************************************/
 
+static int  biblatexin_convertf( fields *bibin, fields *info, int reftype, param *p );
+static int  biblatexin_processf( fields *bibin, char *data, char *filename, long nref, param *p );
+static int  biblatexin_cleanf( bibl *bin, param *p );
+static int  biblatexin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );
+static int  biblatexin_typef( fields *bibin, char *filename, int nrefs, param *p );
+
 void
 biblatexin_initparams( param *p, const char *progname )
 {
@@ -84,7 +93,7 @@ readmore( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line )
  * returns zero if cannot get reference and hit end of-file
  * returns 1 if last reference in file, 2 if reference within file
  */
-int
+static int
 biblatexin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset )
 {
 	int haveref = 0;
@@ -169,7 +178,7 @@ biblatex_tag( char *p, newstr *tag )
 }
 
 static char *
-biblatex_data( char *p, fields *bibin, list *tokens )
+biblatex_data( char *p, fields *bibin, list *tokens, long nref, param *pm )
 {
 	unsigned int nbracket = 0, nquotes = 0;
 	char *startp = p;
@@ -230,10 +239,10 @@ biblatex_data( char *p, fields *bibin, list *tokens )
 	}
 out:
 	if ( nbracket!=0 ) {
-		fprintf( stderr, "%s: Mismatch in number of brackets in reference.\n", progname );
+		fprintf( stderr, "%s: Mismatch in number of brackets in reference %ld\n", pm->progname, nref );
 	}
 	if ( nquotes!=0 ) {
-		fprintf( stderr, "%s: Mismatch in number of quotes in reference.\n", progname );
+		fprintf( stderr, "%s: Mismatch in number of quotes in reference %ld\n", pm->progname, nref );
 	}
 	if ( tok.len ) {
 		s = list_add( tokens, &tok );
@@ -249,7 +258,7 @@ outerr:
  * do string replacement -- only if unprotected by quotation marks or curly brackets
  */
 static void
-replace_strings( list *tokens, fields *bibin )
+replace_strings( list *tokens, fields *bibin, long nref, param *pm )
 {
 	int i, n, ok;
 	newstr *s;
@@ -272,7 +281,7 @@ replace_strings( list *tokens, fields *bibin )
 				if ( !ok ) {
 					fprintf( stderr, "%s: Warning: Non-numeric "
 					   "BibTeX elements should be in quotations or "
-					   "curly brackets in reference.\n", progname );
+					   "curly brackets in reference %ld\n", pm->progname, nref );
 				}
 			}
 		}
@@ -281,7 +290,7 @@ replace_strings( list *tokens, fields *bibin )
 }
 
 static int
-string_concatenate( list *tokens, fields *bibin )
+string_concatenate( list *tokens, fields *bibin, long nref, param *pm )
 {
 	int i, status;
 	newstr *s, *t;
@@ -291,7 +300,7 @@ string_concatenate( list *tokens, fields *bibin )
 		if ( !strcmp( s->data, "#" ) ) {
 			if ( i==0 || i==tokens->n-1 ) {
 				fprintf( stderr, "%s: Warning: Stray string concatenation "
-					"('#' character) in reference\n", progname );
+					"('#' character) in reference %ld\n", pm->progname, nref );
 				status = list_remove( tokens, i );
 				if ( status!=LIST_OK ) return BIBL_ERR_MEMERR;
 				continue;
@@ -299,11 +308,11 @@ string_concatenate( list *tokens, fields *bibin )
 			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 );
+					"be used in context of quotations marks in reference %ld\n", pm->progname, nref );
 			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 );
+					"be used in context of quotations marks in reference %ld\n", pm->progname, nref );
 			if ( ( s->data[s->len-1]=='\"' && t->data[0]=='\"') || (s->data[s->len-1]=='}' && t->data[0]=='{') ) {
 				newstr_trimend( s, 1 );
 				newstr_trimbegin( t, 1 );
@@ -321,7 +330,7 @@ string_concatenate( list *tokens, fields *bibin )
 }
 
 static char *
-process_biblatexline( char *p, newstr *tag, newstr *data, uchar stripquotes )
+process_biblatexline( char *p, newstr *tag, newstr *data, uchar stripquotes, long nref, param *pm )
 {
 	int i, status;
 	list tokens;
@@ -334,11 +343,11 @@ process_biblatexline( char *p, newstr *tag, newstr *data, uchar stripquotes )
 
 	list_init( &tokens );
 
-	if ( *p=='=' ) p = biblatex_data( p+1, NULL, &tokens );
+	if ( *p=='=' ) p = biblatex_data( p+1, NULL, &tokens, nref, pm );
 
-	replace_strings( &tokens, NULL );
+	replace_strings( &tokens, NULL, nref, pm );
 
-	status = string_concatenate( &tokens, NULL );
+	status = string_concatenate( &tokens, NULL, nref, pm );
 	if ( status!=BIBL_OK ) {
 		p = NULL;
 		goto out;
@@ -359,7 +368,7 @@ out:
 }
 
 static int
-process_cite( fields *bibin, char *p, char *filename, long nref )
+process_cite( fields *bibin, char *p, char *filename, long nref, param *pm )
 {
 	int fstatus, status = BIBL_OK;
 	newstr tag, data;
@@ -375,7 +384,7 @@ process_cite( fields *bibin, char *p, char *filename, long nref )
 		if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }
 	}
 	while ( *p ) {
-		p = process_biblatexline( p, &tag, &data, 1 );
+		p = process_biblatexline( p, &tag, &data, 1, nref, pm );
 		if ( !p ) { status = BIBL_ERR_MEMERR; goto out; }
 		/* no anonymous or empty fields allowed */
 		if ( tag.len && data.len ) {
@@ -401,14 +410,14 @@ out:
  *
  */
 static int
-process_string( char *p )
+process_string( char *p, long nref, param *pm )
 {
 	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 );
+	p = process_biblatexline( skip_ws( p ), &s1, &s2, 0, nref, pm );
 	if ( s2.data ) {
 		newstr_findreplace( &s2, "\\ ", " " );
 		if ( newstr_memerr( &s2 ) ) { status = BIBL_ERR_MEMERR; goto out; }
@@ -432,14 +441,14 @@ out:
 	return status;
 }
 
-int
-biblatexin_processf( fields *bibin, char *data, char *filename, long nref )
+static int
+biblatexin_processf( fields *bibin, char *data, char *filename, long nref, param *p )
 {
 	if ( !strncasecmp( data, "@STRING", 7 ) ) {
-		process_string( data+7 );
+		process_string( data+7, nref, p );
 		return 0;
         } else {
-		process_cite( bibin, data, filename, nref );
+		process_cite( bibin, data, filename, nref, p );
 		return 1;
 	}
 }
@@ -769,7 +778,7 @@ biblatexin_cleanref( fields *bibin, param *p )
 	return BIBL_OK;
 }
 
-int
+static int
 biblatexin_cleanf( bibl *bin, param *p )
 {
 	int status;
@@ -786,251 +795,23 @@ biblatexin_cleanf( bibl *bin, param *p )
  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 )
+biblatexin_typef( fields *bibin, char *filename, int nrefs, param *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; }
-	}
+	int ntypename, nrefname, is_default;
+	char *refname = "", *typename="";
 
-	while ( *p && (is_ws(*p) || *p=='-' ) ) p++;
-	if ( *p && is_utf8_emdash( p ) ) p+=3;
-	if ( *p && is_utf8_endash( p ) ) p+=3;
+	ntypename = fields_find( bibin, "INTERNAL_TYPE", LEVEL_MAIN );
+	nrefname  = fields_find( bibin, "REFNUM",        LEVEL_MAIN );
+	if ( nrefname!=-1 )  refname  = fields_value( bibin, nrefname,  FIELDS_CHRP_NOUSE );
+        if ( ntypename!=-1 ) typename = fields_value( bibin, ntypename, FIELDS_CHRP_NOUSE );
 
-	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;
+	return get_reftype( typename, nrefs, p->progname, p->all, p->nall, refname, &is_default, REFTYPE_CHATTY );
 }
 
-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 = FIELDS_OK;
-	/* type in the @thesis is used to distinguish Ph.D. and Master's thesis */
-	if ( !strncasecmp( p, "phdthesis", 9 ) ) {
-		fstatus = fields_replace_or_add( 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 );
-	}
-}
+/*****************************************************
+ PUBLIC: int biblatexin_convertf(), returns BIBL_OK or BIBL_ERR_MEMERR
+*****************************************************/
 
 /* get_title_elements()
  *
@@ -1047,7 +828,7 @@ 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;
+	int nfields, process, level, i;
 	newstr *t, *d;
 	char *newtag;
 
@@ -1065,8 +846,8 @@ get_title_elements( fields *bibin, int currlevel, int reftype, variants *all, in
 		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 ( !translate_oldtag( t->data, reftype, all, nall, &process, &level, &newtag ) )
+			continue;
 		if ( process != TITLE ) continue;
 		if ( level != currlevel ) continue;
 
@@ -1145,14 +926,13 @@ process_separated_title( fields *info, newstr *ttl, newstr *subttl, newstr *ttla
 }
 
 static int
-process_title_all( fields *bibin, fields *info, int reftype, param *p,
-	variants *all, int nall )
+process_title_all( fields *bibin, fields *info, int reftype, param *p )
 {
 	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,
+		found = get_title_elements( bibin, currlevel, reftype, p->all, p->nall,
 				&ttl, &subttl, &ttladdon );
 		if ( !found ) continue;
 		if ( p->nosplittitle )
@@ -1252,6 +1032,141 @@ out:
 	return status;
 }
 
+static int
+biblatexin_bltsubtype( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
+{
+	int fstatus1, fstatus2;
+
+	if ( !strcasecmp( invalue->data, "magazine" ) ) {
+		fstatus1 = fields_add( bibout, "NGENRE", "magazine article", LEVEL_MAIN );
+		fstatus2 = fields_add( bibout, "NGENRE", "magazine",         LEVEL_HOST );
+		if ( fstatus1!=FIELDS_OK || fstatus2!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	}
+
+	else if ( !strcasecmp( invalue->data, "newspaper" ) ) {
+		fstatus1 = fields_add( bibout, "NGENRE", "newspaper article", LEVEL_MAIN );
+		fstatus2 = fields_add( bibout, "GENRE",  "newspaper",         LEVEL_HOST );
+		if ( fstatus1!=FIELDS_OK || fstatus2!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	}
+
+	return BIBL_OK;
+}
+
+/* biblatex drops school field if institution is present */
+static int
+biblatexin_bltschool( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
+{
+	int fstatus;
+	if ( fields_find( bibin, "institution", LEVEL_ANY ) != -1 )
+		return BIBL_OK;
+	else {
+		fstatus = fields_add( bibout, outtag, invalue->data, level );
+		if ( fstatus==FIELDS_OK ) return BIBL_OK;
+		else return BIBL_ERR_MEMERR;
+	}
+}
+
+static int
+biblatexin_bltthesistype( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
+{
+	char *p = invalue->data;
+	int fstatus = FIELDS_OK;
+	/* type in the @thesis is used to distinguish Ph.D. and Master's thesis */
+	if ( !strncasecmp( p, "phdthesis", 9 ) ) {
+		fstatus = fields_replace_or_add( bibout, "NGENRE", "Ph.D. thesis", level );
+	} else if ( !strncasecmp( p, "mastersthesis", 13 ) || !strncasecmp( p, "masterthesis", 12 ) ) {
+		fstatus = fields_replace_or_add( bibout, "NGENRE", "Masters thesis", level );
+	} else if ( !strncasecmp( p, "mathesis", 8 ) ) {
+		fstatus = fields_replace_or_add( bibout, "NGENRE", "Masters thesis", level );
+	} else if ( !strncasecmp( p, "diploma", 7 ) ) {
+		fstatus = fields_replace_or_add( bibout, "NGENRE", "Diploma thesis", level );
+	} else if ( !strncasecmp( p, "habilitation", 12 ) ) {
+		fstatus = fields_replace_or_add( bibout, "NGENRE", "Habilitation thesis", level );
+	}
+	if ( fstatus==FIELDS_OK ) return BIBL_OK;
+	else return BIBL_ERR_MEMERR;
+}
+
+static int
+biblatexin_bteprint( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
+{
+	int neprint, netype, fstatus;
+	char *eprint = NULL, *etype = NULL;
+
+	neprint = fields_find( bibin, "eprint", -1 );
+	netype  = fields_find( bibin, "eprinttype", -1 );
+
+	if ( neprint!=-1 ) eprint = bibin->data[neprint].data;
+	if ( netype!=-1 )  etype =  bibin->data[netype].data;
+
+	if ( eprint && etype ) {
+		if ( !strncasecmp( etype, "arxiv", 5 ) ) {
+			fstatus = fields_add( bibout, "ARXIV", eprint, level );
+			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+		} else if ( !strncasecmp( etype, "jstor", 5 ) ) {
+			fstatus = fields_add( bibout, "JSTOR", eprint, level );
+			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+		} else if ( !strncasecmp( etype, "pubmed", 6 ) ) {
+			fstatus = fields_add( bibout, "PMID", eprint, level );
+			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+		} else if ( !strncasecmp( etype, "medline", 7 ) ) {
+			fstatus = fields_add( bibout, "MEDLINE", eprint, level );
+			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+		} else {
+			fstatus = fields_add( bibout, "EPRINT", eprint, level );
+			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+			fstatus = fields_add( bibout, "EPRINTTYPE", etype, level );
+			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+		}
+		fields_setused( bibin, neprint );
+		fields_setused( bibin, netype );
+	} else if ( eprint ) {
+		fstatus = fields_add( bibout, "EPRINT", eprint, level );
+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+		fields_setused( bibin, neprint );
+	} else if ( etype ) {
+		fstatus = fields_add( bibout, "EPRINTTYPE", etype, level );
+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+		fields_setused( bibin, netype );
+	}
+	return BIBL_OK;
+}
+
+static int
+biblatexin_btgenre( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
+{
+	if ( fields_add( bibout, "NGENRE", invalue->data, level ) == FIELDS_OK ) return BIBL_OK;
+	else return BIBL_ERR_MEMERR;
+}
+
+/* biblatexin_howpublished()
+ *
+ *    howpublished={},
+ *
+ * Normally indicates the manner in which something was
+ * published in lieu of a formal publisher, so typically
+ * 'howpublished' and 'publisher' will never be in the
+ * same reference.
+ *
+ * Occasionally, people put Diploma thesis information
+ * into this field, so check for that first.
+ */
+static int
+biblatexin_howpublished( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
+{
+	int fstatus;
+
+        if ( !strncasecmp( invalue->data, "Diplom", 6 ) )
+                fstatus = fields_replace_or_add( bibout, "NGENRE", "Diploma thesis", level );
+        else if ( !strncasecmp( invalue->data, "Habilitation", 13 ) )
+                fstatus = fields_replace_or_add( bibout, "NGENRE", "Habilitation thesis", level );
+        else
+		fstatus = fields_add( bibout, "PUBLISHER", invalue->data, level );
+
+	if ( fstatus==FIELDS_OK ) return BIBL_OK;
+	else return BIBL_ERR_MEMERR;
+}
+
 /*
  * biblatex has multiple editor fields "editor", "editora", "editorb", "editorc",
  * each of which can be modified from a type of "EDITOR" via "editortype",
@@ -1275,42 +1190,66 @@ out:
  *     "none" (for performer)
  */
 static int
-process_editor( fields *bibin, fields *info, newstr *tag, newstr *value, int level, list *asis, list *corps )
+biblatexin_blteditor( fields *bibin, int m, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
 {
 	char *editor_fields[] = { "editor", "editora", "editorb", "editorc" };
 	char *editor_types[]  = { "editortype", "editoratype", "editorbtype", "editorctype" };
 	int i, n = 0, ntype, neditors = sizeof( editor_fields ) / sizeof( editor_fields[0] );
-	char *type, *outtag = "EDITOR";
+	char *type, *usetag = "EDITOR";
 	for ( i=1; i<neditors; ++i )
-		if ( !strcasecmp( tag->data, editor_fields[i] ) ) n = i;
+		if ( !strcasecmp( intag->data, editor_fields[i] ) ) n = i;
 	ntype = fields_find( bibin, editor_types[n], LEVEL_ANY );
 	if ( ntype!=-1 ) {
 		type = fields_value( bibin, ntype, FIELDS_CHRP_NOUSE );
-		if ( !strcasecmp( type, "collaborator" ) )  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";
+		if ( !strcasecmp( type, "collaborator" ) )  usetag = "COLLABORATOR";
+		else if ( !strcasecmp( type, "compiler" ) ) usetag = "COMPILER";
+		else if ( !strcasecmp( type, "redactor" ) ) usetag = "REDACTOR";
+		else if ( !strcasecmp( type, "director" ) ) usetag = "DIRECTOR";
+		else if ( !strcasecmp( type, "producer" ) ) usetag = "PRODUCER";
+		else if ( !strcasecmp( type, "none" ) )     usetag = "PERFORMER";
 	}
-	return biblatex_names( info, outtag, value, level, asis, corps );
+	return biblatex_names( bibout, usetag, invalue, level, &(pm->asis), &(pm->corps) );
 }
 
 static int
-biblatexin_simple( fields *f, char *tag, char *value, int level )
+biblatexin_person( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
 {
-	int fstatus = fields_add( f, tag, value, level );
-	if ( fstatus==FIELDS_OK ) return BIBL_OK;
-	else return BIBL_ERR_MEMERR;
+	return biblatex_names( bibout, outtag, invalue, level, &(pm->asis), &(pm->corps) );
 }
 
-int
-biblatexin_convertf( fields *bibin, fields *info, int reftype, param *p,
-		variants *all, int nall )
+static void
+biblatexin_notag( param *p, char *tag )
 {
-	int process, level, i, n, nfields, status = BIBL_OK;
-	newstr *t, *d;
-	char *newtag;
+	if ( p->verbose && strcmp( tag, "INTERNAL_TYPE" ) ) {
+		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
+		fprintf( stderr, " Cannot find tag '%s'\n", tag );
+	}
+}
+
+static int
+biblatexin_convertf( fields *bibin, fields *bibout, int reftype, param *p )
+{
+	static int (*convertfns[NUM_REFTYPES])(fields *, int, newstr *, newstr *, int, param *, char *, fields *) = {
+		[ 0 ... NUM_REFTYPES-1 ] = generic_null,
+		[ SIMPLE          ] = generic_simple,
+		[ PAGES           ] = generic_pages,
+		[ NOTES           ] = generic_notes,
+		[ PERSON          ] = biblatexin_person,
+		[ BLT_EDITOR      ] = biblatexin_blteditor,
+		[ HOWPUBLISHED    ] = biblatexin_howpublished,
+		[ URL             ] = generic_url,
+		[ BT_GENRE        ] = biblatexin_btgenre,
+		[ BT_EPRINT       ] = biblatexin_bteprint,
+		[ BLT_THESIS_TYPE ] = biblatexin_bltthesistype,
+		[ BLT_SCHOOL      ] = biblatexin_bltschool,
+		[ BLT_SUBTYPE     ] = biblatexin_bltsubtype,
+		[ BLT_SKIP        ] = generic_skip,
+		[ TITLE           ] = generic_null,    /* delay processing until later */
+	};
+
+	int process, level, i, nfields, status = BIBL_OK;
+	newstr *intag, *invalue;
+	char *outtag;
 
 	nfields = fields_num( bibin );
 	for ( i=0; i<nfields; ++i ) {
@@ -1319,94 +1258,26 @@ biblatexin_convertf( fields *bibin, fields *info, int reftype, param *p,
                 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;
+		intag   = fields_tag  ( bibin, i, FIELDS_STRP_NOUSE );
+		invalue = fields_value( bibin, i, FIELDS_STRP_NOUSE );
+		if ( intag->len == 0 || invalue->len == 0 ) continue;
 
-		n = translate_oldtag( t->data, reftype, all, nall, &process, &level, &newtag );
-		if ( n==-1 ) {
-			biblatexin_notag( p, t->data );
+		if ( !translate_oldtag( intag->data, reftype, p->all, p->nall, &process, &level, &outtag ) ) {
+			biblatexin_notag( p, intag->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;
+		status = convertfns[ process ]( bibin, i, intag, invalue, level, p, outtag, bibout );
+		if ( status!=BIBL_OK ) return status;
 
-		case BLT_SKIP:
-			status = BIBL_OK;
+		if ( convertfns[ process ] != generic_null )
 			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 );
+	status = process_title_all( bibin, bibout, reftype, p );
 
-	if ( status==BIBL_OK && p->verbose ) report( info );
+	if ( status==BIBL_OK && p->verbose ) fields_report( bibout, stdout );
 
 	return status;
 }
diff --git a/lib/biblatexin.h b/lib/biblatexin.h
deleted file mode 100644
index ee9802c..0000000
--- a/lib/biblatexin.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * biblatexin.h
- *
- * Copyright (c) Chris Putnam 2008-2015
- *
- * Source code released under the GPL version 2
- *
- */
-#ifndef BIBLATEXIN_H
-#define BIBLATEXIN_H
-
-#include "newstr.h"
-#include "list.h"
-#include "fields.h"
-#include "bibl.h"
-#include "bibutils.h"
-#include "reftypes.h"
-
-extern int  biblatexin_convertf( fields *bibin, fields *info, int reftype, param *p, variants *all, int nall );
-extern int  biblatexin_processf( fields *bibin, char *data, char *filename, long nref );
-extern int  biblatexin_cleanf( bibl *bin, param *p );
-extern int  biblatexin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );
-extern int  biblatexin_typef( fields *bibin, char *filename, int nrefs,
-        param *p, variants *all, int nall );
-
-extern void biblatexin_initparams( param *p, const char *progname );
-
-extern variants biblatex_all[];
-extern int biblatex_nall;
-
-
-#endif
-
diff --git a/lib/bibtexin.c b/lib/bibtexin.c
index c435f24..769139f 100644
--- a/lib/bibtexin.c
+++ b/lib/bibtexin.c
@@ -1,7 +1,7 @@
 /*
  * bibtexin.c
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -11,24 +11,34 @@
 #include <string.h>
 #include <ctype.h>
 #include "is_ws.h"
-#include "strsearch.h"
 #include "newstr.h"
+#include "utf8.h"
 #include "newstr_conv.h"
 #include "fields.h"
 #include "list.h"
 #include "name.h"
 #include "title.h"
+#include "url.h"
 #include "reftypes.h"
-#include "bibtexin.h"
+#include "bibformats.h"
+#include "generic.h"
 
 static list find    = { 0, 0, NULL, 0 };
 static list replace = { 0, 0, NULL, 0 };
 
-extern const char progname[];
+extern variants bibtex_all[];
+extern int bibtex_nall;
 
 /*****************************************************
  PUBLIC: void bibtexin_initparams()
 *****************************************************/
+
+static int  bibtexin_convertf( fields *bibin, fields *info, int reftype, param *p );
+static int  bibtexin_processf( fields *bibin, char *data, char *filename, long nref, param *p );
+static int  bibtexin_cleanf( bibl *bin, param *p );
+static int  bibtexin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );
+static int  bibtexin_typef( fields *bibin, char *filename, int nrefs, param *p );
+
 void
 bibtexin_initparams( param *p, const char *progname )
 {
@@ -83,7 +93,7 @@ readmore( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line )
  * returns zero if cannot get reference and hit end of-file
  * returns 1 if last reference in file, 2 if reference within file
  */
-int
+static int
 bibtexin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset )
 {
 	int haveref = 0;
@@ -177,7 +187,7 @@ bibtex_tag( char *p, newstr *tag )
 }
 
 static char *
-bibtex_data( char *p, fields *bibin, list *tokens )
+bibtex_data( char *p, fields *bibin, list *tokens, long nref, param *pm )
 {
 	unsigned int nbracket = 0, nquotes = 0;
 	char *startp = p;
@@ -242,10 +252,10 @@ bibtex_data( char *p, fields *bibin, list *tokens )
 	}
 out:
 	if ( nbracket!=0 ) {
-		fprintf( stderr, "%s: Mismatch in number of brackets in reference.\n", progname );
+		fprintf( stderr, "%s: Mismatch in number of brackets in reference %ld.\n", pm->progname, nref );
 	}
 	if ( nquotes!=0 ) {
-		fprintf( stderr, "%s: Mismatch in number of quotes in reference.\n", progname );
+		fprintf( stderr, "%s: Mismatch in number of quotes in reference %ld.\n", pm->progname, nref );
 	}
 	if ( tok.len ) {
 		if ( newstr_memerr( &tok ) ) { p = NULL; goto out; }
@@ -262,7 +272,7 @@ out0:
  * do string replacement -- only if unprotected by quotation marks or curly brackets
  */
 static void
-replace_strings( list *tokens, fields *bibin )
+replace_strings( list *tokens, fields *bibin, param *pm )
 {
 	int i, n, ok;
 	newstr *s;
@@ -285,7 +295,7 @@ replace_strings( list *tokens, fields *bibin )
 				if ( !ok ) {
 					fprintf( stderr, "%s: Warning: Non-numeric "
 					   "BibTeX elements should be in quotations or "
-					   "curly brackets in reference.\n", progname );
+					   "curly brackets in reference.\n", pm->progname );
 				}
 			}
 		}
@@ -294,7 +304,7 @@ replace_strings( list *tokens, fields *bibin )
 }
 
 static int
-string_concatenate( list *tokens, fields *bibin )
+string_concatenate( list *tokens, fields *bibin, long nref, param *pm )
 {
 	newstr *s, *t;
 	int i, status;
@@ -304,7 +314,7 @@ string_concatenate( list *tokens, fields *bibin )
 		if ( !strcmp( s->data, "#" ) ) {
 			if ( i==0 || i==tokens->n-1 ) {
 				fprintf( stderr, "%s: Warning: Stray string concatenation "
-					"('#' character) in reference\n", progname );
+					"('#' character) in reference %ld\n", pm->progname, nref );
 				status = list_remove( tokens, i );
 				if ( status!=LIST_OK ) return BIBL_ERR_MEMERR;
 				continue;
@@ -312,11 +322,11 @@ string_concatenate( list *tokens, fields *bibin )
 			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 );
+					"be used in context of quotations marks in reference %ld\n", pm->progname, nref );
 			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 );
+					"be used in context of quotations marks in reference %ld\n", pm->progname, nref );
 			if ( ( s->data[s->len-1]=='\"' && t->data[0]=='\"') || (s->data[s->len-1]=='}' && t->data[0]=='{') ) {
 				newstr_trimend( s, 1 );
 				newstr_trimbegin( t, 1 );
@@ -335,7 +345,7 @@ string_concatenate( list *tokens, fields *bibin )
 
 /* return NULL on memory error */
 static char *
-process_bibtexline( char *p, newstr *tag, newstr *data, uchar stripquotes, fields *bibin )
+process_bibtexline( char *p, newstr *tag, newstr *data, uchar stripquotes, fields *bibin, long nref, param *pm )
 {
 	int i, status;
 	list tokens;
@@ -349,13 +359,13 @@ process_bibtexline( char *p, newstr *tag, newstr *data, uchar stripquotes, field
 	list_init( &tokens );
 
 	if ( *p=='=' ) {
-		p = bibtex_data( p+1, bibin, &tokens );
+		p = bibtex_data( p+1, bibin, &tokens, nref, pm );
 		if ( p==NULL ) goto out;
 	}
 
-	replace_strings( &tokens, bibin );
+	replace_strings( &tokens, bibin, pm );
 
-	status = string_concatenate( &tokens, bibin );
+	status = string_concatenate( &tokens, bibin, nref, pm );
 	if ( status!=BIBL_OK ) {
 		p = NULL;
 		goto out;
@@ -379,7 +389,7 @@ out:
  *
  */
 static int
-process_cite( fields *bibin, char *p, char *filename, long nref )
+process_cite( fields *bibin, char *p, char *filename, long nref, param *pm )
 {
 	int fstatus, status = BIBL_OK;
 	newstr tag, data;
@@ -399,7 +409,7 @@ process_cite( fields *bibin, char *p, char *filename, long nref )
 	}
 
 	while ( *p ) {
-		p = process_bibtexline( p, &tag, &data, 1, bibin );
+		p = process_bibtexline( p, &tag, &data, 1, bibin, nref, pm );
 		if ( p==NULL ) { status = BIBL_ERR_MEMERR; goto out; }
 		/* no anonymous or empty fields allowed */
 		if ( tag.len && data.len ) {
@@ -425,14 +435,14 @@ out:
  *
  */
 static int
-process_string( char *p )
+process_string( char *p, long nref, param *pm )
 {
 	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 );
+	p = process_bibtexline( skip_ws( p ), &s1, &s2, 0, NULL, nref, pm );
 	if ( p==NULL ) { status = BIBL_ERR_MEMERR; goto out; }
 	if ( s2.data ) {
 		newstr_findreplace( &s2, "\\ ", " " );
@@ -460,17 +470,17 @@ out:
  *
  * Handle '@STRING', '@reftype', and ignore '@COMMENT'
  */
-int
-bibtexin_processf( fields *bibin, char *data, char *filename, long nref )
+static int
+bibtexin_processf( fields *bibin, char *data, char *filename, long nref, param *p )
 {
 	if ( !strncasecmp( data, "@STRING", 7 ) ) {
-		process_string( data+7 );
+		process_string( data+7, nref, p );
 		return 0;
 	} else if ( !strncasecmp( data, "@COMMENT", 8 ) ) {
 		/* Not sure if these are real Bibtex, but not references */
 		return 0;
 	} else {
-		process_cite( bibin, data, filename, nref );
+		process_cite( bibin, data, filename, nref, p );
 		return 1;
 	}
 }
@@ -716,7 +726,7 @@ 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 );
+		n = fields_find( bin->ref[i], "refnum", LEVEL_ANY );
 		if ( n==-1 ) continue;
 		if ( !strcmp( bin->ref[i]->data[n].data, citekey ) ) return i;
 	}
@@ -726,7 +736,7 @@ bibtexin_findref( bibl *bin, char *citekey )
 static void
 bibtexin_nocrossref( bibl *bin, long i, int n, param *p )
 {
-	int n1 = fields_find( bin->ref[i], "REFNUM", -1 );
+	int n1 = fields_find( bin->ref[i], "REFNUM", LEVEL_ANY );
 	if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
 	fprintf( stderr, "Cannot find cross-reference '%s'",
 			bin->ref[i]->data[n].data );
@@ -741,7 +751,7 @@ 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 );
+	ntype = fields_find( bibref, "INTERNAL_TYPE", LEVEL_ANY );
 	type = ( char * ) fields_value( bibref, ntype, FIELDS_CHRP_NOUSE );
 
 	n = fields_num( bibcross );
@@ -774,7 +784,7 @@ bibtexin_crossref( bibl *bin, param *p )
 
 	for ( i=0; i<bin->nrefs; ++i ) {
 		bibref = bin->ref[i];
-		n = fields_find( bibref, "CROSSREF", -1 );
+		n = fields_find( bibref, "CROSSREF", LEVEL_ANY );
 		if ( n==-1 ) continue;
 		fields_setused( bibref, n );
 		ncross = bibtexin_findref( bin, (char*) fields_value( bibref, n, FIELDS_CHRP ) );
@@ -790,7 +800,7 @@ out:
 	return status;
 }
 
-int
+static int
 bibtexin_cleanf( bibl *bin, param *p )
 {
 	int status = BIBL_OK;
@@ -806,23 +816,18 @@ bibtexin_cleanf( bibl *bin, param *p )
  PUBLIC: int bibtexin_typef()
 *****************************************************/
 
-int
-bibtexin_typef( fields *bibin, char *filename, int nrefs, param *p,
-		variants *all, int nall )
+static int
+bibtexin_typef( fields *bibin, char *filename, int nrefs, param *p )
 {
-	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;
+	int ntypename, nrefname, is_default;
+	char *refname = "", *typename = "";
+
+	ntypename = fields_find( bibin, "INTERNAL_TYPE", LEVEL_MAIN );
+	nrefname  = fields_find( bibin, "REFNUM",        LEVEL_MAIN );
+	if ( nrefname!=-1 )  refname  = fields_value( bibin, nrefname,  FIELDS_CHRP_NOUSE );
+	if ( ntypename!=-1 ) typename = fields_value( bibin, ntypename, FIELDS_CHRP_NOUSE );
+
+	return get_reftype( typename, nrefs, p->progname, p->all, p->nall, refname, &is_default, REFTYPE_CHATTY );
 }
 
 /*****************************************************
@@ -830,7 +835,7 @@ bibtexin_typef( fields *bibin, char *filename, int nrefs, param *p,
 *****************************************************/
 
 static int
-bibtex_matches_list( fields *info, char *tag, char *suffix, newstr *data, int level,
+bibtex_matches_list( fields *bibout, char *tag, char *suffix, newstr *data, int level,
 		list *names, int *match )
 {
 	int i, fstatus, status = BIBL_OK;
@@ -845,7 +850,7 @@ bibtex_matches_list( fields *info, char *tag, char *suffix, newstr *data, int le
 		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 );
+		fstatus = fields_add( bibout, newtag.data, data->data, level );
 		if ( fstatus!=FIELDS_OK ) {
 			status = BIBL_ERR_MEMERR;
 			goto out;
@@ -859,250 +864,53 @@ out:
 	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;
-}
+/**** bibtexin_btorg ****/
 
-/* 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)
+/*
+ * 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
-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 )
+bibtexin_btorg( fields *bibin, int m, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
 {
-	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 );
+	int n, fstatus;
+	n = fields_find( bibin, "publisher", LEVEL_ANY );
+	if ( n==-1 )
+		fstatus = fields_add( bibout, "PUBLISHER", invalue->data, level );
 	else
-		fstatus = fields_add( info, default_tag, p, level );
+		fstatus = fields_add( bibout, "ORGANIZER:CORP", invalue->data, 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;
-}
+/**** bibtexin_btsente() ****/
 
 /*
  * sentelink = {file://localhost/full/path/to/file.pdf,Sente,PDF}
+ *
+ * Sente is an academic reference manager for MacOSX and Apple iPad.
  */
+
 static int
-process_sente( fields *info, newstr *d, int level )
+bibtexin_btsente( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
 {
 	int fstatus, status = BIBL_OK;
 	newstr link;
 
 	newstr_init( &link );
-	newstr_cpytodelim( &link, skip_ws( d->data ), ",", 0 );
+	newstr_cpytodelim( &link, skip_ws( invalue->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 );
+		fstatus = fields_add( bibout, "FILEATTACH", link.data, level );
 		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;
 	}
 
@@ -1110,28 +918,7 @@ process_sente( fields *info, newstr *d, int level )
 	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;
-}
+/**** bibtexin_linkedfile() ****/
 
 static int
 count_colons( char *p )
@@ -1164,10 +951,10 @@ last_colon( char *p )
  * file={Description:/full/path/to/file.pdf:PDF}
  */
 static int
-process_file( fields *info, newstr *d, int level )
+bibtexin_linkedfile( fields *bibin, int m, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
 {
 	int fstatus, status = BIBL_OK;
-	char *p = d->data;
+	char *p = invalue->data;
 	int i, n, n1, n2;
 	newstr link;
 
@@ -1188,42 +975,243 @@ process_file( fields *info, newstr *d, int level )
 			goto out;
 		}
 		if ( link.len ) {
-			fstatus = fields_add( info, "FILEATTACH", link.data, level );
+			fstatus = fields_add( bibout, "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 );
+		fstatus = fields_add( bibout, "FILEATTACH", p, level );
 		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;
 	}
 	return status;
+
 }
 
+/**** bibtexin_howpublished() ****/
+
+/*    howpublished={},
+ *
+ * Normally indicates the manner in which something was
+ * published in lieu of a formal publisher, so typically
+ * 'howpublished' and 'publisher' will never be in the
+ * same reference.
+ *
+ * Occassionally, people put Diploma thesis information
+ * into the field, so check that first.
+ *
+ * Returns BIBL_OK or BIBL_ERR_MEMERR
+ */
+
 static int
-process_note( fields *info, newstr *d, int level )
+bibtexin_howpublished( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
 {
 	int fstatus, status = BIBL_OK;
-	if ( !strncasecmp( d->data, "http:", 5 ) ||
-	     !strncasecmp( d->data, "arXiv:", 6 ) ) {
-		status = process_url( info, d, level );
+	if ( !strncasecmp( invalue->data, "Diplom", 6 ) ) {
+		fstatus = fields_replace_or_add( bibout, "GENRE", "Diploma thesis", level );
+		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;
+	} else if ( !strncasecmp( invalue->data, "Habilitation", 13 ) ) {
+		fstatus = fields_replace_or_add( bibout, "GENRE", "Habilitation thesis", level );
+		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;
+	} else if ( is_embedded_link( invalue->data ) ) {
+		status =  urls_split_and_add( invalue->data, bibout, level );
 	} else {
-		fstatus = fields_add( info, "NOTES", d->data, level );
-		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+		fstatus = fields_add( bibout, "PUBLISHER", invalue->data, level );
+		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;
 	}
 	return status;
 }
 
-static void
-bibtexin_notag( param *p, char *tag )
+/**** bibtexin_eprint() ****/
+
+/* Try to capture situations like
+ *
+ * eprint="1605.02026",
+ * archivePrefix="arXiv",
+ *
+ * or
+ *
+ * eprint="13211131",
+ * eprinttype="medline",
+ *
+ * If we don't know anything, concatenate archivePrefix:eprint
+ * and push into URL. (Could be wrong)
+ *
+ * If no info, just push eprint into URL. (Could be wrong)
+ */
+static int
+process_eprint_with_prefix( fields *bibout, char *prefix, newstr *value, int level )
 {
-	if ( p->verbose && strcmp( tag, "INTERNAL_TYPE" ) ) {
-		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
-		fprintf( stderr, "Cannot find tag '%s'\n", tag );
+	int fstatus, status = BIBL_OK;
+	newstr merge;
+
+	if ( !strcmp( prefix, "arXiv" ) ) {
+		fstatus = fields_add( bibout, "ARXIV", value->data, level );
+		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;
+	}
+
+	else if ( !strcmp( prefix, "jstor" ) ) {
+		fstatus = fields_add( bibout, "JSTOR", value->data, level );
+		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;
+	}
+
+	else if ( !strcmp( prefix, "medline" ) ) {
+		fstatus = fields_add( bibout, "MEDLINE", value->data, level );
+		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;
+	}
+
+	else if ( !strcmp( prefix, "pubmed" ) ) {
+		fstatus = fields_add( bibout, "PMID", value->data, level );
+		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;
+	}
+
+	/* ...if this is unknown prefix, merge prefix & eprint */
+	else {
+		newstr_init( &merge );
+		newstr_mergestrs( &merge, prefix, ":", value->data, NULL );
+		fstatus = fields_add( bibout, "URL", merge.data, level );
+		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;
+		newstr_free( &merge );
+	}
+
+	return status;
+}
+static int
+process_eprint_without_prefix( fields *bibout, newstr *value, int level )
+{
+	int fstatus;
+
+	/* ...no archivePrefix, need to handle just 'eprint' tag */
+	fstatus = fields_add( bibout, "URL", value->data, level );
+
+	if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	else return BIBL_OK;
+}
+
+static int
+bibtexin_eprint( fields *bibin, int m, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
+{
+	char *prefix;
+	int n;
+
+	/* ...do we have an archivePrefix too? */
+	n = fields_find( bibin, "ARCHIVEPREFIX", level );
+	if ( n==-1 ) n = fields_find( bibin, "EPRINTTYPE", level );
+	if ( n!=-1 ) {
+		prefix = fields_value( bibin, n, FIELDS_CHRP );
+		return process_eprint_with_prefix( bibout, prefix, invalue, level );
+	}
+
+	/* ...no we don't */
+	return process_eprint_without_prefix( bibout, invalue, level );
+}
+
+/**** bibtexin_keyword() ****/
+
+/* Split keywords="" with semicolons.
+ * Commas are also frequently used, but will break
+ * entries like:
+ *       keywords="Microscopy, Confocal"
+ * Returns BIBL_OK or BIBL_ERR_MEMERR
+ */
+
+static int
+bibtexin_keyword( fields *bibin, int m, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
+{
+	int fstatus, status = BIBL_OK;
+	newstr keyword;
+	char *p;
+
+	p = invalue->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( bibout, "KEYWORD", keyword.data, level );
+			if ( fstatus!=FIELDS_OK ) {
+				status = BIBL_ERR_MEMERR;
+				goto out;
+			}
+		}
+	}
+out:
+	newstr_free( &keyword );
+	return status;
+}
+
+/*
+ * bibtex_names( bibout, newtag, field, level);
+ *
+ * split names in author list separated by and's (use '|' character)
+ * and add names
+ *
+ * returns BIBL_OK on success, BIBL_ERR_MEMERR on memory error
+ */
+
+static int
+bibtexin_person( fields *bibin, int m, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
+{
+	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( bibout, outtag, ":ASIS", invalue, level, &(pm->asis), &match );
+	if ( match==1 || status!=BIBL_OK ) return status;
+	status = bibtex_matches_list( bibout, outtag, ":CORP", invalue, level, &(pm->corps), &match );
+	if ( match==1 || status!=BIBL_OK ) return status;
+
+	list_init( &tokens );
+
+	bibtex_split( &tokens, invalue );
+	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( bibout, outtag, list_getc( &tokens, begin ), level, 0 );
+			if ( !ok ) { status = BIBL_ERR_MEMERR; goto out; }
+		} else {
+			ok = name_addmultielement( bibout, outtag, &tokens, begin, end, level );
+			if ( !ok ) { status = BIBL_ERR_MEMERR; goto out; }
+		}
+
+		begin = end + 1;
+
+		/* Handle repeated 'and' errors: authors="G. F. Author and and B. K. Author" */
+		while ( begin < n && !strcasecmp( list_getc( &tokens, begin ), "and" ) )
+			begin++;
+	}
+
+	if ( etal ) {
+		ok = name_addsingleelement( bibout, outtag, "et al.", level, 0 );
+		if ( !ok ) status = BIBL_ERR_MEMERR;
 	}
+
+out:
+	list_free( &tokens );
+	return status;
+
 }
 
+/**** bibtexin_title() ****/
+
 /* bibtexin_titleinbook_isbooktitle()
  *
  * Normally, the title field of inbook refers to the book.  The
@@ -1251,7 +1239,7 @@ bibtexin_notag( param *p, char *tag )
  *
  */
 static int
-bibtexin_titleinbook_isbooktitle( char *intag, fields *bibin )
+bibtexin_titleinbook_isbooktitle( fields *bibin, char *intag )
 {
 	int n;
 
@@ -1259,117 +1247,79 @@ bibtexin_titleinbook_isbooktitle( char *intag, fields *bibin )
 	if ( strcasecmp( intag, "TITLE" ) ) return 0;
 
 	/* ...look only at '@inbook' references */
-	n = fields_find( bibin, "INTERNAL_TYPE", -1 );
+	n = fields_find( bibin, "INTERNAL_TYPE", LEVEL_ANY );
 	if ( n==-1 ) return 0;
 	if ( strcasecmp( fields_value( bibin, n, FIELDS_CHRP ), "INBOOK" ) ) return 0;
 
 	/* ...look to see if 'booktitle="yyy"' exists */
-	n = fields_find( bibin, "BOOKTITLE", -1 );
+	n = fields_find( bibin, "BOOKTITLE", LEVEL_ANY );
 	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 )
+bibtexin_title( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
 {
-	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 ( bibtexin_titleinbook_isbooktitle( bibin, intag->data ) ) level=LEVEL_MAIN;
+	ok = title_process( bibout, "TITLE", invalue->data, level, pm->nosplittitle );
 	if ( ok ) return BIBL_OK;
 	else return BIBL_ERR_MEMERR;
 }
 
-static int
-bibtex_simple( fields *info, char *outtag, newstr *d, int level )
+static void
+bibtexin_notag( param *p, char *tag )
 {
-	int fstatus;
-	fstatus = fields_add( info, outtag, d->data, level );
-	if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
-	return BIBL_OK;
+	if ( p->verbose && strcmp( tag, "INTERNAL_TYPE" ) ) {
+		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
+		fprintf( stderr, "Cannot find tag '%s'\n", tag );
+	}
 }
 
-int
-bibtexin_convertf( fields *bibin, fields *info, int reftype, param *p,
-		variants *all, int nall )
+static int
+bibtexin_convertf( fields *bibin, fields *bibout, int reftype, param *p )
 {
-	int process, level, i, n, nfields, status;
-	newstr *t, *d;
+	static int (*convertfns[NUM_REFTYPES])(fields *, int, newstr *, newstr *, int, param *, char *, fields *) = {
+		[ 0 ... NUM_REFTYPES-1 ] = generic_null,
+		[ SIMPLE       ] = generic_simple,
+		[ TITLE        ] = bibtexin_title,
+		[ PERSON       ] = bibtexin_person,
+		[ PAGES        ] = generic_pages,
+		[ KEYWORD      ] = bibtexin_keyword,
+		[ EPRINT       ] = bibtexin_eprint,
+		[ HOWPUBLISHED ] = bibtexin_howpublished,
+		[ LINKEDFILE   ] = bibtexin_linkedfile,
+		[ NOTES        ] = generic_notes,
+		[ BT_SENTE     ] = bibtexin_btsente,
+		[ BT_ORG       ] = bibtexin_btorg,
+		[ URL          ] = generic_url
+	};
+
+	int process, level, i, nfields, status = BIBL_OK;
+	newstr *intag, *invalue;
 	char *outtag;
 
 	nfields = fields_num( bibin );
 	for ( i=0; i<nfields; ++i ) {
 
-		if ( fields_used( bibin, i ) ) continue; /* e.g. successful crossref */
+		if ( fields_used( bibin, i ) )   continue; /* e.g. successful crossref */
+		if ( fields_notag( bibin, i ) )  continue;
 		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;
+		intag   = fields_tag( bibin, i, FIELDS_STRP );
+		invalue = fields_value( bibin, i, FIELDS_STRP );
 
-		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 ( !translate_oldtag( intag->data, reftype, p->all, p->nall, &process, &level, &outtag ) ) {
+			bibtexin_notag( p, intag->data );
+			continue;
 		}
 
+		status = convertfns[ process ] ( bibin, i, intag, invalue, level, p, outtag, bibout );
 		if ( status!=BIBL_OK ) return status;
 	}
+
+	if ( status==BIBL_OK && p->verbose ) fields_report( bibout, stderr );
+
 	return status;
 }
-
diff --git a/lib/bibtexin.h b/lib/bibtexin.h
deleted file mode 100644
index 727496e..0000000
--- a/lib/bibtexin.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * bibtexin.h
- *
- * Copyright (c) Chris Putnam 2003-2015
- *
- * Source code released under the GPL version 2
- *
- */
-#ifndef BIBTEXIN_H
-#define BIBTEXIN_H
-
-#include "newstr.h"
-#include "list.h"
-#include "fields.h"
-#include "bibl.h"
-#include "bibutils.h"
-#include "reftypes.h"
-
-extern int  bibtexin_convertf( fields *bibin, fields *info, int reftype, param *p, variants *all, int nall );
-extern int  bibtexin_processf( fields *bibin, char *data, char *filename, long nref );
-extern int  bibtexin_cleanf( bibl *bin, param *p );
-extern int  bibtexin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );
-extern int  bibtexin_typef( fields *bibin, char *filename, int nrefs,
-        param *p, variants *all, int nall );
-extern void bibtexin_initparams( param *p, const char *progname );
-
-
-extern variants bibtex_all[];
-extern int bibtex_nall;
-
-
-#endif
-
diff --git a/lib/bibtexout.c b/lib/bibtexout.c
index 6cfd432..41d9257 100644
--- a/lib/bibtexout.c
+++ b/lib/bibtexout.c
@@ -1,7 +1,7 @@
 /*
  * bibtexout.c
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -16,9 +16,12 @@
 #include "xml.h"
 #include "fields.h"
 #include "name.h"
-#include "bibl.h"
-#include "doi.h"
-#include "bibtexout.h"
+#include "title.h"
+#include "url.h"
+#include "bibformats.h"
+
+static int  bibtexout_write( fields *in, FILE *fp, param *p, unsigned long refnum );
+static void bibtexout_writeheader( FILE *outptr, param *p );
 
 void
 bibtexout_initparams( param *p, const char *progname )
@@ -59,44 +62,22 @@ enum {
 	TYPE_MANUAL,
 	TYPE_UNPUBLISHED,
 	TYPE_ELECTRONIC,
-	TYPE_MISC
+	TYPE_MISC,
+	NUM_TYPES
 };
 
-static void
-output_citekey( FILE *fp, fields *info, unsigned long refnum, int format_opts )
-{
-	int n = fields_find( info, "REFNUM", -1 );
-	char *p;
-	if ( n!=-1 ) {
-		p = info->data[n].data;
-		while ( p && *p && *p!='|' ) {
-			if ( format_opts & BIBOUT_STRICTKEY ) {
-				if ( isdigit((unsigned char)*p) || (*p>='A' && *p<='Z') ||
-				     (*p>='a' && *p<='z' ) )
-					fprintf( fp, "%c", *p );
-			}
-			else {
-				if ( *p!=' ' && *p!='\t' ) {
-					fprintf( fp, "%c", *p );
-				}
-			}
-			p++;
-		}
-	}
-}
-
 static int
-bibtexout_type( fields *info, char *filename, int refnum, param *p )
+bibtexout_type( fields *in, char *filename, int refnum, param *p )
 {
-	char *genre;
 	int type = TYPE_UNKNOWN, i, maxlevel, n, level;
+	char *tag, *genre;
 
 	/* determine bibliography type */
-	for ( i=0; i<info->n; ++i ) {
-		if ( strcasecmp( info->tag[i].data, "GENRE" ) &&
-		     strcasecmp( info->tag[i].data, "NGENRE" ) ) continue;
-		genre = info->data[i].data;
-		level = info->level[i];
+	for ( i=0; i<in->n; ++i ) {
+		tag = fields_tag( in, i, FIELDS_CHRP );
+		if ( strcasecmp( tag, "GENRE" ) && strcasecmp( tag, "NGENRE" ) ) continue;
+		genre = fields_value( in, i, FIELDS_CHRP );
+		level = in->level[i];
 		if ( !strcasecmp( genre, "periodical" ) ||
 		     !strcasecmp( genre, "academic journal" ) ||
 		     !strcasecmp( genre, "magazine" ) ||
@@ -115,9 +96,11 @@ bibtexout_type( fields *info, char *filename, int refnum, param *p )
 			else type = TYPE_INCOLLECTION;
 		} else if ( !strcasecmp( genre, "report" ) )
 			type = TYPE_REPORT;
+		else if ( !strcasecmp( genre, "book chapter" ) )
+			type = TYPE_INBOOK;
 		else if ( !strcasecmp( genre, "book" ) ) {
-			if ( level==0 ) type=TYPE_BOOK;
-			else type=TYPE_INBOOK;
+			if ( level==0 ) type = TYPE_BOOK;
+			else type = TYPE_INBOOK;
 		} else if ( !strcasecmp( genre, "thesis" ) ) {
 			if ( type==TYPE_UNKNOWN ) type=TYPE_PHDTHESIS;
 		} else if ( !strcasecmp( genre, "Ph.D. thesis" ) )
@@ -128,26 +111,27 @@ bibtexout_type( fields *info, char *filename, int refnum, param *p )
 			type = TYPE_ELECTRONIC;
 	}
 	if ( type==TYPE_UNKNOWN ) {
-		for ( i=0; i<info->n; ++i ) {
-			if ( strcasecmp( info->tag[i].data, "ISSUANCE" ) ) continue;
-			if ( !strcasecmp( info->data[i].data, "monographic" ) ) {
-				if ( info->level[i]==0 ) type = TYPE_BOOK;
-				else if ( info->level[i]==1 ) type=TYPE_INBOOK;
+		for ( i=0; i<in->n; ++i ) {
+			tag = fields_tag( in, i, FIELDS_CHRP );
+			if ( strcasecmp( tag, "ISSUANCE" ) ) continue;
+			genre = fields_value( in, i, FIELDS_CHRP );
+			if ( !strcasecmp( genre, "monographic" ) ) {
+				if ( in->level[i]==0 ) type = TYPE_BOOK;
+				else if ( in->level[i]==1 ) type = TYPE_MISC;
 			}
 		}
 	}
 
-	/* default to BOOK type */
+	/* default to TYPE_MISC */
 	if ( type==TYPE_UNKNOWN ) {
-		maxlevel = fields_maxlevel( info );
-		if ( maxlevel > 0 ) type = TYPE_INBOOK;
+		maxlevel = fields_maxlevel( in );
+		if ( maxlevel > 0 ) type = TYPE_MISC;
 		else {
 			if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
-			fprintf( stderr, "Cannot identify TYPE "
-				"in reference %d ", refnum+1 );
-			n = fields_find( info, "REFNUM", -1 );
+			fprintf( stderr, "Cannot identify TYPE in reference %d ", refnum+1 );
+			n = fields_find( in, "REFNUM", LEVEL_ANY );
 			if ( n!=-1 ) 
-				fprintf( stderr, " %s", info->data[n].data);
+				fprintf( stderr, " %s", (char*) fields_value( in, n, FIELDS_CHRP ) );
 			fprintf( stderr, " (defaulting to @Misc)\n" );
 			type = TYPE_MISC;
 		}
@@ -156,163 +140,234 @@ bibtexout_type( fields *info, char *filename, int refnum, param *p )
 }
 
 static void
-output_type( FILE *fp, int type, int format_opts )
+output( FILE *fp, fields *out, int format_opts )
 {
-	typedef struct {
-		int bib_type;
-		char *type_name;
-	} typenames;
-
-	typenames types[] = {
-		{ TYPE_ARTICLE, "Article" },
-		{ TYPE_INBOOK, "Inbook" },
-		{ TYPE_PROCEEDINGS, "Proceedings" },
-		{ TYPE_INPROCEEDINGS, "InProceedings" },
-		{ TYPE_BOOK, "Book" },
-		{ TYPE_PHDTHESIS, "PhdThesis" },
-		{ TYPE_MASTERSTHESIS, "MastersThesis" },
-		{ TYPE_REPORT, "TechReport" },
-		{ TYPE_MANUAL, "Manual" },
-		{ TYPE_COLLECTION, "Collection" },
-		{ TYPE_INCOLLECTION, "InCollection" },
-		{ TYPE_UNPUBLISHED, "Unpublished" },
-		{ TYPE_ELECTRONIC, "Electronic" },
-		{ TYPE_MISC, "Misc" } };
-	int i, len, ntypes = sizeof( types ) / sizeof( types[0] );
-	char *s = NULL;
-	for ( i=0; i<ntypes; ++i ) {
-		if ( types[i].bib_type == type ) {
-			s = types[i].type_name;
-			break;
-		}
-	}
-	if ( !s ) s = types[ntypes-1].type_name; /* default to TYPE_MISC */
-	if ( !(format_opts & BIBOUT_UPPERCASE ) ) fprintf( fp, "@%s{", s );
+	int i, j, len, nquotes;
+	char *tag, *value, ch;
+
+	/* ...output type information "@article{" */
+	value = ( char * ) fields_value( out, 0, FIELDS_CHRP );
+	if ( !(format_opts & BIBL_FORMAT_BIBOUT_UPPERCASE) ) fprintf( fp, "@%s{", value );
 	else {
-		len = strlen( s );
+		len = strlen( value );
 		fprintf( fp, "@" );
 		for ( i=0; i<len; ++i )
-			fprintf( fp, "%c", toupper((unsigned char)s[i]) );
+			fprintf( fp, "%c", toupper((unsigned char)value[i]) );
 		fprintf( fp, "{" );
 	}
-}
 
-static void
-output_element( FILE *fp, char *tag, char *data, int format_opts )
-{
-	int i, len, nquotes = 0;
-	char ch;
-	fprintf( fp, ",\n" );
-	if ( format_opts & BIBOUT_WHITESPACE ) fprintf( fp, "  " );
-	if ( !(format_opts & BIBOUT_UPPERCASE ) ) fprintf( fp, "%s", tag );
-	else {
-		len = strlen( tag );
-		for ( i=0; i<len; ++i )
-			fprintf( fp, "%c", toupper((unsigned char)tag[i]) );
-	}
-	if ( format_opts & BIBOUT_WHITESPACE ) fprintf( fp, " = \t" );
-	else fprintf( fp, "=" );
+	/* ...output refnum "Smith2001" */
+	value = ( char * ) fields_value( out, 1, FIELDS_CHRP );
+	fprintf( fp, "%s", value );
 
-	if ( format_opts & BIBOUT_BRACKETS ) fprintf( fp, "{" );
-	else fprintf( fp, "\"" );
-
-	len = strlen( data );
-	for ( i=0; i<len; ++i ) {
-		ch = data[i];
-		if ( ch!='\"' ) fprintf( fp, "%c", ch );
+	/* ...rest of the references */
+	for ( j=2; j<out->n; ++j ) {
+		nquotes = 0;
+		tag   = ( char * ) fields_tag( out, j, FIELDS_CHRP );
+		value = ( char * ) fields_value( out, j, FIELDS_CHRP );
+		fprintf( fp, ",\n" );
+		if ( format_opts & BIBL_FORMAT_BIBOUT_WHITESPACE ) fprintf( fp, "  " );
+		if ( !(format_opts & BIBL_FORMAT_BIBOUT_UPPERCASE ) ) fprintf( fp, "%s", tag );
 		else {
-			if ( format_opts & BIBOUT_BRACKETS || 
-			    ( i>0 && data[i-1]=='\\' ) )
-				fprintf( fp, "\"" );
+			len = strlen( tag );
+			for ( i=0; i<len; ++i )
+				fprintf( fp, "%c", toupper((unsigned char)tag[i]) );
+		}
+		if ( format_opts & BIBL_FORMAT_BIBOUT_WHITESPACE ) fprintf( fp, " = \t" );
+		else fprintf( fp, "=" );
+
+		if ( format_opts & BIBL_FORMAT_BIBOUT_BRACKETS ) fprintf( fp, "{" );
+		else fprintf( fp, "\"" );
+
+		len = strlen( value );
+		for ( i=0; i<len; ++i ) {
+			ch = value[i];
+			if ( ch!='\"' ) fprintf( fp, "%c", ch );
 			else {
-				if ( nquotes % 2 == 0 )
-					fprintf( fp, "``" );
-				else    fprintf( fp, "\'\'" );
-				nquotes++;
+				if ( format_opts & BIBL_FORMAT_BIBOUT_BRACKETS || ( i>0 && value[i-1]=='\\' ) )
+					fprintf( fp, "\"" );
+				else {
+					if ( nquotes % 2 == 0 )
+						fprintf( fp, "``" );
+					else    fprintf( fp, "\'\'" );
+					nquotes++;
+				}
 			}
 		}
+
+		if ( format_opts & BIBL_FORMAT_BIBOUT_BRACKETS ) fprintf( fp, "}" );
+		else fprintf( fp, "\"" );
 	}
 
-	if ( format_opts & BIBOUT_BRACKETS ) fprintf( fp, "}" );
-	else fprintf( fp, "\"" );
+	/* ...finish reference */
+	if ( format_opts & BIBL_FORMAT_BIBOUT_FINALCOMMA ) fprintf( fp, "," );
+	fprintf( fp, "\n}\n\n" );
+
+	fflush( fp );
 }
 
 static void
-output_and_use( FILE *fp, fields *info, int n, char *outtag, int format_opts )
+append_type( int type, fields *out, int *status )
 {
-	output_element( fp, outtag, info->data[n].data, format_opts );
-	fields_setused( info, n );
+	char *typenames[ NUM_TYPES ] = {
+		[ TYPE_ARTICLE       ] = "Article",
+		[ TYPE_INBOOK        ] = "Inbook",
+		[ TYPE_PROCEEDINGS   ] = "Proceedings",
+		[ TYPE_INPROCEEDINGS ] = "InProceedings",
+		[ TYPE_BOOK          ] = "Book",
+		[ TYPE_PHDTHESIS     ] = "PhdThesis",
+		[ TYPE_MASTERSTHESIS ] = "MastersThesis",
+		[ TYPE_REPORT        ] = "TechReport",
+		[ TYPE_MANUAL        ] = "Manual",
+		[ TYPE_COLLECTION    ] = "Collection",
+		[ TYPE_INCOLLECTION  ] = "InCollection",
+		[ TYPE_UNPUBLISHED   ] = "Unpublished",
+		[ TYPE_ELECTRONIC    ] = "Electronic",
+		[ TYPE_MISC          ] = "Misc",
+	};
+	int fstatus;
+	char *s;
+
+	if ( type < 0 || type >= NUM_TYPES ) type = TYPE_MISC;
+	s = typenames[ type ];
+
+	fstatus = fields_add( out, "TYPE", s, LEVEL_MAIN );
+	if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 }
 
 static void
-output_simple( FILE *fp, fields *info, char *intag, char *outtag, 
-		int format_opts )
+append_citekey( fields *in, fields *out, int format_opts, int *status )
 {
-	int n = fields_find( info, intag, -1 );
+	int n, fstatus;
+	newstr s;
+	char *p;
+
+	n = fields_find( in, "REFNUM", LEVEL_ANY );
+	if ( ( format_opts & BIBL_FORMAT_BIBOUT_DROPKEY ) || n==-1 ) {
+		fstatus = fields_add( out, "REFNUM", "", LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
+
+	else {
+		newstr_init( &s );
+		p = fields_value( in, n, FIELDS_CHRP );
+		while ( p && *p && *p!='|' ) {
+			if ( format_opts & BIBL_FORMAT_BIBOUT_STRICTKEY ) {
+				if ( isdigit((unsigned char)*p) || (*p>='A' && *p<='Z') ||
+				     (*p>='a' && *p<='z' ) ) {
+					newstr_addchar( &s, *p );
+				}
+			}
+			else {
+				if ( *p!=' ' && *p!='\t' ) {
+					newstr_addchar( &s, *p );
+				}
+			}
+			p++;
+		}
+		fstatus = fields_add( out, "REFNUM", newstr_cstr( &s ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+		newstr_free( &s );
+	}
+}
+
+static void
+append_simple( fields *in, char *intag, char *outtag, fields *out, int *status )
+{
+	int n, fstatus;
+
+	n = fields_find( in, intag, LEVEL_ANY );
 	if ( n!=-1 ) {
-		output_and_use( fp, info, n, outtag, format_opts );
+		fields_setused( in, n );
+		fstatus = fields_add( out, outtag, fields_value( in, n, FIELDS_CHRP ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 	}
 }
 
 static void
-output_simpleall( FILE *fp, fields *info, char *intag, char *outtag,
-		int format_opts )
+append_simpleall( fields *in, char *intag, char *outtag, fields *out, int *status )
 {
-	int i;
-	for ( i=0; i<info->n; ++i ) {
-		if ( fields_match_tag( info, i, intag ) )
-			output_and_use( fp, info, i, outtag, format_opts );
+	int i, fstatus;
+
+	for ( i=0; i<in->n; ++i ) {
+		if ( fields_match_tag( in, i, intag ) ) {
+			fields_setused( in, i );
+			fstatus = fields_add( out, outtag, fields_value( in, i, FIELDS_CHRP ), LEVEL_MAIN );
+			if ( fstatus!=FIELDS_OK ) {
+				*status = BIBL_ERR_MEMERR;
+				return;
+			}
+		}
 	}
 }
 
 static void
-output_keywords( FILE *fp, fields *info, int format_opts )
+append_keywords( fields *in, fields *out, int *status )
 {
 	newstr keywords, *word;
+	int i, fstatus;
 	vplist a;
-	int i;
+
 	newstr_init( &keywords );
 	vplist_init( &a );
-	fields_findv_each( info, LEVEL_ANY, FIELDS_STRP, &a, "KEYWORD" );
+
+	fields_findv_each( in, LEVEL_ANY, FIELDS_STRP, &a, "KEYWORD" );
+
 	if ( a.n ) {
+
 		for ( i=0; i<a.n; ++i ) {
 			word = vplist_get( &a, i );
 			if ( i>0 ) newstr_strcat( &keywords, "; " );
 			newstr_newstrcat( &keywords, word );
 		}
-		output_element( fp, "keywords", keywords.data, format_opts );
+
+		fstatus = fields_add( out, "keywords", keywords.data, LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) {
+			*status = BIBL_ERR_MEMERR;
+			goto out;
+		}
+
 
 	}
+
+out:
 	newstr_free( &keywords );
 	vplist_free( &a );
 }
 
 static void
-output_fileattach( FILE *fp, fields *info, int format_opts )
+append_fileattach( fields *in, fields *out, int *status )
 {
+	int i, fstatus;
 	newstr data;
-	int i;
+	char *tag;
+
 	newstr_init( &data );
-	for ( i=0; i<info->n; ++i ) {
-		if ( strcasecmp( info->tag[i].data, "FILEATTACH" ) ) continue;
+	for ( i=0; i<in->n; ++i ) {
+		tag = fields_tag( in, i, FIELDS_CHRP );
+		if ( strcasecmp( tag, "FILEATTACH" ) ) continue;
 		newstr_strcpy( &data, ":" );
-		newstr_newstrcat( &data, &(info->data[i]) );
-		if ( strsearch( info->data[i].data, ".pdf" ) )
+		newstr_newstrcat( &data, &(in->data[i]) );
+		if ( strsearch( in->data[i].data, ".pdf" ) )
 			newstr_strcat( &data, ":PDF" );
-		else if ( strsearch( info->data[i].data, ".html" ) )
+		else if ( strsearch( in->data[i].data, ".html" ) )
 			newstr_strcat( &data, ":HTML" );
 		else newstr_strcat( &data, ":TYPE" );
-		output_element( fp, "file", data.data, format_opts );
-		fields_setused( info, i );
+		fields_setused( in, i );
+		fstatus = fields_add( out, "file", data.data, LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) {
+			*status = BIBL_ERR_MEMERR;
+			goto out;
+		}
 		newstr_empty( &data );
 	}
+out:
 	newstr_free( &data );
 }
 
 static void
-output_people( FILE *fp, fields *info, unsigned long refnum, char *tag, 
-		char *ctag, char *atag, char *bibtag, int level, 
-		int format_opts )
+append_people( fields *in, char *tag, char *ctag, char *atag,
+		char *bibtag, int level, fields *out, int format_opts )
 {
 	newstr allpeople, oneperson;
 	int i, npeople, person, corp, asis;
@@ -321,187 +376,309 @@ output_people( FILE *fp, fields *info, unsigned long refnum, char *tag,
 
 	/* primary citation authors */
 	npeople = 0;
-	for ( i=0; i<info->n; ++i ) {
-		if ( level!=-1 && info->level[i]!=level ) continue;
-		person = ( strcasecmp( info->tag[i].data, tag ) == 0 );
-		corp   = ( strcasecmp( info->tag[i].data, ctag ) == 0 );
-		asis   = ( strcasecmp( info->tag[i].data, atag ) == 0 );
+	for ( i=0; i<in->n; ++i ) {
+		if ( level!=LEVEL_ANY && in->level[i]!=level ) continue;
+		person = ( strcasecmp( in->tag[i].data, tag ) == 0 );
+		corp   = ( strcasecmp( in->tag[i].data, ctag ) == 0 );
+		asis   = ( strcasecmp( in->tag[i].data, atag ) == 0 );
 		if ( person || corp || asis ) {
 			if ( npeople>0 ) {
-				if ( format_opts & BIBOUT_WHITESPACE )
+				if ( format_opts & BIBL_FORMAT_BIBOUT_WHITESPACE )
 					newstr_strcat(&allpeople,"\n\t\tand ");
 				else newstr_strcat( &allpeople, "\nand " );
 			}
 			if ( corp ) {
 				newstr_addchar( &allpeople, '{' );
-				newstr_strcat( &allpeople, fields_value( info, i, FIELDS_CHRP ) );
+				newstr_strcat( &allpeople, fields_value( in, i, FIELDS_CHRP ) );
 				newstr_addchar( &allpeople, '}' );
 			} else if ( asis ) {
 				newstr_addchar( &allpeople, '{' );
-				newstr_strcat( &allpeople, fields_value( info, i, FIELDS_CHRP ) );
+				newstr_strcat( &allpeople, fields_value( in, i, FIELDS_CHRP ) );
 				newstr_addchar( &allpeople, '}' );
 			} else {
-				name_build_withcomma( &oneperson, fields_value( info, i, FIELDS_CHRP ) );
+				name_build_withcomma( &oneperson, fields_value( in, i, FIELDS_CHRP ) );
 				newstr_newstrcat( &allpeople, &oneperson );
 			}
 			npeople++;
 		}
 	}
-	if ( npeople )
-		output_element( fp, bibtag, allpeople.data, format_opts );
+	if ( npeople ) {
+		fields_add( out, bibtag, allpeople.data, LEVEL_MAIN );
+	}
 
 	newstrs_free( &allpeople, &oneperson, NULL );
 }
 
+static int
+append_title_chosen( fields *in, char *bibtag, fields *out, int nmainttl, int nsubttl )
+{
+	newstr fulltitle, *mainttl = NULL, *subttl = NULL;
+	int status, ret = BIBL_OK;
+
+	newstr_init( &fulltitle );
+
+	if ( nmainttl!=-1 ) {
+		mainttl = fields_value( in, nmainttl, FIELDS_STRP );
+		fields_setused( in, nmainttl );
+	}
+
+	if ( nsubttl!=-1 ) {
+		subttl = fields_value( in, nsubttl, FIELDS_STRP );
+		fields_setused( in, nsubttl );
+	}
+
+	title_combine( &fulltitle, mainttl, subttl );
+
+	if ( fulltitle.len ) {
+		status = fields_add( out, bibtag, newstr_cstr( &fulltitle ), LEVEL_MAIN );
+		if ( status!=FIELDS_OK ) ret = BIBL_ERR_MEMERR;
+	}
+
+	newstr_free( &fulltitle );
+
+	return ret;
+}
+
+static int
+append_title( fields *in, char *bibtag, int level, fields *out, int format_opts )
+{
+	int title = -1,     short_title = -1;
+	int subtitle = -1,  short_subtitle = -1;
+	int use_title = -1, use_subtitle = -1;
+
+	title          = fields_find( in, "TITLE",         level );
+	short_title    = fields_find( in, "SHORTTITLE",    level );
+	subtitle       = fields_find( in, "SUBTITLE",      level );
+	short_subtitle = fields_find( in, "SHORTSUBTITLE", level );
+
+	if ( title==-1 || ( ( format_opts & BIBL_FORMAT_BIBOUT_SHORTTITLE ) && level==1 ) ) {
+		use_title    = short_title;
+		use_subtitle = short_subtitle;
+	}
+
+	else {
+		use_title    = title;
+		use_subtitle = subtitle;
+	}
+
+	return append_title_chosen( in, bibtag, out, use_title, use_subtitle );
+}
+
 static void
-output_title( FILE *fp, fields *info, unsigned long refnum, char *bibtag, int level, int format_opts )
+append_titles( fields *in, int type, fields *out, int format_opts, int *status )
 {
-	newstr title, *mainttl, *subttl;
-	int n1 = -1, n2 = -1;
-	/* Option is for short titles of journals */
-	if ( ( format_opts & BIBOUT_SHORTTITLE ) && level==1 ) {
-		n1 = fields_find( info, "SHORTTITLE", level );
-		n2 = fields_find( info, "SHORTSUBTITLE", level );
-	}
-	if ( n1==-1 ) {
-		n1 = fields_find( info, "TITLE", level );
-		n2 = fields_find( info, "SUBTITLE", level );
-	}
-	if ( n1!=-1 ) {
-		newstr_init( &title );
-		mainttl = fields_value( info, n1, FIELDS_STRP );
-		newstr_newstrcpy( &title, mainttl );
-		fields_setused( info, n1 );
-		if ( n2!=-1 ) {
-			subttl = fields_value( info, n2, FIELDS_STRP );
-			if ( mainttl->len > 0 &&
-			     mainttl->data[mainttl->len-1]!='?' )
-				newstr_strcat( &title, ": " );
-			else newstr_addchar( &title, ' ' );
-			newstr_newstrcat( &title, subttl );
-			fields_setused( info, n2 );
-		}
-		output_element( fp, bibtag, title.data, format_opts );
-		newstr_free( &title );
+	/* item=main level title */
+	*status = append_title( in, "title", 0, out, format_opts );
+	if ( *status!=BIBL_OK ) return;
+
+	switch( type ) {
+
+		case TYPE_ARTICLE:
+		*status = append_title( in, "journal", 1, out, format_opts );
+		break;
+
+		case TYPE_INBOOK:
+		*status = append_title( in, "bookTitle", 1, out, format_opts );
+		if ( *status!=BIBL_OK ) return;
+		*status = append_title( in, "series",    2, out, format_opts );
+		break;
+
+		case TYPE_INCOLLECTION:
+		case TYPE_INPROCEEDINGS:
+		*status = append_title( in, "booktitle", 1, out, format_opts );
+		if ( *status!=BIBL_OK ) return;
+		*status = append_title( in, "series",    2, out, format_opts );
+		break;
+
+		case TYPE_PHDTHESIS:
+		case TYPE_MASTERSTHESIS:
+		*status = append_title( in, "series", 1, out, format_opts );
+		break;
+
+		case TYPE_BOOK:
+		case TYPE_REPORT:
+		case TYPE_COLLECTION:
+		case TYPE_PROCEEDINGS:
+		*status = append_title( in, "series", 1, out, format_opts );
+		if ( *status!=BIBL_OK ) return;
+		*status = append_title( in, "series", 2, out, format_opts );
+		break;
+
+		default:
+		/* do nothing */
+		break;
+
+	}
+}
+
+static int
+find_date( fields *in, char *date_element )
+{
+	char date[100], partdate[100];
+	int n;
+
+	sprintf( date, "DATE:%s", date_element );
+	n = fields_find( in, date, LEVEL_ANY );
+
+	if ( n==-1 ) {
+		sprintf( partdate, "PARTDATE:%s", date_element );
+		n = fields_find( in, partdate, LEVEL_ANY );
 	}
+
+	return n;
 }
 
 static void
-output_date( FILE *fp, fields *info, unsigned long refnum, int format_opts )
+append_date( fields *in, fields *out, int *status )
 {
 	char *months[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", 
 		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-	int n, month;
-	n = fields_find( info, "YEAR", -1 );
-	if ( n==-1 ) n = fields_find( info, "PARTYEAR", -1 );
+	int n, month, fstatus;
+
+	n = find_date( in, "YEAR" );
 	if ( n!=-1 ) {
-		output_element( fp, "year", info->data[n].data, format_opts );
-		fields_setused( info, n );
+		fields_setused( in, n );
+		fstatus = fields_add( out, "year", in->data[n].data, LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) {
+			*status = BIBL_ERR_MEMERR;
+			return;
+		}
 	}
-	n = fields_find( info, "MONTH", -1 );
-	if ( n==-1 ) n = fields_find( info, "PARTMONTH", -1 );
+
+	n = find_date( in, "MONTH" );
 	if ( n!=-1 ) {
-		month = atoi( info->data[n].data );
+		fields_setused( in, n );
+		month = atoi( in->data[n].data );
 		if ( month>0 && month<13 )
-			output_element( fp, "month", months[month-1], format_opts );
+			fstatus = fields_add( out, "month", months[month-1], LEVEL_MAIN );
 		else
-			output_element( fp, "month", info->data[n].data, format_opts );
-		fields_setused( info, n );
+			fstatus = fields_add( out, "month", in->data[n].data, LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) {
+			*status = BIBL_ERR_MEMERR;
+			return;
+		}
 	}
-	n = fields_find( info, "DAY", -1 );
-	if ( n==-1 ) n = fields_find( info, "PARTDAY", -1 );
+
+	n = find_date( in, "DAY" );
 	if ( n!=-1 ) {
-		output_element( fp, "day", info->data[n].data, format_opts );
-		fields_setused( info, n );
+		fields_setused( in, n );
+		fstatus = fields_add( out, "day", in->data[n].data, LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) {
+			*status = BIBL_ERR_MEMERR;
+			return;
+		}
 	}
-}
 
+}
 
-/* output article number as pages if true pages aren't found */
 static void
-output_articlenumber( FILE *fp, fields *info, unsigned long refnum,
-	int format_opts )
+append_arxiv( fields *in, fields *out, int *status )
 {
-	int ar = fields_find( info, "ARTICLENUMBER", -1 );
-	if ( ar!=-1 ) {
-		newstr pages;
-		newstr_init( &pages );
-		newstr_strcat( &pages, info->data[ar].data );
-		output_element( fp, "pages", pages.data, format_opts );
-		fields_setused( info, ar );
-		newstr_free( &pages );
+	int n, fstatus1, fstatus2;
+	newstr url;
+
+	n = fields_find( in, "ARXIV", LEVEL_ANY );
+	if ( n==-1 ) return;
+
+	fields_setused( in, n );
+
+	/* ...write:
+	 *     archivePrefix = "arXiv",
+	 *     eprint = "#####",
+	 * ...for people in high energy physics
+	 */
+	fstatus1 = fields_add( out, "archivePrefix", "arXiv", LEVEL_MAIN );
+	fstatus2 = fields_add( out, "eprint", fields_value( in, n, FIELDS_CHRP ), LEVEL_MAIN );
+	if ( fstatus1!=FIELDS_OK || fstatus2!=FIELDS_OK ) {
+		*status = BIBL_ERR_MEMERR;
+		return;
 	}
+
+	/* ...also write:
+	 *     url = "http://arxiv.org/abs/####",
+	 * ...to maximize compatibility
+	 */
+	newstr_init( &url );
+	arxiv_to_url( in, n, "URL", &url );
+	if ( url.len ) {
+		fstatus1 = fields_add( out, "url", newstr_cstr( &url ), LEVEL_MAIN );
+		if ( fstatus1!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
+	newstr_free( &url );
 }
 
 static void
-output_arxiv( FILE *fp, fields *info, int format_opts )
+append_urls( fields *in, fields *out, int *status )
 {
-	int ar = fields_find( info, "ARXIV", -1 );
-	if ( ar!=-1 ) {
-		newstr arxiv;
-		newstr_init( &arxiv );
-		arxiv_to_url( info, ar, "URL", &arxiv );
-		if ( arxiv.len )
-			output_element( fp, "url", arxiv.data, format_opts );
-		newstr_free( &arxiv );
+	int lstatus;
+	list types;
+
+	lstatus = list_init_valuesc( &types, "URL", "PMID", "PMC", "JSTOR", NULL );
+	if ( lstatus!=LIST_OK ) {
+		*status = BIBL_ERR_MEMERR;
+		return;
 	}
+
+	*status = urls_merge_and_add( in, LEVEL_ANY, out, "url", LEVEL_MAIN, &types );
+
+	list_free( &types );
 }
 
 static void
-output_pmid( FILE *fp, fields *info, int format_opts )
+append_isi( fields *in, fields *out, int *status )
 {
-	int pm = fields_find( info, "PMID", -1 );
-	if ( pm!=-1 ) {
-		newstr pmid;
-		newstr_init( &pmid );
-		pmid_to_url( info, pm, "URL", &pmid );
-		if ( pmid.len )
-			output_element( fp, "url", pmid.data, format_opts );
-		newstr_free( &pmid );
+	int n, fstatus;
+
+	n = fields_find( in, "ISIREFNUM", LEVEL_ANY );
+	if ( n!=-1 ) {
+		fstatus = fields_add( out, "note", fields_value( in, n, FIELDS_CHRP ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 	}
 }
 
-static void
-output_jstor( FILE *fp, fields *info, int format_opts )
+static int
+append_articlenumber( fields *in, fields *out )
 {
-	int js = fields_find( info, "JSTOR", -1 );
-	if ( js!=-1 ) {
-		newstr jstor;
-		newstr_init( &jstor );
-		jstor_to_url( info, js, "URL", &jstor );
-		if ( jstor.len )
-			output_element( fp, "url", jstor.data, format_opts );
-		newstr_free( &jstor );
-	}
+	int n, fstatus;
+
+	n = fields_find( in, "ARTICLENUMBER", LEVEL_ANY );
+	if ( n==-1 ) return BIBL_OK;
+
+	fields_setused( in, n );
+	fstatus = fields_add( out, "pages", fields_value( in, n, FIELDS_CHRP ), LEVEL_MAIN );
+	if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+	return BIBL_OK;
 }
 
 static void
-output_pages( FILE *fp, fields *info, unsigned long refnum, int format_opts )
+append_pages( fields *in, fields *out, int format_opts, int *status )
 {
+	int sn, en, fstatus;
 	newstr pages;
-	int sn, en;
-	sn = fields_find( info, "PAGESTART", -1 );
-	en = fields_find( info, "PAGEEND", -1 );
+
+	sn = fields_find( in, "PAGES:START", LEVEL_ANY );
+	en = fields_find( in, "PAGES:STOP",  LEVEL_ANY );
 	if ( sn==-1 && en==-1 ) {
-		output_articlenumber( fp, info, refnum, format_opts );
+		*status = append_articlenumber( in, out );
 		return;
 	}
 	newstr_init( &pages );
 	if ( sn!=-1 ) {
-		newstr_strcat( &pages, info->data[sn].data );
-		fields_setused( info, sn );
+		newstr_newstrcat( &pages, fields_value( in, sn, FIELDS_STRP ) );
+		fields_setused( in, sn );
 	}
 	if ( sn!=-1 && en!=-1 ) {
-		if ( format_opts & BIBOUT_SINGLEDASH ) 
+		if ( format_opts & BIBL_FORMAT_BIBOUT_SINGLEDASH )
 			newstr_strcat( &pages, "-" );
 		else
 			newstr_strcat( &pages, "--" );
 	}
 	if ( en!=-1 ) {
-		newstr_strcat( &pages, info->data[en].data );
-		fields_setused( info, en );
+		newstr_newstrcat( &pages, fields_value( in, en, FIELDS_STRP ) );
+		fields_setused( in, en );
 	}
-	output_element( fp, "pages", pages.data, format_opts );
+	fstatus = fields_add( out, "pages", newstr_cstr( &pages ), LEVEL_MAIN );
+	if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 	newstr_free( &pages );
 }
 
@@ -518,108 +695,93 @@ output_pages( FILE *fp, fields *info, unsigned long refnum, int format_opts )
  */
 
 static void
-output_issue_number( FILE *fp, fields *info, int format_opts )
+append_issue_number( fields *in, fields *out, int *status )
 {
-	int nissue  = fields_find( info, "ISSUE", -1 );
-	int nnumber = fields_find( info, "NUMBER", -1 );
+	int nissue  = fields_find( in, "ISSUE",  LEVEL_ANY );
+	int nnumber = fields_find( in, "NUMBER", LEVEL_ANY );
+	int fstatus;
+
 	if ( nissue!=-1 && nnumber!=-1 ) {
-		output_and_use( fp, info, nissue,  "issue",  format_opts );
-		output_and_use( fp, info, nnumber, "number", format_opts );
-/*		output_element( fp, "issue", info->data[nissue].data, 
-				format_opts );
-		fields_setused( info, nissue );
-		output_element( fp, "number", info->data[nnumber].data, 
-				format_opts );
-		fields_setused( info, nnumber );*/
+		fields_setused( in, nissue );
+		fields_setused( in, nnumber );
+		fstatus = fields_add( out, "issue", fields_value( in, nissue, FIELDS_CHRP ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) {
+			*status = BIBL_ERR_MEMERR;
+			return;
+		}
+		fstatus = fields_add( out, "number", fields_value( in, nnumber, FIELDS_CHRP ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 	} else if ( nissue!=-1 ) {
-		output_and_use( fp, info, nissue, "number", format_opts );
-/*
-		output_element( fp, "number", info->data[nissue].data, 
-				format_opts );
-		fields_setused( info, nissue );*/
+		fields_setused( in, nissue );
+		fstatus = fields_add( out, "number", fields_value( in, nissue, FIELDS_CHRP ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 	} else if ( nnumber!=-1 ) {
-		output_and_use( fp, info, nnumber, "number", format_opts );
-/*
-		output_element( fp, "number", info->data[nnumber].data, 
-				format_opts );
-		fields_setused( info, nnumber );
-*/
+		fields_setused( in, nnumber );
+		fstatus = fields_add( out, "number", fields_value( in, nnumber, FIELDS_CHRP ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 	}
 }
 
-void
-bibtexout_write( fields *info, FILE *fp, param *p, unsigned long refnum )
+static int
+append_data( fields *in, fields *out, param *p, unsigned long refnum )
 {
-	int type;
-	fields_clearused( info );
-	type = bibtexout_type( info, "", refnum, p );
-	output_type( fp, type, p->format_opts );
-	if ( !( p->format_opts & BIBOUT_DROPKEY ) )
-		output_citekey( fp, info, refnum, p->format_opts );
-	output_people( fp, info, refnum, "AUTHOR", "AUTHOR:CORP", "AUTHOR:ASIS", "author", 0,
-		p->format_opts );
-	output_people( fp, info, refnum, "EDITOR", "EDITOR:CORP", "EDITOR:ASIS", "editor", -1,
-		p->format_opts );
-	output_people( fp, info, refnum, "TRANSLATOR", "TRANSLATOR:CORP", "TRANSLATOR:ASIS", "translator", -1, p->format_opts );
+	int type, status = BIBL_OK;
+
+	type = bibtexout_type( in, "", refnum, p );
+
+	append_type        ( type, out, &status );
+	append_citekey     ( in, out, p->format_opts, &status );
+	append_people      ( in, "AUTHOR",     "AUTHOR:CORP",     "AUTHOR:ASIS",     "author", 0, out, p->format_opts );
+	append_people      ( in, "EDITOR",     "EDITOR:CORP",     "EDITOR:ASIS",     "editor", -1, out, p->format_opts );
+	append_people      ( in, "TRANSLATOR", "TRANSLATOR:CORP", "TRANSLATOR:ASIS", "translator", -1, out, p->format_opts );
+	append_titles      ( in, type, out, p->format_opts, &status );
+	append_date        ( in, out, &status );
+	append_simple      ( in, "EDITION",            "edition",   out, &status );
+	append_simple      ( in, "PUBLISHER",          "publisher", out, &status );
+	append_simple      ( in, "ADDRESS",            "address",   out, &status );
+	append_simple      ( in, "VOLUME",             "volume",    out, &status );
+	append_issue_number( in, out, &status );
+	append_pages       ( in, out, p->format_opts, &status );
+	append_keywords    ( in, out, &status );
+	append_simple      ( in, "CONTENTS",           "contents",  out, &status );
+	append_simple      ( in, "ABSTRACT",           "abstract",  out, &status );
+	append_simple      ( in, "LOCATION",           "location",  out, &status );
+	append_simple      ( in, "DEGREEGRANTOR",      "school",    out, &status );
+	append_simple      ( in, "DEGREEGRANTOR:ASIS", "school",    out, &status );
+	append_simple      ( in, "DEGREEGRANTOR:CORP", "school",    out, &status );
+	append_simpleall   ( in, "NOTES",              "note",      out, &status );
+	append_simpleall   ( in, "ANNOTE",             "annote",    out, &status );
+	append_simple      ( in, "ISBN",               "isbn",      out, &status );
+	append_simple      ( in, "ISSN",               "issn",      out, &status );
+	append_simple      ( in, "MRNUMBER",           "mrnumber",  out, &status );
+	append_simple      ( in, "CODEN",              "coden",     out, &status );
+	append_simple      ( in, "DOI",                "doi",       out, &status );
+	append_urls        ( in, out, &status );
+	append_fileattach  ( in, out, &status );
+	append_arxiv       ( in, out, &status );
+	append_isi         ( in, out, &status );
+	append_simple      ( in, "LANGUAGE",           "language",  out, &status );
+
+	return status;
+}
 
-	/* item=main level title */
-	if ( type==TYPE_INBOOK )
-		output_title( fp, info, refnum, "chapter", 0, p->format_opts );
-	else
-		output_title( fp, info, refnum, "title", 0, p->format_opts );
-
-	/* item=host level title */
-	if ( type==TYPE_ARTICLE )
-		output_title( fp, info, refnum, "journal", 1, p->format_opts );
-	else if ( type==TYPE_INBOOK ) {
-		output_title( fp, info, refnum, "title", 1, p->format_opts );
-		output_title( fp, info, refnum, "series", 2, p->format_opts );
-	}
-	else if ( type==TYPE_INPROCEEDINGS || type==TYPE_INCOLLECTION ) {
-		output_title( fp, info, refnum, "booktitle", 1, p->format_opts );
-		output_title( fp, info, refnum, "series", 2, p->format_opts );
-	}
-	else if ( type==TYPE_PHDTHESIS || type==TYPE_MASTERSTHESIS ) {
-		output_title( fp, info, refnum, "series", 1, p->format_opts );
-	}
-	else if ( type==TYPE_BOOK || type==TYPE_COLLECTION || type==TYPE_PROCEEDINGS || type==TYPE_REPORT ) {
-		output_title( fp, info, refnum, "series", 1, p->format_opts );
-		output_title( fp, info, refnum, "series", 2, p->format_opts );
-	}
-
-	output_date( fp, info, refnum, p->format_opts );
-	output_simple( fp, info, "EDITION", "edition", p->format_opts );
-	output_simple( fp, info, "PUBLISHER", "publisher", p->format_opts );
-	output_simple( fp, info, "ADDRESS", "address", p->format_opts );
-	output_simple( fp, info, "VOLUME", "volume", p->format_opts );
-	output_issue_number( fp, info, p->format_opts );
-/*	output_simple( fp, info, "ISSUE", "issue", p->format_opts );
-	output_simple( fp, info, "NUMBER", "number", p->format_opts );s*/
-	output_pages( fp, info, refnum, p->format_opts );
-	output_keywords( fp, info, p->format_opts );
-	output_simple( fp, info, "CONTENTS", "contents", p->format_opts );
-	output_simple( fp, info, "ABSTRACT", "abstract", p->format_opts );
-	output_simple( fp, info, "LOCATION", "location", p->format_opts );
-	output_simple( fp, info, "DEGREEGRANTOR", "school", p->format_opts );
-	output_simple( fp, info, "DEGREEGRANTOR:ASIS", "school", p->format_opts );
-	output_simple( fp, info, "DEGREEGRANTOR:CORP", "school", p->format_opts );
-	output_simpleall( fp, info, "NOTES", "note", p->format_opts );
-	output_simpleall( fp, info, "ANNOTE", "annote", p->format_opts );
-	output_simple( fp, info, "ISBN", "isbn", p->format_opts );
-	output_simple( fp, info, "ISSN", "issn", p->format_opts );
-	output_simple( fp, info, "DOI", "doi", p->format_opts );
-	output_simpleall( fp, info, "URL", "url", p->format_opts );
-	output_fileattach( fp, info, p->format_opts );
-	output_arxiv( fp, info, p->format_opts );
-	output_pmid( fp, info, p->format_opts );
-	output_jstor( fp, info, p->format_opts );
-	output_simple( fp, info, "LANGUAGE", "language", p->format_opts );
-	if ( p->format_opts & BIBOUT_FINALCOMMA ) fprintf( fp, "," );
-	fprintf( fp, "\n}\n\n" );
-	fflush( fp );
+static int
+bibtexout_write( fields *in, FILE *fp, param *p, unsigned long refnum )
+{
+	int status;
+	fields out;
+
+	fields_init( &out );
+
+	status = append_data( in, &out, p, refnum );
+	if ( status==BIBL_OK ) output( fp, &out, p->format_opts );
+
+	fields_free( &out );
+
+	return status;
 }
 
-void
+static void
 bibtexout_writeheader( FILE *outptr, param *p )
 {
 	if ( p->utf8bom ) utf8_writebom( outptr );
diff --git a/lib/bibtexout.h b/lib/bibtexout.h
deleted file mode 100644
index 1cb08d6..0000000
--- a/lib/bibtexout.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * bibtexout.h
- *
- * Copyright (c) Chris Putnam 2005-2015
- *
- * Source code released under GPL version 2
- *
- */
-#ifndef BIBTEXOUT_H
-#define BIBTEXOUT_H
-
-#include <stdio.h>
-#include "fields.h"
-#include "bibutils.h"
-
-/* bibtexout output options */
-#define BIBOUT_FINALCOMMA   (2)
-#define BIBOUT_SINGLEDASH   (4)
-#define BIBOUT_WHITESPACE   (8)
-#define BIBOUT_BRACKETS    (16)
-#define BIBOUT_UPPERCASE   (32)
-#define BIBOUT_STRICTKEY   (64)
-#define BIBOUT_SHORTTITLE (128)
-#define BIBOUT_DROPKEY    (256)
-
-extern void bibtexout_write( fields *info, FILE *fp, param *p, 
-		unsigned long refnum );
-extern void bibtexout_writeheader( FILE *outptr, param *p );
-extern void bibtexout_initparams( param *p, const char *progname );
-
-#endif
diff --git a/lib/bibtextypes.c b/lib/bibtextypes.c
index 3839643..6ed7416 100644
--- a/lib/bibtextypes.c
+++ b/lib/bibtextypes.c
@@ -1,7 +1,7 @@
 /*
  * bibtypes.c
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -16,38 +16,43 @@
  * Journal Article
  */
 static lookups article[] = {
-	{ "author",       "AUTHOR",    PERSON, LEVEL_MAIN },
-	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },
-	{ "title",        "TITLE",     TITLE,  LEVEL_MAIN },
-	{ "year",         "PARTYEAR",  SIMPLE, LEVEL_MAIN },
-	{ "month",        "PARTMONTH", SIMPLE, LEVEL_MAIN },
-	{ "day",          "PARTDAY",   SIMPLE, LEVEL_MAIN },
-	{ "volume",       "VOLUME",    SIMPLE, LEVEL_MAIN },
-	{ "pages",        "PAGES",     PAGES,  LEVEL_MAIN },
-	{ "number",       "ISSUE",     SIMPLE, LEVEL_MAIN },
-	{ "issue",        "ISSUE",     SIMPLE, LEVEL_MAIN },
-	{ "journal",      "TITLE",     TITLE,  LEVEL_HOST },
-	{ "publisher",    "PUBLISHER", SIMPLE, LEVEL_HOST },
-	{ "address",      "ADDRESS",   SIMPLE, LEVEL_HOST },
-	{ "issn",         "ISSN",      SIMPLE, LEVEL_HOST },
-	{ "abstract",     "ABSTRACT",  SIMPLE, LEVEL_MAIN },
-	{ "contents",     "CONTENTS",  SIMPLE, LEVEL_MAIN },
-	{ "language",     "LANGUAGE",  SIMPLE, LEVEL_MAIN },
-	{ "note",         "NOTES",     BT_NOTE, LEVEL_MAIN },
-	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },
-	{ "location",     "LOCATION",  SIMPLE, LEVEL_MAIN },
-	{ "ftp",          "",      BT_URL, LEVEL_MAIN },
-	{ "url",          "",      BT_URL, LEVEL_MAIN },
-	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
-	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
-	{ "howpublished", "",       HOWPUBLISHED, LEVEL_MAIN },
-	{ "doi",          "DOI",       SIMPLE, LEVEL_MAIN },
-	{ "key",          "BIBKEY",       SIMPLE, LEVEL_MAIN },
-	{ "refnum",       "REFNUM",    SIMPLE, LEVEL_MAIN },
-	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
-	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
-	{ "",             "INTERNAL_TYPE|ARTICLE",           ALWAYS, LEVEL_MAIN },
+	{ "author",       "AUTHOR",         PERSON,       LEVEL_MAIN },
+	{ "translator",   "TRANSLATOR",     PERSON,       LEVEL_MAIN },
+	{ "title",        "",               TITLE,        LEVEL_MAIN },
+	{ "year",         "PARTDATE:YEAR",  SIMPLE,       LEVEL_MAIN },
+	{ "month",        "PARTDATE:MONTH", SIMPLE,       LEVEL_MAIN },
+	{ "day",          "PARTDATE:DAY",   SIMPLE,       LEVEL_MAIN },
+	{ "volume",       "VOLUME",         SIMPLE,       LEVEL_MAIN },
+	{ "pages",        "PAGES",          PAGES,        LEVEL_MAIN },
+	{ "number",       "ISSUE",          SIMPLE,       LEVEL_MAIN },
+	{ "issue",        "ISSUE",          SIMPLE,       LEVEL_MAIN },
+	{ "journal",      "",               TITLE,        LEVEL_HOST },
+	{ "publisher",    "PUBLISHER",      SIMPLE,       LEVEL_HOST },
+	{ "address",      "ADDRESS",        SIMPLE,       LEVEL_HOST },
+	{ "issn",         "ISSN",           SIMPLE,       LEVEL_HOST },
+	{ "coden",        "CODEN",          SIMPLE,       LEVEL_HOST },
+	{ "abstract",     "ABSTRACT",       SIMPLE,       LEVEL_MAIN },
+	{ "contents",     "CONTENTS",       SIMPLE,       LEVEL_MAIN },
+	{ "language",     "LANGUAGE",       SIMPLE,       LEVEL_MAIN },
+	{ "note",         "NOTES",          NOTES,        LEVEL_MAIN },
+	{ "annote",       "ANNOTE",         SIMPLE,       LEVEL_MAIN },
+	{ "location",     "LOCATION",       SIMPLE,       LEVEL_MAIN },
+	{ "ftp",          "",               URL,          LEVEL_MAIN },
+	{ "url",          "",               URL,          LEVEL_MAIN },
+	{ "pdf",          "FILEATTACH",     SIMPLE,       LEVEL_MAIN },
+	{ "eprint",       "",               EPRINT,       LEVEL_MAIN },
+	{ "archivePrefix","ARCHIVEPREFIX",  SIMPLE,       LEVEL_MAIN },
+	{ "primaryClass", "KEYWORD",        KEYWORD,      LEVEL_MAIN },
+	{ "sentelink",    "FILEATTACH",     BT_SENTE,     LEVEL_MAIN },
+	{ "file",         "FILEATTACH",     LINKEDFILE,   LEVEL_MAIN },
+	{ "howpublished", "",               HOWPUBLISHED, LEVEL_MAIN },
+	{ "mrnumber",     "MRNUMBER",       SIMPLE,       LEVEL_MAIN },
+	{ "doi",          "DOI",            SIMPLE,       LEVEL_MAIN },
+	{ "key",          "BIBKEY",         SIMPLE,       LEVEL_MAIN },
+	{ "refnum",       "REFNUM",         SIMPLE,       LEVEL_MAIN },
+	{ "crossref",     "CROSSREF",       SIMPLE,       LEVEL_MAIN },
+	{ "keywords",     "KEYWORD",        KEYWORD,      LEVEL_MAIN },
+	{ "",             "INTERNAL_TYPE|ARTICLE",   ALWAYS, LEVEL_MAIN },
 	{ "",             "ISSUANCE|continuing",     ALWAYS, LEVEL_HOST },
 	{ "",             "RESOURCE|text",           ALWAYS, LEVEL_MAIN },
 	{ "",             "NGENRE|journal article",  ALWAYS, LEVEL_MAIN },
@@ -58,43 +63,43 @@ static lookups article[] = {
 /* Book */
 
 static lookups book[] = {
-	{ "author",       "AUTHOR",    PERSON, LEVEL_MAIN },
-	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },
-	{ "title",        "TITLE",     TITLE,  LEVEL_MAIN },
-	{ "booktitle",    "TITLE",     TITLE,  LEVEL_MAIN },
-	{ "series",       "TITLE",     TITLE,  LEVEL_HOST },
-	{ "publisher",    "PUBLISHER", SIMPLE, LEVEL_MAIN },
-	{ "organization", "ORGANIZER:CORP", BT_ORG, LEVEL_MAIN },
-	{ "address",      "ADDRESS",   SIMPLE, LEVEL_MAIN },
-	{ "editor",       "EDITOR",    PERSON, LEVEL_MAIN },
-	{ "year",         "YEAR",      SIMPLE, LEVEL_MAIN },
-	{ "month",        "MONTH",     SIMPLE, LEVEL_MAIN },
-	{ "day",          "DAY",       SIMPLE, LEVEL_MAIN },
-	{ "volume",       "VOLUME",    SIMPLE, LEVEL_MAIN },
-	{ "number",       "NUMBER",    SIMPLE, LEVEL_MAIN },
-	{ "isbn",         "ISBN",      SIMPLE, LEVEL_MAIN },
-	{ "lccn",         "LCCN",      SIMPLE, LEVEL_MAIN },
-	{ "edition",      "EDITION",   SIMPLE, LEVEL_MAIN },
-	{ "abstract",     "ABSTRACT",  SIMPLE, LEVEL_MAIN },
-	{ "contents",     "CONTENTS",  SIMPLE, LEVEL_MAIN },
-	{ "language",     "LANGUAGE",  SIMPLE, LEVEL_MAIN },
-	{ "location",     "LOCATION",  SIMPLE, LEVEL_MAIN },
-	{ "note",         "NOTES",     BT_NOTE, LEVEL_MAIN },
-	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },
-	{ "type",         "GENRE",     SIMPLE, LEVEL_MAIN },
-	{ "key",          "BIBKEY",    SIMPLE, LEVEL_MAIN },
-	{ "ftp",          "",       BT_URL, LEVEL_MAIN },
-	{ "url",          "",       BT_URL, LEVEL_MAIN },
-	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
-	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
-	{ "address",      "ADDRESS",   SIMPLE, LEVEL_MAIN },
-	{ "howpublished", "",       HOWPUBLISHED, LEVEL_MAIN },
-	{ "doi",          "DOI",       SIMPLE, LEVEL_MAIN },
-	{ "refnum",       "REFNUM",    SIMPLE, LEVEL_MAIN },
-	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
-	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
-	{ "refnum",       "REFNUM",    SIMPLE, LEVEL_MAIN },
+	{ "author",       "AUTHOR",         PERSON,       LEVEL_MAIN },
+	{ "translator",   "TRANSLATOR",     PERSON,       LEVEL_MAIN },
+	{ "title",        "",               TITLE,        LEVEL_MAIN },
+	{ "booktitle",    "",               TITLE,        LEVEL_MAIN },
+	{ "series",       "",               TITLE,        LEVEL_HOST },
+	{ "publisher",    "PUBLISHER",      SIMPLE,       LEVEL_MAIN },
+	{ "organization", "ORGANIZER:CORP", BT_ORG,       LEVEL_MAIN },
+	{ "address",      "ADDRESS",        SIMPLE,       LEVEL_MAIN },
+	{ "editor",       "EDITOR",         PERSON,       LEVEL_MAIN },
+	{ "year",         "DATE:YEAR",      SIMPLE,       LEVEL_MAIN },
+	{ "month",        "DATE:MONTH",     SIMPLE,       LEVEL_MAIN },
+	{ "day",          "DATE:DAY",       SIMPLE,       LEVEL_MAIN },
+	{ "volume",       "VOLUME",         SIMPLE,       LEVEL_MAIN },
+	{ "number",       "NUMBER",         SIMPLE,       LEVEL_MAIN },
+	{ "isbn",         "ISBN",           SIMPLE,       LEVEL_MAIN },
+	{ "lccn",         "LCCN",           SIMPLE,       LEVEL_MAIN },
+	{ "edition",      "EDITION",        SIMPLE,       LEVEL_MAIN },
+	{ "abstract",     "ABSTRACT",       SIMPLE,       LEVEL_MAIN },
+	{ "contents",     "CONTENTS",       SIMPLE,       LEVEL_MAIN },
+	{ "language",     "LANGUAGE",       SIMPLE,       LEVEL_MAIN },
+	{ "location",     "LOCATION",       SIMPLE,       LEVEL_MAIN },
+	{ "note",         "NOTES",          NOTES,        LEVEL_MAIN },
+	{ "annote",       "ANNOTE",         SIMPLE,       LEVEL_MAIN },
+	{ "type",         "GENRE",          SIMPLE,       LEVEL_MAIN },
+	{ "key",          "BIBKEY",         SIMPLE,       LEVEL_MAIN },
+	{ "ftp",          "",               URL,          LEVEL_MAIN },
+	{ "url",          "",               URL,          LEVEL_MAIN },
+	{ "pdf",          "FILEATTACH",     SIMPLE,       LEVEL_MAIN },
+	{ "sentelink",    "FILEATTACH",     BT_SENTE,     LEVEL_MAIN },
+	{ "file",         "FILEATTACH",     LINKEDFILE,   LEVEL_MAIN },
+	{ "address",      "ADDRESS",        SIMPLE,       LEVEL_MAIN },
+	{ "howpublished", "",               HOWPUBLISHED, LEVEL_MAIN },
+	{ "doi",          "DOI",            SIMPLE,       LEVEL_MAIN },
+	{ "refnum",       "REFNUM",         SIMPLE,       LEVEL_MAIN },
+	{ "crossref",     "CROSSREF",       SIMPLE,       LEVEL_MAIN },
+	{ "keywords",     "KEYWORD",        KEYWORD,      LEVEL_MAIN },
+	{ "refnum",       "REFNUM",         SIMPLE,       LEVEL_MAIN },
 	{ "",             "INTERNAL_TYPE|BOOK",   ALWAYS, LEVEL_MAIN },
 	{ "",             "RESOURCE|text",        ALWAYS, LEVEL_MAIN },
 	{ "",             "ISSUANCE|monographic", ALWAYS, LEVEL_MAIN },
@@ -104,39 +109,40 @@ static lookups book[] = {
 /* Technical reports */
 
 static lookups report[] = {
-	{ "author",       "AUTHOR",       PERSON, LEVEL_MAIN },
-	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },
-	{ "title",        "TITLE",        TITLE,  LEVEL_MAIN },
-	{ "booktitle",    "TITLE",        TITLE,  LEVEL_MAIN },
-	{ "series",       "TITLE",        TITLE,  LEVEL_HOST },
-	{ "editor",       "EDITOR",       PERSON, LEVEL_MAIN },
-	{ "publisher",    "PUBLISHER",    SIMPLE, LEVEL_MAIN },
-	{ "institution",  "PUBLISHER",    SIMPLE, LEVEL_MAIN },
-	{ "address",      "ADDRESS",      SIMPLE, LEVEL_MAIN },
-	{ "year",         "YEAR",         SIMPLE, LEVEL_MAIN },
-	{ "month",        "MONTH",        SIMPLE, LEVEL_MAIN },
-	{ "day",          "DAY",          SIMPLE, LEVEL_MAIN },
-	{ "number",       "NUMBER",       SIMPLE, LEVEL_MAIN },
-	{ "isbn",         "ISBN",         SIMPLE, LEVEL_MAIN },
-	{ "lccn",         "LCCN",         SIMPLE, LEVEL_MAIN },
-	{ "abstract",     "ABSTRACT",     SIMPLE, LEVEL_MAIN },
-	{ "contents",     "CONTENTS",     SIMPLE, LEVEL_MAIN },
-	{ "language",     "LANGUAGE",     SIMPLE, LEVEL_MAIN },
-	{ "location",     "LOCATION",     SIMPLE, LEVEL_MAIN },
-	{ "note",         "NOTES",        BT_NOTE, LEVEL_MAIN },
-	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },
-	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN },
-	{ "doi",          "DOI",          SIMPLE, LEVEL_MAIN },
-	{ "ftp",          "",          BT_URL, LEVEL_MAIN },
-	{ "url",          "",          BT_URL, LEVEL_MAIN },
-	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
-	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
-	{ "howpublished", "",          HOWPUBLISHED, LEVEL_MAIN },
-	{ "refnum",    "REFNUM",          SIMPLE, LEVEL_MAIN },
-	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
-	{ "type",      "GENRE",            SIMPLE, LEVEL_MAIN },
-	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
+	{ "author",       "AUTHOR",     PERSON,       LEVEL_MAIN },
+	{ "translator",   "TRANSLATOR", PERSON,       LEVEL_MAIN },
+	{ "title",        "",           TITLE,        LEVEL_MAIN },
+	{ "booktitle",    "",           TITLE,        LEVEL_MAIN },
+	{ "series",       "",           TITLE,        LEVEL_HOST },
+	{ "editor",       "EDITOR",     PERSON,       LEVEL_MAIN },
+	{ "publisher",    "PUBLISHER",  SIMPLE,       LEVEL_MAIN },
+	{ "institution",  "PUBLISHER",  SIMPLE,       LEVEL_MAIN },
+	{ "address",      "ADDRESS",    SIMPLE,       LEVEL_MAIN },
+	{ "year",         "DATE:YEAR",  SIMPLE,       LEVEL_MAIN },
+	{ "month",        "DATE:MONTH", SIMPLE,       LEVEL_MAIN },
+	{ "day",          "DATE:DAY",   SIMPLE,       LEVEL_MAIN },
+	{ "number",       "NUMBER",     SIMPLE,       LEVEL_MAIN },
+	{ "isbn",         "ISBN",       SIMPLE,       LEVEL_MAIN },
+	{ "lccn",         "LCCN",       SIMPLE,       LEVEL_MAIN },
+	{ "abstract",     "ABSTRACT",   SIMPLE,       LEVEL_MAIN },
+	{ "contents",     "CONTENTS",   SIMPLE,       LEVEL_MAIN },
+	{ "language",     "LANGUAGE",   SIMPLE,       LEVEL_MAIN },
+	{ "location",     "LOCATION",   SIMPLE,       LEVEL_MAIN },
+	{ "note",         "NOTES",      NOTES,        LEVEL_MAIN },
+	{ "annote",       "ANNOTE",     SIMPLE,       LEVEL_MAIN },
+	{ "key",          "BIBKEY",     SIMPLE,       LEVEL_MAIN },
+	{ "doi",          "DOI",        SIMPLE,       LEVEL_MAIN },
+	{ "ftp",          "",           URL,          LEVEL_MAIN },
+	{ "url",          "",           URL,          LEVEL_MAIN },
+	{ "mrnumber",     "MRNUMBER",   SIMPLE,       LEVEL_MAIN },
+	{ "pdf",          "FILEATTACH", SIMPLE,       LEVEL_MAIN },
+	{ "sentelink",    "FILEATTACH", BT_SENTE,     LEVEL_MAIN },
+	{ "file",         "FILEATTACH", LINKEDFILE,   LEVEL_MAIN },
+	{ "howpublished", "",           HOWPUBLISHED, LEVEL_MAIN },
+	{ "refnum",       "REFNUM",     SIMPLE,       LEVEL_MAIN },
+	{ "crossref",     "CROSSREF",   SIMPLE,       LEVEL_MAIN },
+	{ "type",         "GENRE",      SIMPLE,       LEVEL_MAIN },
+	{ "keywords",     "KEYWORD",    KEYWORD,      LEVEL_MAIN },
 	{ "",         "INTERNAL_TYPE|REPORT", ALWAYS, LEVEL_MAIN },
 	{ "",         "RESOURCE|text",        ALWAYS, LEVEL_MAIN },
 	{ "",         "GENRE|report",         ALWAYS, LEVEL_MAIN }
@@ -145,27 +151,27 @@ static lookups report[] = {
 static lookups manual[] = {
 	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN },
 	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },
-	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },
-	{ "booktitle", "TITLE",     TITLE,  LEVEL_MAIN },
+	{ "title",     "",     TITLE,  LEVEL_MAIN },
+	{ "booktitle", "",     TITLE,  LEVEL_MAIN },
 	{ "editor",    "EDITOR",    PERSON, LEVEL_MAIN },
 	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_MAIN },
 	{ "organization", "ORGANIZER:CORP", BT_ORG, LEVEL_MAIN },
 	{ "address",   "ADDRESS",   SIMPLE, LEVEL_MAIN },
-	{ "year",      "YEAR",      SIMPLE, LEVEL_MAIN },
-	{ "month",     "MONTH",     SIMPLE, LEVEL_MAIN },
-	{ "day",       "DAY",       SIMPLE, LEVEL_MAIN },
+	{ "year",      "DATE:YEAR",      SIMPLE, LEVEL_MAIN },
+	{ "month",     "DATE:MONTH",     SIMPLE, LEVEL_MAIN },
+	{ "day",       "DATE:DAY",       SIMPLE, LEVEL_MAIN },
 	{ "isbn",      "ISBN",      SIMPLE, LEVEL_MAIN },
 	{ "lccn",      "LCCN",      SIMPLE, LEVEL_MAIN },
 	{ "edition",   "EDITION",   SIMPLE, LEVEL_MAIN },
 	{ "abstract",  "ABSTRACT",  SIMPLE, LEVEL_MAIN },
 	{ "contents",  "CONTENTS",  SIMPLE, LEVEL_MAIN },
 	{ "location",     "LOCATION",     SIMPLE, LEVEL_MAIN },
-	{ "note",         "NOTES",        BT_NOTE, LEVEL_MAIN },
+	{ "note",         "NOTES",        NOTES,   LEVEL_MAIN },
 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },
 	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN },
 	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },
-	{ "ftp",       "",       BT_URL, LEVEL_MAIN },
-	{ "url",       "",       BT_URL, LEVEL_MAIN },
+	{ "ftp",       "",       URL,    LEVEL_MAIN },
+	{ "url",       "",       URL,    LEVEL_MAIN },
 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
 	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },
 	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
@@ -182,65 +188,65 @@ static lookups manual[] = {
 /* Part of a book (e.g. chapter or section) */
 
 static lookups inbook[] = {
-	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN },
+	{ "author",       "AUTHOR",    PERSON, LEVEL_MAIN },
 	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },
-	{ "editor",    "EDITOR",    PERSON, LEVEL_HOST },
-	{ "chapter",   "CHAPTER",   SIMPLE, LEVEL_MAIN },
-	{ "title",     "TITLE",     TITLE,  LEVEL_HOST },
-	{ "booktitle", "TITLE",     TITLE,  LEVEL_HOST },
-	{ "series",    "TITLE",     TITLE,  LEVEL_SERIES },
-	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_HOST },
-	{ "address",   "ADDRESS",   SIMPLE, LEVEL_HOST },
-	{ "year",      "YEAR",      SIMPLE, LEVEL_HOST },
-	{ "month",     "MONTH",     SIMPLE, LEVEL_HOST },
-	{ "day",       "DAY",       SIMPLE, LEVEL_HOST },
-	{ "volume",    "VOLUME",    SIMPLE, LEVEL_SERIES },
-	{ "number",    "NUMBER",    SIMPLE, LEVEL_SERIES },
-	{ "pages",     "PAGES",     PAGES,  LEVEL_HOST },
-	{ "isbn",      "ISBN",      SIMPLE, LEVEL_HOST },
-	{ "lccn",      "LCCN",      SIMPLE, LEVEL_HOST },
-	{ "edition",   "EDITION",   SIMPLE, LEVEL_HOST },
-	{ "abstract",  "ABSTRACT",  SIMPLE, LEVEL_MAIN },
-	{ "contents",  "CONTENTS",  SIMPLE, LEVEL_HOST },
-	{ "language",     "LANGUAGE",     SIMPLE, LEVEL_MAIN },
-	{ "location",     "LOCATION",     SIMPLE, LEVEL_HOST },
-	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },
-	{ "ftp",       "",       BT_URL, LEVEL_MAIN },
-	{ "url",       "",       BT_URL, LEVEL_MAIN },
+	{ "editor",       "EDITOR",    PERSON, LEVEL_HOST },
+	{ "chapter",      "CHAPTER",   SIMPLE, LEVEL_MAIN },   /* chapter number */
+	{ "title",        "",          TITLE,  LEVEL_MAIN },   /* chapter name */
+	{ "booktitle",    "",          TITLE,  LEVEL_HOST },
+	{ "series",       "",          TITLE,  LEVEL_SERIES },
+	{ "publisher",    "PUBLISHER", SIMPLE, LEVEL_HOST },
+	{ "address",      "ADDRESS",   SIMPLE, LEVEL_HOST },
+	{ "year",         "DATE:YEAR", SIMPLE, LEVEL_HOST },
+	{ "month",        "DATE:MONTH",SIMPLE, LEVEL_HOST },
+	{ "day",          "DATE:DAY",  SIMPLE, LEVEL_HOST },
+	{ "volume",       "VOLUME",    SIMPLE, LEVEL_SERIES },
+	{ "number",       "NUMBER",    SIMPLE, LEVEL_SERIES },
+	{ "pages",        "PAGES",     PAGES,  LEVEL_HOST },
+	{ "isbn",         "ISBN",      SIMPLE, LEVEL_HOST },
+	{ "lccn",         "LCCN",      SIMPLE, LEVEL_HOST },
+	{ "edition",      "EDITION",   SIMPLE, LEVEL_HOST },
+	{ "abstract",     "ABSTRACT",  SIMPLE, LEVEL_MAIN },
+	{ "contents",     "CONTENTS",  SIMPLE, LEVEL_HOST },
+	{ "language",     "LANGUAGE",  SIMPLE, LEVEL_MAIN },
+	{ "location",     "LOCATION",  SIMPLE, LEVEL_HOST },
+	{ "doi",          "DOI",       SIMPLE, LEVEL_MAIN },
+	{ "ftp",          "",          URL,    LEVEL_MAIN },
+	{ "url",          "",          URL,    LEVEL_MAIN },
 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
 	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },
 	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },
-	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },
+	{ "refnum",       "REFNUM",    SIMPLE, LEVEL_MAIN },
 	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
-	{ "type",      "GENRE",      SIMPLE, LEVEL_MAIN },
-	{ "note",         "NOTES",        BT_NOTE, LEVEL_MAIN },
+	{ "type",         "GENRE",      SIMPLE, LEVEL_MAIN },
+	{ "note",         "NOTES",        NOTES,   LEVEL_MAIN },
 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },
 	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN },
 	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
-	{ "",         "INTERNAL_TYPE|INBOOK", ALWAYS, LEVEL_MAIN },
-	{ "",         "RESOURCE|text",        ALWAYS, LEVEL_MAIN },
-	{ "",         "ISSUANCE|monographic", ALWAYS, LEVEL_HOST },
-	{ "",         "NGENRE|book chapter",  ALWAYS, LEVEL_MAIN },
-	{ "",         "GENRE|book",           ALWAYS, LEVEL_HOST }
+	{ "",             "INTERNAL_TYPE|INBOOK", ALWAYS, LEVEL_MAIN },
+	{ "",             "RESOURCE|text",        ALWAYS, LEVEL_MAIN },
+	{ "",             "ISSUANCE|monographic", ALWAYS, LEVEL_HOST },
+	{ "",             "NGENRE|book chapter",  ALWAYS, LEVEL_MAIN },
+	{ "",             "GENRE|book",           ALWAYS, LEVEL_HOST }
 };
 
 /* References of papers in conference proceedings */
 
 static lookups inproceedings[] = {
-	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN },
-	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },
-	{ "editor",    "EDITOR",    PERSON, LEVEL_HOST },
-	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },
-	{ "booktitle", "TITLE",     TITLE,  LEVEL_HOST },
-	{ "series",    "TITLE",     TITLE,  LEVEL_SERIES },
-	{ "chapter",   "CHAPTER",   SIMPLE, LEVEL_MAIN },
-	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_HOST },
+	{ "author",     "AUTHOR",     PERSON, LEVEL_MAIN },
+	{ "translator", "TRANSLATOR", PERSON, LEVEL_MAIN },
+	{ "editor",     "EDITOR",     PERSON, LEVEL_HOST },
+	{ "chapter",    "CHAPTER",    SIMPLE, LEVEL_MAIN },   /* chapter number */
+	{ "title",      "",           TITLE,  LEVEL_MAIN },   /* chapter name */
+	{ "booktitle",  "",           TITLE,  LEVEL_HOST },
+	{ "series",     "",           TITLE,  LEVEL_SERIES },
+	{ "publisher",  "PUBLISHER",  SIMPLE, LEVEL_HOST },
 	{ "organization", "ORGANIZER:CORP", BT_ORG, LEVEL_HOST },
 	{ "address",   "ADDRESS",   SIMPLE, LEVEL_HOST },
-	{ "year",      "PARTYEAR",  SIMPLE, LEVEL_MAIN },
-	{ "month",     "PARTMONTH", SIMPLE, LEVEL_MAIN },
-	{ "day",       "PARTDAY",   SIMPLE, LEVEL_MAIN },
+	{ "year",      "PARTDATE:YEAR",  SIMPLE, LEVEL_MAIN },
+	{ "month",     "PARTDATE:MONTH", SIMPLE, LEVEL_MAIN },
+	{ "day",       "PARTDATE:DAY",   SIMPLE, LEVEL_MAIN },
 	{ "volume",    "VOLUME",    SIMPLE, LEVEL_MAIN },
 	{ "number",    "NUMBER",    SIMPLE, LEVEL_MAIN },
 	{ "pages",     "PAGES",     PAGES,  LEVEL_MAIN },
@@ -252,13 +258,13 @@ static lookups inproceedings[] = {
 	{ "paper",     "PAPER",     SIMPLE, LEVEL_MAIN },
 	{ "location",     "LOCATION",     SIMPLE, LEVEL_HOST },
 	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },
-	{ "ftp",       "",       BT_URL, LEVEL_MAIN },
-	{ "url",       "",       BT_URL, LEVEL_MAIN },
+	{ "ftp",       "",          URL,    LEVEL_MAIN },
+	{ "url",       "",          URL,    LEVEL_MAIN },
 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
 	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },
 	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "type",      "GENRE",      SIMPLE, LEVEL_MAIN },
-	{ "note",         "NOTES",        BT_NOTE, LEVEL_MAIN },
+	{ "note",         "NOTES",        NOTES,   LEVEL_MAIN },
 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },
 	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN },
 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },
@@ -273,18 +279,18 @@ static lookups inproceedings[] = {
 /* Used for a section of a book with its own title */
 
 static lookups incollection[] = {
-	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN },
-	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },
-	{ "editor",    "EDITOR",    PERSON, LEVEL_HOST },
-	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },
-	{ "chapter",   "CHAPTER",   SIMPLE, LEVEL_MAIN },
-	{ "booktitle", "TITLE",     TITLE,  LEVEL_HOST },
-	{ "series",    "TITLE",     TITLE,  LEVEL_SERIES },
-	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_HOST },
+	{ "author",     "AUTHOR",     PERSON, LEVEL_MAIN },
+	{ "translator", "TRANSLATOR", PERSON, LEVEL_MAIN },
+	{ "editor",     "EDITOR",     PERSON, LEVEL_HOST },
+	{ "chapter",    "CHAPTER",    SIMPLE, LEVEL_MAIN },   /* chapter number */
+	{ "title",      "",           TITLE,  LEVEL_MAIN },   /* chapter name */
+	{ "booktitle",  "",           TITLE,  LEVEL_HOST },
+	{ "series",     "",           TITLE,  LEVEL_SERIES },
+	{ "publisher",  "PUBLISHER",  SIMPLE, LEVEL_HOST },
 	{ "address",   "ADDRESS",   SIMPLE, LEVEL_HOST },
-	{ "year",      "YEAR",      SIMPLE, LEVEL_HOST },
-	{ "month",     "MONTH",     SIMPLE, LEVEL_HOST },
-	{ "day",       "DAY",       SIMPLE, LEVEL_HOST },
+	{ "year",      "DATE:YEAR",      SIMPLE, LEVEL_HOST },
+	{ "month",     "DATE:MONTH",     SIMPLE, LEVEL_HOST },
+	{ "day",       "DATE:DAY",       SIMPLE, LEVEL_HOST },
 	{ "volume",    "VOLUME",    SIMPLE, LEVEL_MAIN },
 	{ "number",    "NUMBER",    SIMPLE, LEVEL_MAIN },
 	{ "pages",     "PAGES",     PAGES,  LEVEL_MAIN },
@@ -293,17 +299,17 @@ static lookups incollection[] = {
 	{ "edition",   "EDITION",   SIMPLE, LEVEL_HOST },
 	{ "abstract",  "ABSTRACT",  SIMPLE, LEVEL_MAIN },
 	{ "contents",  "CONTENTS",  SIMPLE, LEVEL_HOST },
-	{ "language",     "LANGUAGE",     SIMPLE, LEVEL_MAIN },
-	{ "type",      "GENRE",      SIMPLE, LEVEL_MAIN },
-	{ "note",         "NOTES",        BT_NOTE, LEVEL_MAIN },
-	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },
-	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN },
+	{ "language",  "LANGUAGE",  SIMPLE, LEVEL_MAIN },
+	{ "type",      "GENRE",     SIMPLE, LEVEL_MAIN },
+	{ "note",      "NOTES",     NOTES,  LEVEL_MAIN },
+	{ "annote",    "ANNOTE",    SIMPLE, LEVEL_MAIN },
+	{ "key",       "BIBKEY",    SIMPLE, LEVEL_MAIN },
 	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },
-	{ "ftp",       "",       BT_URL, LEVEL_MAIN },
-	{ "url",       "",       BT_URL, LEVEL_MAIN },
-	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
-	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
+	{ "ftp",       "",          URL,    LEVEL_MAIN },
+	{ "url",       "",          URL,    LEVEL_MAIN },
+	{ "pdf",       "FILEATTACH",SIMPLE, LEVEL_MAIN },
+	{ "sentelink", "FILEATTACH",BT_SENTE, LEVEL_MAIN },
+	{ "file",      "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "location",     "LOCATION",     SIMPLE, LEVEL_HOST },
 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },
 	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },
@@ -321,15 +327,15 @@ static lookups proceedings[] = {
 	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN },
 	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "editor",    "EDITOR",    PERSON, LEVEL_MAIN },
-	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },
-	{ "booktitle", "TITLE",     TITLE,  LEVEL_MAIN },
-	{ "series",    "TITLE",     TITLE,  LEVEL_HOST },
+	{ "title",     "",     TITLE,  LEVEL_MAIN },
+	{ "booktitle", "",     TITLE,  LEVEL_MAIN },
+	{ "series",    "",     TITLE,  LEVEL_HOST },
 	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_MAIN },
 	{ "organization", "ORGANIZER:CORP", BT_ORG, LEVEL_MAIN },
 	{ "address",   "ADDRESS",   SIMPLE, LEVEL_MAIN },
-	{ "year",      "YEAR",      SIMPLE, LEVEL_MAIN },
-	{ "month",     "MONTH",     SIMPLE, LEVEL_MAIN },
-	{ "day",       "DAY",       SIMPLE, LEVEL_MAIN },
+	{ "year",      "DATE:YEAR",      SIMPLE, LEVEL_MAIN },
+	{ "month",     "DATE:MONTH",     SIMPLE, LEVEL_MAIN },
+	{ "day",       "DATE:DAY",       SIMPLE, LEVEL_MAIN },
 	{ "volume",    "VOLUME",    SIMPLE, LEVEL_MAIN },
 	{ "number",    "NUMBER",    SIMPLE, LEVEL_MAIN },
 	{ "pages",     "PAGES",     PAGES,  LEVEL_MAIN },
@@ -338,15 +344,15 @@ static lookups proceedings[] = {
 	{ "abstract",  "ABSTRACT",  SIMPLE, LEVEL_MAIN },
 	{ "contents",  "CONTENTS",  SIMPLE, LEVEL_MAIN },
 	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },
-	{ "ftp",       "",       BT_URL, LEVEL_MAIN },
-	{ "url",       "",       BT_URL, LEVEL_MAIN },
+	{ "ftp",       "",          URL,    LEVEL_MAIN },
+	{ "url",       "",          URL,    LEVEL_MAIN },
 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
 	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },
 	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "language",     "LANGUAGE",     SIMPLE, LEVEL_MAIN },
 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },
 	{ "location",     "LOCATION",     SIMPLE, LEVEL_MAIN },
-	{ "note",         "NOTES",        BT_NOTE, LEVEL_MAIN },
+	{ "note",         "NOTES",        NOTES,   LEVEL_MAIN },
 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },
 	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN },
 	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },
@@ -360,24 +366,24 @@ static lookups proceedings[] = {
 static lookups phds[] = {
 	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN },
 	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },
-	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },
-	{ "year",      "YEAR",      SIMPLE, LEVEL_MAIN },
-	{ "month",     "MONTH",     SIMPLE, LEVEL_MAIN },
-	{ "day",       "DAY",       SIMPLE, LEVEL_MAIN },
+	{ "title",     "",     TITLE,  LEVEL_MAIN },
+	{ "year",      "DATE:YEAR",      SIMPLE, LEVEL_MAIN },
+	{ "month",     "DATE:MONTH",     SIMPLE, LEVEL_MAIN },
+	{ "day",       "DATE:DAY",       SIMPLE, LEVEL_MAIN },
 	{ "school",    "DEGREEGRANTOR:ASIS",SIMPLE, LEVEL_MAIN },
 	{ "address",   "ADDRESS",   SIMPLE, LEVEL_MAIN },
 	{ "abstract",  "ABSTRACT",  SIMPLE, LEVEL_MAIN },
 	{ "contents",  "CONTENTS",  SIMPLE, LEVEL_MAIN },
 	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },
-	{ "ftp",       "",       BT_URL, LEVEL_MAIN },
-	{ "url",       "",       BT_URL, LEVEL_MAIN },
+	{ "ftp",       "",          URL,    LEVEL_MAIN },
+	{ "url",       "",          URL,    LEVEL_MAIN },
 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
 	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },
 	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "howpublished", "" ,   HOWPUBLISHED, LEVEL_MAIN },
 	{ "language",     "LANGUAGE",     SIMPLE, LEVEL_MAIN },
 	{ "location",     "LOCATION",     SIMPLE, LEVEL_MAIN },
-	{ "note",         "NOTES",        BT_NOTE, LEVEL_MAIN },
+	{ "note",         "NOTES",        NOTES,   LEVEL_MAIN },
 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },
 	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN },
 	{ "type",         "GENRE",         SIMPLE, LEVEL_MAIN },
@@ -393,23 +399,23 @@ static lookups phds[] = {
 static lookups masters[] = {
 	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN },
 	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },
-	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },
-	{ "year",      "YEAR",      SIMPLE, LEVEL_MAIN },
-	{ "month",     "MONTH",     SIMPLE, LEVEL_MAIN },
-	{ "day",       "DAY",       SIMPLE, LEVEL_MAIN },
+	{ "title",     "",     TITLE,  LEVEL_MAIN },
+	{ "year",      "DATE:YEAR",      SIMPLE, LEVEL_MAIN },
+	{ "month",     "DATE:MONTH",     SIMPLE, LEVEL_MAIN },
+	{ "day",       "DATE:DAY",       SIMPLE, LEVEL_MAIN },
 	{ "school",    "DEGREEGRANTOR:ASIS",SIMPLE, LEVEL_MAIN },
 	{ "address",   "ADDRESS",   SIMPLE, LEVEL_MAIN },
 	{ "abstract",  "ABSTRACT",  SIMPLE, LEVEL_MAIN },
 	{ "contents",  "CONTENTS",  SIMPLE, LEVEL_MAIN },
 	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },
-	{ "ftp",       "",       BT_URL, LEVEL_MAIN },
-	{ "url",       "",       BT_URL, LEVEL_MAIN },
+	{ "ftp",       "",          URL,   LEVEL_MAIN },
+	{ "url",       "",          URL,   LEVEL_MAIN },
 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
 	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },
 	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "language",     "LANGUAGE",     SIMPLE, LEVEL_MAIN },
 	{ "location",     "LOCATION",     SIMPLE, LEVEL_MAIN },
-	{ "note",         "NOTES",        BT_NOTE, LEVEL_MAIN },
+	{ "note",         "NOTES",        NOTES,   LEVEL_MAIN },
 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },
 	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN },
 	{ "type",         "GENRE",         SIMPLE, LEVEL_MAIN },
@@ -428,26 +434,26 @@ static lookups masters[] = {
 static lookups unpublished[] = {
 	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN },
 	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },
-	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },
-	{ "booktitle", "TITLE",     TITLE,  LEVEL_MAIN },
+	{ "title",     "",     TITLE,  LEVEL_MAIN },
+	{ "booktitle", "",     TITLE,  LEVEL_MAIN },
 	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_MAIN },
 	{ "address",   "ADDRESS",   SIMPLE, LEVEL_MAIN },
 	{ "editor",    "EDITOR",    PERSON, LEVEL_MAIN },
-	{ "year",      "YEAR",      SIMPLE, LEVEL_MAIN },
-	{ "month",     "MONTH",     SIMPLE, LEVEL_MAIN },
-	{ "day",       "DAY",       SIMPLE, LEVEL_MAIN },
+	{ "year",      "DATE:YEAR",      SIMPLE, LEVEL_MAIN },
+	{ "month",     "DATE:MONTH",     SIMPLE, LEVEL_MAIN },
+	{ "day",       "DATE:DAY",       SIMPLE, LEVEL_MAIN },
 	{ "abstract",  "ABSTRACT",  SIMPLE, LEVEL_MAIN },
 	{ "contents",  "CONTENTS",  SIMPLE, LEVEL_MAIN },
 	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },
-	{ "ftp",       "",       BT_URL, LEVEL_MAIN },
-	{ "url",       "",       BT_URL, LEVEL_MAIN },
+	{ "ftp",       "",          URL,    LEVEL_MAIN },
+	{ "url",       "",          URL,    LEVEL_MAIN },
 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
 	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },
 	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "language",     "LANGUAGE",     SIMPLE, LEVEL_MAIN },
 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },
 	{ "location",     "LOCATION",     SIMPLE, LEVEL_MAIN },
-	{ "note",         "NOTES",        BT_NOTE, LEVEL_MAIN },
+	{ "note",         "NOTES",        NOTES,   LEVEL_MAIN },
 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },
 	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN },
 	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },
@@ -466,32 +472,32 @@ static lookups standard[] = {
 	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "organization", "ORGANIZER:CORP", BT_ORG, LEVEL_MAIN },
 	{ "institution", "AUTHOR:CORP", SIMPLE, LEVEL_MAIN },
-	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },
-	{ "booktitle", "TITLE",     TITLE,  LEVEL_MAIN },
-	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_MAIN },
-	{ "address",   "ADDRESS",   SIMPLE, LEVEL_MAIN },
-	{ "editor",    "EDITOR",    PERSON, LEVEL_MAIN },
-	{ "year",      "YEAR",      SIMPLE, LEVEL_MAIN },
-	{ "month",     "MONTH",     SIMPLE, LEVEL_MAIN },
-	{ "day",       "DAY",       SIMPLE, LEVEL_MAIN },
-	{ "isbn",      "ISBN",      SIMPLE, LEVEL_MAIN },
-	{ "lccn",      "LCCN",      SIMPLE, LEVEL_MAIN },
-	{ "abstract",  "ABSTRACT",  SIMPLE, LEVEL_MAIN },
-	{ "contents",  "CONTENTS",  SIMPLE, LEVEL_MAIN },
-	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },
-	{ "ftp",       "",      BT_URL, LEVEL_MAIN },
-	{ "url",       "",      BT_URL, LEVEL_MAIN },
-	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
-	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },
+	{ "title",     "",           TITLE,    LEVEL_MAIN },
+	{ "booktitle", "",           TITLE,    LEVEL_MAIN },
+	{ "publisher", "PUBLISHER",  SIMPLE,   LEVEL_MAIN },
+	{ "address",   "ADDRESS",    SIMPLE,   LEVEL_MAIN },
+	{ "editor",    "EDITOR",     PERSON,   LEVEL_MAIN },
+	{ "year",      "DATE:YEAR",  SIMPLE,   LEVEL_MAIN },
+	{ "month",     "DATE:MONTH", SIMPLE,   LEVEL_MAIN },
+	{ "day",       "DATE:DAY",   SIMPLE,   LEVEL_MAIN },
+	{ "isbn",      "ISBN",       SIMPLE,   LEVEL_MAIN },
+	{ "lccn",      "LCCN",       SIMPLE,   LEVEL_MAIN },
+	{ "abstract",  "ABSTRACT",   SIMPLE,   LEVEL_MAIN },
+	{ "contents",  "CONTENTS",   SIMPLE,   LEVEL_MAIN },
+	{ "doi",       "DOI",        SIMPLE,   LEVEL_MAIN },
+	{ "ftp",       "",           URL,      LEVEL_MAIN },
+	{ "url",       "",           URL,      LEVEL_MAIN },
+	{ "pdf",       "FILEATTACH", SIMPLE,   LEVEL_MAIN },
+	{ "sentelink", "FILEATTACH", BT_SENTE, LEVEL_MAIN },
 	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },
 	{ "language",     "LANGUAGE",     SIMPLE, LEVEL_MAIN },
 	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },
 	{ "type",      "GENRE",      SIMPLE, LEVEL_MAIN },
-	{ "number",    "NUMBER",      TITLE,  LEVEL_MAIN },
-	{ "revision",  "REVISION",    TITLE,  LEVEL_MAIN },
+	{ "number",    "NUMBER",      SIMPLE,  LEVEL_MAIN },
+	{ "revision",  "EDITION",    SIMPLE,  LEVEL_MAIN },
 	{ "location",     "LOCATION",     SIMPLE, LEVEL_MAIN },
-	{ "note",         "NOTES",        BT_NOTE, LEVEL_MAIN },
+	{ "note",         "NOTES",        NOTES,   LEVEL_MAIN },
 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },
 	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN },
 	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
@@ -504,30 +510,31 @@ static lookups standard[] = {
  * For Journals and Magazines
  */
 static lookups periodical[] = {
-	{ "title",        "TITLE",       TITLE,  LEVEL_MAIN },
-	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },
-	{ "series",       "TITLE",       TITLE,  LEVEL_HOST },
+	{ "title",        "",            TITLE,  LEVEL_MAIN },
+	{ "translator",   "TRANSLATOR",  PERSON, LEVEL_MAIN },
+	{ "series",       "",            TITLE,  LEVEL_HOST },
 	{ "publisher",    "PUBLISHER",   SIMPLE, LEVEL_MAIN },
 	{ "address",      "ADDRESS",     SIMPLE, LEVEL_MAIN },
 	{ "editor",       "EDITOR",      PERSON, LEVEL_MAIN },
-	{ "year",         "YEAR",        SIMPLE, LEVEL_MAIN },
-	{ "month",        "MONTH",       SIMPLE, LEVEL_MAIN },
-	{ "day",          "DAY",         SIMPLE, LEVEL_MAIN },
+	{ "year",         "DATE:YEAR",   SIMPLE, LEVEL_MAIN },
+	{ "month",        "DATE:MONTH",  SIMPLE, LEVEL_MAIN },
+	{ "day",          "DATE:DAY",    SIMPLE, LEVEL_MAIN },
 	{ "issn",         "ISSN",        SIMPLE, LEVEL_MAIN },
+	{ "coden",        "CODEN",       SIMPLE, LEVEL_MAIN },
 	{ "abstract",     "ABSTRACT",    SIMPLE, LEVEL_MAIN },
-	{ "volume",       "VOLUME",      TITLE,  LEVEL_MAIN },
-	{ "number",       "NUMBER",      TITLE,  LEVEL_MAIN },
+	{ "volume",       "VOLUME",      SIMPLE, LEVEL_MAIN },
+	{ "number",       "NUMBER",      SIMPLE, LEVEL_MAIN },
 	{ "contents",     "CONTENTS",    SIMPLE, LEVEL_MAIN },
 	{ "doi",          "DOI",         SIMPLE, LEVEL_MAIN },
-	{ "ftp",          "",        BT_URL, LEVEL_MAIN },
-	{ "url",          "",        BT_URL, LEVEL_MAIN },
-	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
-	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
-	{ "howpublished", "",         HOWPUBLISHED, LEVEL_MAIN },
+	{ "ftp",          "",            URL,    LEVEL_MAIN },
+	{ "url",          "",            URL,    LEVEL_MAIN },
+	{ "pdf",          "FILEATTACH",  SIMPLE, LEVEL_MAIN },
+	{ "sentelink",    "FILEATTACH",  BT_SENTE, LEVEL_MAIN },
+	{ "file",         "FILEATTACH",  LINKEDFILE,   LEVEL_MAIN },
+	{ "howpublished", "",            HOWPUBLISHED, LEVEL_MAIN },
 	{ "refnum",       "REFNUM",      SIMPLE, LEVEL_MAIN },
 	{ "language",     "LANGUAGE",    SIMPLE, LEVEL_MAIN },
-	{ "note",         "NOTES",       BT_NOTE, LEVEL_MAIN },
+	{ "note",         "NOTES",       NOTES,   LEVEL_MAIN },
 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },
 	{ "organization", "ORGANIZER:CORP", BT_ORG, LEVEL_MAIN },
 	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
@@ -540,38 +547,38 @@ static lookups periodical[] = {
  * For Patent
  */
 static lookups patent[] = {
-	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN },
-	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },
-	{ "assignee",  "ASSIGNEE",  PERSON, LEVEL_MAIN },
-	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },
-	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_MAIN },
-	{ "address",   "ADDRESS",   SIMPLE, LEVEL_MAIN },
-	{ "editor",    "EDITOR",    PERSON, LEVEL_MAIN },
-	{ "year",      "YEAR",      SIMPLE, LEVEL_MAIN }, /* date granted */
-	{ "month",     "MONTH",     SIMPLE, LEVEL_MAIN },
-	{ "day",       "DAY",       SIMPLE, LEVEL_MAIN },
-	{ "yearfiled", "YEAR",      SIMPLE, LEVEL_MAIN }, /* date filed */
-	{ "monthfiled","MONTH",     SIMPLE, LEVEL_MAIN },
-	{ "dayfiled",  "DAY",       SIMPLE, LEVEL_MAIN },
-	{ "abstract",  "ABSTRACT",  SIMPLE, LEVEL_MAIN },
-	{ "contents",  "CONTENTS",  SIMPLE, LEVEL_MAIN },
-	{ "language",  "LANGUAGE",  SIMPLE, LEVEL_MAIN },
-	{ "location",  "LOCATION",  SIMPLE, LEVEL_MAIN },
-	{ "nationality", "NATIONALITY", SIMPLE, LEVEL_MAIN },
-	{ "note",      "NOTES",     BT_NOTE, LEVEL_MAIN },
-	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },
-	{ "key",       "BIBKEY",       SIMPLE, LEVEL_MAIN },
-	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },
-	{ "ftp",       "",      BT_URL, LEVEL_MAIN },
-	{ "url",       "",      BT_URL, LEVEL_MAIN },
-	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
-	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
-	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },
-	{ "type",       "GENRE",     SIMPLE, LEVEL_MAIN },
-	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },
-	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
-	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
+	{ "author",       "AUTHOR",      PERSON,       LEVEL_MAIN },
+	{ "translator",   "TRANSLATOR",  PERSON,       LEVEL_MAIN },
+	{ "assignee",     "ASSIGNEE",    PERSON,       LEVEL_MAIN },
+	{ "title",        "",            TITLE,        LEVEL_MAIN },
+	{ "publisher",    "PUBLISHER",   SIMPLE,       LEVEL_MAIN },
+	{ "address",      "ADDRESS",     SIMPLE,       LEVEL_MAIN },
+	{ "editor",       "EDITOR",      PERSON,       LEVEL_MAIN },
+	{ "year",         "DATE:YEAR",   SIMPLE,       LEVEL_MAIN }, /* date granted */
+	{ "month",        "DATE:MONTH",  SIMPLE,       LEVEL_MAIN },
+	{ "day",          "DATE:DAY",    SIMPLE,       LEVEL_MAIN },
+	{ "yearfiled",    "DATE:YEAR",   SIMPLE,       LEVEL_MAIN }, /* date filed */
+	{ "monthfiled",   "DATE:MONTH",  SIMPLE,       LEVEL_MAIN },
+	{ "dayfiled",     "DATE:DAY",    SIMPLE,       LEVEL_MAIN },
+	{ "abstract",     "ABSTRACT",    SIMPLE,       LEVEL_MAIN },
+	{ "contents",     "CONTENTS",    SIMPLE,       LEVEL_MAIN },
+	{ "language",     "LANGUAGE",    SIMPLE,       LEVEL_MAIN },
+	{ "location",     "LOCATION",    SIMPLE,       LEVEL_MAIN },
+	{ "nationality",  "NATIONALITY", SIMPLE,       LEVEL_MAIN },
+	{ "note",         "NOTES",       NOTES,        LEVEL_MAIN },
+	{ "annote",       "ANNOTE",      SIMPLE,       LEVEL_MAIN },
+	{ "key",          "BIBKEY",      SIMPLE,       LEVEL_MAIN },
+	{ "doi",          "DOI",         SIMPLE,       LEVEL_MAIN },
+	{ "ftp",          "",            URL,          LEVEL_MAIN },
+	{ "url",          "",            URL,          LEVEL_MAIN },
+	{ "pdf",          "FILEATTACH",  SIMPLE,       LEVEL_MAIN },
+	{ "sentelink",    "FILEATTACH",  BT_SENTE,     LEVEL_MAIN },
+	{ "file",         "FILEATTACH",  LINKEDFILE,   LEVEL_MAIN },
+	{ "howpublished", "",            HOWPUBLISHED, LEVEL_MAIN },
+	{ "type",         "GENRE",       SIMPLE,       LEVEL_MAIN },
+	{ "refnum",       "REFNUM",      SIMPLE,       LEVEL_MAIN },
+	{ "crossref",     "CROSSREF",    SIMPLE,       LEVEL_MAIN },
+	{ "keywords",     "KEYWORD",     KEYWORD,      LEVEL_MAIN },
 	{ "",         "RESOURCE|text",        ALWAYS, LEVEL_MAIN },
 	{ "",         "INTERNAL_TYPE|PATENT", ALWAYS, LEVEL_MAIN },
 	{ "",         "GENRE|patent",         ALWAYS, LEVEL_MAIN },
@@ -581,70 +588,70 @@ static lookups patent[] = {
  * Electronic Source
  */
 static lookups electronic[] = {
-	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN },
-	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },
-	{ "organization", "ORGANIZER:CORP", BT_ORG, LEVEL_MAIN },
-	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },
-	{ "booktitle", "TITLE",     TITLE,  LEVEL_MAIN },
-	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_MAIN },
-	{ "address",   "ADDRESS",   SIMPLE, LEVEL_MAIN },
-	{ "editor",    "EDITOR",    PERSON, LEVEL_MAIN },
-	{ "year",      "YEAR",      SIMPLE, LEVEL_MAIN },
-	{ "month",     "MONTH",     SIMPLE, LEVEL_MAIN },
-	{ "day",       "DAY",       SIMPLE, LEVEL_MAIN },
-	{ "abstract",  "ABSTRACT",  SIMPLE, LEVEL_MAIN },
-	{ "volume",    "VOLUME",    SIMPLE, LEVEL_MAIN },
-	{ "contents",  "CONTENTS",  SIMPLE, LEVEL_MAIN },
-	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },
-	{ "ftp",       "",      BT_URL, LEVEL_MAIN },
-	{ "url",       "",      BT_URL, LEVEL_MAIN },
-	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
-	{ "sentelink",    "FILEATTACH",BT_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
-	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },
-	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },
-	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
-	{ "location",  "LOCATION",  SIMPLE, LEVEL_MAIN },
-	{ "note",      "NOTES",     BT_NOTE, LEVEL_MAIN },
-	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },
-	{ "key",       "BIBKEY",       SIMPLE, LEVEL_MAIN },
-	{ "language",  "LANGUAGE",  SIMPLE, LEVEL_MAIN },
-	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
+	{ "author",       "AUTHOR",         PERSON,       LEVEL_MAIN },
+	{ "translator",   "TRANSLATOR",     PERSON,       LEVEL_MAIN },
+	{ "organization", "ORGANIZER:CORP", BT_ORG,       LEVEL_MAIN },
+	{ "title",        "",               TITLE,        LEVEL_MAIN },
+	{ "booktitle",    "",               TITLE,        LEVEL_MAIN },
+	{ "publisher",    "PUBLISHER",      SIMPLE,       LEVEL_MAIN },
+	{ "address",      "ADDRESS",        SIMPLE,       LEVEL_MAIN },
+	{ "editor",       "EDITOR",         PERSON,       LEVEL_MAIN },
+	{ "year",         "DATE:YEAR",      SIMPLE,       LEVEL_MAIN },
+	{ "month",        "DATE:MONTH",     SIMPLE,       LEVEL_MAIN },
+	{ "day",          "DATE:DAY",       SIMPLE,       LEVEL_MAIN },
+	{ "abstract",     "ABSTRACT",       SIMPLE,       LEVEL_MAIN },
+	{ "volume",       "VOLUME",         SIMPLE,       LEVEL_MAIN },
+	{ "contents",     "CONTENTS",       SIMPLE,       LEVEL_MAIN },
+	{ "doi",          "DOI",            SIMPLE,       LEVEL_MAIN },
+	{ "ftp",          "",               URL,          LEVEL_MAIN },
+	{ "url",          "",               URL,          LEVEL_MAIN },
+	{ "pdf",          "FILEATTACH",     SIMPLE,       LEVEL_MAIN },
+	{ "sentelink",    "FILEATTACH",     BT_SENTE,     LEVEL_MAIN },
+	{ "file",         "FILEATTACH",     LINKEDFILE,   LEVEL_MAIN },
+	{ "howpublished", "",               HOWPUBLISHED, LEVEL_MAIN },
+	{ "refnum",       "REFNUM",         SIMPLE,       LEVEL_MAIN },
+	{ "crossref",     "CROSSREF",       SIMPLE,       LEVEL_MAIN },
+	{ "location",     "LOCATION",       SIMPLE,       LEVEL_MAIN },
+	{ "note",         "NOTES",          NOTES,        LEVEL_MAIN },
+	{ "annote",       "ANNOTE",         SIMPLE,       LEVEL_MAIN },
+	{ "key",          "BIBKEY",         SIMPLE,       LEVEL_MAIN },
+	{ "language",     "LANGUAGE",       SIMPLE,       LEVEL_MAIN },
+	{ "keywords",     "KEYWORD",        KEYWORD,      LEVEL_MAIN },
         { "",         "RESOURCE|software, multimedia", ALWAYS, LEVEL_MAIN },
 	{ "",         "GENRE|electronic",              ALWAYS, LEVEL_MAIN },
 };
 
 static lookups misc[] = {
-	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN },
-	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },
-	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },
-	{ "booktitle", "TITLE",     TITLE,  LEVEL_MAIN },
-	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_MAIN },
-	{ "organization", "ORGANIZER:CORP", BT_ORG, LEVEL_MAIN },
-	{ "pages",     "PAGES",     PAGES,  LEVEL_MAIN },
-	{ "address",   "ADDRESS",   SIMPLE, LEVEL_MAIN },
-	{ "editor",    "EDITOR",    PERSON, LEVEL_MAIN },
-	{ "year",      "YEAR",      SIMPLE, LEVEL_MAIN },
-	{ "month",     "MONTH",     SIMPLE, LEVEL_MAIN },
-	{ "day",       "DAY",       SIMPLE, LEVEL_MAIN },
-	{ "abstract",  "ABSTRACT",  SIMPLE, LEVEL_MAIN },
-	{ "contents",  "CONTENTS",  SIMPLE, LEVEL_MAIN },
-	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },
-	{ "ftp",       "",      BT_URL, LEVEL_MAIN },
-	{ "url",       "",      BT_URL, LEVEL_MAIN },
-	{ "pdf",       "FILEATTACH",   SIMPLE, LEVEL_MAIN },
-	{ "sentelink", "FILEATTACH",BT_SENTE, LEVEL_MAIN },
-	{ "file",      "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
-	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },
-	{ "refnum",    "REFNUM",       SIMPLE, LEVEL_MAIN },
-	{ "crossref",  "CROSSREF",     SIMPLE, LEVEL_MAIN },
-	{ "location",  "LOCATION",     SIMPLE, LEVEL_MAIN },
-	{ "note",      "NOTES",        BT_NOTE, LEVEL_MAIN },
-	{ "annote",    "ANNOTE",       SIMPLE, LEVEL_MAIN },
-	{ "key",       "BIBKEY",       SIMPLE, LEVEL_MAIN },
-	{ "language",  "LANGUAGE",     SIMPLE, LEVEL_MAIN },
-	{ "keywords",  "KEYWORD",      KEYWORD, LEVEL_MAIN },
-	{ "",          "INTERNAL_TYPE|MISC",       ALWAYS, LEVEL_MAIN },
+	{ "author",       "AUTHOR",         PERSON,       LEVEL_MAIN },
+	{ "translator",   "TRANSLATOR",     PERSON,       LEVEL_MAIN },
+	{ "title",        "",               TITLE,        LEVEL_MAIN },
+	{ "booktitle",    "",               TITLE,        LEVEL_MAIN },
+	{ "publisher",    "PUBLISHER",      SIMPLE,       LEVEL_MAIN },
+	{ "organization", "ORGANIZER:CORP", BT_ORG,       LEVEL_MAIN },
+	{ "pages",        "PAGES",          PAGES,        LEVEL_MAIN },
+	{ "address",      "ADDRESS",        SIMPLE,       LEVEL_MAIN },
+	{ "editor",       "EDITOR",         PERSON,       LEVEL_MAIN },
+	{ "year",         "DATE:YEAR",      SIMPLE,       LEVEL_MAIN },
+	{ "month",        "DATE:MONTH",     SIMPLE,       LEVEL_MAIN },
+	{ "day",          "DATE:DAY",       SIMPLE,       LEVEL_MAIN },
+	{ "abstract",     "ABSTRACT",       SIMPLE,       LEVEL_MAIN },
+	{ "contents",     "CONTENTS",       SIMPLE,       LEVEL_MAIN },
+	{ "doi",          "DOI",            SIMPLE,       LEVEL_MAIN },
+	{ "ftp",          "",               URL,          LEVEL_MAIN },
+	{ "url",          "",               URL,          LEVEL_MAIN },
+	{ "pdf",          "FILEATTACH",     SIMPLE,       LEVEL_MAIN },
+	{ "sentelink",    "FILEATTACH",     BT_SENTE,     LEVEL_MAIN },
+	{ "file",         "FILEATTACH",     LINKEDFILE,   LEVEL_MAIN },
+	{ "howpublished", "",               HOWPUBLISHED, LEVEL_MAIN },
+	{ "refnum",       "REFNUM",         SIMPLE,       LEVEL_MAIN },
+	{ "crossref",     "CROSSREF",       SIMPLE,       LEVEL_MAIN },
+	{ "location",     "LOCATION",       SIMPLE,       LEVEL_MAIN },
+	{ "note",         "NOTES",          NOTES,        LEVEL_MAIN },
+	{ "annote",       "ANNOTE",         SIMPLE,       LEVEL_MAIN },
+	{ "key",          "BIBKEY",         SIMPLE,       LEVEL_MAIN },
+	{ "language",     "LANGUAGE",       SIMPLE,       LEVEL_MAIN },
+	{ "keywords",     "KEYWORD",        KEYWORD,      LEVEL_MAIN },
+	{ "",             "INTERNAL_TYPE|MISC",       ALWAYS, LEVEL_MAIN },
 };
 
 #define ORIG(a) ( &(a[0]) )
diff --git a/lib/bibutils.c b/lib/bibutils.c
index cab36f8..f636e94 100644
--- a/lib/bibutils.c
+++ b/lib/bibutils.c
@@ -1,7 +1,7 @@
 /*
  * bibutils.c
  *
- * Copyright (c) Chris Putnam 2005-2015
+ * Copyright (c) Chris Putnam 2005-2016
  *
  * Source code released under the GPL version 2
  *
@@ -9,26 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "bibutils.h"
-
-/* bibl format includes */
-#include "adsout.h"
-#include "biblatexin.h"
-#include "bibtexin.h"
-#include "bibtexout.h"
-#include "copacin.h"
-#include "ebiin.h"
-#include "endin.h"
-#include "endxmlin.h"
-#include "endout.h"
-#include "isiin.h"
-#include "isiout.h"
-#include "medin.h"
-#include "modsin.h"
-#include "modsout.h"
-#include "risin.h"
-#include "risout.h"
-#include "wordin.h"
-#include "wordout.h"
+#include "bibformats.h"
 
 void
 bibl_initparams( param *p, int readmode, int writemode, char *progname )
diff --git a/lib/bibutils.h b/lib/bibutils.h
index c2a3ae6..c66db66 100644
--- a/lib/bibutils.h
+++ b/lib/bibutils.h
@@ -1,7 +1,7 @@
 /*
  * bibutils.h
  *
- * Copyright (c) Chris Putnam 2005-2015
+ * Copyright (c) Chris Putnam 2005-2016
  *
  * Source code released under GPL version 2
  *
@@ -36,7 +36,8 @@ extern "C" {
 #define BIBL_BIBLATEXIN   (BIBL_FIRSTIN+8)
 #define BIBL_EBIIN        (BIBL_FIRSTIN+9)
 #define BIBL_WORDIN       (BIBL_FIRSTIN+10)
-#define BIBL_LASTIN       (BIBL_FIRSTIN+10)
+#define BIBL_NBIBIN       (BIBL_FIRSTIN+11)
+#define BIBL_LASTIN       (BIBL_FIRSTIN+11)
 
 #define BIBL_FIRSTOUT     (200)
 #define BIBL_MODSOUT      (BIBL_FIRSTOUT)
@@ -48,7 +49,16 @@ extern "C" {
 #define BIBL_ADSABSOUT    (BIBL_FIRSTOUT+6)
 #define BIBL_LASTOUT      (BIBL_FIRSTOUT+6)
 
-#define BIBL_FORMAT_VERBOSE (1)
+#define BIBL_FORMAT_VERBOSE             (1)
+#define BIBL_FORMAT_BIBOUT_FINALCOMMA   (2)
+#define BIBL_FORMAT_BIBOUT_SINGLEDASH   (4)
+#define BIBL_FORMAT_BIBOUT_WHITESPACE   (8)
+#define BIBL_FORMAT_BIBOUT_BRACKETS    (16)
+#define BIBL_FORMAT_BIBOUT_UPPERCASE   (32)
+#define BIBL_FORMAT_BIBOUT_STRICTKEY   (64)
+#define BIBL_FORMAT_BIBOUT_SHORTTITLE (128)
+#define BIBL_FORMAT_BIBOUT_DROPKEY    (256)
+#define BIBL_FORMAT_MODSOUT_DROPKEY   (512)
 
 #define BIBL_RAW_WITHCHARCONVERT (4)
 #define BIBL_RAW_WITHMAKEREFID   (8)
@@ -102,13 +112,13 @@ typedef struct param {
 
 
         int  (*readf)(FILE*,char*,int,int*,newstr*,newstr*,int*);
-        int  (*processf)(fields*,char*,char*,long);
+        int  (*processf)(fields*,char*,char*,long,struct param*);
         int  (*cleanf)(bibl*,struct param*);
-        int  (*typef) (fields*,char*,int,struct param*,variants*,int);
-        int  (*convertf)(fields*,fields*,int,struct param*,variants*,int);
+        int  (*typef) (fields*,char*,int,struct param*);
+        int  (*convertf)(fields*,fields*,int,struct param*);
         void (*headerf)(FILE*,struct param*);
         void (*footerf)(FILE*);
-        void (*writef)(fields*,FILE*,struct param*,unsigned long);
+        int  (*writef)(fields*,FILE*,struct param*,unsigned long);
         variants *all;
         int  nall;
 
diff --git a/lib/bltypes.c b/lib/bltypes.c
index 4e61b2a..86a22f3 100644
--- a/lib/bltypes.c
+++ b/lib/bltypes.c
@@ -1,8 +1,8 @@
 /*
  * bltypes.c
  *
- * Copyright (c) Chris Putnam 2008-2015
- * Copyright (c) Johannes Wilm 2010-2015
+ * Copyright (c) Chris Putnam 2008-2016
+ * Copyright (c) Johannes Wilm 2010-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -47,7 +47,7 @@ static lookups article[] = {
 	{ "issuesubtitle",   "SUBTITLE",               TITLE,           LEVEL_SERIES }, /*WRONG*/
 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
 	{ "origlanguage",    "LANGUAGE",               SIMPLE,          LEVEL_ORIG   },
-	{ "origyear",        "YEAR",                   SIMPLE,          LEVEL_ORIG   },
+	{ "origyear",        "DATE:YEAR",              SIMPLE,          LEVEL_ORIG   },
 	{ "origdate",        "DATE",                   SIMPLE,          LEVEL_ORIG   },
 	{ "origtitle",       "TITLE",                  SIMPLE,          LEVEL_ORIG   },
 	{ "origlocation",    "ADDRESS",                SIMPLE,          LEVEL_ORIG   },
@@ -58,22 +58,23 @@ static lookups article[] = {
 	{ "eid",             "EID",                    SIMPLE,          LEVEL_MAIN   },
 	{ "issue",           "ISSUE",                  SIMPLE,          LEVEL_MAIN   },
 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/
-	{ "day",             "PARTDAY",                SIMPLE,          LEVEL_MAIN   },
-	{ "month",           "PARTMONTH",              SIMPLE,          LEVEL_MAIN   },
-	{ "year",            "PARTYEAR",               SIMPLE,          LEVEL_MAIN   },
+	{ "day",             "PARTDATE:DAY",           SIMPLE,          LEVEL_MAIN   },
+	{ "month",           "PARTDATE:MONTH",         SIMPLE,          LEVEL_MAIN   },
+	{ "year",            "PARTDATE:YEAR",          SIMPLE,          LEVEL_MAIN   },
 	{ "pages",           "PAGES",                  PAGES,           LEVEL_MAIN   },
 	{ "version",         "EDITION",                SIMPLE,          LEVEL_MAIN   },
-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   },
 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "issn",            "ISSN",                   SIMPLE,          LEVEL_HOST   },
+	{ "coden",           "CODEN",                  SIMPLE,          LEVEL_HOST   },
 	{ "abstract",        "ABSTRACT",               SIMPLE,          LEVEL_MAIN   },
 	{ "addendum",        "ADDENDUM",               SIMPLE,          LEVEL_MAIN   },
 	{ "doi",             "DOI",                    SIMPLE,          LEVEL_MAIN   },
 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   },
 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   },
 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },
-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },
+	{ "url",             "",                       URL,             LEVEL_MAIN   },
 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
 	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   }, /* WRONG */
 	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   }, /* WRONG */
@@ -120,11 +121,11 @@ static lookups book[] = {
 	{ "mainsubtitle",    "SUBTITLE",               TITLE,           LEVEL_HOST   },
 	{ "maintitleaddon",  "TITLEADDON",             TITLE,           LEVEL_HOST   },
 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },
-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },
+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },
+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },
 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/
 	{ "origlanguage",    "LANGUAGE",               SIMPLE,          LEVEL_ORIG   },
-	{ "origyear",        "YEAR",                   SIMPLE,          LEVEL_ORIG   },
+	{ "origyear",        "DATE:YEAR",              SIMPLE,          LEVEL_ORIG   },
 	{ "origdate",        "DATE",                   SIMPLE,          LEVEL_ORIG   },
 	{ "origtitle",       "TITLE",                  SIMPLE,          LEVEL_ORIG   },
 	{ "origlocation",    "ADDRESS",                SIMPLE,          LEVEL_ORIG   },
@@ -135,7 +136,7 @@ static lookups book[] = {
 	{ "volumes",         "NUMVOLUMES",             SIMPLE,          LEVEL_HOST   },
 	{ "series",          "TITLE",                  SIMPLE,          LEVEL_HOST   }, /* WRONG */
 	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },
-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   },
 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "publisher",       "PUBLISHER",              SIMPLE,          LEVEL_MAIN   },
@@ -143,13 +144,13 @@ static lookups book[] = {
 	{ "isbn",            "ISBN",                   SIMPLE,          LEVEL_MAIN   },
 	{ "chapter",         "CHAPTER",                SIMPLE,          LEVEL_MAIN   },
 	{ "pages",           "PAGES",                  PAGES,           LEVEL_MAIN   }, /* WRONG */
-	{ "pagetotal",       "TOTALPAGES",             SIMPLE,          LEVEL_MAIN   },
+	{ "pagetotal",       "PAGES:TOTAL",            SIMPLE,          LEVEL_MAIN   },
 	{ "addendum",        "ADDENDUM",               SIMPLE,          LEVEL_MAIN   },
 	{ "doi",             "DOI",                    SIMPLE,          LEVEL_MAIN   },
 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   },
 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   },
 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },
-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },
+	{ "url",             "",                       URL,             LEVEL_MAIN   },
 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
 	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   },
 	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   },
@@ -184,25 +185,25 @@ static lookups booklet[] = {
 	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   },
 	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   },
 	{ "howpublished",    "",                       HOWPUBLISHED,    LEVEL_MAIN   },
-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },
-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },
+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },
+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },
 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/
 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
 	{ "type",            "GENRE",                  BT_GENRE,        LEVEL_MAIN   },
-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   },
 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "publisher",       "PUBLISHER",              SIMPLE,          LEVEL_MAIN   },
 	{ "location",        "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
 	{ "chapter",         "CHAPTER",                SIMPLE,          LEVEL_MAIN   },
 	{ "pages",           "PAGES",                  PAGES,           LEVEL_MAIN   },
-	{ "pagetotal",       "TOTALPAGES",             SIMPLE,          LEVEL_MAIN   },
+	{ "pagetotal",       "PAGES:TOTAL",            SIMPLE,          LEVEL_MAIN   },
 	{ "addendum",        "ADDENDUM",               SIMPLE,          LEVEL_MAIN   },
 	{ "doi",             "DOI",                    SIMPLE,          LEVEL_MAIN   },
 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   },
 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   },
 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },
-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },
+	{ "url",             "",                       URL,             LEVEL_MAIN   },
 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
 	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   },
 	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   },
@@ -233,8 +234,8 @@ static lookups collection[] = {
 	{ "annotator",       "ANNOTATOR",              PERSON,          LEVEL_MAIN   },
 	{ "commentator",     "COMMENTATOR",            PERSON,          LEVEL_MAIN   },
 	{ "translator",      "TRANSLATOR",             PERSON,          LEVEL_MAIN   },
-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },
-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },
+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },
+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },
 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/
 	{ "introduction",    "INTROAUTHOR",            PERSON,          LEVEL_MAIN   },
 	{ "foreword",        "INTROAUTHOR",            PERSON,          LEVEL_MAIN   },
@@ -248,7 +249,7 @@ static lookups collection[] = {
 	{ "maintitleaddon",  "TITLEADDON",             TITLE,           LEVEL_HOST   },
 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
 	{ "origlanguage",    "LANGUAGE",               SIMPLE,          LEVEL_ORIG   },
-	{ "origyear",        "YEAR",                   SIMPLE,          LEVEL_ORIG   },
+	{ "origyear",        "DATE:YEAR",              SIMPLE,          LEVEL_ORIG   },
 	{ "origdate",        "DATE",                   SIMPLE,          LEVEL_ORIG   },
 	{ "origtitle",       "TITLE",                  SIMPLE,          LEVEL_ORIG   },
 	{ "origlocation",    "ADDRESS",                SIMPLE,          LEVEL_ORIG   },
@@ -259,7 +260,7 @@ static lookups collection[] = {
 	{ "volumes",         "NUMVOLUMES",             SIMPLE,          LEVEL_HOST   },
 	{ "series",          "TITLE",                  SIMPLE,          LEVEL_HOST   },
 	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },
-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   },
 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "publisher",       "PUBLISHER",              SIMPLE,          LEVEL_MAIN   },
@@ -267,13 +268,13 @@ static lookups collection[] = {
 	{ "isbn",            "ISBN",                   SIMPLE,          LEVEL_MAIN   },
 	{ "chapter",         "CHAPTER",                SIMPLE,          LEVEL_MAIN   },
 	{ "pages",           "PAGES",                  PAGES,           LEVEL_MAIN   },
-	{ "pagetotal",       "TOTALPAGES",             SIMPLE,          LEVEL_MAIN   },
+	{ "pagetotal",       "PAGES:TOTAL",            SIMPLE,          LEVEL_MAIN   },
 	{ "addendum",        "ADDENDUM",               SIMPLE,          LEVEL_MAIN   },
 	{ "doi",             "DOI",                    SIMPLE,          LEVEL_MAIN   },
 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   },
 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   },
 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },
-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },
+	{ "url",             "",                       URL,             LEVEL_MAIN   },
 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
 	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   },
 	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   },
@@ -307,8 +308,8 @@ static lookups inbook[] = {
 	{ "annotator",       "ANNOTATOR",              PERSON,          LEVEL_HOST   },
 	{ "commentator",     "COMMENTATOR",            PERSON,          LEVEL_HOST   },
 	{ "translator",      "TRANSLATOR",             PERSON,          LEVEL_HOST   },
-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },
-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },
+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },
+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },
 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/
 	{ "introduction",    "INTROAUTHOR",            PERSON,          LEVEL_HOST   },
 	{ "foreword",        "INTROAUTHOR",            PERSON,          LEVEL_HOST   },
@@ -326,7 +327,7 @@ static lookups inbook[] = {
 	{ "maintitleaddon",  "TITLEADDON",             TITLE,           LEVEL_SERIES },
 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
 	{ "origlanguage",    "LANGUAGE",               SIMPLE,          LEVEL_ORIG   },
-	{ "origyear",        "YEAR",                   SIMPLE,          LEVEL_ORIG   },
+	{ "origyear",        "DATE:YEAR",              SIMPLE,          LEVEL_ORIG   },
 	{ "origdate",        "DATE",                   SIMPLE,          LEVEL_ORIG   },
 	{ "origtitle",       "TITLE",                  SIMPLE,          LEVEL_ORIG   },
 	{ "origlocation",    "ADDRESS",                SIMPLE,          LEVEL_ORIG   },
@@ -338,7 +339,7 @@ static lookups inbook[] = {
 	{ "volumes",         "NUMVOLUMES",             SIMPLE,          LEVEL_HOST   },
 	{ "series",          "TITLE",                  SIMPLE,          LEVEL_SERIES+1 }, /* WRONG */
 	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },
-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   },
 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "publisher",       "PUBLISHER",              SIMPLE,          LEVEL_MAIN   },
@@ -350,7 +351,7 @@ static lookups inbook[] = {
 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   },
 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   },
 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },
-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },
+	{ "url",             "",                       URL,             LEVEL_MAIN   },
 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
 	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   },
 	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   },
@@ -369,8 +370,8 @@ static lookups inbook[] = {
 
 static lookups incollection[] = {
 	{ "author",          "AUTHOR",                 PERSON,          LEVEL_MAIN   },
-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },
-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },
+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },
+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },
 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/
 	{ "title",           "TITLE",                  TITLE,           LEVEL_MAIN   },
 	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   },
@@ -379,7 +380,7 @@ static lookups incollection[] = {
 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
 	{ "edition",         "EDITION",                SIMPLE,          LEVEL_MAIN   },
 	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },
-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   },
 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "introduction",    "INTROAUTHOR",            PERSON,          LEVEL_HOST   },
@@ -416,7 +417,7 @@ static lookups incollection[] = {
 	{ "series",          "TITLE",                  SIMPLE,          LEVEL_SERIES+1 }, /* WRONG */
 
 	{ "origlanguage",    "LANGUAGE",               SIMPLE,          LEVEL_ORIG   },
-	{ "origyear",        "YEAR",                   SIMPLE,          LEVEL_ORIG   },
+	{ "origyear",        "DATE:YEAR",              SIMPLE,          LEVEL_ORIG   },
 	{ "origdate",        "DATE",                   SIMPLE,          LEVEL_ORIG   },
 	{ "origtitle",       "TITLE",                  SIMPLE,          LEVEL_ORIG   },
 	{ "origlocation",    "ADDRESS",                SIMPLE,          LEVEL_ORIG   },
@@ -432,7 +433,7 @@ static lookups incollection[] = {
 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   },
 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   },
 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },
-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },
+	{ "url",             "",                       URL,             LEVEL_MAIN   },
 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
 	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   },
 	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   },
@@ -467,8 +468,8 @@ static lookups inproceedings[] = {
 	{ "commentator",     "COMMENTATOR",            PERSON,          LEVEL_HOST   },
 	{ "translator",      "TRANSLATOR",             PERSON,          LEVEL_HOST   },
 	{ "eventtitle",      "EVENT:CONF",             SIMPLE,          LEVEL_MAIN   },
-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },
-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },
+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },
+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },
 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/
 	{ "introduction",    "INTROAUTHOR",            PERSON,          LEVEL_HOST   },
 	{ "foreword",        "INTROAUTHOR",            PERSON,          LEVEL_HOST   },
@@ -493,7 +494,7 @@ static lookups inproceedings[] = {
 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
 	{ "origlanguage",    "LANGUAGE",               SIMPLE,          LEVEL_ORIG   },
 	{ "origdate",        "DATE",                   SIMPLE,          LEVEL_ORIG   },
-	{ "origyear",        "YEAR",                   SIMPLE,          LEVEL_ORIG   },
+	{ "origyear",        "DATE:YEAR",              SIMPLE,          LEVEL_ORIG   },
 	{ "origtitle",       "TITLE",                  SIMPLE,          LEVEL_ORIG   },
 	{ "origlocation",    "ADDRESS",                SIMPLE,          LEVEL_ORIG   },
 	{ "origpublisher",   "PUBLISHER",              SIMPLE,          LEVEL_ORIG   },
@@ -502,7 +503,7 @@ static lookups inproceedings[] = {
 	{ "edition",         "EDITION",                SIMPLE,          LEVEL_MAIN   },
 	{ "volumes",         "NUMVOLUMES",             SIMPLE,          LEVEL_HOST   },
 	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },
-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   },
 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "publisher",       "PUBLISHER",              SIMPLE,          LEVEL_HOST   },
@@ -515,7 +516,7 @@ static lookups inproceedings[] = {
 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   },
 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   },
 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },
-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },
+	{ "url",             "",                       URL,             LEVEL_MAIN   },
 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
 	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   },
 	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   },
@@ -547,8 +548,8 @@ static lookups manual[] = {
 	{ "annotator",       "ANNOTATOR",              PERSON,          LEVEL_MAIN   },
 	{ "commentator",     "COMMENTATOR",            PERSON,          LEVEL_MAIN   },
 	{ "translator",      "TRANSLATOR",             PERSON,          LEVEL_MAIN   },
-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },
-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },
+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },
+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },
 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   }, /*WRONG*/
 	{ "introduction",    "INTROAUTHOR",            PERSON,          LEVEL_MAIN   },
 	{ "foreword",        "INTROAUTHOR",            PERSON,          LEVEL_MAIN   },
@@ -563,7 +564,7 @@ static lookups manual[] = {
 	{ "type",            "GENRE",                  BT_GENRE,        LEVEL_MAIN   },
 	{ "series",          "TITLE",                  SIMPLE,          LEVEL_HOST   },
 	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },
-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   },
 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "organization",    "ORGANIZER:CORP",         SIMPLE,          LEVEL_MAIN   },
@@ -572,13 +573,13 @@ static lookups manual[] = {
 	{ "isbn",            "ISBN",                   SIMPLE,          LEVEL_MAIN   },
 	{ "chapter",         "CHAPTER",                SIMPLE,          LEVEL_MAIN   },
 	{ "pages",           "PAGES",                  PAGES,           LEVEL_MAIN   },
-	{ "pagetotal",       "TOTALPAGES",             SIMPLE,          LEVEL_MAIN   },
+	{ "pagetotal",       "PAGES:TOTAL",            SIMPLE,          LEVEL_MAIN   },
 	{ "addendum",        "ADDENDUM",               SIMPLE,          LEVEL_MAIN   },
 	{ "doi",             "DOI",                    SIMPLE,          LEVEL_MAIN   },
 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   },
 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   },
 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },
-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },
+	{ "url",             "",                       URL,             LEVEL_MAIN   },
 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
 	{ "urlday",          "?????????",              SIMPLE,          LEVEL_MAIN   },
 	{ "urlmonth",        "?????????",              SIMPLE,          LEVEL_MAIN   },
@@ -609,15 +610,15 @@ static lookups misc[] = {
 	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   },
 	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   },
 	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   },
-	{ "day",             "DAY",                    SIMPLE,          LEVEL_MAIN   },
-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },
-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },
+	{ "day",             "DATE:DAY",               SIMPLE,          LEVEL_MAIN   },
+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },
+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },
 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/
 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
 	{ "howpublished",    "",                       HOWPUBLISHED,    LEVEL_MAIN   },
 	{ "version",         "EDITION",                SIMPLE,          LEVEL_MAIN   },
 	{ "type",            "GENRE",                  BT_GENRE,        LEVEL_MAIN   },
-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   },
 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "organization",    "ORGANIZER:CORP",         SIMPLE,          LEVEL_MAIN   },
@@ -629,7 +630,7 @@ static lookups misc[] = {
 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   },
 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   },
 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },
-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },
+	{ "url",             "",                       URL,             LEVEL_MAIN   },
 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
 	{ "urlday",          "?????????",              SIMPLE,          LEVEL_MAIN   },
 	{ "urlmonth",        "?????????",              SIMPLE,          LEVEL_MAIN   },
@@ -658,13 +659,13 @@ static lookups online[] = {
 	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   },
 	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   },
 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },
-	{ "day",             "DAY",                    SIMPLE,          LEVEL_MAIN   },
-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },
-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },
+	{ "day",             "DATE:DAY",               SIMPLE,          LEVEL_MAIN   },
+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },
+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },
 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
 	{ "version",         "EDITION",                SIMPLE,          LEVEL_MAIN   },
 	{ "type",            "GENRE",                  BT_GENRE,        LEVEL_MAIN   },
-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   },
 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "organization",    "ORGANIZER:CORP",         SIMPLE,          LEVEL_MAIN   },
@@ -675,7 +676,7 @@ static lookups online[] = {
 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   },
 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   },
 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },
-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },
+	{ "url",             "",                       URL,             LEVEL_MAIN   },
 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
 	{ "urlday",          "?????????",              SIMPLE,          LEVEL_MAIN   },
 	{ "urlmonth",        "?????????",              SIMPLE,          LEVEL_MAIN   },
@@ -695,19 +696,19 @@ static lookups patent[] = {
 	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   },
 	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   },
 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },
-	{ "day",             "DAY",                    SIMPLE,          LEVEL_MAIN   },
-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },
-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },
+	{ "day",             "DATE:DAY",               SIMPLE,          LEVEL_MAIN   },
+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },
+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },
 	{ "version",         "EDITION",                SIMPLE,          LEVEL_MAIN   },
 	{ "type",            "GENRE",                  BT_GENRE,        LEVEL_MAIN   },
-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   },
 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "organization",    "ORGANIZER:CORP",         SIMPLE,          LEVEL_MAIN   },
 	{ "location",        "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
 	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },
 	{ "addendum",        "ADDENDUM",               SIMPLE,          LEVEL_MAIN   },
-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },
+	{ "url",             "",                       URL,             LEVEL_MAIN   },
 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
 	{ "urlday",          "?????????",              SIMPLE,          LEVEL_MAIN   },
 	{ "urlmonth",        "?????????",              SIMPLE,          LEVEL_MAIN   },
@@ -753,20 +754,21 @@ static lookups periodical[] = {
 	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },
 	{ "issue",           "ISSUE",                  SIMPLE,          LEVEL_MAIN   },
 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/
-	{ "day",             "PARTDAY",                SIMPLE,          LEVEL_MAIN   },
-	{ "month",           "PARTMONTH",              SIMPLE,          LEVEL_MAIN   },
-	{ "year",            "PARTYEAR",               SIMPLE,          LEVEL_MAIN   },
+	{ "day",             "PARTDATE:DAY",           SIMPLE,          LEVEL_MAIN   },
+	{ "month",           "PARTDATE:MONTH",         SIMPLE,          LEVEL_MAIN   },
+	{ "year",            "PARTDATE:YEAR",          SIMPLE,          LEVEL_MAIN   },
 	{ "pages",           "PAGES",                  PAGES,           LEVEL_MAIN   },
-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   },
 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "issn",            "ISSN",                   SIMPLE,          LEVEL_HOST   },
+	{ "coden",           "CODEN",                  SIMPLE,          LEVEL_HOST   },
 	{ "addendum",        "ADDENDUM",               SIMPLE,          LEVEL_MAIN   },
 	{ "doi",             "DOI",                    SIMPLE,          LEVEL_MAIN   },
 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   },
 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   },
 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },
-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },
+	{ "url",             "",                       URL,             LEVEL_MAIN   },
 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
 	{ "urlday",          "?????",                  SIMPLE,          LEVEL_MAIN   }, /* WRONG */
 	{ "urlmonth",        "?????",                  SIMPLE,          LEVEL_MAIN   }, /* WRONG */
@@ -798,8 +800,8 @@ static lookups proceedings[] = {
 	{ "commentator",     "COMMENTATOR",            PERSON,          LEVEL_MAIN   },
 	{ "translator",      "TRANSLATOR",             PERSON,          LEVEL_MAIN   },
 	{ "eventtitle",      "EVENT:CONF",             SIMPLE,          LEVEL_MAIN   },
-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },
-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },
+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },
+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },
 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/
 	{ "introduction",    "INTROAUTHOR",            PERSON,          LEVEL_MAIN   },
 	{ "foreword",        "INTROAUTHOR",            PERSON,          LEVEL_MAIN   },
@@ -814,7 +816,7 @@ static lookups proceedings[] = {
 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
 	{ "origlanguage",    "LANGUAGE",               SIMPLE,          LEVEL_ORIG   },
 	{ "origdate",        "DATE",                   SIMPLE,          LEVEL_ORIG   },
-	{ "origyear",        "YEAR",                   SIMPLE,          LEVEL_ORIG   },
+	{ "origyear",        "DATE:YEAR",              SIMPLE,          LEVEL_ORIG   },
 	{ "origtitle",       "TITLE",                  SIMPLE,          LEVEL_ORIG   },
 	{ "origlocation",    "ADDRESS",                SIMPLE,          LEVEL_ORIG   },
 	{ "origpublisher",   "PUBLISHER",              SIMPLE,          LEVEL_ORIG   },
@@ -824,7 +826,7 @@ static lookups proceedings[] = {
 	{ "volumes",         "NUMVOLUMES",             SIMPLE,          LEVEL_HOST   },
 	{ "series",          "TITLE",                  SIMPLE,          LEVEL_SERIES },
 	{ "number",          "NUMBER",                 SIMPLE,          LEVEL_MAIN   },
-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   },
 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "organization",    "ORGANIZER:CORP",         SIMPLE,          LEVEL_MAIN   },
@@ -833,13 +835,13 @@ static lookups proceedings[] = {
 	{ "isbn",            "ISBN",                   SIMPLE,          LEVEL_MAIN   },
 	{ "chapter",         "CHAPTER",                SIMPLE,          LEVEL_MAIN   },
 	{ "pages",           "PAGES",                  SIMPLE,          LEVEL_MAIN   },
-	{ "pagetotal",       "TOTALPAGES",             SIMPLE,          LEVEL_MAIN   },
+	{ "pagetotal",       "PAGES:TOTAL",            SIMPLE,          LEVEL_MAIN   },
 	{ "addendum",        "ADDENDUM",               SIMPLE,          LEVEL_MAIN   },
 	{ "doi",             "DOI",                    SIMPLE,          LEVEL_MAIN   },
 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   },
 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   },
 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },
-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },
+	{ "url",             "",                       URL,             LEVEL_MAIN   },
 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
 	{ "urlday",          "?????????",              SIMPLE,          LEVEL_MAIN   },
 	{ "urlmonth",        "?????????",              SIMPLE,          LEVEL_MAIN   },
@@ -862,12 +864,12 @@ static lookups report[] = {
 	{ "series",          "TITLE",                  TITLE,           LEVEL_HOST   },
 	{ "type",            "GENRE",                  BT_GENRE,        LEVEL_MAIN   },
 	{ "institution",     "SPONSOR:ASIS",           SIMPLE,          LEVEL_MAIN   },
-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },
-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },
+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },
+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },
 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/
 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
 	{ "number",          "REPORTNUMBER",           SIMPLE,          LEVEL_MAIN   },
-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   },
 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "version",         "EDITION",                SIMPLE,          LEVEL_MAIN   },
@@ -875,13 +877,13 @@ static lookups report[] = {
 	{ "isrn",            "ISRN",                   SIMPLE,          LEVEL_MAIN   },
 	{ "chapter",         "CHAPTER",                SIMPLE,          LEVEL_MAIN   },
 	{ "pages",           "PAGES",                  SIMPLE,          LEVEL_MAIN   },
-	{ "pagetotal",       "TOTALPAGES",             SIMPLE,          LEVEL_MAIN   },
+	{ "pagetotal",       "PAGES:TOTAL",            SIMPLE,          LEVEL_MAIN   },
 	{ "addendum",        "ADDENDUM",               SIMPLE,          LEVEL_MAIN   },
 	{ "doi",             "DOI",                    SIMPLE,          LEVEL_MAIN   },
 	{ "pubstate",        "PUBSTATE",               SIMPLE,          LEVEL_MAIN   },
 	{ "eprint",          "",                       BT_EPRINT,       LEVEL_MAIN   },
 	{ "eprinttype",      "",                       BT_EPRINT,       LEVEL_MAIN   },
-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },
+	{ "url",             "",                       URL,             LEVEL_MAIN   },
 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
 	{ "urlday",          "?????????",              SIMPLE,          LEVEL_MAIN   },
 	{ "urlmonth",        "?????????",              SIMPLE,          LEVEL_MAIN   },
@@ -902,16 +904,16 @@ static lookups unpublished[] = {
 	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   },
 	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   },
 	{ "howpublished",    "",                       HOWPUBLISHED,    LEVEL_MAIN   },
-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },
-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },
-	{ "day",             "DAY",                    SIMPLE,          LEVEL_MAIN   },
+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },
+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },
+	{ "day",             "DATE:DAY",               SIMPLE,          LEVEL_MAIN   },
 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },
-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },
+	{ "url",             "",                       URL,             LEVEL_MAIN   },
 	{ "urlday",          "?????????",              SIMPLE,          LEVEL_MAIN   },
 	{ "urlmonth",        "?????????",              SIMPLE,          LEVEL_MAIN   },
 	{ "urlyear",         "?????????",              SIMPLE,          LEVEL_MAIN   },
 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   },
 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "addendum",        "ADDENDUM",               SIMPLE,          LEVEL_MAIN   },
@@ -930,23 +932,23 @@ static lookups thesis[] = {
 	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   },
 	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   },
 	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   },
-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },
-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },
-	{ "day",             "DAY",                    SIMPLE,          LEVEL_MAIN   },
+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },
+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },
+	{ "day",             "DATE:DAY",               SIMPLE,          LEVEL_MAIN   },
 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/
 	{ "type",            "",                       BLT_THESIS_TYPE, LEVEL_MAIN   },
 	{ "institution",     "DEGREEGRANTOR:ASIS",     SIMPLE,          LEVEL_MAIN   },
 	{ "school",          "DEGREEGRANTOR:ASIS",     BLT_SCHOOL,      LEVEL_MAIN   },
 	{ "doi",             "DOI",                    SIMPLE,          LEVEL_MAIN   },
 	{ "howpublished",    "",                       HOWPUBLISHED,    LEVEL_MAIN   },
-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },
+	{ "url",             "",                       URL,             LEVEL_MAIN   },
 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
 	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   },
 	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   },
 	{ "urlyear",         "?urlyear?",              SIMPLE,          LEVEL_MAIN   },
 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
 	{ "location",        "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   },
 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
@@ -964,23 +966,23 @@ static lookups phdthesis[] = {
 	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   },
 	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   },
 	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   },
-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },
-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },
-	{ "day",             "DAY",                    SIMPLE,          LEVEL_MAIN   },
+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },
+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },
+	{ "day",             "DATE:DAY",               SIMPLE,          LEVEL_MAIN   },
 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/
 	{ "type",            "",                       BLT_THESIS_TYPE, LEVEL_MAIN   },
 	{ "institution",     "DEGREEGRANTOR:ASIS",     SIMPLE,          LEVEL_MAIN   },
 	{ "school",          "DEGREEGRANTOR:ASIS",     BLT_SCHOOL,      LEVEL_MAIN   },
 	{ "doi",             "DOI",                    SIMPLE,          LEVEL_MAIN   },
 	{ "howpublished",    "",                       HOWPUBLISHED,    LEVEL_MAIN   },
-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },
+	{ "url",             "",                       URL,             LEVEL_MAIN   },
 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
 	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   },
 	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   },
 	{ "urlyear",         "?urlyear?",              SIMPLE,          LEVEL_MAIN   },
 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
 	{ "location",        "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   },
 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
@@ -999,23 +1001,23 @@ static lookups mastersthesis[] = {
 	{ "subtitle",        "SUBTITLE",               TITLE,           LEVEL_MAIN   },
 	{ "titleaddon",      "TITLEADDON",             TITLE,           LEVEL_MAIN   },
 	{ "shorttitle",      "SHORTTITLE",             SIMPLE,          LEVEL_MAIN   },
-	{ "year",            "YEAR",                   SIMPLE,          LEVEL_MAIN   },
-	{ "month",           "MONTH",                  SIMPLE,          LEVEL_MAIN   },
-	{ "day",             "DAY",                    SIMPLE,          LEVEL_MAIN   },
+	{ "year",            "DATE:YEAR",              SIMPLE,          LEVEL_MAIN   },
+	{ "month",           "DATE:MONTH",             SIMPLE,          LEVEL_MAIN   },
+	{ "day",             "DATE:DAY",               SIMPLE,          LEVEL_MAIN   },
 	{ "date",            "DATE",                   SIMPLE,          LEVEL_MAIN   },   /*WRONG*/
 	{ "type",            "",                       BLT_THESIS_TYPE, LEVEL_MAIN   },
 	{ "institution",     "DEGREEGRANTOR:ASIS",     SIMPLE,          LEVEL_MAIN   },
 	{ "school",          "DEGREEGRANTOR:ASIS",     BLT_SCHOOL,      LEVEL_MAIN   },
 	{ "doi",             "DOI",                    SIMPLE,          LEVEL_MAIN   },
 	{ "howpublished",    "",                       HOWPUBLISHED,    LEVEL_MAIN   },
-	{ "url",             "",                       BT_URL,          LEVEL_MAIN   },
+	{ "url",             "",                       URL,             LEVEL_MAIN   },
 	{ "urldate",         "URLDATE",                SIMPLE,          LEVEL_MAIN   },
 	{ "urlday",          "?urlday?",               SIMPLE,          LEVEL_MAIN   },
 	{ "urlmonth",        "?urlmonth?",             SIMPLE,          LEVEL_MAIN   },
 	{ "urlyear",         "?urlyear?",              SIMPLE,          LEVEL_MAIN   },
 	{ "language",        "LANGUAGE",               SIMPLE,          LEVEL_MAIN   },
 	{ "location",        "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
-	{ "note",            "NOTES",                  SIMPLE,          LEVEL_MAIN   },
+	{ "note",            "NOTES",                  NOTES,           LEVEL_MAIN   },
 	{ "annote",          "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "annotation",      "ANNOTATION",             SIMPLE,          LEVEL_MAIN   },
 	{ "address",         "ADDRESS",                SIMPLE,          LEVEL_MAIN   },
diff --git a/lib/charsets.c b/lib/charsets.c
index 01c6832..9cf560e 100644
--- a/lib/charsets.c
+++ b/lib/charsets.c
@@ -1,7 +1,7 @@
 /*
  * charsets.c
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/lib/charsets.h b/lib/charsets.h
index 9e1a092..973584e 100644
--- a/lib/charsets.h
+++ b/lib/charsets.h
@@ -1,7 +1,7 @@
 /*
  * charsets.h
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/lib/copacin.c b/lib/copacin.c
index ac3fa93..9d51618 100644
--- a/lib/copacin.c
+++ b/lib/copacin.c
@@ -1,7 +1,7 @@
 /*
  * copacin.c
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -14,15 +14,22 @@
 #include "newstr_conv.h"
 #include "list.h"
 #include "name.h"
-#include "title.h"
 #include "fields.h"
 #include "reftypes.h"
-#include "serialno.h"
-#include "copacin.h"
+#include "bibformats.h"
+#include "generic.h"
+
+extern variants copac_all[];
+extern int copac_nall;
 
 /*****************************************************
  PUBLIC: void copacin_initparams()
 *****************************************************/
+
+static int copacin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );
+static int copacin_processf( fields *bibin, char *p, char *filename, long nref, param *pm );
+static int copacin_convertf( fields *bibin, fields *info, int reftype, param *pm );
+
 void
 copacin_initparams( param *p, const char *progname )
 {
@@ -80,7 +87,7 @@ readmore( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line )
 	else return newstr_fget( fp, buf, bufsize, bufpos, line );
 }
 
-int
+static int
 copacin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset )
 {
 	int haveref = 0, inref=0;
@@ -152,8 +159,8 @@ copacin_nextline( char *p )
 	return p;
 }
 
-int
-copacin_processf( fields *copacin, char *p, char *filename, long nref )
+static int
+copacin_processf( fields *copacin, char *p, char *filename, long nref, param *pm )
 {
 	newstr tag, data;
 	int status;
@@ -188,17 +195,16 @@ copacin_processf( fields *copacin, char *p, char *filename, long nref )
  * editors seem to be stuck in as authors with the tag "[Editor]" in it
  */
 static int
-copacin_addname( fields *info, char *tag, newstr *name, int level, list *asis,
-	list *corps )
+copacin_person( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
 {
-	char *usetag = tag, editor[]="EDITOR";
+	char *usetag = outtag, editor[]="EDITOR";
+	int comma = 0, i, ok;
 	newstr usename, *s;
 	list tokens;
-	int comma = 0, i, ok;
 
-	if ( list_find( asis, name->data ) !=-1  ||
-	     list_find( corps, name->data ) !=-1 ) {
-		ok = name_add( info, tag, name->data, level, asis, corps );
+	if ( list_find( &(pm->asis), invalue->data ) !=-1  ||
+	     list_find( &(pm->corps), invalue->data ) !=-1 ) {
+		ok = name_add( bibout, outtag, invalue->data, level, &(pm->asis), &(pm->corps) );
 		if ( ok ) return BIBL_OK;
 		else return BIBL_ERR_MEMERR;
 	}
@@ -206,7 +212,7 @@ copacin_addname( fields *info, char *tag, newstr *name, int level, list *asis,
 	list_init( &tokens );
 	newstr_init( &usename );
 
-	list_tokenize( &tokens, name, " ", 1 );
+	list_tokenize( &tokens, invalue, " ", 1 );
 	for ( i=0; i<tokens.n; ++i ) {
 		s = list_get( &tokens, i );
 		if ( !strcmp( s->data, "[Editor]" ) ) {
@@ -223,13 +229,18 @@ copacin_addname( fields *info, char *tag, newstr *name, int level, list *asis,
 	}
 
 	for ( i=0; i<tokens.n; ++i ) {
+		s = list_get( &tokens, i );
+		if ( s->len==0 ) continue;
 		if ( i ) newstr_addchar( &usename, ' ' );
-		newstr_newstrcat( &usename, list_get( &tokens, i ) );
+		newstr_newstrcat( &usename, s );
 	}
 
 	list_free( &tokens );
 
-	ok = name_add( info, usetag, usename.data, level, asis, corps );
+	ok = name_add( bibout, usetag, usename.data, level, &(pm->asis), &(pm->corps) );
+
+	newstr_free( &usename );
+
 	if ( ok ) return BIBL_OK;
 	else return BIBL_ERR_MEMERR;
 }
@@ -244,66 +255,37 @@ copacin_report_notag( param *p, char *tag )
 }
 
 static int
-copacin_simple( fields *out, char *tag, char *value, int level )
+copacin_convertf( fields *bibin, fields *bibout, int reftype, param *p )
 {
-	int fstatus = fields_add( out, tag, value, level );
-	if ( fstatus==FIELDS_OK ) return BIBL_OK;
-	else return BIBL_ERR_MEMERR;
-}
-
-int
-copacin_convertf( fields *copacin, fields *out, int reftype, param *p, variants *all, int nall )
-{
-	int  process, level, i, n, nfields, ok, status = BIBL_OK;
-	newstr *tag, *data;
-	char *newtag;
-
-	nfields = fields_num( copacin );
+	static int (*convertfns[NUM_REFTYPES])(fields *, int, newstr *, newstr *, int, param *, char *, fields *) = {
+		[ 0 ... NUM_REFTYPES-1 ] = generic_null,
+		[ SIMPLE       ] = generic_simple,
+		[ TITLE        ] = generic_title,
+		[ NOTES        ] = generic_notes,
+		[ SERIALNO     ] = generic_serialno,
+		[ PERSON       ] = copacin_person
+	};
+
+	int  process, level, i, nfields, status = BIBL_OK;
+	newstr *intag, *invalue;
+	char *outtag;
+
+	nfields = fields_num( bibin );
 	for ( i=0; i<nfields; ++i ) {
 
-		tag = fields_tag( copacin, i, FIELDS_STRP );
+		intag = fields_tag( bibin, i, FIELDS_STRP );
 
-		n = translate_oldtag( tag->data, reftype, all, nall, &process, &level, &newtag );
-		if ( n==-1 ) {
-			copacin_report_notag( p, tag->data );
+		if ( !translate_oldtag( intag->data, reftype, p->all, p->nall, &process, &level, &outtag ) ) {
+			copacin_report_notag( p, intag->data );
 			continue;
 		}
-		if ( process == ALWAYS ) continue; /*add these later*/
-
-		data = fields_value( copacin, i, FIELDS_STRP );
-
-		switch ( process ) {
-
-		case SIMPLE:
-			status = copacin_simple( out, newtag, data->data, level );
-			break;
 
-		case TITLE:
-			ok = title_process( out, newtag, data->data, level, p->nosplittitle );
-			if ( ok ) status = BIBL_OK;
-			else status = BIBL_ERR_MEMERR;
-			break;
-
-		case PERSON:
-			status = copacin_addname( out, newtag, data, level, &(p->asis), &(p->corps) );
-			break;
-
-		case SERIALNO:
-			ok = addsn( out, data->data, level );
-			if ( ok ) status = BIBL_OK;
-			else status = BIBL_ERR_MEMERR;
-			break;
-
-		default:
-			fprintf(stderr,"%s: internal error -- " "illegal process value %d\n", p->progname, process );
-			status = BIBL_OK;
-			break;
-		}
+		invalue = fields_value( bibin, i, FIELDS_STRP );
 
+		status = convertfns[ process ] ( bibin, i, intag, invalue, level, p, outtag, bibout );
 		if ( status!=BIBL_OK ) return status;
 
 	}
 
 	return status;
 }
-
diff --git a/lib/copacin.h b/lib/copacin.h
deleted file mode 100644
index 85646c5..0000000
--- a/lib/copacin.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * copacin.h
- *
- * Copyright (c) Chris Putnam 2004-2015
- *
- * Source code released under the GPL
- *
- */
-#ifndef COPACIN_H
-#define COPACIN_H
-
-#include "newstr.h"
-#include "fields.h"
-#include "reftypes.h"
-#include "bibutils.h"
-
-extern int copacin_readf( FILE *fp, char *buf, int bufsize, int *bufpos,
-		newstr *line, newstr *reference, int *fcharset );
-extern int copacin_processf( fields *copacin, char *p, char *filename, 
-		long nref );
-extern int copacin_convertf( fields *copacin, fields *info, int reftype, param *p, variants *all, int nall );
-
-extern void copacin_initparams( param *p, const char *progname );
-
-
-extern variants copac_all[];
-extern int copac_nall;
-
-
-#endif
diff --git a/lib/copactypes.c b/lib/copactypes.c
index d6451be..173542e 100644
--- a/lib/copactypes.c
+++ b/lib/copactypes.c
@@ -1,7 +1,7 @@
 /*
  * copactypes.c
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -14,22 +14,22 @@
 
 /* if no specific type can be identified */
 static lookups generic[] = {
-	{ "TI-", "TITLE" ,    TITLE,  LEVEL_MAIN },
-	{ "AU-", "AUTHOR",    PERSON, LEVEL_MAIN },
-	{ "MV-", "VOLUME",    SIMPLE, LEVEL_MAIN },
-	{ "SE-", "TITLE",     TITLE,  LEVEL_HOST },
-	{ "ED-", "EDITION",   SIMPLE, LEVEL_MAIN },
-	{ "SC-", "SCALE",     SIMPLE, LEVEL_MAIN }, /* for maps */
-	{ "PU-", "PUBLISHER", SIMPLE, LEVEL_MAIN },
-	{ "PY-", "YEAR",      SIMPLE, LEVEL_MAIN },
-	{ "PD-", "DESCRIPTION",SIMPLE, LEVEL_MAIN }, /* physical description */
-	{ "DT-", "TYPE",      SIMPLE, LEVEL_MAIN },
-	{ "LA-", "LANGUAGE",  SIMPLE, LEVEL_MAIN },
+	{ "TI-", "TITLE" ,       TITLE,  LEVEL_MAIN },
+	{ "AU-", "AUTHOR",       PERSON, LEVEL_MAIN },
+	{ "MV-", "VOLUME",       SIMPLE, LEVEL_MAIN },
+	{ "SE-", "TITLE",        TITLE,  LEVEL_HOST },
+	{ "ED-", "EDITION",      SIMPLE, LEVEL_MAIN },
+	{ "SC-", "SCALE",        SIMPLE, LEVEL_MAIN }, /* for maps */
+	{ "PU-", "PUBLISHER",    SIMPLE, LEVEL_MAIN },
+	{ "PY-", "DATE:YEAR",    SIMPLE, LEVEL_MAIN },
+	{ "PD-", "DESCRIPTION",  SIMPLE, LEVEL_MAIN }, /* physical description */
+	{ "DT-", "TYPE",         SIMPLE, LEVEL_MAIN },
+	{ "LA-", "LANGUAGE",     SIMPLE, LEVEL_MAIN },
 	{ "IS-", "SERIALNUMBER", SERIALNO, LEVEL_MAIN },
-	{ "NT-", "NOTES",     SIMPLE, LEVEL_MAIN },
-	{ "KW-", "KEYWORD",   SIMPLE, LEVEL_MAIN },
-	{ "UL-", "URL",       SIMPLE, LEVEL_MAIN },
-	{ "HL-", "LOCATION",  SIMPLE, LEVEL_MAIN }
+	{ "NT-", "NOTES",        NOTES,  LEVEL_MAIN },
+	{ "KW-", "KEYWORD",      SIMPLE, LEVEL_MAIN },
+	{ "UL-", "URL",          SIMPLE, LEVEL_MAIN },
+	{ "HL-", "LOCATION",     SIMPLE, LEVEL_MAIN }
 };
 
 /* order is important....."Book" matches "Book" and "Book Section", hence
diff --git a/lib/doi.c b/lib/doi.c
deleted file mode 100644
index f7b426b..0000000
--- a/lib/doi.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * doi.c
- *
- * doi_to_url()
- * Handle outputing DOI as a URL (Endnote and RIS formats)
- *     1) Append http://dx.doi.org as necessary
- *     2) Check for overlap with pre-existing URL for the DOI
- *
- * is_doi()
- * Check for DOI buried in another field.
- *
- * Copyright (c) Chris Putnam 2008-2015
- *
- * Source code released under the GPL version 2
- *
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include "newstr.h"
-#include "fields.h"
-
-static void
-construct_url( char *prefix, newstr *id, newstr *id_url )
-{
-	if ( !strncasecmp( id->data, "http:", 5 ) )
-		newstr_newstrcpy( id_url, id );
-	else {
-		newstr_strcpy( id_url, prefix );
-		if ( id->data[0]!='/' ) newstr_addchar( id_url, '/' );
-		newstr_newstrcat( id_url, id );
-	}
-}
-
-static int
-url_exists( fields *f, char *urltag, newstr *doi_url )
-{
-	int i, n;
-	if ( urltag ) {
-		n = fields_num( f );
-		for ( i=0; i<n; ++i ) {
-			if ( strcmp( fields_tag( f, i, FIELDS_CHRP ), urltag ) ) continue;
-			if ( strcmp( fields_value( f, i, FIELDS_CHRP ), doi_url->data ) ) continue;
-			return 1;
-		}
-	}
-	return 0;
-}
-
-static void
-xxx_to_url( fields *f, int n, char *http_prefix, char *urltag, newstr *xxx_url )
-{
-	newstr_empty( xxx_url );
-	construct_url( http_prefix, fields_value( f, n, FIELDS_STRP ), xxx_url );
-	if ( url_exists( f, urltag, xxx_url ) )
-		newstr_empty( xxx_url );
-}
-void
-doi_to_url( fields *f, int n, char *urltag, newstr *url )
-{
-	xxx_to_url( f, n, "http://dx.doi.org", urltag, url );
-}
-void
-jstor_to_url( fields *f, int n, char *urltag, newstr *url )
-{
-	xxx_to_url( f, n, "http://www.jstor.org/stable", urltag, url );
-}
-void
-pmid_to_url( fields *f, int n, char *urltag, newstr *url )
-{
-	xxx_to_url( f, n, "http://www.ncbi.nlm.nih.gov/pubmed", urltag, url );
-}
-void
-arxiv_to_url( fields *f, int n, char *urltag, newstr *url )
-{
-	xxx_to_url( f, n, "http://arxiv.org/abs", urltag, url );
-}
-
-/* Rules for the pattern:
- *   '#' = number
- *   isalpha() = match precisely (matchcase==1) or match regardless of case
- *   	(matchcase==0)
- *   all others must match precisely
- */
-static int
-string_pattern( char *s, char *pattern, int matchcase )
-{
-	int patlen, match, i;
-	patlen = strlen( pattern );
-	if ( strlen( s ) < patlen ) return 0; /* too short */
-	for ( i=0; i<patlen; ++i ) {
-		match = 0;
-		if ( pattern[i]=='#' ) {
-			if ( isdigit( (unsigned char)s[i] ) ) match = 1;
-		} else if ( !matchcase && isalpha( (unsigned char)pattern[i] ) ) {
-			if ( tolower((unsigned char)pattern[i])==tolower((unsigned char)s[i])) match = 1;
-		} else {
-			if ( pattern[i] == s[i] ) match = 1;
-		}
-		if ( !match ) return 0;
-	}
-	return 1;
-}
-
-/* science direct is now doing "M3  - doi: DOI: 10.xxxx/xxxxx" */
-int
-is_doi( char *s )
-{
-	if ( string_pattern( s, "##.####/", 0 ) ) return 0;
-	if ( string_pattern( s, "doi:##.####/", 0 ) ) return 4;
-	if ( string_pattern( s, "doi: ##.####/", 0 ) ) return 5;
-	if ( string_pattern( s, "doi: DOI: ##.####/", 0 ) ) return 10;
-	return -1;
-}
diff --git a/lib/doi.h b/lib/doi.h
deleted file mode 100644
index 2bfb57d..0000000
--- a/lib/doi.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * doi.h
- *
- * Copyright (c) Chris Putnam 2004-2015
- *
- * Source code released under the GPL version 2
- *
- */
-#ifndef DOI_H
-#define DOI_H
-
-#include "newstr.h"
-#include "fields.h"
-
-extern void doi_to_url( fields *info, int n, char *urltag, newstr *doi_url );
-extern int is_doi( char *s );
-extern void pmid_to_url( fields *info, int n, char *urltag, newstr *pmid_url );
-extern void arxiv_to_url( fields *info, int n, char *urltag, newstr *arxiv_url );
-extern void jstor_to_url( fields *info, int n, char *urltag, newstr *jstor_url );
-
-#endif
diff --git a/lib/ebiin.c b/lib/ebiin.c
index 1c4ed30..31eaa37 100644
--- a/lib/ebiin.c
+++ b/lib/ebiin.c
@@ -1,7 +1,7 @@
 /*
  * ebiin.c
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -14,7 +14,11 @@
 #include "fields.h"
 #include "xml.h"
 #include "xml_encoding.h"
-#include "ebiin.h"
+#include "bibformats.h"
+
+static int ebiin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );
+static int ebiin_processf( fields *ebiin, char *data, char *filename, long nref, param *p );
+
 
 /*****************************************************
  PUBLIC: void ebiin_initparams()
@@ -52,7 +56,7 @@ ebiin_initparams( param *p, const char *progname )
 /*****************************************************
  PUBLIC: int ebiin_readf()
 *****************************************************/
-int
+static int
 ebiin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset )
 {
 	newstr tmp;
@@ -154,7 +158,7 @@ ebiin_medlinedate_year( fields *info, char *p, newstr *s, int level, char **end
 	*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 );
+		status = fields_add( info, "PARTDATE:YEAR", s->data, level );
 		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
 	return BIBL_OK;
@@ -167,7 +171,7 @@ ebiin_medlinedate_month( fields *info, char *p, newstr *s, int level, char **end
 	newstr_findreplace( s, "-", "/" );
 	if ( newstr_memerr( s ) ) return BIBL_ERR_MEMERR;
 	if ( s->len ) {
-		status = fields_add( info, "PARTMONTH", s->data, level );
+		status = fields_add( info, "PARTDATE:MONTH", s->data, level );
 		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
 	return BIBL_OK;
@@ -179,7 +183,7 @@ ebiin_medlinedate_day( fields *info, char *p, newstr *s, int level, char **end )
 	*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 );
+		status = fields_add( info, "PARTDATE:DAY", s->data, level );
 		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
 	return BIBL_OK;
@@ -231,13 +235,13 @@ static int
 ebiin_journal1( xml *node, fields *info )
 {
 	xml_convert c[] = {
-		{ "ISSN",     NULL, NULL, "ISSN",      1 },
-		{ "Volume",   NULL, NULL, "VOLUME",    1 },
-		{ "Issue",    NULL, NULL, "ISSUE",     1 },
-		{ "Year",     NULL, NULL, "PARTYEAR",  1 },
-		{ "Month",    NULL, NULL, "PARTMONTH", 1 },
-		{ "Day",      NULL, NULL, "PARTDAY",   1 },
-		{ "Language", NULL, NULL, "LANGUAGE",  1 },
+		{ "ISSN",     NULL, NULL, "ISSN",           1 },
+		{ "Volume",   NULL, NULL, "VOLUME",         1 },
+		{ "Issue",    NULL, NULL, "ISSUE",          1 },
+		{ "Year",     NULL, NULL, "PARTDATE:YEAR",  1 },
+		{ "Month",    NULL, NULL, "PARTDATE:MONTH", 1 },
+		{ "Day",      NULL, NULL, "PARTDATE:DAY",   1 },
+		{ "Language", NULL, NULL, "LANGUAGE",       1 },
 	};
 	int nc = sizeof( c ) / sizeof( c[0] ), status, found;
 	if ( xml_hasdata( node ) ) {
@@ -289,7 +293,7 @@ ebiin_pages( fields *info, char *p )
 	}
 
 	if ( sp.len ) {
-		status = fields_add( info, "PAGESTART", sp.data, level );
+		status = fields_add( info, "PAGES:START", sp.data, level );
 		if ( status!=FIELDS_OK ) {
 			ret = BIBL_ERR_MEMERR;
 			goto out;
@@ -301,7 +305,7 @@ ebiin_pages( fields *info, char *p )
 				sp.data[i] = ep.data[i-sp.len+ep.len];
 				up = &(sp);
 		} else up = &(ep);
-		status = fields_add( info, "PAGEEND", up->data, level );
+		status = fields_add( info, "PAGES:STOP", up->data, level );
 		if ( status!=FIELDS_OK ) ret = BIBL_ERR_MEMERR;
 	}
 
@@ -495,33 +499,33 @@ static int
 ebiin_book( xml *node, fields *info, int book_level )
 {
 	xml_convert book[] = {
-		{ "Publisher",              NULL, NULL, "PUBLISHER",  0 },
-		{ "Language",               NULL, NULL, "LANGUAGE",   0 },
-		{ "ISBN10",                 NULL, NULL, "ISBN",       0 },
-		{ "ISBN13",                 NULL, NULL, "ISBN13",     0 },
-		{ "Year",                   NULL, NULL, "YEAR",       0 },
-		{ "Month",                  NULL, NULL, "MONTH",      0 },
-		{ "Day",                    NULL, NULL, "DAY",        0 },
-		{ "PageTotal",              NULL, NULL, "TOTALPAGES", 0 },
-		{ "SeriesName",             NULL, NULL, "TITLE",      1 },
-		{ "SeriesISSN",             NULL, NULL, "ISSN",       0 },
-		{ "OtherReportInformation", NULL, NULL, "NOTES",      0 },
-		{ "Edition",                NULL, NULL, "EDITION",    0 },
+		{ "Publisher",              NULL, NULL, "PUBLISHER",      0 },
+		{ "Language",               NULL, NULL, "LANGUAGE",       0 },
+		{ "ISBN10",                 NULL, NULL, "ISBN",           0 },
+		{ "ISBN13",                 NULL, NULL, "ISBN13",         0 },
+		{ "Year",                   NULL, NULL, "DATE:YEAR",      0 },
+		{ "Month",                  NULL, NULL, "DATE:MONTH",     0 },
+		{ "Day",                    NULL, NULL, "DATE:DAY",       0 },
+		{ "PageTotal",              NULL, NULL, "PAGES:TOTAL",    0 },
+		{ "SeriesName",             NULL, NULL, "TITLE",          1 },
+		{ "SeriesISSN",             NULL, NULL, "ISSN",           0 },
+		{ "OtherReportInformation", NULL, NULL, "NOTES",          0 },
+		{ "Edition",                NULL, NULL, "EDITION",        0 },
 	};
 	int nbook = sizeof( book ) / sizeof( book[0] );
 	xml_convert inbook[] = {
-		{ "Publisher",              NULL, NULL, "PUBLISHER",  1 },
-		{ "Language",               NULL, NULL, "LANGUAGE",   0 },
-		{ "ISBN10",                 NULL, NULL, "ISBN",       1 },
-		{ "ISBN13",                 NULL, NULL, "ISBN13",     1 },
-		{ "Year",                   NULL, NULL, "PARTYEAR",   1 },
-		{ "Month",                  NULL, NULL, "PARTMONTH",  1 },
-		{ "Day",                    NULL, NULL, "PARTDAY",    1 },
-		{ "PageTotal",              NULL, NULL, "TOTALPAGES", 1 },
-		{ "SeriesName",             NULL, NULL, "TITLE",      2 },
-		{ "SeriesISSN",             NULL, NULL, "ISSN",       1 },
-		{ "OtherReportInformation", NULL, NULL, "NOTES",      1 },
-		{ "Edition",                NULL, NULL, "EDITION",    1 },
+		{ "Publisher",              NULL, NULL, "PUBLISHER",      1 },
+		{ "Language",               NULL, NULL, "LANGUAGE",       0 },
+		{ "ISBN10",                 NULL, NULL, "ISBN",           1 },
+		{ "ISBN13",                 NULL, NULL, "ISBN13",         1 },
+		{ "Year",                   NULL, NULL, "PARTDATE:YEAR",  1 },
+		{ "Month",                  NULL, NULL, "PARTDATE:MONTH", 1 },
+		{ "Day",                    NULL, NULL, "PARTDATE:DAY",   1 },
+		{ "PageTotal",              NULL, NULL, "PAGES:TOTAL",    1 },
+		{ "SeriesName",             NULL, NULL, "TITLE",          2 },
+		{ "SeriesISSN",             NULL, NULL, "ISSN",           1 },
+		{ "OtherReportInformation", NULL, NULL, "NOTES",          1 },
+		{ "Edition",                NULL, NULL, "EDITION",        1 },
 	};
 	int ninbook = sizeof( inbook ) / sizeof( inbook[0] );
 	xml_convert *c;
@@ -684,8 +688,8 @@ ebiin_assembleref( xml *node, fields *info )
 	return BIBL_OK;
 }
 
-int
-ebiin_processf( fields *ebiin, char *data, char *filename, long nref )
+static int
+ebiin_processf( fields *ebiin, char *data, char *filename, long nref, param *p )
 {
 	int status;
 	xml top;
diff --git a/lib/ebiin.h b/lib/ebiin.h
deleted file mode 100644
index d468627..0000000
--- a/lib/ebiin.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * ebiin.h
- *
- * Copyright (c) Chris Putnam 2004-2015
- *
- * Source code released under the GPL version 2
- *
- */
-#ifndef PUBIN_H
-#define PUBIN_H
-
-#include "newstr.h"
-#include "fields.h"
-#include "reftypes.h"
-#include "bibutils.h"
-
-extern int ebiin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );
-extern int ebiin_processf( fields *ebiin, char *data, char *filename, long nref );
-
-extern void ebiin_initparams( param *p, const char *progname );
-
-
-extern variants med_all[];
-extern int med_nall;
-
-#endif
-
diff --git a/lib/endin.c b/lib/endin.c
index 173a9ca..d106d55 100644
--- a/lib/endin.c
+++ b/lib/endin.c
@@ -1,7 +1,7 @@
 /*
  * endin.c
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -11,19 +11,27 @@
 #include <string.h>
 #include <ctype.h>
 #include "is_ws.h"
-#include "doi.h"
 #include "newstr.h"
 #include "newstr_conv.h"
 #include "fields.h"
-#include "name.h"
-#include "title.h"
-#include "serialno.h"
+#include "url.h"
 #include "reftypes.h"
-#include "endin.h"
+#include "bibformats.h"
+#include "generic.h"
+
+extern variants end_all[];
+extern int end_nall;
 
 /*****************************************************
  PUBLIC: void endin_initparams()
 *****************************************************/
+
+static int endin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );
+static int endin_processf( fields *endin, char *p, char *filename, long nref, param *pm );
+int endin_typef( fields *endin, char *filename, int nrefs, param *p );
+int endin_convertf( fields *endin, fields *info, int reftype, param *p );
+int endin_cleanf( bibl *bin, param *p );
+
 void
 endin_initparams( param *p, const char *progname )
 {
@@ -82,7 +90,7 @@ readmore( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line )
 	else return newstr_fget( fp, buf, bufsize, bufpos, line );
 }
 
-int
+static int
 endin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset )
 {
 	int haveref = 0, inref = 0;
@@ -156,8 +164,8 @@ process_endline2( newstr *tag, newstr *data, char *p )
 	return p;
 }
 
-int
-endin_processf( fields *endin, char *p, char *filename, long nref )
+static int
+endin_processf( fields *endin, char *p, char *filename, long nref, param *pm )
 {
 	newstr tag, data;
 	int status, n;
@@ -192,7 +200,7 @@ endin_processf( fields *endin, char *p, char *filename, long nref )
  PUBLIC: int endin_typef()
 *****************************************************/
 
-/* Endnote defaults if no %0
+/* Endnote defaults if no %0 tag
  *
  * if %J & %V - journal article
  * if %B - book section
@@ -201,18 +209,16 @@ endin_processf( fields *endin, char *p, char *filename, long nref )
  * if !%B & !%J & !%R & !%I - journal article
  */
 int
-endin_typef( fields *endin, char *filename, int nrefs, param *p, 
-	variants *all, int nall )
+endin_typef( fields *endin, char *filename, int nrefs, param *p )
 {
-	char *refnum = "";
-	int n, reftype, nrefnum, nj, nv, nb, nr, nt, ni;
-	n = fields_find( endin, "%0", 0 );
-	nrefnum = fields_find( endin, "%F", 0 );
-	if ( nrefnum!=-1 ) refnum = endin->data[nrefnum].data;
-	if ( n!=-1 ) {
-		reftype = get_reftype( endin->data[n].data, nrefs, 
-			p->progname, all, nall, refnum );
-	} else {
+	int ntypename, nrefname, is_default, nj, nv, nb, nr, nt, ni;
+	char *refname = "", *typename="";
+
+	ntypename = fields_find( endin, "%0", LEVEL_MAIN );
+	nrefname  = fields_find( endin, "%F", LEVEL_MAIN );
+	if ( nrefname!=-1  ) refname  = fields_value( endin, nrefname,  FIELDS_CHRP_NOUSE );
+	if ( ntypename!=-1 ) typename = fields_value( endin, ntypename, FIELDS_CHRP_NOUSE );
+	else {
 		nj = fields_find( endin, "%J", 0 );
 		nv = fields_find( endin, "%V", 0 );
 		nb = fields_find( endin, "%B", 0 );
@@ -220,26 +226,19 @@ endin_typef( fields *endin, char *filename, int nrefs, param *p,
 		nt = fields_find( endin, "%T", 0 );
 		ni = fields_find( endin, "%I", 0 );
 		if ( nj!=-1 && nv!=-1 ) {
-			reftype = get_reftype( "Journal Article", nrefs,
-					p->progname, all, nall, refnum );
+			typename = "Journal Article";
 		} else if ( nb!=-1 ) {
-			reftype = get_reftype( "Book Section", nrefs,
-					p->progname, all, nall, refnum );
+			typename = "Book Section";
 		} else if ( nr!=-1 && nt==-1 ) {
-			reftype = get_reftype( "Report", nrefs,
-					p->progname, all, nall, refnum );
+			typename = "Report";
 		} else if ( ni!=-1 && nb==-1 && nj==-1 && nr==-1 ) {
-			reftype = get_reftype( "Book", nrefs,
-					p->progname, all, nall, refnum );
+			typename = "Book";
 		} else if ( nb==-1 && nj==-1 && nr==-1 && ni==-1 ) {
-			reftype = get_reftype( "Journal Article", nrefs,
-					p->progname, all, nall, refnum );
-		} else {
-			reftype = get_reftype( "", nrefs, p->progname, 
-					all, nall, refnum ); /* default */
+			typename = "Journal Article";
 		}
 	}
-	return reftype;
+
+	return get_reftype( typename, nrefs, p->progname, p->all, p->nall, refname, &is_default, REFTYPE_CHATTY );
 }
 
 /*****************************************************
@@ -332,35 +331,6 @@ endin_cleanf( bibl *bin, param *p )
  PUBLIC: int endin_convertf(), returns BIBL_OK or BIBL_ERR_MEMERR
 *****************************************************/
 
-static int
-endin_addpage( fields *info, char *p, int level )
-{
-	newstr page;
-	int status;
-
-	newstr_init( &page );
-
-	p = newstr_cpytodelim( &page, skip_ws( p ), "- \t\r\n", 0 );
-	if ( newstr_memerr( &page ) ) return BIBL_ERR_MEMERR;
-	if ( page.len>0 ) {
-		status = fields_add( info, "PAGESTART", page.data, level );
-		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
-	}
-
-	while ( *p && (is_ws(*p) || *p=='-' ) ) p++;
-
-	p = newstr_cpytodelim( &page, p, "- \t\r\n", 0 );
-	if ( newstr_memerr( &page ) ) return BIBL_ERR_MEMERR;
-	if ( page.len>0 ) {
-		status = fields_add( info, "PAGEEND", page.data, level );
-		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
-	}
-
-	newstr_free( &page );
-
-	return BIBL_OK;
-}
-
 /* month_convert()
  * convert month name to number in format MM, e.g. "January" -> "01"
  * if converted, return 1
@@ -403,28 +373,29 @@ month_convert( char *in, char *out )
 }
 
 static int
-endin_adddate( fields *info, char *tag, char *newtag, char *p, int level )
+endin_date( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
 {
 	char *tags[3][2] = {
-		{ "YEAR",  "PARTYEAR" },
-		{ "MONTH", "PARTMONTH" },
-		{ "DAY",   "PARTDAY" }
+		{ "DATE:YEAR",  "PARTDATE:YEAR" },
+		{ "DATE:MONTH", "PARTDATE:MONTH" },
+		{ "DATE:DAY",   "PARTDATE:DAY" }
 	};
+	char *p = invalue->data;
 	char month[10], *m;
 	int part, status;
 	newstr date;
 
 	newstr_init( &date );
 
-	if ( !strncasecmp( newtag, "PART", 4 ) ) part = 1;
+	if ( !strncasecmp( outtag, "PART", 4 ) ) part = 1;
 	else part = 0;
 
 	/* %D YEAR */
-	if ( !strcasecmp( tag, "%D" ) ) {
+	if ( !strcasecmp( intag->data, "%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 );
+			status = fields_add( bibout, tags[0][part], date.data, level );
 			if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 		}
 	}
@@ -432,7 +403,7 @@ endin_adddate( fields *info, char *tag, char *newtag, char *p, int level )
 	/* %8 MONTH DAY, YEAR */
 	/* %8 MONTH, YEAR */
 	/* %8 MONTH YEAR */
-	else if ( !strcasecmp( tag, "%8" ) ) {
+	else if ( !strcasecmp( intag->data, "%8" ) ) {
 
 		/* ...get month */
 		p = newstr_cpytodelim( &date, skip_ws( p ), " ,\n", 0 );
@@ -440,7 +411,7 @@ endin_adddate( fields *info, char *tag, char *newtag, char *p, int level )
 		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 );
+			status = fields_add( bibout, tags[1][part], m, level );
 			if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 		}
 
@@ -451,10 +422,10 @@ endin_adddate( fields *info, char *tag, char *newtag, char *p, int level )
 		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 );
+			status = fields_add( bibout, tags[2][part], date.data, level );
 			if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 		} else if ( date.len==4 ) {
-			status = fields_add( info, tags[0][part], date.data, level );
+			status = fields_add( bibout, tags[0][part], date.data, level );
 			if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 		}
 
@@ -465,7 +436,7 @@ endin_adddate( fields *info, char *tag, char *newtag, char *p, int level )
 		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 );
+			status = fields_add( bibout, tags[0][part], date.data, level );
 			if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 		}
 	}
@@ -474,7 +445,7 @@ endin_adddate( fields *info, char *tag, char *newtag, char *p, int level )
 }
 
 static int
-endin_addtype( fields *info, char *data, int level )
+endin_type( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
 {
 	lookups types[] = {
 		{ "GENERIC",                "ARTICLE" },
@@ -506,17 +477,16 @@ endin_addtype( fields *info, char *data, int level )
 	int  ntypes = sizeof( types ) / sizeof( lookups );
 	int  i, status, found=0;
 	for ( i=0; i<ntypes; ++i ) {
-		if ( !strcasecmp( types[i].oldstr, data ) ) {
+		if ( !strcasecmp( types[i].oldstr, invalue->data ) ) {
 			found = 1;
-			status = fields_add( info, "INTERNAL_TYPE", types[i].newstr, level );
+			status = fields_add( bibout, "INTERNAL_TYPE", types[i].newstr, level );
 			if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 		}
 	}
 	if ( !found ) {
-		fprintf( stderr, "Did not identify reference type '%s'\n",
-			data );
+		fprintf( stderr, "Did not identify reference type '%s'\n", invalue->data );
 		fprintf( stderr, "Defaulting to journal article type\n");
-		status = fields_add( info, "INTERNAL_TYPE", types[0].newstr, level );
+		status = fields_add( bibout, "INTERNAL_TYPE", types[0].newstr, level );
 		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
 	return BIBL_OK;
@@ -531,110 +501,57 @@ endin_notag( param *p, char *tag, char *data )
 	}
 }
 
-/* Wiley's EndNote download has DOI's in "%1" tag */
-static int
-endin_addnotes( fields *info, char *tag, char *value, int level )
-{
-	int fstatus, doi;
-	doi = is_doi( value );
-	if ( doi!=-1 )
-		fstatus = fields_add( info, "DOI", &(value[doi]), level );
-	else
-		fstatus = fields_add( info, tag, value, level );
-	if ( fstatus==FIELDS_OK ) return BIBL_OK;
-	else return BIBL_ERR_MEMERR;
-}
-
-static int
-endin_simple( fields *info, char *tag, char *value, int level )
-{
-	int fstatus = fields_add( info, tag, value, level );
-	if ( fstatus==FIELDS_OK ) return BIBL_OK;
-	else return BIBL_ERR_MEMERR;
-}
-
 int
-endin_convertf( fields *endin, fields *info, int reftype, param *p, variants *all, int nall )
+endin_convertf( fields *bibin, fields *bibout, int reftype, param *p )
 {
-	int i, level, n, process, nfields, ok, fstatus, status = BIBL_OK;
-	char *newtag, *t;
-	newstr *d;
-
-	nfields = fields_num( endin );
+	static int (*convertfns[NUM_REFTYPES])(fields *, int, newstr *, newstr *, int, param *, char *, fields *) = {
+		[ 0 ... NUM_REFTYPES-1 ] = generic_null,
+		[ SIMPLE       ] = generic_simple,
+		[ TITLE        ] = generic_title,
+		[ PERSON       ] = generic_person,
+		[ SERIALNO     ] = generic_serialno,
+		[ PAGES        ] = generic_pages,
+		[ NOTES        ] = generic_notes,
+		[ URL          ] = generic_url,
+		[ TYPE         ] = endin_type,
+		[ DATE         ] = endin_date,
+        };
+
+	int i, level, process, nfields, fstatus, status = BIBL_OK;
+	char *outtag;
+	newstr *intag, *invalue;
+
+	nfields = fields_num( bibin );
 	for ( i=0; i<nfields; ++i ) {
-		/* Ensure that data exists */
-		d = fields_value( endin, i, FIELDS_STRP_NOUSE );
-		if ( d->len == 0 ) {
-			fields_setused( endin, i );
+
+		/* Ensure we have data */
+		if ( fields_nodata( bibin, i ) ) {
+			fields_setused( bibin, i );
 			continue;
 		}
+
+		intag = fields_tag( bibin, i, FIELDS_STRP );
+		invalue = fields_value( bibin, i, FIELDS_STRP );
+
 		/*
-		 * All refer format tags start with '%'.  If we have one
+		 * Refer format tags start with '%'.  If we have one
 		 * that doesn't, assume that it comes from endx2xml
 		 * and just copy and paste to output
 		 */
-		t = fields_tag( endin, i, FIELDS_CHRP );
-		if ( t[0]!='%' ) {
-			fstatus = fields_add( info, t, d->data, endin->level[i] );
+		if ( intag->len && intag->data[0]!='%' ) {
+			fstatus = fields_add( bibout, intag->data, invalue->data, bibin->level[i] );
 			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 			continue;
 		}
 
-		n = translate_oldtag( t, reftype, all, nall, &process, &level, &newtag );
-		if ( n==-1 ) {
-			endin_notag( p, t, d->data );
+		if ( !translate_oldtag( intag->data, reftype, p->all, p->nall, &process, &level, &outtag ) ) {
+			endin_notag( p, intag->data, invalue->data );
 			continue;
 		}
-		if ( process == ALWAYS ) continue; /* add these later */
-
-		fields_setused( endin, i );
-
-		switch ( process ) {
-
-		case SIMPLE:
-			status = endin_simple( info, newtag, d->data, level );
-			break;
-
-		case TYPE:
-			status = endin_addtype( info, d->data, level );
-			break;
-
-		case TITLE:
-			ok = title_process( info, newtag, d->data, level, p->nosplittitle );
-			if ( !ok ) status = BIBL_ERR_MEMERR;
-			status = BIBL_OK;
-			break;
-
-		case PERSON:
-			ok = name_add( info, newtag, d->data, level, &(p->asis), &(p->corps) );
-			if ( !ok ) status = BIBL_ERR_MEMERR;
-			status = BIBL_OK;
-			break;
-
-		case DATE:
-			status = endin_adddate( info, t, newtag,d->data,level);
-			break;
-
-		case PAGES:
-			status = endin_addpage( info, d->data, level );
-			break;
-
-		case SERIALNO:
-			ok = addsn( info, d->data, level );
-			if ( !ok ) status = BIBL_ERR_MEMERR;
-			status = BIBL_OK;
-			break;
-
-		case NOTES:
-			status = endin_addnotes( info, newtag, d->data, level );
-			break;
-
-		default:
-			fprintf(stderr,"%s: internal error -- illegal process number %d\n", p->progname, process );
-			status = BIBL_OK;
-			break;
-		}
 
+		fields_setused( bibin, i );
+
+		status = convertfns[ process ]( bibin, i, intag, invalue, level, p, outtag, bibout );
 		if ( status!=BIBL_OK ) return status;
 
 	}
diff --git a/lib/endin.h b/lib/endin.h
deleted file mode 100644
index 45269d9..0000000
--- a/lib/endin.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * endin.h
- *
- * Copyright (c) Chris Putnam 2003-2015
- *
- * Source code released under the GPL version 2
- *
- */
-#ifndef ENDIN_H
-#define ENDIN_H
-
-#include "newstr.h"
-#include "fields.h"
-#include "reftypes.h"
-#include "bibutils.h"
-
-extern int endin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );
-extern int endin_processf( fields *endin, char *p, char *filename, long nref );
-extern int endin_typef( fields *endin, char *filename, int nrefs, param *p, variants *all, int nall );
-extern int endin_convertf( fields *endin, fields *info, int reftype, param *p, variants *all, int nall );
-extern int endin_cleanf( bibl *bin, param *p );
-
-extern void endin_initparams( param *p, const char *progname );
-
-extern variants end_all[];
-extern int end_nall;
-
-
-#endif
-
diff --git a/lib/endout.c b/lib/endout.c
index 848925b..91a9485 100644
--- a/lib/endout.c
+++ b/lib/endout.c
@@ -1,7 +1,7 @@
 /*
  * endout.c
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -14,9 +14,14 @@
 #include "newstr.h"
 #include "strsearch.h"
 #include "fields.h"
-#include "doi.h"
 #include "name.h"
-#include "endout.h"
+#include "title.h"
+#include "url.h"
+#include "bibformats.h"
+
+static int  endout_write( fields *in, FILE *fp, param *p, unsigned long refnum );
+static void endout_writeheader( FILE *outptr, param *p );
+
 
 void
 endout_initparams( param *p, const char *progname )
@@ -142,7 +147,7 @@ typedef struct match_type {
 } match_type;
 
 static int
-get_type( fields *info, param *p, unsigned long refnum )
+get_type( fields *in, param *p, unsigned long refnum )
 {
 	/* Comment out TYPE_GENERIC entries as that is default, but
          * keep in source as record of mapping decision. */
@@ -257,20 +262,20 @@ get_type( fields *info, param *p, unsigned long refnum )
 	char *tag, *data;
 
 	/* Determine type from genre information */
-	for ( i=0; i<info->n; ++i ) {
-		tag = info->tag[i].data;
+	for ( i=0; i<in->n; ++i ) {
+		tag = fields_tag( in, i, FIELDS_CHRP );
 		if ( strcasecmp( tag, "GENRE" )!=0 &&
 		     strcasecmp( tag, "NGENRE" )!=0 ) continue;
-		data = info->data[i].data;
+		data = fields_value( in, i, FIELDS_CHRP );
 		for ( j=0; j<nmatch_genres; ++j ) {
 			if ( !strcasecmp( data, match_genres[j].name ) ) {
 				type = match_genres[j].type;
-				fields_setused( info, i );
+				fields_setused( in, i );
 			}
 		}
 		if ( p->verbose ) {
 			if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
-			fprintf( stderr, "Type from tag '%s' data '%s': ", info->tag[i].data, info->data[i].data );
+			fprintf( stderr, "Type from tag '%s' data '%s': ", tag, data );
 			write_type( stderr, type );
 			fprintf( stderr, "\n" );
 		}
@@ -280,17 +285,17 @@ get_type( fields *info, param *p, unsigned long refnum )
 			else if ( !strcasecmp( data, "thesis" ) )
 				type = TYPE_THESIS;
 			else if ( !strcasecmp( data, "book" ) ) {
-				if ( info->level[i]==0 ) type = TYPE_BOOK;
+				if ( in->level[i]==0 ) type = TYPE_BOOK;
 				else type = TYPE_INBOOK;
 			}
 			else if ( !strcasecmp( data, "collection" ) ) {
-				if ( info->level[i]==0 ) type = TYPE_BOOK;
+				if ( in->level[i]==0 ) type = TYPE_BOOK;
 				else type = TYPE_INBOOK;
 			}
-			if ( type!=TYPE_UNKNOWN ) fields_setused( info, i );
+			if ( type!=TYPE_UNKNOWN ) fields_setused( in, i );
 		}
 		/* the inbook type should be defined if 'book' in host */
-		if ( type==TYPE_BOOK && info->level[i]>0 ) type = TYPE_INBOOK;
+		if ( type==TYPE_BOOK && in->level[i]>0 ) type = TYPE_INBOOK;
 	}
 	if ( p->verbose ) {
 		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
@@ -301,15 +306,15 @@ get_type( fields *info, param *p, unsigned long refnum )
 
 	/* Determine from resource information */
 	if ( type==TYPE_UNKNOWN ) {
-		for ( i=0; i<info->n; ++i ) {
-			if ( strcasecmp( info->tag[i].data, "RESOURCE" ) )
+		for ( i=0; i<in->n; ++i ) {
+			if ( strcasecmp( fields_tag( in, i, FIELDS_CHRP ), "RESOURCE" ) )
 				continue;
-			data = info->data[i].data;
+			data = fields_value( in, i, FIELDS_CHRP );
 			if ( !strcasecmp( data, "moving image" ) )
 				type = TYPE_FILMBROADCAST;
 			else if ( !strcasecmp( data, "software, multimedia" ) )
 				type = TYPE_PROGRAM;
-			if ( type!=TYPE_UNKNOWN ) fields_setused( info, i );
+			if ( type!=TYPE_UNKNOWN ) fields_setused( in, i );
 		}
 		if ( p->verbose ) {
 			if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
@@ -321,12 +326,12 @@ get_type( fields *info, param *p, unsigned long refnum )
 
 	/* Determine from issuance information */
 	if ( type==TYPE_UNKNOWN ) {
-		for ( i=0; i<info->n; ++i ) {
-			if ( strcasecmp( info->tag[i].data, "ISSUANCE" ) )
+		for ( i=0; i<in->n; ++i ) {
+			if ( strcasecmp( fields_tag( in, i, FIELDS_CHRP ), "ISSUANCE" ) )
 				continue;
-			data = info->data[i].data;
+			data = fields_value( in, i, FIELDS_CHRP );
 			if ( !strcasecmp( data, "monographic" ) ) {
-				if ( info->level[i]==0 ) type = TYPE_BOOK;
+				if ( in->level[i]==0 ) type = TYPE_BOOK;
 				else type = TYPE_INBOOK;
 			}
 		}
@@ -340,14 +345,14 @@ get_type( fields *info, param *p, unsigned long refnum )
 
 	/* default to generic or book chapter, depending on maxlevel */
 	if ( type==TYPE_UNKNOWN ) {
-		maxlevel = fields_maxlevel( info );
+		maxlevel = fields_maxlevel( in );
 		if ( maxlevel > 0 ) type = TYPE_INBOOK;
 		else {
 			if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
 			fprintf( stderr, "Cannot identify TYPE in reference %lu ", refnum+1 );
-			n = fields_find( info, "REFNUM", -1 );
+			n = fields_find( in, "REFNUM", -1 );
 			if ( n!=-1 )
-				fprintf( stderr, " %s", info->data[n].data );
+				fprintf( stderr, " %s", (char *) fields_value( in, n, FIELDS_CHRP ) );
 			fprintf( stderr, " (defaulting to generic)\n" );
 			type = TYPE_GENERIC;
 		}
@@ -364,7 +369,7 @@ get_type( fields *info, param *p, unsigned long refnum )
 }
 
 static void
-output_type( FILE *fp, int type, param *p )
+append_type( int type, fields *out, param *p, int *status )
 {
 	/* These are restricted to Endnote-defined types */
 	match_type genrenames[] = {
@@ -410,315 +415,331 @@ output_type( FILE *fp, int type, param *p )
 		{ "Unpublished Work",       TYPE_UNPUBLISHED },
 	};
 	int ngenrenames = sizeof( genrenames ) / sizeof( genrenames[0] );
-	int i, found = 0;
-	fprintf( fp, "%%0 ");
+	int i, fstatus, found = 0;
 	for ( i=0; i<ngenrenames && !found; ++i ) {
 		if ( genrenames[i].type == type ) {
-			fprintf( fp, "%s", genrenames[i].name );
+			fstatus = fields_add( out, "%0", genrenames[i].name, LEVEL_MAIN );
+			if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 			found = 1;
 		}
 	}
 	if ( !found ) {
-		fprintf( fp, "Generic" );
+		fstatus = fields_add( out, "%0", "Generic", LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
 		fprintf( stderr, "Cannot identify type %d\n", type );
 	}
-	fprintf( fp, "\n" );
 }
 
-static void
-output_title( FILE *fp, fields *info, char *full, char *sub, char *endtag, 
-		int level )
+static int
+append_title( fields *in, char *full, char *sub, char *endtag,
+		int level, fields *out, int *status )
 {
-	newstr *mainttl = fields_findv( info, level, FIELDS_STRP, full );
-	newstr *subttl  = fields_findv( info, level, FIELDS_STRP, sub );
+	newstr *mainttl = fields_findv( in, level, FIELDS_STRP, full );
+	newstr *subttl  = fields_findv( in, level, FIELDS_STRP, sub );
+	newstr fullttl;
+	int fstatus;
 
-	if ( !mainttl ) return;
+	newstr_init( &fullttl );
+	title_combine( &fullttl, mainttl, subttl );
 
-	fprintf( fp, "%s %s", endtag, mainttl->data );
-	if ( subttl ) {
-		if ( mainttl->len > 0 &&
-		     mainttl->data[ mainttl->len-1 ]!='?' )
-				fprintf( fp, ":" );
-		fprintf( fp, " %s", subttl->data );
+	if ( fullttl.len ) {
+		fstatus = fields_add( out, endtag, newstr_cstr( &fullttl ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 	}
-	fprintf( fp, "\n" );
+
+	newstr_free( &fullttl );
+
+	return 1;
 }
 
 static void
-output_people( FILE *fp, fields *info, char *tag, char *entag, int level )
+append_people( fields *in, char *tag, char *entag, int level, fields *out, int *status )
 {
+	int i, n, flvl, fstatus;
 	newstr oneperson;
-	int i, n, flvl;
 	char *ftag;
+
 	newstr_init( &oneperson );
-	n = fields_num( info );
+	n = fields_num( in );
 	for ( i=0; i<n; ++i ) {
-		flvl = fields_level( info, i );
+		flvl = fields_level( in, i );
 		if ( level!=LEVEL_ANY && flvl!=level ) continue;
-		ftag = fields_tag( info, i, FIELDS_CHRP );
+		ftag = fields_tag( in, i, FIELDS_CHRP );
 		if ( !strcasecmp( ftag, tag ) ) {
-			name_build_withcomma( &oneperson, fields_value( info, i, FIELDS_CHRP ) );
-			fprintf( fp, "%s %s\n", entag, oneperson.data );
+			name_build_withcomma( &oneperson, fields_value( in, i, FIELDS_CHRP ) );
+			fstatus = fields_add_can_dup( out, entag, newstr_cstr( &oneperson ), LEVEL_MAIN );
+			if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 		}
 	}
 	newstr_free( &oneperson );
 }
 
 static void
-output_pages( FILE *fp, fields *info )
+append_pages( fields *in, fields *out, int *status )
 {
-	char *sn = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "PAGESTART" );
-	char *en = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "PAGEEND" );
-	char *ar;
+	char *ar, *sn, *en;
+	newstr pages;
+	int fstatus;
+
+	sn = fields_findv( in, LEVEL_ANY, FIELDS_CHRP, "PAGES:START" );
+	en = fields_findv( in, LEVEL_ANY, FIELDS_CHRP, "PAGES:STOP" );
 	if ( sn || en ) {
-		fprintf( fp, "%%P ");
-		if ( sn ) fprintf( fp, "%s", sn );
-		if ( sn && en ) fprintf( fp, "-" );
-		if ( en ) fprintf( fp, "%s", en );
-		fprintf( fp, "\n" );
+		newstr_init( &pages );
+		if ( sn ) newstr_strcpy( &pages, sn );
+		if ( sn && en ) newstr_strcat( &pages, "-" );
+		if ( en ) newstr_strcat( &pages, en );
+		fstatus = fields_add( out, "%P", newstr_cstr( &pages ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+		newstr_free( &pages );
 	} else {
-		ar = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "ARTICLENUMBER" );
-		if ( ar ) fprintf( fp, "%%P %s\n", ar );
+		ar = fields_findv( in, LEVEL_ANY, FIELDS_CHRP, "ARTICLENUMBER" );
+		if ( ar ) {
+			fstatus = fields_add( out, "%P", ar, LEVEL_MAIN );
+			if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+		}
 	}
 }
 
 static void
-output_doi( FILE *fp, fields *f )
+append_urls( fields *in, fields *out, int *status )
 {
-	newstr doi_url;
-	int i, n;
-
-	newstr_init( &doi_url );
+	int lstatus;
+	list types;
 
-	n = fields_num( f );
-	for ( i=0; i<n; ++i ) {
-		if ( !fields_match_tag( f, i, "DOI" ) ) continue;
-		doi_to_url( f, i, "URL", &doi_url );
-		if ( doi_url.len )
-			fprintf( fp, "%%U %s\n", doi_url.data );
+	lstatus = list_init_valuesc( &types, "URL", "DOI", "PMID", "PMC", "ARXIV", "JSTOR", "MRNUMBER", NULL );
+	if ( lstatus!=LIST_OK ) {
+		*status = BIBL_ERR_MEMERR;
+		return;
 	}
 
-	newstr_free( &doi_url );
-}
+	*status = urls_merge_and_add( in, LEVEL_ANY, out, "%U", LEVEL_MAIN, &types );
 
-static void
-output_pmid( FILE *fp, fields *f )
-{
-	newstr pmid_url;
-	int i, n;
-
-	newstr_init( &pmid_url );
-
-	n = fields_num( f );
-	for ( i=0; i<n; ++i ) {
-		if ( !fields_match_tag( f, i, "PMID" ) ) continue;
-		pmid_to_url( f, i, "URL", &pmid_url );
-		if ( pmid_url.len )
-			fprintf( fp, "%%U %s\n", pmid_url.data );
-	}
-
-	newstr_free( &pmid_url );
-}
-
-static void
-output_arxiv( FILE *fp, fields *f )
-{
-	newstr arxiv_url;
-	int i, n;
-
-	newstr_init( &arxiv_url );
-
-	n = fields_num( f );
-	for ( i=0; i<n; ++i ) {
-		if ( !fields_match_tag( f, i, "ARXIV" ) ) continue;
-		arxiv_to_url( f, i, "URL", &arxiv_url );
-		if ( arxiv_url.len )
-			fprintf( fp, "%%U %s\n", arxiv_url.data );
-	}
-
-	newstr_free( &arxiv_url );
+	list_free( &types );
 }
 
 static void
-output_jstor( FILE *fp, fields *f )
+append_year( fields *in, fields *out, int *status )
 {
-	newstr jstor_url;
-	int i, n;
-
-	newstr_init( &jstor_url );
+	int fstatus;
+	char *year;
 
-	n = fields_num( f );
-	for ( i=0; i<n; ++i ) {
-		if ( !fields_match_tag( f, i, "JSTOR" ) ) continue;
-		jstor_to_url( f, i, "URL", &jstor_url );
-		if ( jstor_url.len )
-			fprintf( fp, "%%U %s\n", jstor_url.data );
+	year = fields_findv_firstof( in, LEVEL_ANY, FIELDS_CHRP, "DATE:YEAR", "PARTDATE:YEAR", NULL );
+	if ( year ) {
+		fstatus = fields_add( out, "%D", year, LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 	}
-
-	newstr_free( &jstor_url );
-}
-
-static void
-output_year( FILE *fp, fields *info, int level )
-{
-	char *year = fields_findv_firstof( info, level, FIELDS_CHRP,
-			"YEAR", "PARTYEAR", NULL );
-	if ( year )
-		fprintf( fp, "%%D %s\n", year );
 }
 
 static void
-output_monthday( FILE *fp, fields *info, int level )
+append_monthday( fields *in, fields *out, int *status )
 {
 	char *months[12] = { "January", "February", "March", "April",
 		"May", "June", "July", "August", "September", "October",
 		"November", "December" };
-	int m;
-	char *month = fields_findv_firstof( info, level, FIELDS_CHRP,
-			"MONTH", "PARTMONTH", NULL );
-	char *day   = fields_findv_firstof( info, level, FIELDS_CHRP,
-			"DAY", "PARTDAY", NULL );
+	char *month, *day;
+	int m, fstatus;
+	newstr monday;
+
+	newstr_init( &monday );
+	month = fields_findv_firstof( in, LEVEL_ANY, FIELDS_CHRP, "DATE:MONTH", "PARTDATE:MONTH", NULL );
+	day   = fields_findv_firstof( in, LEVEL_ANY, FIELDS_CHRP, "DATE:DAY",   "PARTDATE:DAY",   NULL );
 	if ( month || day ) {
-		fprintf( fp, "%%8 " );
 		if ( month ) {
 			m = atoi( month );
-			if ( m>0 && m<13 ) fprintf( fp, "%s", months[m-1] );
-			else fprintf( fp, "%s", month );
+			if ( m>0 && m<13 ) newstr_strcpy( &monday, months[m-1] );
+			else newstr_strcpy( &monday, month );
 		}
-		if ( month && day ) fprintf( fp, " " );
-		if ( day ) fprintf( fp, "%s", day );
-		fprintf( fp, "\n" );
+		if ( month && day ) newstr_strcat( &monday, " " );
+		if ( day ) newstr_strcat( &monday, day );
+		fstatus = fields_add( out, "%8", newstr_cstr( &monday ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 	}
+	newstr_free( &monday );
 }
 
 static void
-output_thesishint( FILE *fp, int type )
+append_thesishint( int type, fields *out, int *status )
 {
-	if ( type==TYPE_MASTERSTHESIS )
-		fprintf( fp, "%%9 Masters thesis\n" );
-	else if ( type==TYPE_PHDTHESIS )
-		fprintf( fp, "%%9 Ph.D. thesis\n" );
-	else if ( type==TYPE_DIPLOMATHESIS )
-		fprintf( fp, "%%9 Diploma thesis\n" );
-	else if ( type==TYPE_DOCTORALTHESIS )
-		fprintf( fp, "%%9 Doctoral thesis\n" );
-	else if ( type==TYPE_HABILITATIONTHESIS )
-		fprintf( fp, "%%9 Habilitation thesis\n" );
+	int fstatus;
+
+	if ( type==TYPE_MASTERSTHESIS ) {
+		fstatus = fields_add( out, "%9", "Masters thesis", LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
+	else if ( type==TYPE_PHDTHESIS ) {
+		fstatus = fields_add( out, "%9", "Ph.D. thesis", LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
+	else if ( type==TYPE_DIPLOMATHESIS ) {
+		fstatus = fields_add( out, "%9", "Diploma thesis", LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
+	else if ( type==TYPE_DOCTORALTHESIS ) {
+		fstatus = fields_add( out, "%9", "Doctoral thesis", LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
+	else if ( type==TYPE_HABILITATIONTHESIS ) {
+		fstatus = fields_add( out, "%9", "Habilitation thesis", LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
 }
 
 static void
-output_easyall( FILE *fp, fields *info, char *tag, char *entag, int level )
+append_easyall( fields *in, char *tag, char *entag, int level, fields *out, int *status )
 {
+	int i, fstatus;
 	vplist a;
-	int i;
 	vplist_init( &a );
-	fields_findv_each( info, level, FIELDS_CHRP, &a, tag );
-	for ( i=0; i<a.n; ++i )
-		fprintf( fp, "%s %s\n", entag, (char *) vplist_get( &a, i ) );
+	fields_findv_each( in, level, FIELDS_CHRP, &a, tag );
+	for ( i=0; i<a.n; ++i ) {
+		fstatus = fields_add( out, entag, (char *) vplist_get( &a, i ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
 	vplist_free( &a );
 }
 
 static void
-output_easy( FILE *fp, fields *info, char *tag, char *entag, int level )
+append_easy( fields *in, char *tag, char *entag, int level, fields *out, int *status )
 {
-	char *value = fields_findv( info, level, FIELDS_CHRP, tag );
-	if ( value ) fprintf( fp, "%s %s\n", entag, value );
+	char *value;
+	int fstatus;
+
+	value = fields_findv( in, level, FIELDS_CHRP, tag );
+	if ( value ) {
+		fstatus = fields_add( out, entag, value, LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
 }
 
-void
-endout_write( fields *info, FILE *fp, param *p, unsigned long refnum )
+static int
+append_data( fields *in, fields *out, param *p, unsigned long refnum )
 {
-	int type;
+	int added, type, status = BIBL_OK;
 
-	fields_clearused( info );
+	fields_clearused( in );
 
-	type = get_type( info, p, refnum );
+	type = get_type( in, p, refnum );
 
-	output_type( fp, type, p );
+	append_type( type, out, p, &status );
 
-	output_title( fp, info, "TITLE",      "SUBTITLE",      "%T", LEVEL_MAIN );
-	output_title( fp, info, "SHORTTITLE", "SHORTSUBTITLE", "%!", LEVEL_MAIN );
+	added = append_title( in, "TITLE",      "SUBTITLE",      "%T", LEVEL_MAIN, out, &status );
+	if ( added==0 ) append_title( in, "SHORTTITLE", "SHORTSUBTITLE", "%T", LEVEL_MAIN, out, &status );
+	else            append_title( in, "SHORTTITLE", "SHORTSUBTITLE", "%!", LEVEL_MAIN, out, &status );
 
-	output_people( fp, info, "AUTHOR",     "%A", LEVEL_MAIN );
-	output_people( fp, info, "EDITOR",     "%E", LEVEL_MAIN );
+	append_people( in, "AUTHOR",     "%A", LEVEL_MAIN, out, &status );
+	append_people( in, "EDITOR",     "%E", LEVEL_MAIN, out, &status );
 	if ( type==TYPE_ARTICLE || type==TYPE_MAGARTICLE || type==TYPE_ELECTRONICARTICLE || type==TYPE_NEWSARTICLE )
-		output_people( fp, info, "EDITOR", "%E", LEVEL_HOST );
+		append_people( in, "EDITOR", "%E", LEVEL_HOST, out, &status );
 	else if ( type==TYPE_INBOOK || type==TYPE_INPROCEEDINGS ) {
-		output_people( fp, info, "EDITOR", "%E", LEVEL_HOST );
+		append_people( in, "EDITOR", "%E", LEVEL_HOST, out, &status );
 	} else {
-		output_people( fp, info, "EDITOR", "%Y", LEVEL_HOST );
+		append_people( in, "EDITOR", "%Y", LEVEL_HOST, out, &status );
 	}
-	output_people( fp, info, "TRANSLATOR", "%H", LEVEL_ANY  );
+	append_people( in, "TRANSLATOR", "%H", LEVEL_ANY,    out, &status  );
 
-	output_people( fp, info, "AUTHOR",     "%Y", LEVEL_SERIES );
-	output_people( fp, info, "EDITOR",     "%Y", LEVEL_SERIES );
+	append_people( in, "AUTHOR",     "%Y", LEVEL_SERIES, out, &status );
+	append_people( in, "EDITOR",     "%Y", LEVEL_SERIES, out, &status );
 
 	if ( type==TYPE_CASE )
-		output_easy(    fp, info, "AUTHOR:CORP", "%I", LEVEL_MAIN );
+		append_easy(    in, "AUTHOR:CORP", "%I", LEVEL_MAIN, out, &status );
 	else if ( type==TYPE_HEARING )
-		output_easyall( fp, info, "AUTHOR:CORP", "%S", LEVEL_MAIN );
+		append_easyall( in, "AUTHOR:CORP", "%S", LEVEL_MAIN, out, &status );
 	else if ( type==TYPE_NEWSARTICLE )
-		output_people(  fp, info, "REPORTER",    "%A", LEVEL_MAIN );
+		append_people(  in, "REPORTER",    "%A", LEVEL_MAIN, out, &status );
 	else if ( type==TYPE_COMMUNICATION )
-		output_people(  fp, info, "RECIPIENT",   "%E", LEVEL_ANY  );
+		append_people(  in, "RECIPIENT",   "%E", LEVEL_ANY,  out, &status  );
 	else {
-		output_easyall( fp, info, "AUTHOR:CORP",     "%A", LEVEL_MAIN );
-		output_easyall( fp, info, "AUTHOR:ASIS",     "%A", LEVEL_MAIN );
-		output_easyall( fp, info, "EDITOR:CORP",     "%E", LEVEL_ANY  );
-		output_easyall( fp, info, "EDITOR:ASIS",     "%E", LEVEL_ANY  );
-		output_easyall( fp, info, "TRANSLATOR:CORP", "%H", LEVEL_ANY  );
-		output_easyall( fp, info, "TRANSLATOR:ASIS", "%H", LEVEL_ANY  );
+		append_easyall( in, "AUTHOR:CORP",     "%A", LEVEL_MAIN, out, &status );
+		append_easyall( in, "AUTHOR:ASIS",     "%A", LEVEL_MAIN, out, &status );
+		append_easyall( in, "EDITOR:CORP",     "%E", LEVEL_ANY,  out, &status  );
+		append_easyall( in, "EDITOR:ASIS",     "%E", LEVEL_ANY,  out, &status  );
+		append_easyall( in, "TRANSLATOR:CORP", "%H", LEVEL_ANY,  out, &status  );
+		append_easyall( in, "TRANSLATOR:ASIS", "%H", LEVEL_ANY,  out, &status  );
+	}
+
+	if ( type==TYPE_ARTICLE || type==TYPE_MAGARTICLE || type==TYPE_ELECTRONICARTICLE || type==TYPE_NEWSARTICLE ) {
+		added = append_title( in, "TITLE", "SUBTITLE", "%J", LEVEL_HOST, out, &status );
+		if ( added==0 ) append_title( in, "SHORTTITLE", "SHORTSUBTITLE", "%J", LEVEL_HOST, out, &status );
 	}
 
-	if ( type==TYPE_ARTICLE || type==TYPE_MAGARTICLE || type==TYPE_ELECTRONICARTICLE || type==TYPE_NEWSARTICLE )
-		output_title( fp, info, "TITLE", "SUBTITLE", "%J", LEVEL_HOST );
 	else if ( type==TYPE_INBOOK || type==TYPE_INPROCEEDINGS ) {
-		output_title( fp, info, "TITLE", "SUBTITLE", "%B", LEVEL_HOST );
-	} else {
-		output_title( fp, info, "TITLE", "SUBTITLE", "%S", LEVEL_HOST );
+		added = append_title( in, "TITLE", "SUBTITLE", "%B", LEVEL_HOST, out, &status );
+		if ( added==0 ) append_title( in, "SHORTTITLE", "SHORTSUBTITLE", "%B", LEVEL_HOST, out, &status );
+	}
+
+	else {
+		added = append_title( in, "TITLE", "SUBTITLE", "%S", LEVEL_HOST, out, &status );
+		if ( added==0 ) append_title( in, "SHORTTITLE", "SHORTSUBTITLE", "%S", LEVEL_HOST, out, &status );
 	}
 
 	if ( type!=TYPE_CASE && type!=TYPE_HEARING ) {
-		output_title( fp, info, "TITLE", "SUBTITLE", "%S", LEVEL_SERIES );
+		append_title( in, "TITLE", "SUBTITLE", "%S", LEVEL_SERIES, out, &status );
+	}
+
+	append_year    ( in, out, &status );
+	append_monthday( in, out, &status );
+
+	append_easy    ( in, "VOLUME",             "%V", LEVEL_ANY, out, &status );
+	append_easy    ( in, "ISSUE",              "%N", LEVEL_ANY, out, &status );
+	append_easy    ( in, "NUMBER",             "%N", LEVEL_ANY, out, &status );
+	append_easy    ( in, "EDITION",            "%7", LEVEL_ANY, out, &status );
+	append_easy    ( in, "PUBLISHER",          "%I", LEVEL_ANY, out, &status );
+	append_easy    ( in, "ADDRESS",            "%C", LEVEL_ANY, out, &status );
+	append_easy    ( in, "DEGREEGRANTOR",      "%C", LEVEL_ANY, out, &status );
+	append_easy    ( in, "DEGREEGRANTOR:CORP", "%C", LEVEL_ANY, out, &status );
+	append_easy    ( in, "DEGREEGRANTOR:ASIS", "%C", LEVEL_ANY, out, &status );
+	append_easy    ( in, "SERIALNUMBER",       "%@", LEVEL_ANY, out, &status );
+	append_easy    ( in, "ISSN",               "%@", LEVEL_ANY, out, &status );
+	append_easy    ( in, "ISBN",               "%@", LEVEL_ANY, out, &status );
+	append_easy    ( in, "LANGUAGE",           "%G", LEVEL_ANY, out, &status );
+	append_easy    ( in, "REFNUM",             "%F", LEVEL_ANY, out, &status );
+	append_easyall ( in, "NOTES",              "%O", LEVEL_ANY, out, &status );
+	append_easy    ( in, "ABSTRACT",           "%X", LEVEL_ANY, out, &status );
+	append_easy    ( in, "CLASSIFICATION"   ,  "%L", LEVEL_ANY, out, &status );
+	append_easyall ( in, "KEYWORD",            "%K", LEVEL_ANY, out, &status );
+	append_easyall ( in, "NGENRE",             "%9", LEVEL_ANY, out, &status );
+	append_thesishint( type, out, &status );
+	append_easyall ( in, "DOI",                "%R", LEVEL_ANY, out, &status );
+	append_easyall ( in, "URL",                "%U", LEVEL_ANY, out, &status );
+	append_easyall ( in, "FILEATTACH",         "%U", LEVEL_ANY, out, &status );
+	append_urls    ( in, out, &status );
+	append_pages   ( in, out, &status );
+
+	return status;
+}
+
+static void
+output( FILE *fp, fields *out )
+{
+	int i;
+
+	for ( i=0; i<out->n; ++i ) {
+		fprintf( fp, "%s %s\n",
+			(char*) fields_tag( out, i, FIELDS_CHRP ),
+			(char*) fields_value( out, i, FIELDS_CHRP )
+		);
 	}
 
-	output_year( fp, info, LEVEL_ANY );
-	output_monthday( fp, info, LEVEL_ANY );
-
-	output_easy( fp, info, "VOLUME",             "%V", LEVEL_ANY );
-	output_easy( fp, info, "ISSUE",              "%N", LEVEL_ANY );
-	output_easy( fp, info, "NUMBER",             "%N", LEVEL_ANY );
-	output_easy( fp, info, "EDITION",            "%7", LEVEL_ANY );
-	output_easy( fp, info, "PUBLISHER",          "%I", LEVEL_ANY );
-	output_easy( fp, info, "ADDRESS",            "%C", LEVEL_ANY );
-	output_easy( fp, info, "DEGREEGRANTOR",      "%C", LEVEL_ANY );
-	output_easy( fp, info, "DEGREEGRANTOR:CORP", "%C", LEVEL_ANY );
-	output_easy( fp, info, "DEGREEGRANTOR:ASIS", "%C", LEVEL_ANY );
-	output_easy( fp, info, "SERIALNUMBER",       "%@", LEVEL_ANY );
-	output_easy( fp, info, "ISSN",               "%@", LEVEL_ANY );
-	output_easy( fp, info, "ISBN",               "%@", LEVEL_ANY );
-	output_easy( fp, info, "LANGUAGE",           "%G", LEVEL_ANY );
-	output_easy( fp, info, "REFNUM",             "%F", LEVEL_ANY );
-	output_easyall( fp, info, "NOTES",           "%O", LEVEL_ANY );
-	output_easy( fp, info, "ABSTRACT",           "%X", LEVEL_ANY );
-	output_easy( fp, info, "CLASSIFICATION",     "%L", LEVEL_ANY );
-	output_easyall( fp, info, "KEYWORD",         "%K", LEVEL_ANY );
-	output_easyall( fp, info, "NGENRE",          "%9", LEVEL_ANY );
-	output_thesishint( fp, type );
-	output_easyall( fp, info, "DOI",             "%R", LEVEL_ANY );
-	output_easyall( fp, info, "URL",             "%U", LEVEL_ANY ); 
-	output_easyall( fp, info, "FILEATTACH",      "%U", LEVEL_ANY ); 
-	output_doi( fp, info );
-	output_pmid( fp, info );
-	output_arxiv( fp, info );
-	output_jstor( fp, info );
-	output_pages( fp, info );
 	fprintf( fp, "\n" );
 	fflush( fp );
 }
 
-void
+static int
+endout_write( fields *in, FILE *fp, param *p, unsigned long refnum )
+{
+	int status;
+	fields out;
+
+	fields_init( &out );
+	status = append_data( in, &out, p, refnum );
+	if ( status==BIBL_OK ) output( fp, &out );
+	fields_free( &out );
+
+	return status;
+}
+
+static void
 endout_writeheader( FILE *outptr, param *p )
 {
 	if ( p->utf8bom ) utf8_writebom( outptr );
diff --git a/lib/endout.h b/lib/endout.h
deleted file mode 100644
index 148b233..0000000
--- a/lib/endout.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * endout.h
- *
- * Copyright (c) Chris Putnam 2005-2015
- *
- * Source code released under the GPL version 2
- *
- */
-#ifndef ENDOUT_H
-#define ENDOUT_H
-
-#include <stdio.h>
-#include "bibutils.h"
-
-extern void endout_write( fields *info, FILE *fp, param *p, 
-		unsigned long refnum );
-extern void endout_writeheader( FILE *outptr, param *p );
-
-extern void endout_initparams( param *p, const char *progname );
-
-
-#endif
diff --git a/lib/endtypes.c b/lib/endtypes.c
index 2f1a707..2984f1f 100644
--- a/lib/endtypes.c
+++ b/lib/endtypes.c
@@ -1,7 +1,7 @@
 /*
  * endtypes.c
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -18,7 +18,7 @@ static lookups generic[] = {
 	{ "%A", "AUTHOR",    PERSON, LEVEL_MAIN },
 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
-	{ "%D", "YEAR",      SIMPLE, LEVEL_MAIN },
+	{ "%D", "DATE:YEAR",      SIMPLE, LEVEL_MAIN },
 	{ "%T", "TITLE" ,    TITLE,  LEVEL_MAIN },
 	{ "%J", "TITLE",     TITLE,  LEVEL_HOST }, /* for refer formats */
 	{ "%E", "2ND_AUTHOR",PERSON, LEVEL_MAIN },
@@ -33,7 +33,7 @@ static lookups generic[] = {
 	{ "%Y", "AUTHOR",   PERSON, LEVEL_SERIES },
 	{ "%S", "TITLE",     TITLE, LEVEL_SERIES },
 	{ "%7", "EDITION",      SIMPLE, LEVEL_MAIN },
-	{ "%8", "MONTH",    DATE,   LEVEL_MAIN },
+	{ "%8", "DATE:MONTH",    DATE,   LEVEL_MAIN },
 	{ "%9", "GENRE",        SIMPLE, LEVEL_MAIN },
 	{ "%?", "SUB_AUTHOR",   PERSON, LEVEL_MAIN }, /* subsidiary-authors */
 	{ "%!", "SHORTTITLE",   TITLE,  LEVEL_MAIN },
@@ -53,7 +53,7 @@ static lookups generic[] = {
 	{ "%K", "KEYWORD",      SIMPLE, LEVEL_MAIN }, 
 	{ "%X", "ABSTRACT",     SIMPLE, LEVEL_MAIN },
 	{ "%O", "NOTES",        NOTES, LEVEL_MAIN },
-	{ "%U", "URL",          SIMPLE, LEVEL_MAIN },
+	{ "%U", "URL",          URL,    LEVEL_MAIN },
 	{ "%>", "PDFLINK",      SIMPLE, LEVEL_MAIN },
 	{ "%Z", "NOTES",        SIMPLE, LEVEL_MAIN },
 	{ "%W", "PHYSICALLOC",  SIMPLE, LEVEL_MAIN },  /* physical location */
@@ -70,7 +70,7 @@ static lookups journalarticle[] = {
 	{ "%A", "AUTHOR",       PERSON,   LEVEL_MAIN },
 	{ "%H", "TRANSLATOR",   PERSON,   LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE",SIMPLE, LEVEL_MAIN },
-	{ "%D", "PARTYEAR",     SIMPLE,   LEVEL_MAIN },
+	{ "%D", "PARTDATE:YEAR",     SIMPLE,   LEVEL_MAIN },
 	{ "%T", "TITLE" ,       TITLE,    LEVEL_MAIN },
 	{ "%J", "TITLE",        TITLE,    LEVEL_HOST }, /* journal title */
 	{ "%B", "TITLE",        TITLE,    LEVEL_HOST }, /* journal title */
@@ -79,7 +79,7 @@ static lookups journalarticle[] = {
 	{ "%N", "ISSUE",        SIMPLE,   LEVEL_MAIN },
 	{ "%P", "PAGES",        PAGES,    LEVEL_MAIN },
 	{ "%I", "PUBLISHER",    SIMPLE,   LEVEL_HOST }, 
-	{ "%8", "PARTMONTH",    DATE,     LEVEL_MAIN },
+	{ "%8", "PARTDATE:MONTH",    DATE,     LEVEL_MAIN },
 	{ "%9", "GENRE",        SIMPLE,   LEVEL_MAIN },
 	{ "%!", "SHORTTITLE",   TITLE,    LEVEL_MAIN },
 	{ "%@", "SERIALNUMBER", SERIALNO, LEVEL_HOST },
@@ -91,7 +91,7 @@ static lookups journalarticle[] = {
 	{ "%F", "REFNUM",       SIMPLE,   LEVEL_MAIN },
 	{ "%K", "KEYWORD",      SIMPLE,   LEVEL_MAIN },
 	{ "%X", "ABSTRACT",     SIMPLE,   LEVEL_MAIN },
-	{ "%U", "URL",          SIMPLE,   LEVEL_MAIN },
+	{ "%U", "URL",          URL,      LEVEL_MAIN },
 	{ "%O", "NOTES",        NOTES,    LEVEL_MAIN },
 	{ "%Z", "NOTES",        NOTES,    LEVEL_MAIN },
 	{ "%1", "CUSTOM1",      NOTES,    LEVEL_MAIN },
@@ -120,7 +120,7 @@ static lookups magazinearticle[] = {
 	{ "%A", "AUTHOR",    PERSON,  LEVEL_MAIN },
 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
-	{ "%D", "PARTYEAR",  SIMPLE,  LEVEL_MAIN },
+	{ "%D", "PARTDATE:YEAR",  SIMPLE,  LEVEL_MAIN },
 	{ "%T", "TITLE",     TITLE,   LEVEL_MAIN },
 	{ "%J", "TITLE",     TITLE,   LEVEL_HOST }, /* magazine name */
 	{ "%B", "TITLE",     TITLE,   LEVEL_HOST }, /* magazine name */
@@ -129,7 +129,7 @@ static lookups magazinearticle[] = {
 	{ "%N", "ISSUE",     SIMPLE,  LEVEL_MAIN },
 	{ "%P", "PAGES",     PAGES,   LEVEL_MAIN },
 	{ "%I", "PUBLISHER", SIMPLE,    LEVEL_HOST }, 
-	{ "%8", "PARTMONTH", DATE,    LEVEL_MAIN },
+	{ "%8", "PARTDATE:MONTH", DATE,    LEVEL_MAIN },
 	{ "%!", "SHORTTITLE",TITLE,   LEVEL_MAIN },
 	{ "%@", "SERIALNUMBER",      SERIALNO,LEVEL_HOST },
 	{ "%(", "TITLE",     SIMPLE,  LEVEL_ORIG }, /* original pub */
@@ -140,7 +140,7 @@ static lookups magazinearticle[] = {
 	{ "%F", "REFNUM",    SIMPLE,  LEVEL_MAIN },
 	{ "%K", "KEYWORD",   SIMPLE,  LEVEL_MAIN }, 
 	{ "%X", "ABSTRACT",  SIMPLE,  LEVEL_MAIN },
-	{ "%U", "URL",       SIMPLE,  LEVEL_MAIN },
+	{ "%U", "URL",       URL,     LEVEL_MAIN },
 	{ "%O", "NOTES",     SIMPLE,  LEVEL_MAIN },
 	{ "%Z", "NOTES",     SIMPLE,  LEVEL_MAIN },
 	{ "%1", "CUSTOM1",      NOTES,    LEVEL_MAIN },
@@ -168,7 +168,7 @@ static lookups newspaperarticle[] = {
 	{ "%A", "REPORTER",  PERSON,  LEVEL_MAIN },
 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
-	{ "%D", "PARTYEAR",  SIMPLE,  LEVEL_MAIN },
+	{ "%D", "PARTDATE:YEAR",  SIMPLE,  LEVEL_MAIN },
 	{ "%T", "TITLE" ,    TITLE,   LEVEL_MAIN },
 	{ "%J", "TITLE",     TITLE,   LEVEL_HOST }, /* newspaper name */
 	{ "%B", "TITLE",     TITLE,   LEVEL_HOST }, /* newspaper name */
@@ -177,7 +177,7 @@ static lookups newspaperarticle[] = {
 	{ "%N", "ISSUE",     SIMPLE,  LEVEL_MAIN },
 	{ "%P", "PAGES",     PAGES,   LEVEL_MAIN },
 	{ "%7", "EDITION",   SIMPLE,  LEVEL_MAIN },
-	{ "%8", "PARTMONTH", DATE,    LEVEL_MAIN },
+	{ "%8", "PARTDATE:MONTH", DATE,    LEVEL_MAIN },
 	{ "%!", "SHORTTITLE",TITLE,   LEVEL_MAIN },
 	{ "%@", "SERIALNUMBER",      SERIALNO, LEVEL_MAIN },
 	{ "%(", "TITLE",     SIMPLE, LEVEL_ORIG }, /* original pub */
@@ -188,7 +188,7 @@ static lookups newspaperarticle[] = {
 	{ "%F", "REFNUM",    SIMPLE,  LEVEL_MAIN },
 	{ "%K", "KEYWORD",   SIMPLE,  LEVEL_MAIN }, 
 	{ "%X", "ABSTRACT",  SIMPLE,  LEVEL_MAIN },
-	{ "%U", "URL",       SIMPLE,  LEVEL_MAIN },
+	{ "%U", "URL",       URL,     LEVEL_MAIN },
 	{ "%O", "NOTES",     SIMPLE,  LEVEL_MAIN },
 	{ "%Z", "NOTES",     SIMPLE,  LEVEL_MAIN },
 	{ "%1", "CUSTOM1",      NOTES,    LEVEL_MAIN },
@@ -215,7 +215,7 @@ static lookups book[] = {
 	{ "%A", "AUTHOR",    PERSON,    LEVEL_MAIN },
 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
-	{ "%D", "YEAR",      SIMPLE,    LEVEL_MAIN },
+	{ "%D", "DATE:YEAR",      SIMPLE,    LEVEL_MAIN },
 	{ "%T", "TITLE" ,    TITLE,     LEVEL_MAIN },
 	{ "%E", "AUTHOR",    PERSON,    LEVEL_HOST }, /* SERIES_AUTHOR */
 	{ "%B", "TITLE",     TITLE,     LEVEL_HOST }, /* SERIES_TITLE */
@@ -225,7 +225,7 @@ static lookups book[] = {
 	{ "%V", "VOLUME" ,   SIMPLE,    LEVEL_MAIN },
 	{ "%N", "NUMBER",    SIMPLE,    LEVEL_MAIN },
 	{ "%6", "NUMVOLUMES",SIMPLE,    LEVEL_MAIN },
-	{ "%P", "TOTALPAGES", SIMPLE,LEVEL_MAIN },
+	{ "%P", "PAGES:TOTAL", SIMPLE,LEVEL_MAIN },
 	{ "%7", "EDITION",   SIMPLE,    LEVEL_MAIN },
 	{ "%?", "TRANSLATOR",PERSON,    LEVEL_MAIN },
 	{ "%!", "SHORTTITLE",TITLE,     LEVEL_MAIN },
@@ -244,7 +244,7 @@ static lookups book[] = {
 	{ "%K", "KEYWORD",   SIMPLE,    LEVEL_MAIN }, 
 	{ "%X", "ABSTRACT",  SIMPLE,    LEVEL_MAIN },
 	{ "%O", "NOTES",     NOTES,     LEVEL_MAIN },
-	{ "%U", "URL",       SIMPLE,    LEVEL_MAIN },
+	{ "%U", "URL",       URL,       LEVEL_MAIN },
 	{ "%Z", "NOTES",     SIMPLE,    LEVEL_MAIN },
 	{ "%+", "AUTHORADDRESS",SIMPLE, LEVEL_MAIN },
 	{ "%>", "PDFLINK",      SIMPLE, LEVEL_MAIN },
@@ -264,7 +264,7 @@ static lookups booksection[] = {
 	{ "%A", "AUTHOR",    PERSON,    LEVEL_MAIN },
 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
-	{ "%D", "YEAR",      SIMPLE,    LEVEL_HOST },
+	{ "%D", "DATE:YEAR",      SIMPLE,    LEVEL_HOST },
 	{ "%T", "TITLE" ,    TITLE,     LEVEL_MAIN },
 	{ "%E", "EDITOR",    PERSON,    LEVEL_HOST }, /* editor for book */
 	{ "%B", "TITLE",     TITLE,     LEVEL_HOST }, /* book title */
@@ -294,7 +294,7 @@ static lookups booksection[] = {
 	{ "%K", "KEYWORD",   SIMPLE,    LEVEL_MAIN }, 
 	{ "%X", "ABSTRACT",  SIMPLE,    LEVEL_MAIN },
 	{ "%O", "NOTES",     NOTES,     LEVEL_MAIN },
-	{ "%U", "URL",       SIMPLE,    LEVEL_MAIN },
+	{ "%U", "URL",       URL,       LEVEL_MAIN },
 	{ "%Z", "NOTES",     SIMPLE,    LEVEL_MAIN },
 	{ "%+", "AUTHORADDRESS",SIMPLE, LEVEL_MAIN },
 	{ "%>", "PDFLINK",      SIMPLE, LEVEL_MAIN },
@@ -315,7 +315,7 @@ static lookups editedbook[] = {
 	{ "%A", "EDITOR",    PERSON,    LEVEL_MAIN },
 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
-	{ "%D", "YEAR",      SIMPLE,    LEVEL_MAIN },
+	{ "%D", "DATE:YEAR",      SIMPLE,    LEVEL_MAIN },
 	{ "%T", "TITLE" ,    TITLE,     LEVEL_MAIN },
 	{ "%E", "EDITOR",    PERSON,    LEVEL_HOST }, /* SERIES_EDITOR */
 	{ "%B", "TITLE",     TITLE,     LEVEL_HOST }, /* SERIES_TITLE */
@@ -324,7 +324,7 @@ static lookups editedbook[] = {
 	{ "%N", "NUMBER",    SIMPLE,    LEVEL_MAIN },
 	{ "%V", "VOLUME" ,   SIMPLE,    LEVEL_MAIN },
 	{ "%6", "NUMVOLUMES",SIMPLE,    LEVEL_HOST },
-	{ "%P", "TOTALPAGES", SIMPLE,LEVEL_MAIN },
+	{ "%P", "PAGES:TOTAL", SIMPLE,LEVEL_MAIN },
 	{ "%7", "EDITION",   SIMPLE,    LEVEL_MAIN },
 	{ "%?", "TRANSLATOR",PERSON,    LEVEL_MAIN },
 	{ "%!", "SHORTTITLE",TITLE,     LEVEL_MAIN },
@@ -343,7 +343,7 @@ static lookups editedbook[] = {
 	{ "%K", "KEYWORD",   SIMPLE,    LEVEL_MAIN }, 
 	{ "%X", "ABSTRACT",  SIMPLE,    LEVEL_MAIN },
 	{ "%O", "NOTES",     NOTES,     LEVEL_MAIN },
-	{ "%U", "URL",       SIMPLE,    LEVEL_MAIN },
+	{ "%U", "URL",       URL,       LEVEL_MAIN },
 	{ "%Z", "NOTES",     NOTES,     LEVEL_MAIN },
 	{ "%+", "AUTHORADDRESS",SIMPLE, LEVEL_MAIN },
 	{ "%>", "PDFLINK",      SIMPLE, LEVEL_MAIN },
@@ -363,13 +363,13 @@ static lookups manuscript[] = {
 	{ "%A", "AUTHOR",    PERSON,  LEVEL_MAIN },
 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
-	{ "%D", "YEAR",      SIMPLE,  LEVEL_MAIN },
+	{ "%D", "DATE:YEAR",      SIMPLE,  LEVEL_MAIN },
 	{ "%T", "TITLE",     TITLE,   LEVEL_MAIN },
 	{ "%B", "TITLE",     TITLE,   LEVEL_HOST }, /* COLLECTION_TITLE */
 	{ "%C", "ADDRESS",   SIMPLE,  LEVEL_MAIN },
 	{ "%N", "NUMBER",    SIMPLE,  LEVEL_MAIN },
 	{ "%P", "PAGES",     PAGES,   LEVEL_MAIN },
-	{ "%8", "MONTH", DATE,    LEVEL_MAIN },
+	{ "%8", "DATE:MONTH", DATE,    LEVEL_MAIN },
 	{ "%9", "GENRE",     SIMPLE,  LEVEL_MAIN },
 	{ "%!", "SHORTTITLE",TITLE,   LEVEL_MAIN },
 	{ "%M", "ACCESSNUM", SIMPLE,  LEVEL_MAIN },
@@ -378,7 +378,7 @@ static lookups manuscript[] = {
 	{ "%K", "KEYWORD",   SIMPLE,  LEVEL_MAIN }, 
 	{ "%X", "ABSTRACT",  SIMPLE,  LEVEL_MAIN },
 	{ "%O", "NOTES",     NOTES,   LEVEL_MAIN },
-	{ "%U", "URL",       SIMPLE,  LEVEL_MAIN },
+	{ "%U", "URL",       URL,     LEVEL_MAIN },
 	{ "%Z", "NOTES",     NOTES,   LEVEL_MAIN },
 	{ "%1", "CUSTOM1",   NOTES,   LEVEL_MAIN },
 	{ "%2", "CUSTOM2",   NOTES,   LEVEL_MAIN },
@@ -403,13 +403,13 @@ static lookups communication[] = {
 	{ "%A", "AUTHOR",    PERSON,  LEVEL_MAIN },
 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
-	{ "%D", "YEAR",      SIMPLE,  LEVEL_MAIN },
+	{ "%D", "DATE:YEAR",      SIMPLE,  LEVEL_MAIN },
 	{ "%T", "TITLE" ,    TITLE,   LEVEL_MAIN },
 	{ "%E", "RECIPIENT", PERSON,  LEVEL_MAIN },
 	{ "%C", "ADDRESS",   SIMPLE,  LEVEL_MAIN },
 	{ "%V", "VOLUME",    SIMPLE,  LEVEL_MAIN },
 	{ "%I", "PUBLISHER", SIMPLE,  LEVEL_MAIN },
-	{ "%8", "MONTH", DATE,    LEVEL_MAIN },
+	{ "%8", "DATE:MONTH", DATE,    LEVEL_MAIN },
 	{ "%9", "GENRE",     SIMPLE,  LEVEL_MAIN },
 	{ "%!", "SHORTTITLE",TITLE,   LEVEL_MAIN },
 	{ "%M", "ACCESSNUM", SIMPLE,  LEVEL_MAIN },
@@ -418,7 +418,7 @@ static lookups communication[] = {
 	{ "%K", "KEYWORD",   SIMPLE,  LEVEL_MAIN }, 
 	{ "%X", "ABSTRACT",  SIMPLE,  LEVEL_MAIN },
 	{ "%O", "NOTES",     NOTES,   LEVEL_MAIN },
-	{ "%U", "URL",       SIMPLE,  LEVEL_MAIN },
+	{ "%U", "URL",       URL,     LEVEL_MAIN },
 	{ "%Z", "NOTES",     NOTES,   LEVEL_MAIN },
 	{ "%1", "CUSTOM1",   NOTES,   LEVEL_MAIN },
 	{ "%2", "CUSTOM2",   NOTES,   LEVEL_MAIN },
@@ -442,7 +442,7 @@ static lookups proceedings[] = {
 	{ "%A", "AUTHOR",    PERSON,  LEVEL_MAIN },
 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
-	{ "%D", "YEAR",      SIMPLE,  LEVEL_HOST },
+	{ "%D", "DATE:YEAR",      SIMPLE,  LEVEL_HOST },
 	{ "%T", "TITLE" ,    TITLE,   LEVEL_MAIN },
 	{ "%E", "EDITOR",    PERSON,  LEVEL_MAIN },
 	{ "%B", "TITLE",     SIMPLE,  LEVEL_HOST }, 
@@ -455,7 +455,7 @@ static lookups proceedings[] = {
 	{ "%Y", "EDITOR",    PERSON,  LEVEL_SERIES },
 	{ "%S", "TITLE",     TITLE,   LEVEL_SERIES },
 	{ "%7", "EDITION",   SIMPLE,  LEVEL_HOST },
-	{ "%8", "MONTH", DATE,    LEVEL_MAIN },
+	{ "%8", "DATE:MONTH", DATE,    LEVEL_MAIN },
 	{ "%!", "SHORTTITLE",TITLE,   LEVEL_MAIN },
 	{ "%1", "CUSTOM1",   NOTES,   LEVEL_MAIN },
 	{ "%2", "CUSTOM2",   NOTES,   LEVEL_MAIN },
@@ -469,7 +469,7 @@ static lookups proceedings[] = {
 	{ "%K", "KEYWORD",   SIMPLE,  LEVEL_MAIN }, 
 	{ "%X", "ABSTRACT",  SIMPLE,  LEVEL_MAIN },
 	{ "%O", "NOTES",     NOTES,   LEVEL_MAIN },
-	{ "%U", "URL",       SIMPLE,  LEVEL_MAIN },
+	{ "%U", "URL",       URL,     LEVEL_MAIN },
 	{ "%Z", "NOTES",     NOTES,   LEVEL_MAIN },
 	{ "%+", "AUTHORADDRESS",SIMPLE,LEVEL_MAIN},
 	{ "%>", "PDFLINK",      SIMPLE, LEVEL_MAIN },
@@ -488,7 +488,7 @@ static lookups conferencepaper[] = {
 	{ "%A", "AUTHOR",       PERSON,   LEVEL_MAIN },
 	{ "%H", "TRANSLATOR",   PERSON,   LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE",SIMPLE, LEVEL_MAIN },
-	{ "%D", "PARTYEAR",     SIMPLE,   LEVEL_MAIN },
+	{ "%D", "PARTDATE:YEAR",     SIMPLE,   LEVEL_MAIN },
 	{ "%T", "TITLE" ,       TITLE,    LEVEL_MAIN },
 	{ "%J", "TITLE",        TITLE,    LEVEL_HOST }, /* journal title */
 	{ "%B", "TITLE",        TITLE,    LEVEL_HOST }, /* journal title */
@@ -497,7 +497,7 @@ static lookups conferencepaper[] = {
 	{ "%N", "ISSUE",        SIMPLE,   LEVEL_MAIN },
 	{ "%P", "PAGES",        PAGES,    LEVEL_MAIN },
 	{ "%I", "PUBLISHER",    SIMPLE,   LEVEL_HOST }, 
-	{ "%8", "PARTMONTH",    DATE,     LEVEL_MAIN },
+	{ "%8", "PARTDATE:MONTH",    DATE,     LEVEL_MAIN },
 	{ "%9", "GENRE",        SIMPLE,   LEVEL_MAIN },
 	{ "%!", "SHORTTITLE",   TITLE,    LEVEL_MAIN },
 	{ "%@", "SERIALNUMBER", SERIALNO, LEVEL_HOST },
@@ -509,7 +509,7 @@ static lookups conferencepaper[] = {
 	{ "%F", "REFNUM",       SIMPLE,   LEVEL_MAIN },
 	{ "%K", "KEYWORD",      SIMPLE,   LEVEL_MAIN },
 	{ "%X", "ABSTRACT",     SIMPLE,   LEVEL_MAIN },
-	{ "%U", "URL",          SIMPLE,   LEVEL_MAIN },
+	{ "%U", "URL",          URL,      LEVEL_MAIN },
 	{ "%O", "NOTES",        NOTES,    LEVEL_MAIN },
 	{ "%Z", "NOTES",        NOTES,    LEVEL_MAIN },
 	{ "%1", "CUSTOM1",      NOTES,    LEVEL_MAIN },
@@ -535,15 +535,15 @@ static lookups thesis[] = {
 	{ "%A", "AUTHOR",       PERSON, LEVEL_MAIN },
 	{ "%H", "TRANSLATOR",   PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
-	{ "%D", "YEAR",         SIMPLE, LEVEL_MAIN },
+	{ "%D", "DATE:YEAR",         SIMPLE, LEVEL_MAIN },
 	{ "%T", "TITLE" ,       TITLE,  LEVEL_MAIN },
 	{ "%B", "ACADEMIC_DEPARTMENT", SIMPLE, LEVEL_MAIN },
 	{ "%C", "ADDRESS",      SIMPLE, LEVEL_MAIN },
 	{ "%I", "PUBLISHER",    SIMPLE, LEVEL_MAIN }, 
 	{ "%V", "VOLUME",       SIMPLE, LEVEL_MAIN },
-	{ "%P", "NUMPAGES",     PAGES,  LEVEL_MAIN },
+	{ "%P", "PAGES:TOTAL",  PAGES,  LEVEL_MAIN },
 	{ "%9", "GENRE",        SIMPLE, LEVEL_MAIN }, /* thesis type */
-	{ "%8", "MONTH",        DATE,   LEVEL_MAIN },
+	{ "%8", "DATE:MONTH",   DATE,   LEVEL_MAIN },
 	{ "%!", "SHORTTITLE",   TITLE,  LEVEL_MAIN },
 	{ "%1", "CUSTOM1",      NOTES,  LEVEL_MAIN },
 	{ "%2", "CUSTOM2",      NOTES,  LEVEL_MAIN },
@@ -557,7 +557,7 @@ static lookups thesis[] = {
 	{ "%K", "KEYWORD",      SIMPLE, LEVEL_MAIN }, 
 	{ "%X", "ABSTRACT",     SIMPLE, LEVEL_MAIN },
 	{ "%O", "NOTES",        NOTES,  LEVEL_MAIN },
-	{ "%U", "URL",          SIMPLE, LEVEL_MAIN },
+	{ "%U", "URL",          URL,    LEVEL_MAIN },
 	{ "%Z", "NOTES",        NOTES,  LEVEL_MAIN },
 	{ "%+", "AUTHORADDRESS",SIMPLE, LEVEL_MAIN },
 	{ "%>", "PDFLINK",      SIMPLE, LEVEL_MAIN },
@@ -576,7 +576,7 @@ static lookups program[] = {
 	{ "%A", "AUTHOR",    PERSON   , LEVEL_MAIN },
 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
-	{ "%D", "YEAR",      SIMPLE   , LEVEL_MAIN },
+	{ "%D", "DATE:YEAR",      SIMPLE   , LEVEL_MAIN },
 	{ "%T", "TITLE" ,    TITLE    , LEVEL_MAIN },
 	{ "%C", "ADDRESS",   SIMPLE   , LEVEL_MAIN },
 	{ "%I", "PUBLISHER", SIMPLE   , LEVEL_MAIN },
@@ -588,7 +588,7 @@ static lookups program[] = {
 	{ "%K", "KEYWORD",   SIMPLE   , LEVEL_MAIN }, 
 	{ "%X", "ABSTRACT",  SIMPLE   , LEVEL_MAIN },
 	{ "%O", "NOTES",     SIMPLE   , LEVEL_MAIN },
-	{ "%U", "URL",       SIMPLE   , LEVEL_MAIN },
+	{ "%U", "URL",       URL,       LEVEL_MAIN },
 	{ "%Z", "NOTES",     SIMPLE   , LEVEL_MAIN },
 	{ "%1", "COMPUTER",  SIMPLE   , LEVEL_MAIN },
 	{ "%2", "CUSTOM2",   SIMPLE   , LEVEL_MAIN },
@@ -613,14 +613,14 @@ static lookups audiovisual[] = {
 	{ "%A", "WRITER",    PERSON   , LEVEL_MAIN },
 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
-	{ "%D", "YEAR",      SIMPLE   , LEVEL_MAIN },
+	{ "%D", "DATE:YEAR",      SIMPLE   , LEVEL_MAIN },
 	{ "%T", "TITLE" ,    TITLE    , LEVEL_MAIN },
 	{ "%B", "TITLE",     TITLE    , LEVEL_HOST }, /* COLLECTION_TITLE */
 	{ "%C", "ADDRESS",   SIMPLE   , LEVEL_MAIN },
 	{ "%I", "PUBLISHER", SIMPLE   , LEVEL_MAIN },
 	{ "%V", "EXTENTOFWORK",     SIMPLE   , LEVEL_MAIN },
 	{ "%N", "NUMBER",    SIMPLE   , LEVEL_MAIN },
-	{ "%8", "MONTH", DATE     , LEVEL_MAIN },
+	{ "%8", "DATE:MONTH", DATE     , LEVEL_MAIN },
 	{ "%9", "GENRE",     SIMPLE   , LEVEL_MAIN },
 	{ "%?", "PERFORMER", PERSON   , LEVEL_MAIN },
 	{ "%!", "SHORTTITLE",TITLE    , LEVEL_MAIN },
@@ -630,7 +630,7 @@ static lookups audiovisual[] = {
 	{ "%K", "KEYWORD",   SIMPLE   , LEVEL_MAIN }, 
 	{ "%X", "ABSTRACT",  SIMPLE   , LEVEL_MAIN },
 	{ "%O", "NOTES",     NOTES,     LEVEL_MAIN },
-	{ "%U", "URL",       SIMPLE   , LEVEL_MAIN },
+	{ "%U", "URL",       URL,       LEVEL_MAIN },
 	{ "%Z", "NOTES",     NOTES,     LEVEL_MAIN },
 	{ "%1", "CUSTOM1",   NOTES,     LEVEL_MAIN },
 	{ "%2", "CUSTOM2",   NOTES,     LEVEL_MAIN },
@@ -654,14 +654,14 @@ static lookups broadcast[] = {
 	{ "%A", "AUTHOR",       PERSON,   LEVEL_MAIN },
 	{ "%H", "TRANSLATOR",   PERSON,   LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
-	{ "%D", "YEAR",         SIMPLE,   LEVEL_MAIN },
+	{ "%D", "DATE:YEAR",         SIMPLE,   LEVEL_MAIN },
 	{ "%T", "TITLE" ,       TITLE,    LEVEL_MAIN },
 	{ "%E", "DIRECTOR",     PERSON,   LEVEL_MAIN },
 	{ "%B", "TITLE",        TITLE,    LEVEL_HOST }, /* SERIES_TITLE */
 	{ "%C", "ADDRESS",      SIMPLE,   LEVEL_MAIN },
 	{ "%I", "PUBLISHER",    SIMPLE,   LEVEL_MAIN },
 	{ "%Y", "PRODUCER",     PERSON,   LEVEL_MAIN },
-	{ "%8", "MONTH",        DATE,     LEVEL_MAIN },
+	{ "%8", "DATE:MONTH",        DATE,     LEVEL_MAIN },
 	{ "%9", "GENRE",        SIMPLE,   LEVEL_MAIN },
 	{ "%!", "SHORTTITLE",   TITLE,    LEVEL_MAIN },
 	{ "%@", "SERIALNUMBER", SERIALNO, LEVEL_MAIN },
@@ -672,7 +672,7 @@ static lookups broadcast[] = {
 	{ "%K", "KEYWORD",      SIMPLE,   LEVEL_MAIN }, 
 	{ "%X", "ABSTRACT",     SIMPLE,   LEVEL_MAIN },
 	{ "%O", "NOTES",        NOTES,    LEVEL_MAIN },
-	{ "%U", "URL",          SIMPLE,   LEVEL_MAIN },
+	{ "%U", "URL",          URL,      LEVEL_MAIN },
 	{ "%Z", "NOTES",        SIMPLE,   LEVEL_MAIN },
 	{ "%1", "CUSTOM1",      NOTES,    LEVEL_MAIN },
 	{ "%2", "CUSTOM2",      NOTES,    LEVEL_MAIN },
@@ -696,7 +696,7 @@ static lookups electronic[] = {
 	{ "%A", "AUTHOR",    PERSON    , LEVEL_MAIN },
 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
-	{ "%D", "YEAR",      SIMPLE    , LEVEL_MAIN },
+	{ "%D", "DATE:YEAR",      SIMPLE    , LEVEL_MAIN },
 	{ "%T", "TITLE" ,    TITLE     , LEVEL_MAIN },
 	{ "%C", "ADDRESS",   SIMPLE, LEVEL_MAIN },
 	{ "%I", "PUBLISHER", SIMPLE    , LEVEL_MAIN }, 
@@ -717,7 +717,7 @@ static lookups electronic[] = {
 	{ "%K", "KEYWORD",   SIMPLE,     LEVEL_MAIN }, 
 	{ "%X", "ABSTRACT",  SIMPLE,     LEVEL_MAIN },
 	{ "%O", "NOTES",     NOTES,      LEVEL_MAIN },
-	{ "%U", "URL",       SIMPLE,     LEVEL_MAIN },
+	{ "%U", "URL",       URL,        LEVEL_MAIN },
 	{ "%V", "VOLUME",    SIMPLE,     LEVEL_MAIN },
 	{ "%Z", "NOTES",     NOTES,      LEVEL_MAIN },
 	{ "%W", "PHYSICALLOC",  SIMPLE, LEVEL_MAIN },  /* physical location */
@@ -737,7 +737,7 @@ static lookups webpage[] = {
 	{ "%A", "AUTHOR",    PERSON    , LEVEL_MAIN },
 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
-	{ "%D", "YEAR",      SIMPLE    , LEVEL_MAIN },
+	{ "%D", "DATE:YEAR",      SIMPLE    , LEVEL_MAIN },
 	{ "%T", "TITLE" ,    TITLE     , LEVEL_MAIN },
 	{ "%C", "ADDRESS",   SIMPLE, LEVEL_MAIN },
 	{ "%I", "PUBLISHER", SIMPLE    , LEVEL_MAIN }, 
@@ -758,7 +758,7 @@ static lookups webpage[] = {
 	{ "%K", "KEYWORD",   SIMPLE,     LEVEL_MAIN }, 
 	{ "%X", "ABSTRACT",  SIMPLE,     LEVEL_MAIN },
 	{ "%O", "NOTES",     NOTES,      LEVEL_MAIN },
-	{ "%U", "URL",       SIMPLE,     LEVEL_MAIN },
+	{ "%U", "URL",       URL,        LEVEL_MAIN },
 	{ "%V", "VOLUME",    SIMPLE,     LEVEL_MAIN },
 	{ "%Z", "NOTES",     NOTES,      LEVEL_MAIN },
 	{ "%W", "PHYSICALLOC",  SIMPLE, LEVEL_MAIN },  /* physical location */
@@ -778,11 +778,11 @@ static lookups artwork[] = {
 	{ "%A", "ARTIST",    PERSON   , LEVEL_MAIN },
 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
-	{ "%D", "YEAR",         SIMPLE   , LEVEL_MAIN },
+	{ "%D", "DATE:YEAR",         SIMPLE   , LEVEL_MAIN },
 	{ "%T", "TITLE" ,       TITLE    , LEVEL_MAIN },
 	{ "%C", "ADDRESS",      SIMPLE   , LEVEL_MAIN },
 	{ "%I", "PUBLISHER",    SIMPLE   , LEVEL_MAIN },
-	{ "%8", "MONTH",        DATE,   LEVEL_MAIN },
+	{ "%8", "DATE:MONTH",        DATE,   LEVEL_MAIN },
 	{ "%9", "GENRE",        SIMPLE, LEVEL_MAIN },
 	{ "%!", "SHORTTITLE",   TITLE,  LEVEL_MAIN },
 	{ "%M", "ACCESSNUM",    SIMPLE, LEVEL_MAIN },
@@ -791,7 +791,7 @@ static lookups artwork[] = {
 	{ "%K", "KEYWORD",      SIMPLE, LEVEL_MAIN }, 
 	{ "%X", "ABSTRACT",     SIMPLE, LEVEL_MAIN },
 	{ "%O", "NOTES",        NOTES,  LEVEL_MAIN },
-	{ "%U", "URL",          SIMPLE, LEVEL_MAIN },
+	{ "%U", "URL",          URL,    LEVEL_MAIN },
 	{ "%Z", "NOTES",        NOTES,  LEVEL_MAIN },
 	{ "%1", "CUSTOM1",      NOTES,  LEVEL_MAIN },
 	{ "%2", "CUSTOM2",      NOTES,  LEVEL_MAIN },
@@ -815,12 +815,12 @@ static lookups report[] = {
 	{ "%A", "AUTHOR",    PERSON   , LEVEL_MAIN },
 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
-	{ "%D", "YEAR",      SIMPLE   , LEVEL_MAIN },
+	{ "%D", "DATE:YEAR",      SIMPLE   , LEVEL_MAIN },
 	{ "%T", "TITLE" ,    TITLE    , LEVEL_MAIN },
 	{ "%C", "ADDRESS",   SIMPLE   , LEVEL_MAIN },
 	{ "%I", "PUBLISHER", SIMPLE, LEVEL_MAIN },
 	{ "%P", "PAGES",     PAGES, LEVEL_MAIN },
-	{ "%8", "MONTH",     DATE, LEVEL_MAIN },
+	{ "%8", "DATE:MONTH",     DATE, LEVEL_MAIN },
 	{ "%9", "GENRE",     SIMPLE,    LEVEL_MAIN },
 	{ "%N", "NUMBER",    SIMPLE,    LEVEL_MAIN },
 	{ "%@", "SERIALNUMBER", SERIALNO, LEVEL_MAIN },
@@ -831,7 +831,7 @@ static lookups report[] = {
 	{ "%K", "KEYWORD",   SIMPLE,    LEVEL_MAIN }, 
 	{ "%X", "ABSTRACT",  SIMPLE,    LEVEL_MAIN },
 	{ "%O", "NOTES",     NOTES,     LEVEL_MAIN },
-	{ "%U", "URL",       SIMPLE,    LEVEL_MAIN },
+	{ "%U", "URL",       URL,       LEVEL_MAIN },
 	{ "%Z", "NOTES",     NOTES,     LEVEL_MAIN },
 	{ "%1", "CUSTOM1",   NOTES,     LEVEL_MAIN },
 	{ "%2", "CUSTOM2",   NOTES,     LEVEL_MAIN },
@@ -856,7 +856,7 @@ static lookups map[] = {
 	{ "%A", "CARTOGRAPHER",    PERSON   , LEVEL_MAIN },
 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
-	{ "%D", "YEAR",      SIMPLE   , LEVEL_MAIN },
+	{ "%D", "DATE:YEAR",      SIMPLE   , LEVEL_MAIN },
 	{ "%T", "TITLE" ,    TITLE    , LEVEL_MAIN },
 	{ "%C", "ADDRESS",   SIMPLE   , LEVEL_MAIN },
 	{ "%I", "PUBLISHER", SIMPLE   , LEVEL_MAIN },
@@ -869,7 +869,7 @@ static lookups map[] = {
 	{ "%K", "KEYWORD",   SIMPLE   , LEVEL_MAIN }, 
 	{ "%X", "ABSTRACT",  SIMPLE   , LEVEL_MAIN },
 	{ "%O", "NOTES",     SIMPLE   , LEVEL_MAIN },
-	{ "%U", "URL",       SIMPLE   , LEVEL_MAIN },
+	{ "%U", "URL",       URL,       LEVEL_MAIN },
 	{ "%Z", "NOTES",     SIMPLE   , LEVEL_MAIN },
 	{ "%1", "SCALE",     SIMPLE   , LEVEL_MAIN },
 	{ "%2", "CUSTOM2",   SIMPLE   , LEVEL_MAIN },
@@ -894,7 +894,7 @@ static lookups patent[] = {
 	{ "%A", "AUTHOR",    PERSON, LEVEL_MAIN  },
 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
-	{ "%D", "YEAR",      SIMPLE, LEVEL_MAIN  },
+	{ "%D", "DATE:YEAR",      SIMPLE, LEVEL_MAIN  },
 	{ "%T", "TITLE" ,    TITLE, LEVEL_MAIN   },
 	{ "%B", "PUBLISHED_SOURCE", SIMPLE, LEVEL_MAIN},
 	{ "%C", "COUNTRY",   SIMPLE, LEVEL_MAIN  },
@@ -909,7 +909,7 @@ static lookups patent[] = {
 	{ "%K", "KEYWORD",   SIMPLE, LEVEL_MAIN  }, 
 	{ "%X", "ABSTRACT",  SIMPLE, LEVEL_MAIN  },
 	{ "%O", "NOTES",     SIMPLE, LEVEL_MAIN  },
-	{ "%U", "URL",       SIMPLE, LEVEL_MAIN  },
+	{ "%U", "URL",       URL,    LEVEL_MAIN  },
 	{ "%Z", "NOTES",     SIMPLE, LEVEL_MAIN  },
 	{ "%1", "SCALE",     SIMPLE, LEVEL_MAIN  },
 	{ "%2", "CUSTOM2",   SIMPLE, LEVEL_MAIN  },
@@ -931,7 +931,7 @@ static lookups patent[] = {
 
 static lookups hearing[] = {
 	{ "%0", "INTERNAL_TYPE",         TYPE, LEVEL_MAIN    },
-	{ "%D", "YEAR",         SIMPLE, LEVEL_MAIN  },
+	{ "%D", "DATE:YEAR",         SIMPLE, LEVEL_MAIN  },
 	{ "%H", "TRANSLATOR",   PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
 	{ "%T", "TITLE" ,       TITLE, LEVEL_MAIN   },
@@ -940,10 +940,10 @@ static lookups hearing[] = {
 	{ "%I", "PUBLISHER",    SIMPLE, LEVEL_MAIN  }, 
 	{ "%6", "NUMVOLUMES",   SIMPLE, LEVEL_MAIN  },
 	{ "%N", "NUMBER",       SIMPLE, LEVEL_MAIN  },
-	{ "%P", "NUMPAGES",     PAGES,  LEVEL_MAIN  },
+	{ "%P", "PAGES:TOTAL",  PAGES,  LEVEL_MAIN  },
 	{ "%S", "LEGISLATIVEBODY:CORP", SIMPLE, LEVEL_MAIN  },
 	{ "%7", "SESSION",       SIMPLE, LEVEL_MAIN  },
-	{ "%8", "MONTH",         DATE,   LEVEL_MAIN  },
+	{ "%8", "DATE:MONTH",         DATE,   LEVEL_MAIN  },
 	{ "%!", "SHORTTITLE",    TITLE,  LEVEL_MAIN  },
 	{ "%(", "TITLE",         SIMPLE, LEVEL_ORIG }, /* orig publication */
 	{ "%M", "ACCESSNUM",     SIMPLE, LEVEL_MAIN  },
@@ -952,7 +952,7 @@ static lookups hearing[] = {
 	{ "%K", "KEYWORD",       SIMPLE, LEVEL_MAIN  }, 
 	{ "%X", "ABSTRACT",      SIMPLE, LEVEL_MAIN  },
 	{ "%O", "NOTES",         NOTES,  LEVEL_MAIN  },
-	{ "%U", "URL",           SIMPLE, LEVEL_MAIN  },
+	{ "%U", "URL",           URL,    LEVEL_MAIN  },
 	{ "%Z", "NOTES",         NOTES,  LEVEL_MAIN  },
 	{ "%1", "CUSTOM1",       NOTES,  LEVEL_MAIN  },
 	{ "%2", "CUSTOM2",       NOTES,  LEVEL_MAIN  },
@@ -973,7 +973,7 @@ static lookups hearing[] = {
 
 static lookups bill[] = {
 	{ "%0", "INTERNAL_TYPE",      TYPE, LEVEL_MAIN    },
-	{ "%D", "YEAR",      SIMPLE, LEVEL_MAIN  },
+	{ "%D", "DATE:YEAR",      SIMPLE, LEVEL_MAIN  },
 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
 	{ "%T", "TITLE" ,    TITLE, LEVEL_MAIN   },
@@ -984,7 +984,7 @@ static lookups bill[] = {
 	{ "%&", "CODESECTION",SIMPLE, LEVEL_MAIN  },
 	{ "%S", "LEGISLATIVEBODY:CORP", SIMPLE, LEVEL_MAIN  },
 	{ "%7", "SESSION",   SIMPLE, LEVEL_MAIN  },
-	{ "%8", "MONTH", DATE, LEVEL_MAIN    },
+	{ "%8", "DATE:MONTH", DATE, LEVEL_MAIN    },
 	{ "%?", "SPONSOR",   PERSON, LEVEL_MAIN  },
 	{ "%!", "SHORTTITLE",TITLE,  LEVEL_MAIN   },
 	{ "%(", "TITLE",     SIMPLE, LEVEL_ORIG  }, /* original pub */
@@ -994,7 +994,7 @@ static lookups bill[] = {
 	{ "%K", "KEYWORD",   SIMPLE, LEVEL_MAIN  }, 
 	{ "%X", "ABSTRACT",  SIMPLE, LEVEL_MAIN  },
 	{ "%O", "NOTES",     NOTES,  LEVEL_MAIN  },
-	{ "%U", "URL",       SIMPLE, LEVEL_MAIN  },
+	{ "%U", "URL",       URL,    LEVEL_MAIN  },
 	{ "%Z", "NOTES",     NOTES,  LEVEL_MAIN  },
 	{ "%1", "CUSTOM1",   NOTES,  LEVEL_MAIN  },
 	{ "%2", "CUSTOM2",   NOTES,  LEVEL_MAIN  },
@@ -1015,7 +1015,7 @@ static lookups bill[] = {
 
 static lookups statute[] = {
 	{ "%0", "INTERNAL_TYPE",      TYPE, LEVEL_MAIN    },
-	{ "%D", "YEAR",      SIMPLE, LEVEL_MAIN  },
+	{ "%D", "DATE:YEAR",      SIMPLE, LEVEL_MAIN  },
 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
 	{ "%T", "TITLE" ,    TITLE, LEVEL_MAIN   },
@@ -1025,7 +1025,7 @@ static lookups statute[] = {
 	{ "%P", "PAGES",     PAGES, LEVEL_MAIN    },
 	{ "%&", "SECTION",   SIMPLE, LEVEL_MAIN  },
 	{ "%7", "SESSION",   SIMPLE, LEVEL_MAIN  },
-	{ "%8", "MONTH", DATE, LEVEL_MAIN    },
+	{ "%8", "DATE:MONTH", DATE, LEVEL_MAIN    },
 	{ "%!", "SHORTTITLE",TITLE,  LEVEL_MAIN   },
 	{ "%(", "TITLE",     SIMPLE, LEVEL_ORIG  }, /* original pub */
 	{ "%M", "ACCESSNUM", SIMPLE, LEVEL_MAIN  },
@@ -1034,7 +1034,7 @@ static lookups statute[] = {
 	{ "%K", "KEYWORD",   SIMPLE, LEVEL_MAIN  }, 
 	{ "%X", "ABSTRACT",  SIMPLE, LEVEL_MAIN  },
 	{ "%O", "NOTES",     NOTES,  LEVEL_MAIN  },
-	{ "%U", "URL",       SIMPLE, LEVEL_MAIN  },
+	{ "%U", "URL",       URL,    LEVEL_MAIN  },
 	{ "%Z", "NOTES",     NOTES,  LEVEL_MAIN  },
 	{ "%1", "CUSTOM1",   NOTES,  LEVEL_MAIN  },
 	{ "%2", "CUSTOM2",   NOTES,  LEVEL_MAIN  },
@@ -1055,7 +1055,7 @@ static lookups statute[] = {
 
 static lookups lawcase[] = {
 	{ "%0", "INTERNAL_TYPE",      TYPE, LEVEL_MAIN    },
-	{ "%D", "YEAR",      SIMPLE, LEVEL_MAIN  },
+	{ "%D", "DATE:YEAR",      SIMPLE, LEVEL_MAIN  },
 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
 	{ "%T", "TITLE" ,    TITLE, LEVEL_MAIN   },
@@ -1065,7 +1065,7 @@ static lookups lawcase[] = {
 	{ "%V", "VOLUME",    SIMPLE, LEVEL_MAIN   },
 	{ "%N", "PUBLICLAWNUMBER",    SIMPLE, LEVEL_MAIN  },
 	{ "%P", "STARTPAGE",     SIMPLE, LEVEL_MAIN  },
-	{ "%8", "MONTH", DATE, LEVEL_MAIN    },
+	{ "%8", "DATE:MONTH", DATE, LEVEL_MAIN    },
 	{ "%?", "COUNSEL",   PERSON, LEVEL_MAIN  },
 	{ "%!", "SHORTTITLE",TITLE,  LEVEL_MAIN   },
 	{ "%(", "TITLE",     SIMPLE, LEVEL_ORIG  }, /* original pub */
@@ -1075,7 +1075,7 @@ static lookups lawcase[] = {
 	{ "%K", "KEYWORD",   SIMPLE, LEVEL_MAIN  }, 
 	{ "%X", "ABSTRACT",  SIMPLE, LEVEL_MAIN  },
 	{ "%O", "NOTES",     NOTES,  LEVEL_MAIN  },
-	{ "%U", "URL",       SIMPLE, LEVEL_MAIN  },
+	{ "%U", "URL",       URL,    LEVEL_MAIN  },
 	{ "%Z", "NOTES",     NOTES,  LEVEL_MAIN  },
 	{ "%1", "CUSTOM1",   NOTES,  LEVEL_MAIN  },
 	{ "%2", "CUSTOM2",   NOTES,  LEVEL_MAIN  },
@@ -1099,7 +1099,7 @@ static lookups chart[] = {
 	{ "%A", "AUTHOR",    PERSON, LEVEL_MAIN },
 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
-	{ "%D", "YEAR",      SIMPLE, LEVEL_MAIN },
+	{ "%D", "DATE:YEAR",      SIMPLE, LEVEL_MAIN },
 	{ "%T", "TITLE" ,    TITLE,  LEVEL_MAIN },
 	{ "%J", "TITLE",     TITLE,  LEVEL_HOST }, /* for refer formats */
 	{ "%E", "2ND_AUTHOR",PERSON, LEVEL_MAIN },
@@ -1114,7 +1114,7 @@ static lookups chart[] = {
 	{ "%Y", "AUTHOR",    PERSON, LEVEL_SERIES },
 	{ "%S", "TITLE",     TITLE,  LEVEL_SERIES },
 	{ "%7", "EDITION",   SIMPLE, LEVEL_MAIN },
-	{ "%8", "MONTH",     DATE,   LEVEL_MAIN },
+	{ "%8", "DATE:MONTH",     DATE,   LEVEL_MAIN },
 	{ "%9", "GENRE",     SIMPLE, LEVEL_MAIN },
 	{ "%?", "SUB_AUTHOR",   PERSON, LEVEL_MAIN }, /* subsidiary-authors */
 	{ "%!", "SHORTTITLE",   TITLE,  LEVEL_MAIN },
@@ -1134,7 +1134,7 @@ static lookups chart[] = {
 	{ "%K", "KEYWORD",      SIMPLE, LEVEL_MAIN }, 
 	{ "%X", "ABSTRACT",     SIMPLE, LEVEL_MAIN },
 	{ "%O", "NOTES",        NOTES,  LEVEL_MAIN },
-	{ "%U", "URL",          SIMPLE, LEVEL_MAIN },
+	{ "%U", "URL",          URL,    LEVEL_MAIN },
 	{ "%Z", "NOTES",        NOTES,  LEVEL_MAIN },
 	{ "%W", "PHYSICALLOC",  SIMPLE, LEVEL_MAIN },  /* physical location */
 	{ "%+", "AUTHORADDRESS",SIMPLE, LEVEL_MAIN },
@@ -1152,7 +1152,7 @@ static lookups unpublished[] = {
 	{ "%A", "AUTHOR",    PERSON, LEVEL_MAIN },
 	{ "%H", "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "%Q", "TRANSLATEDTITLE", SIMPLE, LEVEL_MAIN },
-	{ "%D", "YEAR",      SIMPLE, LEVEL_MAIN },
+	{ "%D", "DATE:YEAR",      SIMPLE, LEVEL_MAIN },
 	{ "%T", "TITLE" ,    TITLE,  LEVEL_MAIN },
 	{ "%J", "TITLE",     TITLE,  LEVEL_HOST }, /* for refer formats */
 	{ "%E", "2ND_AUTHOR",PERSON, LEVEL_MAIN },
@@ -1167,7 +1167,7 @@ static lookups unpublished[] = {
 	{ "%Y", "AUTHOR",   PERSON, LEVEL_SERIES },
 	{ "%S", "TITLE",    TITLE, LEVEL_SERIES },
 	{ "%7", "EDITION",      SIMPLE, LEVEL_MAIN },
-	{ "%8", "MONTH",    DATE,   LEVEL_MAIN },
+	{ "%8", "DATE:MONTH",    DATE,   LEVEL_MAIN },
 	{ "%9", "GENRE",        SIMPLE, LEVEL_MAIN },
 	{ "%?", "SUB_AUTHOR",   PERSON, LEVEL_MAIN }, /* subsidiary-authors */
 	{ "%!", "SHORTTITLE",   TITLE,  LEVEL_MAIN },
@@ -1187,7 +1187,7 @@ static lookups unpublished[] = {
 	{ "%K", "KEYWORD",      SIMPLE, LEVEL_MAIN }, 
 	{ "%X", "ABSTRACT",     SIMPLE, LEVEL_MAIN },
 	{ "%O", "NOTES",        NOTES,  LEVEL_MAIN },
-	{ "%U", "URL",          SIMPLE, LEVEL_MAIN },
+	{ "%U", "URL",          URL,    LEVEL_MAIN },
 	{ "%>", "PDFLINK",      SIMPLE, LEVEL_MAIN },
 	{ "%Z", "NOTES",        NOTES,  LEVEL_MAIN },
 	{ "%W", "PHYSICALLOC",  SIMPLE, LEVEL_MAIN },  /* physical location */
diff --git a/lib/endxmlin.c b/lib/endxmlin.c
index 4121b86..34f7e45 100644
--- a/lib/endxmlin.c
+++ b/lib/endxmlin.c
@@ -1,7 +1,7 @@
 /*
  * endxmlin.c
  *
- * Copyright (c) Chris Putnam 2006-2015
+ * Copyright (c) Chris Putnam 2006-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -15,14 +15,23 @@
 #include "xml.h"
 #include "xml_encoding.h"
 #include "reftypes.h"
-#include "endxmlin.h"
-#include "endin.h"
+#include "bibformats.h"
 
 typedef struct {
 	char *attrib;
 	char *internal;
 } attribs;
 
+extern variants end_all[];
+extern int end_nall;
+
+static int endxmlin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );
+static int endxmlin_processf( fields *endin, char *p, char *filename, long nref, param *pm );
+extern int endin_typef( fields *endin, char *filename, int nrefs, param *p );
+extern int endin_convertf( fields *endin, fields *info, int reftype, param *p );
+extern int endin_cleanf( bibl *bin, param *p );
+
+
 /*****************************************************
  PUBLIC: void endxmlin_initparams()
 *****************************************************/
@@ -66,7 +75,7 @@ xml_readmore( FILE *fp, char *buf, int bufsize, int *bufpos )
 	return 1;
 }
 
-int
+static int
 endxmlin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line,
 	newstr *reference, int *fcharset )
 {
@@ -541,8 +550,8 @@ endxmlin_assembleref( xml *node, fields *info )
  * this is necessary as the xml format is as nasty and as overloaded
  * as the tags used in the Refer format output
  */
-int
-endxmlin_processf( fields *fin, char *data, char *filename, long nref )
+static int
+endxmlin_processf( fields *fin, char *data, char *filename, long nref, param *pm )
 {
 	int status;
 	xml top;
diff --git a/lib/endxmlin.h b/lib/endxmlin.h
deleted file mode 100644
index ec25032..0000000
--- a/lib/endxmlin.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * endxmlin.h
- *
- * Copyright (c) Chris Putnam 2006-2015
- *
- * Source code released under the GPL version 2
- *
- */
-#ifndef ENDXMLIN_H
-#define ENDXMLIN_H
-
-#include "newstr.h"
-#include "fields.h"
-#include "reftypes.h"
-#include "bibutils.h"
-
-extern int endxmlin_readf( FILE *fp, char *buf, int bufsize, int *bufpos,
-	newstr *line, newstr *reference, int *fcharset );
-extern int endxmlin_processf( fields *endin, char *p, char *filename, long nref );
-
-extern void endxmlin_initparams( param *p, const char *progname );
-
-#endif
diff --git a/lib/entities.c b/lib/entities.c
index 21ce86e..2ae8843 100644
--- a/lib/entities.c
+++ b/lib/entities.c
@@ -1,7 +1,7 @@
 /*
  * entities.c
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/lib/entities.h b/lib/entities.h
index 38f71e1..c2eeb6f 100644
--- a/lib/entities.h
+++ b/lib/entities.h
@@ -1,7 +1,7 @@
 /*
  * entities.h
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/lib/fields.c b/lib/fields.c
index 76ca866..6a6fc97 100644
--- a/lib/fields.c
+++ b/lib/fields.c
@@ -1,7 +1,7 @@
 /*
  * fields.c
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Source code released under the GPL version 2
  *
@@ -105,9 +105,9 @@ fields_realloc( fields *f )
 }
 
 int
-fields_add( fields *f, char *tag, char *data, int level )
+_fields_add( fields *f, char *tag, char *data, int level, int mode )
 {
-	int i, status, found;
+	int i, n, status;
 
 	if ( !tag || !data ) return FIELDS_OK;
 
@@ -119,29 +119,33 @@ fields_add( fields *f, char *tag, char *data, int level )
 		if ( status!=FIELDS_OK ) return status;
 	}
 
-	/* Don't duplicate identical entries */
-	found = 0;
-	for ( i=0; i<f->n && !found; ++i ) {
-		if ( f->level[i]==level &&
-		     !strcasecmp( f->tag[i].data, tag ) &&
-		     !strcasecmp( f->data[i].data, data ) ) found = 1;
-	}
-	if ( !found ) {
-		f->used[ f->n ]  = 0;
-		f->level[ f->n ] = level;
-		newstr_strcpy( &(f->tag[f->n]), tag );
-		newstr_strcpy( &(f->data[f->n]), data );
-		if ( newstr_memerr( &(f->tag[f->n]) ) ||
-		     newstr_memerr( &(f->data[f->n] ) ) )
-			return FIELDS_ERR;
-		f->n++;
+	/* Don't duplicate identical entries if FIELDS_NO_DUPS */
+	if ( mode == FIELDS_NO_DUPS ) {
+		for ( i=0; i<f->n; i++ ) {
+			if ( f->level[i]==level &&
+			     !strcasecmp( f->tag[i].data, tag ) &&
+			     !strcasecmp( f->data[i].data, data ) )
+				return FIELDS_OK;
+		}
 	}
+
+	n = f->n;
+	f->used[ n ]  = 0;
+	f->level[ n ] = level;
+	newstr_strcpy( &(f->tag[n]), tag );
+	newstr_strcpy( &(f->data[n]), data );
+
+	if ( newstr_memerr( &(f->tag[n]) ) || newstr_memerr( &(f->data[n] ) ) )
+		return FIELDS_ERR;
+
+	f->n++;
+
 	return FIELDS_OK;
 }
 
 int
-fields_add_tagsuffix( fields *f, char *tag, char *suffix,
-		char *data, int level )
+_fields_add_tagsuffix( fields *f, char *tag, char *suffix,
+		char *data, int level, int mode )
 {
 	newstr newtag;
 	int ret;
@@ -149,7 +153,7 @@ fields_add_tagsuffix( fields *f, char *tag, char *suffix,
 	newstr_init( &newtag );
 	newstr_mergestrs( &newtag, tag, suffix, NULL );
 	if ( newstr_memerr( &newtag ) ) ret = FIELDS_ERR;
-	else ret = fields_add( f, newtag.data, data, level );
+	else ret = _fields_add( f, newtag.data, data, level, mode );
 	newstr_free( &newtag );
 
 	return ret;
@@ -161,7 +165,7 @@ fields_add_tagsuffix( fields *f, char *tag, char *suffix,
  *
  * level==LEVEL_ANY is a special flag meaning any level can match
  */
-inline int
+int
 fields_match_level( fields *f, int n, int level )
 {
 	if ( level==LEVEL_ANY ) return 1;
@@ -174,28 +178,28 @@ fields_match_level( fields *f, int n, int level )
  * returns 1 if tag matches, 0 if not
  *
  */
-inline int
+int
 fields_match_tag( fields *info, int n, char *tag )
 {
 	if ( !strcmp( fields_tag( info, n, FIELDS_CHRP ), tag ) ) return 1;
 	return 0;
 }
 
-inline int
+int
 fields_match_casetag( fields *info, int n, char *tag )
 {
 	if ( !strcasecmp( fields_tag( info, n, FIELDS_CHRP ), tag ) ) return 1;
 	return 0;
 }
 
-inline int
+int
 fields_match_tag_level( fields *info, int n, char *tag, int level )
 {
 	if ( !fields_match_level( info, n, level ) ) return 0;
 	return fields_match_tag( info, n, tag );
 }
 
-inline int
+int
 fields_match_casetag_level( fields *info, int n, char *tag, int level )
 {
 	if ( !fields_match_level( info, n, level ) ) return 0;
@@ -276,27 +280,36 @@ fields_replace_or_add( fields *f, char *tag, char *data, int level )
 
 char *fields_null_value = "\0";
 
-inline int
+int
 fields_used( fields *f, int n )
 {
 	if ( n >= 0 && n < f->n ) return f->used[n];
 	else return 0;
 }
 
-inline int
+int
+fields_notag( fields *f, int n )
+{
+	newstr *t;
+	if ( n >= 0 && n < f->n ) {
+		t = &( f->tag[n] );
+		if ( t->len > 0 ) return 0;
+	}
+	return 1;
+}
+
+int
 fields_nodata( fields *f, int n )
 {
 	newstr *d;
 	if ( n >= 0 && n < f->n ) {
 		d = &( f->data[n] );
 		if ( d->len > 0 ) return 0;
-		return 1;
-	} else {
-		return 1;
 	}
+	return 1;
 }
 
-inline int
+int
 fields_num( fields *f )
 {
 	return f->n;
@@ -504,3 +517,20 @@ fields_findv_eachof( fields *f, int level, int mode, vplist *a, ... )
 
 	vplist_free( &tags );
 }
+
+void
+fields_report( fields *f, FILE *fp )
+{
+	int i, n;
+	n = fields_num( f );
+	fprintf( fp, "# NUM   level = LEVEL   'TAG' = 'VALUE'\n" );
+	for ( i=0; i<n; ++i ) {
+		fprintf( stderr, "%d\tlevel = %d\t'%s' = '%s'\n",
+			i+1,
+			fields_level( f, i ),
+			(char*)fields_tag( f, i, FIELDS_CHRP_NOUSE ),
+			(char*)fields_value( f, i, FIELDS_CHRP_NOUSE )
+		);
+	}
+}
+
diff --git a/lib/fields.h b/lib/fields.h
index c0df0bd..3e3335d 100644
--- a/lib/fields.h
+++ b/lib/fields.h
@@ -1,7 +1,7 @@
 /*
  * fields.h
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Source code released under the GPL version 2
  *
@@ -23,7 +23,7 @@
 #include "newstr.h"
 #include "vplist.h"
 
-typedef struct {
+typedef struct fields {
 	newstr    *tag;
 	newstr    *data;
 	int       *used;
@@ -32,28 +32,39 @@ typedef struct {
 	int       max;
 } fields;
 
-extern void fields_init( fields *f );
-extern fields *fields_new( void );
-extern void fields_free( fields *f );
+void    fields_init( fields *f );
+fields *fields_new( void );
+void    fields_free( fields *f );
 
-extern int  fields_add( fields *f, char *tag, char *data, int level );
-extern int  fields_add_tagsuffix( fields *f, char *tag, char *suffix,
-		char *data, int level );
+#define FIELDS_CAN_DUP (0)
+#define FIELDS_NO_DUPS (1)
 
-extern int  fields_maxlevel( fields *f );
-extern void fields_clearused( fields *f );
-extern void fields_setused( fields *f, int n );
-extern int  fields_replace_or_add( fields *f, char *tag, char *data, int level );
+#define fields_add( a, b, c, d )         _fields_add( a, b, c, d, FIELDS_NO_DUPS )
+#define fields_add_can_dup( a, b, c, d ) _fields_add( a, b, c, d, FIELDS_CAN_DUP )
+#define fields_add_tagsuffix( a, b, c, d, e )         _fields_add( a, b, c, d, e, FIELDS_NO_DUPS )
+#define fields_add_tagsuffix_can_dup( a, b, c, d, e ) _fields_add( a, b, c, d, e, FIELDS_CAN_DUP )
 
-extern inline int fields_num( fields *f );
-extern inline int fields_used( fields *f, int n );
-extern inline int fields_nodata( fields *f, int n );
+int  _fields_add( fields *f, char *tag, char *data, int level, int mode );
+int  _fields_add_tagsuffix( fields *f, char *tag, char *suffix,
+		char *data, int level, int mode );
 
-extern inline int fields_match_level( fields *f, int n, int level );
-extern inline int fields_match_tag( fields *f, int n, char *tag );
-extern inline int fields_match_casetag( fields *f, int n, char *tag );
-extern inline int fields_match_tag_level( fields *f, int n, char *tag, int level );
-extern inline int fields_match_casetag_level( fields *f, int n, char *tag, int level );
+int  fields_maxlevel( fields *f );
+void fields_clearused( fields *f );
+void fields_setused( fields *f, int n );
+int  fields_replace_or_add( fields *f, char *tag, char *data, int level );
+
+int fields_num( fields *f );
+int fields_used( fields *f, int n );
+int fields_notag( fields *f, int n );
+int fields_nodata( fields *f, int n );
+
+int fields_match_level( fields *f, int n, int level );
+int fields_match_tag( fields *f, int n, char *tag );
+int fields_match_casetag( fields *f, int n, char *tag );
+int fields_match_tag_level( fields *f, int n, char *tag, int level );
+int fields_match_casetag_level( fields *f, int n, char *tag, int level );
+
+void fields_report( fields *f, FILE *fp );
 
 #define FIELDS_STRP_FLAG     (2)
 #define FIELDS_POSP_FLAG     (4)
@@ -69,16 +80,16 @@ extern inline int fields_match_casetag_level( fields *f, int n, char *tag, int l
 #define FIELDS_CHRP_NOUSE  (                            0                              )
 #define FIELDS_STRP_NOUSE  (                     FIELDS_STRP_FLAG                      )
 
-extern void *fields_tag( fields *f, int n, int mode );
-extern void *fields_value( fields *f, int n, int mode );
-extern int   fields_level( fields *f, int n );
+void *fields_tag( fields *f, int n, int mode );
+void *fields_value( fields *f, int n, int mode );
+int   fields_level( fields *f, int n );
  
-extern int   fields_find( fields *f, char *searchtag, int level );
+int   fields_find( fields *f, char *searchtag, int level );
 
-extern void *fields_findv( fields *f, int level, int mode, char *tag );
-extern void *fields_findv_firstof( fields *f, int level, int mode, ... );
+void *fields_findv( fields *f, int level, int mode, char *tag );
+void *fields_findv_firstof( fields *f, int level, int mode, ... );
 
-extern void  fields_findv_each( fields *f, int level, int mode, vplist *a, char *tag );
-extern void  fields_findv_eachof( fields *f, int level, int mode, vplist *a, ... );
+void  fields_findv_each( fields *f, int level, int mode, vplist *a, char *tag );
+void  fields_findv_eachof( fields *f, int level, int mode, vplist *a, ... );
 
 #endif
diff --git a/lib/gb18030.h b/lib/gb18030.h
index b0a5d98..a1d0ae5 100644
--- a/lib/gb18030.h
+++ b/lib/gb18030.h
@@ -1,7 +1,7 @@
 /*
  * gb18030.h
  *
- * Copyright (c) Chris Putnam 2008-2015
+ * Copyright (c) Chris Putnam 2008-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/lib/generic.c b/lib/generic.c
new file mode 100644
index 0000000..33331e7
--- /dev/null
+++ b/lib/generic.c
@@ -0,0 +1,77 @@
+/* generic.c
+ *
+ * xxxx_converf() stubs that can be shared.
+ */
+#include "name.h"
+#include "notes.h"
+#include "pages.h"
+#include "serialno.h"
+#include "title.h"
+#include "url.h"
+#include "generic.h"
+
+/* stub for processtypes that aren't used, such as DEFAULT and ALWAYS handled by bibcore.c  */
+int
+generic_null( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
+{
+	return BIBL_OK;
+}
+
+int
+generic_url( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
+{
+	return urls_split_and_add( invalue->data, bibout, level );
+}
+
+int
+generic_notes( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
+{
+        if ( notes_add( bibout, invalue, level ) ) return BIBL_OK;
+        else return BIBL_ERR_MEMERR;
+}
+
+int
+generic_pages( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
+{
+        if ( pages_add( bibout, outtag, invalue, level ) ) return BIBL_OK;
+        else return BIBL_ERR_MEMERR;
+}
+
+int
+generic_person( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
+{
+        if ( name_add( bibout, outtag, invalue->data, level, &(pm->asis), &(pm->corps) ) ) return BIBL_OK;
+        else return BIBL_ERR_MEMERR;
+}
+
+int
+generic_serialno( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
+{
+	if ( addsn( bibout, invalue->data, level ) ) return BIBL_OK;
+	return BIBL_ERR_MEMERR;
+}
+
+/* SIMPLE = just copy */
+int
+generic_simple( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
+{
+	if ( fields_add( bibout, outtag, invalue->data, level ) == FIELDS_OK ) return BIBL_OK;
+	else return BIBL_ERR_MEMERR;
+}
+
+/* just like generic_null(), but useful if we need one that isn't identical to generic_null() ala biblatexin.c */
+int
+generic_skip( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
+{
+	fields_setused( bibin, n );
+	return BIBL_OK;
+}
+
+int
+generic_title( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
+{
+        if ( title_process( bibout, outtag, invalue->data, level, pm->nosplittitle ) ) return BIBL_OK;
+        else return BIBL_ERR_MEMERR;
+}
+
+
diff --git a/lib/generic.h b/lib/generic.h
new file mode 100644
index 0000000..d6c3697
--- /dev/null
+++ b/lib/generic.h
@@ -0,0 +1,23 @@
+/* generic.h
+ *
+ * Copyright (c) Chris Putnam 2016
+ *
+ * Source code released under GPL version 2
+ *
+ */
+#ifndef GENERIC_H
+#define GENERIC_H
+
+#include "bibutils.h"
+
+int generic_null    ( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout );
+int generic_url     ( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout );
+int generic_notes   ( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout );
+int generic_pages   ( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout );
+int generic_person  ( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout );
+int generic_serialno( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout );
+int generic_simple  ( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout );
+int generic_skip    ( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout );
+int generic_title   ( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout );
+
+#endif
diff --git a/lib/intlist.c b/lib/intlist.c
index 0f5154a..ec122a2 100644
--- a/lib/intlist.c
+++ b/lib/intlist.c
@@ -1,7 +1,7 @@
 /*
  * intlist.c
  *
- * Copyright (c) Chris Putnam 2007-2015
+ * Copyright (c) Chris Putnam 2007-2016
  *
  * Version 9/5/2013
  *
diff --git a/lib/intlist.h b/lib/intlist.h
index 9391a18..6485802 100644
--- a/lib/intlist.h
+++ b/lib/intlist.h
@@ -1,7 +1,7 @@
 /*
  * intlist.h
  *
- * Copyright (c) Chris Putnam 2007-2015
+ * Copyright (c) Chris Putnam 2007-2016
  *
  * Version 9/5/2013
  *
diff --git a/lib/is_ws.c b/lib/is_ws.c
index ab45e8c..2c6ce6f 100644
--- a/lib/is_ws.c
+++ b/lib/is_ws.c
@@ -1,7 +1,7 @@
 /*
  * is_ws.c
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/lib/is_ws.h b/lib/is_ws.h
index 5931dcc..df9af3f 100644
--- a/lib/is_ws.h
+++ b/lib/is_ws.h
@@ -1,7 +1,7 @@
 /*
  * is_ws.h
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/lib/isiin.c b/lib/isiin.c
index 44e1008..69a5679 100644
--- a/lib/isiin.c
+++ b/lib/isiin.c
@@ -1,7 +1,7 @@
 /*
  * isiin.c
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -12,12 +12,20 @@
 #include "is_ws.h"
 #include "newstr.h"
 #include "newstr_conv.h"
-#include "fields.h"
 #include "name.h"
-#include "title.h"
-#include "serialno.h"
+#include "fields.h"
 #include "reftypes.h"
-#include "isiin.h"
+#include "bibformats.h"
+#include "generic.h"
+
+extern variants isi_all[];
+extern int isi_nall;
+
+static int isiin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );
+static int isiin_typef( fields *isiin, char *filename, int nref, param *p );
+static int isiin_convertf( fields *isiin, fields *info, int reftype, param *p );
+static int isiin_processf( fields *isiin, char *p, char *filename, long nref, param *pm );
+
 
 /*****************************************************
  PUBLIC: void isiin_initparams()
@@ -75,7 +83,7 @@ readmore( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line )
 	else return newstr_fget( fp, buf, bufsize, bufpos, line );
 }
 
-int
+static int
 isiin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset )
 {
 	int haveref = 0, inref = 0;
@@ -146,8 +154,8 @@ process_isiline( newstr *tag, newstr *data, char *p )
 	return p;
 }
 
-int
-isiin_processf( fields *isiin, char *p, char *filename, long nref )
+static int
+isiin_processf( fields *isiin, char *p, char *filename, long nref, param *pm )
 {
 	int status, n, ret = 1;
 	newstr tag, data;
@@ -191,44 +199,25 @@ out:
 /*****************************************************
  PUBLIC: int isiin_typef()
 *****************************************************/
-int
-isiin_typef( fields *isiin, char *filename, int nref, param *p, variants *all, int nall )
+static int
+isiin_typef( fields *isiin, char *filename, int nref, param *p )
 {
-	char *refnum = "";
-	int n, reftype, nrefnum;
-	n = fields_find( isiin, "PT", 0 );
-	nrefnum = fields_find ( isiin, "UT", 0 );
-	if ( nrefnum!=-1 ) refnum = isiin->data[nrefnum].data;
-	if ( n!=-1 )
-		reftype = get_reftype( (isiin->data[n]).data, nref, p->progname, all, nall, refnum );
-	else
-		reftype = get_reftype( "", nref, p->progname, all, nall, refnum ); /* default */
-	return reftype;
+	int ntypename, nrefname, is_default;
+	char *refname = "", *typename="";
+
+	ntypename = fields_find( isiin, "PT", LEVEL_MAIN );
+	nrefname  = fields_find( isiin, "UT", LEVEL_MAIN );
+
+	if ( nrefname!=-1 )  refname  = fields_value( isiin, nrefname,  FIELDS_CHRP_NOUSE );
+	if ( ntypename!=-1 ) typename = fields_value( isiin, ntypename, FIELDS_CHRP_NOUSE );
+
+	return get_reftype( typename, nref, p->progname, p->all, p->nall, refname, &is_default, REFTYPE_CHATTY );
 }
 
 /*****************************************************
  PUBLIC: int isiin_convertf(), returns BIBL_OK or BIBL_ERR_MEMERR
 *****************************************************/
 
-static int
-isiin_keyword_process( fields *info, char *newtag, char *p, int level )
-{
-	int fstatus, status = BIBL_OK;
-	newstr keyword;
-	newstr_init( &keyword );
-	while ( *p ) {
-		p = newstr_cpytodelim( &keyword, skip_ws( p ), ";", 1 );
-		if ( newstr_memerr( &keyword ) ) { status = BIBL_ERR_MEMERR; goto out; }
-		if ( keyword.len ) {
-			fstatus = fields_add( info, newtag, keyword.data, level );
-			if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }
-		}
-	}
-out:
-	newstr_free( &keyword );
-	return status;
-}
-
 /* pull off authors first--use AF before AU */
 static int
 isiin_addauthors( fields *isiin, fields *info, int reftype, variants *all, int nall, list *asis, list *corps )
@@ -259,6 +248,27 @@ isiin_addauthors( fields *isiin, fields *info, int reftype, variants *all, int n
 	return BIBL_OK;
 }
 
+static int
+isiin_keyword( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
+{
+	int fstatus, status = BIBL_OK;
+	char *p = invalue->data;
+	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( bibout, outtag, keyword.data, level );
+			if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }
+		}
+	}
+out:
+	newstr_free( &keyword );
+	return status;
+}
+
 static void
 isiin_report_notag( param *p, char *tag )
 {
@@ -269,79 +279,45 @@ isiin_report_notag( param *p, char *tag )
 }
 
 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 )
+isiin_convertf( fields *bibin, fields *bibout, int reftype, param *p )
 {
-	int process, level, i, n, nfields, ok, status;
-	newstr *t, *d;
-	char *newtag;
-
-	status = isiin_addauthors( isiin, info, reftype, all, nall, &(p->asis), &(p->corps) );
+	static int (*convertfns[NUM_REFTYPES])(fields *, int, newstr *, newstr *, int, param *, char *, fields *) = {
+		[ 0 ... NUM_REFTYPES-1 ] = generic_null,
+		[ SIMPLE       ] = generic_simple,
+		[ TITLE        ] = generic_title,
+		[ PERSON       ] = generic_person,
+		[ SERIALNO     ] = generic_serialno,
+		[ DATE         ] = generic_simple,
+		[ NOTES        ] = generic_notes,
+		[ KEYWORD      ] = isiin_keyword,
+	};
+
+	int process, level, i, nfields, status;
+	newstr *intag, *invalue;
+	char *outtag;
+
+	status = isiin_addauthors( bibin, bibout, reftype, p->all, p->nall, &(p->asis), &(p->corps) );
 	if ( status!=BIBL_OK ) return status;
 
-	nfields = fields_num( isiin );
+	nfields = fields_num( bibin );
 	for ( i=0; i<nfields; ++i ) {
 
-		t = fields_tag( isiin, i, FIELDS_STRP );
-		if ( !strcasecmp( t->data, "AU" ) || !strcasecmp( t->data, "AF" ) )
+		intag = fields_tag( bibin, i, FIELDS_STRP );
+		if ( !strcasecmp( intag->data, "AU" ) || !strcasecmp( intag->data, "AF" ) )
 			continue;
 
-		n = translate_oldtag( t->data, reftype, all, nall, &process, &level, &newtag );
-		if ( n==-1 ) {
-			isiin_report_notag( p, t->data );
+		if ( !translate_oldtag( intag->data, reftype, p->all, p->nall, &process, &level, &outtag ) ) {
+			isiin_report_notag( p, intag->data );
 			continue;
 		}
-		if ( process == ALWAYS ) continue; /* add in core code */
-
-		d = fields_value( isiin, i, FIELDS_STRP );
-
-		ok = 1;
-
-		switch ( process ) {
 
-		case SIMPLE:
-		case DATE:
-			status = isiin_simple( info, newtag, d->data, level );
-			break;
-
-		case PERSON:
-			ok = name_add( info, newtag, d->data, level, &(p->asis), &(p->corps) );
-			if ( ok ) status = BIBL_OK;
-			else status = BIBL_ERR_MEMERR;
-			break;
-
-		case TITLE:
-			ok = title_process( info, newtag, d->data, level, p->nosplittitle );
-			if ( ok ) status = BIBL_OK;
-			else status = BIBL_ERR_MEMERR;
-			break;
-
-		case KEYWORD:
-			status = isiin_keyword_process( info, newtag, d->data, level );
-			break;
-
-		case SERIALNO:
-			ok = addsn( info, d->data, level );
-			if ( ok ) status = BIBL_OK;
-			else status = BIBL_ERR_MEMERR;
-			break;
-
-		/* do nothing if process==TYPE || process==ALWAYS */
-		default:
-			status = BIBL_OK;
-			break;
-
-		}
+		invalue = fields_value( bibin, i, FIELDS_STRP );
 
+		status = convertfns[ process ] ( bibin, i, intag, invalue, level, p, outtag, bibout );
 		if ( status!=BIBL_OK ) return status;
 	}
 
+	if ( status==BIBL_OK && p->verbose ) fields_report( bibout, stderr );
+
 	return status;
 }
diff --git a/lib/isiin.h b/lib/isiin.h
deleted file mode 100644
index d0b911a..0000000
--- a/lib/isiin.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * isiin.h
- * 
- * Copyright (c) Chris Putnam 2004-2015
- *
- * Source code released under the GPL version 2
- *
- */
-#ifndef ISIIN_H
-#define ISIIN_H
-
-#include "newstr.h"
-#include "fields.h"
-#include "reftypes.h"
-#include "bibutils.h"
-
-extern int isiin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );
-extern int isiin_typef( fields *isiin, char *filename, int nref, param *p, variants *all, int nall );
-extern int isiin_convertf( fields *isiin, fields *info, int reftype, param *p, variants *all, int nall );
-extern int isiin_processf( fields *isiin, char *p, char *filename, long nref );
-
-extern void isiin_initparams( param *p, const char *progname );
-
-extern variants isi_all[];
-extern int isi_nall;
-
-#endif
-
diff --git a/lib/isiout.c b/lib/isiout.c
index a1357fa..9718c09 100644
--- a/lib/isiout.c
+++ b/lib/isiout.c
@@ -1,7 +1,7 @@
 /*
  * isiout.c
  *
- * Copyright (c) Chris Putnam 2008-2015
+ * Copyright (c) Chris Putnam 2008-2016
  *
  * Source code released under the GPL version 2
  *
@@ -14,8 +14,12 @@
 #include "newstr.h"
 #include "strsearch.h"
 #include "fields.h"
+#include "title.h"
 #include "bibutils.h"
-#include "isiout.h"
+#include "bibformats.h"
+
+static int  isiout_write( fields *info, FILE *fp, param *p, unsigned long refnum );
+static void isiout_writeheader( FILE *outptr, param *p );
 
 void
 isiout_initparams( param *p, const char *progname )
@@ -49,29 +53,18 @@ enum {
         TYPE_BOOK    = 3,
 };
 
-static void
-output_type( FILE *fp, int type )
-{
-	fprintf( fp, "PT " );
-	if ( type==TYPE_ARTICLE ) fprintf( fp, "Journal" );
-	else if ( type==TYPE_INBOOK ) fprintf( fp, "Chapter" );
-	else if ( type==TYPE_BOOK ) fprintf( fp, "Book" );
-	else fprintf( fp, "Unknown" );
-	fprintf( fp, "\n" );
-}
-
 static int 
-get_type( fields *f )
+get_type( fields *in )
 {
         int type = TYPE_UNKNOWN, i, n, level;
 	char *tag, *value;
-	n = fields_num( f );
+	n = fields_num( in );
         for ( i=0; i<n; ++i ) {
-		tag = fields_tag( f, i, FIELDS_CHRP );
+		tag = fields_tag( in, i, FIELDS_CHRP );
                 if ( strcasecmp( tag, "GENRE" ) &&
                      strcasecmp( tag, "NGENRE") ) continue;
-		value = fields_value( f, i, FIELDS_CHRP );
-		level = fields_level( f, i );
+		value = fields_value( in, i, FIELDS_CHRP );
+		level = fields_level( in, i );
                 if ( !strcasecmp( value, "periodical" ) ||
                      !strcasecmp( value, "academic journal" ) ||
 		     !strcasecmp( value, "journal article" ) ) {
@@ -87,60 +80,83 @@ get_type( fields *f )
 }
 
 static void
-output_titlecore( FILE *fp, fields *f, char *isitag, int level,
-	char *maintag, char *subtag )
+append_type( int type, fields *out, int *status )
 {
-	newstr *mainttl = fields_findv( f, level, FIELDS_STRP, maintag );
-	newstr *subttl  = fields_findv( f, level, FIELDS_STRP, subtag );
+	int fstatus;
+	char *s;
 
-	if ( !mainttl ) return;
+	if ( type==TYPE_ARTICLE ) s = "Journal";
+	else if ( type==TYPE_INBOOK ) s = "Chapter";
+	else if ( type==TYPE_BOOK ) s = "Book";
+	else s = "Unknown";
+
+	fstatus = fields_add( out, "PT", s, LEVEL_MAIN );
+	if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+}
 
-	fprintf( fp, "%s %s", isitag, mainttl->data );
-	if ( subttl ) {
-		if ( mainttl->len > 0 &&
-		     mainttl->data[ mainttl->len - 1 ]!='?' )
-				fprintf( fp, ":" );
-		fprintf( fp, " %s", subttl->data );
+static void
+append_titlecore( fields *in, char *isitag, int level, char *maintag, char *subtag, fields *out, int *status )
+{
+	newstr *mainttl = fields_findv( in, level, FIELDS_STRP, maintag );
+	newstr *subttl  = fields_findv( in, level, FIELDS_STRP, subtag );
+	newstr fullttl;
+	int fstatus;
+
+	newstr_init( &fullttl );
+	title_combine( &fullttl, mainttl, subttl );
+
+	if ( fullttl.len ) {
+		fstatus = fields_add( out, isitag, newstr_cstr( &fullttl ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 	}
-	fprintf( fp, "\n" );
+
+	newstr_free( &fullttl );
 }
 
 static void
-output_title( FILE *fp, fields *f, char *isitag, int level )
+append_title( fields *in, char *isitag, int level, fields *out, int *status )
 {
-	output_titlecore( fp, f, isitag, level, "TITLE", "SUBTITLE" );
+	append_titlecore( in, isitag, level, "TITLE", "SUBTITLE", out, status );
 }
 
 static void
-output_abbrtitle( FILE *fp, fields *f, char *isitag, int level )
+append_abbrtitle( fields *in, char *isitag, int level, fields *out, int *status )
 {
-	output_titlecore( fp, f, isitag, level, "SHORTTITLE", "SHORTSUBTITLE" );
+	append_titlecore( in, isitag, level, "SHORTTITLE", "SHORTSUBTITLE", out, status );
 }
 
 static void
-output_keywords( FILE *fp, fields *f )
+append_keywords( fields *in, fields *out, int *status )
 {
+	newstr keywords;
+	int i, fstatus;
 	vplist kw;
-	int i;
+
+	newstr_init( &keywords );
+
 	vplist_init( &kw );
-	fields_findv_each( f, LEVEL_ANY, FIELDS_CHRP, &kw, "KEYWORD" );
+	fields_findv_each( in, LEVEL_ANY, FIELDS_CHRP, &kw, "KEYWORD" );
 	if ( kw.n ) {
-		fprintf( fp, "DE " );
 		for ( i=0; i<kw.n; ++i ) {
-			if ( i>0 ) fprintf( fp, "; " );
-			fprintf( fp, "%s", (char *)vplist_get( &kw, i ) );
+			if ( i>0 ) newstr_strcat( &keywords, "; " );
+			newstr_strcat( &keywords, (char *) vplist_get( &kw, i ) );
 		}
-		fprintf( fp, "\n" );
+		fstatus = fields_add( out, "DE", newstr_cstr( &keywords ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 	}
 	vplist_free( &kw );
+
+	newstr_free( &keywords );
 }
 
 static void
-output_person( FILE *fp, char *name )
+process_person( newstr *person, char *name )
 {
 	newstr family, given, suffix;
 	char *p = name;
 
+	newstr_empty( person );
+
 	newstrs_init( &family, &given, &suffix, NULL );
 
 	while ( *p && *p!='|' )
@@ -157,155 +173,195 @@ output_person( FILE *fp, char *name )
 		while ( *p && *p!='|' ) newstr_addchar( &suffix, *p++ );
 	}
 
-	if ( family.len ) fprintf( fp, "%s", family.data );
+	if ( family.len ) newstr_newstrcat( person, &family );
 	if ( suffix.len ) {
-		if ( family.len ) fprintf( fp, " %s", suffix.data );
-		else fprintf( fp, "%s", suffix.data );
+		if ( family.len ) newstr_strcat( person, " " );
+		newstr_newstrcat( person, &suffix );
+	}
+	if ( given.len ) {
+		if ( person->len ) newstr_strcat( person, ", " );
+		newstr_newstrcat( person, &given );
 	}
-	if ( given.len ) fprintf( fp, ", %s", given.data );
 
 	newstrs_free( &family, &given, &suffix, NULL );
 }
 
 static void
-output_people( FILE *fp, fields *f, char *tag, char *isitag, int level )
+append_people( fields *f, char *tag, char *isitag, int level, fields *out, int *status )
 {
+	int i, fstatus;
 	vplist people;
-	int i;
+	newstr person;
+
+	newstr_init( &person );
+
 	vplist_init( &people );
 	fields_findv_each( f, level, FIELDS_CHRP, &people, tag );
 	if ( people.n ) {
-		fprintf( fp, "%s ", isitag );
 		for ( i=0; i<people.n; ++i ) {
-			if ( i!=0 ) fprintf( fp, "   " );
-			output_person( fp, (char *)vplist_get( &people, i ) );
-			fprintf( fp, "\n" );
+			process_person( &person, (char *)vplist_get( &people, i ) );
+			if ( i==0 ) fstatus = fields_add_can_dup( out, isitag, newstr_cstr( &person ), LEVEL_MAIN );
+			else        fstatus = fields_add_can_dup( out, "  ",   newstr_cstr( &person ), LEVEL_MAIN );
+			if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 		}
 	}
 	vplist_free( &people );
+
+	newstr_free( &person );
 }
 
 static void
-output_easy( FILE *fp, fields *f, char *tag, char *isitag, int level )
+append_easy( fields *in, char *tag, char *isitag, int level, fields *out, int *status )
 {
-	char *value = fields_findv( f, level, FIELDS_CHRP, tag );
-	if ( value ) fprintf( fp, "%s %s\n", isitag, value );
+	char *value;
+	int fstatus;
+
+	value = fields_findv( in, level, FIELDS_CHRP, tag );
+	if ( value ) {
+		fstatus = fields_add( out, isitag, value, LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
 }
 
 static void
-output_easyall( FILE *fp, fields *f, char *tag, char *isitag, int level )
+append_easyall( fields *in, char *tag, char *isitag, int level, fields *out, int *status )
 {
+	int i, fstatus;
 	vplist a;
-	int i;
+
 	vplist_init( &a );
-	fields_findv_each( f, level, FIELDS_CHRP, &a, tag );
-	for ( i=0; i<a.n; ++i )
-		fprintf( fp, "%s %s\n", isitag, (char *) vplist_get( &a, i ) );
+	fields_findv_each( in, level, FIELDS_CHRP, &a, tag );
+	for ( i=0; i<a.n; ++i ) {
+		fstatus = fields_add( out, isitag, (char *) vplist_get( &a, i ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
 	vplist_free( &a );
 }
 
 static void
-output_date( FILE *fp, fields *f )
+append_date( fields *in, fields *out, int *status )
+{
+	char *month, *year;
+	int fstatus;
+
+	month = fields_findv_firstof( in, LEVEL_ANY, FIELDS_CHRP, "PARTDATE:MONTH", "DATE:MONTH", NULL );
+	if ( month ) {
+		fstatus = fields_add( out, "PD", month, LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
+	year  = fields_findv_firstof( in, LEVEL_ANY, FIELDS_CHRP, "PARTDATE:YEAR",  "DATE:YEAR",  NULL );
+	if ( year ) {
+		fstatus = fields_add( out, "PY", year, LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
+}
+
+static int
+append_data( fields *in, fields *out )
 {
-	char *month = fields_findv_firstof( f, LEVEL_ANY, FIELDS_CHRP,
-		"PARTMONTH", "MONTH", NULL );
-	char *year  = fields_findv_firstof( f, LEVEL_ANY, FIELDS_CHRP,
-		"PARTYEAR", "YEAR", NULL );
-	if ( month ) fprintf( fp, "PD %s\n", month );
-	if ( year )  fprintf( fp, "PY %s\n", year );
+	int type, status = BIBL_OK;
+
+	type = get_type( in );
+
+	append_type   ( type, out, &status );
+	append_people ( in, "AUTHOR",      "AU", LEVEL_MAIN, out, &status );
+	append_easyall( in, "AUTHOR:CORP", "AU", LEVEL_MAIN, out, &status );
+	append_easyall( in, "AUTHOR:ASIS", "AU", LEVEL_MAIN, out, &status );
+
+	append_title  ( in, "TI", LEVEL_MAIN, out, &status );
+	if ( type==TYPE_ARTICLE ) {
+		append_title( in, "SO", LEVEL_HOST,   out, &status );
+		append_abbrtitle( in, "JI", LEVEL_HOST, out, &status );
+		append_title( in, "SE", LEVEL_SERIES, out, &status );
+	} else if ( type==TYPE_INBOOK ) {
+		append_title( in, "BT", LEVEL_HOST,   out, &status );
+		append_title( in, "SE", LEVEL_SERIES, out, &status );
+	} else { /* type==BOOK */
+		append_title( in, "SE", LEVEL_HOST,   out, &status );
+	}
+
+	append_date( in, out, &status );
+
+	append_easy( in, "PAGES:START",    "BP", LEVEL_ANY, out, &status );
+	append_easy( in, "PAGES:STOP",     "EP", LEVEL_ANY, out, &status );
+	append_easy( in, "ARTICLENUMBER",  "AR", LEVEL_ANY, out, &status );
+	append_easy( in, "PAGES:TOTAL",    "PG", LEVEL_ANY, out, &status );
+
+	append_easy( in, "VOLUME",         "VL", LEVEL_ANY, out, &status );
+	append_easy( in, "ISSUE",          "IS", LEVEL_ANY, out, &status );
+	append_easy( in, "NUMBER",         "IS", LEVEL_ANY, out, &status );
+	append_easy( in, "DOI",            "DI", LEVEL_ANY, out, &status );
+	append_easy( in, "ISIREFNUM",      "UT", LEVEL_ANY, out, &status );
+	append_easy( in, "LANGUAGE",       "LA", LEVEL_ANY, out, &status );
+	append_easy( in, "ISIDELIVERNUM",  "GA", LEVEL_ANY, out, &status );
+	append_keywords( in, out, &status );
+	append_easy( in, "ABSTRACT",       "AB", LEVEL_ANY, out, &status );
+	append_easy( in, "TIMESCITED",     "TC", LEVEL_ANY, out, &status );
+	append_easy( in, "NUMBERREFS",     "NR", LEVEL_ANY, out, &status );
+	append_easy( in, "CITEDREFS",      "CR", LEVEL_ANY, out, &status );
+	append_easy( in, "ADDRESS",        "PI", LEVEL_ANY, out, &status );
+
+	return status;
 }
 
 static void
-output_verbose( fields *f, unsigned long refnum )
+output_verbose( fields *f, const char *type, unsigned long refnum )
 {
 	char *tag, *value;
 	int i, n, level;
-	fprintf( stderr, "REF #%lu----\n", refnum+1 );
+
+	fprintf( stderr, "REF #%lu %s---\n", refnum+1, type );
+
 	n = fields_num( f );
 	for ( i=0; i<n; ++i ) {
 		tag   = fields_tag( f, i, FIELDS_CHRP_NOUSE );
 		value = fields_value( f, i, FIELDS_CHRP_NOUSE );
 		level = fields_level( f, i );
-		fprintf( stderr, "\t'%s'\t'%s'\t%d\n",
-			tag, value, level );
+		fprintf( stderr, "\t'%s'\t'%s'\t%d\n", tag, value, level );
 	}
+
+	fflush( stderr );
 }
 
-void
-isiout_write( fields *f, FILE *fp, param *p, unsigned long refnum )
+static void
+output( FILE *fp, fields *out )
 {
-        int type = get_type( f );
+	int i;
 
-	if ( p->format_opts & BIBL_FORMAT_VERBOSE )
-		output_verbose( f, refnum );
-
-        output_type( fp, type );
-	output_people( fp, f, "AUTHOR", "AU", 0 );
-	output_easyall( fp, f, "AUTHOR:CORP", "AU", 0 );
-	output_easyall( fp, f, "AUTHOR:ASIS", "AU", 0 );
-/*      output_people( fp, f, "AUTHOR", "A2", 1 );
-        output_people( fp, f, "AUTHOR:CORP", "A2", 1 );
-        output_people( fp, f, "AUTHOR:ASIS", "A2", 1 );
-        output_people( fp, f, "AUTHOR", "A3", 2 );
-        output_people( fp, f, "AUTHOR:CORP", "A3", 2 );
-        output_people( fp, f, "AUTHOR:ASIS", "A3", 2 );
-        output_people( fp, f, "EDITOR", "ED", -1 );
-	output_people( fp, f, "EDITOR:CORP", "ED", -1 );
-        output_people( fp, f, "EDITOR:ASIS", "ED", -1 );*/
-/*        output_date( fp, f, refnum );*/
-
-        output_title( fp, f, "TI", 0 );
-        if ( type==TYPE_ARTICLE ) {
-		output_title( fp, f, "SO", 1 );
-		output_abbrtitle( fp, f, "JI", 1 );
-		output_title( fp, f, "SE", 2 );
-	} else if ( type==TYPE_INBOOK ) {
-		output_title( fp, f, "BT", 1 );
-		output_title( fp, f, "SE", 2 );
-	} else { /* type==BOOK */
-		output_title( fp, f, "SE", 1 );
+	for ( i=0; i<out->n; ++i ) {
+		fprintf( fp, "%s %s\n",
+			( char * ) fields_tag  ( out, i, FIELDS_CHRP ),
+			( char * ) fields_value( out, i, FIELDS_CHRP )
+		);
 	}
-
-	output_date( fp, f );
-/*	output_easy( fp, f, "PARTMONTH", "PD", -1 );
-	output_easy( fp, f, "PARTYEAR", "PY", -1 );*/
-
-	output_easy( fp, f, "PAGESTART", "BP", -1 );
-	output_easy( fp, f, "PAGEEND",   "EP", -1 );
-        output_easy( fp, f, "ARTICLENUMBER", "AR", -1 );
-        /* output article number as pages */
-	output_easy( fp, f, "TOTALPAGES","PG", -1 );
-
-        output_easy( fp, f, "VOLUME",    "VL", -1 );
-        output_easy( fp, f, "ISSUE",     "IS", -1 );
-        output_easy( fp, f, "NUMBER",    "IS", -1 );
-	output_easy( fp, f, "DOI",       "DI", -1 );
-	output_easy( fp, f, "ISIREFNUM", "UT", -1 );
-	output_easy( fp, f, "LANGUAGE",  "LA", -1 );
-	output_easy( fp, f, "ISIDELIVERNUM", "GA", -1 );
-	output_keywords( fp, f );
-	output_easy( fp, f, "ABSTRACT",  "AB", -1 );
-	output_easy( fp, f, "TIMESCITED", "TC", -1 );
-	output_easy( fp, f, "NUMBERREFS", "NR", -1 );
-	output_easy( fp, f, "CITEDREFS",  "CR", -1 );
-	output_easy( fp, f, "ADDRESS",    "PI", -1 );
-
-/*        output_easy( fp, f, "PUBLISHER", "PB", -1 );
-        output_easy( fp, f, "DEGREEGRANTOR", "PB", -1 );
-        output_easy( fp, f, "ADDRESS", "CY", -1 );
-        output_easy( fp, f, "ABSTRACT", "AB", -1 );
-        output_easy( fp, f, "ISSN", "SN", -1 );
-        output_easy( fp, f, "ISBN", "SN", -1 );
-        output_easyall( fp, f, "URL", "UR", -1 );
-        output_easyall( fp, f, "FILEATTACH", "UR", -1 );
-        output_pubmed( fp, f, refnum );
-        output_easyall( fp, f, "NOTES", "N1", -1 );
-        output_easyall( fp, f, "REFNUM", "ID", -1 );*/
         fprintf( fp, "ER\n\n" );
         fflush( fp );
 }
 
-void
+static int
+isiout_write( fields *in, FILE *fp, param *p, unsigned long refnum )
+{
+	int status;
+	fields out;
+
+	fields_init( &out );
+
+	if ( p->format_opts & BIBL_FORMAT_VERBOSE )
+		output_verbose( in, "IN", refnum );
+
+	status = append_data( in, &out );
+
+	if ( status==BIBL_OK ) output( fp, &out );
+
+	if ( p->format_opts & BIBL_FORMAT_VERBOSE )
+		output_verbose( &out, "OUT", refnum );
+
+	fields_free( &out );
+
+	return status;
+}
+
+static void
 isiout_writeheader( FILE *outptr, param *p )
 {
 	if ( p->utf8bom ) utf8_writebom( outptr );
diff --git a/lib/isiout.h b/lib/isiout.h
deleted file mode 100644
index bc1a79d..0000000
--- a/lib/isiout.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * isiout.h
- *
- * Copyright (c) Chris Putnam 2007-2015
- *
- * Source code released under the GPL version 2
- *
- */
-#ifndef ISIOUT_H
-#define ISIOUT_H
-
-#include <stdio.h>
-#include "bibutils.h"
-
-extern void isiout_write( fields *info, FILE *fp, param *p,
-		unsigned long refnum );
-extern void isiout_writeheader( FILE *outptr, param *p );
-
-extern void isiout_initparams( param *p, const char *progname );
-
-#endif
diff --git a/lib/isitypes.c b/lib/isitypes.c
index 2a34a73..c8d546b 100644
--- a/lib/isitypes.c
+++ b/lib/isitypes.c
@@ -1,7 +1,7 @@
 /*
  * isitypes.c
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Program and source code released under the GPL version 2
  *
@@ -24,17 +24,17 @@ static lookups article[] = {
 	{ "C1",     "ADDRESS",   SIMPLE, LEVEL_MAIN }, /* author address */
 	{ "PA",     "ADDRESS",   SIMPLE, LEVEL_HOST }, /* publisher address */
 	{ "RP",     "REPRINTADDRESS", SIMPLE, LEVEL_MAIN },
-	{ "PY",     "PARTYEAR",  SIMPLE, LEVEL_MAIN },
-	{ "PD",     "PARTMONTH", SIMPLE, LEVEL_MAIN },
+	{ "PY",     "PARTDATE:YEAR",  SIMPLE, LEVEL_MAIN },
+	{ "PD",     "PARTDATE:MONTH", SIMPLE, LEVEL_MAIN },
 	{ "VL",     "VOLUME",    SIMPLE, LEVEL_MAIN },
 	{ "AR",     "ARTICLENUMBER", SIMPLE, LEVEL_MAIN }, /* AR=article number that Phys. Rev. B uses instead of page numbers */
-	{ "BP",     "PAGESTART", SIMPLE, LEVEL_MAIN },
-	{ "EP",     "PAGEEND",   SIMPLE, LEVEL_MAIN },
-	{ "PG",     "TOTALPAGES", SIMPLE, LEVEL_MAIN },
+	{ "BP",     "PAGES:START", SIMPLE, LEVEL_MAIN },
+	{ "EP",     "PAGES:STOP",   SIMPLE, LEVEL_MAIN },
+	{ "PG",     "PAGES:TOTAL", SIMPLE, LEVEL_MAIN },
 	{ "IS",     "ISSUE",     SIMPLE, LEVEL_MAIN },
 	{ "SN",     "SERIALNUMBER", SERIALNO, LEVEL_HOST },
 	{ "AB",     "ABSTRACT",  SIMPLE, LEVEL_MAIN },
-	{ "NF",     "NOTES",     SIMPLE, LEVEL_MAIN },
+	{ "NF",     "NOTES",     NOTES,  LEVEL_MAIN },
 	{ "DE",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* author keywords */
 	{ "ID",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* new ISI keywords */
 	{ "LA",     "LANGUAGE",  SIMPLE, LEVEL_MAIN },
@@ -67,16 +67,16 @@ static lookups book[] = {
 	{ "C1",     "ADDRESS",   SIMPLE, LEVEL_MAIN }, /* author address */
 	{ "PA",     "ADDRESS",   SIMPLE, LEVEL_MAIN }, /* publisher address */
 	{ "RP",     "REPRINTADDRESS", SIMPLE, LEVEL_MAIN },
-	{ "PY",     "YEAR",      SIMPLE, LEVEL_MAIN },
-	{ "PD",     "MONTH",     SIMPLE, LEVEL_MAIN },
+	{ "PY",     "DATE:YEAR",      SIMPLE, LEVEL_MAIN },
+	{ "PD",     "DATE:MONTH",     SIMPLE, LEVEL_MAIN },
 	{ "VL",     "VOLUME",    SIMPLE, LEVEL_MAIN },
-	{ "BP",     "PAGESTART", SIMPLE, LEVEL_MAIN },
-	{ "EP",     "PAGEEND",   SIMPLE, LEVEL_MAIN },
-	{ "PG",     "TOTALPAGES", SIMPLE, LEVEL_MAIN },
-	{ "IS",     "ISSUE",     SIMPLE, LEVEL_MAIN },
+	{ "BP",     "PAGES:START", SIMPLE, LEVEL_MAIN },
+	{ "EP",     "PAGES:STOP",  SIMPLE, LEVEL_MAIN },
+	{ "PG",     "PAGES:TOTAL", SIMPLE, LEVEL_MAIN },
+	{ "IS",     "ISSUE",       SIMPLE, LEVEL_MAIN },
 	{ "SN",     "SERIALNUMBER", SERIALNO, LEVEL_HOST },
 	{ "AB",     "ABSTRACT",  SIMPLE, LEVEL_MAIN },
-	{ "NF",     "NOTES",     SIMPLE, LEVEL_MAIN },
+	{ "NF",     "NOTES",     NOTES,  LEVEL_MAIN },
 	{ "DE",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* author keywords */
 	{ "ID",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* new ISI keywords */
 	{ "LA",     "LANGUAGE",  SIMPLE, LEVEL_MAIN },
@@ -108,16 +108,16 @@ static lookups inbook[] = {
 	{ "C1",     "ADDRESS",   SIMPLE, LEVEL_MAIN }, /* author address */
 	{ "PA",     "ADDRESS",   SIMPLE, LEVEL_HOST }, /* publisher address */
 	{ "RP",     "REPRINTADDRESS", SIMPLE, LEVEL_MAIN },
-	{ "PY",     "PARTYEAR",  SIMPLE, LEVEL_MAIN },
-	{ "PD",     "PARTMONTH", SIMPLE, LEVEL_MAIN },
+	{ "PY",     "PARTDATE:YEAR",  SIMPLE, LEVEL_MAIN },
+	{ "PD",     "PARTDATE:MONTH", SIMPLE, LEVEL_MAIN },
 	{ "VL",     "VOLUME",    SIMPLE, LEVEL_MAIN },
-	{ "BP",     "PAGESTART", SIMPLE, LEVEL_MAIN },
-	{ "EP",     "PAGEEND",   SIMPLE, LEVEL_MAIN },
-	{ "PG",     "TOTALPAGES", SIMPLE, LEVEL_HOST },
-	{ "IS",     "ISSUE",     SIMPLE, LEVEL_MAIN },
+	{ "BP",     "PAGES:START", SIMPLE, LEVEL_MAIN },
+	{ "EP",     "PAGES:STOP",  SIMPLE, LEVEL_MAIN },
+	{ "PG",     "PAGES:TOTAL", SIMPLE, LEVEL_HOST },
+	{ "IS",     "ISSUE",       SIMPLE, LEVEL_MAIN },
 	{ "SN",     "SERIALNUMBER", SERIALNO, LEVEL_HOST },
 	{ "AB",     "ABSTRACT",  SIMPLE, LEVEL_MAIN },
-	{ "NF",     "NOTES",     SIMPLE, LEVEL_MAIN },
+	{ "NF",     "NOTES",     NOTES,  LEVEL_MAIN },
 	{ "DE",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* author keywords */
 	{ "ID",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* new ISI keywords */
 	{ "LA",     "LANGUAGE",  SIMPLE, LEVEL_MAIN },
@@ -150,16 +150,16 @@ static lookups bookinseries[] = {
 	{ "C1",     "ADDRESS",   SIMPLE, LEVEL_MAIN }, /* author address */
 	{ "PA",     "ADDRESS",   SIMPLE, LEVEL_HOST }, /* publisher address */
 	{ "RP",     "REPRINTADDRESS", SIMPLE, LEVEL_MAIN },
-	{ "PY",     "PARTYEAR",  SIMPLE, LEVEL_MAIN },
-	{ "PD",     "PARTMONTH", SIMPLE, LEVEL_MAIN },
+	{ "PY",     "PARTDATE:YEAR",  SIMPLE, LEVEL_MAIN },
+	{ "PD",     "PARTDATE:MONTH", SIMPLE, LEVEL_MAIN },
 	{ "VL",     "VOLUME",    SIMPLE, LEVEL_MAIN },
-	{ "BP",     "PAGESTART", SIMPLE, LEVEL_MAIN },
-	{ "EP",     "PAGEEND",   SIMPLE, LEVEL_MAIN },
-	{ "PG",     "TOTALPAGES", SIMPLE, LEVEL_MAIN },
+	{ "BP",     "PAGES:START", SIMPLE, LEVEL_MAIN },
+	{ "EP",     "PAGES:STOP",  SIMPLE, LEVEL_MAIN },
+	{ "PG",     "PAGES:TOTAL", SIMPLE, LEVEL_MAIN },
 	{ "IS",     "ISSUE",     SIMPLE, LEVEL_MAIN },
 	{ "SN",     "SERIALNUMBER", SERIALNO, LEVEL_HOST },
 	{ "AB",     "ABSTRACT",  SIMPLE, LEVEL_MAIN },
-	{ "NF",     "NOTES",     SIMPLE, LEVEL_MAIN },
+	{ "NF",     "NOTES",     NOTES,  LEVEL_MAIN },
 	{ "DE",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* author keywords */
 	{ "ID",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* new ISI keywords */
 	{ "LA",     "LANGUAGE",  SIMPLE, LEVEL_MAIN },
diff --git a/lib/latex.c b/lib/latex.c
index 2c140fd..43fcdc9 100644
--- a/lib/latex.c
+++ b/lib/latex.c
@@ -3,489 +3,493 @@
  *
  * convert between latex special chars and unicode
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Source code released under the GPL version 2
  *
  */
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include "latex.h"
 
+#define LATEX_COMBO (0)  /* 'combo' no need for protection on output */
+#define LATEX_MACRO (1)  /* 'macro_name' to be protected by {\macro_name} on output */
+#define LATEX_MATH  (2)  /* 'math_expression' to be protected by $math_expression$ on output */
+
 struct latex_chars {
-	unsigned int unicode;
-	char *bib1, *bib2, *bib3;
+	unsigned int unicode;      /* unicode code point */
+	unsigned char type;        /* LATEX_COMBO/LATEX_MACRO/LATEX_MATH */
+	char *out;                 /* unadorned latex combination for output */
+	char *variant[3];         /* possible variations on input */
 };
 
 static struct latex_chars latex_chars[] = { 
 
-   {  35, "\\#",     "",   ""        },    /* Number/pound/hash sign */
-   {  36, "\\$",     "",   ""        },    /* Dollar Sign */
-   {  37, "\\%",     "",   ""        },    /* Percent Sign */
-   {  38, "\\&",     "",   ""        },    /* Ampersand */
-   {  92, "{\\backslash}", "\\backslash", ""   }, /* Backslash */
-   { 123, "\\{", "{\\textbraceleft}", "\\textbraceleft" }, /* Left Curly Bracket */
-   { 125, "\\}", "{\\textbraceright}", "\\textbraceright" }, /* Right Curly Bracket */
-   {  95, "\\_",     "", ""        },      /* Underscore alone indicates subscript */
-   { 176, "{\\textdegree}", "\\textdegree", "^\\circ" }, /* Degree sign */
-/* fix sticky spaces in bibtex token cleaning--allows tokens to be parsed properly */
-/*   {  32, "~",       "\\ ", ""        }, */   /* "sticky" space */
-   {  32, "\\ ",     "",   ""           },      /* escaping the space is used to avoid extra space after periods */
-   { 126, "{\\textasciitilde}", "\\textasciitilde", "\\~{}" }, /* Tilde in latex */
-                                 /* This is a cheat, should use "\verb" */
-                                 /* Need same for ^ character */
-
-                                           /* Latin Capital A */
-   { 192, "{\\`A}",  "\\`{A}",  "\\`A"  }, /*               with grave */
-   { 193, "{\\'A}",  "\\'{A}",  "\\'A"  }, /*               with acute */
-   { 194, "{\\^A}",  "\\^{A}",  "\\^A"  }, /*               with circumflex */
-   { 195, "{\\~A}",  "\\~{A}",  "\\~A"  }, /*               with tilde */
-   { 196, "{\\\"A}", "\\\"{A}", "\\\"A" }, /*               with diuresis */
-   { 197, "{\\AA}",  "{\\r{A}}","\\r{A}"}, /*               with ring above */
-   { 256, "{\\={A}}","\\={A}",  "\\=A"  }, /*               with macron */
-   { 258, "{\\u{A}}","\\u{A}",  "\\u A" }, /*               with breve */
-   { 260, "{\\k{A}}","\\k{A}",  "\\k A" }, /*               with ogonek */
-   { 461, "{\\v{A}}","\\v{A}",  "\\v A" }, /*               with caron */
+                                            /* LaTeX special characters */
+   {  32, LATEX_COMBO, " ",              { "\\ ",                NULL,                 NULL               } }, /* escaping the space is used to avoid extra space after periods */
+   {  35, LATEX_MACRO, "#",              { "\\#",                NULL,                 NULL               } }, /* Number/pound/hash sign */
+   {  36, LATEX_MACRO, "$",              { "\\$",                NULL,                 NULL               } }, /* Dollar Sign */
+   {  37, LATEX_MACRO, "%",              { "\\%",                NULL,                 NULL               } }, /* Percent Sign */
+   {  38, LATEX_MACRO, "&",              { "\\&",                NULL,                 NULL               } }, /* Ampersand */
+   {  95, LATEX_MACRO, "_",              { "\\_",                NULL,                 NULL               } }, /* Underscore alone indicates subscript */
+   { 123, LATEX_MACRO, "{",              { "\\{",                "{\\textbraceleft}",  "\\textbraceleft"  } }, /* Left Curly Bracket */
+   { 125, LATEX_MACRO, "}",              { "\\}",                "{\\textbraceright}", "\\textbraceright" } }, /* Right Curly Bracket */
+   {  92, LATEX_MACRO, "backslash",      { "{\\backslash}",      "\\backslash",        NULL               } }, /* Backslash */
+   { 176, LATEX_MACRO, "textdegree",     { "{\\textdegree}",     "\\textdegree",       "^\\circ"          } }, /* Degree sign */
+   { 126, LATEX_MACRO, "textasciitilde", { "{\\textasciitilde}", "\\textasciitilde",   "\\~{}"            } }, /* Tilde in latex */
+/* fix sticky spaces "~" in bibtex token cleaning--allows tokens to be parsed properly */
+
+                                            /* Latin Capital A */
+   { 192, LATEX_MACRO, "`A",   { "{\\`A}",   "\\`{A}",   "\\`A"  } }, /*               with grave */
+   { 193, LATEX_MACRO, "'A",   { "{\\'A}",   "\\'{A}",   "\\'A"  } }, /*               with acute */
+   { 194, LATEX_MACRO, "^A",   { "{\\^A}",   "\\^{A}",   "\\^A"  } }, /*               with circumflex */
+   { 195, LATEX_MACRO, "~A",   { "{\\~A}",   "\\~{A}",   "\\~A"  } }, /*               with tilde */
+   { 196, LATEX_MACRO, "\"A",  { "{\\\"A}",  "\\\"{A}",  "\\\"A" } }, /*               with diuresis */
+   { 197, LATEX_MACRO, "AA",   { "{\\AA}",   "{\\r{A}}", "\\r{A}"} }, /*               with ring above */
+   { 256, LATEX_MACRO, "={A}", { "{\\={A}}", "\\={A}",   "\\=A"  } }, /*               with macron */
+   { 258, LATEX_MACRO, "u{A}", { "{\\u{A}}", "\\u{A}",   "\\u A" } }, /*               with breve */
+   { 260, LATEX_MACRO, "k{A}", { "{\\k{A}}", "\\k{A}",   "\\k A" } }, /*               with ogonek */
+   { 461, LATEX_MACRO, "v{A}", { "{\\v{A}}", "\\v{A}",   "\\v A" } }, /*               with caron */
 
                                            /* Latin Small a */
-   { 224, "{\\`a}",  "\\`{a}",  "\\`a"  }, /*               with grave */
-   { 225, "{\\'a}",  "\\'{a}",  "\\'a"  }, /*               with acute */
-   { 226, "{\\^a}",  "\\^{a}",  "\\^a"  }, /*               with circumflex */
-   { 227, "{\\~a}",  "\\~{a}",  "\\~a"  }, /*               with tilde */
-   { 228, "{\\\"a}", "\\\"{a}", "\\\"a" }, /*               with diuresis */
-   { 229, "{\\aa}",  "{\\r{a}}","\\r{a}"}, /*               with ring above */
-   { 257, "{\\={a}}","\\={a}",  "\\=a"  }, /*               with macron */
-   { 259, "{\\u{a}}","\\u{a}",  "\\u a" }, /*               with breve */
-   { 261, "{\\k{a}}","\\k{a}",  "\\k a" }, /*               with ogonek */
-   { 462, "{\\v{a}}","\\v{a}",  "\\v a" }, /*               with caron */
-
-   { 198, "{\\AE}",  "\\AE",    ""      }, /* Latin Capital AE */
-   { 230, "{\\ae}",  "\\ae",    ""      }, /* Latin Small ae */
+   { 224, LATEX_MACRO, "`a",   { "{\\`a}",   "\\`{a}",   "\\`a"  } }, /*               with grave */
+   { 225, LATEX_MACRO, "'a",   { "{\\'a}",   "\\'{a}",   "\\'a"  } }, /*               with acute */
+   { 226, LATEX_MACRO, "^a",   { "{\\^a}",   "\\^{a}",   "\\^a"  } }, /*               with circumflex */
+   { 227, LATEX_MACRO, "~a",   { "{\\~a}",   "\\~{a}",   "\\~a"  } }, /*               with tilde */
+   { 228, LATEX_MACRO, "\"a",  { "{\\\"a}",  "\\\"{a}",  "\\\"a" } }, /*               with diuresis */
+   { 229, LATEX_MACRO, "aa",   { "{\\aa}",   "{\\r{a}}", "\\r{a}"} }, /*               with ring above */
+   { 257, LATEX_MACRO, "={a}", { "{\\={a}}", "\\={a}",   "\\=a"  } }, /*               with macron */
+   { 259, LATEX_MACRO, "u{a}", { "{\\u{a}}", "\\u{a}",   "\\u a" } }, /*               with breve */
+   { 261, LATEX_MACRO, "k{a}", { "{\\k{a}}", "\\k{a}",   "\\k a" } }, /*               with ogonek */
+   { 462, LATEX_MACRO, "v{a}", { "{\\v{a}}", "\\v{a}",   "\\v a" } }, /*               with caron */
+
+   { 198, LATEX_MACRO, "AE",   { "{\\AE}",   "\\AE",     NULL    } }, /* Latin Capital AE */
+   { 230, LATEX_MACRO, "ae",   { "{\\ae}",   "\\ae",     NULL    } }, /* Latin Small ae */
 
                                            /* Latin Capital C */
-   { 199, "{\\c{C}}","\\c{C}",  "\\c c" }, /*               with cedilla */
-   { 262, "{\\'{C}}","\\'{C}",  "\\'C"  }, /*               with acute */
-   { 264, "{\\^{C}}","\\^{C}",  "\\^C"  }, /*               with circumflex */
-   { 266, "{\\.{C}}","\\.{C}",  "\\.C"  }, /*               with dot above */
-   { 268, "{\\v{C}}","\\v{C}",  "\\v C" }, /*               with caron (hacek) */
+   { 199, LATEX_MACRO, "c{C}", { "{\\c{C}}", "\\c{C}",  "\\c c"  } }, /*               with cedilla */
+   { 262, LATEX_MACRO, "'{C}", { "{\\'{C}}", "\\'{C}",  "\\'C"   } }, /*               with acute */
+   { 264, LATEX_MACRO, "^{C}", { "{\\^{C}}", "\\^{C}",  "\\^C"   } }, /*               with circumflex */
+   { 266, LATEX_MACRO, ".{C}", { "{\\.{C}}", "\\.{C}",  "\\.C"   } }, /*               with dot above */
+   { 268, LATEX_MACRO, "v{C}", { "{\\v{C}}", "\\v{C}",  "\\v C"  } }, /*               with caron (hacek) */
 
                                            /* Latin Small c */
-   { 231, "{\\c{c}}","\\c{c}",  "\\c C" }, /*               with cedilla*/
-   { 263, "{\\'{c}}","\\'{c}",  "\\'c"  }, /*               with acute */
-   { 265, "{\\^{c}}","\\^{c}",  "\\^c"  }, /*               with circumflex */
-   { 267, "{\\.{c}}","\\.{c}",  "\\.c"  }, /*               with dot above */
-   { 269, "{\\v{c}}","\\v{c}",  "\\v c" }, /*               with caron (hacek) */
+   { 231, LATEX_MACRO, "c{c}", { "{\\c{c}}", "\\c{c}",  "\\c C"  } }, /*               with cedilla*/
+   { 263, LATEX_MACRO, "'{c}", { "{\\'{c}}", "\\'{c}",  "\\'c"   } }, /*               with acute */
+   { 265, LATEX_MACRO, "^{c}", { "{\\^{c}}", "\\^{c}",  "\\^c"   } }, /*               with circumflex */
+   { 267, LATEX_MACRO, ".{c}", { "{\\.{c}}", "\\.{c}",  "\\.c"   } }, /*               with dot above */
+   { 269, LATEX_MACRO, "v{c}", { "{\\v{c}}", "\\v{c}",  "\\v c"  } }, /*               with caron (hacek) */
 
                                            /* Latin Capital D */
-   { 270, "{\\v{D}}","\\v{D}",  "\\v D" }, /*               with caron */
-   { 272, "{\\DJ}",  "",        ""      }, /*               with stroke */
+   { 270, LATEX_MACRO, "v{D}", { "{\\v{D}}", "\\v{D}",  "\\v D"  } }, /*               with caron */
+   { 272, LATEX_MACRO, "DJ",   { "{\\DJ}",   NULL,      NULL     } }, /*               with stroke */
 
                                            /* Latin Small d */
-   { 271, "{\\v{d}}","\\v{d}",  "\\v d" }, /*               with caron */
-   { 273, "{\\dj}",  "",        ""      }, /*               with stroke */
+   { 271, LATEX_MACRO, "v{d}", { "{\\v{d}}", "\\v{d}",  "\\v d"  } }, /*               with caron */
+   { 273, LATEX_MACRO, "dj",   { "{\\dj}",   NULL,      NULL     } }, /*               with stroke */
 
                                            /* Latin Capital E */
-   { 200, "{\\`E}",  "\\`{E}",  "\\`E"  }, /*               with grave */
-   { 201, "{\\'E}",  "\\'{E}",  "\\'E"  }, /*               with acute */
-   { 202, "{\\^E}",  "\\^{E}",  "\\^E"  }, /*               with circumflex */
-   { 203, "{\\\"E}", "\\\"{E}", "\\\"E" }, /*               with diuresis */
-   { 274, "{\\={E}}","\\={E}",  "\\=E"  }, /*               with macron */
-   { 276, "{\\u{E}}","\\u{E}",  "\\u E" }, /*               with breve */
-   { 278, "{\\.{E}}","\\.{E}",  "\\.E"  }, /*               with dot above */
-   { 280, "{\\k{E}}","\\k{E}",  "\\k E" }, /*               with ogonek */
-   { 282, "{\\v{E}}","\\v{E}",  "\\v E" }, /*               with caron */
+   { 200, LATEX_MACRO, "`E",   { "{\\`E}",   "\\`{E}",  "\\`E"   } }, /*               with grave */
+   { 201, LATEX_MACRO, "'E",   { "{\\'E}",   "\\'{E}",  "\\'E"   } }, /*               with acute */
+   { 202, LATEX_MACRO, "^E",   { "{\\^E}",   "\\^{E}",  "\\^E"   } }, /*               with circumflex */
+   { 203, LATEX_MACRO, "\"E",  { "{\\\"E}",  "\\\"{E}", "\\\"E"  } }, /*               with diuresis */
+   { 274, LATEX_MACRO, "={E}", { "{\\={E}}", "\\={E}",  "\\=E"   } }, /*               with macron */
+   { 276, LATEX_MACRO, "u{E}", { "{\\u{E}}", "\\u{E}",  "\\u E"  } }, /*               with breve */
+   { 278, LATEX_MACRO, ".{E}", { "{\\.{E}}", "\\.{E}",  "\\.E"   } }, /*               with dot above */
+   { 280, LATEX_MACRO, "k{E}", { "{\\k{E}}", "\\k{E}",  "\\k E"  } }, /*               with ogonek */
+   { 282, LATEX_MACRO, "v{E}", { "{\\v{E}}", "\\v{E}",  "\\v E"  } }, /*               with caron */
  
                                            /* Latin Small e */
-   { 232, "{\\`e}",  "\\`{e}",  "\\`e"  }, /*               with grave */
-   { 233, "{\\'e}",  "\\'{e}",  "\\'e"  }, /*               with acute */
-   { 234, "{\\^e}",  "\\^{e}",  "\\^e"  }, /*               with circumflex */
-   { 235, "{\\\"e}", "\\\"{e}", "\\\"e" }, /*               with diuresis */
-   { 275, "{\\={e}}","\\={e}",  "\\=e"  }, /*               with macron */
-   { 277, "{\\u{e}}","\\u{e}",  "\\u e" }, /*               with breve */
-   { 279, "{\\.{e}}","\\.{e}",  "\\.e"  }, /*               with dot above */
-   { 281, "{\\k{e}}","\\k{e}",  "\\k e" }, /*               with ogonek */
-   { 283, "{\\v{e}}","\\v{e}",  "\\v e" }, /*               with caron */
+   { 232, LATEX_MACRO, "`e",   { "{\\`e}",   "\\`{e}",  "\\`e"   } }, /*               with grave */
+   { 233, LATEX_MACRO, "'e",   { "{\\'e}",   "\\'{e}",  "\\'e"   } }, /*               with acute */
+   { 234, LATEX_MACRO, "^e",   { "{\\^e}",   "\\^{e}",  "\\^e"   } }, /*               with circumflex */
+   { 235, LATEX_MACRO, "\"e",  { "{\\\"e}",  "\\\"{e}", "\\\"e"  } }, /*               with diuresis */
+   { 275, LATEX_MACRO, "={e}", { "{\\={e}}", "\\={e}",  "\\=e"   } }, /*               with macron */
+   { 277, LATEX_MACRO, "u{e}", { "{\\u{e}}", "\\u{e}",  "\\u e"  } }, /*               with breve */
+   { 279, LATEX_MACRO, ".{e}", { "{\\.{e}}", "\\.{e}",  "\\.e"   } }, /*               with dot above */
+   { 281, LATEX_MACRO, "k{e}", { "{\\k{e}}", "\\k{e}",  "\\k e"  } }, /*               with ogonek */
+   { 283, LATEX_MACRO, "v{e}", { "{\\v{e}}", "\\v{e}",  "\\v e"  } }, /*               with caron */
 
                                            /* Latin Capital G */
-   { 284, "{\\^{G}}","\\^{G}",  "\\^G"  }, /*               with circumflex */
-   { 286, "{\\u{G}}","\\u{G}",  "\\u G" }, /*               with breve */
-   { 288, "{\\.{G}}","\\.{G}",  "\\.G"  }, /*               with dot above */
-   { 290, "{\\c{G}}","\\c{G}",  "\\c G" }, /*               with cedilla */
-   { 486, "{\\v{G}}","\\v{G}",  "\\v G" }, /*               with caron */
-   { 500, "{\\'{G}}","\\'{G}",  "\\'G"  }, /*               with acute */
+   { 284, LATEX_MACRO, "^{G}", { "{\\^{G}}", "\\^{G}",  "\\^G"   } }, /*               with circumflex */
+   { 286, LATEX_MACRO, "u{G}", { "{\\u{G}}", "\\u{G}",  "\\u G"  } }, /*               with breve */
+   { 288, LATEX_MACRO, ".{G}", { "{\\.{G}}", "\\.{G}",  "\\.G"   } }, /*               with dot above */
+   { 290, LATEX_MACRO, "c{G}", { "{\\c{G}}", "\\c{G}",  "\\c G"  } }, /*               with cedilla */
+   { 486, LATEX_MACRO, "v{G}", { "{\\v{G}}", "\\v{G}",  "\\v G"  } }, /*               with caron */
+   { 500, LATEX_MACRO, "'{G}", { "{\\'{G}}", "\\'{G}",  "\\'G"   } }, /*               with acute */
 
                                            /* Latin Small g */
-   { 285, "{\\^{g}}","\\^{g}",  "\\^g"  }, /*               with circumflex */
-   { 287, "{\\u{g}}","\\u{g}",  "\\u g" }, /*               with breve */
-   { 289, "{\\.{g}}","\\.{g}",  "\\.g"  }, /*               with dot above */
-   { 291, "{\\c{g}}","\\c{g}",  "\\c g" }, /*               with cedilla */
-   { 487, "{\\v{g}}","\\v{g}",  "\\v g" }, /*               with caron */
-   { 501, "{\\'{g}}","\\'{g}",  "\\'g"  }, /*               with acute */
+   { 285, LATEX_MACRO, "^{g}", { "{\\^{g}}", "\\^{g}",  "\\^g"   } }, /*               with circumflex */
+   { 287, LATEX_MACRO, "u{g}", { "{\\u{g}}", "\\u{g}",  "\\u g"  } }, /*               with breve */
+   { 289, LATEX_MACRO, ".{g}", { "{\\.{g}}", "\\.{g}",  "\\.g"   } }, /*               with dot above */
+   { 291, LATEX_MACRO, "c{g}", { "{\\c{g}}", "\\c{g}",  "\\c g"  } }, /*               with cedilla */
+   { 487, LATEX_MACRO, "v{g}", { "{\\v{g}}", "\\v{g}",  "\\v g"  } }, /*               with caron */
+   { 501, LATEX_MACRO, "'{g}", { "{\\'{g}}", "\\'{g}",  "\\'g"   } }, /*               with acute */
 
                                            /* Latin Capital H */
-   { 292, "{\\^{H}}","\\^{H}",  "\\^H"  }, /*               with circumflex */
-/* { 294, "",        "",        ""      },*//*              with stroke */
+   { 292, LATEX_MACRO, "^{H}", { "{\\^{H}}", "\\^{H}",  "\\^H"   } }, /*               with circumflex */
+/* { 294, LATEX_MACRO, "",     { NULL,       NULL,      NULL     } },*//*              with stroke */
 
                                            /* Latin Capital h */
-   { 293, "{\\^{h}}","\\^{h}",  "\\^h"  }, /*               with circumflex */
-/* { 295, "",        "",        ""      },*//*              with stroke */
+   { 293, LATEX_MACRO, "^{h}", { "{\\^{h}}", "\\^{h}",  "\\^h"   } }, /*               with circumflex */
+/* { 295, LATEX_MACRO, "",     { NULL,       NULL,      NULL     } },*//*              with stroke */
  
                                            /* Latin Capital I */
-   { 204, "{\\`I}",  "\\`{I}",  "\\`I"  }, /*               with grave */
-   { 205, "{\\'I}",  "\\'{I}",  "\\'I"  }, /*               with acute */
-   { 206, "{\\^I}",  "\\^{I}",  "\\^I"  }, /*               with circumflex */
-   { 207, "{\\\"I}", "\\\"{I}", "\\\"I" }, /*               with diuresis */
-   { 296, "{\\~{I}}","\\~{I}",  "\\~I"  }, /*               with tilde */
-   { 298, "{\\={I}}","\\={I}",  "\\=I"  }, /*               with macron */
-   { 300, "{\\u{I}}","\\u{I}",  "\\u I" }, /*               with breve */
-   { 302, "{\\k{I}}","\\k{I}",  "\\k I" }, /*               with ogonek */
-   { 304, "{\\.{I}}","\\.{I}",  "\\. I" }, /*               with dot above */
-   { 463, "{\\v{I}}","\\v{I}",  "\\v I" }, /*               with caron */
+   { 204, LATEX_MACRO, "`I",   { "{\\`I}",   "\\`{I}",  "\\`I"   } }, /*               with grave */
+   { 205, LATEX_MACRO, "'I",   { "{\\'I}",   "\\'{I}",  "\\'I"   } }, /*               with acute */
+   { 206, LATEX_MACRO, "^I",   { "{\\^I}",   "\\^{I}",  "\\^I"   } }, /*               with circumflex */
+   { 207, LATEX_MACRO, "\"I",  { "{\\\"I}",  "\\\"{I}", "\\\"I"  } }, /*               with diuresis */
+   { 296, LATEX_MACRO, "~{I}", { "{\\~{I}}", "\\~{I}",  "\\~I"   } }, /*               with tilde */
+   { 298, LATEX_MACRO, "={I}", { "{\\={I}}", "\\={I}",  "\\=I"   } }, /*               with macron */
+   { 300, LATEX_MACRO, "u{I}", { "{\\u{I}}", "\\u{I}",  "\\u I"  } }, /*               with breve */
+   { 302, LATEX_MACRO, "k{I}", { "{\\k{I}}", "\\k{I}",  "\\k I"  } }, /*               with ogonek */
+   { 304, LATEX_MACRO, ".{I}", { "{\\.{I}}", "\\.{I}",  "\\. I"  } }, /*               with dot above */
+   { 463, LATEX_MACRO, "v{I}", { "{\\v{I}}", "\\v{I}",  "\\v I"  } }, /*               with caron */
 
                                            /* Latin Small i */
-   { 236, "{\\`i}",  "\\`{i}",  "\\`i"  }, /*               with grave */
-   { 237, "{\\'i}",  "\\'{i}",  "\\'i"  }, /*               with acute */
-   { 238, "{\\^i}",  "\\^{i}",  "\\^i"  }, /*               with circumflex */
-   { 239, "{\\\"i}", "\\\"{i}", "\\\"i" }, /*               with diuresis */
-   { 236, "{\\`\\i}",  "\\`{\\i}",  "\\`\\i"  }, /*         with grave */
-   { 237, "{\\'\\i}",  "\\'{\\i}",  "\\'\\i"  }, /*         with acute */
-   { 238, "{\\^\\i}",  "\\^{\\i}",  "\\^\\i"  }, /*         with circumflex */
-   { 239, "{\\\"\\i}", "\\\"{\\i}", "\\\"\\i" }, /*         with diuresis */
-   { 297, "{\\~{\\i}}","\\~{\\i}",  "\\~\\i{}"}, /*         with tilde */
-   { 299, "{\\={\\i}}", "\\={\\i}", "\\=\\i{}"}, /*         with macron */
-   { 301, "{\\u{\\i}}","\\u{\\i}",  "\\u\\i{}"}, /*         with breve */
-   { 303, "{\\k{i}}","\\k{i}",  "\\k i" }, /*               with ogonek */
-                                           /* Latex \i has no dot on "i"*/
-   { 305, "{\\i}",     "\\i{}",     ""        }, /*         without dot above */
-   { 464, "{\\v \\i{}}", "\\v \\i{}", ""      }, /*         with caron */
-
-/*   { 306, "",  "",    ""      },*/ /* Latin Capital IJ */
-/*   { 307, ""  "",    ""       },*/ /* Latin Small ij */
+   { 236, LATEX_MACRO, "`i",   { "{\\`i}",   "\\`{i}",  "\\`i"   } }, /*               with grave */
+   { 237, LATEX_MACRO, "'i",   { "{\\'i}",   "\\'{i}",  "\\'i"   } }, /*               with acute */
+   { 238, LATEX_MACRO, "^i",   { "{\\^i}",   "\\^{i}",  "\\^i"   } }, /*               with circumflex */
+   { 239, LATEX_MACRO, "\"i",  { "{\\\"i}",  "\\\"{i}", "\\\"i"  } }, /*               with diuresis */
+   { 303, LATEX_MACRO, "k{i}", { "{\\k{i}}", "\\k{i}",  "\\k i"  } }, /*               with ogonek */
+                                           /* Latex "\i" has no dot on "i" */
+   { 305, LATEX_MACRO, "i",       { "{\\i}",      "\\i{}",    NULL       } }, /*    without dot above */
+   { 236, LATEX_MACRO, "`{\\i}",  { "{\\`\\i}",   "\\`{\\i}", "\\`\\i"   } }, /*       with grave */
+   { 237, LATEX_MACRO, "'{\\i}",  { "{\\'\\i}",   "\\'{\\i}", "\\'\\i"   } }, /*       with acute */
+   { 238, LATEX_MACRO, "^{\\i}",  { "{\\^\\i}",   "\\^{\\i}", "\\^\\i"   } }, /*       with circumflex */
+   { 239, LATEX_MACRO, "\"{\\i}", { "{\\\"\\i}",  "\\\"{\\i}","\\\"\\i"  } }, /*       with diuresis */
+   { 297, LATEX_MACRO, "`{\\i}",  { "{\\~{\\i}}", "\\~{\\i}", "\\~\\i{}" } }, /*       with tilde */
+   { 299, LATEX_MACRO, "={\\i}",  { "{\\={\\i}}", "\\={\\i}", "\\=\\i{}" } }, /*       with macron */
+   { 301, LATEX_MACRO, "u{\\i}",  { "{\\u{\\i}}", "\\u{\\i}", "\\u\\i{}" } }, /*       with breve */
+   { 464, LATEX_MACRO, "v{\\i}",  { "{\\v \\i{}}", "\\v \\i{}", NULL   } }, /*         with caron */
+
+/* { 306, LATEX_MACRO, "",     { NULL,       NULL,      NULL     } },*/ /* Latin Capital IJ */
+/* { 307, LATEX_MACRO, "",     { NULL,       NULL,      NULL     } },*/ /* Latin Small ij */
 
                                            /* Latin Capital J */
-   { 308, "{\\^{J}}","\\^{J}",  "\\^J"  }, /*                with circumflex */
+   { 308, LATEX_MACRO, "^{J}", { "{\\^{J}}", "\\^{J}",  "\\^J"   } }, /*               with circumflex */
 
                                            /* Latin Small j */
-   { 309, "{\\^{j}}","\\^{j}",  "\\^j"  }, /*                with circumflex */
+   { 309, LATEX_MACRO, "^{j}", { "{\\^{j}}", "\\^{j}",  "\\^j"   } }, /*               with circumflex */
 
                                            /* Latin Capital K */
-   { 310, "{\\c{K}}","\\c{K}",  "\\c K" }, /*               with cedilla */
-   { 488, "{\\v{K}}","\\v{K}",  "\\v K" }, /*               with caron */
+   { 310, LATEX_MACRO, "c{K}", { "{\\c{K}}", "\\c{K}",  "\\c K"  } }, /*               with cedilla */
+   { 488, LATEX_MACRO, "v{K}", { "{\\v{K}}", "\\v{K}",  "\\v K"  } }, /*               with caron */
 
                                            /* Latin Small k */
-   { 311, "{\\c{k}}","\\c{k}",  "\\c k" }, /*               with cedilla */
-   { 489, "{\\v{k}}","\\v{k}",  "\\v k" }, /*               with caron */
+   { 311, LATEX_MACRO, "c{k}", { "{\\c{k}}", "\\c{k}",  "\\c k"  } }, /*               with cedilla */
+   { 489, LATEX_MACRO, "v{k}", { "{\\v{k}}", "\\v{k}",  "\\v k"  } }, /*               with caron */
 
                                            /* Latin Capital L */
-   { 313, "{\\'{L}}","\\'{L}",  "\\'L"  }, /*               with acute */
-   { 315, "{\\c{L}}","\\c{L}",  "\\c L" }, /*               with cedilla */
-   { 317, "{\\v{L}}","\\v{l}",  "\\v L" }, /*               with caron */
-   { 319, "{L\\hspace{-0.35em}$\\cdot$}","L\\hspace{-0.35em}$\\cdot$", "" }, /*               with middle dot */
-   { 321, "{\\L}",   "{\\L{}}", "\\L{}" }, /*               with stroke */
+   { 313, LATEX_MACRO, "'{L}", { "{\\'{L}}", "\\'{L}",  "\\'L"   } }, /*               with acute */
+   { 315, LATEX_MACRO, "c{L}", { "{\\c{L}}", "\\c{L}",  "\\c L"  } }, /*               with cedilla */
+   { 317, LATEX_MACRO, "v{L}", { "{\\v{L}}", "\\v{l}",  "\\v L"  } }, /*               with caron */
+   { 319, LATEX_COMBO, "{L\\hspace{-0.35em}$\\cdot$}", { "{L\\hspace{-0.35em}$\\cdot$}","L\\hspace{-0.35em}$\\cdot$", NULL } }, /*               with middle dot */
+   { 321, LATEX_MACRO, "L",    { "{\\L}",   "{\\L{}}", "\\L{}"   } }, /*               with stroke */
 
                                            /* Latin Small l */
-   { 314, "{\\'{l}}","\\'{l}",  "\\'l"  }, /*               with acute */
-   { 316, "{\\c{l}}","\\c{l}",  "\\c l" }, /*               with cedilla */
-   { 318, "{\\v{l}}","\\v{l}",  "\\v l" }, /*               with caron */
-   { 320, "{l$\\cdot$}","l$\\cdot$", "" }, /*               with middle dot */
-   { 322, "{\\l}",   "{\\l{}}", "\\l{}" }, /*               with stroke */
+   { 314, LATEX_MACRO, "'{l}", { "{\\'{l}}", "\\'{l}",  "\\'l"   } }, /*               with acute */
+   { 316, LATEX_MACRO, "c{l}", { "{\\c{l}}", "\\c{l}",  "\\c l"  } }, /*               with cedilla */
+   { 318, LATEX_MACRO, "v{l}", { "{\\v{l}}", "\\v{l}",  "\\v l"  } }, /*               with caron */
+   { 320, LATEX_COMBO, "{l$\\cdot$}", { "{l$\\cdot$}","l$\\cdot$", NULL } }, /*               with middle dot */
+   { 322, LATEX_MACRO, "l",    { "{\\l}",    "{\\l{}}", "\\l{}"  } }, /*               with stroke */
 
                                            /* Latin Capital N */
-   { 209, "{\\~{N}}","\\~{N}",  "\\~N"  }, /*               with tilde */
-   { 323, "{\\'{N}}","\\'{N}",  "\\'N"  }, /*               with acute */
-   { 325, "{\\c{N}}","\\c{N}",  "\\c N" }, /*               with cedilla */
-   { 327, "{\\v{N}}","\\v{N}",  "\\v N" }, /*               with caron */
+   { 209, LATEX_MACRO, "~{N}", { "{\\~{N}}", "\\~{N}",  "\\~N"   } }, /*               with tilde */
+   { 323, LATEX_MACRO, "'{N}", { "{\\'{N}}", "\\'{N}",  "\\'N"   } }, /*               with acute */
+   { 325, LATEX_MACRO, "c{N}", { "{\\c{N}}", "\\c{N}",  "\\c N"  } }, /*               with cedilla */
+   { 327, LATEX_MACRO, "v{N}", { "{\\v{N}}", "\\v{N}",  "\\v N"  } }, /*               with caron */
 
                                            /* Latin Small n */
-   { 241, "{\\~{n}}","\\~{n}",  "\\~n"  }, /*               with tilde */
-   { 324, "{\\'{n}}","\\'{n}",  "\\'n"  }, /*               with acute */
-   { 326, "{\\c{n}}","\\c{n}",  "\\c N" }, /*               with cedilla */
-   { 328, "{\\v{n}}","\\v{n}",  "\\v n" }, /*               with caron */
-   { 329, "\n",      "",        ""      }, /*               preceeded by apostrophe */
+   { 241, LATEX_MACRO, "~{n}", { "{\\~{n}}", "\\~{n}",  "\\~n"   } }, /*               with tilde */
+   { 324, LATEX_MACRO, "'{n}", { "{\\'{n}}", "\\'{n}",  "\\'n"   } }, /*               with acute */
+   { 326, LATEX_MACRO, "c{n}", { "{\\c{n}}", "\\c{n}",  "\\c N"  } }, /*               with cedilla */
+   { 328, LATEX_MACRO, "v{n}", { "{\\v{n}}", "\\v{n}",  "\\v n"  } }, /*               with caron */
+   { 329, LATEX_MACRO, "n",    { "\\n",      NULL,      NULL     } }, /*               preceeded by apostrophe */
  
                                            /* Latin Capital O */
-   { 210, "{\\`O}",  "\\`{O}",  "\\`O"  }, /*               with grave */
-   { 211, "{\\'O}",  "\\'{O}",  "\\'O"  }, /*               with acute */
-   { 212, "{\\^O}",  "\\^{O}",  "\\^O"  }, /*               with circumflex */
-   { 213, "{\\~O}",  "\\~{O}",  "\\~O"  }, /*               with tilde */
-   { 214, "{\\\"O}", "\\\"{O}", "\\\"O" }, /*               with diaeresis */
-   { 216, "{\\O}",   "\\O",     ""      }, /*               with stroke */
-   { 332, "{\\={O}}", "\\={O}", "\\=O"  }, /*               with macron */
-   { 334, "{\\u{O}}", "\\u{O}", "\\u O" }, /*               with breve */
-   { 336, "{\\H{O}}", "\\H{O}", "\\H O" }, /*               with double acute */
-   { 465, "{\\v{O}}", "\\v{O}", "\\v O" }, /*               with caron */
-   { 490, "{\\k{O}}", "\\k{O}", "\\k O" }, /*               with ogonek */
+   { 210, LATEX_MACRO, "`O",   { "{\\`O}",   "\\`{O}",  "\\`O"   } }, /*               with grave */
+   { 211, LATEX_MACRO, "'O",   { "{\\'O}",   "\\'{O}",  "\\'O"   } }, /*               with acute */
+   { 212, LATEX_MACRO, "^O",   { "{\\^O}",   "\\^{O}",  "\\^O"   } }, /*               with circumflex */
+   { 213, LATEX_MACRO, "~O",   { "{\\~O}",   "\\~{O}",  "\\~O"   } }, /*               with tilde */
+   { 214, LATEX_MACRO, "\"O",  { "{\\\"O}",  "\\\"{O}", "\\\"O"  } }, /*               with diaeresis */
+   { 216, LATEX_MACRO, "O",    { "{\\O}",    "\\O",     NULL     } }, /*               with stroke */
+   { 332, LATEX_MACRO, "={O}", { "{\\={O}}", "\\={O}", "\\=O"    } }, /*               with macron */
+   { 334, LATEX_MACRO, "u{O}", { "{\\u{O}}", "\\u{O}", "\\u O"   } }, /*               with breve */
+   { 336, LATEX_MACRO, "H{O}", { "{\\H{O}}", "\\H{O}", "\\H O"   } }, /*               with double acute */
+   { 465, LATEX_MACRO, "v{O}", { "{\\v{O}}", "\\v{O}", "\\v O"   } }, /*               with caron */
+   { 490, LATEX_MACRO, "k{O}", { "{\\k{O}}", "\\k{O}", "\\k O"   } }, /*               with ogonek */
 
                                            /* Latin Small o */
-   { 242, "{\\`o}",  "\\`{o}",  "\\`o"  }, /*               with grave */
-   { 243, "{\\'o}",  "\\'{o}",  "\\'o"  }, /*               with acute */
-   { 244, "{\\^o}",  "\\^{o}",  "\\^o"  }, /*               with circumflex */
-   { 245, "{\\~o}",  "\\~{o}",  "\\~o"  }, /*               with tilde */
-   { 246, "{\\\"o}", "\\\"{o}", "\\\"o" }, /*               with diaeresis */
-   { 248, "{\\o}",   "\\o",     ""      }, /*               with stroke */
-   { 333, "{\\={o}}", "\\={o}", "\\=o"  }, /*               with macron */
-   { 335, "{\\u{o}}", "\\u{o}", "\\u o" }, /*               with breve */
-   { 337, "{\\H{o}}", "\\H{o}", "\\H o" }, /*               with double acute */
-   { 466, "{\\v{o}}", "\\v{o}", "\\v o" }, /*               with caron */
-   { 491, "{\\k{o}}", "\\k{o}", "\\k o" }, /*               with ogonek */
-
-   { 338, "{\\OE}",  "\\OE",    ""      }, /* Latin Capital OE */
-   { 339, "{\\oe}",  "\\oe",    ""      }, /* Latin Small oe */
+   { 242, LATEX_MACRO, "`o",   { "{\\`o}",   "\\`{o}",  "\\`o"   } }, /*               with grave */
+   { 243, LATEX_MACRO, "'o",   { "{\\'o}",   "\\'{o}",  "\\'o"   } }, /*               with acute */
+   { 244, LATEX_MACRO, "^o",   { "{\\^o}",   "\\^{o}",  "\\^o"   } }, /*               with circumflex */
+   { 245, LATEX_MACRO, "~o",   { "{\\~o}",   "\\~{o}",  "\\~o"   } }, /*               with tilde */
+   { 246, LATEX_MACRO, "\"o",  { "{\\\"o}",  "\\\"{o}", "\\\"o"  } }, /*               with diaeresis */
+   { 248, LATEX_MACRO, "o",    { "{\\o}",    "\\o",     NULL     } }, /*               with stroke */
+   { 333, LATEX_MACRO, "={o}", { "{\\={o}}", "\\={o}", "\\=o"    } }, /*               with macron */
+   { 335, LATEX_MACRO, "u{o}", { "{\\u{o}}", "\\u{o}", "\\u o"   } }, /*               with breve */
+   { 337, LATEX_MACRO, "H{o}", { "{\\H{o}}", "\\H{o}", "\\H o"   } }, /*               with double acute */
+   { 466, LATEX_MACRO, "v{o}", { "{\\v{o}}", "\\v{o}", "\\v o"   } }, /*               with caron */
+   { 491, LATEX_MACRO, "k{o}", { "{\\k{o}}", "\\k{o}", "\\k o"   } }, /*               with ogonek */
+
+   { 338, LATEX_MACRO, "OE",   { "{\\OE}",   "\\OE",   NULL      } }, /* Latin Capital OE */
+   { 339, LATEX_MACRO, "oe",   { "{\\oe}",   "\\oe",   NULL      } }, /* Latin Small oe */
 
                                            /* Latin Capital R */
-   { 340, "{\\'{R}}", "\\'{R}", "\\'R"  }, /*                 with acute */
-   { 342, "{\\c{R}}", "\\c{R}", "\\c R" }, /*                 with cedilla */
-   { 344, "{\\v{R}}", "\\v{R}", "\\v R" }, /*                 with caron */
+   { 340, LATEX_MACRO, "'R",   { "{\\'{R}}", "\\'{R}", "\\'R"    } }, /*               with acute */
+   { 342, LATEX_MACRO, "c{R}", { "{\\c{R}}", "\\c{R}", "\\c R"   } }, /*               with cedilla */
+   { 344, LATEX_MACRO, "v{R}", { "{\\v{R}}", "\\v{R}", "\\v R"   } }, /*               with caron */
  
                                            /* Latin Small r */
-   { 341, "{\\'{r}}", "\\'{r}", "\\'r"  }, /*               with acute */
-   { 343, "{\\c{r}}", "\\c{r}", "\\c r" }, /*               with cedilla */
-   { 345, "{\\v{r}}", "\\v{r}", "\\v r" }, /*               with caron */
+   { 341, LATEX_MACRO, "'r",   { "{\\'{r}}", "\\'{r}", "\\'r"    } }, /*               with acute */
+   { 343, LATEX_MACRO, "c{r}", { "{\\c{r}}", "\\c{r}", "\\c r"   } }, /*               with cedilla */
+   { 345, LATEX_MACRO, "v{r}", { "{\\v{r}}", "\\v{r}", "\\v r"   } }, /*               with caron */
 
                                            /* Latin Capital S */
-   { 346, "{\\'{S}}", "\\'{S}", "\\'S"  }, /*               with acute */
-   { 348, "{\\^{S}}", "\\^{S}", "\\^S"  }, /*               with circumflex */
-   { 350, "{\\c{S}}", "\\c{S}", "\\c S" }, /*               with cedilla */
-   { 352, "{\\v{S}}", "\\v{S}", "\\v S" }, /*               with caron */
+   { 346, LATEX_MACRO, "'{S}", { "{\\'{S}}", "\\'{S}", "\\'S"    } }, /*               with acute */
+   { 348, LATEX_MACRO, "^{S}", { "{\\^{S}}", "\\^{S}", "\\^S"    } }, /*               with circumflex */
+   { 350, LATEX_MACRO, "c{S}", { "{\\c{S}}", "\\c{S}", "\\c S"   } }, /*               with cedilla */
+   { 352, LATEX_MACRO, "v{S}", { "{\\v{S}}", "\\v{S}", "\\v S"   } }, /*               with caron */
 
                                            /* Latin Small s */
-   { 347, "{\\'{s}}","\\'{s}",  "\\'s"  }, /*               with acute */
-   { 349, "{\\^{s}}","\\^{s}",  "\\^s"  }, /*               with circumflex */
-   { 351, "{\\c{s}}","\\c{s}",  "\\c s" }, /*               with cedilla */
-   { 353, "{\\v{s}}","\\v{s}",  "\\v s" }, /*               with caron */
+   { 347, LATEX_MACRO, "'{s}", { "{\\'{s}}", "\\'{s}", "\\'s"    } }, /*               with acute */
+   { 349, LATEX_MACRO, "^{s}", { "{\\^{s}}", "\\^{s}", "\\^s"    } }, /*               with circumflex */
+   { 351, LATEX_MACRO, "c{s}", { "{\\c{s}}", "\\c{s}", "\\c s"   } }, /*               with cedilla */
+   { 353, LATEX_MACRO, "v{s}", { "{\\v{s}}", "\\v{s}", "\\v s"   } }, /*               with caron */
 
                                            /* Latin Capital T */
-   { 354, "{\\c{T}}", "\\c{T}", ""      }, /*               with cedilla */
-   { 356, "{\\v{T}}", "\\v{T}", ""      }, /*               with caron */
-/* { 358, "",         "",       ""      },*//*               with stroke */
+   { 354, LATEX_MACRO, "c{T}", { "{\\c{T}}", "\\c{T}", NULL      } }, /*               with cedilla */
+   { 356, LATEX_MACRO, "v{T}", { "{\\v{T}}", "\\v{T}", NULL      } }, /*               with caron */
+/* { 358, LATEX_MACRO, "",     { NULL,       NULL,     NULL      } },*//*              with stroke */
 
                                            /* Latin Small t */
-   { 355, "{\\c{t}}", "\\c{t}", ""      }, /*               with cedilla */
-   { 357, "{\\v{t}}", "\\v{t}", ""      }, /*               with caron */
-/* { 359, "",         "",       ""      },*//*               with stroke */
+   { 355, LATEX_MACRO, "c{T}", { "{\\c{t}}", "\\c{t}", NULL      } }, /*               with cedilla */
+   { 357, LATEX_MACRO, "v{T}", { "{\\v{t}}", "\\v{t}", NULL      } }, /*               with caron */
+/* { 359, LATEX_MACRO, "",     { NULL,       NULL,     NULL      } },*//*              with stroke */
 
-   { 223, "{\\ss}",  "\\ss",    ""      }, /* German sz ligature, "sharp s" */
+   { 223, LATEX_MACRO, "ss",   { "{\\ss}",   "\\ss",   NULL      } }, /* German sz ligature, "sharp s" */
 
                                            /* Latin Capital U */
-   { 217, "{\\`U}",  "\\`{U}",  "\\`U"  }, /*               with grave */
-   { 218, "{\\'U}",  "\\'{U}",  "\\'U"  }, /*               with acute */
-   { 219, "{\\^U}",  "\\^{U}",  "\\^U"  }, /*               with circumflex */
-   { 220, "{\\\"U}", "\\\"{U}", "\\\"U" }, /*               with diaeresis */
-   { 360, "{\\~{U}}","\\~{U}",  "\\~U"  }, /*               with tilde */
-   { 362, "{\\={U}}","\\={U}",  "\\=U"  }, /*               with macron */
-   { 364, "{\\u{U}}","\\u{U}",  "\\u U" }, /*               with breve */
-   { 366, "{\\r{U}}","\\r{U}",  "\\r U" }, /*               with ring above */
-   { 368, "{\\H{U}}","\\H{U}",  "\\H U" }, /*               with double acute */
-   { 370, "{\\k{U}}","\\k{U}",  "\\k U" }, /*               with ogonek */
-   { 467, "{\\v{U}}","\\v{U}",  "\\v U" }, /*               with caron */
+   { 217, LATEX_MACRO, "`U",   { "{\\`U}",   "\\`{U}", "\\`U"    } }, /*               with grave */
+   { 218, LATEX_MACRO, "'U",   { "{\\'U}",   "\\'{U}", "\\'U"    } }, /*               with acute */
+   { 219, LATEX_MACRO, "^U",   { "{\\^U}",   "\\^{U}", "\\^U"    } }, /*               with circumflex */
+   { 220, LATEX_MACRO, "\"U",  { "{\\\"U}",  "\\\"{U}","\\\"U"   } }, /*               with diaeresis */
+   { 360, LATEX_MACRO, "~{U}", { "{\\~{U}}", "\\~{U}", "\\~U"    } }, /*               with tilde */
+   { 362, LATEX_MACRO, "={U}", { "{\\={U}}", "\\={U}", "\\=U"    } }, /*               with macron */
+   { 364, LATEX_MACRO, "u{U}", { "{\\u{U}}", "\\u{U}", "\\u U"   } }, /*               with breve */
+   { 366, LATEX_MACRO, "r{U}", { "{\\r{U}}", "\\r{U}", "\\r U"   } }, /*               with ring above */
+   { 368, LATEX_MACRO, "H{U}", { "{\\H{U}}", "\\H{U}", "\\H U"   } }, /*               with double acute */
+   { 370, LATEX_MACRO, "k{U}", { "{\\k{U}}", "\\k{U}", "\\k U"   } }, /*               with ogonek */
+   { 467, LATEX_MACRO, "v{U}", { "{\\v{U}}", "\\v{U}", "\\v U"   } }, /*               with caron */
 
                                            /* Latin Small u */
-   { 249, "{\\`u}",  "\\`{u}",  "\\`u"  }, /*               with grave */
-   { 250, "{\\'u}",  "\\'{u}",  "\\'u"  }, /*               with acute */
-   { 251, "{\\^u}",  "\\^{u}",  "\\^u"  }, /*               with circumflex */
-   { 252, "{\\\"u}", "\\\"{u}", "\\\"u" }, /*               with diaeresis */
-   { 361, "{\\~{u}}","\\~{u}",  ""      }, /*               with tilde */
-   { 363, "{\\={u}}","\\={u}",  "\\=u"  }, /*               with macron */
-   { 365, "{\\u{u}}","\\u{u}",  "\\u u" }, /*               with breve */
-   { 367, "{\\r{u}}","\\r{u}",  "\\r u" }, /*               with ring above */
-   { 369, "{\\H{u}}","\\H{u}",  "\\H u" }, /*               with double acute */
-   { 371, "{\\k{u}}","\\k{u}",  "\\k u" }, /*               with ogonek */
-   { 468, "{\\v{u}}","\\v{u}",  "\\v u" }, /*               with caron */
+   { 249, LATEX_MACRO, "`u",   { "{\\`u}",   "\\`{u}", "\\`u"    } }, /*               with grave */
+   { 250, LATEX_MACRO, "'u",   { "{\\'u}",   "\\'{u}", "\\'u"    } }, /*               with acute */
+   { 251, LATEX_MACRO, "^u",   { "{\\^u}",   "\\^{u}", "\\^u"    } }, /*               with circumflex */
+   { 252, LATEX_MACRO, "\"u",  { "{\\\"u}",  "\\\"{u}","\\\"u"   } }, /*               with diaeresis */
+   { 361, LATEX_MACRO, "~{u}", { "{\\~{u}}", "\\~{u}", NULL      } }, /*               with tilde */
+   { 363, LATEX_MACRO, "={u}", { "{\\={u}}", "\\={u}", "\\=u"    } }, /*               with macron */
+   { 365, LATEX_MACRO, "u{u}", { "{\\u{u}}", "\\u{u}", "\\u u"   } }, /*               with breve */
+   { 367, LATEX_MACRO, "r{u}", { "{\\r{u}}", "\\r{u}", "\\r u"   } }, /*               with ring above */
+   { 369, LATEX_MACRO, "H{u}", { "{\\H{u}}", "\\H{u}", "\\H u"   } }, /*               with double acute */
+   { 371, LATEX_MACRO, "k{u}", { "{\\k{u}}", "\\k{u}", "\\k u"   } }, /*               with ogonek */
+   { 468, LATEX_MACRO, "v{u}", { "{\\v{u}}", "\\v{u}", "\\v u"   } }, /*               with caron */
 
                                            /* Latin Capital W */
-   { 372, "{\\^{W}}", "\\^{W}", "\\^W"  }, /*               with circumflex */
+   { 372, LATEX_MACRO, "^{W}", { "{\\^{W}}", "\\^{W}", "\\^W"    } }, /*               with circumflex */
 
                                            /* Latin Small w */
-   { 373, "{\\^{w}}", "\\^{w}", "\\^w"  }, /*               with circumflex */
+   { 373, LATEX_MACRO, "^{w}", { "{\\^{w}}", "\\^{w}", "\\^w"    } }, /*               with circumflex */
 
                                            /* Latin Capital Y */
-   { 221, "{\\'{Y}}","\\'{Y}", "\\'Y"   }, /*               with acute */
-   { 374, "{\\^{Y}}","\\^{Y}", "\\^Y"   }, /*               with circumflex */
-   { 376, "{\\\"{Y}}","\\\"{Y}","\\\"Y" }, /*               with diaeresis */
+   { 221, LATEX_MACRO, "'{Y}", { "{\\'{Y}}", "\\'{Y}", "\\'Y"    } }, /*               with acute */
+   { 374, LATEX_MACRO, "^{Y}", { "{\\^{Y}}", "\\^{Y}", "\\^Y"    } }, /*               with circumflex */
+   { 376, LATEX_MACRO, "\"{Y}",{ "{\\\"{Y}}","\\\"{Y}","\\\"Y"   } }, /*               with diaeresis */
 
                                            /* Latin Small y */
-   { 253, "{\\'y}",  "\\'{y}", "\\'y"   }, /*               with acute */
-   { 255, "{\\\"y}", "\\\"{y}","\\\"y"  }, /*               with diaeresis */
-   { 375, "{\\^{y}}","\\^{y}", "\\^y"   }, /*               with circumflex */
+   { 253, LATEX_MACRO, "'y",   { "{\\'y}",  "\\'{y}", "\\'y"     } }, /*               with acute */
+   { 255, LATEX_MACRO, "\"y",  { "{\\\"y}", "\\\"{y}","\\\"y"    } }, /*               with diaeresis */
+   { 375, LATEX_MACRO, "^{y}", { "{\\^{y}}","\\^{y}", "\\^y"     } }, /*               with circumflex */
 
                                            /* Latin Capital Z */
-   { 377, "{\\'{Z}}","\\'{Z}", "\\'Z"   }, /*               with acute */
-   { 379, "{\\.{Z}}","\\.{Z}", "\\.Z"   }, /*               with dot above */
-   { 381, "{\\v{Z}}","\\v{Z}", "\\v Z"  }, /*               with caron */
+   { 377, LATEX_MACRO, "'{Z}", { "{\\'{Z}}","\\'{Z}", "\\'Z"     } }, /*               with acute */
+   { 379, LATEX_MACRO, ".{Z}", { "{\\.{Z}}","\\.{Z}", "\\.Z"     } }, /*               with dot above */
+   { 381, LATEX_MACRO, "v{Z}", { "{\\v{Z}}","\\v{Z}", "\\v Z"    } }, /*               with caron */
 
                                            /* Latin Small z */
-   { 378, "{\\'{z}}","\\'{z}", "\\'z"   }, /*               with acute */
-   { 380, "{\\.{z}}","\\.{z}", "\\.z"   }, /*               with dot above */
-   { 382, "{\\v{z}}","\\v{z}", "\\v z"  }, /*               with caron */
+   { 378, LATEX_MACRO, "'{z}", { "{\\'{z}}","\\'{z}", "\\'z"     } }, /*               with acute */
+   { 380, LATEX_MACRO, ".{z}", { "{\\.{z}}","\\.{z}", "\\.z"     } }, /*               with dot above */
+   { 382, LATEX_MACRO, "v{z}", { "{\\v{z}}","\\v{z}", "\\v z"    } }, /*               with caron */
 
 
 				/* Needs to be before \nu */
-   { 8203, "$\\null$", "\\null", "" },           /* No space &#x200B; */
-
-   { 913, "$\\Alpha$", "\\Alpha", ""       }, /*GREEKCAPITALLETTERALPHA*/
-   /* 902 = GREEKCAPITALLETTERALPHAWITHTONOS*/
-   { 914, "$\\Beta$",  "\\Beta", ""       }, /*GREEKCAPITALLETTERBETA*/
-   { 915, "$\\Gamma$", "\\Gamma", ""       }, /*GREEKCAPITALLETTERGAMMA*/
-   { 916, "$\\Delta$", "\\Delta", ""       }, /*GREEKCAPITALLETTERDELTA*/
-   { 917, "$\\Epsilon$", "\\Epsilon", ""     }, /*GREEKCAPITALLETTEREPSILON*/
-   /* 904 = GREEKCAPITALLETTEREPSILONWITHTONOS*/
-   { 918, "$\\Zeta$", "\\Zeta", ""        }, /*GREEKCAPITALLETTERZETA*/
-   { 919, "$\\Eta$", "\\Eta", ""         }, /*GREEKCAPITALLETTERETA*/
-   /* 905 = GREEKCAPITALLETTERETAWITHTONOS*/
-   { 920, "$\\Theta$", "\\Theta", ""       }, /*GREEKCAPITALLETTERTHETA*/
-   { 921, "$\\Iota$", "\\Iota", ""        }, /*GREEKCAPITALLETTERIOTA*/
-   /* 938 = GREEKCAPITALLETTERIOTAWITHDIALYTIKA*/
-   /* 906 = GREEKCAPITALLETTERIOTAWITHTONOS*/
-   { 922, "$\\Kappa$", "\\Kappa", ""       }, /*GREEKCAPITALLETTERKAPPA*/
-   { 923, "$\\Lambda$", "\\Lambda", ""      }, /*GREEKCAPITALLETTERLAMDA*/
-   { 924, "$\\Mu$", "\\Mu", ""          }, /*GREEKCAPITALLETTERMU*/
-   { 925, "$\\Nu$", "\\Nu", ""          }, /*GREEKCAPITALLETTERNU*/
-   { 926, "$\\Xi$", "\\Xi", ""          }, /*GREEKCAPITALLETTERXI*/
-   { 927, "$\\Omicron$", "\\Omicron", ""     }, /*GREEKCAPITALLETTEROMICRON*/
-   /* 908 = GREEKCAPITALLETTEROMICRONWITHTONOS*/
-   { 928, "$\\Pi$", "\\Pi", ""          }, /*GREEKCAPITALLETTERPI*/
-   { 929, "$\\Rho$", "\\Rho", ""         }, /*GREEKCAPITALLETTERRHO*/
-   { 931, "$\\Sigma$", "\\Sigma", ""       }, /*GREEKCAPITALLETTERSIGMA*/
-   { 932, "$\\Tau$", "\\Tau", ""         }, /*GREEKCAPITALLETTERTAU*/
-   { 933, "$\\Upsilon$", "\\Upsilon", ""     }, /*GREEKCAPITALLETTERUPSILON*/
-   /* 939 = GREEKCAPITALLETTERUPSILONWITHDIALYTIKA*/
-   /* 910 = GREEKCAPITALLETTERUPSILONWITHTONOS*/
-   { 934, "$\\Phi$", "\\Phi", ""         }, /*GREEKCAPITALLETTERPHI*/
-   { 935, "$\\Chi$", "\\Chi", ""         }, /*GREEKCAPITALLETTERCHI*/
-   { 936, "$\\Psi$", "\\Psi", ""         }, /*GREEKCAPITALLETTERPSI*/
-   { 937, "$\\Omega$", "\\Omega", ""       }, /*GREEKCAPITALLETTEROMEGA*/
-   /* 911, = GREEKCAPITALLETTEROMEGAWITHTONOS*/
-
-   { 945, "$\\alpha$", "\\alpha", ""       }, /*GREEKSMALLLETTERALPHA*/
-   /* 940 = GREEKSMALLLETTERALPHAWITHTONOS*/
-   { 946, "$\\beta$", "\\beta", ""        }, /*GREEKSMALLLETTERBETA*/
-   { 968, "$\\psi$", "\\psi", ""         }, /*GREEKSMALLLETTERPSI*/
-   { 948, "$\\delta$", "\\delta", ""       }, /*GREEKSMALLLETTERDELTA*/
-   { 949, "$\\epsilon$", "\\epsilon", ""     }, /*GREEKSMALLLETTEREPSILON*/
-   /* 941 = GREEKSMALLLETTEREPSILONWITHTONOS*/
-   { 966, "$\\phi$", "\\phi", ""         }, /*GREEKSMALLLETTERPHI*/
-   { 947, "$\\gamma$", "\\gamma", ""       }, /*GREEKSMALLLETTERGAMMA*/
-   { 951, "$\\eta$", "\\eta", ""         }, /*GREEKSMALLLETTERETA*/
-   /* 942 = GREEKSMALLLETTERETAWITHTONOS */
-   { 953, "$\\iota$", "\\iota", ""        }, /*GREEKSMALLLETTERIOTA*/
-   /* 912 = GREEKSMALLLETTERIOTAWITHDIALYTIKAANDTONOS*/
-   /* 943 = GREEKSMALLLETTERIOTAWITHTONOS */
-   /* 970 = GREEKSMALLLETTERIOTAWITHDIALYTIKA */
-   { 958, "$\\xi$", "\\xi", ""          }, /*GREEKSMALLLETTERXI*/
-   { 954, "$\\kappa$", "\\kappa" , ""      }, /*GREEKSMALLLETTERKAPPA*/
-   { 955, "$\\lambda$", "\\lambda", ""      }, /*GREEKSMALLLETTERLAMDA*/
-   { 956, "$\\mu$", "\\mu", ""          }, /*GREEKSMALLLETTERMU*/
-   { 957, "$\\nu$", "\\nu", ""          }, /*GREEKSMALLLETTERNU*/
-   { 959, "$\\omicron$", "\\omicron", ""     }, /*GREEKSMALLLETTEROMICRON*/
-   /* 972 = GREEKSMALLLETTEROMICRONWITHTONOS*/
-   { 960, "$\\pi$", "\\pi", ""          }, /*GREEKSMALLLETTERPI*/
-   { 961, "$\\rho$", "\\rho", ""         }, /*GREEKSMALLLETTERRHO*/
-   { 963, "$\\sigma$", "\\sigma", ""       }, /*GREEKSMALLLETTERSIGMA*/
-   { 964, "$\\tau$", "\\tau", ""         }, /*GREEKSMALLLETTERTAU*/
-   { 952, "$\\theta$", "\\theta", ""       }, /*GREEKSMALLLETTERTHETA*/
-   { 969, "$\\omega$", "\\omega", ""       }, /*GREEKSMALLLETTEROMEGA*/
-   /* 974 = GREEKSMALLLETTEROMEGAWITHTONOS*/
-   { 967, "$\\chi$", "\\chi", ""         }, /*GREEKSMALLLETTERCHI*/
-   { 965, "$\\upsilon$", "\\upsilon", ""     }, /*GREEKSMALLLETTERUPSILON*/
-   /* 973 = GREEKSMALLLETTERUPSILONWITHTONOS*/
-   /* 971 = GREEKSMALLLETTERUPSILONWITHDIALYTIKA*/
-   /* 944 = GREEKSMALLLETTERUPSILONWITHDIALYTIKAANDTONOS*/
-   { 950, "$\\zeta$", "\\zeta", ""        },  /*GREEKSMALLLETTERZETA*/
-
-   { 181, "{\\textmu}", "\\textmu", "$\\mu$" }, /* 181=micro sign, techically &#xB5; */
+   { 8203,LATEX_MATH, "null",  { "$\\null$", "\\null", NULL      } }, /* No space &#x200B; */
+
+   { 913, LATEX_MATH, "Alpha",   { "$\\Alpha$",   "\\Alpha",    NULL    } }, /*GREEK CAPITAL LETTERALPHA*/
+   { 914, LATEX_MATH, "Beta",    { "$\\Beta$",    "\\Beta",     NULL    } }, /*GREEK CAPITAL LETTERBETA*/
+   { 915, LATEX_MATH, "Gamma",   { "$\\Gamma$",   "\\Gamma",    NULL    } }, /*GREEK CAPITAL LETTERGAMMA*/
+   { 916, LATEX_MATH, "Delta",   { "$\\Delta$",   "\\Delta",    NULL    } }, /*GREEK CAPITAL LETTERDELTA*/
+   { 917, LATEX_MATH, "Epsilon", { "$\\Epsilon$", "\\Epsilon",  NULL    } }, /*GREEK CAPITAL LETTEREPSILON*/
+   { 918, LATEX_MATH, "Zeta",    { "$\\Zeta$",     "\\Zeta",    NULL    } }, /*GREEK CAPITAL LETTERZETA*/
+   { 919, LATEX_MATH, "Eta",     { "$\\Eta$",      "\\Eta",     NULL    } }, /*GREEK CAPITAL LETTERETA*/
+   { 920, LATEX_MATH, "Theta",   { "$\\Theta$",    "\\Theta",   NULL    } }, /*GREEK CAPITAL LETTERTHETA*/
+   { 921, LATEX_MATH, "Iota",    { "$\\Iota$",     "\\Iota",    NULL    } }, /*GREEK CAPITAL LETTERIOTA*/
+   { 922, LATEX_MATH, "Kappa",   { "$\\Kappa$",    "\\Kappa",   NULL    } }, /*GREEK CAPITAL LETTERKAPPA*/
+   { 923, LATEX_MATH, "Lambda",  { "$\\Lambda$",   "\\Lambda",  NULL    } }, /*GREEK CAPITAL LETTERLAMDA*/
+   { 924, LATEX_MATH, "Mu",      { "$\\Mu$",       "\\Mu",      NULL    } }, /*GREEK CAPITAL LETTERMU*/
+   { 925, LATEX_MATH, "Nu",      { "$\\Nu$",       "\\Nu",      NULL    } }, /*GREEK CAPITAL LETTERNU*/
+   { 926, LATEX_MATH, "Xi",      { "$\\Xi$",       "\\Xi",      NULL    } }, /*GREEK CAPITAL LETTERXI*/
+   { 927, LATEX_MATH, "Omicron", { "$\\Omicron$",  "\\Omicron", NULL    } }, /*GREEK CAPITAL LETTEROMICRON*/
+   { 928, LATEX_MATH, "Pi",      { "$\\Pi$",       "\\Pi",      NULL    } }, /*GREEK CAPITAL LETTERPI*/
+   { 929, LATEX_MATH, "Rho",     { "$\\Rho$",      "\\Rho",     NULL    } }, /*GREEK CAPITAL LETTERRHO*/
+   { 931, LATEX_MATH, "Sigma",   { "$\\Sigma$",    "\\Sigma",   NULL    } }, /*GREEK CAPITAL LETTERSIGMA*/
+   { 932, LATEX_MATH, "Tau",     { "$\\Tau$",      "\\Tau",     NULL    } }, /*GREEK CAPITAL LETTERTAU*/
+   { 933, LATEX_MATH, "Upsilon", { "$\\Upsilon$",  "\\Upsilon", NULL    } }, /*GREEK CAPITAL LETTERUPSILON*/
+   { 934, LATEX_MATH, "Phi",     { "$\\Phi$",      "\\Phi",     NULL    } }, /*GREEK CAPITAL LETTERPHI*/
+   { 935, LATEX_MATH, "Chi",     { "$\\Chi$",      "\\Chi",     NULL    } }, /*GREEK CAPITAL LETTERCHI*/
+   { 936, LATEX_MATH, "Psi",     { "$\\Psi$",      "\\Psi",     NULL    } }, /*GREEK CAPITAL LETTERPSI*/
+   { 937, LATEX_MATH, "Omega",   { "$\\Omega$",    "\\Omega",   NULL    } }, /*GREEK CAPITAL LETTEROMEGA*/
+   /* 902 = GREEK CAPITAL LETTER ALPHAWITHTONOS*/
+   /* 904 = GREEK CAPITAL LETTER EPSILONWITHTONOS*/
+   /* 905 = GREEK CAPITAL LETTER ETAWITHTONOS*/
+   /* 938 = GREEK CAPITAL LETTER IOTAWITHDIALYTIKA*/
+   /* 906 = GREEK CAPITAL LETTER IOTAWITHTONOS*/
+   /* 908 = GREEK CAPITAL LETTER OMICRONWITHTONOS*/
+   /* 939 = GREEK CAPITAL LETTER UPSILONWITHDIALYTIKA*/
+   /* 910 = GREEK CAPITAL LETTER UPSILONWITHTONOS*/
+   /* 911, = GREEK CAPITAL LETTER OMEGAWITHTONOS*/
+
+   { 945, LATEX_MATH, "alpha",   { "$\\alpha$",    "\\alpha",   NULL    } }, /*GREEK SMALL LETTER ALPHA*/
+   { 946, LATEX_MATH, "beta",    { "$\\beta$",     "\\beta",    NULL    } }, /*GREEK SMALL LETTER BETA*/
+   { 968, LATEX_MATH, "psi",     { "$\\psi$",      "\\psi",     NULL    } }, /*GREEK SMALL LETTER PSI*/
+   { 948, LATEX_MATH, "delta",   { "$\\delta$",    "\\delta",   NULL    } }, /*GREEK SMALL LETTER DELTA*/
+   { 949, LATEX_MATH, "epsilon", { "$\\epsilon$",  "\\epsilon", NULL    } }, /*GREEK SMALL LETTER EPSILON*/
+   { 966, LATEX_MATH, "phi",     { "$\\phi$",      "\\phi",     NULL    } }, /*GREEK SMALL LETTER PHI*/
+   { 947, LATEX_MATH, "gamma",   { "$\\gamma$", "\\gamma", NULL }   }, /*GREEK SMALL LETTER GAMMA*/
+   { 951, LATEX_MATH, "eta",     { "$\\eta$", "\\eta", NULL }     }, /*GREEK SMALL LETTER ETA*/
+   { 953, LATEX_MATH, "iota",    { "$\\iota$", "\\iota", NULL }    }, /*GREEK SMALL LETTER IOTA*/
+   { 958, LATEX_MATH, "xi",      { "$\\xi$", "\\xi", NULL }      }, /*GREEK SMALL LETTER XI*/
+   { 954, LATEX_MATH, "kappa",   { "$\\kappa$", "\\kappa" , NULL }  }, /*GREEK SMALL LETTER KAPPA*/
+   { 955, LATEX_MATH, "lambda",  { "$\\lambda$", "\\lambda", NULL }  }, /*GREEK SMALL LETTER LAMDA*/
+   { 956, LATEX_MATH, "mu",      { "$\\mu$", "\\mu", NULL }      }, /*GREEK SMALL LETTER MU*/
+   { 957, LATEX_MATH, "nu",      { "$\\nu$", "\\nu", NULL }      }, /*GREEK SMALL LETTER NU*/
+   { 959, LATEX_MATH, "omicron", { "$\\omicron$", "\\omicron", NULL  }    }, /*GREEK SMALL LETTER OMICRON*/
+   { 960, LATEX_MATH, "pi",      { "$\\pi$", "\\pi", NULL }      }, /*GREEK SMALL LETTER PI*/
+   { 961, LATEX_MATH, "rho",     { "$\\rho$", "\\rho", NULL }     }, /*GREEK SMALL LETTER RHO*/
+   { 963, LATEX_MATH, "sigma",   { "$\\sigma$", "\\sigma", NULL }   }, /*GREEK SMALL LETTER SIGMA*/
+   { 964, LATEX_MATH, "tau",     { "$\\tau$", "\\tau", NULL }     }, /*GREEK SMALL LETTER TAU*/
+   { 952, LATEX_MATH, "theta",   { "$\\theta$", "\\theta", NULL }   }, /*GREEK SMALL LETTER THETA*/
+   { 969, LATEX_MATH, "omega",   { "$\\omega$", "\\omega", NULL }   }, /*GREEK SMALL LETTER OMEGA*/
+   { 967, LATEX_MATH, "chi",     { "$\\chi$", "\\chi", NULL }     }, /*GREEK SMALL LETTER CHI*/
+   { 965, LATEX_MATH, "upsilon", { "$\\upsilon$", "\\upsilon", NULL } }, /*GREEK SMALL LETTER UPSILON*/
+   { 950, LATEX_MATH, "zeta",    { "$\\zeta$", "\\zeta", NULL }    },  /*GREEK SMALL LETTER ZETA*/
+   /* 940 = GREEK SMALL LETTER ALPHAWITHTONOS*/
+   /* 941 = GREEK SMALL LETTER EPSILONWITHTONOS*/
+   /* 942 = GREEK SMALL LETTER ETAWITHTONOS */
+   /* 912 = GREEK SMALL LETTER IOTAWITHDIALYTIKAANDTONOS*/
+   /* 943 = GREEK SMALL LETTER IOTAWITHTONOS */
+   /* 970 = GREEK SMALL LETTER IOTAWITHDIALYTIKA */
+   /* 972 = GREEK SMALL LETTER OMICRONWITHTONOS*/
+   /* 974 = GREEK SMALL LETTER OMEGAWITHTONOS*/
+   /* 973 = GREEK SMALL LETTER UPSILONWITHTONOS*/
+   /* 971 = GREEK SMALL LETTER UPSILONWITHDIALYTIKA*/
+   /* 944 = GREEK SMALL LETTER UPSILONWITHDIALYTIKAANDTONOS*/
+
+   { 181, LATEX_MACRO, "textmu", { "{\\textmu}", "\\textmu", "$\\mu$" } }, /* 181=micro sign, techically &#xB5; */
 
 /* Make sure that these don't stomp on other latex things above */
 
-   { 8242, "{\\textasciiacutex}", "\\textasciiacutex", "$'$" },  /* Prime symbol &#x2032; */
-   { 180, "{\\textasciiacute}", "\\textasciiacute", "\\'" }, /* acute accent &#xB4; */
-/*   { 769,  "\\'",    "", "" },*/  /* Acute accent &#x0301;--apply to next char */
-
-   { 8243, "{\\textacutedbl}", "\\textacutedbl", "$''$" },  /* Double prime &#x2033; */
-   { 8245, "{\\textasciigrave}", "\\textasciigrave", "\\`" }, /* Grave accent &#x2035; */
-/*   { 768,  "\\`",    "", "" },*/  /* Grave accent &#x0300;--apply to next char */
-
-   { 8963, "{\\textasciicircum}", "\\textasciicircum", ""} , /* &#x2303; */
-   { 184,  "{\\textasciicedilla}", "\\textasciicedilla", "" },  /* cedilla &#xB8; */
-   { 168,  "{\\textasciidieresis}", "\\textasciidieresis", "" }, /* dieresis &#xA8; */
-   { 175,  "{\\textasciimacron}", "\\textasciimacron", "" }, /* macron &#xAF; */
-
-   { 8593, "{\\textuparrow}", "\\textuparrow", "" },    /* Up arrow &#x2191; */
-   { 8595, "{\\textdownarrow}", "\\textdownarrow", "" },  /* Down arrow &#x2193; */
-   { 8594, "{\\textrightarrow}", "\\textrightarrow", "" }, /* Right arrow &#x2192; */
-   { 8592, "{\\textleftarrow}", "\\textleftarrow", "" },  /* Left arrow &#x2190; */
-   { 12296, "{\\textlangle}", "\\textlangle", "" } ,   /* L-angle &#x3008; */
-   { 12297, "{\\textrangle}", "\\textrangle", "" } ,   /* L-angle &#x3009; */
-
-   { 166, "{\\textbrokenbar}", "\\textbrokenbar", "" }, /* Broken vertical bar &#xA6; */
-   { 167, "{\\textsection}", "\\textsection", "\\S{}" },   /* Section sign, &#xA7; */
-   { 170, "{\\textordfeminine}", "\\textordfeminine", "$^a$" }, /* &#xAA; */
-   { 172, "{\\textlnot}", "\\textlnot", "" },      /* Lnot &#xAC; */
-   { 182, "{\\textparagraph}", "\\textparagraph", "" }, /* Paragraph sign &#xB6; */
-   { 183, "{\\textperiodcentered}", "\\textperiodcentered", "" }, /* Period-centered &#xB7; */
-   { 186, "{\\textordmasculine}", "\\textordmasculine", "" }, /* &#xBA; */
-   { 8214, "{\\textbardbl}", "\\textbardbl", "" },   /* Double vertical bar &#x2016; */
-   { 8224, "{\\textdagger}", "\\textdagger", "" },   /* Dagger &#x2020; */
-   { 8225, "{\\textdaggerdbl}", "\\textdaggerdbl", "" },/* Double dagger &x2021; */
-   { 8226, "{\\textbullet}", "\\textbullet", "" },   /* Bullet &#x2022; */
-   { 8494, "{\\textestimated}", "\\textestimated", "" },/* Estimated &#x212E; */
-   { 9526, "{\\textopenbullet}", "\\textopenbullet", "" },/* &#x2536; */
-
-   { 8220, "``", "{\\textquotedblleft}", "\\textquotedblleft" }, /* Opening double quote &#x201C; */
-   { 8221, "''", "{\\textquotedblright}","\\textquotedblright" }, /* Closing double quote &#x201D; */
-   { 8216, "`",  "{\\textquoteleft}", "\\textquoteleft" },    /* Opening single quote &#x2018; */
-   { 8217, "'",  "{\\textquoteright}", "\\textquoteright" },   /* Closing single quote &#x2019; */
-   { 8261, "{\\textlquill}", "\\textlquill", "" },         /* Left quill &#x2045; */
-   { 8262, "{\\textrquill}", "\\textrquill", "" },         /* Right quill &#x2046; */
-
-   { 8212, "---",     "{\\textemdash}", "\\textemdash" },     /* Em-dash &#x2014; */
-   { 8211, "--",      "{\\textendash}", "\\textendash" },     /* En-dash &#x2013; */
-   { 8230, "\\ldots", "{\\textellipsis}", "\\textellipsis" },   /* Ellipsis &#x2026; */
-
-   { 8194, "\\enspace", "\\hspace{.5em}", "" }, /* En-space &#x2002; */
-   { 8195, "\\emspace", "\\hspace{1em}",  "" }, /* Em-space &#x2003; */
-   { 8201, "\\thinspace", "", ""},              /* Thin space &#x2009; */
-   { 8203, "{\\textnospace}", "\\textnospace", "" },           /* No space &#x200B; */
-   { 9251, "{\\textvisiblespace}", "\\textvisiblespace", "" },      /* Visible space &#x2423; */
-
-   { 215, "{\\texttimes}", "\\texttimes", "" }, /* Multiplication symbol &#xD7; */
-   { 247, "{\\textdiv}", "\\textdiv", "" },   /* Division symbol &#xF7; */
-   { 177, "{\\textpm}", "\\textpm", "" }, /* Plus-minus character &#B1; */
-   { 189, "{\\textonehalf}", "\\textonehalf", "" }, /* Vulgar fraction one half &#xBD; */
-   { 188, "{\\textonequarter}", "\\textonequarter", "" }, /* Vulgar fraction one quarter &#xBD; */
-   { 190, "{\\textthreequarters}", "\\textthreequarters", "" }, /* Vulgar fraction three quarters &#xBE; */
-   { 8240, "{\\texttenthousand}", "\\texttenthousand", "" }, /* Per thousand sign &#x2030; */
-   { 8241, "{\\textpertenthousand}", "\\textpertenthousand", "" }, /* Per ten thousand sign &#x2031;*/
-   { 8260, "{\\textfractionsolidus}", "\\textfractionsolidus", "" }, /* &x8260; */
-   { 8451, "{\\textcelcius}", "\\textcelcius", "" }, /* Celcicus &#x2103; */
-   { 8470, "{\\textnumero}", "\\textnumero", "" },  /* Numero symbol &#x2116; */
-   { 8486, "{\\textohm}", "\\textohm", "" }, /* Ohm symbol &#x2126; */
-   { 8487, "{\\textmho}", "\\textmho", "" }, /* Mho symbol &#x2127; */
-   { 8730, "{\\textsurd}", "\\textsurd", "" }, /* &#x221A; */
-
-   { 185, "{\\textonesuperior}", "\\textonesuperior", "" },   /*Superscript 1 &#xB9; */
-   { 178, "{\\texttwosuperior}", "\\texttwosuperior", "" },   /*Superscript 2 &#xB2; */
-   { 179, "{\\textthreesuperior}", "\\textthreesuperior", "" }, /*Superscript 3 &#xB3; */
-
-   { 161, "{\\textexclamdown}", "\\textexclamdown", "" },   /* Inverted exclamation mark &#xA1;*/
-   { 191, "{\\textquestiondown}", "\\textquestiondown", "" }, /* Inverted question mark &#xBF; */
-
-   { 162, "{\\textcent}", "\\textcent", "" },         /* Cent sign &#xA2; */
-   { 163, "{\\textsterling}", "\\textsterling", "\\pounds" },     /* Pound sign &#xA3; */
-   { 165, "{\\textyen}", "\\textyen", "" },          /* Yen sign &#xA5; */
-   { 402, "{\\textflorin}", "\\textflorin", "" },       /* Florin sign &#x192; */
-   { 3647, "{\\textbaht}", "\\textbaht", "" },        /* Thai currency &#xE3F; */
-   { 8355, "{\\textfrenchfranc}", "\\textfrenchfranc", "" }, /* French franc &#x20A3; */
-   { 8356, "{\\textlira}", "\\textlira", "" },        /* Lira &#x20A4; */
-   { 8358, "{\\textnaira}", "\\textnaria", "" },       /* Naira &#x20A6; */
-   { 8361, "{\\textwon}", "\\textwon", "" },         /* &#x20A9; */
-   { 8363, "{\\textdong}", "\\textdong", "" },        /* Vietnamese currency &#x20AB; */
-   { 8364, "{\\texteuro}", "\\texteuro", "" },        /* Euro sign */
-
-   { 169, "{\\textcopyright}", "\\textcopyright", "" },           /* Copyright (C) &#xA9; */
-   { 175, "{\\textregistered}", "\\textregistered", "" },          /* Registered sign (R) &#xAF;*/
-   { 8482, "{\\texttrademark}", "\\texttrademark", "$^{TM}$" },   /* Trademark (TM) &#x2122; */
-   { 8480, "{\\textservicemark}", "\\textservicemark", "$^{SM}$" }, /* Servicemark (SM) &#x2120;*/
-   { 8471, "{\\textcircledP}", "\\textcircledP", "" },           /* Circled P ࡅ */
+   { 8242, LATEX_MACRO, "textasciiacutex",   { "{\\textasciiacutex}",   "\\textasciiacutex",     "$'$"                 } }, /* Prime symbol &#x2032; */
+   { 180,  LATEX_MACRO, "textasciiacute",    { "{\\textasciiacute}",    "\\textasciiacute",      "\\'"                 } }, /* acute accent &#xB4; */
+   { 8243, LATEX_MACRO, "textacutedbl",      { "{\\textacutedbl}",      "\\textacutedbl",        "$''$"                } }, /* Double prime &#x2033; */
+   { 8245, LATEX_MACRO, "textasciigrave",    { "{\\textasciigrave}",    "\\textasciigrave",      "\\`"                 } }, /* Grave accent &#x2035; */
+/* { 768,  LATEX_MACRO, "`",                 { "\\`",                   NULL,                    NULL                  } },*//* Grave accent &#x0300;--apply to next char */
+/* { 769,  LATEX_MACRO, "'",                 { "\\'",                   NULL,                    NULL                  } },*//* Acute accent &#x0301;--apply to next char */
+
+   { 8963, LATEX_MACRO, "textasciicircum",   { "{\\textasciicircum}",   "\\textasciicircum",     NULL                  } }, /* &#x2303; */
+   { 184,  LATEX_MACRO, "textasciicedilla",  { "{\\textasciicedilla}",  "\\textasciicedilla",    NULL                  } }, /* cedilla &#xB8; */
+   { 168,  LATEX_MACRO, "textasciidieresis", { "{\\textasciidieresis}", "\\textasciidieresis",   NULL                  } }, /* dieresis &#xA8; */
+   { 175,  LATEX_MACRO, "textasciimacron",   { "{\\textasciimacron}",   "\\textasciimacron",     NULL                  } }, /* macron &#xAF; */
+
+   { 8593, LATEX_MACRO, "textuparrow",       { "{\\textuparrow}",       "\\textuparrow",         NULL                  } }, /* Up arrow &#x2191; */
+   { 8595, LATEX_MACRO, "textdownarrow",     { "{\\textdownarrow}",     "\\textdownarrow",       NULL                  } }, /* Down arrow &#x2193; */
+   { 8594, LATEX_MACRO, "textrightarrow",    { "{\\textrightarrow}",    "\\textrightarrow",      NULL                  } }, /* Right arrow &#x2192; */
+   { 8592, LATEX_MACRO, "textleftarrow",     { "{\\textleftarrow}",     "\\textleftarrow",       NULL                  } }, /* Left arrow &#x2190; */
+   { 12296,LATEX_MACRO, "textlangle",        { "{\\textlangle}",        "\\textlangle",          NULL                  } }, /* L-angle &#x3008; */
+   { 12297,LATEX_MACRO, "textrangle",        { "{\\textrangle}",        "\\textrangle",          NULL                  } }, /* L-angle &#x3009; */
+
+   { 166,  LATEX_MACRO, "textbrokenbar",     { "{\\textbrokenbar}",     "\\textbrokenbar",       NULL                  } }, /* Broken vertical bar &#xA6; */
+   { 167,  LATEX_MACRO, "textsection",       { "{\\textsection}",       "\\textsection",         "\\S{}"               } }, /* Section sign, &#xA7; */
+   { 170,  LATEX_MACRO, "textordfeminine",   { "{\\textordfeminine}",   "\\textordfeminine",     "$^a$"                } }, /* &#xAA; */
+   { 172,  LATEX_MACRO, "textlnot",          { "{\\textlnot}",          "\\textlnot",            NULL                  } }, /* Lnot &#xAC; */
+   { 182,  LATEX_MACRO, "textparagraph",     { "{\\textparagraph}",     "\\textparagraph",       NULL                  } }, /* Paragraph sign &#xB6; */
+   { 183,  LATEX_MACRO, "textperiodcentered",{ "{\\textperiodcentered}","\\textperiodcentered",  NULL                  } }, /* Period-centered &#xB7; */
+   { 186,  LATEX_MACRO, "textordmasculine",  { "{\\textordmasculine}",  "\\textordmasculine",    NULL                  } }, /* &#xBA; */
+   { 8214, LATEX_MACRO, "textbardbl",        { "{\\textbardbl}",        "\\textbardbl",          NULL                  } }, /* Double vertical bar &#x2016; */
+   { 8224, LATEX_MACRO, "textdagger",        { "{\\textdagger}",        "\\textdagger",          NULL                  } }, /* Dagger &#x2020; */
+   { 8225, LATEX_MACRO, "textdaggerdbl",     { "{\\textdaggerdbl}",     "\\textdaggerdbl",       NULL                  } }, /* Double dagger &x2021; */
+   { 8226, LATEX_MACRO, "textbullet",        { "{\\textbullet}",        "\\textbullet",          NULL                  } }, /* Bullet &#x2022; */
+   { 8494, LATEX_MACRO, "textestimated",     { "{\\textestimated}",     "\\textestimated",       NULL                  } }, /* Estimated &#x212E; */
+   { 9526, LATEX_MACRO, "textopenbullet",    { "{\\textopenbullet}",    "\\textopenbullet",      NULL                  } }, /* &#x2536; */
+
+   { 8220, LATEX_COMBO, "``",                { "``",                    "{\\textquotedblleft}",  "\\textquotedblleft"  } }, /* Opening double quote &#x201C; */
+   { 8221, LATEX_COMBO, "''",                { "''",                    "{\\textquotedblright}", "\\textquotedblright" } }, /* Closing double quote &#x201D; */
+   { 8216, LATEX_COMBO, "`",                 { "`",                     "{\\textquoteleft}",     "\\textquoteleft"     } }, /* Opening single quote &#x2018; */
+   { 8217, LATEX_COMBO, "'",                 { "'",                     "{\\textquoteright}",    "\\textquoteright"    } }, /* Closing single quote &#x2019; */
+   { 8261, LATEX_MACRO, "textlquill",        { "{\\textlquill}",        "\\textlquill",          NULL                  } }, /* Left quill &#x2045; */
+   { 8262, LATEX_MACRO, "textrquill",        { "{\\textrquill}",        "\\textrquill",          NULL                  } }, /* Right quill &#x2046; */
+
+   { 8212, LATEX_COMBO, "---",               { "---",                   "{\\textemdash}",        "\\textemdash"        } }, /* Em-dash &#x2014; */
+   { 8211, LATEX_COMBO, "--",                { "--",                    "{\\textendash}",        "\\textendash"        } }, /* En-dash &#x2013; */
+   { 8230, LATEX_MACRO, "ldots",             { "{\\ldots}",             "{\\textellipsis}",      "\\textellipsis"      } }, /* Ellipsis &#x2026; */
+
+   { 8194, LATEX_MACRO, "enspace",           { "{\\enspace}",           "\\hspace{.5em}",        NULL                  } }, /* En-space &#x2002; */
+   { 8195, LATEX_MACRO, "emspace",           { "{\\emspace}",           "\\hspace{1em}",         NULL                  } }, /* Em-space &#x2003; */
+   { 8201, LATEX_MACRO, "thinspace",         { "{\\thinspace}",         NULL,                    NULL                  } }, /* Thin space &#x2009; */
+   { 8203, LATEX_MACRO, "textnospace",       { "{\\textnospace}",       "\\textnospace",         NULL                  } }, /* No space &#x200B; */
+   { 9251, LATEX_MACRO, "textvisiblespace",  { "{\\textvisiblespace}",  "\\textvisiblespace",    NULL                  } }, /* Visible space &#x2423; */
+
+   { 215,  LATEX_MACRO, "texttimes",         { "{\\texttimes}",         "\\texttimes",           NULL                  } }, /* Multiplication symbol &#xD7; */
+   { 247,  LATEX_MACRO, "textdiv",           { "{\\textdiv}",           "\\textdiv",             NULL                  } }, /* Division symbol &#xF7; */
+   { 177,  LATEX_MACRO, "textpm",            { "{\\textpm}",            "\\textpm",              NULL                  } }, /* Plus-minus character &#B1; */
+   { 189,  LATEX_MACRO, "textonehalf",       { "{\\textonehalf}",       "\\textonehalf",         NULL                  } }, /* Vulgar fraction one half &#xBD; */
+   { 188,  LATEX_MACRO, "textonequarter",    { "{\\textonequarter}",    "\\textonequarter",      NULL                  } }, /* Vulgar fraction one quarter &#xBD; */
+   { 190,  LATEX_MACRO, "textthreequarters", { "{\\textthreequarters}", "\\textthreequarters",   NULL                  } }, /* Vulgar fraction three quarters &#xBE; */
+   { 8240, LATEX_MACRO, "texttenthousand",   { "{\\texttenthousand}",   "\\texttenthousand",     NULL                  } }, /* Per thousand sign &#x2030; */
+   { 8241, LATEX_MACRO, "textpertenthousand",{ "{\\textpertenthousand}","\\textpertenthousand",  NULL                  } }, /* Per ten thousand sign &#x2031;*/
+   { 8260, LATEX_MACRO, "textfractionssolidus",{"{\\textfractionsolidus}", "\\textfractionsolidus", NULL               } }, /* &x8260; */
+   { 8451, LATEX_MACRO, "textcelcius",       { "{\\textcelcius}",       "\\textcelcius",         NULL                  } }, /* Celcicus &#x2103; */
+   { 8470, LATEX_MACRO, "textnumero",        { "{\\textnumero}",        "\\textnumero",          NULL                  } }, /* Numero symbol &#x2116; */
+   { 8486, LATEX_MACRO, "textohm",           { "{\\textohm}",           "\\textohm",             NULL                  } }, /* Ohm symbol &#x2126; */
+   { 8487, LATEX_MACRO, "textmho",           { "{\\textmho}",           "\\textmho",             NULL                  } }, /* Mho symbol &#x2127; */
+   { 8730, LATEX_MACRO, "textsurd",          { "{\\textsurd}",          "\\textsurd",            NULL                  } }, /* &#x221A; */
+
+   { 185,  LATEX_MACRO, "textonesuperior",   { "{\\textonesuperior}",   "\\textonesuperior",     "$^1$"                } }, /*Superscript 1 &#xB9; */
+   { 178,  LATEX_MACRO, "texttwosuperior",   { "{\\texttwosuperior}",   "\\texttwosuperior",     "$^2$"                } }, /*Superscript 2 &#xB2; */
+   { 179,  LATEX_MACRO, "textthreesuperior", { "{\\textthreesuperior}", "\\textthreesuperior",   "$^3$"                } }, /*Superscript 3 &#xB3; */
+
+   { 161,  LATEX_MACRO, "textexclamdown",    { "{\\textexclamdown}",    "\\textexclamdown",      NULL                  } }, /* Inverted exclamation mark &#xA1;*/
+   { 191,  LATEX_MACRO, "textquestiondown",  { "{\\textquestiondown}",  "\\textquestiondown",    NULL                  } }, /* Inverted question mark &#xBF; */
+
+   { 162,  LATEX_MACRO, "textcent",          { "{\\textcent}",          "\\textcent",            NULL                  } }, /* Cent sign &#xA2; */
+   { 163,  LATEX_MACRO, "textsterling",      { "{\\textsterling}",      "\\textsterling",        "\\pounds"            } }, /* Pound sign &#xA3; */
+   { 165,  LATEX_MACRO, "textyen",           { "{\\textyen}",           "\\textyen",             NULL                  } }, /* Yen sign &#xA5; */
+   { 402,  LATEX_MACRO, "textflorin",        { "{\\textflorin}",        "\\textflorin",          NULL                  } }, /* Florin sign &#x192; */
+   { 3647, LATEX_MACRO, "textbaht",          { "{\\textbaht}",          "\\textbaht",            NULL                  } }, /* Thai currency &#xE3F; */
+   { 8355, LATEX_MACRO, "textfrenchfranc",   { "{\\textfrenchfranc}",   "\\textfrenchfranc",     NULL                  } }, /* French franc &#x20A3; */
+   { 8356, LATEX_MACRO, "textlira",          { "{\\textlira}",          "\\textlira",            NULL                  } }, /* Lira &#x20A4; */
+   { 8358, LATEX_MACRO, "textnaira",         { "{\\textnaira}",         "\\textnaria",           NULL                  } }, /* Naira &#x20A6; */
+   { 8361, LATEX_MACRO, "textwon",           { "{\\textwon}",           "\\textwon",             NULL                  } }, /* &#x20A9; */
+   { 8363, LATEX_MACRO, "textdong",          { "{\\textdong}",          "\\textdong",            NULL                  } }, /* Vietnamese currency &#x20AB; */
+   { 8364, LATEX_MACRO, "texteuro",          { "{\\texteuro}",          "\\texteuro",            NULL                  } }, /* Euro sign */
+
+   { 169,  LATEX_MACRO, "textcopyright",     { "{\\textcopyright}",     "\\textcopyright",       NULL                  } }, /* Copyright (C) &#xA9; */
+   { 175,  LATEX_MACRO, "textregistered",    { "{\\textregistered}",    "\\textregistered",      NULL                  } }, /* Registered sign (R) &#xAF;*/
+   { 8482, LATEX_MACRO, "texttrademark",     { "{\\texttrademark}",     "\\texttrademark",       "$^{TM}$"             } }, /* Trademark (TM) &#x2122; */
+   { 8480, LATEX_MACRO, "textservicemark",   { "{\\textservicemark}",   "\\textservicemark",     "$^{SM}$"             } }, /* Servicemark (SM) &#x2120;*/
+   { 8471, LATEX_MACRO, "textcircledP",      { "{\\textcircledP}",      "\\textcircledP",        NULL                  } }, /* Circled P ࡅ */
 
 };
 
@@ -505,31 +509,35 @@ unsigned int
 latex2char( char *s, unsigned int *pos, int *unicode )
 {
 	unsigned int value;
-	char *p, *q[3];
-	int i, j, l[3];
+//	char *p, *q[3];
+	int i, j, len;
+	char *p;
+
 	p = &( s[*pos] );
 	value = (unsigned char) *p;
 	if ( value=='{' || value=='\\' || value=='~' || 
 	     value=='$' || value=='\'' || value=='`' || 
 	     value=='-' || value=='^' ) {
-		if ( *p=='\\' && ( *p=='{' || *p=='}' ) ) {
-		} else {
+//		if ( *p=='\\' && ( *p=='{' || *p=='}' ) ) {
+//		} else {
 		for ( i=0; i<nlatex_chars; ++i ) {
-			q[0] = latex_chars[i].bib1;
-			l[0] = strlen( q[0] );
-			q[1] = latex_chars[i].bib2;
-			l[1] = strlen( q[1] );
-			q[2] = latex_chars[i].bib3;
-			l[2] = strlen( q[2] );
+//			q[0] = latex_chars[i].bib1;
+//			l[0] = strlen( q[0] );
+//			q[1] = latex_chars[i].bib2;
+//			l[1] = strlen( q[1] );
+//			q[2] = latex_chars[i].bib3;
+//			l[2] = strlen( q[2] );
 			for ( j=0; j<3; ++j ) {
-				if ( l[j] && !strncmp( p, q[j], l[j] ) ) {
-					*pos = *pos + l[j];
+				if ( latex_chars[i].variant[j] == NULL ) continue;
+				len = strlen( latex_chars[i].variant[j] );
+				if ( !strncmp( p, latex_chars[i].variant[j], len ) ) {
+					*pos = *pos + len;
 					*unicode = 1;
 					return latex_chars[i].unicode;
 				}
 			}
 		}
-		}
+//		}
 	}
 	*unicode = 0;
 	*pos = *pos + 1;
@@ -539,20 +547,51 @@ latex2char( char *s, unsigned int *pos, int *unicode )
 void
 uni2latex( unsigned int ch, char buf[], int buf_size )
 {
-	int i;
+	int i, j, n;
+
+	if ( buf_size==0 ) return;
+
 	buf[0] = '?';
 	buf[1] = '\0';
+
 	if ( ch==' ' ) {
 		buf[0] = ' '; /*special case to avoid  */
 		return;
 	}
+
 	for ( i=0; i<nlatex_chars; ++i ) {
 		if ( ch == latex_chars[i].unicode ) {
-			strncpy( buf, latex_chars[i].bib1, buf_size );
-			buf[ buf_size-1 ] = '\0';
+			n = 0;
+
+			if ( latex_chars[i].type == LATEX_MACRO ) {
+				if ( n < buf_size ) buf[n++] = '{';
+				if ( n < buf_size ) buf[n++] = '\\';
+			}
+			else if ( latex_chars[i].type == LATEX_MATH ) {
+				if ( n < buf_size ) buf[n++] = '$';
+				if ( n < buf_size ) buf[n++] = '\\';
+			}
+
+			j = 0;
+			while ( latex_chars[i].out[j] ) {
+				if ( n < buf_size ) buf[n++] = latex_chars[i].out[j];
+				j++;
+			}
+
+			if ( latex_chars[i].type == LATEX_MACRO ) {
+				if ( n < buf_size ) buf[n++] = '}';
+			}
+			else if ( latex_chars[i].type == LATEX_MATH ) {
+				if ( n < buf_size ) buf[n++] = '$';
+			}
+
+			if ( n < buf_size ) buf[n] = '\0';
+			else buf[ buf_size-1 ] = '\0';
+
 			return;
 		}
 	}
-	if ( ch < 128 && buf[0]=='?' ) buf[0] = (char)ch;
+
+	if ( ch < 128 ) buf[0] = (char)ch;
 }
 
diff --git a/lib/latex.h b/lib/latex.h
index 30b49d7..2f84d81 100644
--- a/lib/latex.h
+++ b/lib/latex.h
@@ -1,7 +1,7 @@
 /*
  * latex.h
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/lib/list.c b/lib/list.c
index 0964bdc..f3ff9de 100644
--- a/lib/list.c
+++ b/lib/list.c
@@ -1,9 +1,9 @@
 /*
  * list.c
  *
- * version: 2014-11-15
+ * version: 2016-11-03
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Source code released under the GPL version 2
  *
@@ -21,6 +21,59 @@ list_init( list *a  )
 	a->sorted = 1;
 }
 
+int
+list_init_values( list *a, ... )
+{
+	int status = LIST_OK;
+	va_list ap;
+	newstr *s, *t;
+
+	list_init( a );
+
+	va_start( ap, a );
+	do {
+		s = va_arg( ap, newstr * );
+		if ( s ) {
+			t = list_add( a, s );
+			if ( !t ) {
+				status = LIST_ERR;
+				goto out;
+			}
+		}
+	} while ( s );
+out:
+	va_end( ap );
+
+	return status;
+}
+
+int
+list_init_valuesc( list *a, ... )
+{
+	int status = LIST_OK;
+	va_list ap;
+	newstr *t;
+	char *s;
+
+	list_init( a );
+
+	va_start( ap, a );
+	do {
+		s = va_arg( ap, char * );
+		if ( s ) {
+			t = list_addc( a, s );
+			if ( !t ) {
+				status = LIST_ERR;
+				goto out;
+			}
+		}
+	} while ( s );
+out:
+	va_end( ap );
+
+	return status;
+}
+
 void
 list_empty( list *a )
 {
diff --git a/lib/list.h b/lib/list.h
index 9005cb3..d9840c5 100644
--- a/lib/list.h
+++ b/lib/list.h
@@ -1,9 +1,9 @@
 /*
  * list.h
  *
- * version: 2014-11-15
+ * version: 2016-11-03
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Source code released under the GPL version 2
  *
@@ -32,56 +32,57 @@ typedef struct list {
 } list;
 
 
-extern void    lists_init( list *a, ... );
-extern void    lists_free( list *a, ... );
-extern void    lists_empty( list *a, ... );
+void    lists_init( list *a, ... );
+void    lists_free( list *a, ... );
+void    lists_empty( list *a, ... );
 
+void    list_init( list *a );
+int     list_init_values ( list *a, ... );
+int     list_init_valuesc( list *a, ... );
+void    list_free( list *a );
+void    list_empty( list *a );
 
-extern void    list_init( list *a );
-extern void    list_free( list *a );
-extern void    list_empty( list *a );
+list *  list_new( void );
+void    list_delete( list * );
 
-extern list *  list_new( void );
-extern void    list_delete( list * );
+list*   list_dup( list *a );
+int     list_copy( list *to, list *from );
 
-extern list*   list_dup( list *a );
-extern int     list_copy( list *to, list *from );
+newstr * list_addvp( list *a, unsigned char mode, void *vp );
+newstr * list_addc( list *a, const char *value );
+newstr * list_add( list *a, newstr *value );
 
-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 );
+int      list_addvp_all( list *a, unsigned char mode, ... );
+int      list_addc_all( list *a, ... );
+int      list_add_all( 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, ... );
+newstr * list_addvp_unique( list *a, unsigned char mode, void *vp );
+newstr * list_addc_unique( list *a, const char *value );
+newstr * list_add_unique( list *a, newstr *value );
 
-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 );
+int     list_append( list *a, list *toadd );
+int     list_append_unique( list *a, list *toadd );
 
-extern int     list_append( list *a, list *toadd );
-extern int     list_append_unique( list *a, list *toadd );
+int     list_remove( list *a, int n );
 
-extern int     list_remove( list *a, int n );
+newstr* list_get( list *a, int n );
+char*   list_getc( list *a, int n );
 
-extern newstr* list_get( list *a, int n );
-extern char*   list_getc( list *a, int n );
+newstr* list_set( list *a, int n, newstr *s );
+newstr* list_setc( list *a, int n, const char *s );
 
-extern newstr* list_set( list *a, int n, newstr *s );
-extern newstr* list_setc( list *a, int n, const char *s );
+void    list_sort( list *a );
 
-extern void    list_sort( list *a );
+void    list_swap( list *a, int n1, int n2 );
 
-extern void    list_swap( list *a, int n1, int n2 );
+int     list_find( list *a, const char *searchstr );
+int     list_findnocase( list *a, const char *searchstr );
+int     list_match_entry( list *a, int n, char *s );
+void    list_trimend( list *a, int n );
 
-extern int     list_find( list *a, const char *searchstr );
-extern int     list_findnocase( list *a, const char *searchstr );
-extern int     list_match_entry( list *a, int n, char *s );
-extern void    list_trimend( list *a, int n );
-
-extern int     list_fill( list *a, const char *filename, unsigned char skip_blank_lines );
-extern int     list_fillfp( list *a, FILE *fp, unsigned char skip_blank_lines );
-extern int     list_tokenize( list *tokens, newstr *in, const char *delim, int merge_delim );
-extern int     list_tokenizec( list *tokens, char *p, const char *delim, int merge_delim );
+int     list_fill( list *a, const char *filename, unsigned char skip_blank_lines );
+int     list_fillfp( list *a, FILE *fp, unsigned char skip_blank_lines );
+int     list_tokenize( list *tokens, newstr *in, const char *delim, int merge_delim );
+int     list_tokenizec( list *tokens, char *p, const char *delim, int merge_delim );
 
 #endif
diff --git a/lib/marc.c b/lib/marc.c
index 8825d7e..49cd034 100644
--- a/lib/marc.c
+++ b/lib/marc.c
@@ -1,7 +1,7 @@
 /*
  * marc.c
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/lib/marc.h b/lib/marc.h
index 26912a0..fc61240 100644
--- a/lib/marc.h
+++ b/lib/marc.h
@@ -1,7 +1,7 @@
 /*
  * marc.h
  *
- * Copyright (c) Chris Putnam 2008-2015
+ * Copyright (c) Chris Putnam 2008-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/lib/medin.c b/lib/medin.c
index 61cb050..1ee1c9e 100644
--- a/lib/medin.c
+++ b/lib/medin.c
@@ -1,7 +1,7 @@
 /*
  * medin.c
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Source code released under the GPL version 2
  *
@@ -14,9 +14,13 @@
 #include "fields.h"
 #include "xml.h"
 #include "xml_encoding.h"
-#include "medin.h"
 #include "iso639_2.h"
 #include "bibutils.h"
+#include "bibformats.h"
+
+static int medin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );
+static int medin_processf( fields *medin, char *data, char *filename, long nref, param *p );
+
 
 /*****************************************************
  PUBLIC: void medin_initparams()
@@ -82,7 +86,7 @@ medin_findendwrapper( char *buf, int ntype )
 	return endptr;
 }
 
-int
+static int
 medin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset )
 {
 	newstr tmp;
@@ -178,7 +182,7 @@ medin_medlinedate( fields *info, char *p, int 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, "PARTYEAR", tmp.data, level );
+		fstatus = fields_add( info, "PARTDATE:YEAR", tmp.data, level );
 		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
 
@@ -186,14 +190,14 @@ medin_medlinedate( fields *info, char *p, int level )
 	if ( newstr_memerr( &tmp ) ) return BIBL_ERR_MEMERR;
 	if ( tmp.len > 0 ) {
 		newstr_findreplace( &tmp, "-", "/" );
-		fstatus = fields_add( info, "PARTMONTH", tmp.data, level );
+		fstatus = fields_add( info, "PARTDATE:MONTH", tmp.data, level );
 		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
 
 	p = newstr_cpytodelim( &tmp, skip_ws( p ), " \t\n\r", 0 );
 	if ( newstr_memerr( &tmp ) ) return BIBL_ERR_MEMERR;
 	if ( tmp.len > 0 ) {
-		fstatus = fields_add( info, "PARTDAY", tmp.data, level );
+		fstatus = fields_add( info, "PARTDATE:DAY", tmp.data, level );
 		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
 
@@ -252,14 +256,14 @@ static int
 medin_journal1( xml *node, fields *info )
 {
 	xml_convert c[] = {
-		{ "Title",           NULL, NULL, "TITLE",      1 },
-		{ "ISOAbbreviation", NULL, NULL, "SHORTTITLE", 1 },
-		{ "ISSN",            NULL, NULL, "ISSN",       1 },
-		{ "Volume",          NULL, NULL, "VOLUME",     1 },
-		{ "Issue",           NULL, NULL, "ISSUE",      1 },
-		{ "Year",            NULL, NULL, "PARTYEAR",   1 },
-		{ "Month",           NULL, NULL, "PARTMONTH",  1 },
-		{ "Day",             NULL, NULL, "PARTDAY",    1 },
+		{ "Title",           NULL, NULL, "TITLE",          1 },
+		{ "ISOAbbreviation", NULL, NULL, "SHORTTITLE",     1 },
+		{ "ISSN",            NULL, NULL, "ISSN",           1 },
+		{ "Volume",          NULL, NULL, "VOLUME",         1 },
+		{ "Issue",           NULL, NULL, "ISSUE",          1 },
+		{ "Year",            NULL, NULL, "PARTDATE:YEAR",  1 },
+		{ "Month",           NULL, NULL, "PARTDATE:MONTH", 1 },
+		{ "Day",             NULL, NULL, "PARTDATE:DAY",   1 },
 	};
 	int nc = sizeof( c ) / sizeof( c[0] ), status, found;
 	if ( xml_hasdata( node ) ) {
@@ -302,7 +306,7 @@ medin_pagination( xml *node, fields *info )
 		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 );
+			fstatus = fields_add( info, "PAGES:START", sp.data, 1 );
 			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 		}
 		p = newstr_cpytodelim( &ep, p, "", 0 );
@@ -313,7 +317,7 @@ medin_pagination( xml *node, fields *info )
 					sp.data[i] = ep.data[i-sp.len+ep.len];
 				pp = sp.data;
 			} else  pp = ep.data;
-			fstatus = fields_add( info, "PAGEEND", pp, 1 );
+			fstatus = fields_add( info, "PAGES:STOP", pp, 1 );
 			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 		}
 		newstrs_free( &sp, &ep, NULL );
@@ -491,7 +495,7 @@ medin_meshheadinglist( xml *node, fields *info )
  *         <ArticleId IdType="pubmed">14523232</ArticleId>
  *         <ArticleId IdType="doi">10.1073/pnas.2133463100</ArticleId>
  *         <ArticleId IdType="pii">2133463100</ArticleId>
- *         <ArticleId IdType="medline">22922082</ArticleId>
+ *         <ArticleId IdType="pmc">PMC4833866</ArticleId>
  *     </ArticleIdList>
  * </PubmedData>
  *
@@ -504,6 +508,7 @@ medin_pubmeddata( xml *node, fields *info )
 		{ "ArticleId", "IdType", "doi",     "DOI",     0 },
 		{ "ArticleId", "IdType", "pubmed",  "PMID",    0 },
 		{ "ArticleId", "IdType", "medline", "MEDLINE", 0 },
+		{ "ArticleId", "IdType", "pmc",     "PMC",     0 },
 		{ "ArticleId", "IdType", "pii",     "PII",     0 },
 	};
 	int nc = sizeof( c ) / sizeof( c[0] ), found, status;
@@ -542,7 +547,7 @@ medin_article( xml *node, fields *info )
 	}
 	if ( status!=BIBL_OK ) return status;
 	if ( node->next ) status = medin_article( node->next, info );
-	return BIBL_OK;
+	return status;
 }
 
 static int
@@ -616,8 +621,8 @@ medin_assembleref( xml *node, fields *info )
 	return status;
 }
 
-int
-medin_processf( fields *medin, char *data, char *filename, long nref )
+static int
+medin_processf( fields *medin, char *data, char *filename, long nref, param *p )
 {
 	int status;
 	xml top;
diff --git a/lib/medin.h b/lib/medin.h
deleted file mode 100644
index 5320f16..0000000
--- a/lib/medin.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * medin.h
- *
- * Copyright (c) Chris Putnam 2004-2015
- *
- * Source code released under the GPL version 2
- *
- */
-#ifndef MEDIN_H
-#define MEDIN_H
-
-#include "newstr.h"
-#include "fields.h"
-#include "reftypes.h"
-#include "bibutils.h"
-
-extern int medin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );
-extern int medin_processf( fields *medin, char *data, char *filename, long nref );
-
-extern void medin_initparams( param *p, const char *progname );
-
-extern variants med_all[];
-extern int med_nall;
-
-#endif
-
diff --git a/lib/modsin.c b/lib/modsin.c
index 9f2a31f..40d56c8 100644
--- a/lib/modsin.c
+++ b/lib/modsin.c
@@ -1,7 +1,7 @@
 /*
  * modsin.c
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Source code released under the GPL version 2
  *
@@ -24,7 +24,10 @@
 #include "iso639_2.h"
 #include "iso639_3.h"
 #include "bibutils.h"
-#include "modsin.h"
+#include "bibformats.h"
+
+static int modsin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );
+static int modsin_processf( fields *medin, char *data, char *filename, long nref, param *p );
 
 /*****************************************************
  PUBLIC: void modsin_initparams()
@@ -102,7 +105,7 @@ modsin_detail( xml *node, fields *info, int level )
 		status = modsin_detailr( node->down, &value );
 		if ( status!=BIBL_OK ) goto out;
 		if ( type.data && !strcasecmp( type.data, "PAGE" ) ) {
-			fstatus = fields_add( info, "PAGESTART", value.data, level );
+			fstatus = fields_add( info, "PAGES:START", value.data, level );
 		} else {
 			fstatus = fields_add( info, type.data, value.data, level );
 		}
@@ -126,7 +129,7 @@ modsin_date( xml *node, fields *info, int level, int part )
 		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";
+			tag = ( part ) ? "PARTDATE:YEAR" : "DATE:YEAR";
 			fstatus =  fields_add( info, tag, s.data, level );
 			if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }
 		}
@@ -134,7 +137,7 @@ modsin_date( xml *node, fields *info, int level, int part )
 		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";
+			tag = ( part ) ? "PARTDATE:MONTH" : "DATE:MONTH";
 			fstatus =  fields_add( info, tag, s.data, level );
 			if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }
 		}
@@ -142,7 +145,7 @@ modsin_date( xml *node, fields *info, int level, int part )
 		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";
+			tag = ( part ) ? "PARTDATE:DAY" : "DATE:DAY";
 			fstatus =  fields_add( info, tag, s.data, level );
 			if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }
 		}
@@ -194,24 +197,24 @@ modsin_page( xml *node, fields *info, int level )
 
 	if ( sp.len || ep.len ) {
 		if ( sp.len ) {
-			fstatus = fields_add( info, "PAGESTART", sp.data, level );
+			fstatus = fields_add( info, "PAGES:START", sp.data, level );
 			if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }
 		}
 		if ( ep.len ) {
-			fstatus = fields_add( info, "PAGEEND", ep.data, level );
+			fstatus = fields_add( info, "PAGES:STOP", 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 );
+		fstatus = fields_add( info, "PAGES:START", lp.data, level );
 		if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }
 	}
 	if ( tp.len ) {
-		fstatus = fields_add( info, "TOTALPAGES", tp.data, level );
+		fstatus = fields_add( info, "PAGES:TOTAL", tp.data, level );
 		if ( fstatus!=FIELDS_OK ) { status = BIBL_ERR_MEMERR; goto out; }
 	}
 out:
 	newstrs_free( &sp, &ep, &tp, &lp, NULL );
-	return BIBL_OK;
+	return status;
 }
 
 static int
@@ -248,7 +251,7 @@ modsin_title( xml *node, fields *info, int level )
 	};
 	int fstatus, status = BIBL_OK;
 	newstr title, subtitle;
-	xml *dnode = node->down;
+	xml *dnode;
 	int abbr;
 
 	dnode = node->down;
@@ -361,40 +364,6 @@ modsin_asis_corp_r( xml *node, newstr *name, newstr *role )
 }
 
 static int
-modsin_personr( xml *node, newstr *name, newstr *suffix, newstr *roles )
-{
-	newstr outname;
-	int status = BIBL_OK;
-	newstr_init( &outname );
-	if ( xml_tagexact( node, "namePart" ) ) {
-		if ( xml_tag_attrib( node, "namePart", "type", "family" ) ) {
-			if ( name->len ) newstr_prepend( name, "|" );
-			newstr_prepend( name, node->value->data );
-		} else if (xml_tag_attrib( node, "namePart", "type", "suffix") ||
-		           xml_tag_attrib( node, "namePart", "type", "termsOfAddress" )) {
-			if ( suffix->len ) newstr_addchar( suffix, ' ' );
-			newstr_strcat( suffix, node->value->data );
-		} else if (xml_tag_attrib( node, "namePart", "type", "date")){
-		} else {
-			if ( name->len ) newstr_addchar( name, '|' );
-			name_parse( &outname, node->value, NULL, NULL );
-			newstr_newstrcat( name, &outname );
-		}
-	} else if ( xml_tagexact( node, "roleTerm" ) ) {
-		if ( roles->len ) newstr_addchar( roles, '|' );
-		newstr_newstrcat( roles, node->value );
-	}
-	if ( node->down ) {
-		status = modsin_personr( node->down, name, suffix, roles );
-		if ( status!=BIBL_OK ) goto out;
-	}
-	if ( node->next ) status = modsin_personr( node->next, name, suffix, roles );
-out:
-	newstr_free( &outname );
-	return status;
-}
-
-static int
 modsin_asis_corp( xml *node, fields *info, int level, char *suffix )
 {
 	int fstatus, status = BIBL_OK;
@@ -415,30 +384,124 @@ out:
 }
 
 static int
+modsin_roler( xml *node, newstr *roles )
+{
+	int status = BIBL_OK;
+
+	if ( roles->len ) newstr_addchar( roles, '|' );
+	newstr_newstrcat( roles, node->value );
+	if ( newstr_memerr( roles ) ) status = BIBL_ERR_MEMERR;
+
+	return status;
+}
+
+static int
+modsin_personr( xml *node, newstr *familyname, newstr *givenname, newstr *suffix )
+{
+	int status = BIBL_OK;
+
+	if ( xml_tag_attrib( node, "namePart", "type", "family" ) ) {
+		if ( familyname->len ) newstr_addchar( familyname, ' ' );
+		newstr_newstrcat( familyname, node->value );
+		if ( newstr_memerr( familyname ) ) status = BIBL_ERR_MEMERR;
+	}
+
+	else if ( xml_tag_attrib( node, "namePart", "type", "suffix") ||
+	          xml_tag_attrib( node, "namePart", "type", "termsOfAddress" )) {
+		if ( suffix->len ) newstr_addchar( suffix, ' ' );
+		newstr_newstrcat( suffix, node->value );
+		if ( newstr_memerr( suffix ) ) status = BIBL_ERR_MEMERR;
+	}
+
+	else if (xml_tag_attrib( node, "namePart", "type", "date") ){
+		/* no nothing */
+	}
+
+	else {
+		if ( givenname->len ) newstr_addchar( givenname, '|' );
+		newstr_newstrcat( givenname, node->value );
+		if ( newstr_memerr( givenname ) ) status = BIBL_ERR_MEMERR;
+	}
+
+	return status;
+}
+
+static int
 modsin_person( xml *node, fields *info, int level )
 {
-	newstr name, suffix, roles, role_out;
+	newstr familyname, givenname, name, suffix, roles, role_out;
 	int fstatus, status = BIBL_OK;
-	xml *dnode = node->down;
-	if ( dnode ) {
-		newstrs_init( &name, &suffix, &roles, &role_out, NULL );
+	xml *dnode, *rnode;
 
-		status = modsin_personr( dnode, &name, &suffix, &roles );
-		if ( status!=BIBL_OK ) goto out;
-		if ( suffix.len ) {
-			newstr_strcat( &name, "||" );
-			newstr_newstrcat( &name, &suffix );
-			if ( newstr_memerr( &name ) ) { status=BIBL_ERR_MEMERR; goto out; }
+	dnode = node->down;
+	if ( !dnode ) return status;
+
+	newstrs_init( &name, &familyname, &givenname, &suffix, &roles, &role_out, NULL );
+
+	while ( dnode ) {
+
+		if ( xml_tagexact( dnode, "namePart" ) ) {
+			status = modsin_personr( dnode, &familyname, &givenname, &suffix );
+			if ( status!=BIBL_OK ) goto out;
 		}
 
-		status = modsin_marcrole_convert( &roles, NULL, &role_out );
-		if ( status!=BIBL_OK ) goto out;
+		else if ( xml_tagexact( dnode, "role" ) ) {
+			rnode = dnode->down;
+			while ( rnode ) {
+				if ( xml_tagexact( rnode, "roleTerm" ) ) {
+					status = modsin_roler( rnode, &roles );
+					if ( status!=BIBL_OK ) goto out;
+				}
+				rnode = rnode->next;
+			}
+		}
 
-		fstatus = fields_add( info, role_out.data, name.data, level );
-		if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;
-out:
-		newstrs_free( &name, &suffix, &roles, &role_out, NULL );
+		dnode = dnode->next;
+
+	}
+
+	/*
+	 * Handle:
+	 *          <namePart type='given'>Noah A.</namePart>
+	 *          <namePart type='family'>Smith</namePart>
+	 * without mangling the order of "Noah A."
+	 */
+	if ( familyname.len ) {
+		newstr_newstrcpy( &name, &familyname );
+		if ( givenname.len ) {
+			newstr_addchar( &name, '|' );
+			newstr_newstrcat( &name, &givenname );
+		}
+	}
+
+	/*
+	 * Handle:
+	 *          <namePart>Noah A. Smith</namePart>
+	 * with name order mangling.
+	 */
+	else {
+		if ( givenname.len )
+			name_parse( &name, &givenname, NULL, NULL );
+	}
+
+	if ( suffix.len ) {
+		newstr_strcat( &name, "||" );
+		newstr_newstrcat( &name, &suffix );
 	}
+
+	if ( newstr_memerr( &name ) ) {
+		status=BIBL_ERR_MEMERR;
+		goto out;
+	}
+
+	status = modsin_marcrole_convert( &roles, NULL, &role_out );
+	if ( status!=BIBL_OK ) goto out;
+
+	fstatus = fields_add_can_dup( info, role_out.data, name.data, level );
+	if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;
+
+out:
+	newstrs_free( &name, &familyname, &givenname, &suffix, &roles, &role_out, NULL );
 	return status;
 }
 
@@ -791,7 +854,7 @@ modsin_description( xml *node, fields *info, int level )
 	}
 out:
 	newstr_free( &s );
-	return BIBL_OK;
+	return status;
 }
 
 static int
@@ -863,6 +926,7 @@ modsin_identifier( xml *node, fields *info, int level )
 	convert ids[] = {
 		{ "citekey",       "REFNUM",      0, 0 },
 		{ "issn",          "ISSN",        0, 0 },
+		{ "coden",         "CODEN",       0, 0 },
 		{ "isbn",          "ISBN",        0, 0 },
 		{ "doi",           "DOI",         0, 0 },
 		{ "url",           "URL",         0, 0 },
@@ -870,7 +934,9 @@ modsin_identifier( xml *node, fields *info, int level )
 		{ "pmid",          "PMID",        0, 0 },
 		{ "pubmed",        "PMID",        0, 0 },
 		{ "medline",       "MEDLINE",     0, 0 },
+		{ "pmc",           "PMC",         0, 0 },
 		{ "arXiv",         "ARXIV",       0, 0 },
+		{ "MRnumber",      "MRNUMBER",    0, 0 },
 		{ "pii",           "PII",         0, 0 },
 		{ "isi",           "ISIREFNUM",   0, 0 },
 		{ "serial number", "SERIALNUMBER",0, 0 },
@@ -944,6 +1010,10 @@ modsin_mods( xml *node, fields *info, int level )
 			  xml_tag_attrib( node, "relatedItem", "type", "series" ) ) {
 			if ( node->down ) status = modsin_mods( node->down, info, level+1 );
 		}
+		else if ( xml_tag_attrib( node, "relatedItem", "type", "original" ) ) {
+			if ( node->down ) status = modsin_mods( node->down, info, LEVEL_ORIG );
+		}
+
 		if ( status!=BIBL_OK ) return status;
 	}
 
@@ -971,8 +1041,8 @@ modsin_assembleref( xml *node, fields *info )
 	return status;
 }
 
-int
-modsin_processf( fields *modsin, char *data, char *filename, long nref )
+static int
+modsin_processf( fields *modsin, char *data, char *filename, long nref, param *p )
 {
 	int status;
 	xml top;
@@ -1011,7 +1081,7 @@ modsin_endptr( char *p )
 	return xml_findend( p, "mods" );
 }
 
-int
+static int
 modsin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line,
 		newstr *reference, int *fcharset )
 {
diff --git a/lib/modsin.h b/lib/modsin.h
deleted file mode 100644
index 0e25200..0000000
--- a/lib/modsin.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * modsin.h
- *
- * Copyright (c) Chris Putnam 2004-2015
- *
- * Source code released under the GPL version 2
- *
- */
-#ifndef MODSIN_H
-#define MODSIN_H
-
-#include "newstr.h"
-#include "fields.h"
-#include "reftypes.h"
-
-extern int modsin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );
-extern int modsin_processf( fields *medin, char *data, char *filename, long nref );
-extern void modsin_initparams( param *p, const char *progname );
-
-#endif
diff --git a/lib/modsout.c b/lib/modsout.c
index 69611d0..9dac7f0 100644
--- a/lib/modsout.c
+++ b/lib/modsout.c
@@ -1,7 +1,7 @@
 /*
  * modsout.c
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Source code released under the GPL version 2
  *
@@ -17,9 +17,13 @@
 #include "fields.h"
 #include "iso639_2.h"
 #include "utf8.h"
-#include "modsout.h"
 #include "modstypes.h"
 #include "marc.h"
+#include "bibformats.h"
+
+static void modsout_writeheader( FILE *outptr, param *p );
+static void modsout_writefooter( FILE *outptr );
+static int  modsout_write( fields *info, FILE *outptr, param *p, unsigned long numrefs );
 
 void
 modsout_initparams( param *p, const char *progname )
@@ -348,9 +352,9 @@ output_names( fields *f, FILE *outptr, int level )
 
 /* datepos[ NUM_DATE_TYPES ]
  *     use define to ensure that the array and loops don't get out of sync
- *     datepos[0] -> YEAR/PARTYEAR
- *     datepos[1] -> MONTH/PARTMONTH
- *     datepos[2] -> DAY/PARTDAY
+ *     datepos[0] -> DATE:YEAR/PARTDATE:YEAR
+ *     datepos[1] -> DATE:MONTH/PARTDATE:MONTH
+ *     datepos[2] -> DATE:DAY/PARTDATE:DAY
  *     datepos[3] -> DATE/PARTDATE
  */
 #define DATE_YEAR      (0)
@@ -362,8 +366,8 @@ output_names( fields *f, FILE *outptr, int level )
 static int
 find_datepos( fields *f, int level, unsigned char use_altnames, int datepos[NUM_DATE_TYPES] )
 {
-	char      *src_names[] = { "YEAR", "MONTH", "DAY", "DATE" };
-	char      *alt_names[] = { "PARTYEAR", "PARTMONTH", "PARTDAY", "PARTDATE" };
+	char      *src_names[] = { "DATE:YEAR", "DATE:MONTH", "DATE:DAY", "DATE" };
+	char      *alt_names[] = { "PARTDATE:YEAR", "PARTDATE:MONTH", "PARTDATE:DAY", "PARTDATE" };
 	int       found = 0;
 	int       i;
 
@@ -624,9 +628,9 @@ static int
 output_partdate( fields *f, FILE *outptr, int level, int wrote_header )
 {
 	convert parts[] = {
-		{ "",	"PARTYEAR",                0, 0 },
-		{ "",	"PARTMONTH",               0, 0 },
-		{ "",	"PARTDAY",                 0, 0 },
+		{ "",	"PARTDATE:YEAR",           0, 0 },
+		{ "",	"PARTDATE:MONTH",          0, 0 },
+		{ "",	"PARTDATE:DAY",            0, 0 },
 	};
 	int nparts = sizeof(parts)/sizeof(parts[0]);
 
@@ -659,10 +663,10 @@ static int
 output_partpages( fields *f, FILE *outptr, int level, int wrote_header )
 {
 	convert parts[] = {
-		{ "",  "PAGESTART",                0, 0 },
-		{ "",  "PAGEEND",                  0, 0 },
+		{ "",  "PAGES:START",              0, 0 },
+		{ "",  "PAGES:STOP",               0, 0 },
 		{ "",  "PAGES",                    0, 0 },
-		{ "",  "TOTALPAGES",               0, 0 }
+		{ "",  "PAGES:TOTAL",              0, 0 }
 	};
 	int nparts = sizeof(parts)/sizeof(parts[0]);
 
@@ -670,7 +674,7 @@ output_partpages( fields *f, FILE *outptr, int level, int wrote_header )
 
 	try_output_partheader( outptr, wrote_header, level );
 
-	/* If PAGESTART or PAGEEND are undefined */
+	/* If PAGES:START or PAGES:STOP are undefined */
 	if ( parts[0].pos==-1 || parts[1].pos==-1 ) {
 		if ( parts[0].pos!=-1 )
 			mods_output_detail( f, outptr, parts[0].pos, "page", level );
@@ -681,7 +685,7 @@ output_partpages( fields *f, FILE *outptr, int level, int wrote_header )
 		if ( parts[3].pos!=-1 )
 			mods_output_extents( f, outptr, -1, -1, parts[3].pos, "page", level );
 	}
-	/* If both PAGESTART and PAGEEND are defined */
+	/* If both PAGES:START and PAGES:STOP are defined */
 	else {
 		mods_output_extents( f, outptr, parts[0].pos, parts[1].pos, parts[3].pos, "page", level );
 	}
@@ -870,14 +874,17 @@ output_sn( fields *f, FILE *outptr, int level )
 		{ "isbn",      "ISBN13",    0, 0 },
 		{ "lccn",      "LCCN",      0, 0 },
 		{ "issn",      "ISSN",      0, 0 },
+		{ "coden",     "CODEN",     0, 0 },
 		{ "citekey",   "REFNUM",    0, 0 },
 		{ "doi",       "DOI",       0, 0 },
 		{ "eid",       "EID",       0, 0 },
 		{ "eprint",    "EPRINT",    0, 0 },
 		{ "eprinttype","EPRINTTYPE",0, 0 },
 		{ "pubmed",    "PMID",      0, 0 },
+		{ "MRnumber",  "MRNUMBER",  0, 0 },
 		{ "medline",   "MEDLINE",   0, 0 },
 		{ "pii",       "PII",       0, 0 },
+		{ "pmc",       "PMC",       0, 0 },
 		{ "arXiv",     "ARXIV",     0, 0 },
 		{ "isi",       "ISIREFNUM", 0, 0 },
 		{ "accessnum", "ACCESSNUM", 0, 0 },
@@ -1052,7 +1059,7 @@ modsout_report_unused_tags( fields *f, param *p, unsigned long numrefs )
 		for ( i=0; i<n; ++i ) {
 			if ( fields_level( f, i ) != 0 ) continue;
 			tag = fields_tag( f, i, FIELDS_CHRP_NOUSE );
-			if ( strncasecmp( tag, "AUTHOR", 6 ) ) continue;
+			if ( strcasecmp( tag, "AUTHOR" ) && strcasecmp( tag, "AUTHOR:ASIS" ) && strcasecmp( tag, "AUTHOR:CORP" ) ) continue;
 			value = fields_value( f, i, FIELDS_CHRP_NOUSE );
 			if ( nwritten==0 ) fprintf( stderr, "\tAuthor(s) (level=0):\n" );
 			fprintf( stderr, "\t\t'%s'\n", value );
@@ -1062,7 +1069,7 @@ modsout_report_unused_tags( fields *f, param *p, unsigned long numrefs )
 		for ( i=0; i<n; ++i ) {
 			if ( fields_level( f, i ) != 0 ) continue;
 			tag = fields_tag( f, i, FIELDS_CHRP_NOUSE );
-			if ( strcasecmp( tag, "YEAR" ) && strcasecmp( tag, "PARTYEAR" ) ) continue;
+			if ( strcasecmp( tag, "DATE:YEAR" ) && strcasecmp( tag, "PARTDATE:YEAR" ) ) continue;
 			value = fields_value( f, i, FIELDS_CHRP_NOUSE );
 			if ( nwritten==0 ) fprintf( stderr, "\tYear(s) (level=0):\n" );
 			fprintf( stderr, "\t\t'%s'\n", value );
@@ -1091,12 +1098,12 @@ modsout_report_unused_tags( fields *f, param *p, unsigned long numrefs )
 	}
 }
 
-void
+static int
 modsout_write( fields *f, FILE *outptr, param *p, unsigned long numrefs )
 {
 	int max, dropkey;
 	max = fields_maxlevel( f );
-	dropkey = ( p->format_opts & MODSOUT_DROPKEY );
+	dropkey = ( p->format_opts & BIBL_FORMAT_MODSOUT_DROPKEY );
 
 	output_head( f, outptr, dropkey, numrefs );
 	output_citeparts( f, outptr, 0, max );
@@ -1104,9 +1111,11 @@ modsout_write( fields *f, FILE *outptr, param *p, unsigned long numrefs )
 
 	fprintf( outptr, "</mods>\n" );
 	fflush( outptr );
+
+	return BIBL_OK;
 }
 
-void
+static void
 modsout_writeheader( FILE *outptr, param *p )
 {
 	if ( p->utf8bom ) utf8_writebom( outptr );
@@ -1115,7 +1124,7 @@ modsout_writeheader( FILE *outptr, param *p )
 	fprintf(outptr,"<modsCollection xmlns=\"http://www.loc.gov/mods/v3\">\n");
 }
 
-void
+static void
 modsout_writefooter( FILE *outptr )
 {
 	fprintf(outptr,"</modsCollection>\n");
diff --git a/lib/modsout.h b/lib/modsout.h
deleted file mode 100644
index 7ebefd2..0000000
--- a/lib/modsout.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * modsout.h
- *
- * Copyright (c) Chris Putnam 2003-2015
- *
- * Source code released under the GPL version 2
- *
- */
-#ifndef MODSOUT_H
-#define MODSOUT_H
-
-/* format-specific options */
-#define MODSOUT_DROPKEY (2)
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "bibl.h"
-#include "bibutils.h"
-
-extern void modsout_writeheader( FILE *outptr, param *p );
-extern void modsout_writefooter( FILE *outptr );
-extern void modsout_write( fields *info, FILE *outptr,
-	param *p, unsigned long numrefs );
-extern void modsout_initparams( param *p, const char *progname );
-
-#endif
-
diff --git a/lib/modstypes.c b/lib/modstypes.c
index 6b82091..e8b9b43 100644
--- a/lib/modstypes.c
+++ b/lib/modstypes.c
@@ -1,7 +1,7 @@
 /*
  * modstypes.c
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Source code released under the GPL version 2
  *      
@@ -16,19 +16,20 @@
  *
  */
 convert identifier_types[] = {
-                { "citekey", "REFNUM" },
-                { "issn",    "ISSN"   },
-                { "isbn",    "ISBN"   },
-                { "doi",     "DOI"    },
-                { "url",     "URL"    },
-                { "uri",     "URL"    },
-                { "pubmed",  "PUBMED" },
-                { "medline", "MEDLINE" },
-                { "pii",     "PII" },
-                { "isi",     "ISIREFNUM" },
-		{ "lccn",    "LCCN" },
-                { "serial number", "SERIALNUMBER" },
-                { "accessnum", "ACCESSNUM" }
+	{ "citekey",       "REFNUM"    },
+	{ "issn",          "ISSN"      },
+	{ "isbn",          "ISBN"      },
+	{ "doi",           "DOI"       },
+	{ "url",           "URL"       },
+	{ "uri",           "URL"       },
+	{ "pubmed",        "PMID",     },
+	{ "medline",       "MEDLINE"   },
+	{ "pmc",           "PMC"       },
+	{ "pii",           "PII"       },
+	{ "isi",           "ISIREFNUM" },
+	{ "lccn",          "LCCN"      },
+	{ "serial number", "SERIALNUMBER" },
+	{ "accessnum",     "ACCESSNUM"    }
 };
 
 int nidentifier_types = sizeof( identifier_types ) / sizeof( identifier_types[0] );
diff --git a/lib/modstypes.h b/lib/modstypes.h
index 4fd94d8..b296a0c 100644
--- a/lib/modstypes.h
+++ b/lib/modstypes.h
@@ -1,7 +1,7 @@
 /*
  * modstypes.h
  *
- * Copyright (c) Chris Putnam 2008-2015
+ * Copyright (c) Chris Putnam 2008-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/lib/mycvout.c b/lib/mycvout.c
index 9c02163..fab0292 100644
--- a/lib/mycvout.c
+++ b/lib/mycvout.c
@@ -1,7 +1,7 @@
 /*
  * bibtexout.c
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Source code released under the GPL version 2
  *
@@ -17,7 +17,7 @@
 #include "fields.h"
 #include "bibl.h"
 #include "doi.h"
-#include "bibtexout.h"
+#include "bibutils.h"
 
 void
 bibtexout_initparams( param *p, const char *progname )
@@ -69,7 +69,7 @@ output_citekey( FILE *fp, fields *info, unsigned long refnum, int format_opts )
 	if ( n!=-1 ) {
 		p = info->data[n].data;
 		while ( p && *p && *p!='|' ) {
-			if ( format_opts & BIBOUT_STRICTKEY ) {
+			if ( format_opts & BIBL_FORMAT_BIBOUT_STRICTKEY ) {
 				if ( isdigit((unsigned char)*p) || (*p>='A' && *p<='Z') ||
 				     (*p>='a' && *p<='z' ) )
 					fprintf( fp, "%c", *p );
@@ -91,7 +91,7 @@ bibtexout_type( fields *info, char *filename, int refnum, param *p )
 	int type = TYPE_UNKNOWN, i, maxlevel, n, level;
 
 	/* determine bibliography type */
-	for ( i=0; i<info->nfields; ++i ) {
+	for ( i=0; i<info->n; ++i ) {
 		if ( strcasecmp( info->tag[i].data, "GENRE" ) &&
 		     strcasecmp( info->tag[i].data, "NGENRE" ) ) continue;
 		genre = info->data[i].data;
@@ -127,7 +127,7 @@ bibtexout_type( fields *info, char *filename, int refnum, param *p )
 			type = TYPE_ELECTRONIC;
 	}
 	if ( type==TYPE_UNKNOWN ) {
-		for ( i=0; i<info->nfields; ++i ) {
+		for ( i=0; i<info->n; ++i ) {
 			if ( strcasecmp( info->tag[i].data, "ISSUANCE" ) ) continue;
 			if ( !strcasecmp( info->data[i].data, "monographic" ) ) {
 				if ( info->level[i]==0 ) type = TYPE_BOOK;
@@ -186,7 +186,7 @@ output_type( FILE *fp, int type, int format_opts )
 		}
 	}
 	if ( !s ) s = types[ntypes-1].type_name; /* default to TYPE_MISC */
-	if ( !(format_opts & BIBOUT_UPPERCASE ) ) fprintf( fp, "@%s{", s );
+	if ( !(format_opts & BIBL_FORMAT_BIBOUT_UPPERCASE ) ) fprintf( fp, "@%s{", s );
 	else {
 		len = strlen( s );
 		fprintf( fp, "@" );
@@ -202,17 +202,17 @@ output_element( FILE *fp, char *tag, char *data, int format_opts )
 	int i, len, nquotes = 0;
 	char ch;
 	fprintf( fp, ",\n" );
-	if ( format_opts & BIBOUT_WHITESPACE ) fprintf( fp, "  " );
-	if ( !(format_opts & BIBOUT_UPPERCASE ) ) fprintf( fp, "%s", tag );
+	if ( format_opts & BIBL_FORMAT_BIBOUT_WHITESPACE ) fprintf( fp, "  " );
+	if ( !(format_opts & BIBL_FORMAT_BIBOUT_UPPERCASE ) ) fprintf( fp, "%s", tag );
 	else {
 		len = strlen( tag );
 		for ( i=0; i<len; ++i )
 			fprintf( fp, "%c", toupper((unsigned char)tag[i]) );
 	}
-	if ( format_opts & BIBOUT_WHITESPACE ) fprintf( fp, " = \t" );
+	if ( format_opts & BIBL_FORMAT_BIBOUT_WHITESPACE ) fprintf( fp, " = \t" );
 	else fprintf( fp, "=" );
 
-	if ( format_opts & BIBOUT_BRACKETS ) fprintf( fp, "{" );
+	if ( format_opts & BIBL_FORMAT_BIBOUT_BRACKETS ) fprintf( fp, "{" );
 	else fprintf( fp, "\"" );
 
 	len = strlen( data );
@@ -220,7 +220,7 @@ output_element( FILE *fp, char *tag, char *data, int format_opts )
 		ch = data[i];
 		if ( ch!='\"' ) fprintf( fp, "%c", ch );
 		else {
-			if ( format_opts & BIBOUT_BRACKETS || 
+			if ( format_opts & BIBL_FORMAT_BIBOUT_BRACKETS || 
 			    ( i>0 && data[i-1]=='\\' ) )
 				fprintf( fp, "\"" );
 			else {
@@ -232,7 +232,7 @@ output_element( FILE *fp, char *tag, char *data, int format_opts )
 		}
 	}
 
-	if ( format_opts & BIBOUT_BRACKETS ) fprintf( fp, "}" );
+	if ( format_opts & BIBL_FORMAT_BIBOUT_BRACKETS ) fprintf( fp, "}" );
 	else fprintf( fp, "\"" );
 }
 
@@ -258,7 +258,7 @@ output_simpleall( FILE *fp, fields *info, char *intag, char *outtag,
 		int format_opts )
 {
 	int i;
-	for ( i=0; i<info->nfields; ++i ) {
+	for ( i=0; i<info->n; ++i ) {
 		if ( strcasecmp( info->tag[i].data, intag ) ) continue;
 		output_and_use( fp, info, i, outtag, format_opts );
 	}
@@ -270,7 +270,7 @@ output_fileattach( FILE *fp, fields *info, int format_opts )
 	newstr data;
 	int i;
 	newstr_init( &data );
-	for ( i=0; i<info->nfields; ++i ) {
+	for ( i=0; i<info->n; ++i ) {
 		if ( strcasecmp( info->tag[i].data, "FILEATTACH" ) ) continue;
 		newstr_strcpy( &data, ":" );
 		newstr_newstrcat( &data, &(info->data[i]) );
@@ -314,7 +314,7 @@ output_people( FILE *fp, fields *info, unsigned long refnum, char *tag,
 
 	/* primary citation authors */
 	npeople = 0;
-	for ( i=0; i<info->nfields; ++i ) {
+	for ( i=0; i<info->n; ++i ) {
 		if ( level!=-1 && info->level[i]!=level ) continue;
 		person = ( strcasecmp( info->tag[i].data, tag ) == 0 );
 		corp   = ( strcasecmp( info->tag[i].data, ctag ) == 0 );
@@ -322,7 +322,7 @@ output_people( FILE *fp, fields *info, unsigned long refnum, char *tag,
 		if ( person || corp || asis ) {
 			if ( npeople==0 ) newstr_init( &allpeople );
 			else {
-				if ( format_opts & BIBOUT_WHITESPACE )
+				if ( format_opts & BIBL_FORMAT_BIBOUT_WHITESPACE )
 					newstr_strcat(&allpeople,"\n\t\tand ");
 				else newstr_strcat( &allpeople, "\nand " );
 			}
@@ -351,7 +351,7 @@ output_title( FILE *fp, fields *info, unsigned long refnum, char *bibtag, int le
 	newstr title;
 	int n1 = -1, n2 = -1;
 	/* Option is for short titles of journals */
-	if ( ( format_opts & BIBOUT_SHORTTITLE ) && level==1 ) {
+	if ( ( format_opts & BIBL_FORMAT_BIBOUT_SHORTTITLE ) && level==1 ) {
 		n1 = fields_find( info, "SHORTTITLE", level );
 		n2 = fields_find( info, "SHORTSUBTITLE", level );
 	}
@@ -381,14 +381,14 @@ output_date( FILE *fp, fields *info, unsigned long refnum, int format_opts )
 	char *months[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", 
 		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
 	int n, month;
-	n = fields_find( info, "YEAR", -1 );
-	if ( n==-1 ) n = fields_find( info, "PARTYEAR", -1 );
+	n = fields_find( info, "DATE:YEAR", -1 );
+	if ( n==-1 ) n = fields_find( info, "PARTDATE:YEAR", -1 );
 	if ( n!=-1 ) {
 		output_element( fp, "year", info->data[n].data, format_opts );
 		fields_setused( info, n );
 	}
-	n = fields_find( info, "MONTH", -1 );
-	if ( n==-1 ) n = fields_find( info, "PARTMONTH", -1 );
+	n = fields_find( info, "DATE:MONTH", -1 );
+	if ( n==-1 ) n = fields_find( info, "PARTDATE:MONTH", -1 );
 	if ( n!=-1 ) {
 		month = atoi( info->data[n].data );
 		if ( month>0 && month<13 )
@@ -397,8 +397,8 @@ output_date( FILE *fp, fields *info, unsigned long refnum, int format_opts )
 			output_element( fp, "month", info->data[n].data, format_opts );
 		fields_setused( info, n );
 	}
-	n = fields_find( info, "DAY", -1 );
-	if ( n==-1 ) n = fields_find( info, "PARTDAY", -1 );
+	n = fields_find( info, "DATE:DAY", -1 );
+	if ( n==-1 ) n = fields_find( info, "PARTDATE:DAY", -1 );
 	if ( n!=-1 ) {
 		output_element( fp, "day", info->data[n].data, format_opts );
 		fields_setused( info, n );
@@ -469,8 +469,8 @@ output_pages( FILE *fp, fields *info, unsigned long refnum, int format_opts )
 {
 	newstr pages;
 	int sn, en;
-	sn = fields_find( info, "PAGESTART", -1 );
-	en = fields_find( info, "PAGEEND", -1 );
+	sn = fields_find( info, "PAGES:START", -1 );
+	en = fields_find( info, "PAGES:STOP", -1 );
 	if ( sn==-1 && en==-1 ) {
 		output_articlenumber( fp, info, refnum, format_opts );
 		return;
@@ -481,7 +481,7 @@ output_pages( FILE *fp, fields *info, unsigned long refnum, int format_opts )
 		fields_setused( info, sn );
 	}
 	if ( sn!=-1 && en!=-1 ) {
-		if ( format_opts & BIBOUT_SINGLEDASH ) 
+		if ( format_opts & BIBL_FORMAT_BIBOUT_SINGLEDASH ) 
 			newstr_strcat( &pages, "-" );
 		else
 			newstr_strcat( &pages, "--" );
@@ -543,7 +543,7 @@ bibtexout_write( fields *info, FILE *fp, param *p, unsigned long refnum )
 	fields_clearused( info );
 	type = bibtexout_type( info, "", refnum, p );
 	output_type( fp, type, p->format_opts );
-	if ( !( p->format_opts & BIBOUT_DROPKEY ) )
+	if ( !( p->format_opts & BIBL_FORMAT_BIBOUT_DROPKEY ) )
 		output_citekey( fp, info, refnum, p->format_opts );
 	output_people( fp, info, refnum, "AUTHOR", "AUTHOR:CORP", "AUTHOR:ASIS", "author", 0,
 		p->format_opts );
@@ -601,7 +601,7 @@ bibtexout_write( fields *info, FILE *fp, param *p, unsigned long refnum )
 	output_pmid( fp, info, p->format_opts );
 	output_jstor( fp, info, p->format_opts );
 	output_simple( fp, info, "LANGUAGE", "language", p->format_opts );
-	if ( p->format_opts & BIBOUT_FINALCOMMA ) fprintf( fp, "," );
+	if ( p->format_opts & BIBL_FORMAT_BIBOUT_FINALCOMMA ) fprintf( fp, "," );
 	fprintf( fp, "\n}\n\n" );
 	fflush( fp );
 }
diff --git a/lib/name.c b/lib/name.c
index 010387c..9dfbde1 100644
--- a/lib/name.c
+++ b/lib/name.c
@@ -3,7 +3,7 @@
  *
  * mangle names w/ and w/o commas
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Source code released under the GPL version 2
  *
@@ -369,7 +369,7 @@ name_addmultielement( fields *info, char *tag, list *tokens, int begin, int end,
 	newstr_init( &name );
 
 	name_construct_multi( &name, tokens, begin, end );
-	status = fields_add( info, tag, name.data, level );
+	status = fields_add_can_dup( info, tag, name.data, level );
 	if ( status!=FIELDS_OK ) ok = 0;
 
 	newstr_free( &name );
@@ -393,7 +393,7 @@ name_addsingleelement( fields *info, char *tag, char *name, int level, int corp
 	newstr_strcpy( &outtag, tag );
 	if ( !corp ) newstr_strcat( &outtag, ":ASIS" );
 	else newstr_strcat( &outtag, ":CORP" );
-	status = fields_add( info, outtag.data, name, level );
+	status = fields_add_can_dup( info, outtag.data, name, level );
 	if ( status!=FIELDS_OK ) ok = 0;
 	newstr_free( &outtag );
 	return ok;
@@ -505,7 +505,7 @@ name_add( fields *info, char *tag, char *q, int level, list *asis, list *corps )
 		if ( !nametype ) { ret = 0; goto out; }
 
 		if ( nametype==1 ) {
-			status = fields_add( info, tag, outname.data, level );
+			status = fields_add_can_dup( info, tag, outname.data, level );
 			ok = ( status==FIELDS_OK ) ? 1 : 0;
 		}
 		else if ( nametype==2 )
diff --git a/lib/name.h b/lib/name.h
index f43a49d..a1867f1 100644
--- a/lib/name.h
+++ b/lib/name.h
@@ -3,7 +3,7 @@
  *
  * mangle names w/ and w/o commas
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/lib/nbibin.c b/lib/nbibin.c
new file mode 100644
index 0000000..e6ad0d6
--- /dev/null
+++ b/lib/nbibin.c
@@ -0,0 +1,482 @@
+/*
+ * nbibin.c
+ *
+ * Copyright (c) Chris Putnam 2016
+ *
+ * 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 "newstr.h"
+#include "newstr_conv.h"
+#include "fields.h"
+#include "name.h"
+#include "title.h"
+#include "url.h"
+#include "serialno.h"
+#include "reftypes.h"
+#include "bibformats.h"
+#include "generic.h"
+
+extern variants nbib_all[];
+extern int nbib_nall;
+
+/*****************************************************
+ PUBLIC: void nbib_initparams()
+*****************************************************/
+
+static int nbib_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );
+static int nbib_processf( fields *nbib, char *p, char *filename, long nref, param *pm );
+static int nbib_typef( fields *nbib, char *filename, int nref, param *p );
+static int nbib_convertf( fields *nbib, fields *info, int reftype, param *p );
+
+void
+nbibin_initparams( param *p, const char *progname )
+{
+	p->readformat       = BIBL_NBIBIN;
+	p->charsetin        = BIBL_CHARSET_DEFAULT;
+	p->charsetin_src    = BIBL_SRC_DEFAULT;
+	p->latexin          = 0;
+	p->xmlin            = 0;
+	p->utf8in           = 0;
+	p->nosplittitle     = 0;
+	p->verbose          = 0;
+	p->addcount         = 0;
+	p->output_raw       = 0;
+
+	p->readf    = nbib_readf;
+	p->processf = nbib_processf;
+	p->cleanf   = NULL;
+	p->typef    = nbib_typef;
+	p->convertf = nbib_convertf;
+	p->all      = nbib_all;
+	p->nall     = nbib_nall;
+
+	list_init( &(p->asis) );
+	list_init( &(p->corps) );
+
+	if ( !progname ) p->progname = NULL;
+	else p->progname = strdup( progname );
+}
+
+/*****************************************************
+ PUBLIC: int nbib_readf()
+*****************************************************/
+
+/* RIS definition of a tag is strict:
+    character 1 = uppercase alphabetic character
+    character 2 = uppercase alphabetic character
+    character 3 = character or space (ansi 32)
+    character 4 = character or space (ansi 32)
+    character 5 = dash (ansi 45)
+    character 6 = space (ansi 32)
+*/
+static int
+is_upperchar( char c )
+{
+	if ( c>='A' && c<='Z' ) return 1;
+	else return 0;
+}
+
+static int
+is_upperchar_space( char c )
+{
+	if ( c==' ' ) return 1;
+	if ( c>='A' && c<='Z' ) return 1;
+	else return 0;
+}
+
+static int
+nbib_istag( char *buf )
+{
+	if ( !is_upperchar( buf[0] ) ) return 0;
+	if ( !is_upperchar( buf[1] ) ) return 0;
+	if ( !is_upperchar_space( buf[2] ) ) return 0;
+	if ( !is_upperchar_space( buf[3] ) ) return 0;
+	if (buf[4]!='-') return 0;
+	if (buf[5]!=' ') return 0;
+	return 1;
+}
+
+static int
+readmore( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line )
+{
+	if ( line->len ) return 1;
+	else return newstr_fget( fp, buf, bufsize, bufpos, line );
+}
+
+static int
+skip_utf8_bom( newstr *line, int *fcharset )
+{
+	unsigned char *up;
+
+	if ( line->len < 3 ) return 0;
+
+	up = ( unsigned char *) newstr_cstr( line );
+	if ( up[0]==0xEF && up[1]==0xBB && up[2]==0xBF ) {
+		*fcharset = CHARSET_UNICODE;
+		return 3;
+	}
+
+	return 0;
+}
+
+static int
+nbib_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, 
+		newstr *reference, int *fcharset )
+{
+	int n, haveref = 0, inref = 0, readtoofar = 0;
+	char *p;
+
+	*fcharset = CHARSET_UNKNOWN;
+
+	while ( !haveref && readmore( fp, buf, bufsize, bufpos, line ) ) {
+
+		/* ...references are terminated by an empty line */
+		if ( !line->data || line->len==0 ) {
+			if ( reference->len ) haveref = 1;
+			continue;
+		}
+
+		/* ...recognize and skip over UTF8 BOM */
+		n = skip_utf8_bom( line, fcharset );
+		p = &( line->data[n] );
+
+		/* Each reference starts with 'PMID- ' && ends with blank line */
+		if ( strncmp(p,"PMID- ",6)==0 ) {
+			if ( !inref ) {
+				inref = 1;
+			} else {
+				/* we've read too far.... */
+				readtoofar = 1;
+				inref = 0;
+			}
+		}
+		if ( nbib_istag( p ) ) {
+			if ( !inref ) {
+				fprintf(stderr,"Warning.  Tagged line not "
+					"in properly started reference.\n");
+				fprintf(stderr,"Ignored: '%s'\n", p );
+			} else if ( !strncmp(p,"ER  -",5) ) {
+				inref = 0;
+			} else {
+				newstr_addchar( reference, '\n' );
+				newstr_strcat( reference, p );
+			}
+		}
+		/* not a tag, but we'll append to last values ...*/
+		else if ( inref && strlen( p ) >= 6 ) {
+			newstr_strcat( reference, p+5 );
+		}
+		if ( !readtoofar ) newstr_empty( line );
+	}
+	if ( inref ) haveref = 1;
+	return haveref;
+}
+
+/*****************************************************
+ PUBLIC: int nbib_processf()
+*****************************************************/
+
+static char*
+process_line2( newstr *tag, newstr *data, char *p )
+{
+	while ( *p==' ' || *p=='\t' ) p++;
+	while ( *p && *p!='\r' && *p!='\n' )
+		newstr_addchar( data, *p++ );
+	while ( *p=='\r' || *p=='\n' ) p++;
+	return p;
+}
+
+static char*
+process_line( newstr *tag, newstr *data, char *p )
+{
+	int i;
+
+	i = 0;
+	while ( i<6 && *p ) {
+		if ( *p!=' ' && *p!='-' ) newstr_addchar( tag, *p );
+		p++;
+		i++;
+	}
+	while ( *p==' ' || *p=='\t' ) p++;
+	while ( *p && *p!='\r' && *p!='\n' )
+		newstr_addchar( data, *p++ );
+	newstr_trimendingws( data );
+	while ( *p=='\n' || *p=='\r' ) p++;
+	return p;
+}
+
+static int
+nbib_processf( fields *nbib, char *p, char *filename, long nref, param *pm )
+{
+	newstr tag, data;
+	int status, n;
+
+	newstrs_init( &tag, &data, NULL );
+
+	while ( *p ) {
+		if ( nbib_istag( p ) )
+			p = process_line( &tag, &data, p );
+		/* no anonymous fields allowed */
+		if ( tag.len ) {
+			status = fields_add( nbib, tag.data, data.data, 0 );
+			if ( status!=FIELDS_OK ) return 0;
+		} else {
+			p = process_line2( &tag, &data, p );
+			n = fields_num( nbib );
+			if ( data.len && n>0 ) {
+				newstr *od;
+				od = fields_value( nbib, n-1, FIELDS_STRP );
+				newstr_addchar( od, ' ' );
+				newstr_strcat( od, data.data );
+			}
+		}
+		newstrs_empty( &tag, &data, NULL );
+	}
+
+	newstrs_free( &tag, &data, NULL );
+	return 1;
+}
+
+/*****************************************************
+ PUBLIC: int nbib_typef()
+*****************************************************/
+
+/*
+ * PT  - Case Reports
+ * PT  - Journal Article
+ * PT  - Research Support, N.I.H., Extramural
+ * PT  - Review
+ */
+static int
+nbib_typef( fields *nbib, char *filename, int nref, param *p )
+{
+	int i, reftype, nrefname, is_default;
+	char *typename, *refname = "";
+	vplist a;
+
+	nrefname  = fields_find( nbib, "PMID", LEVEL_MAIN );
+	if ( nrefname!=-1 ) refname = fields_value( nbib, nrefname, FIELDS_CHRP_NOUSE );
+
+	vplist_init( &a );
+
+	fields_findv_each( nbib, LEVEL_MAIN, FIELDS_CHRP_NOUSE, &a, "PT" );
+	is_default = 1;
+	for ( i=0; i<a.n; ++i ) {
+		typename = vplist_get( &a, i );
+		reftype  = get_reftype( typename, nref, p->progname, p->all, p->nall, refname, &is_default, REFTYPE_SILENT );
+		if ( !is_default ) break;
+	}
+
+	if ( a.n==0 )
+		reftype = get_reftype( "", nref, p->progname, p->all, p->nall, refname, &is_default, REFTYPE_CHATTY );
+	else if ( is_default ) {
+                if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
+                fprintf( stderr, "Did not recognize type of refnum %d (%s).\n"
+                        "\tDefaulting to %s.\n", nref, refname, p->all[0].type );
+	}
+
+	vplist_free( &a );
+
+	return reftype;
+}
+
+/*****************************************************
+ PUBLIC: int nbib_convertf()
+*****************************************************/
+
+/* PB  - 2016 May 7 */
+
+static int
+nbibin_date( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
+{
+	int fstatus, status = BIBL_OK;
+	newstr s;
+	char *p;
+
+	p = newstr_cstr( invalue );
+	if ( !p ) return status;
+
+	newstr_init( &s );
+
+	/* ...handle year */
+	while ( *p && !is_ws( *p ) ) {
+		newstr_addchar( &s, *p );
+		p++;
+	}
+	if ( s.len ) {
+		fstatus = fields_add( bibout, "DATE:YEAR", newstr_cstr( &s ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) {
+			status = BIBL_ERR_MEMERR;
+			goto out;
+		}
+	}
+
+	/* ...handle month */
+	newstr_empty( &s );
+	while ( is_ws( *p ) ) p++;
+	while ( *p && !is_ws( *p ) ) {
+		newstr_addchar( &s, *p );
+		p++;
+	}
+	if ( s.len ) {
+		fstatus = fields_add( bibout, "DATE:MONTH", newstr_cstr( &s ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) {
+			status = BIBL_ERR_MEMERR;
+			goto out;
+		}
+	}
+
+	/* ...handle day */
+	newstr_empty( &s );
+	while ( is_ws( *p ) ) p++;
+	while ( *p && !is_ws( *p ) ) {
+		newstr_addchar( &s, *p );
+		p++;
+	}
+	if ( s.len ) {
+		fstatus = fields_add( bibout, "DATE:DAY", newstr_cstr( &s ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) {
+			status = BIBL_ERR_MEMERR;
+			goto out;
+		}
+	}
+
+out:
+	newstr_free( &s );
+
+	return status;
+}
+
+/* the LID and AID fields that can be doi's or pii's */
+static int
+nbibin_doi( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
+{
+	int fstatus, status = BIBL_OK;
+	char *id, *type, *usetag="";
+	list tokens;
+
+	list_init( &tokens );
+
+	list_tokenize( &tokens, invalue, " ", 1 );
+
+	if ( tokens.n == 2 ) {
+		id   = list_getc( &tokens, 0 );
+		type = list_getc( &tokens, 1 );
+		if ( !strcmp( type, "[doi]" ) ) usetag = "DOI";
+		else if ( !strcmp( type, "[pii]" ) ) usetag = "PII";
+		if ( strlen( outtag ) > 0 ) {
+			fstatus = fields_add( bibout, usetag, id, LEVEL_MAIN );
+			if ( fstatus!=FIELDS_OK ) {
+				status = BIBL_ERR_MEMERR;
+				goto out;
+			}
+		}
+	}
+out:
+	list_free( &tokens );
+	return status;
+}
+
+static int
+nbibin_pages( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
+{
+	int fstatus, status = BIBL_OK;
+	newstr sp, tmp, ep;
+	char *p;
+	int i;
+
+	p = newstr_cstr( invalue );
+	if ( !p ) return BIBL_OK;
+
+	newstr_init( &sp );
+	newstr_init( &tmp );
+	newstr_init( &ep );
+
+	while ( *p && *p!='-' ) {
+		newstr_addchar( &sp, *p );
+		p++;
+	}
+
+	while ( *p=='-' ) p++;
+
+	while ( *p ) {
+		newstr_addchar( &tmp, *p );
+		p++;
+	}
+
+	if ( sp.len ) {
+		fstatus = fields_add( bibout, "PAGES:START", newstr_cstr( &sp ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) {
+			status = BIBL_ERR_MEMERR;
+			goto out;
+		}
+	}
+
+	if ( tmp.len ) {
+		for ( i=0; i<sp.len - tmp.len; ++i )
+			newstr_addchar( &ep, sp.data[i] );
+		newstr_newstrcat( &ep, &tmp );
+
+		fstatus = fields_add( bibout, "PAGES:STOP", newstr_cstr( &ep ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) {
+			status = BIBL_ERR_MEMERR;
+			goto out;
+		}
+	}
+out:
+	newstr_free( &sp );
+	newstr_free( &tmp );
+	newstr_free( &ep );
+	return status;
+}
+
+static void
+nbib_report_notag( param *p, char *tag )
+{
+	if ( p->verbose && strcmp( tag, "TY" ) ) {
+		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
+		fprintf( stderr, "Did not identify NBIB tag '%s'\n", tag );
+	}
+}
+
+static int
+nbib_convertf( fields *bibin, fields *bibout, int reftype, param *p )
+{
+	static int (*convertfns[NUM_REFTYPES])(fields *, int i, newstr *, newstr *, int, param *, char *, fields *) = {
+		[ 0 ... NUM_REFTYPES-1 ] = generic_null,
+		[ SIMPLE       ] = generic_simple,
+		[ TITLE        ] = generic_title,
+		[ PERSON       ] = generic_person,
+		[ SKIP         ] = generic_skip,
+		[ DATE         ] = nbibin_date,
+		[ PAGES        ] = nbibin_pages,
+		[ DOI          ] = nbibin_doi,
+        };
+	int process, level, i, nfields, status = BIBL_OK;
+	newstr *intag, *invalue;
+	char *outtag;
+
+	nfields = fields_num( bibin );
+
+	for ( i=0; i<nfields; ++i ) {
+		intag = fields_tag( bibin, i, FIELDS_STRP );
+		if ( !translate_oldtag( intag->data, reftype, p->all, p->nall, &process, &level, &outtag ) ) {
+			nbib_report_notag( p, intag->data );
+			continue;
+		}
+		invalue = fields_value( bibin, i, FIELDS_STRP );
+
+		status = convertfns[ process ] ( bibin, i, intag, invalue, level, p, outtag, bibout );
+		if ( status!=BIBL_OK ) return status;
+	}
+
+	if ( status==BIBL_OK && p->verbose ) fields_report( bibout, stderr );
+
+	return status;
+}
diff --git a/lib/nbibtypes.c b/lib/nbibtypes.c
new file mode 100644
index 0000000..55ec8ce
--- /dev/null
+++ b/lib/nbibtypes.c
@@ -0,0 +1,68 @@
+/*
+ * nbibtypes.c
+ *
+ * Copyright (c) Chris Putnam 2016
+ *
+ * Program and source code released under the GPL version 2
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include "is_ws.h"
+#include "fields.h"
+#include "reftypes.h"
+
+static lookups article[] = {
+	{ "PMID",   "PMID",               SIMPLE, LEVEL_MAIN },
+	{ "OWN",    "",                   SKIP,   LEVEL_MAIN },
+	{ "STAT",   "",                   SKIP,   LEVEL_MAIN },
+	{ "DA",     "",                   SKIP,   LEVEL_MAIN },
+	{ "DCOM",   "",                   SKIP,   LEVEL_MAIN },
+	{ "LR",     "",                   SKIP,   LEVEL_MAIN },
+	{ "IS",     "",                   SKIP,   LEVEL_MAIN },
+	{ "VI",     "VOLUME",             SIMPLE, LEVEL_MAIN },
+	{ "IP",     "ISSUE",              SIMPLE, LEVEL_MAIN },
+	{ "DP",     "",                   DATE,   LEVEL_MAIN }, /* date published? */
+	{ "TI",     "TITLE",              TITLE,  LEVEL_MAIN },
+	{ "PG",     "PAGES",              PAGES,  LEVEL_MAIN },
+	{ "LID",    "DOI",                DOI,    LEVEL_MAIN }, /* linking ID? -- can be DOI/PII */
+	{ "AB",     "ABSTRACT",           SIMPLE, LEVEL_MAIN },
+	{ "FAU",    "AUTHOR",             PERSON, LEVEL_MAIN },
+	{ "AU",     "",                   SKIP,   LEVEL_MAIN },
+	{ "AD",     "",                   SKIP,   LEVEL_MAIN },
+	{ "LA",     "",                   SKIP,   LEVEL_MAIN },
+	{ "GR",     "",                   SKIP,   LEVEL_MAIN },
+	{ "DEP",    "",                   SKIP,   LEVEL_MAIN }, /* a date */
+	{ "PL",     "ADDRESS",            SIMPLE, LEVEL_MAIN }, /* Publisher location */
+	{ "TA",     "SHORTTITLE",         SIMPLE, LEVEL_HOST }, /* Journal title abbreviation */
+	{ "JT",     "TITLE",              SIMPLE, LEVEL_HOST }, /* Journal title */
+	{ "JID",    "",                   SKIP,   LEVEL_HOST }, /* Journal ID? */
+	{ "SB",     "",                   SKIP,   LEVEL_MAIN },
+	{ "PMC",    "PMC",                SIMPLE, LEVEL_MAIN },
+	{ "OID",    "",                   SKIP,   LEVEL_MAIN },
+	{ "EDAT",   "",                   SKIP,   LEVEL_MAIN },
+	{ "MHDA",   "",                   SKIP,   LEVEL_MAIN },
+	{ "CRDT",   "",                   SKIP,   LEVEL_MAIN },
+	{ "PHST",   "",                   SKIP,   LEVEL_MAIN }, /* Publication history? */
+	{ "AID",    "DOI",                DOI,    LEVEL_MAIN }, /* Article ID? -- can be DOI/PII */
+	{ "PST",    "",                   SKIP,   LEVEL_MAIN },
+	{ "SO",     "",                   SKIP,   LEVEL_MAIN },
+	{ " ",      "INTERNAL_TYPE|ARTICLE",  ALWAYS, LEVEL_MAIN },
+	{ " ",      "ISSUANCE|continuing",    ALWAYS, LEVEL_HOST },
+	{ " ",      "RESOURCE|text",          ALWAYS, LEVEL_MAIN },
+	{ " ",      "GENRE|journal article",  ALWAYS, LEVEL_MAIN },
+	{ " ",      "GENRE|periodical",       ALWAYS, LEVEL_HOST },
+	{ " ",      "GENRE|academic journal", ALWAYS, LEVEL_HOST }
+};
+
+#define ORIG(a) ( &(a[0]) )
+#define SIZE(a) ( sizeof( a ) / sizeof( lookups ) )
+#define REFTYPE(a,b) { a, ORIG(b), SIZE(b) }
+
+variants nbib_all[] = {
+	REFTYPE( "Journal article", article ),
+	REFTYPE( "News",            article ),
+};
+
+int nbib_nall = sizeof( nbib_all ) / sizeof( variants );
+
diff --git a/lib/newstr.c b/lib/newstr.c
index f5cf1f4..354e16c 100644
--- a/lib/newstr.c
+++ b/lib/newstr.c
@@ -1,9 +1,9 @@
 /*
  * newstr.c
  *
- * Version: 04/27/14
+ * Version: 04/17/15
  *
- * Copyright (c) Chris Putnam 1999-2015
+ * Copyright (c) Chris Putnam 1999-2016
  *
  * Source code released under the GPL version 2
  *
@@ -228,6 +228,13 @@ newstrs_empty( newstr *s, ... )
 	va_end( ap );
 }
 
+char *
+newstr_cstr( newstr *s )
+{
+	assert( s );
+	return s->data;
+}
+
 void
 newstr_addchar( newstr *s, char newchar )
 {
@@ -241,6 +248,21 @@ newstr_addchar( newstr *s, char newchar )
 	s->data[s->len] = '\0';
 }
 
+void
+newstr_fill( newstr *s, unsigned long n, char fillchar )
+{
+	unsigned long i;
+	assert( s );
+	if ( !s->data || s->dim==0 )
+		newstr_initalloc( s, n+1 );
+	if ( n + 1 > s->dim )
+		newstr_realloc( s, n+1 );
+	for ( i=0; i<n; ++i )
+		s->data[i] = fillchar;
+	s->data[n] = '\0';
+	s->len = n;
+}
+
 /* newstr_addutf8
  *
  * Add potential multibyte character to s starting at pointer p.
@@ -328,10 +350,10 @@ newstr_strcat( newstr *s, const char *addstr )
 }
 
 void
-newstr_segcat( newstr *s, char *startat, char *endat )
+newstr_segcat( newstr *s, const char *startat, const char *endat )
 {
 	unsigned long n;
-	char *p;
+	const char *p;
 
 	assert( s && startat && endat );
 	assert( (size_t) startat < (size_t) endat );
@@ -349,6 +371,13 @@ newstr_segcat( newstr *s, char *startat, char *endat )
 }
 
 void
+newstr_plcat( newstr *s, const char *startat, unsigned long n )
+{
+	assert( s && startat );
+	newstr_strcat_internal( s, startat, n );
+}
+
+void
 newstr_indxcat( newstr *s, char *p, unsigned long start, unsigned long stop )
 {
 	unsigned long i;
@@ -382,7 +411,7 @@ newstr_cattodelim( newstr *s, char *p, const char *delim, unsigned char finalste
 		newstr_addchar( s, *p );
 		p++;
 	}
-	if ( *p && finalstep ) p++;
+	if ( p && *p && finalstep ) p++;
 	return p;
 }
 
@@ -428,19 +457,14 @@ newstr_strcpy( newstr *s, const char *addstr )
  * copies [start,end) into s
  */
 void
-newstr_segcpy( newstr *s, char *startat, char *endat )
+newstr_segcpy( newstr *s, const char *startat, const char *endat )
 {
 	unsigned long n;
-	char *p;
+	const 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 ) {
@@ -451,6 +475,13 @@ newstr_segcpy( newstr *s, char *startat, char *endat )
 	newstr_strcpy_internal( s, startat, n );
 }
 
+void
+newstr_plcpy( newstr *s, const char *startat, unsigned long n )
+{
+	assert( s && startat );
+	newstr_strcpy_internal( s, startat, n );
+}
+
 /*
  * newstr_indxcpy( s, in, start, stop );
  *
diff --git a/lib/newstr.h b/lib/newstr.h
index 343b907..5e2d275 100644
--- a/lib/newstr.h
+++ b/lib/newstr.h
@@ -1,9 +1,9 @@
 /*
  * newstr.h
  *
- * Version: 04/27/14
+ * Version: 04/17/15
  *
- * Copyright (c) Chris Putnam 1999-2015
+ * Copyright (c) Chris Putnam 1999-2016
  *
  * Source code released under the GPL version 2
  *
@@ -22,45 +22,50 @@ typedef struct newstr {
 newstr *newstr_new         ( void ); 
 void    newstr_delete      ( newstr *s );
 
-void    newstr_init        ( newstr *s );
-void    newstr_initstr     ( newstr *s, const char *initstr );
-void    newstr_empty       ( newstr *s );
-void    newstr_free        ( newstr *s );
-
-void    newstrs_init       ( newstr *s, ... );
-void    newstrs_empty      ( newstr *s, ... );
-void    newstrs_free       ( newstr *s, ... );
-
-void newstr_mergestrs   ( newstr *s, ... );
-newstr *newstr_strdup   ( const char *p );
-void newstr_addchar     ( newstr *s, char newchar );
-void newstr_reverse     ( newstr *s );
-const char *newstr_addutf8    ( newstr *s, const char *p );
-void newstr_strcat      ( newstr *s, const char *addstr );
-void newstr_newstrcat   ( newstr *s, newstr *old );
-void newstr_segcat      ( newstr *s, char *startat, char *endat );
-char *newstr_cpytodelim  ( newstr *s, char *p, const char *delim, unsigned char finalstep );
-char *newstr_cattodelim  ( newstr *s, char *p, const char *delim, unsigned char finalstep );
-void newstr_prepend     ( newstr *s, const char *addstr );
-void newstr_strcpy      ( newstr *s, const char *addstr );
-void newstr_newstrcpy   ( newstr *s, newstr *old );
-void newstr_segcpy      ( newstr *s, char *startat, char *endat );
-void newstr_segdel      ( newstr *s, char *startat, char *endat );
-void newstr_indxcpy     ( newstr *s, char *p, unsigned long start, unsigned long stop );
-void newstr_indxcat     ( newstr *s, char *p, unsigned long start, unsigned long stop );
-void newstr_fprintf     ( FILE *fp, newstr *s );
-int  newstr_fget        ( FILE *fp, char *buf, int bufsize, int *pbufpos,
-                          newstr *outs );
-char newstr_char        ( newstr *s, unsigned long n );
-char newstr_revchar     ( newstr *s, unsigned long n );
-int  newstr_fgetline    ( newstr *s, FILE *fp );
-int  newstr_findreplace ( newstr *s, const char *find, const char *replace );
-void newstr_toupper     ( newstr *s );
-void newstr_tolower     ( newstr *s );
-void newstr_trimstartingws( newstr *s );
-void newstr_trimendingws( newstr *s );
-void newstr_swapstrings ( newstr *s1, newstr *s2 );
-void newstr_stripws     ( newstr *s );
+void     newstr_init      ( newstr *s );
+void     newstr_initstr   ( newstr *s, const char *initstr );
+void     newstr_empty     ( newstr *s );
+void     newstr_free      ( newstr *s );
+newstr * newstr_strdup    ( const char *p );
+
+void     newstrs_init     ( newstr *s, ... );
+void     newstrs_empty    ( newstr *s, ... );
+void     newstrs_free     ( newstr *s, ... );
+
+char *   newstr_cstr      ( newstr *s );
+
+void     newstr_mergestrs ( newstr *s, ... );
+void     newstr_fill      ( newstr *s, unsigned long n, char fillchar );
+void     newstr_addchar   ( newstr *s, char newchar );
+void     newstr_reverse   ( newstr *s );
+void     newstr_strcat    ( newstr *s, const char *addstr );
+void     newstr_newstrcat ( newstr *s, newstr *old );
+void     newstr_segcat    ( newstr *s, const char *startat, const char *endat );
+void     newstr_plcat     ( newstr *s, const char *startat, unsigned long n );
+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, const char *startat, const char *endat );
+void     newstr_plcpy     ( newstr *s, const char *startat, unsigned long n );
+void     newstr_segdel    ( newstr *s, char *startat, char *endat );
+void     newstr_indxcpy   ( newstr *s, char *p, unsigned long start, unsigned long stop );
+void     newstr_indxcat   ( newstr *s, char *p, unsigned long start, unsigned long stop );
+void     newstr_fprintf   ( FILE *fp, newstr *s );
+int      newstr_fget      ( FILE *fp, char *buf, int bufsize, int *pbufpos, newstr *outs );
+char     newstr_char      ( newstr *s, unsigned long n );
+char     newstr_revchar   ( newstr *s, unsigned long n );
+int      newstr_fgetline  ( newstr *s, FILE *fp );
+void     newstr_toupper   ( newstr *s );
+void     newstr_tolower   ( newstr *s );
+int      newstr_findreplace( newstr *s, const char *find, const char *replace );
+void     newstr_trimstartingws( newstr *s );
+void     newstr_trimendingws( newstr *s );
+void     newstr_swapstrings( newstr *s1, newstr *s2 );
+void     newstr_stripws   ( newstr *s );
+
+const char *newstr_addutf8( newstr *s, const char *p );
 
 int  newstr_match_first ( newstr *s, char ch );
 int  newstr_match_end   ( newstr *s, char ch );
diff --git a/lib/newstr_conv.c b/lib/newstr_conv.c
index 40a5b2b..1b4532f 100644
--- a/lib/newstr_conv.c
+++ b/lib/newstr_conv.c
@@ -1,7 +1,7 @@
 /*
  * newstr_conv.c
  *
- * Copyright (c) Chris Putnam 1999-2015
+ * Copyright (c) Chris Putnam 1999-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/lib/newstr_conv.h b/lib/newstr_conv.h
index 00669e9..5e9a648 100644
--- a/lib/newstr_conv.h
+++ b/lib/newstr_conv.h
@@ -1,7 +1,7 @@
 /*
  * newstring_conv.h
  *
- * Copyright (c) Chris Putnam 1999-2015
+ * Copyright (c) Chris Putnam 1999-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/lib/notes.c b/lib/notes.c
new file mode 100644
index 0000000..8409899
--- /dev/null
+++ b/lib/notes.c
@@ -0,0 +1,97 @@
+/*
+ * notes.c
+ */
+#include <string.h>
+#include "url.h"
+#include "notes.h"
+
+/*
+ * notes are mostly directly copies; however, lots of formats hide
+ * URLs/DOIs in the notes fields. For example:
+ *
+ * For RIS, Oxford Journals hides DOI in the N1 field.
+ * For Endnote, Wiley hides DOI in the %1 field.
+ * etc.
+ */
+
+typedef struct url_t {
+	char *prefix;
+	char *tag;
+	int offset;
+} url_t;
+
+static void
+notes_added_url( fields *bibout, newstr *invalue, int level, int *ok )
+{
+	url_t prefixes[] = {
+		{ "arXiv:",                                    "ARXIV",     6 },
+		{ "http://arxiv.org/abs/",                     "ARXIV",    21 },
+		{ "jstor:",                                    "JSTOR",     6 },
+		{ "http://www.jstor.org/stable/",              "JSTOR",    28 },
+		{ "medline:",                                  "MEDLINE",   8 },
+		{ "pubmed:",                                   "PMID",      7 },
+		{ "http://www.ncbi.nlm.nih.gov/pubmed/",       "PMID",     35 },
+		{ "http://www.ncbi.nlm.nih.gov/pmc/articles/", "PMC",      41 },
+		{ "http://dx.doi.org/",                        "DOI",      19 },
+		{ "isi:",                                      "ISIREFNUM", 4 },
+	};
+	int nprefixes = sizeof( prefixes ) / sizeof( prefixes[0] );
+
+	char *p = invalue->data;
+	char *tag = "URL";
+	int fstatus;
+	int i;
+
+	/* bibtex/biblatex-specific */
+	if ( !strncasecmp( p, "\\urllink", 8 ) ) p += 8;
+	if ( !strncasecmp( p, "\\url", 4 ) ) p += 4;
+
+	for ( i=0; i<nprefixes; ++i ) {
+		if ( !strncasecmp( p, prefixes[i].prefix, prefixes[i].offset ) ) {
+			tag = prefixes[i].tag;
+			p   = p + prefixes[i].offset;
+			break;
+		}
+	}
+
+	fstatus = fields_add( bibout, tag, p, level );
+
+	if ( fstatus==FIELDS_OK ) *ok = 1;
+	else *ok = 0;
+}
+
+static int
+notes_added_doi( fields *bibout, newstr *invalue, int level, int *ok )
+{
+	int doi, fstatus;
+
+	doi = is_doi( invalue->data );
+
+	if ( doi != -1 ) {
+		fstatus = fields_add( bibout, "DOI", &(invalue->data[doi]), level );
+		if ( fstatus != FIELDS_OK ) *ok = 0;
+		return 1;
+	}
+
+	else return 0;
+}
+
+int
+notes_add( fields *bibout, newstr *invalue, int level )
+{
+	int fstatus, done = 0, ok = 1;
+
+	if ( !is_embedded_link( invalue->data ) ) {
+		fstatus = fields_add( bibout, "NOTES", invalue->data, level );
+		if ( fstatus != FIELDS_OK ) ok = 0;
+	}
+
+	else {
+
+		done = notes_added_doi( bibout, invalue, level, &ok );
+		if ( !done ) notes_added_url( bibout, invalue, level, &ok );
+
+	}
+
+	return ok;
+}
diff --git a/lib/notes.h b/lib/notes.h
new file mode 100644
index 0000000..e6dbdbd
--- /dev/null
+++ b/lib/notes.h
@@ -0,0 +1,17 @@
+/*
+ * notes.h
+ *
+ * Copyright (c) Chris Putnam 2016
+ *
+ * Source code released under the GPL version 2
+ *
+ */
+#ifndef NOTES_H
+#define NOTES_H
+
+#include "bibutils.h"
+
+int notes_add( fields *bibout, newstr *invalue, int level );
+
+#endif
+
diff --git a/lib/pages.c b/lib/pages.c
new file mode 100644
index 0000000..e245d77
--- /dev/null
+++ b/lib/pages.c
@@ -0,0 +1,83 @@
+/*
+ * pages.c
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "is_ws.h"
+#include "utf8.h"
+#include "pages.h"
+
+/* extract_range()
+ *
+ * Handle input strings like:
+ *
+ * "1-15"
+ * " 1 - 15 "
+ * " 1000--- 1500"
+ * " 1 <<em-dash>> 10"
+ * " 107 111"
+ */
+static void
+extract_range( newstr *input, newstr *begin, newstr *end )
+{
+	/* -30 is the first character of a UTF8 em-dash and en-dash */
+	const char terminators[] = { ' ', '-', '\t', '\r', '\n', -30, '\0' };
+	char *p;
+
+	newstr_empty( begin );
+	newstr_empty( end );
+
+	if ( input->len==0 ) return;
+
+	p = skip_ws( input->data );
+	while ( *p && !strchr( terminators, *p ) )
+		newstr_addchar( begin, *p++ );
+
+	p = skip_ws( p );
+
+	while ( *p=='-' ) p++;
+	while ( utf8_is_emdash( p ) ) p+=3;
+	while ( utf8_is_endash( p ) ) p+=3;
+
+	p = skip_ws( p );
+
+	while ( *p && !strchr( terminators, *p ) )
+		newstr_addchar( end, *p++ );
+}
+
+int
+pages_add( fields *bibout, char *outtag, newstr *invalue, int level )
+{
+	int fstatus, status = 1;
+	newstr start, stop;
+
+	newstr_init( &start );
+	newstr_init( &stop );
+
+	extract_range( invalue, &start, &stop );
+
+	if ( newstr_memerr( &start ) || newstr_memerr( &stop ) ) {
+		status = 0;
+		goto out;
+	}
+
+	if ( start.len>0 ) {
+		fstatus = fields_add( bibout, "PAGES:START", start.data, level );
+		if ( fstatus!=FIELDS_OK ) {
+			status = 0;
+			goto out;
+		}
+	}
+
+	if ( stop.len>0 ) {
+		fstatus = fields_add( bibout, "PAGES:STOP", stop.data, level );
+		if ( fstatus!=FIELDS_OK ) status = 0;
+	}
+
+out:
+	newstr_free( &start );
+	newstr_free( &stop );
+	return status;
+}
+
diff --git a/lib/pages.h b/lib/pages.h
new file mode 100644
index 0000000..269d30e
--- /dev/null
+++ b/lib/pages.h
@@ -0,0 +1,13 @@
+/*
+ * pages.h
+ *
+ */
+#ifndef PAGES_H
+#define PAGES_H
+
+#include "bibl.h"
+
+int pages_add( fields *bibout, char *outtag, newstr *invalue, int level );
+
+#endif
+
diff --git a/lib/reftypes.c b/lib/reftypes.c
index 8ccc152..b4d960e 100644
--- a/lib/reftypes.c
+++ b/lib/reftypes.c
@@ -1,7 +1,7 @@
 /*
  * reftypes.c
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Source code released under the GPL version 2
  *
@@ -13,16 +13,27 @@
 #include "reftypes.h"
 
 int
-get_reftype( char *p, long refnum, char *progname, variants *all, int nall, char *tag )
+get_reftype( char *p, long refnum, char *progname, variants *all, int nall, char *tag, int *is_default, int chattiness )
 {
 	int i;
+
 	p = skip_ws( p );
-	for ( i=0; i<nall; ++i )
+
+	*is_default = 0;
+
+	for ( i=0; i<nall; ++i ) {
 		if ( !strncasecmp( all[i].type, p, strlen(all[i].type) ) ) 
 			return i;
-	if ( progname ) fprintf( stderr, "%s: ", progname );
-	fprintf( stderr, "Did not recognize type '%s' of refnum %ld (%s).\n"
-		"\tDefaulting to article.\n", p, refnum, tag );
+	}
+
+	*is_default = 1;
+
+	if ( chattiness==REFTYPE_CHATTY ) {
+		if ( progname ) fprintf( stderr, "%s: ", progname );
+		fprintf( stderr, "Did not recognize type '%s' of refnum %ld (%s).\n"
+			"\tDefaulting to %s.\n", p, refnum, tag, all[0].type );
+	}
+
 	return 0;
 }
 
@@ -52,6 +63,7 @@ translate_oldtag( char *oldtag, int reftype, variants all[], int nall,
 		*processingtype = ((all[reftype]).tags[n]).processingtype;
 		*level          = ((all[reftype]).tags[n]).level;
 		*newtag         = ((all[reftype]).tags[n]).newstr;
+		return 1;
 	}
-	return n;
+	return 0;
 }
diff --git a/lib/reftypes.h b/lib/reftypes.h
index 33788d0..9d409ec 100644
--- a/lib/reftypes.h
+++ b/lib/reftypes.h
@@ -1,7 +1,7 @@
 /*
  * reftypes.h
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Source code released under the GPL version 2
  *
@@ -9,9 +9,13 @@
 #ifndef REFTYPES_H
 #define REFTYPES_H
 
+#define REFTYPE_CHATTY  (0)
+#define REFTYPE_SILENT  (1)
+
 /* Reftypes handled by core code */
 #define ALWAYS          (0)
 #define DEFAULT         (1)
+#define SKIP            (2)
 
 /* Reftypes to be handled by converters */
 #define SIMPLE          (2)
@@ -26,17 +30,18 @@
 #define HOWPUBLISHED    (11)
 #define LINKEDFILE      (12)
 #define KEYWORD         (13)
-#define BT_URL          (14) /* Bibtex URL */
-#define BT_NOTE         (15) /* Bibtex Note */
-#define BT_SENTE        (16) /* Bibtex 'Sente' */
-#define BT_GENRE        (17) /* Bibtex Genre */
-#define BT_EPRINT       (18) /* Bibtex 'Eprint' */
-#define BT_ORG          (19) /* Bibtex Organization */
-#define BLT_THESIS_TYPE (20) /* Biblatex Thesis Type */
-#define BLT_SCHOOL      (21) /* Biblatex School */
-#define BLT_EDITOR      (22) /* Biblatex Editor */
-#define BLT_SUBTYPE     (23) /* Biblatex entrysubtype */
-#define BLT_SKIP        (24) /* Biblatex Skip Entry */
+#define URL             (14)
+#define BT_SENTE        (15) /* Bibtex 'Sente' */
+#define BT_GENRE        (16) /* Bibtex Genre */
+#define BT_EPRINT       (17) /* Bibtex 'Eprint' */
+#define BT_ORG          (18) /* Bibtex Organization */
+#define BLT_THESIS_TYPE (19) /* Biblatex Thesis Type */
+#define BLT_SCHOOL      (20) /* Biblatex School */
+#define BLT_EDITOR      (21) /* Biblatex Editor */
+#define BLT_SUBTYPE     (22) /* Biblatex entrysubtype */
+#define BLT_SKIP        (23) /* Biblatex Skip Entry */
+#define EPRINT          (24)
+#define NUM_REFTYPES    (25)
 
 typedef struct {
 	char *oldstr;
@@ -51,10 +56,8 @@ typedef struct {
 	int     ntags;
 } variants;
 
-extern int get_reftype( char *q, long refnum, char *progname, variants *all, int nall, char *tag );
-extern int process_findoldtag( char *oldtag, int reftype, variants all[], int nall );
-extern int translate_oldtag( char *oldtag, int reftype, variants all[], int nall, int *processingtype, int *level, char **newtag );
-
-
+int get_reftype( char *q, long refnum, char *progname, variants *all, int nall, char *tag, int *is_default, int chattiness );
+int process_findoldtag( char *oldtag, int reftype, variants all[], int nall );
+int translate_oldtag( char *oldtag, int reftype, variants all[], int nall, int *processingtype, int *level, char **newtag );
 
 #endif
diff --git a/lib/risin.c b/lib/risin.c
index 1ef2adb..93ad2a3 100644
--- a/lib/risin.c
+++ b/lib/risin.c
@@ -1,7 +1,7 @@
 /*
  * risin.c
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Source code released under the GPL version 2
  *
@@ -15,14 +15,24 @@
 #include "fields.h"
 #include "name.h"
 #include "title.h"
+#include "url.h"
 #include "serialno.h"
 #include "reftypes.h"
-#include "doi.h"
-#include "risin.h"
+#include "bibformats.h"
+#include "generic.h"
+
+extern variants ris_all[];
+extern int ris_nall;
 
 /*****************************************************
  PUBLIC: void risin_initparams()
 *****************************************************/
+
+static int risin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );
+static int risin_processf( fields *risin, char *p, char *filename, long nref, param *pm );
+static int risin_typef( fields *risin, char *filename, int nref, param *p );
+static int risin_convertf( fields *risin, fields *info, int reftype, param *p );
+
 void
 risin_initparams( param *p, const char *progname )
 {
@@ -84,7 +94,7 @@ readmore( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line )
 	else return newstr_fget( fp, buf, bufsize, bufpos, line );
 }
 
-int
+static int
 risin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, 
 		newstr *reference, int *fcharset )
 {
@@ -168,8 +178,8 @@ process_line( newstr *tag, newstr *data, char *p )
 	return p;
 }
 
-int
-risin_processf( fields *risin, char *p, char *filename, long nref )
+static int
+risin_processf( fields *risin, char *p, char *filename, long nref, param *pm )
 {
 	newstr tag, data;
 	int status, n;
@@ -177,10 +187,10 @@ risin_processf( fields *risin, char *p, char *filename, long nref )
 	newstrs_init( &tag, &data, NULL );
 
 	while ( *p ) {
-		if ( risin_istag( p ) ) {
-		p = process_line( &tag, &data, p );
+		if ( risin_istag( p ) )
+			p = process_line( &tag, &data, p );
 		/* no anonymous fields allowed */
-		if ( tag.len )
+		if ( tag.len ) {
 			status = fields_add( risin, tag.data, data.data, 0 );
 			if ( status!=FIELDS_OK ) return 0;
 		} else {
@@ -204,40 +214,24 @@ risin_processf( fields *risin, char *p, char *filename, long nref )
  PUBLIC: int risin_typef()
 *****************************************************/
 
-int
-risin_typef( fields *risin, char *filename, int nref, param *p, variants *all, int nall )
+static int
+risin_typef( fields *risin, char *filename, int nref, param *p )
 {
-	char *refnum = "";
-	int n, reftype, nreftype;
-	n = fields_find( risin, "TY", 0 );
-	nreftype = fields_find( risin, "ID", 0 );
-	if ( nreftype!=-1 ) refnum = risin[n].data->data;
-	if ( n!=-1 )
-		reftype = get_reftype( (risin[n].data)->data, nref, p->progname,
-			all, nall, refnum );
-	else
-		reftype = get_reftype( "", nref, p->progname, all, nall, refnum ); /*default */
-	return reftype;
+	int ntypename, nrefname, is_default;
+	char *refname = "", *typename = "";
+
+	ntypename = fields_find( risin, "TY", LEVEL_MAIN );
+	nrefname  = fields_find( risin, "ID", LEVEL_MAIN );
+	if ( ntypename!=-1 ) typename = fields_value( risin, ntypename, FIELDS_CHRP_NOUSE );
+	if ( nrefname!=-1 )  refname  = fields_value( risin, nrefname,  FIELDS_CHRP_NOUSE );
+
+	return get_reftype( typename, nref, p->progname, p->all, p->nall, refname, &is_default, REFTYPE_CHATTY );
 }
 
 /*****************************************************
  PUBLIC: int risin_convertf()
 *****************************************************/
 
-/* oxfordjournals hide the DOI in the NOTES N1 field */
-static int
-risin_addnotes( fields *f, char *tag, newstr *s, int level )
-{
-	int doi, status;
-	doi = is_doi( s->data );
-	if ( doi!=-1 )
-		status = fields_add( f, "DOI", &(s->data[doi]), level );
-	else
-		status = fields_add( f, tag, s->data, level );
-	if ( status==FIELDS_OK ) return BIBL_OK;
-	else return BIBL_ERR_MEMERR;
-}
-
 static int
 is_uri_file_scheme( char *p )
 {
@@ -246,76 +240,63 @@ is_uri_file_scheme( char *p )
 }
 
 static int
-is_uri_remote_scheme( char *p )
+risin_linkedfile( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
 {
-	char *scheme[] = { "http:", "ftp:", "git:", "gopher:" };
-	int i, len, nschemes = sizeof( scheme ) / sizeof( scheme[0] );
-	for ( i=0; i<nschemes; ++i ) {
-		len = strlen( scheme[i] );
-		if ( !strncmp( p, scheme[i], len ) ) return len;
-	}
-	return 0;
-}
-
-static int
-risin_addfile( fields *f, char *tag, newstr *s, int level )
-{
-	int status, n;
+	int fstatus, m;
 	char *p;
 
 	/* if URL is file:///path/to/xyz.pdf, only store "///path/to/xyz.pdf" */
-	n = is_uri_file_scheme( s->data );
-	if ( n ) {
+	m = is_uri_file_scheme( invalue->data );
+	if ( m ) {
 		/* skip past "file:" and store only actual path */
-		p = s->data + n;
-		status = fields_add( f, tag, p, level );
-		if ( status==FIELDS_OK ) return BIBL_OK;
+		p = invalue->data + m;
+		fstatus = fields_add( bibout, outtag, p, level );
+		if ( fstatus==FIELDS_OK ) return BIBL_OK;
 		else return BIBL_ERR_MEMERR;
 	}
 
 	/* if URL is http:, ftp:, etc. store as a URL */
-	n = is_uri_remote_scheme( s->data );
-	if ( n ) {
-		status = fields_add( f, "URL", s->data, level );
-		if ( status==FIELDS_OK ) return BIBL_OK;
+	m = is_uri_remote_scheme( invalue->data );
+	if ( m!=-1 ) {
+		fstatus = fields_add( bibout, "URL", invalue->data, level );
+		if ( fstatus==FIELDS_OK ) return BIBL_OK;
 		else return BIBL_ERR_MEMERR;
 	}
 
 	/* badly formed, RIS wants URI, but store value anyway */
-	status = fields_add( f, tag, s->data, level );
-	if ( status==FIELDS_OK ) return BIBL_OK;
+	fstatus = fields_add( bibout, outtag, invalue->data, level );
+	if ( fstatus==FIELDS_OK ) return BIBL_OK;
 	else return BIBL_ERR_MEMERR;
 }
 
 /* scopus puts DOI in the DO or DI tag, but it needs cleaning */
 static int
-risin_adddoi( fields *f, char *tag, newstr *s, int level )
+risin_doi( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
 {
-	int status, doi;
-	doi = is_doi( s->data );
+	int fstatus, doi;
+	doi = is_doi( invalue->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;
+		fstatus = fields_add( bibout, "DOI", &(invalue->data[doi]), level );
+		if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
-	else return BIBL_OK;
+	return BIBL_OK;
 }
 
 static int
-risin_adddate( fields *f, char *tag, newstr *d, int level )
+risin_date( fields *bibin, int n, newstr *intag, newstr *invalue, int level, param *pm, char *outtag, fields *bibout )
 {
-	char *p = d->data;
-	newstr date;
+	char *p = invalue->data;
 	int part, status;
+	newstr date;
 
-	part = ( !strncasecmp( tag, "PART", 4 ) );
+	part = ( !strncasecmp( outtag, "PART", 4 ) );
 
 	newstr_init( &date );
 	while ( *p && *p!='/' ) newstr_addchar( &date, *p++ );
 	if ( *p=='/' ) p++;
 	if ( date.len>0 ) {
-		if ( part ) status = fields_add( f, "PARTYEAR", date.data, level );
-		else        status = fields_add( f, "YEAR",     date.data, level );
+		if ( part ) status = fields_add( bibout, "PARTDATE:YEAR", date.data, level );
+		else        status = fields_add( bibout, "DATE:YEAR",     date.data, level );
 		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
 
@@ -323,8 +304,8 @@ risin_adddate( fields *f, char *tag, newstr *d, int level )
 	while ( *p && *p!='/' ) newstr_addchar( &date, *p++ );
 	if ( *p=='/' ) p++;
 	if ( date.len>0 ) {
-		if ( part ) status = fields_add( f, "PARTMONTH", date.data, level );
-		else        status = fields_add( f, "MONTH",     date.data, level );
+		if ( part ) status = fields_add( bibout, "PARTDATE:MONTH", date.data, level );
+		else        status = fields_add( bibout, "DATE:MONTH",     date.data, level );
 		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
 
@@ -332,22 +313,48 @@ risin_adddate( fields *f, char *tag, newstr *d, int level )
 	while ( *p && *p!='/' ) newstr_addchar( &date, *p++ );
 	if ( *p=='/' ) p++;
 	if ( date.len>0 ) {
-		if ( part ) status = fields_add( f, "PARTDAY", date.data, level );
-		else        status = fields_add( f, "DAY",     date.data, level );
+		if ( part ) status = fields_add( bibout, "PARTDATE:DAY", date.data, level );
+		else        status = fields_add( bibout, "DATE: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 ) status = fields_add( f, "PARTDATEOTHER", date.data,level);
-		else        status = fields_add( f, "DATEOTHER", date.data, level );
+		if ( part ) status = fields_add( bibout, "PARTDATE:OTHER", date.data,level);
+		else        status = fields_add( bibout, "DATE:OTHER", date.data, level );
 		if ( status!=FIELDS_OK ) return BIBL_ERR_MEMERR;
 	}
 	newstr_free( &date );
 	return BIBL_OK;
 }
 
+/* look for thesis-type hint */
+static int
+risin_thesis_hints( fields *bibin, int reftype, param *p, fields *bibout )
+{
+	int i, nfields, fstatus;
+	char *tag, *value;
+
+	if ( strcasecmp( p->all[reftype].type, "THES" ) ) return BIBL_OK;
+
+	nfields = fields_num( bibin );
+	for ( i=0; i<nfields; ++i ) {
+		tag = fields_tag( bibin, i, FIELDS_CHRP );
+		if ( strcasecmp( tag, "U1" ) ) continue;
+		value = fields_value( bibin, i, FIELDS_CHRP );
+		if ( !strcasecmp(value,"Ph.D. Thesis")||
+		     !strcasecmp(value,"Masters Thesis")||
+		     !strcasecmp(value,"Diploma Thesis")||
+		     !strcasecmp(value,"Doctoral Thesis")||
+		     !strcasecmp(value,"Habilitation Thesis")) {
+			fstatus = fields_add( bibout, "GENRE", value, 0 );
+			if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
+		}
+	}
+	return BIBL_OK;
+}
+
 static void
 risin_report_notag( param *p, char *tag )
 {
@@ -358,97 +365,41 @@ risin_report_notag( param *p, char *tag )
 }
 
 static int
-risin_simple( fields *f, char *tag, char *value, int level )
+risin_convertf( fields *bibin, fields *bibout, int reftype, param *p )
 {
-	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, fstatus, status = BIBL_OK;
-	char *outtag, *tag, *value;
-	newstr *t, *d;
-
-	nfields = fields_num( risin );
+	static int (*convertfns[NUM_REFTYPES])(fields *, int, newstr *, newstr *, int, param *, char *, fields *) = {
+		[ 0 ... NUM_REFTYPES-1 ] = generic_null,
+		[ SIMPLE       ] = generic_simple,
+		[ TITLE        ] = generic_title,
+		[ PERSON       ] = generic_person,
+		[ SERIALNO     ] = generic_serialno,
+		[ NOTES        ] = generic_notes,
+		[ URL          ] = generic_url,
+		[ DATE         ] = risin_date,
+		[ DOI          ] = risin_doi,
+		[ LINKEDFILE   ] = risin_linkedfile,
+        };
+	int process, level, i, nfields, status = BIBL_OK;
+	newstr *intag, *invalue;
+	char *outtag;
+
+	nfields = fields_num( bibin );
 
 	for ( i=0; i<nfields; ++i ) {
-		t = fields_tag( risin, i, FIELDS_STRP );
-		n = translate_oldtag( t->data, reftype, all, nall, &process, &level, &outtag );
-		if ( n==-1 ) {
-			risin_report_notag( p, t->data );
+		intag = fields_tag( bibin, i, FIELDS_STRP );
+		if ( !translate_oldtag( intag->data, reftype, p->all, p->nall, &process, &level, &outtag ) ) {
+			risin_report_notag( p, intag->data );
 			continue;
 		}
-		if ( process==ALWAYS ) continue; /* add in core code */
-
-		d = fields_value( risin, i, FIELDS_STRP );
-
-		switch ( process ) {
+		invalue = fields_value( bibin, i, FIELDS_STRP );
 
-		case SIMPLE:
-			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:
-			status = risin_adddate( f, outtag, d, level );
-			break;
-
-		case NOTES:
-			status = risin_addnotes( f, outtag, d, level );
-			break;
-
-		case DOI:
-			status = risin_adddoi( f, outtag, d, level );
-			break;
-
-		case LINKEDFILE:
-			status = risin_addfile( f, outtag, d, level );
-			break;
-
-		default:
-			status = BIBL_OK;
-			break;
-
-		}
+		status = convertfns[ process ] ( bibin, i, intag, invalue, level, p, outtag, bibout );
 		if ( status!=BIBL_OK ) return status;
 	}
 
-	/* look for thesis-type hint */
-	if ( !strcasecmp( all[reftype].type, "THES" ) ) {
-		for ( i=0; i<nfields; ++i ) {
-			tag = fields_tag( risin, i, FIELDS_CHRP );
-			if ( strcasecmp( tag, "U1" ) ) continue;
-			value = fields_value( risin, i, FIELDS_CHRP );
-			if ( !strcasecmp(value,"Ph.D. Thesis")||
-			     !strcasecmp(value,"Masters Thesis")||
-			     !strcasecmp(value,"Diploma Thesis")||
-			     !strcasecmp(value,"Doctoral Thesis")||
-			     !strcasecmp(value,"Habilitation Thesis")) {
-				fstatus = fields_add( f, "GENRE", value, 0 );
-				if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR;
-			}
-		}
-	}
+	if ( status == BIBL_OK ) status = risin_thesis_hints( bibin, reftype, p, bibout );
+
+	if ( status==BIBL_OK && p->verbose ) fields_report( bibout, stderr );
 
 	return status;
 }
diff --git a/lib/risin.h b/lib/risin.h
deleted file mode 100644
index 6adfe94..0000000
--- a/lib/risin.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * risin.h
- *
- * Copyright (c) Chris Putnam 2003-2015
- *
- * Source code released under the GPL version 2
- *
- */
-#ifndef RISIN_H
-#define RISIN_H
-
-#include "newstr.h"
-#include "fields.h"
-#include "reftypes.h"
-#include "bibutils.h"
-
-extern int risin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );
-extern int risin_processf( fields *risin, char *p, char *filename, long nref );
-extern int risin_typef( fields *risin, char *filename, int nref, param *p, variants *all, int nall );
-extern int risin_convertf( fields *risin, fields *info, int reftype, param *p, variants *all, int nall ); 
-
-extern void risin_initparams( param *p, const char *progname );
-
-extern variants ris_all[];
-extern int ris_nall;
-
-#endif
-
diff --git a/lib/risout.c b/lib/risout.c
index a29775b..1987594 100644
--- a/lib/risout.c
+++ b/lib/risout.c
@@ -1,7 +1,7 @@
 /*
  * risout.c
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Source code released under the GPL version 2
  *
@@ -14,9 +14,14 @@
 #include "newstr.h"
 #include "strsearch.h"
 #include "fields.h"
-#include "doi.h"
 #include "name.h"
-#include "risout.h"
+#include "title.h"
+#include "url.h"
+#include "bibformats.h"
+
+static int  risout_write( fields *info, FILE *fp, param *p, unsigned long refnum );
+static void risout_writeheader( FILE *outptr, param *p );
+
 
 void
 risout_initparams( param *p, const char *progname )
@@ -44,7 +49,7 @@ risout_initparams( param *p, const char *progname )
 }
 
 enum { 
-	TYPE_UNKNOWN,
+	TYPE_UNKNOWN = 0,
 	TYPE_STD,                /* standard/generic */
 	TYPE_ABSTRACT,           /* abstract */
 	TYPE_ARTICLE,            /* article */
@@ -55,9 +60,9 @@ enum {
 	TYPE_ELEC,               /* electronic */
 	TYPE_HEAR,               /* hearing */
 	TYPE_MAGARTICLE,         /* magazine article */
-	TYPE_NEWS,               /* newspaper */
+	TYPE_NEWSPAPER,          /* newspaper */
 	TYPE_MPCT,               /* mpct */
-	TYPE_PAMP,               /* pamphlet */
+	TYPE_PAMPHLET,           /* pamphlet */
 	TYPE_PATENT,             /* patent */
 	TYPE_PCOMM,              /* personal communication */
 	TYPE_PROGRAM,            /* program */
@@ -71,41 +76,78 @@ enum {
 	TYPE_HABILITATIONTHESIS, /* thesis */
 	TYPE_MAP,                /* map, cartographic data */
 	TYPE_UNPUBLISHED,        /* unpublished */
+	NUM_TYPES
+};
+
+static int type_is_element[ NUM_TYPES ] = {
+	[ 0 ... NUM_TYPES-1 ] = 0,
+	[ TYPE_ARTICLE      ] = 1,
+	[ TYPE_INBOOK       ] = 1,
+	[ TYPE_MAGARTICLE   ] = 1,
+	[ TYPE_NEWSPAPER    ] = 1,
+	[ TYPE_ABSTRACT     ] = 1,
+	[ TYPE_CONF         ] = 1,
+};
+
+static int type_uses_journal[ NUM_TYPES ] = {
+	[ 0 ... NUM_TYPES-1 ] = 0,
+	[ TYPE_ARTICLE      ] = 1,
+	[ TYPE_MAGARTICLE   ] = 1,
 };
 
 static void
 write_type( FILE *fp, int type )
 {
-	switch( type ) {
-	case TYPE_UNKNOWN:            fprintf( fp, "TYPE_UNKNOWN" );            break;
-	case TYPE_STD:                fprintf( fp, "TYPE_STD" );                break;
-	case TYPE_ABSTRACT:           fprintf( fp, "TYPE_ABSTRACT" );           break;
-	case TYPE_ARTICLE:            fprintf( fp, "TYPE_ARTICLE" );            break;
-	case TYPE_BOOK:               fprintf( fp, "TYPE_BOOK" );               break;
-	case TYPE_CASE:               fprintf( fp, "TYPE_CASE" );               break;
-	case TYPE_INBOOK:             fprintf( fp, "TYPE_INBOOK" );             break;
-	case TYPE_CONF:               fprintf( fp, "TYPE_CONF" );               break;
-	case TYPE_ELEC:               fprintf( fp, "TYPE_ELEC" );               break;
-	case TYPE_HEAR:               fprintf( fp, "TYPE_HEAR" );               break;
-	case TYPE_MAGARTICLE:         fprintf( fp, "TYPE_MAGARTICLE" );         break;
-	case TYPE_NEWS:               fprintf( fp, "TYPE_NEWS" );               break;
-	case TYPE_MPCT:               fprintf( fp, "TYPE_MCPT" );               break;
-	case TYPE_PAMP:               fprintf( fp, "TYPE_PAMP" );               break;
-	case TYPE_PATENT:             fprintf( fp, "TYPE_PATENT" );             break;
-	case TYPE_PCOMM:              fprintf( fp, "TYPE_PCOMM" );              break;
-	case TYPE_PROGRAM:            fprintf( fp, "TYPE_PROGRAM" );            break;
-	case TYPE_REPORT:             fprintf( fp, "TYPE_REPORT" );             break;
-	case TYPE_STATUTE:            fprintf( fp, "TYPE_STATUTE" );            break;
-	case TYPE_THESIS:             fprintf( fp, "TYPE_THESIS" );             break;
-	case TYPE_MASTERSTHESIS:      fprintf( fp, "TYPE_MASTERSTHESIS" );      break;
-	case TYPE_PHDTHESIS:          fprintf( fp, "TYPE_PHDTHESIS" );          break;
-	case TYPE_DIPLOMATHESIS:      fprintf( fp, "TYPE_DIPLOMATHESIS" );      break;
-	case TYPE_DOCTORALTHESIS:     fprintf( fp, "TYPE_DOCTORALTHESIS" );     break;
-	case TYPE_HABILITATIONTHESIS: fprintf( fp, "TYPE_HABILITATIONTHESIS" ); break;
-	case TYPE_MAP:                fprintf( fp, "TYPE_MAP" );                break;
-	case TYPE_UNPUBLISHED:        fprintf( fp, "TYPE_UNPUBLISHED" );        break;
-	default:                      fprintf( fp, "Error - type not in enum" );break;
-	}
+	const char *typenames[ NUM_TYPES ] = {
+		[ TYPE_UNKNOWN            ] = "TYPE_UNKNOWN",
+		[ TYPE_STD                ] = "TYPE_STD",
+		[ TYPE_ABSTRACT           ] = "TYPE_ABSTRACT",
+		[ TYPE_ARTICLE            ] = "TYPE_ARTICLE",
+		[ TYPE_BOOK               ] = "TYPE_BOOK",
+		[ TYPE_CASE               ] = "TYPE_CASE",
+		[ TYPE_INBOOK             ] = "TYPE_INBOOK",
+		[ TYPE_CONF               ] = "TYPE_CONF",
+		[ TYPE_ELEC               ] = "TYPE_ELEC",
+		[ TYPE_HEAR               ] = "TYPE_HEAR",
+		[ TYPE_MAGARTICLE         ] = "TYPE_MAGARTICLE",
+		[ TYPE_NEWSPAPER          ] = "TYPE_NEWSPAPER",
+		[ TYPE_MPCT               ] = "TYPE_MPCT",
+		[ TYPE_PAMPHLET           ] = "TYPE_PAMPHLET",
+		[ TYPE_PATENT             ] = "TYPE_PATENT",
+		[ TYPE_PCOMM              ] = "TYPE_PCOMM",
+		[ TYPE_PROGRAM            ] = "TYPE_PROGRAM",
+		[ TYPE_REPORT             ] = "TYPE_REPORT",
+		[ TYPE_STATUTE            ] = "TYPE_STATUTE",
+		[ TYPE_THESIS             ] = "TYPE_THESIS",
+		[ TYPE_MASTERSTHESIS      ] = "TYPE_MASTERSTHESIS",
+		[ TYPE_PHDTHESIS          ] = "TYPE_PHDTHESIS",
+		[ TYPE_DIPLOMATHESIS      ] = "TYPE_DIPLOMATHESIS",
+		[ TYPE_DOCTORALTHESIS     ] = "TYPE_DOCTORALTHESIS",
+		[ TYPE_HABILITATIONTHESIS ] = "TYPE_HABILITATIONTHESIS",
+		[ TYPE_MAP                ] = "TYPE_MAP",
+		[ TYPE_UNPUBLISHED        ] = "TYPE_UNPUBLISHED",
+	};
+
+	if ( type < 0 || type >= NUM_TYPES ) fprintf( fp, "Error - type not in enum" );
+	else fprintf( fp, "%s", typenames[ type ] );
+}
+
+static void
+verbose_type_identified( char *element_type, param *p, int type )
+{
+	if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
+	fprintf( stderr, "Type from %s element: ", element_type );
+	write_type( stderr, type );
+	fprintf( stderr, "\n" );
+}
+
+static void
+verbose_type_assignment( char *tag, char *value, param *p, int type )
+{
+	if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
+	fprintf( stderr, "Type from tag '%s' data '%s': ", tag, value );
+	write_type( stderr, type );
+	fprintf( stderr, "\n" );
 }
 
 typedef struct match_type {
@@ -125,7 +167,7 @@ get_type_genre( fields *f, param *p )
 		{ "journal article",           TYPE_ARTICLE },
 		{ "magazine",                  TYPE_MAGARTICLE },
 		{ "conference publication",    TYPE_CONF },
-		{ "newspaper",                 TYPE_NEWS },
+		{ "newspaper",                 TYPE_NEWSPAPER },
 		{ "legislation",               TYPE_STATUTE },
 		{ "communication",             TYPE_PCOMM },
 		{ "hearing",                   TYPE_HEAR },
@@ -144,26 +186,19 @@ get_type_genre( fields *f, param *p )
 		{ "map",                       TYPE_MAP },
 	};
 	int nmatch_genres = sizeof( match_genres ) / sizeof( match_genres[0] );
-	int type, i, j;
 	char *tag, *value;
+	int type, i, j;
 
 	type = TYPE_UNKNOWN;
 
 	for ( i=0; i<fields_num( f ); ++i ) {
-		if ( !fields_match_tag( f, i, "GENRE" ) &&
-		     !fields_match_tag( f, i, "NGENRE" ) )
-			continue;
+		tag = ( char * ) fields_tag( f, i, FIELDS_CHRP );
+		if ( strcmp( tag, "GENRE" ) && strcmp( tag, "NGENRE" ) ) continue;
 		value = ( char * ) fields_value( f, i, FIELDS_CHRP );
 		for ( j=0; j<nmatch_genres; ++j )
 			if ( !strcasecmp( match_genres[j].name, value ) )
 				type = match_genres[j].type;
-		if ( p->verbose ) {
-			tag = ( char * ) fields_tag( f, i, FIELDS_CHRP );
-			if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
-			fprintf( stderr, "Type from tag '%s' data '%s': ", tag, value );
-			write_type( stderr, type );
-			fprintf( stderr, "\n" );
-		}
+		if ( p->verbose ) verbose_type_assignment( tag, value, p, type );
 		if ( type==TYPE_UNKNOWN ) {
 			if ( !strcasecmp( value, "periodical" ) )
 				type = TYPE_ARTICLE;
@@ -181,12 +216,7 @@ get_type_genre( fields *f, param *p )
 
 	}
 
-	if ( p->verbose ) {
-		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
-		fprintf( stderr, "Type from genre element: " );
-		write_type( stderr, type );
-		fprintf( stderr, "\n" );
-	}
+	if ( p->verbose ) verbose_type_identified( "genre", p, type );
 
 	return type;
 }
@@ -217,20 +247,10 @@ get_type_resource( fields *f, param *p )
 			if ( !strcasecmp( value, match_res[j].name ) )
 				type = match_res[j].type;
 		}
-		if ( p->verbose ) {
-			if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
-			fprintf( stderr, "Type from tag 'RESOURCE' data '%s': ", value );
-			write_type( stderr, type );
-			fprintf( stderr, "\n" );
-		}
+		if ( p->verbose ) verbose_type_assignment( "RESOURCE", value, p, type );
 	}
 
-	if ( p->verbose ) {
-		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
-		fprintf( stderr, "Type from resource element: " );
-		write_type( stderr, type );
-		fprintf( stderr, "\n" );
-	}
+	if ( p->verbose ) verbose_type_identified( "resource", p, type );
 
 	vplist_free( &a );
 	return type;
@@ -295,242 +315,229 @@ get_type( fields *f, param *p )
 }
 
 static void
-output_type( FILE *fp, int type, param *p )
+append_type( int type, param *p, fields *out, int *status )
 {
-	match_type tyout[] = {
-		{ "STD",  TYPE_STD },
-		{ "ABST", TYPE_ABSTRACT },
-		{ "JOUR", TYPE_ARTICLE },
-		{ "BOOK", TYPE_BOOK },
-		{ "CASE", TYPE_CASE },
-		{ "CHAP", TYPE_INBOOK },
-		{ "CONF", TYPE_CONF },
-		{ "ELEC", TYPE_ELEC },
-		{ "HEAR", TYPE_HEAR },
-		{ "MGZN", TYPE_MAGARTICLE },
-		{ "NEWS", TYPE_NEWS },
-		{ "MPCT", TYPE_MPCT },
-		{ "PAMP", TYPE_PAMP },
-		{ "PAT",  TYPE_PATENT },
-		{ "PCOMM",TYPE_PCOMM },
-		{ "COMP", TYPE_PROGRAM },
-		{ "RPRT", TYPE_REPORT },
-		{ "STAT", TYPE_STATUTE },
-		{ "THES", TYPE_THESIS },
-		{ "THES", TYPE_MASTERSTHESIS },
-		{ "THES", TYPE_PHDTHESIS },
-		{ "THES", TYPE_DIPLOMATHESIS },
-		{ "THES", TYPE_DOCTORALTHESIS },
-		{ "THES", TYPE_HABILITATIONTHESIS },
-		{ "MAP",  TYPE_MAP },
-		{ "UNPB", TYPE_UNPUBLISHED }
+	char *typenames[ NUM_TYPES ] = {
+		[ TYPE_STD                ] = "STD",
+		[ TYPE_ABSTRACT           ] = "ABST",
+		[ TYPE_ARTICLE            ] = "JOUR",
+		[ TYPE_BOOK               ] = "BOOK",
+		[ TYPE_CASE               ] = "CASE",
+		[ TYPE_INBOOK             ] = "CHAP",
+		[ TYPE_CONF               ] = "CONF",
+		[ TYPE_ELEC               ] = "ELEC",
+		[ TYPE_HEAR               ] = "HEAR",
+		[ TYPE_MAGARTICLE         ] = "MGZN",
+		[ TYPE_NEWSPAPER          ] = "NEWS",
+		[ TYPE_MPCT               ] = "MPCT",
+		[ TYPE_PAMPHLET           ] = "PAMP",
+		[ TYPE_PATENT             ] = "PAT",
+		[ TYPE_PCOMM              ] = "PCOMM",
+		[ TYPE_PROGRAM            ] = "COMP",
+		[ TYPE_REPORT             ] = "RPRT",
+		[ TYPE_STATUTE            ] = "STAT",
+		[ TYPE_THESIS             ] = "THES",
+		[ TYPE_MASTERSTHESIS      ] = "THES",
+		[ TYPE_PHDTHESIS          ] = "THES",
+		[ TYPE_DIPLOMATHESIS      ] = "THES",
+		[ TYPE_DOCTORALTHESIS     ] = "THES",
+		[ TYPE_HABILITATIONTHESIS ] = "THES",
+		[ TYPE_MAP                ] = "MAP",
+		[ TYPE_UNPUBLISHED        ] = "UNPB",
 	};
-	int ntyout = sizeof( tyout ) / sizeof( tyout[0] );
-	int i, found;
-
-	fprintf( fp, "TY  - " );
-	found = 0;
-	for ( i=0; i<ntyout && !found ; ++i ) {
-		if ( tyout[i].type == type ) {
-			fprintf( fp, "%s", tyout[i].name );
-			found = 1;
-		}
-	}
-	/* Report internal error, default to TYPE_STD */
-	if ( !found ) {
+	int fstatus;
+
+	if ( type < 0 || type >= NUM_TYPES ) {
 		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
-		fprintf( stderr, "Internal Error: Cannot identify type %d\n",
-			type );
-		fprintf( fp, "STD" );
+		fprintf( stderr, "Internal error: Cannot recognize type %d, switching to TYPE_STD %d\n", type, TYPE_STD );
+		type = TYPE_STD;
 	}
-	fprintf( fp, "\n" );
+
+	fstatus = fields_add( out, "TY", typenames[ type ], LEVEL_MAIN );
+	if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 }
 
 static void
-output_people( FILE *fp, fields *f, char *tag, char *ristag, int level )
+append_people( fields *f, char *tag, char *ristag, int level, fields *out, int *status )
 {
 	newstr oneperson;
+	int i, fstatus;
 	vplist people;
-	int i;
+
 	newstr_init( &oneperson );
 	vplist_init( &people );
 	fields_findv_each( f, level, FIELDS_CHRP, &people, tag );
 	for ( i=0; i<people.n; ++i ) {
 		name_build_withcomma( &oneperson, ( char * ) vplist_get( &people, i ) );
-		fprintf( fp, "%s  - %s\n", ristag, oneperson.data );
+		fstatus = fields_add_can_dup( out, ristag, newstr_cstr( &oneperson ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 	}
 	vplist_free( &people );
 	newstr_free( &oneperson );
 }
 
 static void
-output_date( FILE *fp, fields *f )
+append_date( fields *in, fields *out, int *status )
 {
-	char *year  = fields_findv_firstof( f, LEVEL_ANY, FIELDS_CHRP,
-			"YEAR", "PARTYEAR", NULL );
-	char *month = fields_findv_firstof( f, LEVEL_ANY, FIELDS_CHRP,
-			"MONTH", "PARTMONTH", NULL );
-	char *day   = fields_findv_firstof( f, LEVEL_ANY, FIELDS_CHRP,
-			"DAY", "PARTDAY", NULL );
-	if ( year )
-		fprintf( fp, "PY  - %s\n", year );
+	char *year, *month, *day;
+	newstr date;
+	int fstatus;
+
+	year  = fields_findv_firstof( in, LEVEL_ANY, FIELDS_CHRP, "DATE:YEAR",  "PARTDATE:YEAR",  NULL );
+	month = fields_findv_firstof( in, LEVEL_ANY, FIELDS_CHRP, "DATE:MONTH", "PARTDATE:MONTH", NULL );
+	day   = fields_findv_firstof( in, LEVEL_ANY, FIELDS_CHRP, "DATE:DAY",   "PARTDATE:DAY",   NULL );
+
+	if ( year ) {
+		fstatus = fields_add( out, "PY", year, LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
+
 	if ( year || month || day ) {
-		fprintf( fp, "DA  - " );
-		if ( year ) fprintf( fp, "%s", year );
-		fprintf( fp, "/" );
-		if ( month ) fprintf( fp, "%s", month );
-		fprintf( fp, "/" );
-		if ( day ) fprintf( fp, "%s", day );
-		fprintf( fp, "\n" );
+		newstr_init( &date );
+
+		if ( year ) newstr_strcat( &date, year );
+		newstr_addchar( &date, '/' );
+		if ( month ) newstr_strcat( &date, month );
+		newstr_addchar( &date, '/' );
+		if ( day ) newstr_strcat( &date, day );
+
+		fstatus = fields_add( out, "DA", newstr_cstr( &date ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+
+		newstr_free( &date );
 	}
 }
 
 static void
-output_titlecore( FILE *fp, fields *f, char *ristag, int level,
-	char *maintag, char *subtag )
+append_titlecore( fields *in, char *ristag, int level, char *maintag, char *subtag, fields *out, int *status )
 {
-	newstr *mainttl = fields_findv( f, level, FIELDS_STRP, maintag );
-	newstr *subttl  = fields_findv( f, level, FIELDS_STRP, subtag );
+	newstr *mainttl = fields_findv( in, level, FIELDS_STRP, maintag );
+	newstr *subttl  = fields_findv( in, level, FIELDS_STRP, subtag );
+	newstr fullttl;
+	int fstatus;
 
-	if ( !mainttl ) return;
+	newstr_init( &fullttl );
 
-	fprintf( fp, "%s  - %s", ristag, mainttl->data );
-	if ( subttl ) {
-		if ( mainttl->len > 0 &&
-		     mainttl->data[ mainttl->len - 1 ]!='?' )
-			fprintf( fp, ":" );
-		fprintf( fp, " %s", subttl->data );
-	}
-	fprintf( fp, "\n" );
-}
+	title_combine( &fullttl, mainttl, subttl );
 
-static int
-type_is_element( int type )
-{
-	if ( type==TYPE_ARTICLE )    return 1;
-	if ( type==TYPE_INBOOK )     return 1;
-	if ( type==TYPE_MAGARTICLE ) return 1;
-	if ( type==TYPE_NEWS )       return 1;
-	if ( type==TYPE_ABSTRACT )   return 1;
-	if ( type==TYPE_CONF )       return 1;
-	return 0;
-}
+	if ( fullttl.len ) {
+		fstatus = fields_add( out, ristag, newstr_cstr( &fullttl ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
 
-static int
-type_uses_journal( int type )
-{
-	if ( type==TYPE_ARTICLE )    return 1;
-	if ( type==TYPE_MAGARTICLE ) return 1;
-	return 0;
+	newstr_free( &fullttl );
 }
 
 static void
-output_alltitles( FILE *fp, fields *f, int type )
+append_alltitles( fields *in, int type, fields *out, int *status )
 {
-	output_titlecore( fp, f, "TI", 0, "TITLE", "SUBTITLE" );
-	output_titlecore( fp, f, "T2", -1, "SHORTTITLE", "SHORTSUBTITLE" );
-	if ( type_is_element( type ) ) {
-		if ( type_uses_journal( type ) )
-			output_titlecore( fp, f, "JO", 1, "TITLE", "SUBTITLE" );
-		else output_titlecore( fp, f, "BT", 1, "TITLE", "SUBTITLE" );
-		output_titlecore( fp, f, "T3", 2, "TITLE", "SUBTITLE" );
+	append_titlecore( in, "TI", 0, "TITLE", "SUBTITLE", out, status );
+	append_titlecore( in, "T2", -1, "SHORTTITLE", "SHORTSUBTITLE", out, status );
+	if ( type_is_element[ type ] ) {
+		if ( type_uses_journal[ type ] )
+			append_titlecore( in, "JO", 1, "TITLE", "SUBTITLE", out, status );
+		else append_titlecore( in, "BT", 1, "TITLE", "SUBTITLE", out, status );
+		append_titlecore( in, "T3", 2, "TITLE", "SUBTITLE", out, status );
 	} else {
-		output_titlecore( fp, f, "T3", 1, "TITLE", "SUBTITLE" );
+		append_titlecore( in, "T3", 1, "TITLE", "SUBTITLE", out, status );
 	}
 }
 
 static void
-output_pages( FILE *fp, fields *f )
+append_pages( fields *in, fields *out, int *status )
 {
-	char *sn = fields_findv( f, LEVEL_ANY, FIELDS_CHRP, "PAGESTART" );
-	char *en = fields_findv( f, LEVEL_ANY, FIELDS_CHRP, "PAGEEND" );
-	char *ar;
+	char *sn, *en, *ar;
+	int fstatus;
+
+	sn = fields_findv( in, LEVEL_ANY, FIELDS_CHRP, "PAGES:START" );
+	en = fields_findv( in, LEVEL_ANY, FIELDS_CHRP, "PAGES:STOP" );
 
 	if ( sn || en ) {
-		if ( sn ) fprintf( fp, "SP  - %s\n", sn );
-		if ( en ) fprintf( fp, "EP  - %s\n", en );
+		if ( sn ) {
+			fstatus = fields_add( out, "SP", sn, LEVEL_MAIN );
+			if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+		}
+		if ( en ) {
+			fstatus = fields_add( out, "EP", en, LEVEL_MAIN );
+			if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+		}
 	} else {
-		ar = fields_findv( f, LEVEL_ANY, FIELDS_CHRP, "ARTICLENUMBER" );
-		if ( ar ) fprintf( fp, "SP  - %s\n", ar );
+		ar = fields_findv( in, LEVEL_ANY, FIELDS_CHRP, "ARTICLENUMBER" );
+		if ( ar ) {
+			fstatus = fields_add( out, "SP", ar, LEVEL_MAIN );
+			if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+		}
 	}
 }
 
 static void
-output_keywords( FILE *fp, fields *f )
+append_keywords( fields *in, fields *out, int *status )
 {
+	int i, fstatus;
 	vplist vpl;
-	int i;
+
 	vplist_init( &vpl );
-	fields_findv_each( f, LEVEL_ANY, FIELDS_CHRP, &vpl, "KEYWORD" );
-	for ( i=0; i<vpl.n; ++i )
-		fprintf( fp, "KW  - %s\n", ( char * ) vplist_get( &vpl, i ) );
+	fields_findv_each( in, LEVEL_ANY, FIELDS_CHRP, &vpl, "KEYWORD" );
+	for ( i=0; i<vpl.n; ++i ) {
+		fstatus = fields_add( out, "KW", ( char * ) vplist_get( &vpl, i ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
 	vplist_free( &vpl );
 }
 
 static void
-output_pmid( FILE *fp, fields *f )
+append_urls( fields *in, fields *out, int *status )
 {
-	newstr s;
-	int i;
-	newstr_init( &s );
-	for ( i=0; i<fields_num( f ); ++i ) {
-		if ( !fields_match_tag( f, i, "PMID" ) ) continue;
-		pmid_to_url( f, i, "URL", &s );
-		if ( s.len )
-			fprintf( fp, "UR  - %s\n", s.data );
+	int lstatus;
+	list types;
+
+	lstatus = list_init_valuesc( &types, "URL", "PMID", "PMC", "ARXIV", "JSTOR", "MRNUMBER", NULL );
+	if ( lstatus!=LIST_OK ) {
+		*status = BIBL_ERR_MEMERR;
+		return;
 	}
-	newstr_free( &s );
+
+	*status = urls_merge_and_add( in, LEVEL_ANY, out, "UR", LEVEL_MAIN, &types );
+
+	list_free( &types );
+
 }
 
 static void
-output_arxiv( FILE *fp, fields *f )
+append_thesishint( int type, fields *out, int *status )
 {
-	newstr s;
-	int i;
-	newstr_init( &s );
-	for ( i=0; i<fields_num( f ); ++i ) {
-		if ( !fields_match_tag( f, i, "ARXIV" ) ) continue;
-		arxiv_to_url( f, i, "URL", &s );
-		if ( s.len )
-			fprintf( fp, "UR  - %s\n", s.data );
+	int fstatus;
+
+	if ( type==TYPE_MASTERSTHESIS ) {
+		fstatus = fields_add( out, "U1", "Masters thesis", LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 	}
-	newstr_free( &s );
-}
 
-static void
-output_jstor( FILE *fp, fields *f )
-{
-	newstr s;
-	int i;
-	newstr_init( &s );
-	for ( i=0; i<fields_num( f ); ++i ) {
-		if ( !fields_match_tag( f, i, "JSTOR" ) ) continue;
-		jstor_to_url( f, i, "URL", &s );
-		if ( s.len )
-			fprintf( fp, "UR  - %s\n", s.data );
+	else if ( type==TYPE_PHDTHESIS ) {
+		fstatus = fields_add( out, "U1", "Ph.D. thesis", LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 	}
-	newstr_free( &s );
-}
 
-static void
-output_thesishint( FILE *fp, int type )
-{
-	if ( type==TYPE_MASTERSTHESIS )
-		fprintf( fp, "%s  - %s\n", "U1", "Masters thesis" );
-	else if ( type==TYPE_PHDTHESIS )
-		fprintf( fp, "%s  - %s\n", "U1", "Ph.D. thesis" );
-	else if ( type==TYPE_DIPLOMATHESIS )
-		fprintf( fp, "%s  - %s\n", "U1", "Diploma thesis" );
-	else if ( type==TYPE_DOCTORALTHESIS )
-		fprintf( fp, "%s  - %s\n", "U1", "Doctoral thesis" );
-	else if ( type==TYPE_HABILITATIONTHESIS )
-		fprintf( fp, "%s  - %s\n", "U1", "Habilitation thesis" );
+	else if ( type==TYPE_DIPLOMATHESIS ) {
+		fstatus = fields_add( out, "U1", "Diploma thesis", LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
+
+	else if ( type==TYPE_DOCTORALTHESIS ) {
+		fstatus = fields_add( out, "U1", "Doctoral thesis", LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
+
+	else if ( type==TYPE_HABILITATIONTHESIS ) {
+		fstatus = fields_add( out, "U1", "Habilitation thesis", LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
 }
 
 static int
 is_uri_scheme( char *p )
 {
-	char *scheme[] = { "http:", "file:", "ftp:", "git:", "gopher:" };
+	char *scheme[] = { "http:", "https:", "file:", "ftp:", "git:", "gopher:" };
 	int i, len, nschemes = sizeof( scheme ) / sizeof( scheme[0] );
 	for ( i=0; i<nschemes; ++i ) {
 		len = strlen( scheme[i] );
@@ -541,120 +548,160 @@ is_uri_scheme( char *p )
 
 
 static void
-output_file( FILE *fp, fields *f, char *tag, char *ristag, int level )
+append_file( fields *in, char *tag, char *ristag, int level, fields *out, int *status )
 {
+	newstr filename;
+	int i, fstatus;
 	vplist a;
 	char *fl;
-	int i;
+
+	newstr_init( &filename );
 	vplist_init( &a );
-	fields_findv_each( f, level, FIELDS_CHRP, &a, tag );
+	fields_findv_each( in, level, FIELDS_CHRP, &a, tag );
 	for ( i=0; i<a.n; ++i ) {
-		fprintf( fp, "%s  - ", ristag );
 		fl = ( char * ) vplist_get( &a, i );
-		if ( !is_uri_scheme( fl ) )
-			fprintf( fp, "file:" );
-		fprintf( fp, "%s\n", fl );
+		newstr_empty( &filename );
+		if ( !is_uri_scheme( fl ) ) newstr_strcat( &filename, "file:" );
+		newstr_strcat( &filename, fl );
+		fstatus = fields_add( out, ristag, newstr_cstr( &filename ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
 	}
 	vplist_free( &a );
+	newstr_free( &filename );
 }
 
 static void
-output_easy( FILE *fp, fields *f, char *tag, char *ristag, int level )
+append_easy( fields *in, char *tag, char *ristag, int level, fields *out, int *status )
 {
-	char *value = fields_findv( f, level, FIELDS_CHRP, tag );
-	if ( value ) fprintf( fp, "%s  - %s\n", ristag, value );
+	char *value;
+	int fstatus;
+
+	value = fields_findv( in, level, FIELDS_CHRP, tag );
+	if ( value ) {
+		fstatus = fields_add( out, ristag, value, LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
 }
 
 static void
-output_easyall( FILE *fp, fields *f, char *tag, char *ristag, int level )
+append_easyall( fields *in, char *tag, char *ristag, int level, fields *out, int *status )
 {
+	int i, fstatus;
 	vplist a;
-	int i;
+
 	vplist_init( &a );
-	fields_findv_each( f, level, FIELDS_CHRP, &a, tag );
-	for ( i=0; i<a.n; ++i )
-		fprintf( fp, "%s  - %s\n", ristag, (char *) vplist_get( &a, i ) );
+	fields_findv_each( in, level, FIELDS_CHRP, &a, tag );
+	for ( i=0; i<a.n; ++i ) {
+		fstatus = fields_add( out, ristag, (char *) vplist_get( &a, i ), LEVEL_MAIN );
+		if ( fstatus!=FIELDS_OK ) *status = BIBL_ERR_MEMERR;
+	}
 	vplist_free( &a );
 }
 
 static void
-output_allpeople( FILE *fp, fields *f, int type )
+append_allpeople( fields *in, int type, fields *out, int *status )
 {
-	output_people(  fp, f, "AUTHOR",      "AU", LEVEL_MAIN   );
-	output_easyall( fp, f, "AUTHOR:CORP", "AU", LEVEL_MAIN   );
-	output_easyall( fp, f, "AUTHOR:ASIS", "AU", LEVEL_MAIN   );
-	output_people(  fp, f, "AUTHOR",      "A2", LEVEL_HOST   );
-	output_easyall( fp, f, "AUTHOR:CORP", "A2", LEVEL_HOST   );
-	output_easyall( fp, f, "AUTHOR:ASIS", "A2", LEVEL_HOST   );
-	output_people(  fp, f, "AUTHOR",      "A3", LEVEL_SERIES );
-	output_easyall( fp, f, "AUTHOR:CORP", "A3", LEVEL_SERIES );
-	output_easyall( fp, f, "AUTHOR:ASIS", "A3", LEVEL_SERIES );
-	output_people(  fp, f, "EDITOR",      "ED", LEVEL_MAIN   );
-	output_easyall( fp, f, "EDITOR:CORP", "ED", LEVEL_MAIN   );
-	output_easyall( fp, f, "EDITOR:ASIS", "ED", LEVEL_MAIN   );
-	if ( type_is_element( type ) ) {
-		output_people(  fp, f, "EDITOR",      "ED", LEVEL_HOST   );
-		output_easyall( fp, f, "EDITOR:CORP", "ED", LEVEL_HOST   );
-		output_easyall( fp, f, "EDITOR:ASIS", "ED", LEVEL_HOST   );
+	append_people ( in, "AUTHOR",      "AU", LEVEL_MAIN,   out, status );
+	append_easyall( in, "AUTHOR:CORP", "AU", LEVEL_MAIN,   out, status );
+	append_easyall( in, "AUTHOR:ASIS", "AU", LEVEL_MAIN,   out, status );
+	append_people ( in, "AUTHOR",      "A2", LEVEL_HOST,   out, status );
+	append_easyall( in, "AUTHOR:CORP", "A2", LEVEL_HOST,   out, status );
+	append_easyall( in, "AUTHOR:ASIS", "A2", LEVEL_HOST,   out, status );
+	append_people ( in, "AUTHOR",      "A3", LEVEL_SERIES, out, status );
+	append_easyall( in, "AUTHOR:CORP", "A3", LEVEL_SERIES, out, status );
+	append_easyall( in, "AUTHOR:ASIS", "A3", LEVEL_SERIES, out, status );
+	append_people ( in, "EDITOR",      "ED", LEVEL_MAIN,   out, status );
+	append_easyall( in, "EDITOR:CORP", "ED", LEVEL_MAIN,   out, status );
+	append_easyall( in, "EDITOR:ASIS", "ED", LEVEL_MAIN,   out, status );
+	if ( type_is_element[ type ] ) {
+		append_people ( in, "EDITOR",      "ED", LEVEL_HOST, out, status );
+		append_easyall( in, "EDITOR:CORP", "ED", LEVEL_HOST, out, status );
+		append_easyall( in, "EDITOR:ASIS", "ED", LEVEL_HOST, out, status );
 	} else {
-		output_people(  fp, f, "EDITOR",      "A3", LEVEL_HOST   );
-		output_easyall( fp, f, "EDITOR:CORP", "A3", LEVEL_HOST   );
-		output_easyall( fp, f, "EDITOR:ASIS", "A3", LEVEL_HOST   );
+		append_people ( in, "EDITOR",      "A3", LEVEL_HOST, out, status );
+		append_easyall( in, "EDITOR:CORP", "A3", LEVEL_HOST, out, status );
+		append_easyall( in, "EDITOR:ASIS", "A3", LEVEL_HOST, out, status );
 	}
-	output_people(  fp, f, "EDITOR",      "A3", LEVEL_SERIES );
-	output_easyall( fp, f, "EDITOR:CORP", "A3", LEVEL_SERIES );
-	output_easyall( fp, f, "EDITOR:ASIS", "A3", LEVEL_SERIES );
+	append_people ( in, "EDITOR",      "A3", LEVEL_SERIES, out, status );
+	append_easyall( in, "EDITOR:CORP", "A3", LEVEL_SERIES, out, status );
+	append_easyall( in, "EDITOR:ASIS", "A3", LEVEL_SERIES, out, status );
 }
 
-void
-risout_write( fields *f, FILE *fp, param *p, unsigned long refnum )
+static void
+output( FILE *fp, fields *out )
 {
-	int type;
-	type = get_type( f, p );
-	output_type( fp, type, p );
-
-	output_allpeople( fp, f, type );
-
-	output_date( fp, f );
-
-	output_alltitles( fp, f, type );
-
-	output_pages( fp, f );
-	output_easy( fp, f, "VOLUME",             "VL", LEVEL_ANY );
-	output_easy( fp, f, "ISSUE",              "IS", LEVEL_ANY );
-	output_easy( fp, f, "NUMBER",             "IS", LEVEL_ANY );
-	output_easy( fp, f, "EDITION",            "ET", LEVEL_ANY );
-	output_easy( fp, f, "NUMVOLUMES",         "NV", LEVEL_ANY );
-	output_easy( fp, f, "AUTHORADDRESS",      "AD", LEVEL_ANY );
-	output_easy( fp, f, "PUBLISHER",          "PB", LEVEL_ANY );
-	output_easy( fp, f, "DEGREEGRANTOR",      "PB", LEVEL_ANY );
-	output_easy( fp, f, "DEGREEGRANTOR:ASIS", "PB", LEVEL_ANY );
-	output_easy( fp, f, "DEGREEGRANTOR:CORP", "PB", LEVEL_ANY );
-	output_easy( fp, f, "ADDRESS",            "CY", LEVEL_ANY );
-	output_keywords( fp, f );
-	output_easy( fp, f, "ABSTRACT",           "AB", LEVEL_ANY );
-	output_easy( fp, f, "CALLNUMBER",         "CN", LEVEL_ANY );
-	output_easy( fp, f, "ISSN",               "SN", LEVEL_ANY );
-	output_easy( fp, f, "ISBN",               "SN", LEVEL_ANY );
-	output_easyall( fp, f, "URL",             "UR", LEVEL_ANY );
-	output_easyall( fp, f, "DOI",             "DO", LEVEL_ANY );
-	output_file(    fp, f, "FILEATTACH",      "L1", LEVEL_ANY );
-	output_file(    fp, f, "FIGATTACH",       "L4", LEVEL_ANY );
-	output_easy( fp, f, "CAPTION",            "CA", LEVEL_ANY );
-	output_pmid( fp, f );
-	output_arxiv( fp, f );
-	output_jstor( fp, f );
-	output_easy( fp, f, "LANGUAGE",           "LA", LEVEL_ANY );
-	output_easy( fp, f, "NOTES",              "N1", LEVEL_ANY );
-	output_easy( fp, f, "REFNUM",             "ID", LEVEL_ANY );
-	output_thesishint( fp, type );
+	char *tag, *value;
+	int i;
+
+	for ( i=0; i<out->n; ++i ) {
+		tag   = fields_tag( out, i, FIELDS_CHRP );
+		value = fields_value( out, i, FIELDS_CHRP );
+		fprintf( fp, "%s  - %s\n", tag, value );
+	}
+
 	fprintf( fp, "ER  - \n" );
 	fflush( fp );
 }
 
-void
+static int
+append_data( fields *in, param *p, fields *out )
+{
+	int type, status = BIBL_OK;
+
+	type = get_type( in, p );
+
+	append_type      ( type, p, out, &status );
+	append_allpeople ( in, type, out, &status );
+	append_date      ( in, out, &status );
+	append_alltitles ( in, type, out, &status );
+	append_pages     ( in, out, &status );
+	append_easy      ( in, "VOLUME",             "VL", LEVEL_ANY, out, &status );
+	append_easy      ( in, "ISSUE",              "IS", LEVEL_ANY, out, &status );
+	append_easy      ( in, "NUMBER",             "IS", LEVEL_ANY, out, &status );
+	append_easy      ( in, "EDITION",            "ET", LEVEL_ANY, out, &status );
+	append_easy      ( in, "NUMVOLUMES",         "NV", LEVEL_ANY, out, &status );
+	append_easy      ( in, "AUTHORADDRESS",      "AD", LEVEL_ANY, out, &status );
+	append_easy      ( in, "PUBLISHER",          "PB", LEVEL_ANY, out, &status );
+	append_easy      ( in, "DEGREEGRANTOR",      "PB", LEVEL_ANY, out, &status );
+	append_easy      ( in, "DEGREEGRANTOR:ASIS", "PB", LEVEL_ANY, out, &status );
+	append_easy      ( in, "DEGREEGRANTOR:CORP", "PB", LEVEL_ANY, out, &status );
+	append_easy      ( in, "ADDRESS",            "CY", LEVEL_ANY, out, &status );
+	append_keywords  ( in, out, &status );
+	append_easy      ( in, "ABSTRACT",           "AB", LEVEL_ANY, out, &status );
+	append_easy      ( in, "CALLNUMBER",         "CN", LEVEL_ANY, out, &status );
+	append_easy      ( in, "ISSN",               "SN", LEVEL_ANY, out, &status );
+	append_easy      ( in, "ISBN",               "SN", LEVEL_ANY, out, &status );
+	append_file      ( in, "FILEATTACH",         "L1", LEVEL_ANY, out, &status );
+	append_file      ( in, "FIGATTACH",          "L4", LEVEL_ANY, out, &status );
+	append_easy      ( in, "CAPTION",            "CA", LEVEL_ANY, out, &status );
+	append_urls      ( in, out, &status );
+	append_easyall   ( in, "DOI",                "DO", LEVEL_ANY, out, &status );
+	append_easy      ( in, "LANGUAGE",           "LA", LEVEL_ANY, out, &status );
+	append_easy      ( in, "NOTES",              "N1", LEVEL_ANY, out, &status );
+	append_easy      ( in, "REFNUM",             "ID", LEVEL_ANY, out, &status );
+	append_thesishint( type, out, &status );
+
+	return status;
+}
+
+static int
+risout_write( fields *in, FILE *fp, param *p, unsigned long refnum )
+{
+	int status;
+	fields out;
+
+	fields_init( &out );
+
+	status = append_data( in, p, &out );
+	if ( status==BIBL_OK ) output( fp, &out );
+
+	fields_free( &out );
+
+	return status;
+}
+
+static void
 risout_writeheader( FILE *outptr, param *p )
 {
 	if ( p->utf8bom ) utf8_writebom( outptr );
 }
-
diff --git a/lib/risout.h b/lib/risout.h
deleted file mode 100644
index 96fe0b4..0000000
--- a/lib/risout.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * risout.h
- *
- * Copyright (c) Chris Putnam 2005-2015
- *
- * Source code released under the GPL version 2
- *
- */
-#ifndef RISOUT_H
-#define RISOUT_H
-
-#include <stdio.h>
-#include "bibutils.h"
-
-extern void risout_write( fields *info, FILE *fp, param *p,
-		unsigned long refnum );
-extern void risout_writeheader( FILE *outptr, param *p );
-
-extern void risout_initparams( param *p, const char *progname );
-
-
-#endif
diff --git a/lib/ristypes.c b/lib/ristypes.c
index 2580b79..257a7c8 100644
--- a/lib/ristypes.c
+++ b/lib/ristypes.c
@@ -1,7 +1,7 @@
 /*
  * ristypes.c
  *
- * Copyright (c) Chris Putnam 2003-2015
+ * Copyright (c) Chris Putnam 2003-2016
  *
  * Source code released under the GPL version 2
  *
@@ -34,13 +34,13 @@ static lookups generic[] = {
 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */
 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Name of Database */
 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */
 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
@@ -62,13 +62,13 @@ static lookups generic[] = {
 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */
 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Resarch Notes -> Notes */
+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Resarch Notes -> Notes */
 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */
 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
@@ -80,11 +80,11 @@ static lookups generic[] = {
 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */
 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated? */
-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated? */
+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */
 };
 
 static lookups article[] = {
@@ -108,13 +108,13 @@ static lookups article[] = {
 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */
 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
 	{ "ED", "EDITOR",       PERSON,  LEVEL_HOST },   /* Deprecated? */
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */
 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
@@ -136,13 +136,13 @@ static lookups article[] = {
 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_HOST },   /* Publisher */
-	{ "PY", "PARTYEAR",     DATE,    LEVEL_MAIN },   /* Year */
+	{ "PY", "PARTDATE:YEAR",DATE,    LEVEL_MAIN },   /* Year */
 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */
 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_HOST },   /* ISBN/ISSN */
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */
 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
@@ -154,12 +154,12 @@ static lookups article[] = {
 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */
 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
-	{ "Y1", "PARTYEAR",     DATE,    LEVEL_MAIN },   /* Deprecated */
-	{ "Y2", "PARTMONTH",    SIMPLE,  LEVEL_MAIN },   /* Access Date */
-	{ "  ", "INTERNAL_TYPE|ARTICLE",           ALWAYS, LEVEL_MAIN },
+	{ "Y1", "PARTDATE:YEAR",DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "PARTDATE:MONTH",SIMPLE, LEVEL_MAIN },   /* Access Date */
+	{ "  ", "INTERNAL_TYPE|ARTICLE",  ALWAYS, LEVEL_MAIN },
 	{ "  ", "ISSUANCE|continuing",    ALWAYS, LEVEL_HOST },
 	{ "  ", "RESOURCE|text",          ALWAYS, LEVEL_MAIN },
 	{ "  ", "GENRE|journal article",  ALWAYS, LEVEL_MAIN },
@@ -189,13 +189,13 @@ static lookups magarticle[] = {
 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */
 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
 	{ "ED", "EDITOR",       PERSON,  LEVEL_HOST },   /* Deprecated? */
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */
 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
@@ -217,13 +217,13 @@ static lookups magarticle[] = {
 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_HOST },   /* Publisher */
-	{ "PY", "PARTYEAR",     DATE,    LEVEL_MAIN },   /* Year */
+	{ "PY", "PARTDATE:YEAR",DATE,    LEVEL_MAIN },   /* Year */
 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */
 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_HOST },   /* ISBN/ISSN */
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */
 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
@@ -235,11 +235,11 @@ static lookups magarticle[] = {
 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */
 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
-	{ "Y1", "PARTYEAR",     DATE,    LEVEL_MAIN },   /* Deprecated */
-	{ "Y2", "PARTMONTH",    SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "Y1", "PARTDATE:YEAR",DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "PARTDATE:MONTH",SIMPLE, LEVEL_MAIN },   /* Access Date */
 	{ "  ", "ISSUANCE|continuing",    ALWAYS, LEVEL_HOST },
 	{ "  ", "RESOURCE|text",          ALWAYS, LEVEL_MAIN },
 	{ "  ", "GENRE|periodical",       ALWAYS, LEVEL_HOST },
@@ -267,13 +267,13 @@ static lookups newsarticle[] = {
 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */
 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
 	{ "ED", "EDITOR",       PERSON,  LEVEL_HOST },   /* Deprecated? */
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */
 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
@@ -295,13 +295,13 @@ static lookups newsarticle[] = {
 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_HOST },   /* Publisher */
-	{ "PY", "PARTYEAR",     DATE,    LEVEL_MAIN },   /* Year */
+	{ "PY", "PARTDATE:YEAR",DATE,    LEVEL_MAIN },   /* Year */
 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */
 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_HOST },   /* ISBN/ISSN */
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */
 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
@@ -313,15 +313,15 @@ static lookups newsarticle[] = {
 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */
 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
-	{ "Y1", "PARTYEAR",     DATE,    LEVEL_MAIN },   /* Deprecated */
-	{ "Y2", "PARTMONTH",    SIMPLE,  LEVEL_MAIN },   /* Access Date */
-	{ "  ", "INTERNAL_TYPE|NEWSARTICLE",       ALWAYS, LEVEL_MAIN },
-	{ "  ", "ISSUANCE|continuing",    ALWAYS, LEVEL_HOST },
-	{ "  ", "RESOURCE|text",          ALWAYS, LEVEL_MAIN },
-	{ "  ", "GENRE|newspaper",        ALWAYS, LEVEL_HOST }
+	{ "Y1", "PARTDATE:YEAR",DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "PARTDATE:MONTH",SIMPLE, LEVEL_MAIN },   /* Access Date */
+	{ "  ", "INTERNAL_TYPE|NEWSARTICLE", ALWAYS, LEVEL_MAIN },
+	{ "  ", "ISSUANCE|continuing",       ALWAYS, LEVEL_HOST },
+	{ "  ", "RESOURCE|text",             ALWAYS, LEVEL_MAIN },
+	{ "  ", "GENRE|newspaper",           ALWAYS, LEVEL_HOST }
 };
 
 static lookups book[] = {
@@ -346,13 +346,13 @@ static lookups book[] = {
 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */
 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */
 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
@@ -374,13 +374,13 @@ static lookups book[] = {
 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */
 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */
 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */
 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title -- here abbreviated title for series*/
@@ -392,14 +392,14 @@ static lookups book[] = {
 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */
 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
-	{ "  ", "ISSUANCE|monographic",  ALWAYS, LEVEL_MAIN },
-	{ "  ", "GENRE|book",    ALWAYS, LEVEL_MAIN },
-	{ "  ", "RESOURCE|text", ALWAYS, LEVEL_MAIN }
+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "  ", "ISSUANCE|monographic",   ALWAYS, LEVEL_MAIN },
+	{ "  ", "GENRE|book",             ALWAYS, LEVEL_MAIN },
+	{ "  ", "RESOURCE|text",          ALWAYS, LEVEL_MAIN }
 };
 
 static lookups inbook[] = {
@@ -424,13 +424,13 @@ static lookups inbook[] = {
 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_HOST },   /* Deprecated? */
 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_HOST },   /* Place Published */
-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */
 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
 	{ "ED", "EDITOR",       PERSON,  LEVEL_HOST },   /* Deprecated? */
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */
 	{ "ET", "EDITION",      SIMPLE,  LEVEL_HOST },   /* Edition */
 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_HOST },   /* Number */
@@ -452,13 +452,13 @@ static lookups inbook[] = {
 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_HOST },   /* Publisher */
-	{ "PY", "YEAR",         DATE,    LEVEL_HOST },   /* Year */
+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_HOST },   /* Year */
 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */
 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_HOST },   /* ISBN/ISSN */
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */
 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_SERIES }, /* 'Secondary' Title -- here abbreviated title for series*/
@@ -470,11 +470,11 @@ static lookups inbook[] = {
 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */
 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_HOST },   /* Volume */
 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_HOST },   /* Deprecated? */
-	{ "Y1", "YEAR",         DATE,    LEVEL_HOST },   /* Deprecated */
-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_HOST },   /* Access Date */
+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_HOST },   /* Deprecated */
+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_HOST },   /* Access Date */
 	{ "  ", "GENRE|book chapter",   ALWAYS, LEVEL_MAIN },
 	{ "  ", "GENRE|book",           ALWAYS, LEVEL_HOST },
 	{ "  ", "ISSUANCE|monographic", ALWAYS, LEVEL_HOST },
@@ -502,13 +502,13 @@ static lookups conference[] = {
 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */
 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */
 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
@@ -530,13 +530,13 @@ static lookups conference[] = {
 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_HOST },   /* Publisher */
-	{ "PY", "YEAR",         DATE,    LEVEL_HOST },   /* Year */
+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_HOST },   /* Year */
 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */
 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */
 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
 	{ "BT", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Book Title */
@@ -549,12 +549,12 @@ static lookups conference[] = {
 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */
 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
-	{ "Y1", "YEAR",         DATE,    LEVEL_HOST },   /* Deprecated */
-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_HOST },   /* Access Date */
-	{ "  ", "INTERNAL_TYPE|CONFERENCE",       ALWAYS, LEVEL_MAIN },
+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_HOST },   /* Deprecated */
+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_HOST },   /* Access Date */
+	{ "  ", "INTERNAL_TYPE|CONFERENCE",     ALWAYS, LEVEL_MAIN },
 	{ "  ", "RESOURCE|text",                ALWAYS, LEVEL_MAIN },
 	{ "  ", "GENRE|conference publication", ALWAYS, LEVEL_HOST }
 };
@@ -581,13 +581,13 @@ static lookups statute[] = {
 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */
 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */
 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
@@ -609,13 +609,13 @@ static lookups statute[] = {
 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */
 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */
 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */
 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
@@ -627,12 +627,12 @@ static lookups statute[] = {
 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */
 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
-	{ "  ", "INTERNAL_TYPE|STATUTE",          ALWAYS, LEVEL_MAIN },
+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "  ", "INTERNAL_TYPE|STATUTE", ALWAYS, LEVEL_MAIN },
 	{ "  ", "RESOURCE|text",         ALWAYS, LEVEL_MAIN },
 	{ "  ", "GENRE|legislation",     ALWAYS, LEVEL_MAIN }
 };
@@ -659,13 +659,13 @@ static lookups hearing[] = {
 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */
 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */
 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
@@ -687,13 +687,13 @@ static lookups hearing[] = {
 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */
 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */
 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */
 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
@@ -705,11 +705,11 @@ static lookups hearing[] = {
 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */
 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */
 	{ "  ", "INTERNAL_TYPE|HEARING", ALWAYS, LEVEL_MAIN },
 	{ "  ", "GENRE|hearing",         ALWAYS, LEVEL_MAIN }
 };
@@ -736,13 +736,13 @@ static lookups cases[] = {
 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */
 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */
 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
@@ -764,13 +764,13 @@ static lookups cases[] = {
 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */
 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */
 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */
 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
@@ -782,11 +782,11 @@ static lookups cases[] = {
 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */
 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */
 	{ "  ", "INTERNAL_TYPE|CASE",              ALWAYS, LEVEL_MAIN },
 	{ "  ", "GENRE|legal case and case notes", ALWAYS, LEVEL_MAIN }
 };
@@ -813,13 +813,13 @@ static lookups communication[] = {
 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */
 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */
 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
@@ -841,13 +841,13 @@ static lookups communication[] = {
 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */
 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */
 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */
 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
@@ -859,11 +859,11 @@ static lookups communication[] = {
 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */
 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */
 	{ "  ", "INTERNAL_TYPE|ARTICLE", ALWAYS, LEVEL_MAIN },
 	{ "  ", "GENRE|communication",   ALWAYS, LEVEL_MAIN }
 };
@@ -890,13 +890,13 @@ static lookups thesis[] = {
 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */
 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */
 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
@@ -918,13 +918,13 @@ static lookups thesis[] = {
 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */
 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */
 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */
 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
@@ -936,11 +936,11 @@ static lookups thesis[] = {
 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */
 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */
 	{ "  ", "INTERNAL_TYPE|THESIS",  ALWAYS,  LEVEL_MAIN },
 	{ "  ", "RESOURCE|text",         ALWAYS,  LEVEL_MAIN },
 	{ "  ", "GENRE|thesis",          ALWAYS,  LEVEL_MAIN },
@@ -968,13 +968,13 @@ static lookups report[] = {
 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */
 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */
 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
@@ -996,13 +996,13 @@ static lookups report[] = {
 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */
 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */
 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */
 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
@@ -1014,11 +1014,11 @@ static lookups report[] = {
 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */
 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */
 	{ "  ", "INTERNAL_TYPE|REPORT",  ALWAYS,  LEVEL_MAIN },
 	{ "  ", "RESOURCE|text",         ALWAYS,  LEVEL_MAIN },
 	{ "  ", "GENRE|report",          ALWAYS,  LEVEL_MAIN }
@@ -1046,13 +1046,13 @@ static lookups abstract[] = {
 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */
 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */
 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
@@ -1074,13 +1074,13 @@ static lookups abstract[] = {
 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */
 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */
 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */
 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
@@ -1092,11 +1092,11 @@ static lookups abstract[] = {
 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */
 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */
 	{ "  ", "GENRE|abstract or summary", ALWAYS,  LEVEL_MAIN }
 };
 
@@ -1122,13 +1122,13 @@ static lookups program[] = {
 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */
 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */
 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
@@ -1150,13 +1150,13 @@ static lookups program[] = {
 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */
 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */
 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */
 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
@@ -1168,11 +1168,11 @@ static lookups program[] = {
 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */
 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */
 	{ "  ", "RESOURCE|software, multimedia", ALWAYS, LEVEL_MAIN }
 };
 
@@ -1198,13 +1198,13 @@ static lookups patent[] = {
 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */
 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */
 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
@@ -1226,13 +1226,13 @@ static lookups patent[] = {
 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */
 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */
 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */
 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
@@ -1244,11 +1244,11 @@ static lookups patent[] = {
 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */
 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */
 	{ "  ", "RESOURCE|text", ALWAYS, LEVEL_MAIN },
 	{ "  ", "GENRE|patent",  ALWAYS, LEVEL_MAIN }
 };
@@ -1275,13 +1275,13 @@ static lookups electric[] = {
 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */
 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */
 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
@@ -1303,13 +1303,13 @@ static lookups electric[] = {
 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */
 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */
 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */
 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
@@ -1321,11 +1321,11 @@ static lookups electric[] = {
 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */
 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */
 	{ " ",  "RESOURCE|software, multimedia", ALWAYS, LEVEL_MAIN },
 	{ " ",  "GENRE|electronic",              ALWAYS, LEVEL_MAIN },
 };
@@ -1352,13 +1352,13 @@ static lookups pamphlet[] = {
 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */
 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */
 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
@@ -1380,13 +1380,13 @@ static lookups pamphlet[] = {
 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */
 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */
 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */
 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
@@ -1398,11 +1398,11 @@ static lookups pamphlet[] = {
 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */
 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */
 	{ " ",  "RESOURCE|text",  ALWAYS, LEVEL_MAIN },
 	{ " ",  "GENRE|pamphlet", ALWAYS, LEVEL_MAIN },
 };
@@ -1429,13 +1429,13 @@ static lookups map[] = {
 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */
 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Name of Database */
 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */
 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
@@ -1457,13 +1457,13 @@ static lookups map[] = {
 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */
 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Resarch Notes -> Notes */
+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Resarch Notes -> Notes */
 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */
 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
@@ -1475,11 +1475,11 @@ static lookups map[] = {
 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */
 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated? */
-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated? */
+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */
 	{ " ",  "RESOURCE|cartographic",   ALWAYS, LEVEL_MAIN },
 	{ " ",  "GENRE|map",               ALWAYS, LEVEL_MAIN }
 };
@@ -1506,13 +1506,13 @@ static lookups unpublished[] = {
 	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
-	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DA", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Date */
 	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
 	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
 	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
 	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
 	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "EP", "PAGES:STOP",   SIMPLE,  LEVEL_MAIN },   /* End Page */
 	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
 	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
 	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
@@ -1534,13 +1534,13 @@ static lookups unpublished[] = {
 	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
 	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
 	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "PY", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Year */
 	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
-	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RN", "NOTES",        NOTES,   LEVEL_MAIN },   /* Research Notes */
 	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
 	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
 	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "SP", "PAGES:START",  SIMPLE,  LEVEL_MAIN },   /* Start Page */
 	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
 	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
 	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
@@ -1552,13 +1552,13 @@ static lookups unpublished[] = {
 	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
 	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "UR", "URL",          URL,     LEVEL_MAIN },   /* URL */
 	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
 	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
-	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
-	{ " ",         "RESOURCE|text",   ALWAYS, LEVEL_MAIN },
-	{ " ",         "GENRE|unpublished",      ALWAYS, LEVEL_MAIN }
+	{ "Y1", "DATE:YEAR",    DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "DATE:MONTH",   SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ " ",  "RESOURCE|text",     ALWAYS, LEVEL_MAIN },
+	{ " ",  "GENRE|unpublished", ALWAYS, LEVEL_MAIN }
 };
 
 #define ORIG(a) ( &(a[0]) )
diff --git a/lib/serialno.c b/lib/serialno.c
index e9fcbf2..091a02c 100644
--- a/lib/serialno.c
+++ b/lib/serialno.c
@@ -1,7 +1,7 @@
 /*
  * serialno.c
  *
- * Copyright (c) Chris Putnam 2005-2015
+ * Copyright (c) Chris Putnam 2005-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/lib/serialno.h b/lib/serialno.h
index f96dc2e..f5c3022 100644
--- a/lib/serialno.h
+++ b/lib/serialno.h
@@ -1,7 +1,7 @@
 /*
  * serialno.h
  *
- * Copyright (c) Chris Putnam 2005-2015
+ * Copyright (c) Chris Putnam 2005-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/lib/strsearch.c b/lib/strsearch.c
index 77fc860..7e0d903 100644
--- a/lib/strsearch.c
+++ b/lib/strsearch.c
@@ -1,6 +1,6 @@
 /* strsearch.c
  *
- * Copyright (c) Chris Putnam 1995-2015
+ * Copyright (c) Chris Putnam 1995-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/lib/strsearch.h b/lib/strsearch.h
index 396247f..e2af6c3 100644
--- a/lib/strsearch.h
+++ b/lib/strsearch.h
@@ -1,7 +1,7 @@
 /*
  * strsearch.h
  *
- * Copyright (c) Chris Putnam 1995-2015
+ * Copyright (c) Chris Putnam 1995-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/lib/title.c b/lib/title.c
index b921b65..86a2d63 100644
--- a/lib/title.c
+++ b/lib/title.c
@@ -3,7 +3,7 @@
  *
  * process titles into title/subtitle pairs for MODS
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Source code released under the GPL version 2
  *
@@ -66,3 +66,35 @@ title_process( fields *info, char *tag, char *data, int level,
 	return 1;
 }
 
+/* title_combine()
+ *
+ * Combine a main title and a subtitle into a full title.
+ *
+ * Example:
+ * 	Main title = "A Clearing in the Distance"
+ * 	Subtitle   = "The Biography of Frederick Law Olmstead"
+ * 	Full title = "A Clearing in the Distance: The Biography of Frederick Law Olmstead"
+ * Example:
+ *	Main title = "What Makes a Good Team Player?"
+ *	Subtitle   = "Personality and Team Effectiveness"
+ *	Full title = "What Makes a Good Team Player? Personality and Team Effectiveness"
+ */
+void
+title_combine( newstr *fullttl, newstr *mainttl, newstr *subttl )
+{
+	newstr_empty( fullttl );
+
+	if ( !mainttl ) return;
+
+	newstr_newstrcpy( fullttl, mainttl );
+
+	if ( subttl ) {
+		if ( mainttl->len > 0 ) {
+			if ( mainttl->data[ mainttl->len - 1 ] != '?' )
+				newstr_strcat( fullttl, ": " );
+			else
+				newstr_strcat( fullttl, " " );
+		}
+		newstr_newstrcat( fullttl, subttl );
+	}
+}
diff --git a/lib/title.h b/lib/title.h
index 1f37d7d..07d00f9 100644
--- a/lib/title.h
+++ b/lib/title.h
@@ -3,7 +3,7 @@
  *
  * process titles into title/subtitle pairs for MODS
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Source code released under the GPL verison 2
  *
@@ -14,7 +14,7 @@
 #include "newstr.h"
 #include "fields.h"
 
-extern int title_process( fields *info, char *tag, char *data, int level,
-		unsigned char nosplittitle );
+int  title_process( fields *info, char *tag, char *data, int level, unsigned char nosplittitle );
+void title_combine( newstr *fullttl, newstr *mainttl, newstr *subttl );
 
 #endif
diff --git a/lib/unicode.h b/lib/unicode.h
index 9174e08..9efa087 100644
--- a/lib/unicode.h
+++ b/lib/unicode.h
@@ -1,7 +1,7 @@
 /*
  * unicode.h
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Program and source code released under the GPL version 2
  */
diff --git a/lib/url.c b/lib/url.c
new file mode 100644
index 0000000..d3137f9
--- /dev/null
+++ b/lib/url.c
@@ -0,0 +1,311 @@
+/*
+ * url.c
+ *
+ * doi_to_url()
+ * Handle outputing DOI as a URL (Endnote and RIS formats)
+ *     1) Append http://dx.doi.org as necessary
+ *     2) Check for overlap with pre-existing URL for the DOI
+ *
+ * is_doi()
+ * Check for DOI buried in another field.
+ *
+ * Copyright (c) Chris Putnam 2008-2016
+ *
+ * Source code released under the GPL version 2
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "bibutils.h"
+#include "url.h"
+
+static void
+construct_url( char *prefix, newstr *id, newstr *id_url, char sep )
+{
+	if ( !strncasecmp( id->data, "http:", 5 ) )
+		newstr_newstrcpy( id_url, id );
+	else {
+		newstr_strcpy( id_url, prefix );
+		if ( sep!='\0' ) {
+			if ( id->data[0]!=sep ) newstr_addchar( id_url, sep );
+		}
+		newstr_newstrcat( id_url, id );
+	}
+}
+
+static int
+url_exists( fields *f, char *urltag, newstr *doi_url )
+{
+	int i, n;
+	if ( urltag ) {
+		n = fields_num( f );
+		for ( i=0; i<n; ++i ) {
+			if ( strcmp( fields_tag( f, i, FIELDS_CHRP ), urltag ) ) continue;
+			if ( strcmp( fields_value( f, i, FIELDS_CHRP ), doi_url->data ) ) continue;
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static void
+xxx_to_url( fields *f, int n, char *http_prefix, char *urltag, newstr *xxx_url, char sep )
+{
+	newstr_empty( xxx_url );
+	construct_url( http_prefix, fields_value( f, n, FIELDS_STRP ), xxx_url, sep );
+	if ( url_exists( f, urltag, xxx_url ) )
+		newstr_empty( xxx_url );
+}
+void
+doi_to_url( fields *f, int n, char *urltag, newstr *url )
+{
+	xxx_to_url( f, n, "http://dx.doi.org", urltag, url, '/' );
+}
+void
+jstor_to_url( fields *f, int n, char *urltag, newstr *url )
+{
+	xxx_to_url( f, n, "http://www.jstor.org/stable", urltag, url, '/' );
+}
+void
+pmid_to_url( fields *f, int n, char *urltag, newstr *url )
+{
+	xxx_to_url( f, n, "http://www.ncbi.nlm.nih.gov/pubmed", urltag, url, '/' );
+}
+void
+pmc_to_url( fields *f, int n, char *urltag, newstr *url )
+{
+	xxx_to_url( f, n, "http://www.ncbi.nlm.nih.gov/pmc/articles", urltag, url, '/' );
+}
+void
+arxiv_to_url( fields *f, int n, char *urltag, newstr *url )
+{
+	xxx_to_url( f, n, "http://arxiv.org/abs", urltag, url, '/' );
+}
+void
+mrnumber_to_url( fields *f, int n, char *urltag, newstr *url )
+{
+	xxx_to_url( f, n, "http://www.ams.org/mathscinet-getitem?mr=", urltag, url, '\0' );
+}
+
+/* Rules for the pattern:
+ *   '#' = number
+ *   isalpha() = match precisely (matchcase==1) or match regardless of case
+ *   	(matchcase==0)
+ *   all others must match precisely
+ */
+static int
+string_pattern( char *s, char *pattern, int matchcase )
+{
+	int patlen, match, i;
+	patlen = strlen( pattern );
+	if ( strlen( s ) < patlen ) return 0; /* too short */
+	for ( i=0; i<patlen; ++i ) {
+		match = 0;
+		if ( pattern[i]=='#' ) {
+			if ( isdigit( (unsigned char)s[i] ) ) match = 1;
+		} else if ( !matchcase && isalpha( (unsigned char)pattern[i] ) ) {
+			if ( tolower((unsigned char)pattern[i])==tolower((unsigned char)s[i])) match = 1;
+		} else {
+			if ( pattern[i] == s[i] ) match = 1;
+		}
+		if ( !match ) return 0;
+	}
+	return 1;
+}
+
+/* science direct is now doing "M3  - doi: DOI: 10.xxxx/xxxxx" */
+int
+is_doi( char *s )
+{
+	if ( string_pattern( s, "##.####/", 0 ) ) return 0;
+	if ( string_pattern( s, "doi:##.####/", 0 ) ) return 4;
+	if ( string_pattern( s, "doi: ##.####/", 0 ) ) return 5;
+	if ( string_pattern( s, "doi: DOI: ##.####/", 0 ) ) return 10;
+	return -1;
+}
+
+/* determine if string has the header of a Universal Resource Identifier
+ *
+ * returns -1, if not true
+ * returns offset that skips over the URI scheme, if true
+ */
+int
+is_uri_remote_scheme( char *p )
+{
+	char *scheme[]   = { "http:", "https:", "ftp:", "git:", "gopher:" };
+	int  schemelen[] = { 5,       6,         4,       4,     7 };
+        int i, nschemes = sizeof( scheme ) / sizeof( scheme[0] );
+        for ( i=0; i<nschemes; ++i ) {
+                if ( !strncasecmp( p, scheme[i], schemelen[i] ) ) return schemelen[i];
+        }
+        return -1;
+}
+
+int
+is_reference_database( char *p )
+{
+	char *scheme[]   = { "arXiv:", "pubmed:", "medline:", "isi:" };
+	int  schemelen[] = { 6,        7,         8,          4 };
+        int i, nschemes = sizeof( scheme ) / sizeof( scheme[0] );
+        for ( i=0; i<nschemes; ++i ) {
+                if ( !strncasecmp( p, scheme[i], schemelen[i] ) ) return schemelen[i];
+        }
+        return -1;
+}
+
+/* many fields have been abused to embed URLs, DOIs, etc. */
+int
+is_embedded_link( char *s )
+{
+	if ( is_uri_remote_scheme( s ) != -1 ) return 1;
+	if ( is_reference_database( s ) != -1 ) return 1;
+	if ( is_doi( s ) !=-1 ) return 1;
+	return 0;
+}
+
+typedef struct url_t {
+	char *tag;
+	char *prefix;
+	int offset;
+} url_t;
+
+static url_t prefixes[] = {
+        /*              00000000001111111112222222222333333333344444444445 */
+        /*              12345678901234567890123456789012345678901234567890 */
+	{ "ARXIV",     "http://arxiv.org/abs/",                     21 },
+	{ "DOI",       "http://dx.doi.org/",                        18 },
+	{ "JSTOR",     "http://www.jstor.org/stable/",              28 },
+	{ "MRNUMBER",  "http://www.ams.org/mathscinet-getitem?mr=", 41 },
+	{ "PMID",      "http://www.ncbi.nlm.nih.gov/pubmed/",       35 },
+	{ "PMC",       "http://www.ncbi.nlm.nih.gov/pmc/articles/", 41 },
+	{ "ISIREFNUM", "isi:",                                       4 },
+};
+static int nprefixes = sizeof( prefixes ) / sizeof( prefixes[0] );
+
+/* do not add, but recognize */
+static url_t extraprefixes[] = {
+        /*              00000000001111111112222222222333333333344444444445 */
+        /*              12345678901234567890123456789012345678901234567890 */
+	{ "ARXIV",     "arXiv:",                                     6 },
+	{ "JSTOR",     "jstor:",                                     6 },
+	{ "PMID",      "pmid:",                                      5 },
+	{ "PMID",      "pubmed:",                                    7 },
+	{ "PMC",       "pmc:",                                       4 },
+	{ "URL",       "\\urllink",                                  8 },
+	{ "URL",       "\\url",                                      4 },
+};
+static int nextraprefixes = sizeof( extraprefixes ) / sizeof( extraprefixes[0] );
+
+static int
+find_prefix( char *s, url_t *p, int np )
+{
+	int i;
+
+	for ( i=0; i<np; ++i )
+		if ( !strncmp( p[i].prefix, s, p[i].offset ) ) return i;
+
+	return -1;
+}
+
+int
+urls_split_and_add( char *value_in, fields *out, int lvl_out )
+{
+	int n, fstatus, status = BIBL_OK;
+	char *tag = "URL";
+	int offset = 0;
+
+	n = find_prefix( value_in, prefixes, nprefixes );
+	if ( n!=-1 ) {
+		tag    = prefixes[n].tag;
+		offset = prefixes[n].offset;
+	} else {
+		n = find_prefix( value_in, extraprefixes, nextraprefixes );
+		if ( n!=-1 ) {
+			tag    = extraprefixes[n].tag;
+			offset = extraprefixes[n].offset;
+		}
+	}
+
+	fstatus = fields_add( out, tag, &(value_in[offset]), lvl_out );
+	if ( fstatus!=FIELDS_OK ) status = BIBL_ERR_MEMERR;
+
+	return status;
+}
+
+/* urls_add_type()
+ *
+ * Append urls of a specific type with a specific prefix (which can be empty).
+ * We don't allow duplications here.
+ *
+ */
+static int
+urls_merge_and_add_type( fields *out, char *tag_out, int lvl_out, char *prefix, vplist *values )
+{
+	int i, fstatus, status = BIBL_OK;
+	newstr url;
+
+	newstr_init( &url );
+
+	for ( i=0; i<values->n; ++i ) {
+		newstr_strcpy( &url, prefix );
+		newstr_strcat( &url, ( char * ) vplist_get( values, i ) );
+		fstatus = fields_add( out, tag_out, newstr_cstr( &url ), lvl_out );
+		if ( fstatus!=FIELDS_OK ) {
+			status = BIBL_ERR_MEMERR;
+			goto out;
+		}
+
+	}
+out:
+	newstr_free( &url );
+	return status;
+}
+
+/*
+ * urls_merge_and_add()
+ *
+ * Append urls of types controlled by the list type and automatically append appropriate
+ * prefixes. If no prefix is found for the entry, don't add one (e.g. "URL" entries).
+ *
+ * Control of the types to be added by list type is necessary as some reference formats
+ * like bibtex ought to do special things with DOI, ARXIV, MRNUMBER, and the like.
+ */
+int
+urls_merge_and_add( fields *in, int lvl_in, fields *out, char *tag_out, int lvl_out, list *types )
+{
+	int i, j, status = BIBL_OK;
+	char *tag, *prefix, *empty="";
+	vplist a;
+
+	vplist_init( &a );
+
+	for ( i=0; i<types->n; ++i ) {
+
+		tag = list_getc( types, i );
+
+		/* ...look for data of requested type; if not found skip */
+		vplist_empty( &a );
+		fields_findv_each( in, lvl_in, FIELDS_CHRP, &a, tag );
+		if ( a.n==0 ) continue;
+
+		/* ...find the prefix (if present) */
+		prefix = empty;
+		for ( j=0; j<nprefixes; ++j ) {
+			if ( !strcmp( prefixes[j].tag, tag ) ) {
+				prefix = prefixes[j].prefix;
+				break; /* take the first prefix in the list */
+			}
+		}
+
+		/* ...append all data of this type */
+		status = urls_merge_and_add_type( out, tag_out, lvl_out, prefix, &a );
+		if ( status!=BIBL_OK ) goto out;
+	}
+
+out:
+	vplist_free( &a );
+
+	return status;
+}
diff --git a/lib/url.h b/lib/url.h
new file mode 100644
index 0000000..86824b3
--- /dev/null
+++ b/lib/url.h
@@ -0,0 +1,30 @@
+/*
+ * url.h
+ *
+ * Copyright (c) Chris Putnam 2004-2016
+ *
+ * Source code released under the GPL version 2
+ *
+ */
+#ifndef URL_H
+#define URL_H
+
+#include "list.h"
+#include "fields.h"
+
+int is_doi( char *s );
+int is_uri_remote_scheme( char *p );
+int is_embedded_link( char *s );
+
+void doi_to_url( fields *info, int n, char *urltag, newstr *doi_url );
+void pmid_to_url( fields *info, int n, char *urltag, newstr *pmid_url );
+void pmc_to_url( fields *info, int n, char *urltag, newstr *pmid_url );
+void arxiv_to_url( fields *info, int n, char *urltag, newstr *arxiv_url );
+void jstor_to_url( fields *info, int n, char *urltag, newstr *jstor_url );
+void mrnumber_to_url( fields *info, int n, char *urltag, newstr *jstor_url );
+
+int urls_merge_and_add( fields *in, int lvl_in, fields *out, char *tag_out, int lvl_out, list *types );
+int urls_split_and_add( char *value_in, fields *out, int lvl_out );
+
+
+#endif
diff --git a/lib/utf8.c b/lib/utf8.c
index 93afe37..bb377ca 100644
--- a/lib/utf8.c
+++ b/lib/utf8.c
@@ -1,12 +1,13 @@
 /*
  * utf8.c
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Source code released under the GPL version 2
  *
  */
 #include <stdio.h>
+#include <string.h>
 #include "utf8.h"
 
 /* UTF-8 encoding
@@ -148,3 +149,27 @@ utf8_writebom( FILE *outptr )
 		fprintf(outptr,"%c",code[i]);
 }
 
+/* utf8_is_emdash()
+ *
+ *emdash = 0xE2 (-30) 0x80 (-128) 0x94 (-108)
+ */
+int
+utf8_is_emdash( char *p )
+{
+	const char emdash[3] = { -30, -128, -108 };
+	if ( strncmp( p, emdash, 3 ) ) return 0;
+	return 1;
+}
+
+/* utf8_is_endash()
+ *
+ * endash = 0xE2 (-30) 0x80 (-128) 0x93 (-109)
+ */
+int
+utf8_is_endash( char *p )
+{
+	const char endash[3] = { -30, -128, -109 };
+	if ( strncmp( p, endash, 3 ) ) return 0;
+	return 1;
+}
+
diff --git a/lib/utf8.h b/lib/utf8.h
index be3b973..4e0f507 100644
--- a/lib/utf8.h
+++ b/lib/utf8.h
@@ -1,7 +1,7 @@
 /*
  * utf8.h
  *
- * Copyright (c) Chris Putnam 2004-2015
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Source code released under the GPL version 2
  *
@@ -11,10 +11,11 @@
 
 #include <stdio.h>
 
-extern int utf8_encode( unsigned int value, unsigned char out[6] );
-extern void utf8_encode_str( unsigned int value, char outstr[7] );
-extern unsigned int utf8_decode( char *s, unsigned int *pi );
-extern void utf8_writebom( FILE *outptr );
-
+int          utf8_encode( unsigned int value, unsigned char out[6] );
+void         utf8_encode_str( unsigned int value, char outstr[7] );
+unsigned int utf8_decode( char *s, unsigned int *pi );
+void         utf8_writebom( FILE *outptr );
+int          utf8_is_emdash( char *p );
+int          utf8_is_endash( char *p );
 
 #endif
diff --git a/lib/vplist.c b/lib/vplist.c
index ac90457..1eeae9a 100644
--- a/lib/vplist.c
+++ b/lib/vplist.c
@@ -1,9 +1,9 @@
 /*
  * vplist.c
  *
- * Version: 4/08/2013
+ * Version: 11/20/2014
  *
- * Copyright (c) Chris Putnam 2011-2015
+ * Copyright (c) Chris Putnam 2011-2016
  *
  * Source code released under the GPL version 2
  *
@@ -11,9 +11,14 @@
  *
  */
 #include <stdlib.h>
-#include <assert.h>
 #include "vplist.h"
 
+/* Do not use asserts in VPLIST_NOASSERT defined */
+#ifdef VPLIST_NOASSERT
+#define NDEBUG
+#endif
+#include <assert.h>
+
 void
 vplist_init( vplist *vpl )
 {
@@ -50,26 +55,26 @@ vplist_copy( vplist *to, vplist *from )
 	if ( from->n > to->max ) {
 		if ( to->max ) free( to->data );
 		to->data = ( void ** ) malloc( sizeof( void * ) * from->n );
-		if ( !to->data ) return 0;
+		if ( !to->data ) return VPLIST_ERR;
 		to->max = from->n;
 	}
 	for ( i=0; i<from->n; ++i )
 		to->data[i] = from->data[i];
 	to->n = from->n;
-	return 1;
+	return VPLIST_OK;
 }
 
 int
 vplist_append( vplist *to, vplist *from )
 {
-	int i, ok;
+	int i, status;
 	assert( to );
 	assert( from );
 	for ( i=0; i<from->n; ++i ) {
-		ok = vplist_add( to, from->data[i] );
-		if ( !ok ) return 0;
+		status = vplist_add( to, from->data[i] );
+		if ( status!=VPLIST_OK ) return status;
 	}
-	return 1;
+	return VPLIST_OK;
 }
 
 static int
@@ -84,10 +89,10 @@ vplist_alloc( vplist *vpl )
 {
 	int alloc = 20;
 	vpl->data = ( void ** ) malloc( sizeof( void * ) * alloc );
-	if ( !vpl->data ) return 0;
+	if ( !vpl->data ) return VPLIST_ERR;
 	vpl->max = alloc;
 	vpl->n = 0;
-	return 1;
+	return VPLIST_OK;
 }
 
 static int
@@ -96,29 +101,29 @@ vplist_realloc( vplist *vpl )
 	void **more;
 	int alloc = vpl->max * 2;
 	more = ( void ** ) realloc( vpl->data, sizeof( void * ) * alloc );
-	if ( !more ) return 0;
+	if ( !more ) return VPLIST_ERR;
 	vpl->data = more;
 	vpl->max = alloc;
-	return 1;
+	return VPLIST_OK;
 }
 
 int
 vplist_add( vplist *vpl, void *v )
 {
-	int ok = 1;
+	int status = VPLIST_OK;
 
 	assert( vpl );
 
 	/* ensure sufficient space */
-	if ( vpl->max==0 ) ok = vplist_alloc( vpl );
-	else if ( vpl->n >= vpl->max ) ok = vplist_realloc( vpl );
+	if ( vpl->max==0 ) status = vplist_alloc( vpl );
+	else if ( vpl->n >= vpl->max ) status = vplist_realloc( vpl );
 
-	if ( ok ) {
+	if ( status==VPLIST_OK ) {
 		vpl->data[vpl->n] = v;
 		vpl->n++;
 	}
 
-	return ok;
+	return status;
 }
 
 void *
@@ -133,16 +138,35 @@ void
 vplist_set( vplist *vpl, int n, void *v )
 {
 	assert( vpl );
-	if ( !vplist_validindex( vpl, n ) ) return;
+	assert( vplist_validindex( vpl, n ) );
+
 	vpl->data[ n ] = v;
 }
 
 void
+vplist_swap( vplist *vpl, int n1, int n2 )
+{
+	void *v1, *v2;
+
+	assert( vpl );
+	assert( vplist_validindex( vpl, n1 ) );
+	assert( vplist_validindex( vpl, n2 ) );
+
+	v1 = vpl->data[n1];
+	v2 = vpl->data[n2];
+
+	vpl->data[n1] = v2;
+	vpl->data[n2] = v1;
+}
+
+void
 vplist_remove( vplist *vpl, int n )
 {
 	int i;
+
 	assert( vpl );
-	if ( !vplist_validindex( vpl, n ) ) return;
+	assert( vplist_validindex( vpl, n ) );
+
 	for ( i=n+1; i<vpl->n; ++i )
 		vpl->data[ i-1 ] = vpl->data[ i ];
 	vpl->n -= 1;
@@ -162,9 +186,12 @@ vplist_removevp( vplist *vpl, void *v )
 static void
 vplist_freemembers( vplist *vpl, vplist_ptrfree vpf )
 {
+	void *v;
 	int i;
-	for ( i=0; i<vpl->n; ++i )
-		(*vpf)( vplist_get( vpl, i ) );
+	for ( i=0; i<vpl->n; ++i ) {
+		v = vplist_get( vpl, i );
+		if ( v ) (*vpf)( v );
+	}
 }
 
 void
@@ -199,7 +226,7 @@ vplist_freefn( vplist *vpl, vplist_ptrfree vpf )
 }
 
 void
-vplist_destroy( vplist **vpl )
+vplist_delete( vplist **vpl )
 {
 	assert( *vpl );
 	vplist_free( *vpl );
@@ -208,9 +235,9 @@ vplist_destroy( vplist **vpl )
 }
 
 void
-vplist_destroyfn( vplist **vpl, vplist_ptrfree vpf )
+vplist_deletefn( vplist **vpl, vplist_ptrfree vpf )
 {
 	assert( *vpl );
 	vplist_freemembers( *vpl, vpf );
-	vplist_destroy( vpl );
+	vplist_delete( vpl );
 }
diff --git a/lib/vplist.h b/lib/vplist.h
index 7bea343..bd953e1 100644
--- a/lib/vplist.h
+++ b/lib/vplist.h
@@ -1,9 +1,9 @@
 /*
  * vplist.h
  *
- * Version: 4/08/2013
+ * Version: 11/20/2014
  *
- * Copyright (c) Chris Putnam 2011-2015
+ * Copyright (c) Chris Putnam 2011-2016
  *
  * Source code released under the GPL version 2
  *
@@ -12,6 +12,9 @@
 #ifndef VPLIST_H
 #define VPLIST_H
 
+#define VPLIST_ERR (1)
+#define VPLIST_OK  (0)
+
 /* vplist = void pointer list (generic container struct)
  */
 typedef struct vplist {
@@ -28,6 +31,7 @@ extern int      vplist_copy( vplist *to, vplist *from );
 extern int      vplist_append( vplist *to, vplist *from );
 extern void *   vplist_get( vplist *vpl, int n );
 extern void     vplist_set( vplist *vpl, int n, void *v );
+extern void     vplist_swap( vplist *vpl, int n1, int n2 );
 extern void     vplist_remove( vplist *vpl, int n );
 extern void     vplist_removevp( vplist *vpl, void *v );
 extern int      vplist_find( vplist *vpl, void *v );
@@ -59,10 +63,10 @@ extern void   vplist_emptyfn( vplist *vpl, vplist_ptrfree fn );
 extern void vplist_free( vplist *vpl );
 extern void vplist_freefn( vplist *vpl, vplist_ptrfree fn );
 /*
- * vplist_destroy does vplist_free and deallocates the struct
+ * vplist_delete does vplist_free and deallocates the struct
  * vplist * and replaces with NULL.
  */
-extern void vplist_destroy( vplist **vpl );
-extern void vplist_destroyfn( vplist **vpl, vplist_ptrfree fn );
+extern void vplist_delete( vplist **vpl );
+extern void vplist_deletefn( vplist **vpl, vplist_ptrfree fn );
 
 #endif
diff --git a/lib/wordin.c b/lib/wordin.c
index 466287f..1274f2e 100644
--- a/lib/wordin.c
+++ b/lib/wordin.c
@@ -1,7 +1,7 @@
 /*
  * wordin.c
  *
- * Copyright (c) Chris Putnam 2010-2013
+ * Copyright (c) Chris Putnam 2010-2016
  *
  * Source code released under the GPL version 2
  *
@@ -14,7 +14,11 @@
 #include "fields.h"
 #include "xml.h"
 #include "xml_encoding.h"
-#include "wordin.h"
+#include "bibformats.h"
+
+static int wordin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );
+static int wordin_processf( fields *wordin, char *data, char *filename, long nref, param *p );
+
 
 /*****************************************************
  PUBLIC: void wordin_initparams()
@@ -68,7 +72,7 @@ wordin_findendwrapper( char *buf, int ntype )
 	return endptr;
 }
 
-int
+static int
 wordin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset )
 {
 	newstr tmp;
@@ -223,7 +227,7 @@ wordin_pages( xml *node, fields *info )
 	}
 
 	if ( sp.len ) {
-		status = fields_add( info, "PAGESTART", sp.data, 1 );
+		status = fields_add( info, "PAGES:START", sp.data, 1 );
 		if ( status!=FIELDS_OK ) {
 			ret = BIBL_ERR_MEMERR;
 			goto out;
@@ -234,9 +238,9 @@ wordin_pages( xml *node, fields *info )
 		if ( sp.len > ep.len ) {
 			for ( i=sp.len-ep.len; i<sp.len; ++i )
 				sp.data[i] = ep.data[i-sp.len+ep.len];
-			status = fields_add( info, "PAGEEND", sp.data, 1 );
+			status = fields_add( info, "PAGES:STOP", sp.data, 1 );
 		} else
-			status = fields_add( info, "PAGEEND", ep.data, 1 );
+			status = fields_add( info, "PAGES:STOP", ep.data, 1 );
 		if ( status!=FIELDS_OK ) {
 			ret = BIBL_ERR_MEMERR;
 			goto out;
@@ -299,8 +303,8 @@ wordin_assembleref( xml *node, fields *info )
 	return ret;
 }
 
-int
-wordin_processf( fields *wordin, char *data, char *filename, long nref )
+static int
+wordin_processf( fields *wordin, char *data, char *filename, long nref, param *p )
 {
 	int status, ret = 1;
 	xml top;
diff --git a/lib/wordin.h b/lib/wordin.h
deleted file mode 100644
index 2ae9f92..0000000
--- a/lib/wordin.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * wordin.h
- *
- * Copyright (c) Chris Putnam 2009-2013
- *
- * Source code released under the GPL version 2
- *
- */
-#ifndef WORDIN_H
-#define WORDIN_H
-
-#include "newstr.h"
-#include "fields.h"
-#include "reftypes.h"
-#include "bibutils.h"
-
-extern int wordin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset );
-extern int wordin_processf( fields *wordin, char *data, char *filename, long nref );
-
-extern void wordin_initparams( param *p, const char *progname );
-
-#endif
-
diff --git a/lib/wordout.c b/lib/wordout.c
index 30a49d9..6c519dd 100644
--- a/lib/wordout.c
+++ b/lib/wordout.c
@@ -3,7 +3,7 @@
  * 
  * (Word 2007 format)
  *
- * Copyright (c) Chris Putnam 2007-2014
+ * Copyright (c) Chris Putnam 2007-2016
  *
  * Source code released under the GPL version 2
  *
@@ -14,7 +14,11 @@
 #include "newstr.h"
 #include "fields.h"
 #include "utf8.h"
-#include "wordout.h"
+#include "bibformats.h"
+
+static void wordout_writeheader( FILE *outptr, param *p );
+static void wordout_writefooter( FILE *outptr );
+static int  wordout_write( fields *info, FILE *outptr, param *p, unsigned long numrefs );
 
 void
 wordout_initparams( param *p, const char *progname )
@@ -41,8 +45,9 @@ wordout_initparams( param *p, const char *progname )
 }
 
 typedef struct convert {
-	char oldtag[25];
-	char newtag[25];
+	char *oldtag;
+	char *newtag;
+	char *prefix;
 	int  code;
 } convert;
 
@@ -113,12 +118,12 @@ output_fixed( FILE *outptr, char *tag, char *data, int level )
  *
  */
 static void
-output_item( fields *info, FILE *outptr, char *tag, int item, int level )
+output_item( fields *info, FILE *outptr, char *tag, char *prefix, int item, int level )
 {
 	int i;
 	if ( item==-1 ) return;
 	for ( i=0; i<level; ++i ) fprintf( outptr, " " );
-	fprintf( outptr, "<%s>%s</%s>\n", tag, info->data[item].data, tag );
+	fprintf( outptr, "<%s>%s%s</%s>\n", tag, prefix, info->data[item].data, tag );
 	fields_setused( info, item );
 }
 
@@ -157,7 +162,7 @@ output_list( fields *info, FILE *outptr, convert *c, int nc )
         int i, n;
         for ( i=0; i<nc; ++i ) {
                 n = fields_find( info, c[i].oldtag, c[i].code );
-                if ( n!=-1 ) output_item( info, outptr, c[i].newtag, n, 0 );
+                if ( n!=-1 ) output_item( info, outptr, c[i].newtag, c[i].prefix, n, 0 );
         }
 
 }
@@ -220,7 +225,7 @@ get_type_from_genre( fields *info )
 			}
 			else if ( !strcasecmp( genre, "conference publication" ) ) {
 				if ( level==0 ) type=TYPE_CONFERENCE;
-				type = TYPE_PROCEEDINGS;
+				else type = TYPE_PROCEEDINGS;
 			}
 			else if ( !strcasecmp( genre, "thesis" ) ) {
 	                        if ( type==TYPE_UNKNOWN ) type=TYPE_THESIS;
@@ -262,43 +267,68 @@ get_type( fields *info )
 }
 
 static void
-output_titleinfo( fields *info, FILE *outptr, char *tag, int level )
+output_titlebits( char *mainttl, char *subttl, FILE *outptr )
+{
+	if ( mainttl ) fprintf( outptr, "%s", mainttl );
+	if ( subttl ) {
+		if ( mainttl ) {
+			if ( mainttl[ strlen( mainttl ) - 1 ] != '?' )
+				fprintf( outptr, ": " );
+			else fprintf( outptr, " " );
+		}
+		fprintf( outptr, "%s", subttl );
+	}
+}
+
+static void
+output_titleinfo( char *mainttl, char *subttl, FILE *outptr, char *tag, int level )
 {
-	newstr *mainttl = fields_findv( info, level, FIELDS_STRP, "TITLE" );
-	newstr *subttl  = fields_findv( info, level, FIELDS_STRP, "SUBTITLE" );
 	if ( mainttl || subttl ) {
 		fprintf( outptr, "<%s>", tag );
-		if ( mainttl ) fprintf( outptr, "%s", mainttl->data );
-		if ( subttl ) {
-			if ( mainttl ) {
-				if ( mainttl->len > 0 &&
-				     mainttl->data[mainttl->len-1]!='?' )
-					fprintf( outptr, ": " );
-				else fprintf( outptr, " " );
-			}
-			fprintf( outptr, "%s", subttl->data );
-		}
+		output_titlebits( mainttl, subttl, outptr );
 		fprintf( outptr, "</%s>\n", tag );
 	}
 }
 
 static void
-output_title( fields *info, FILE *outptr, int level )
+output_generaltitle( fields *info, FILE *outptr, char *tag, int level )
 {
-	char *ttl    = fields_findv( info, level, FIELDS_CHRP, "TITLE" );
-	char *subttl = fields_findv( info, level, FIELDS_CHRP, "SUBTITLE" );
-	char *shrttl = fields_findv( info, level, FIELDS_CHRP, "SHORTTITLE" );
-
-	output_titleinfo( info, outptr, "b:Title", level );
-
-	/* output shorttitle if it's different from normal title */
-	if ( shrttl ) {
-		if ( !ttl || ( strcmp( shrttl, ttl ) || subttl ) ) {
-			fprintf( outptr,  " <b:ShortTitle>" );
-			fprintf( outptr, "%s", shrttl );
-			fprintf( outptr, "</b:ShortTitle>\n" );
+	char *ttl       = fields_findv( info, level, FIELDS_CHRP, "TITLE" );
+	char *subttl    = fields_findv( info, level, FIELDS_CHRP, "SUBTITLE" );
+	char *shrttl    = fields_findv( info, level, FIELDS_CHRP, "SHORTTITLE" );
+	char *shrsubttl = fields_findv( info, level, FIELDS_CHRP, "SHORTSUBTITLE" );
+
+	if ( ttl ) {
+		output_titleinfo( ttl, subttl, outptr, tag, level );
+	}
+	else if ( shrttl ) {
+		output_titleinfo( shrttl, shrsubttl, outptr, tag, level );
+	}
+}
+
+static void
+output_maintitle( fields *info, FILE *outptr, int level )
+{
+	char *ttl       = fields_findv( info, level, FIELDS_CHRP, "TITLE" );
+	char *subttl    = fields_findv( info, level, FIELDS_CHRP, "SUBTITLE" );
+	char *shrttl    = fields_findv( info, level, FIELDS_CHRP, "SHORTTITLE" );
+	char *shrsubttl = fields_findv( info, level, FIELDS_CHRP, "SHORTSUBTITLE" );
+
+	if ( ttl ) {
+		output_titleinfo( ttl, subttl, outptr, "b:Title", level );
+
+		/* output shorttitle if it's different from normal title */
+		if ( shrttl ) {
+			if ( !ttl || ( strcmp( shrttl, ttl ) || subttl ) ) {
+				fprintf( outptr,  " <b:ShortTitle>" );
+				output_titlebits( shrttl, shrsubttl, outptr );
+				fprintf( outptr, "</b:ShortTitle>\n" );
+			}
 		}
 	}
+	else if ( shrttl ) {
+		output_titleinfo( shrttl, shrsubttl, outptr, "b:Title", level );
+	}
 }
 
 static void
@@ -418,11 +448,11 @@ static void
 output_date( fields *info, FILE *outptr, int level )
 {
 	char *year  = fields_findv_firstof( info, level, FIELDS_CHRP,
-			"PARTYEAR", "YEAR", NULL );
+			"PARTDATE:YEAR", "DATE:YEAR", NULL );
 	char *month = fields_findv_firstof( info, level, FIELDS_CHRP,
-			"PARTMONTH", "MONTH", NULL );
+			"PARTDATE:MONTH", "DATE:MONTH", NULL );
 	char *day   = fields_findv_firstof( info, level, FIELDS_CHRP,
-			"PARTDAY", "DAY", NULL );
+			"PARTDATE:DAY", "DATE:DAY", NULL );
 	if ( year )  output_itemv( outptr, "b:Year", year, 0 );
 	if ( month ) output_itemv( outptr, "b:Month", month, 0 );
 	if ( day )   output_itemv( outptr, "b:Day", day, 0 );
@@ -431,8 +461,8 @@ output_date( fields *info, FILE *outptr, int level )
 static void
 output_pages( fields *info, FILE *outptr, int level )
 {
-	char *sn = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "PAGESTART" );
-	char *en = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "PAGEEND" );
+	char *sn = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "PAGES:START" );
+	char *en = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "PAGES:STOP" );
 	char *ar = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "ARTICLENUMBER" );
 	if ( sn || en )
 		output_range( outptr, "b:Pages", sn, en, level );
@@ -444,13 +474,13 @@ static void
 output_includedin( fields *info, FILE *outptr, int type )
 {
 	if ( type==TYPE_JOURNALARTICLE ) {
-		output_titleinfo( info, outptr, "b:JournalName", 1 );
+		output_generaltitle( info, outptr, "b:JournalName", 1 );
 	} else if ( type==TYPE_ARTICLEINAPERIODICAL ) {
-		output_titleinfo( info, outptr, "b:PeriodicalTitle", 1 );
+		output_generaltitle( info, outptr, "b:PeriodicalTitle", 1 );
 	} else if ( type==TYPE_BOOKSECTION ) {
-		output_titleinfo( info, outptr, "b:ConferenceName", 1 ); /*??*/
+		output_generaltitle( info, outptr, "b:ConferenceName", 1 ); /*??*/
 	} else if ( type==TYPE_PROCEEDINGS ) {
-		output_titleinfo( info, outptr, "b:ConferenceName", 1 );
+		output_generaltitle( info, outptr, "b:ConferenceName", 1 );
 	}
 }
 
@@ -483,7 +513,7 @@ output_thesisdetails( fields *info, FILE *outptr, int type )
 			strcasecmp( tag, "DEGREEGRANTOR:ASIS") &
 			strcasecmp( tag, "DEGREEGRANTOR:CORP"))
 				continue;
-		output_item( info, outptr, "b:Institution", i, 0 );
+		output_item( info, outptr, "b:Institution", "", i, 0 );
 	}
 }
 
@@ -564,20 +594,26 @@ static void
 output_citeparts( fields *info, FILE *outptr, int level, int max, int type )
 {
 	convert origin[] = {
-		{ "ADDRESS",	"b:City",	LEVEL_ANY },
-		{ "PUBLISHER",	"b:Publisher",	LEVEL_ANY },
-		{ "EDITION",	"b:Edition",	LEVEL_ANY }
+		{ "ADDRESS",	"b:City",	"", LEVEL_ANY },
+		{ "PUBLISHER",	"b:Publisher",	"", LEVEL_ANY },
+		{ "EDITION",	"b:Edition",	"", LEVEL_ANY }
 	};
 	int norigin = sizeof( origin ) / sizeof ( convert );
 	
 	convert parts[] = {
-		{ "VOLUME",          "b:Volume",  LEVEL_ANY },
-		{ "SECTION",         "b:Section", LEVEL_ANY },
-		{ "ISSUE",           "b:Issue",   LEVEL_ANY },
-		{ "NUMBER",          "b:Issue",   LEVEL_ANY },
-		{ "PUBLICLAWNUMBER", "b:Volume",  LEVEL_ANY },
-		{ "SESSION",         "b:Issue",   LEVEL_ANY },
-		{ "URL",             "b:Url",     LEVEL_ANY },
+		{ "VOLUME",          "b:Volume",  "", LEVEL_ANY },
+		{ "SECTION",         "b:Section", "", LEVEL_ANY },
+		{ "ISSUE",           "b:Issue",   "", LEVEL_ANY },
+		{ "NUMBER",          "b:Issue",   "", LEVEL_ANY },
+		{ "PUBLICLAWNUMBER", "b:Volume",  "", LEVEL_ANY },
+		{ "SESSION",         "b:Issue",   "", LEVEL_ANY },
+		{ "URL",             "b:Url",     "", LEVEL_ANY },
+		{ "JSTOR",           "b:Url",     "http://www.jstor.org/stable/", LEVEL_ANY },
+		{ "ARXIV",           "b:Url",     "http://arxiv.org/abs/",        LEVEL_ANY },
+		{ "PMID",            "b:Url",     "http://www.ncbi.nlm.nih.gov/pubmed/", LEVEL_ANY },
+		{ "PMC",             "b:Url",     "http://www.ncbi.nlm.nih.gov/pmc/articles/", LEVEL_ANY },
+		{ "DOI",             "b:Url",     "http://dx.doi.org/", LEVEL_ANY },
+		{ "MRNUMBER",        "b:Url",     "http://www.ams.org/mathscinet-getitem?mr=", LEVEL_ANY },
 	};
 	int nparts=sizeof(parts)/sizeof(convert);
 	
@@ -589,11 +625,11 @@ output_citeparts( fields *info, FILE *outptr, int level, int max, int type )
 	output_list( info, outptr, parts, nparts );
 	output_pages( info, outptr, level );
 	output_names( info, outptr, level, type );
-	output_title( info, outptr, 0 );
+	output_maintitle( info, outptr, 0 );
 	output_comments( info, outptr, level );
 }
 
-void
+static int
 wordout_write( fields *info, FILE *outptr, param *p, unsigned long numrefs )
 {
 	int max = fields_maxlevel( info );
@@ -604,9 +640,11 @@ wordout_write( fields *info, FILE *outptr, param *p, unsigned long numrefs )
 	fprintf( outptr, "</b:Source>\n" );
 
 	fflush( outptr );
+
+	return BIBL_OK;
 }
 
-void
+static void
 wordout_writeheader( FILE *outptr, param *p )
 {
 	if ( p->utf8bom ) utf8_writebom( outptr );
@@ -616,7 +654,7 @@ wordout_writeheader( FILE *outptr, param *p )
 		" xmlns=\"http://schemas.openxmlformats.org/officeDocument/2006/bibliography\" >\n");
 }
 
-void
+static void
 wordout_writefooter( FILE *outptr )
 {
 	fprintf(outptr,"</b:Sources>\n");
diff --git a/lib/wordout.h b/lib/wordout.h
deleted file mode 100644
index adc1684..0000000
--- a/lib/wordout.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * wordout.h
- *
- * Copyright (c) Chris Putnam 2008-2013
- *
- * Source code released under the GPL version 2
- *
- */
-#ifndef WORDOUT_H
-#define WORDOUT_H
-
-/* format-specific options */
-#define WORDOUT_DROPKEY (2)
-
-#include <stdio.h>
-#include "bibl.h"
-#include "bibutils.h"
-
-extern void wordout_writeheader( FILE *outptr, param *p );
-extern void wordout_writefooter( FILE *outptr );
-extern void wordout_write( fields *info, FILE *outptr, param *p,
-	unsigned long numrefs );
-extern void wordout_initparams( param *p, const char *progname );
-
-
-#endif
-
diff --git a/lib/xml.c b/lib/xml.c
index 931995e..e1111db 100644
--- a/lib/xml.c
+++ b/lib/xml.c
@@ -1,7 +1,7 @@
 /*
  * xml.c
  *
- * Copyright (c) Chris Putnam 2004-2013
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/lib/xml.h b/lib/xml.h
index a6f8d77..589d49e 100644
--- a/lib/xml.h
+++ b/lib/xml.h
@@ -1,7 +1,7 @@
 /*
  * xml.h
  *
- * Copyright (c) Chris Putnam 2004-2013
+ * Copyright (c) Chris Putnam 2004-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/lib/xml_encoding.c b/lib/xml_encoding.c
index 1a85690..ea7fe64 100644
--- a/lib/xml_encoding.c
+++ b/lib/xml_encoding.c
@@ -1,7 +1,7 @@
 /*
  * xml_getencoding.c
  *
- * Copyright (c) Chris Putnam 2007-2013
+ * Copyright (c) Chris Putnam 2007-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/lib/xml_encoding.h b/lib/xml_encoding.h
index 366977c..1b39c2f 100644
--- a/lib/xml_encoding.h
+++ b/lib/xml_encoding.h
@@ -1,7 +1,7 @@
 /*
  * xml_getencoding.h
  *
- * Copyright (c) Chris Putnam 2007-2013
+ * Copyright (c) Chris Putnam 2007-2016
  *
  * Source code released under the GPL version 2
  *
diff --git a/test/Makefile.dynamic b/test/Makefile.dynamic
index 4d047fd..7a11417 100644
--- a/test/Makefile.dynamic
+++ b/test/Makefile.dynamic
@@ -6,7 +6,8 @@ CFLAGS   = -I ../lib $(CFLAGSIN)
 LDFLAGS  = -L ../lib
 LDLIBS   = -lbibutils
 
-PROGS    = entities_test \
+PROGS    = doi_test \
+           entities_test \
            list_test \
            newstr_test \
            utf8_test
@@ -19,6 +20,9 @@ entities_test : entities_test.o
 utf8_test : utf8_test.o
 	$(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
 
+doi_test : doi_test.o
+	$(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
+
 newstr_test : newstr_test.o
 	$(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
 
@@ -31,7 +35,8 @@ test: $(PROGS) FORCE
 	./newstr_test; \
 	./list_test; \
 	./entities_test; \
-	./utf8_test )
+	./utf8_test;
+	./doi_test )
 
 clean:
 	rm -f *.o core 
diff --git a/test/Makefile.static b/test/Makefile.static
index 47f420c..cd2b2c3 100644
--- a/test/Makefile.static
+++ b/test/Makefile.static
@@ -3,7 +3,8 @@
 #
 
 CFLAGS     = -I ../lib $(CFLAGSIN)
-PROGS      = entities_test \
+PROGS      = doi_test \
+             entities_test \
              list_test \
              newstr_test \
              utf8_test
@@ -16,6 +17,9 @@ entities_test : entities_test.o ../lib/libbibcore.a
 utf8_test : utf8_test.o ../lib/libbibcore.a
 	$(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
 
+doi_test : doi_test.o ../lib/libbibcore.a
+	$(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
+
 newstr_test : newstr_test.o ../lib/libbibcore.a
 	$(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
 
@@ -26,6 +30,7 @@ test: $(PROGS) FORCE
 	./newstr_test
 	./list_test
 	./entities_test
+	./doi_test
 	./utf8_test
 
 clean:
diff --git a/test/doi_test.c b/test/doi_test.c
new file mode 100644
index 0000000..0ed0258
--- /dev/null
+++ b/test/doi_test.c
@@ -0,0 +1,120 @@
+/*
+ * doi_test.c
+ *
+ * Copyright (c) 2016
+ *
+ * Source code released under the GPL version 2
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include "doi.h"
+
+char progname[] = "doi_test";
+
+typedef struct test_t {
+	char *s;
+	int expected;
+} test_t;
+
+int
+test_is_doi( void )
+{
+	test_t tests[] = {
+		{ "10.1021/",            0 },
+		{ "00.0000/",            0 },
+		{ "00,0000/",            -1 },
+		{ "doi:99.9999/",        4 },
+		{ "doi: 99.9999/",       5 },
+		{ "doi: DOI: 99.9999/",  10 },
+		{ "http://www.test.com", -1 },
+	};
+	int ntests = sizeof( tests ) / sizeof( tests[0] );
+	int failed = 0;
+	int found;
+	int i;
+
+	for ( i=0; i<ntests; ++i ) {
+		found = is_doi( tests[i].s );
+		if ( found != tests[i].expected ) {
+			printf( "%s: Error is_doi( '%s' ) returned %d, expected %d\n", progname, tests[i].s, found, tests[i].expected );
+			failed++;
+		}
+	}
+	return failed;
+}
+
+int
+test_is_uri_remote_scheme( void )
+{
+	test_t tests[] = {
+		{ "This is a note",           -1 },
+		{ "doi:99.9999/",             -1 },
+		{ "git://www.git.com",        4 },
+		{ "ftp://www.ftp.com",        4 },
+		{ "gopher://www.gopher.com",  7 },
+		{ "arXiv:10121",              -1 },
+		{ "pubmed:121211",            -1 },
+		{ "http://www.test.com",      5 },
+		{ "https://www.test.com",     6 },
+	};
+	int ntests = sizeof( tests ) / sizeof( tests[0] );
+	int failed = 0;
+	int found;
+	int i;
+
+	for ( i=0; i<ntests; ++i ) {
+		found = is_uri_remote_scheme( tests[i].s );
+		if ( found != tests[i].expected ) {
+			printf( "%s: Error is_uri_remote_scheme( '%s' ) returned %d, expected %d\n", progname, tests[i].s, found, tests[i].expected );
+			failed++;
+		}
+	}
+	return failed;
+}
+
+int
+test_is_embedded_link( void )
+{
+	test_t tests[] = {
+		{ "This is a note",           0 },
+		{ "doi:99.9999/",             1 },
+		{ "git://www.git.com",        1 },
+		{ "ftp://www.ftp.com",        1 },
+		{ "gopher://www.gopher.com",  1 },
+		{ "arXiv:10121",              1 },
+		{ "pubmed:121211",            1 },
+		{ "http://www.test.com",      1 },
+		{ "https://www.test.com",     1 },
+	};
+	int ntests = sizeof( tests ) / sizeof( tests[0] );
+	int failed = 0;
+	int found;
+	int i;
+
+	for ( i=0; i<ntests; ++i ) {
+		found = is_embedded_link( tests[i].s );
+		if ( found != tests[i].expected ) {
+			printf( "%s: Error is_embedded_link( '%s' ) returned %d, expected %d\n", progname, tests[i].s, found, tests[i].expected );
+			failed++;
+		}
+	}
+	return failed;
+}
+
+
+int
+main( int argc, char *argv[] )
+{
+	int failed = 0;
+	failed += test_is_doi();
+	failed += test_is_uri_remote_scheme();
+	failed += test_is_embedded_link();
+	if ( !failed ) {
+		printf( "%s: PASSED\n", progname );
+		return EXIT_SUCCESS;
+	} else {
+		printf( "%s: FAILED\n", progname );
+		return EXIT_FAILURE;
+	}
+}
diff --git a/test/entities_test.c b/test/entities_test.c
index 34a5ca5..f6c4270 100644
--- a/test/entities_test.c
+++ b/test/entities_test.c
@@ -1,6 +1,9 @@
 /*
  * entities_test.c
  *
+ * Copyright (c) 2012-2016
+ *
+ * Source code released under the GPL version 2
  */
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/test/list_test.c b/test/list_test.c
index 50e90ea..183527c 100644
--- a/test/list_test.c
+++ b/test/list_test.c
@@ -1,6 +1,11 @@
 /*
  * list_test.c
  *
+ * Copyright (c) 2013-2016
+ *
+ * Source code released under the GPL version 2
+ *
+ *
  * test list functions
  */
 #include <stdio.h>
diff --git a/test/newstr_test.c b/test/newstr_test.c
index 4468b95..f297b02 100644
--- a/test/newstr_test.c
+++ b/test/newstr_test.c
@@ -1,6 +1,10 @@
 /*
  * newstr_test.c
  *
+ * Copyright (c) 2012-2016
+ *
+ * Source code released under the GPL version 2
+ *
  * test newstr functions
  */
 
diff --git a/test/utf8_test.c b/test/utf8_test.c
index 6e22a4e..e3c3255 100644
--- a/test/utf8_test.c
+++ b/test/utf8_test.c
@@ -1,5 +1,10 @@
 /*
  * utf8_test.c
+ *
+ * Copyright (c) 2012-2016
+ *
+ * Source code released under the GPL version 2
+ *
  */
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/test/vplist_test.c b/test/vplist_test.c
index 2703c3b..4d1e077 100644
--- a/test/vplist_test.c
+++ b/test/vplist_test.c
@@ -1,6 +1,11 @@
 /*
  * vplist_test.c
  *
+ * Copyright (c) 2014-2016
+ *
+ * Source code released under the GPL version 2
+ *
+ *
  * test vplist functions
  */
 #include <stdio.h>

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/bibutils.git



More information about the debian-science-commits mailing list