diff --git a/bibutils/biblatexin.c b/bibutils/biblatexin.c
--- a/bibutils/biblatexin.c
+++ b/bibutils/biblatexin.c
@@ -538,12 +538,12 @@
 static void
 process_genre( fields *info, char *p, int level )
 {
-        /* Some users put Diploma thesis in "type" */
-        if ( !strncasecmp( p, "Diplom", 6 ) )
-                fields_replace_or_add( info, "GENRE", "Diploma thesis", level );
-        else if ( !strncasecmp( p, "Habilitation", 13 ) )
-                fields_replace_or_add( info, "GENRE", "Habilitation thesis", level );
-        else 
+	/* Some users put Diploma thesis in "type" */
+	if ( !strncasecmp( p, "Diplom", 6 ) )
+		fields_replace_or_add( info, "GENRE", "Diploma thesis", level );
+	else if ( !strncasecmp( p, "Habilitation", 13 ) )
+		fields_replace_or_add( info, "GENRE", "Habilitation thesis", level );
+	else
 		fields_add( info, "GENRE", p, level );
 }
 
@@ -556,7 +556,6 @@
 	netype  = fields_find( bibin, "eprinttype", -1 );
 	if ( neprint!=-1 ) eprint = bibin->data[neprint].data;
 	if ( netype!=-1 ) etype = bibin->data[netype].data;
-fprintf(stderr,"process_eprint: neprint=%d netype=%d\n", neprint,netype );
 	if ( eprint && etype ) {
 		if ( !strncasecmp( etype, "arxiv", 5 ) )
 			fields_add( info, "ARXIV", eprint, level );
diff --git a/bibutils/bibtexin.c b/bibutils/bibtexin.c
--- a/bibutils/bibtexin.c
+++ b/bibutils/bibtexin.c
@@ -644,6 +644,27 @@
 	newstr_free( &link );
 }
 
