diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,8 @@
+# 6.7.0.0
+
+  - Import Bibutils 6.7
+
+
 # 6.6.0.0
 
   - Import Bibutils 6.6.
diff --git a/bibutils/adsout.c b/bibutils/adsout.c
--- a/bibutils/adsout.c
+++ b/bibutils/adsout.c
@@ -357,6 +357,96 @@
 }
 
 static char
+initial_ascii( const char *name )
+{
+	int b1, b2;
+
+	if ( isascii( name[0] )  )
+		return name[0];
+
+        b1 = name[0]+256;
+        b2 = name[1]+256;
+
+	switch( b1 ) {
+
+	case 0xc3:
+		     if ( b2 >= 0x80 && b2 <= 0x86 ) return 'A';
+		else if ( b2 == 0x87 )               return 'C';
+		else if ( b2 >= 0x88 && b2 <= 0x8b ) return 'E';
+		else if ( b2 >= 0x8c && b2 <= 0x8f ) return 'I';
+		else if ( b2 == 0x90 )               return 'D';
+		else if ( b2 == 0x91 )               return 'N';
+		else if ( b2 >= 0x92 && b2 <= 0x98 ) return 'O';
+		else if ( b2 >= 0x99 && b2 <= 0x9c ) return 'U';
+		else if ( b2 == 0x9d )               return 'Y';
+		else if ( b2 == 0x9f )               return 'S';
+		else if ( b2 >= 0xa0 && b2 <= 0xa6 ) return 'A';
+		else if ( b2 == 0xa7 )               return 'C';
+		else if ( b2 >= 0xa8 && b2 <= 0xab ) return 'E';
+		else if ( b2 >= 0xac && b2 <= 0xaf ) return 'I';
+		else if ( b2 == 0xb0 )               return 'D';
+		else if ( b2 == 0xb1 )               return 'N';
+		else if ( b2 >= 0xb2 && b2 <= 0xb8 ) return 'O';
+		else if ( b2 >= 0xb9 && b2 <= 0xbc ) return 'U';
+		else if ( b2 >= 0xbd && b2 <= 0xbf ) return 'Y';
+	break;
+
+	case 0xc4:
+		     if ( b2 >= 0x80 && b2 <= 0x85 ) return 'A';
+		else if ( b2 >= 0x86 && b2 <= 0x8d ) return 'C';
+		else if ( b2 >= 0x8e || b2 <= 0x91 ) return 'D';
+		else if ( b2 >= 0x92 && b2 <= 0x9b ) return 'E';
+		else if ( b2 >= 0x9c && b2 <= 0xa3 ) return 'G';
+		else if ( b2 >= 0xa4 && b2 <= 0xa7 ) return 'H';
+		else if ( b2 >= 0xa8 && b2 <= 0xb3 ) return 'I';
+		else if ( b2 >= 0xb4 && b2 <= 0xb5 ) return 'J';
+		else if ( b2 >= 0xb6 && b2 <= 0xb8 ) return 'K';
+		else if ( b2 >= 0xb9 && b2 <= 0xbf ) return 'L';
+	break;
+
+	case 0xc5:
+		     if ( b2 >= 0x80 && b2 <= 0x82 ) return 'L';
+		else if ( b2 >= 0x83 && b2 <= 0x8b ) return 'N';
+		else if ( b2 >= 0x8c || b2 <= 0x93 ) return 'O';
+		else if ( b2 >= 0x94 && b2 <= 0x99 ) return 'R';
+		else if ( b2 >= 0x9a && b2 <= 0xa1 ) return 'S';
+		else if ( b2 >= 0xa2 && b2 <= 0xa7 ) return 'T';
+		else if ( b2 >= 0xa8 && b2 <= 0xb3 ) return 'U';
+		else if ( b2 >= 0xb4 && b2 <= 0xb5 ) return 'W';
+		else if ( b2 >= 0xb6 && b2 <= 0xb8 ) return 'Y';
+		else if ( b2 >= 0xb9 && b2 <= 0xbf ) return 'Z';
+	break;
+
+	case 0xc6:
+		     if ( b2 >= 0x80 && b2 <= 0x85 ) return 'B';
+		else if ( b2 >= 0x86 && b2 <= 0x88 ) return 'C';
+		else if ( b2 >= 0x89 || b2 <= 0x8d ) return 'D';
+		else if ( b2 >= 0x8e && b2 <= 0x90 ) return 'E';
+		else if ( b2 >= 0x91 && b2 <= 0x92 ) return 'F';
+		else if ( b2 >= 0x93 && b2 <= 0x94 ) return 'G';
+		else if ( b2 == 0x95 )               return 'H';
+		else if ( b2 >= 0x96 && b2 <= 0x97 ) return 'I';
+		else if ( b2 >= 0x98 && b2 <= 0x99 ) return 'K';
+		else if ( b2 >= 0xba && b2 <= 0x9b ) return 'L';
+		else if ( b2 == 0xbc )               return 'M';
+		else if ( b2 >= 0x9d && b2 <= 0x9e ) return 'N';
+		else if ( b2 >= 0x9f && b2 <= 0xa3 ) return 'O';
+		else if ( b2 >= 0xa4 && b2 <= 0xa5 ) return 'P';
+		else if ( b2 == 0xa6 )               return 'R';
+		else if ( b2 >= 0xa7 && b2 <= 0xaa ) return 'S';
+		else if ( b2 >= 0xab && b2 <= 0xae ) return 'T';
+		else if ( b2 >= 0xaf && b2 <= 0xb1 ) return 'U';
+		else if ( b2 == 0xb2 )               return 'V';
+		else if ( b2 >= 0xb3 && b2 <= 0xb4 ) return 'Y';
+		else if ( b2 >= 0xb5 && b2 <= 0xbe ) return 'Z';
+	break;
+
+	}
+
+	return '.';
+}
+
+static char
 get_firstinitial( fields *in )
 {
 	char *name;
@@ -367,7 +457,7 @@
 
 	if ( n!=FIELDS_NOTFOUND ) {
 		name = fields_value( in, n, FIELDS_CHRP );
-		return name[0];
+		return initial_ascii( name );
 	} else return '\0';
 }
 
