+ BerVarray vals,
+ BerVarray nvals )
+{
+ int rc;
+
+ Attribute **a;
+
+ for ( a = &e->e_attrs; *a != NULL; a = &(*a)->a_next ) {
+ if ( (*a)->a_desc == desc ) {
+ break;
+ }
+ }
+
+ if ( *a == NULL ) {
+ *a = attr_alloc( desc );
+ } else {
+ /*
+ * FIXME: if the attribute already exists, the presence
+ * of nvals and the value of (*a)->a_nvals must be consistent
+ */
+ assert( ( nvals == NULL && (*a)->a_nvals == (*a)->a_vals )
+ || ( nvals != NULL && (
+ ( (*a)->a_vals == NULL && (*a)->a_nvals == NULL )
+ || ( (*a)->a_nvals != (*a)->a_vals ) ) ) );
+ }
+
+ rc = value_add( &(*a)->a_vals, vals );
+
+ if ( rc == LDAP_SUCCESS ) {
+ if ( nvals ) {
+ rc = value_add( &(*a)->a_nvals, nvals );
+ /* FIXME: what if rc != LDAP_SUCCESS ? */
+ } else {
+ (*a)->a_nvals = (*a)->a_vals;
+ }
+ }
+
+ return rc;
+}
+
+/*
+ * if a normalization function is defined for the equality matchingRule
+ * of desc, the value is normalized and stored in nval; otherwise nval
+ * is NULL
+ */
+int
+attr_normalize(
+ AttributeDescription *desc,
+ BerVarray vals,
+ BerVarray *nvalsp,
+ void *memctx )
+{
+ int rc = LDAP_SUCCESS;
+ BerVarray nvals = NULL;
+
+ *nvalsp = NULL;
+
+ if ( desc->ad_type->sat_equality &&
+ desc->ad_type->sat_equality->smr_normalize )
+ {
+ int i;
+
+ for ( i = 0; !BER_BVISNULL( &vals[i] ); i++ );
+
+ nvals = slap_sl_calloc( sizeof(struct berval), i + 1, memctx );
+ for ( i = 0; !BER_BVISNULL( &vals[i] ); i++ ) {
+ rc = desc->ad_type->sat_equality->smr_normalize(
+ SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+ desc->ad_type->sat_syntax,
+ desc->ad_type->sat_equality,
+ &vals[i], &nvals[i], memctx );
+
+ if ( rc != LDAP_SUCCESS ) {
+ BER_BVZERO( &nvals[i + 1] );
+ break;
+ }
+ }
+ BER_BVZERO( &nvals[i] );
+ *nvalsp = nvals;
+ }
+
+error_return:;
+ if ( rc != LDAP_SUCCESS && nvals != NULL ) {
+ ber_bvarray_free_x( nvals, memctx );
+ }
+
+ return rc;
+}
+
+int
+attr_merge_normalize(
+ Entry *e,
+ AttributeDescription *desc,
+ BerVarray vals,
+ void *memctx )
+{
+ BerVarray nvals = NULL;
+ int rc;
+
+ rc = attr_normalize( desc, vals, &nvals, memctx );
+ if ( rc == LDAP_SUCCESS ) {
+ rc = attr_merge( e, desc, vals, nvals );
+ if ( nvals != NULL ) {
+ ber_bvarray_free_x( nvals, memctx );
+ }
+ }
+
+ return rc;
+}
+
+int
+attr_merge_one(
+ Entry *e,
+ AttributeDescription *desc,
+ struct berval *val,
+ struct berval *nval )