+/*
+ * 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 void
+process_organization( fields *bibin, fields *info, newstr *d, int level )
+{
+	int n;
+	n = fields_find( bibin, "publisher", LEVEL_ANY );
+	if ( n==-1 )
+		fields_add( info, "PUBLISHER", d->data, level );
+	else
+		fields_add( info, "ORGANIZER:CORP", d->data, level );
+}
+
 static int
 count_colons( char *p )
 {
@@ -852,16 +873,20 @@
 			process_howpublished( info, d, level );
 			break;
 
-		case BIBTEX_URL:
-			process_url( info, d, level );
-			break;
-
 		case LINKEDFILE:
 			process_file( info, d, level );
 			break;
 
 		case BIBTEX_SENTE:
 			process_sente( info, d, level );
+			break;
+
+		case BIBTEX_URL:
+			process_url( info, d, level );
+			break;
+
+		case BIBTEX_ORGANIZATION:
+			process_organization( bibin, info, d, level );
 			break;
 
 		case ALWAYS:
diff --git a/bibutils/bibtextypes.c b/bibutils/bibtextypes.c
--- a/bibutils/bibtextypes.c
+++ b/bibutils/bibtextypes.c
@@ -25,7 +25,7 @@
 	{ "day",          "PARTDAY",   SIMPLE, LEVEL_MAIN },
 	{ "volume",       "VOLUME",    SIMPLE, LEVEL_MAIN },
 	{ "pages",        "PAGES",     PAGES,  LEVEL_MAIN },
-	{ "number",       "NUMBER",    SIMPLE, LEVEL_MAIN },
+	{ "number",       "ISSUE",     SIMPLE, LEVEL_MAIN },
 	{ "issue",        "ISSUE",     SIMPLE, LEVEL_MAIN },
 	{ "journal",      "TITLE",     TITLE,  LEVEL_HOST },
 	{ "publisher",    "PUBLISHER", SIMPLE, LEVEL_HOST },
@@ -65,7 +65,7 @@
 	{ "booktitle",    "TITLE",     TITLE,  LEVEL_MAIN },
 	{ "series",       "TITLE",     TITLE,  LEVEL_HOST },
 	{ "publisher",    "PUBLISHER", SIMPLE, LEVEL_MAIN },
-	{ "organization", "AUTHOR:CORP", SIMPLE, LEVEL_MAIN },
+	{ "organization", "ORGANIZER:CORP", BIBTEX_ORGANIZATION, LEVEL_MAIN },
 	{ "address",      "ADDRESS",   SIMPLE, LEVEL_MAIN },
 	{ "editor",       "EDITOR",    PERSON, LEVEL_MAIN },
 	{ "year",         "YEAR",      SIMPLE, LEVEL_MAIN },
@@ -149,7 +149,7 @@
 	{ "booktitle", "TITLE",     TITLE,  LEVEL_MAIN },
 	{ "editor",    "EDITOR",    PERSON, LEVEL_MAIN },
 	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_MAIN },
-	{ "organization", "AUTHOR:CORP", SIMPLE, LEVEL_MAIN },
+	{ "organization", "ORGANIZER:CORP", BIBTEX_ORGANIZATION, LEVEL_MAIN },
 	{ "address",   "ADDRESS",   SIMPLE, LEVEL_MAIN },
 	{ "year",      "YEAR",      SIMPLE, LEVEL_MAIN },
 	{ "month",     "MONTH",     SIMPLE, LEVEL_MAIN },
@@ -236,7 +236,7 @@
 	{ "series",    "TITLE",     TITLE,  LEVEL_SERIES },
 	{ "chapter",   "CHAPTER",   SIMPLE, LEVEL_MAIN },
 	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_HOST },
-	{ "organization", "AUTHOR:CORP", SIMPLE, LEVEL_HOST },
+	{ "organization", "ORGANIZER:CORP", BIBTEX_ORGANIZATION, LEVEL_HOST },
 	{ "address",   "ADDRESS",   SIMPLE, LEVEL_HOST },
 	{ "year",      "PARTYEAR",  SIMPLE, LEVEL_MAIN },
 	{ "month",     "PARTMONTH", SIMPLE, LEVEL_MAIN },
@@ -325,7 +325,7 @@
 	{ "booktitle", "TITLE",     TITLE,  LEVEL_MAIN },
 	{ "series",    "TITLE",     TITLE,  LEVEL_HOST },
 	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_MAIN },
-	{ "organization", "AUTHOR:CORP", SIMPLE, LEVEL_MAIN },
+	{ "organization", "ORGANIZER:CORP", BIBTEX_ORGANIZATION, LEVEL_MAIN },
 	{ "address",   "ADDRESS",   SIMPLE, LEVEL_MAIN },
 	{ "year",      "YEAR",      SIMPLE, LEVEL_MAIN },
 	{ "month",     "MONTH",     SIMPLE, LEVEL_MAIN },
@@ -464,7 +464,7 @@
 static lookups standard[] = {
 	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN },
 	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },
-	{ "organization", "AUTHOR:CORP", SIMPLE, LEVEL_MAIN },
+	{ "organization", "ORGANIZER:CORP", BIBTEX_ORGANIZATION, LEVEL_MAIN },
 	{ "institution", "AUTHOR:CORP", SIMPLE, LEVEL_MAIN },
 	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },
 	{ "booktitle", "TITLE",     TITLE,  LEVEL_MAIN },
@@ -529,7 +529,7 @@
 	{ "language",     "LANGUAGE",    SIMPLE, LEVEL_MAIN },
 	{ "note",         "NOTES",       SIMPLE, LEVEL_MAIN },
 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },
-	{ "organization", "AUTHOR:CORP", SIMPLE, LEVEL_MAIN },
+	{ "organization", "ORGANIZER:CORP", BIBTEX_ORGANIZATION, LEVEL_MAIN },
 	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
 	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
 	{ " ",            "RESOURCE|text",   ALWAYS, LEVEL_MAIN },
@@ -583,7 +583,7 @@
 static lookups electronic[] = {
 	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN },
 	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },
-	{ "organization", "AUTHOR:CORP", SIMPLE, LEVEL_MAIN },
+	{ "organization", "ORGANIZER:CORP", BIBTEX_ORGANIZATION, LEVEL_MAIN },
 	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },
 	{ "booktitle", "TITLE",     TITLE,  LEVEL_MAIN },
 	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_MAIN },
@@ -620,7 +620,7 @@
 	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },
 	{ "booktitle", "TITLE",     TITLE,  LEVEL_MAIN },
 	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_MAIN },
-	{ "organization", "AUTHOR:CORP", SIMPLE, LEVEL_MAIN },
+	{ "organization", "ORGANIZER:CORP", BIBTEX_ORGANIZATION, LEVEL_MAIN },
 	{ "pages",     "PAGES",     PAGES,  LEVEL_MAIN },
 	{ "address",   "ADDRESS",   SIMPLE, LEVEL_MAIN },
 	{ "editor",    "EDITOR",    PERSON, LEVEL_MAIN },
@@ -659,6 +659,7 @@
 	REFTYPE( "inbook", inbook ),
 	REFTYPE( "incollection", incollection ),
 	REFTYPE( "inconference", inproceedings ),
+	REFTYPE( "conference", inproceedings ),
 	REFTYPE( "inproceedings", inproceedings ),
 	REFTYPE( "manual", manual ),
 	REFTYPE( "mastersthesis", masters ),
diff --git a/bibutils/bltypes.c b/bibutils/bltypes.c
--- a/bibutils/bltypes.c
+++ b/bibutils/bltypes.c
@@ -93,6 +93,7 @@
 	{ "maintitleaddon",  "?maintitleaddon?",SIMPLE, LEVEL_HOST },   /*WRONG*/
 	{ "language",        "LANGUAGE",     SIMPLE, LEVEL_MAIN },
 	{ "year",            "YEAR",         SIMPLE, LEVEL_MAIN },