@@ -429,7 +519,7 @@
 	}
 
 	/** A */
-        ch = toupper( (unsigned char) get_firstinitial( in ) );
+	 ch = toupper( (unsigned char) get_firstinitial( in ) );
 	if ( ch!='\0' ) outstr[18] = ch;
 
 	fstatus = fields_add( out, adstag, outstr, LEVEL_MAIN );
@@ -437,24 +527,34 @@
 }
 
 static void
-append_easyall( fields *in, char *tag, char *adstag, int level, fields *out, int *status )
+append_easyall( fields *in, char *tag, char *adstag, int level, fields *out, char *prefix, int *status )
 {
 	vplist_index i;
 	int fstatus;
+	str output;
+	char *val;
 	vplist a;
 
 	vplist_init( &a );
+	if ( prefix ) str_init( &output );
 
 	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 );
+		val = ( char * ) vplist_get( &a, i );
+		if ( prefix ) {
+			str_strcpyc( &output, prefix );
+			str_strcatc( &output, val );
+			val = str_cstr( &output );
+		}
+		fstatus = fields_add( out, adstag, val, LEVEL_MAIN );
 		if ( fstatus!=FIELDS_OK ) {
 			*status = BIBL_ERR_MEMERR;
 			goto out;
 		}
 	}
 out:
+	if ( prefix ) str_free( &output );
 	vplist_free( &a );
 }
 
@@ -503,7 +603,8 @@
 	int lstatus;
 	slist types;
 
