+ rc = attr_merge( e, desc, vals, nvals );
+
+error_return:;
+ if ( nvals != NULL ) {
+ ber_bvarray_free( nvals );
+ }
+ return rc;
+}
+
+int
+attr_merge_one(
+ Entry *e,
+ AttributeDescription *desc,
+ struct berval *val,
+ struct berval *nval
+) {
+ int rc;
+ Attribute **a;
+
+ for ( a = &e->e_attrs; *a != NULL; a = &(*a)->a_next ) {
+ if ( ad_cmp( (*a)->a_desc, desc ) == 0 ) {
+ break;
+ }
+ }
+
+ if ( *a == NULL ) {
+ *a = (Attribute *) ch_malloc( sizeof(Attribute) );
+ (*a)->a_desc = desc;
+ (*a)->a_vals = NULL;
+ (*a)->a_nvals = NULL;
+ (*a)->a_next = NULL;
+ (*a)->a_flags = 0;
+ }
+
+ rc = value_add_one( &(*a)->a_vals, val );
+
+ if( !rc && nval ) rc = value_add_one( &(*a)->a_nvals, nval );
+ else (*a)->a_nvals = (*a)->a_vals;
+ return rc;
+}
+
+int
+attr_merge_normalize_one(
+ Entry *e,
+ AttributeDescription *desc,
+ struct berval *val,
+ void *memctx
+) {
+ struct berval nval;
+ struct berval *nvalp;
+ int rc;
+
+ if ( desc->ad_type->sat_equality && desc->ad_type->sat_equality->smr_normalize ) {
+ rc = (*desc->ad_type->sat_equality->smr_normalize)(
+ 0,
+ desc->ad_type->sat_syntax,
+ desc->ad_type->sat_equality,
+ val, &nval, memctx );
+
+ if ( rc != LDAP_SUCCESS ) {
+ return rc;
+ }
+ nvalp = &nval;
+ } else {
+ nvalp = NULL;
+ }
+
+ rc = attr_merge_one( e, desc, val, nvalp );
+ if ( nvalp != NULL ) {
+ ch_free( nval.bv_val );
+ }
+ return rc;