+	{ "month",           "MONTH",        SIMPLE, LEVEL_MAIN },
 	{ "origlanguage",    "LANGUAGE",     SIMPLE, LEVEL_ORIG },
 	{ "origyear",        "YEAR",         SIMPLE, LEVEL_ORIG },
 	{ "origtitle",       "TITLE",        SIMPLE, LEVEL_ORIG },
@@ -140,6 +141,7 @@
 	{ "titleaddon",      "?titleaddon?",        SIMPLE, LEVEL_MAIN },   /*WRONG*/
 	{ "howpublished",    "",       HOWPUBLISHED, LEVEL_MAIN },
 	{ "year",            "YEAR",         SIMPLE, LEVEL_MAIN },
+	{ "month",           "MONTH",        SIMPLE, LEVEL_MAIN },
 	{ "language",        "LANGUAGE",     SIMPLE, LEVEL_MAIN },
 	{ "type",            "GENRE",  BIBTEX_GENRE, LEVEL_MAIN },
 	{ "note",            "NOTES",        SIMPLE, LEVEL_MAIN },
@@ -174,6 +176,7 @@
 	{ "commentator",     "COMMENTATOR",  PERSON, LEVEL_MAIN },
 	{ "translator",      "TRANSLATOR",   PERSON, LEVEL_MAIN },
 	{ "year",            "YEAR",         SIMPLE, LEVEL_MAIN },
+	{ "month",           "MONTH",        SIMPLE, LEVEL_MAIN },
 	{ "introduction",    "?introduction?",        SIMPLE, LEVEL_MAIN }, /*WRONG*/
 	{ "foreward",        "?foreward?",        SIMPLE, LEVEL_MAIN }, /*WRONG*/
 	{ "afterward",       "?afterward?",        SIMPLE, LEVEL_MAIN }, /*WRONG*/
@@ -231,6 +234,7 @@
 	{ "commentator",     "COMMENTATOR",  PERSON, LEVEL_HOST },
 	{ "translator",      "TRANSLATOR",   PERSON, LEVEL_HOST },
 	{ "year",            "YEAR",         SIMPLE, LEVEL_MAIN },
+	{ "month",           "MONTH",        SIMPLE, LEVEL_MAIN },
 	{ "introduction",    "?introduction?",        SIMPLE, LEVEL_HOST }, /*WRONG*/
 	{ "foreward",        "?foreward?",        SIMPLE, LEVEL_HOST }, /*WRONG*/
 	{ "afterward",       "?afterward?",        SIMPLE, LEVEL_HOST }, /*WRONG*/