-	lstatus = slist_init_valuesc( &types, "URL", "DOI", "PMID", "PMC", "ARXIV", "JSTOR", "MRNUMBER", "FILEATTACH", "FIGATTACH", NULL );
+	/* skip DOI as we'll add that separately */
+	lstatus = slist_init_valuesc( &types, "URL", "PMID", "PMC", "ARXIV", "JSTOR", "MRNUMBER", "FILEATTACH", "FIGATTACH", NULL );
 	if ( lstatus!=SLIST_OK ) {
 		*status = BIBL_ERR_MEMERR;
 		return;
@@ -556,23 +657,23 @@
 	fields_clearused( in );
 	type = get_type( in );
 
+	append_Rtag   ( in, "%R", type, out, &status );
 	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_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_easyall( in, "NOTES",      "%X", LEVEL_ANY, out, NULL, &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_easyall( in, "DOI",        "%Y", LEVEL_ANY, out, "DOI:", &status );
 	append_trailer( out, &status );
-	append_Rtag   ( in, "%R", type, out, &status );
 
 	return status;
 }
diff --git a/bibutils/fields.c b/bibutils/fields.c
--- a/bibutils/fields.c
+++ b/bibutils/fields.c
@@ -456,7 +456,7 @@
 	if ( mode & FIELDS_STRP_FLAG ) {
 		v = ( void * ) &( f->data[n] );
 	} else if ( mode & FIELDS_POSP_FLAG ) {
-		v = ( void * )( (long) n );
+		v = ( void * )( (long long) n );
 	} else {
 		v = ( void * ) str_cstr( &( f->data[n] ) );
 	}
diff --git a/bibutils/str.c b/bibutils/str.c
--- a/bibutils/str.c
+++ b/bibutils/str.c
@@ -1,7 +1,7 @@
 /*
  * str.c
  *
- * Version: 2017-07-03
+ * Version: 2018-08-03
  *
  * Copyright (c) Chris Putnam 1999-2018
  *
@@ -28,7 +28,42 @@
 
 #define str_initlen (64)
 
+#ifndef STR_SMALL
 
+#define str_clear_status( s ) s->status = STR_OK;
+#define handle_memerr( s, f ) s->status = STR_MEMERR;
+#define return_if_memerr( s ) \
+{ \
+	if ( s->status != STR_OK ) return; \
+}
+#define return_zero_if_memerr( s ) \
+{ \
+	if ( s->status != STR_OK ) return 0; \
+}
+#define return_after_delim_if_memerr( s, p, delim, finalstep ) \
+{ \
+	if ( s->status != STR_OK ) { \
+		while ( p && *p && !strchr( delim, *p ) ) p++; \
+		if ( p && *p && finalstep ) p++; \
+		return p; \
+	} \
+}
+
+#else
+
+#define str_clear_status( s ) {}
+#define handle_memerr( s, f ) \
+{ \
+	fprintf( stderr,"Error.  Cannot allocate memory in %s.\n", f ); \
+	exit( EXIT_FAILURE ); \
+}
+#define return_if_memerr( s ) {}
+#define return_zero_if_memerr( s ) {}
+#define return_after_delim_if_memerr( s, p, delim, finalstep ) {}
+
+#endif
+
+
 /* Clear memory in resize/free if STR_PARANOIA defined */
 
 #ifndef STR_PARANOIA
@@ -36,16 +71,18 @@
 static void 
 str_realloc( str *s, unsigned long minsize )
 {
-	char *newptr;
 	unsigned long size;
+	char *newptr;
+
 	assert( s );
+	return_if_memerr( s );
+
 	size = 2 * s->dim;
 	if (size < minsize) size = minsize;
+
 	newptr = (char *) realloc( s->data, sizeof( *(s->data) )*size );
-	if ( !newptr ) {
-		fprintf( stderr,"Error.  Cannot reallocate memory (%lu bytes) in str_realloc.\n", sizeof(*(s->data))*size );
-		exit( EXIT_FAILURE );
-	}
+	if ( !newptr ) handle_memerr( s, __FUNCTION__ );
+
 	s->data = newptr;
 	s->dim = size;
 }
@@ -58,16 +95,18 @@
 static void 
 str_realloc( str *s, unsigned long minsize )
 {
-	char *newptr;
 	unsigned long size;
+	char *newptr;
+
 	assert( s );
+	return_if_memerr( s );
+
 	size = 2 * s->dim;
 	if ( size < minsize ) size = minsize;
+
 	newptr = (char *) malloc( sizeof( *(s->data) ) * size );
-	if ( !newptr ) {
-		fprintf( stderr, "Error.  Cannot reallocate memory (%lu bytes) in str_realloc.\n", sizeof(*(s->data))*size );
-		exit( EXIT_FAILURE );
-	}
+	if ( !newptr ) handle_memerr( s, __FUNCTION__ );
+
 	if ( s->data ) {
 		str_nullify( s );
 		free( s->data );
@@ -91,6 +130,7 @@
 	s->dim = 0;
 	s->len = 0;
 	s->data = NULL;
+	str_clear_status( s );
 }
 
 void
@@ -139,16 +179,14 @@
 	va_end( ap );
 }
 
-/*
- * This is currently a stub. Later it will
- * report whether or not a str function
- * could not be performed due to a memory
- * error.
- */
 int
 str_memerr( str *s )
 {
+#ifndef STR_SMALL
+	return s->status == STR_MEMERR;
+#else
 	return 0;
+#endif
 }
 
 void
@@ -156,6 +194,7 @@
 {
 	va_list ap;
 	const char *cp;
+	str_clear_status( s );
 	str_empty( s );
 	va_start( ap, s );
 	do {
@@ -229,6 +268,7 @@
 str_empty( str *s )
 {
 	assert( s );
+	str_clear_status( s );
 	if ( s->data ) {
 		str_nullify( s );
 		s->data[0] = '\0';
@@ -254,11 +294,16 @@
 str_addchar( str *s, char newchar )
 {
 	assert( s );
+
+	return_if_memerr( s );
+
 	if ( newchar=='\0' ) return; /* appending '\0' is a null operation */
+
 	if ( !s->data || s->dim==0 ) 
 		str_initalloc( s, str_initlen );
 	if ( s->len + 2 > s->dim ) 
 		str_realloc( s, s->len*2 );
+
 	s->data[s->len++] = newchar;
 	s->data[s->len] = '\0';
 }
@@ -304,9 +349,14 @@
 str_prepend( str *s, const char *addstr )
 {
 	unsigned long lenaddstr, i;
+
 	assert( s && addstr );
+
+	return_if_memerr( s );
+
 	lenaddstr = strlen( addstr );
-	if ( lenaddstr==0 ) return;
+	if ( lenaddstr==0 ) return; /* appending an empty string is a null op */
+
 	if ( !s->data || !s->dim )
 		str_initalloc( s, lenaddstr+1 );
 	else {
@@ -333,6 +383,7 @@
 static inline void 
 str_strcat_internal( str *s, const char *addstr, unsigned long n )
 {
+	return_if_memerr( s );
 	str_strcat_ensurespace( s, n );
 	strncat( &(s->data[s->len]), addstr, n );
 	s->len += n;
@@ -365,6 +416,8 @@
 	assert( s && startat && endat );
 	assert( (size_t) startat < (size_t) endat );
 
+	return_if_memerr( s );
+
 	if ( startat==endat ) return;
 
 	n = 0;
@@ -381,8 +434,12 @@
 str_indxcat( str *s, char *p, unsigned long start, unsigned long stop )
 {
 	unsigned long i;
+
 	assert( s && p );
 	assert( start <= stop );
+
+	return_if_memerr( s );
+
 	for ( i=start; i<stop; ++i )
 		str_addchar( s, p[i] );
 }
@@ -396,6 +453,7 @@
 str_cpytodelim( str *s, char *p, const char *delim, unsigned char finalstep )
 {
 	assert( s );
+
 	str_empty( s );
 	return str_cattodelim( s, p, delim, finalstep );
 }
@@ -409,6 +467,9 @@
 str_cattodelim( str *s, char *p, const char *delim, unsigned char finalstep )
 {
 	assert( s );
+
+	return_after_delim_if_memerr( s, p, delim, finalstep );
+
 	while ( p && *p && !strchr( delim, *p ) ) {
 		str_addchar( s, *p );
 		p++;
@@ -430,6 +491,8 @@
 static inline void
 str_strcpy_internal( str *s, const char *p, unsigned long n )
 {
+	return_if_memerr( s );
+
 	str_strcpy_ensurespace( s, n );
 	strncpy( s->data, p, n );
 	s->data[n] = '\0';
@@ -468,6 +531,8 @@
 	assert( s && startat && endat );
 	assert( ((size_t) startat) <= ((size_t) endat) );
 
+	return_if_memerr( s );
+
 	if ( startat==endat ) {
 		str_empty( s );
 		return;
@@ -492,8 +557,12 @@
 str_indxcpy( str *s, char *p, unsigned long start, unsigned long stop )
 {
 	unsigned long i;
+
 	assert( s && p );
 	assert( start <= stop );
+
+	return_if_memerr( s );
+
 	if ( start == stop ) {
 		str_empty( s );
 		return;
@@ -528,7 +597,11 @@
 {
 	str tmp1, tmp2;
 	char *r;
+
 	assert( s );
+
+	return_if_memerr( s );
+
 	r = &(s->data[s->len]);
 	str_init( &tmp1 );
 	str_init( &tmp2 );
@@ -560,7 +633,10 @@
 	int n = 0;
 
 	assert( s && find );
-	if ( !s->data || !s->dim ) return n;
+
+	return_zero_if_memerr( s );
+
+	if ( !s->data || !s->dim ) return 0;
 	if ( !replace ) replace = empty;
 
 	find_len = strlen( find );
@@ -1015,6 +1091,7 @@
 {
 	unsigned long i;
 	assert( s );
+	str_clear_status( s );
 	if ( !s->data || s->dim==0 )
 		str_initalloc( s, n+1 );
 	if ( n + 1 > s->dim )
diff --git a/bibutils/str.h b/bibutils/str.h
--- a/bibutils/str.h
+++ b/bibutils/str.h
@@ -1,7 +1,7 @@
 /*
  * str.h
  *
- * Version: 2017-07-03
+ * Version: 2018-08-03
  *
  * Copyright (c) Chris Putnam 1999-2018
  *
@@ -11,12 +11,18 @@
 #ifndef STR_H
 #define STR_H
 
+#define STR_OK (0)
+#define STR_MEMERR (-1)
+
 #include <stdio.h>
 
 typedef struct str {
 	char *data;
 	unsigned long dim;
 	unsigned long len;
+#ifndef STR_SMALL
+	int status;
+#endif
 }  str;
 
 str *  str_new         ( void );
@@ -120,6 +126,12 @@
  * in str functions...useful for library construction for
  * Linux distributions that don't want libraries calling exit, but
  * not useful during code development
+ */
+
+/* #define STR_SMALL
+ *
+ * set to make the smallest possible struct str, but will get
+ * exit( EXIT_FAILURE ) upon memory failures
  */
 
 #endif
diff --git a/bibutils/url.c b/bibutils/url.c
--- a/bibutils/url.c
+++ b/bibutils/url.c
@@ -116,6 +116,7 @@
 }
 
 /* science direct is now doing "M3  - doi: DOI: 10.xxxx/xxxxx" */
+/* elsevier is doing "DO - https://doi.org/xx.xxxx/xxxx..." */
 int
 is_doi( char *s )
 {
@@ -123,6 +124,7 @@
 	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;
+	if ( string_pattern( s, "https://doi.org/##.####/", 0 ) ) return 16;
 	return -1;
 }
 
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:            6.6.0.0
+version:            6.7.0.0
 homepage:           https://github.com/wilx/hs-bibutils
 
 synopsis:           Haskell bindings to bibutils, the bibliography
