From 0aaf5180f7ef1d43e360dbd44829066d4ef2f2ca Mon Sep 17 00:00:00 2001
From: Sergey Poznyakoff <gray@Pirx.gnu.org.ua>
Date: Sat, 13 Jun 2009 18:50:28 +0300
Subject: [PATCH] Fix reloading sequence maps

* include/sm/map.h (sm_map_initopt, sm_map_addopt): New prototypes.
* libsmmap/mapconfopen.c (sm_mapconfopen): Properly handle
MST_SEQUENCE type: use sm_map_addopt instead of sm_map_setopt.
* libsmmap/mapopt.c (collect_options_from): New auxiliary finction.
(sm_map_initopt, sm_map_addopt): New functions.
(sm_map_setopt): Use collect_options_from.
---
 include/sm/map.h       |    2 +
 libsmmap/mapconfopen.c |    6 +-
 libsmmap/mapopt.c      |  105 +++++++++++++++++++++++++++++++++++++----------
 3 files changed, 87 insertions(+), 26 deletions(-)

diff --git a/include/sm/map.h b/include/sm/map.h
index 35290bb..19c09d2 100644
--- a/include/sm/map.h
+++ b/include/sm/map.h
@@ -123,7 +123,9 @@ sm_ret_T sm_map_open(sm_maps_P _maps, const sm_cstr_P _name, const sm_cstr_P _ty
 sm_ret_T sm_map_close(sm_map_P _map, uint32_t _flags);
 sm_ret_T sm_map_destroy(sm_map_P _map, uint32_t flags);
 sm_ret_T sm_map_reopen(sm_map_P _map, uint32_t flags, ...);
+void sm_map_initopt(sm_map_P map);
 sm_ret_T sm_map_setopt(sm_map_P _map, ...);
+sm_ret_T sm_map_addopt(sm_map_P map, ...);
 sm_ret_T sm_map_getopt(sm_map_P _map, int _which, void *_valp);
 
 sm_ret_T sm_map_lookup(sm_map_P _map, uint32_t _flags, sm_map_key_P _key, sm_map_data_P _data);
diff --git a/libsmmap/mapconfopen.c b/libsmmap/mapconfopen.c
index 1172220..e14eccd 100644
--- a/libsmmap/mapconfopen.c
+++ b/libsmmap/mapconfopen.c
@@ -105,7 +105,7 @@ sm_mapconfopen(map_decl_P mapdef, sm_maps_P maps, const char *confdir)
 			break;
 
 		  case MST_SEQUENCE:
-			ret = SM_SUCCESS;
+			sm_map_initopt(map);
 			for (i = 0;
 			     md_maps->mst_seq.mst_seq_maps[i] != NULL && ret == SM_SUCCESS;
 			     i++)
@@ -119,8 +119,8 @@ sm_mapconfopen(map_decl_P mapdef, sm_maps_P maps, const char *confdir)
 					ret = sm_error_temp(SM_EM_MAP, ENOMEM);
 					goto error;
 				}
-				ret = sm_map_setopt(map, SMPO_MAPNAME, sname, SMPO_END);
-				SM_CSTR_FREE(sname);
+				ret = sm_map_addopt(map, SMPO_MAPNAME, sname,
+						    SMPO_END);
 			}
 			if (sm_is_err(ret))
 				break;
diff --git a/libsmmap/mapopt.c b/libsmmap/mapopt.c
index db918b7..3052f0c 100644
--- a/libsmmap/mapopt.c
+++ b/libsmmap/mapopt.c
@@ -17,6 +17,44 @@ SM_RCSID("@(#)$Id: mapopt.c,v 1.10 2006/05/02 17:13:41 ca Exp $")
 #include "sm/map.h"
 #include "sm/mapc.h"
 