@@ -288,6 +292,7 @@
 
 	{ "author",          "AUTHOR",       PERSON, LEVEL_MAIN },
 	{ "year",            "YEAR",         SIMPLE, LEVEL_MAIN },
+	{ "month",           "MONTH",        SIMPLE, LEVEL_MAIN },
 	{ "title",           "TITLE",        SIMPLE, LEVEL_MAIN },
 	{ "subtitle",        "SUBTITLE",     SIMPLE, LEVEL_MAIN },
 	{ "titleaddon",      "?titleaddon?", SIMPLE, LEVEL_MAIN },   /*WRONG*/
@@ -359,6 +364,7 @@
 	{ "translator",      "TRANSLATOR",   PERSON, LEVEL_HOST },
 	{ "eventtitle",      "EVENT:CONF",   SIMPLE, LEVEL_MAIN },
 	{ "year",            "YEAR",         SIMPLE, LEVEL_MAIN },
+	{ "month",           "MONTH",        SIMPLE, LEVEL_MAIN },
 	{ "introduction",    "?introduction?",SIMPLE, LEVEL_HOST }, /*WRONG*/
 	{ "foreward",        "?foreward?",   SIMPLE, LEVEL_HOST }, /*WRONG*/
 	{ "afterward",       "?afterward?",  SIMPLE, LEVEL_HOST }, /*WRONG*/
@@ -414,6 +420,7 @@
 	{ "commentator",     "COMMENTATOR",  PERSON, LEVEL_MAIN },
 	{ "translator",      "TRANSLATOR",   PERSON, LEVEL_MAIN },
 	{ "year",            "YEAR",         SIMPLE, LEVEL_MAIN },
+	{ "month",           "MONTH",        SIMPLE, LEVEL_MAIN },
 	{ "introduction",    "?????",        SIMPLE, LEVEL_MAIN }, /*WRONG*/
 	{ "foreward",        "?????",        SIMPLE, LEVEL_MAIN }, /*WRONG*/
 	{ "afterward",       "?????",        SIMPLE, LEVEL_MAIN }, /*WRONG*/
@@ -597,6 +604,7 @@
 	{ "translator",      "TRANSLATOR",   PERSON, LEVEL_MAIN },
 	{ "eventtitle",      "EVENT:CONF",   SIMPLE, LEVEL_MAIN },
 	{ "year",            "YEAR",         SIMPLE, LEVEL_MAIN },
+	{ "month",           "MONTH",        SIMPLE, LEVEL_MAIN },
 	{ "introduction",    "?????",        SIMPLE, LEVEL_MAIN }, /*WRONG*/
 	{ "foreward",        "?????",        SIMPLE, LEVEL_MAIN }, /*WRONG*/
 	{ "afterward",       "?????",        SIMPLE, LEVEL_MAIN }, /*WRONG*/
@@ -649,6 +657,7 @@
 	{ "subtitle",        "SUBTITLE",     SIMPLE, LEVEL_MAIN },
 	{ "titleaddon",      "?????",        SIMPLE, LEVEL_MAIN },   /*WRONG*/
 	{ "year",            "YEAR",         SIMPLE, LEVEL_MAIN },
+	{ "month",           "MONTH",        SIMPLE, LEVEL_MAIN },
 	{ "language",        "LANGUAGE",     SIMPLE, LEVEL_MAIN },
 	{ "number",          "NUMBER",       SIMPLE, LEVEL_MAIN },
 	{ "note",            "NOTES",        SIMPLE, LEVEL_MAIN },
diff --git a/bibutils/newstr.c b/bibutils/newstr.c
--- a/bibutils/newstr.c
+++ b/bibutils/newstr.c
@@ -1,14 +1,14 @@
 /*
  * newstr.c
  *
+ * Version: 9/20/12
+ *
  * Copyright (c) Chris Putnam 1999-2012
  *
  * Source code released under the GPL
  *
  *
- * newstring routines for dynamically allocated strings
- *
- * C. Putnam 3/29/02  Clean up newstr_findreplace() (x4 speed increase too)
+ * routines for dynamically allocated strings
  *
  */
 #include <stdio.h>
@@ -91,6 +91,15 @@
 }
 
 void
+newstr_initstr( newstr *s, char *initstr )
+{
+	assert( s );
+	assert( initstr );
+	newstr_init( s );
+	newstr_strcpy( s, initstr );
+}
+
+void
 newstrs_init( newstr *s, ... )
 {
 	newstr *s2;
@@ -336,9 +345,9 @@
 void
 newstr_newstrcpy( newstr *s, newstr *old )
 {
-	assert( s && old );
+	assert( s );
 	if ( s==old ) return;
-	if ( !old->data || !old->dim ) newstr_empty( s );
+	else if ( !old || old->len==0 ) newstr_empty( s );
 	else newstr_strcpy_internal( s, old->data, old->len );
 }
 
@@ -360,6 +369,36 @@
 	return s2;
 }
 
+/*
+ * newstr_indxcpy( s, in, start, stop );
+ *
+ * copies in[start] to in[stop] (includes stop) into s
+ */
+void
+newstr_indxcpy( newstr *s, char *p, int start, int stop )
+{
+	int i;
+	assert( s );
+	assert( p );
+	assert( start <= stop );
+	newstr_strcpy_ensurespace( s, stop-start+1 );
+	for ( i=start; i<=stop; ++i )
+		s->data[i-start] = p[i];
+	s->data[i] = '\0';
+	s->len = stop-start+1;
+}
+
+void
+newstr_indxcat( newstr *s, char *p, int start, int stop )
+{
+	int i;
+	assert( s );
+	assert( p );
+	assert( start <= stop );
+	for ( i=start; i<=stop; ++i )
+		newstr_addchar( s, p[i] );
+}
+
 /* newstr_segcpy( s, start, end );
  *
  * copies [start,end) into s
@@ -667,4 +706,54 @@
 		*q = '\0';
 	}
 	s->len = len;
+}
+
+int
+newstr_newstrcmp( newstr *s, newstr *t )
+{
+	assert( s );
+	assert( t );
+	if ( s->len == 0 && t->len == 0 ) return 0;
+	return strcmp( s->data, t->data );
+}
+
+void
+newstr_reverse( newstr *s )
+{
+	newstr ns;
+	unsigned long i;
+
+	assert( s );
+
+	if ( s->len==0 ) return;
+	newstr_init( &ns );
+	i = s->len;
+	do {
+		i--;
+		newstr_addchar( &ns, s->data[i] );
+	} while ( i>0 );
+	newstr_swapstrings( s, &ns );
+	newstr_free( &ns );
+}
+
+int
+newstr_fgetline( newstr *s, FILE *fp )
+{
+	int ch, eol = 0;
+	assert( s );
+	newstr_empty( s );
+	if ( feof( fp ) ) return 0;
+	while ( !feof( fp ) && !eol ) {
+		ch = fgetc( fp );
+		if ( ch == EOF ) eol = 1;
+		else if ( ch == '\n' ) eol = 1;
+		else if ( ch == '\r' ) {
+			ch = fgetc( fp );
+			if ( ch != '\n' ) ungetc( ch, fp );
+			eol = 1;
+		} else {
+			newstr_addchar( s, (char) ch );
+		}
+	}
+	return 1;
 }
diff --git a/bibutils/newstr.h b/bibutils/newstr.h
--- a/bibutils/newstr.h
+++ b/bibutils/newstr.h
@@ -1,8 +1,10 @@
 /*
  * newstring.h
  *
- * Copyright (c) Chris Putnam 1999-2012
+ * Version: 9/20/12
  *
+ * Copyright (c) Chris Putnam 1999-2011
+ *
  * Source code released under the GPL
  *
  */
@@ -21,6 +23,7 @@
 newstr *newstr_new         ( void ); 
 
 void    newstr_init        ( newstr *s );
+void    newstr_initstr     ( newstr *s, char *initstr );
 void    newstr_empty       ( newstr *s );
 void    newstr_free        ( newstr *s );
 