+static sm_ret_T
+collect_options_from(sm_map_P map, int i, va_list ap)
+{
+	int opttype;
+	
+	for (; i < SM_MAP_MAX_OPT; i++)
+	{
+		opttype = va_arg(ap, int);
+		map->sm_map_opts[i].sm_map_opt_type = opttype;
+		if (opttype == SMPO_END)
+			break;
+		switch (SMPO_GET_TYPE(opttype))
+		{
+		  case SMPO_INT:
+			map->sm_map_opts[i].sm_map_opt_int = va_arg(ap, int);
+			break;
+		  case SMPO_PTR:
+			map->sm_map_opts[i].sm_map_opt_ptr = va_arg(ap,
+								    void *);
+			break;
+		  default:
+			/* crash and burn */
+			SM_ASSERT(opttype == SMPO_END);
+			break;
+		}
+	}
+	if (i >= SM_MAP_MAX_OPT)
+		return sm_error_perm(SM_EM_MAP, SM_E_FULL);
+	return SM_SUCCESS;
+}
+
+void
+sm_map_initopt(sm_map_P map)
+{
+	SM_IS_MAP(map);
+	sm_memzero(&map->sm_map_opts, sizeof(map->sm_map_opts));
+}
+
 /*
 **  MAP_SETOPT -- set options for map
 **
@@ -41,31 +79,52 @@ sm_map_setopt(sm_map_P map, ...)
 	SM_IS_MAPC(mapc);
 	sm_memzero(&map->sm_map_opts, sizeof(map->sm_map_opts));
 	va_start(ap, map);
-	for (i = 0; i < SM_MAP_MAX_OPT; i++)
+	ret = collect_options_from(map, 0, ap);
+	va_end(ap);
+	if (sm_is_error(ret))
+		return ret;
+	
+	if (mapc->sm_mapc_setoptf != NULL)
 	{
-		opttype = va_arg(ap, int);
-		map->sm_map_opts[i].sm_map_opt_type = opttype;
-		if (opttype == SMPO_END)
-			break;
-		switch (SMPO_GET_TYPE(opttype))
-		{
-		  case SMPO_INT:
-			map->sm_map_opts[i].sm_map_opt_int = va_arg(ap, int);
-			break;
-		  case SMPO_PTR:
-			map->sm_map_opts[i].sm_map_opt_ptr = va_arg(ap,
-								void *);
-			break;
-		  default:
-			/* crash and burn */
-			SM_ASSERT(opttype == SMPO_END);
-			break;
-		}
+		va_start(ap, map);
+		ret = mapc->sm_mapc_setoptf(map, ap);
+		va_end(ap);
 	}
-	va_end(ap);
-	if (i >= SM_MAP_MAX_OPT)
-		return sm_error_perm(SM_EM_MAP, SM_E_FULL);
+	else
+		ret = sm_error_perm(SM_EM_MAP, EINVAL);	/* XXX */
+	return ret;
+}	
+
+/*
+**  MAP_ADDOPT -- add options to map
+**
+**	Parameters:
+**		map -- map
+**		... -- options
+**
+**	Returns:
+**		usual sm_error code
+*/
+sm_ret_T
+sm_map_addopt(sm_map_P map, ...)
+{
+	sm_ret_T ret;
+	sm_mapc_P mapc;
+	int i, opttype;
+	va_list ap;
 
+	SM_IS_MAP(map);
+	mapc = map->sm_map_class;
+	SM_IS_MAPC(mapc);
+	for (i = 0; i < SM_MAP_MAX_OPT
+		     && map->sm_map_opts[i].sm_map_opt_type != SMPO_END; i++)
+		;
+	va_start(ap, map);
+	ret = collect_options_from(map, i, ap);
+	va_end(ap);
+	if (sm_is_error(ret))
+		return ret;
+	
 	if (mapc->sm_mapc_setoptf != NULL)
 	{
 		va_start(ap, map);
@@ -76,7 +135,7 @@ sm_map_setopt(sm_map_P map, ...)
 		ret = sm_error_perm(SM_EM_MAP, EINVAL);	/* XXX */
 	return ret;
 }
-
+	
 /*
 **  MAP_SETONEOPT -- set one option for a map
 **
-- 
1.6.0