@@ -31,6 +34,7 @@
 void newstr_mergestrs   ( newstr *s, ... );
 newstr *newstr_strdup   ( char *buf );
 void newstr_addchar     ( newstr *s, char newchar );
+void newstr_reverse     ( newstr *s );
 char *newstr_addutf8    ( newstr *s, char *p );
 void newstr_strcat      ( newstr *s, char *addstr );
 void newstr_newstrcat   ( newstr *s, newstr *old );
@@ -40,9 +44,12 @@
 void newstr_newstrcpy   ( newstr *s, newstr *old );
 void newstr_segcpy      ( newstr *s, char *startat, char *endat );
 void newstr_segdel      ( newstr *s, char *startat, char *endat );
+void newstr_indxcpy     ( newstr *s, char *p, int start, int stop );
+void newstr_indxcat     ( newstr *s, char *p, int start, int stop );
 void newstr_fprintf     ( FILE *fp, newstr *s );
 int  newstr_fget        ( FILE *fp, char *buf, int bufsize, int *pbufpos,
                           newstr *outs );
+int  newstr_fgetline    ( newstr *s, FILE *fp );
 int  newstr_findreplace ( newstr *s, char *find, char *replace );
 void newstr_toupper     ( newstr *s );
 void newstr_tolower     ( newstr *s );
@@ -58,6 +65,8 @@
 int  newstr_is_mixedcase( newstr *s );
 int  newstr_is_lowercase( newstr *s );
 int  newstr_is_uppercase( newstr *s );
+
+int newstr_newstrcmp    ( newstr *s, newstr *t );
 
 /* NEWSTR_PARANOIA
  *
diff --git a/bibutils/reftypes.h b/bibutils/reftypes.h
--- a/bibutils/reftypes.h
+++ b/bibutils/reftypes.h
@@ -9,23 +9,24 @@
 #ifndef REFTYPES_H
 #define REFTYPES_H
 
-#define SIMPLE        (0)
-#define TYPE          (1)
-#define PERSON        (2)
-#define DATE          (3)
-#define PAGES         (4)
-#define SERIALNO      (5)
-#define TITLE         (6)
-#define ALWAYS        (7)
-#define NOTES         (8)
-#define DOI           (9)
-#define HOWPUBLISHED  (10)
-#define BIBTEX_URL    (11)
-#define BIBTEX_SENTE  (12)
-#define LINKEDFILE    (13)
-#define BIBTEX_GENRE  (14)
-#define BIBTEX_EPRINT (15)
-#define KEYWORD       (16)
+#define SIMPLE              (0)
+#define TYPE                (1)
+#define PERSON              (2)
+#define DATE                (3)
+#define PAGES               (4)
+#define SERIALNO            (5)
+#define TITLE               (6)
+#define ALWAYS              (7)
+#define NOTES               (8)
+#define DOI                 (9)
+#define HOWPUBLISHED        (10)
+#define LINKEDFILE          (11)
+#define KEYWORD             (12)
+#define BIBTEX_URL          (13)
+#define BIBTEX_SENTE        (14)
+#define BIBTEX_GENRE        (15)
+#define BIBTEX_EPRINT       (16)
+#define BIBTEX_ORGANIZATION (17)
 
 typedef struct {
 	char *oldstr;
diff --git a/bibutils/vplist.c b/bibutils/vplist.c
--- a/bibutils/vplist.c
+++ b/bibutils/vplist.c
@@ -1,80 +1,174 @@
 /*
  * vplist.c
  *
+ * Version: 9/20/2012
+ *
  * Copyright (c) Chris Putnam 2011-2012
  *
  * Source code released under the GPL
  *
- * Implements a simple managed array of newstrs.
+ * Implements a simple managed array of pointers to void
  *
  */
+#include <stdlib.h>
+#include <assert.h>
 #include "vplist.h"
 
-void *
-vplist_get( vplist *a, int n )
+void
+vplist_init( vplist *vpl )
 {
-	if ( n<0 || n>a->n ) return NULL;
-	else return a->data[n];
+	assert( vpl );
+	vpl->data = NULL;
+	vpl->n = vpl->max = 0;
 }
 
+void
+vplist_empty( vplist *vpl )
+{
+	assert( vpl );
+	vpl->n = 0;
+}
+
+int
+vplist_find( vplist *vpl, void *v )
+{
+	int i;
+	assert( vpl );
+	for ( i=0; i<vpl->n; ++i )
+		if ( vpl->data[i]==v ) return i;
+	return -1;
+}
+
+int
+vplist_copy( vplist *to, vplist *from )
+{
+	int i;
+	assert( to );
+	assert( from );
+	if ( to->max >= from->n ) {
+		if ( to->max ) free( to->data );
+		to->data = ( void ** ) malloc( sizeof( void * ) * from->n );
+		if ( !to->data ) return 0;
+		to->max = from->n;
+	}
+	for ( i=0; i<from->n; ++i )
+		to->data[i] = from->data[i];
+	to->n = from->n;
+	return 1;
+}
+
+int
+vplist_append( vplist *to, vplist *from )
+{
+	int i, ok;
+	assert( to );
+	assert( from );
+	for ( i=0; i<from->n; ++i ) {
+		ok = vplist_add( to, from->data[i] );
+		if ( !ok ) return 0;
+	}
+	return 1;
+}
+
 static int
-vplist_alloc( vplist *a )
+vplist_validindex( vplist *vpl, int n )
 {
+	if ( n < 0 || n >= vpl->n ) return 0;
+	return 1;
+}
+
+static int
+vplist_alloc( vplist *vpl )
+{
 	int alloc = 20;
-	a->data = malloc( sizeof( void * ) * alloc );
-	if ( !(a->data) ) return 0;
-	a->max = alloc;
-	a->n = 0;
+	vpl->data = ( void ** ) malloc( sizeof( void * ) * alloc );
+	if ( !vpl->data ) return 0;
+	vpl->max = alloc;
+	vpl->n = 0;
 	return 1;
 }
 
 static int
-vplist_realloc( vplist *a )
+vplist_realloc( vplist *vpl )
 {
 	void **more;
-	int alloc = a->max * 2;
-	more = ( void** ) realloc( a->data, sizeof( void * ) * alloc );
+	int alloc = vpl->max * 2;
+	more = ( void ** ) realloc( vpl->data, sizeof( void * ) * alloc );
 	if ( !more ) return 0;
-	a->data = more;
-	a->max = alloc;
+	vpl->data = more;
+	vpl->max = alloc;
 	return 1;
 }
 
 int
-vplist_add( vplist *a, void *value )
+vplist_add( vplist *vpl, void *v )
 {
 	int ok = 1;
 
+	assert( vpl );
+
 	/* ensure sufficient space */
-	if ( a->max==0 ) ok = vplist_alloc( a );
-	else if ( a->n >= a->max ) ok = vplist_realloc( a );
+	if ( vpl->max==0 ) ok = vplist_alloc( vpl );
+	else if ( vpl->n >= vpl->max ) ok = vplist_realloc( vpl );
 
 	if ( ok ) {
-		a->data[a->n] = value;
-		a->n++;
+		vpl->data[vpl->n] = v;
+		vpl->n++;
 	}
 
 	return ok;
 }
 
+void *
+vplist_get( vplist *vpl, int n )
+{
+	assert( vpl );
+	if ( !vplist_validindex( vpl, n ) ) return NULL;
+	return vpl->data[ n ];
+}
+
 void
-vplist_empty( vplist *a )
+vplist_set( vplist *vpl, int n, void *v )
 {
-	a->n = 0;
+	assert( vpl );
+	if ( !vplist_validindex( vpl, n ) ) return;
+	vpl->data[ n ] = v;
 }
 
 void
-vplist_free( vplist *a )
+vplist_remove( vplist *vpl, int n )
 {
-	free( a->data );
-	vplist_init( a );
+	int i;
+	assert( vpl );
+	if ( !vplist_validindex( vpl, n ) ) return;
+	for ( i=n+1; i<vpl->n; ++i )
+		vpl->data[ i-1 ] = vpl->data[ i ];
+	vpl->n -= 1;
 }
 
 void
-vplist_init( vplist *a  )
+vplist_removevp( vplist *vpl, void *v )
 {
-	a->data = NULL;
-	a->max = 0;
-	a->n = 0;
+	int n;
+	assert( vpl );
+	do {
+		n = vplist_find( vpl, v );
+		if ( n!=-1 ) vplist_remove( vpl, n );
+	} while ( n!=-1 );
+}
+
+void
+vplist_free( vplist *vpl )
+{
+	free( vpl->data );
+	vplist_init( vpl );
+}
+
+void
+vplist_destroy( vplist **vpl )
+{
+	vplist_free( *vpl );
+	free( *vpl );
+	*vpl = NULL;
 }
 
diff --git a/bibutils/vplist.h b/bibutils/vplist.h
--- a/bibutils/vplist.h
+++ b/bibutils/vplist.h
@@ -1,29 +1,64 @@
 /*
  * vplist.h
  *
+ * Version: 9/20/2012
+ *
  * Copyright (c) Chris Putnam 2011-2012
  *
  * Source code released under the GPL
  *
  */
 
-#ifndef VPLISTS_H
-#define VPLISTS_H
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#ifndef VPLIST_H
+#define VPLIST_H
 
+/* vplist = void pointer list (generic container struct)
+ */
 typedef struct vplist {
 	int n, max;
 	void **data;
 } vplist;
 
-extern void    vplist_init( vplist *a );
-extern int     vplist_add( vplist *a, void *value );
-extern void    vplist_free( vplist *a );
-extern void*   vplist_get( vplist *a, int n );
-extern void    vplist_empty( vplist *a );
-
+extern void   vplist_init( vplist *vpl );
+extern int    vplist_add( vplist *vpl, void *v );
+extern void   vplist_empty( vplist *vpl );
+extern int    vplist_copy( vplist *to, vplist *from );
+extern int    vplist_append( vplist *to, vplist *from );
+extern void * vplist_get( vplist *vpl, int n );
+extern void   vplist_set( vplist *vpl, int n, void *v );
+extern void   vplist_remove( vplist *vpl, int n );
+extern void   vplist_removevp( vplist *vpl, void *v );
+extern int    vplist_find( vplist *vpl, void *v );
+/*
+ * vplist_free frees the space for the data array of void * elements.
+ *
+ * if members require their own free calls, then, vplist_free()
+ * should be wrapped in another deallocater:
+ *
+ * void foolist_free( vplist *vpl )
+ * {
+ *     int i;
+ *     for ( i=0; i<vpl->n; ++i )
+ *          if ( vpl->data[i] ) foo_free( (struct foo *) vpl->data[i] );
+ *     vplist_free( vpl );
+ * }
+ *
+ * vplist_free also does not deallocate any space corresponding
+ * to vplist.
+ */
+extern void vplist_free( vplist *vpl );
+/*
+ * vplist_destroy does vplist_free and deallocates the struct
+ * vplist * and replaces with NULL.
+ *
+ * void foolist_destroy( vplist **vpl )
+ * {
+ *     int i;
+ *     for ( i=0; i<(*vpl)->n; ++i )
+ *         if ( (*vpl)->data[i] ) foo_free( (struct foo *) (*vpl)->data[i] );
+ *     vplist_destroy( vpl );
+ * }
+ */
+extern void vplist_destroy( vplist **vpl );
 
 #endif
diff --git a/hs-bibutils.cabal b/hs-bibutils.cabal
--- a/hs-bibutils.cabal
+++ b/hs-bibutils.cabal
@@ -1,5 +1,5 @@
 name:               hs-bibutils
-version:            4.14
+version:            4.15
 homepage:           http://gorgias.mine.nu/repos/hs-bibutils/
 
 synopsis:           Haskell bindings to bibutils, the bibliography
@@ -14,7 +14,7 @@
                     the LICENSE file for details.
                     .
                     For more details about bibutils, please check:
-		    <http://www.scripps.edu/~cdputnam/software/bibutils/>.
+		    <http://sourceforge.net/p/bibutils/home/Bibutils/>.
                     .
                     The original API documentation is available here:
                     <http://www.scripps.edu/~cdputnam/software/bibutils/library_specs.html>.
