Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
s/TRY/TRYOLD/ I'd like to introduce a TRY macro in the exception mecanism, but this...
[simgrid.git] / src / xbt / config.c
index 49271b1..fc595b2 100644 (file)
@@ -29,6 +29,10 @@ typedef struct {
   /* Allowed type of the variable */
   e_xbt_cfgelm_type_t type;
   int min,max;
+  
+  /* Callbacks */
+  xbt_cfg_cb_t cb_set;
+  xbt_cfg_cb_t cb_rm;
 
   /* actual content 
      (cannot be an union because type host uses both str and i) */
@@ -36,7 +40,7 @@ typedef struct {
 } s_xbt_cfgelm_t,*xbt_cfgelm_t;
 
 static const char *xbt_cfgelm_type_name[xbt_cfgelm_type_count]=
-  {"int","double","string","host"};
+  {"int","double","string","host","any"};
 
 /* Internal stuff used in cache to free a variable */
 static void xbt_cfgelm_free(void *data);
@@ -46,13 +50,10 @@ static xbt_error_t xbt_cfgelm_get(xbt_cfg_t cfg, const char *name,
                                    e_xbt_cfgelm_type_t type,
                                    /* OUT */ xbt_cfgelm_t *whereto);
 
-void xbt_cfg_str_free(void *d);
-void xbt_cfg_host_free(void *d);
-
-void xbt_cfg_str_free(void *d){
+static void xbt_cfg_str_free(void *d){
   free(*(void**)d);
 }
-void xbt_cfg_host_free(void *d){
+static void xbt_cfg_host_free(void *d){
   xbt_host_t *h=(xbt_host_t*) *(void**)d; 
   if (h) {
     if (h->name) free(h->name);
@@ -72,7 +73,7 @@ xbt_cfg_t xbt_cfg_new(void) {
   return (xbt_cfg_t)xbt_dict_new();
 }
 
-/** @brief Copy an existing configuration set
+/** \brief Copy an existing configuration set
  *
  * \arg whereto the config set to be created
  * \arg tocopy the source data
@@ -90,7 +91,8 @@ xbt_cfg_cpy(xbt_cfg_t tocopy,xbt_cfg_t *whereto) {
   xbt_assert0(tocopy,"cannot copy NULL config");
 
   xbt_dict_foreach((xbt_dict_t)tocopy,cursor,name,variable) {
-    xbt_cfg_register(*whereto, name, variable->type, variable->min, variable->max);
+    xbt_cfg_register(*whereto, name, variable->type, variable->min, variable->max,
+                     variable->cb_set, variable->cb_rm);
   }
 }
 
@@ -124,9 +126,10 @@ void xbt_cfg_dump(const char *name,const char *indent,xbt_cfg_t cfg) {
     printf("%s  %s:",indent,key);
 
     size = xbt_dynar_length(variable->content);
-    printf("%d_to_%d_%s. Actual size=%d. List of values:\n",
+    printf("%d_to_%d_%s. Actual size=%d. prerm=%p,postset=%p, List of values:\n",
           variable->min,variable->max,xbt_cfgelm_type_name[variable->type],
-          size);
+          size,
+           variable->cb_rm, variable->cb_set);
 
     switch (variable->type) {
        
@@ -196,11 +199,15 @@ void xbt_cfgelm_free(void *data) {
 void
 xbt_cfg_register(xbt_cfg_t cfg,
                  const char *name, e_xbt_cfgelm_type_t type,
-                 int min, int max){
+                 int min, int max,
+                 xbt_cfg_cb_t cb_set,  xbt_cfg_cb_t cb_rm){
   xbt_cfgelm_t res;
   xbt_error_t errcode;
 
-  DEBUG4("Register cfg elm %s (%d to %d %s)",name,min,max,xbt_cfgelm_type_name[type]);
+  xbt_assert4(type>=xbt_cfgelm_int && type<=xbt_cfgelm_host,
+              "type of %s not valid (%d should be between %d and %d)",
+              name,type,xbt_cfgelm_int, xbt_cfgelm_host);
+  DEBUG5("Register cfg elm %s (%d to %d %s (=%d))",name,min,max,xbt_cfgelm_type_name[type],type);
   errcode = xbt_dict_get((xbt_dict_t)cfg,name,(void**)&res);
 
   if (errcode == no_error) {
@@ -214,6 +221,8 @@ xbt_cfg_register(xbt_cfg_t cfg,
   res->type=type;
   res->min=min;
   res->max=max;
+  res->cb_set = cb_set;
+  res->cb_rm  = cb_rm;
 
   switch (type) {
   case xbt_cfgelm_int:
@@ -258,7 +267,7 @@ xbt_cfg_unregister(xbt_cfg_t cfg,const char *name) {
  * @arg cfg the config set
  * @arg entry a string describing the element to register
  *
- * The string may consist in several variable description separated by a space. 
+ * The string may consist in several variable descriptions separated by a space. 
  * Each of them must use the following syntax: \<name\>:\<min nb\>_to_\<max nb\>_\<type\>
  * with type being one of  'string','int', 'host' or 'double'.
  */
@@ -323,7 +332,7 @@ xbt_cfg_register_str(xbt_cfg_t cfg,const char *entry) {
     xbt_abort();
   }
 
-  xbt_cfg_register(cfg,entrycpy,type,min,max);
+  xbt_cfg_register(cfg,entrycpy,type,min,max,NULL,NULL);
 
   free(entrycpy); /* strdup'ed by dict mechanism, but cannot be const */
   return no_error;
@@ -352,7 +361,7 @@ xbt_cfg_check(xbt_cfg_t cfg) {
       return mismatch_error;
     }
 
-    if (variable->max < size) {
+    if (variable->max > 0 && variable->max < size) {
       ERROR4("Config elem %s accepts at most %d %s, but there is %d values.",
             name,
             variable->max,
@@ -377,14 +386,14 @@ static xbt_error_t xbt_cfgelm_get(xbt_cfg_t  cfg,
                                       (void**)whereto);
 
   if (errcode == mismatch_error) {
-    ERROR1("No registered variable %s in this config set",
+    RAISE1(mismatch_error,
+           "No registered variable '%s' in this config set",
           name);
-    return mismatch_error;
   }
   if (errcode != no_error)
      return errcode;
 
-  xbt_assert3((*whereto)->type == type,
+  xbt_assert3(type == xbt_cfgelm_any || (*whereto)->type == type,
               "You tried to access to the config element %s as an %s, but its type is %s.",
               name,
               xbt_cfgelm_type_name[type],
@@ -408,14 +417,16 @@ xbt_cfg_get_type(xbt_cfg_t cfg, const char *name,
   xbt_cfgelm_t variable;
   xbt_error_t errcode;
 
-  TRYCATCH(mismatch_error,xbt_dict_get((xbt_dict_t)cfg,name,(void**)&variable));
+  errcode=xbt_dict_get((xbt_dict_t)cfg,name,(void**)&variable);
 
   if (errcode == mismatch_error) {
-    ERROR1("Can't get the type of '%s' since this variable does not exist",
+    RAISE1(mismatch_error,"Can't get the type of '%s' since this variable does not exist",
           name);
-    return mismatch_error;
+  } else if (errcode != no_error) {
+    return errcode;
   }
 
+  INFO1("type in variable = %d",variable->type);
   *type=variable->type;
 
   return no_error;
@@ -425,69 +436,68 @@ xbt_cfg_get_type(xbt_cfg_t cfg, const char *name,
 /**  @brief va_args version of xbt_cfg_set
  *
  * \arg cfg config set to fill
- * \arg varargs NULL-terminated list of pairs {(const char*)key, value}
+ * \arg n   variable name
+ * \arg pa  variable value
  *
  * Add some values to the config set.
- * \warning if the list isn't NULL terminated, it will segfault. 
  */
 xbt_error_t
-xbt_cfg_set_vargs(xbt_cfg_t cfg, va_list pa) {
-  char *str,*name;
+xbt_cfg_set_vargs(xbt_cfg_t cfg, const char *name, va_list pa) {
+  char *str;
   int i;
   double d;
   e_xbt_cfgelm_type_t type;
 
   xbt_error_t errcode;
   
-  while ((name=va_arg(pa,char *))) {
-
-    if (!xbt_cfg_get_type(cfg,name,&type)) {
-      ERROR1("Can't set the property '%s' since it's not registered",name);
-      return mismatch_error;
-    }
+  errcode = xbt_cfg_get_type(cfg,name,&type);
+  if (errcode != no_error) {
+    ERROR1("Can't set the property '%s' since it's not registered",name);
+    return mismatch_error;
+  }
 
-    switch (type) {
-    case xbt_cfgelm_host:
-      str = va_arg(pa, char *);
-      i=va_arg(pa,int);
-      TRY(xbt_cfg_set_host(cfg,name,str,i));
-      break;
+  switch (type) {
+  case xbt_cfgelm_host:
+    str = va_arg(pa, char *);
+    i=va_arg(pa,int);
+    TRYOLD(xbt_cfg_set_host(cfg,name,str,i));
+    break;
       
-    case xbt_cfgelm_string:
-      str=va_arg(pa, char *);
-      TRY(xbt_cfg_set_string(cfg, name, str));
-      break;
+  case xbt_cfgelm_string:
+    str=va_arg(pa, char *);
+    TRYOLD(xbt_cfg_set_string(cfg, name, str));
+    break;
 
-    case xbt_cfgelm_int:
-      i=va_arg(pa,int);
-      TRY(xbt_cfg_set_int(cfg,name,i));
-      break;
+  case xbt_cfgelm_int:
+    i=va_arg(pa,int);
+    TRYOLD(xbt_cfg_set_int(cfg,name,i));
+    break;
 
-    case xbt_cfgelm_double:
-      d=va_arg(pa,double);
-      TRY(xbt_cfg_set_double(cfg,name,d));
-      break;
+  case xbt_cfgelm_double:
+    d=va_arg(pa,double);
+    TRYOLD(xbt_cfg_set_double(cfg,name,d));
+    break;
 
-    default: 
-      RAISE1(unknown_error,"Config element variable %s not valid.",name);
-    }
+  default:
+    xbt_assert2(0,"Config element variable %s not valid (type=%d)",name,type);
   }
+
   return no_error;
 }
 
 /** @brief Add a NULL-terminated list of pairs {(char*)key, value} to the set
  *
  * \arg cfg config set to fill
- * \arg varargs NULL-terminated list of pairs {(const char*)key, value}
+ * \arg name variable name
+ * \arg varargs variable value
  *
- * \warning if the list isn't NULL terminated, it will segfault. 
  */
-xbt_error_t xbt_cfg_set(xbt_cfg_t cfg, ...) {
+xbt_error_t xbt_cfg_set(xbt_cfg_t cfg, const char *name, ...) {
   va_list pa;
   xbt_error_t errcode;
 
-  va_start(pa,cfg);
-  errcode=xbt_cfg_set_vargs(cfg,pa);
+  va_start(pa,name);
+  errcode=xbt_cfg_set_vargs(cfg,name,pa);
   va_end(pa);
   return errcode;
 }
@@ -536,15 +546,15 @@ xbt_cfg_set_parse(xbt_cfg_t cfg, const char *options) {
 
     /* Pass the value */
     while (option-name<=(len-1) && *option != ' ' && *option != '\n' && *option != '\t') {
-      DEBUG1("Take %c.\n",*option);
+      DEBUG1("Take %c.",*option);
       option++;
     }
     if (option-name == len) {
-      DEBUG0("Boundary=EOL\n");
+      DEBUG0("Boundary=EOL");
       option=NULL; /* don't do next iteration */
 
     } else {
-      DEBUG3("Boundary on '%c'. len=%d;option-name=%d\n",
+      DEBUG3("Boundary on '%c'. len=%d;option-name=%d",
             *option,len,option-name);
 
       /* Pass the following blank chars */
@@ -678,13 +688,24 @@ xbt_cfg_set_int(xbt_cfg_t cfg,const char*name, int val) {
   xbt_error_t errcode;
 
   VERB2("Configuration setting: %s=%d",name,val);
-  TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_int,&variable));
+  TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_int,&variable));
 
-  if (variable->max > 1) {
-    xbt_dynar_push(variable->content,&val);
-  } else {
+  if (variable->max == 1) {
+    if (variable->cb_rm && xbt_dynar_length(variable->content))
+      (*variable->cb_rm)(name, 0);
+          
     xbt_dynar_set(variable->content,0,&val);
+  } else {
+    if (variable->max && xbt_dynar_length(variable->content) == variable->max)
+      RAISE3(mismatch_error,
+             "Cannot add value %d to the config element %s since it's already full (size=%d)",
+             val,name,variable->max); 
+             
+    xbt_dynar_push(variable->content,&val);
   }
+
+  if (variable->cb_set)
+    (*variable->cb_set)(name, xbt_dynar_length(variable->content) -1);
   return no_error;
 }
 
@@ -701,13 +722,24 @@ xbt_cfg_set_double(xbt_cfg_t cfg,const char*name, double val) {
   xbt_error_t errcode;
 
   VERB2("Configuration setting: %s=%f",name,val);
-  TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_double,&variable));
+  TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_double,&variable));
 
-  if (variable->max > 1) {
-    xbt_dynar_push(variable->content,&val);
-  } else {
+  if (variable->max == 1) {
+    if (variable->cb_rm && xbt_dynar_length(variable->content))
+      (*variable->cb_rm)(name, 0);
+          
     xbt_dynar_set(variable->content,0,&val);
+  } else {
+    if (variable->max && xbt_dynar_length(variable->content) == variable->max)
+      RAISE3(mismatch_error,
+             "Cannot add value %f to the config element %s since it's already full (size=%d)",
+             val,name,variable->max); 
+             
+    xbt_dynar_push(variable->content,&val);
   }
+
+  if (variable->cb_set)
+    (*variable->cb_set)(name, xbt_dynar_length(variable->content) -1);
   return no_error;
 }
 
@@ -726,13 +758,24 @@ xbt_cfg_set_string(xbt_cfg_t cfg,const char*name, const char*val) {
   char *newval = xbt_strdup(val);
 
   VERB2("Configuration setting: %s=%s",name,val);
-  TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_string,&variable));
+  TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_string,&variable));
 
-  if (variable->max > 1) {
-    xbt_dynar_push(variable->content,&newval);
-  } else {
+  if (variable->max == 1) {
+    if (variable->cb_rm && xbt_dynar_length(variable->content))
+      (*variable->cb_rm)(name, 0);
+          
     xbt_dynar_set(variable->content,0,&newval);
+  } else {
+    if (variable->max && xbt_dynar_length(variable->content) == variable->max)
+      RAISE3(mismatch_error,
+             "Cannot add value %s to the config element %s since it's already full (size=%d)",
+             name,val,variable->max); 
+             
+    xbt_dynar_push(variable->content,&newval);
   }
+
+  if (variable->cb_set)
+    (*variable->cb_set)(name, xbt_dynar_length(variable->content) -1);
   return no_error;
 }
 
@@ -758,13 +801,24 @@ xbt_cfg_set_host(xbt_cfg_t cfg,const char*name,
   val->name = xbt_strdup(name);
   val->port = port;
 
-  TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_host,&variable));
+  TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_host,&variable));
 
-  if (variable->max > 1) {
-    xbt_dynar_push(variable->content,&val);
-  } else {
+  if (variable->max == 1) {
+    if (variable->cb_rm && xbt_dynar_length(variable->content))
+      (*variable->cb_rm)(name, 0);
+          
     xbt_dynar_set(variable->content,0,&val);
+  } else {
+    if (variable->max && xbt_dynar_length(variable->content) == variable->max)
+      RAISE4(mismatch_error,
+             "Cannot add value %s:%d to the config element %s since it's already full (size=%d)",
+             host,port,name,variable->max); 
+             
+    xbt_dynar_push(variable->content,&val);
   }
+
+  if (variable->cb_set)
+    (*variable->cb_set)(name, xbt_dynar_length(variable->content) -1);
   return no_error;
 }
 
@@ -782,10 +836,16 @@ xbt_error_t xbt_cfg_rm_int(xbt_cfg_t cfg,const char*name, int val) {
   int cpt,seen;
   xbt_error_t errcode;
 
-  TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_int,&variable));
+  if (xbt_dynar_length(variable->content) == variable->min)
+    RAISE3(mismatch_error,
+           "Cannot remove value %d from the config element %s since it's already at its minimal size (=%d)",
+           val,name,variable->min); 
+
+  TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_int,&variable));
   
   xbt_dynar_foreach(variable->content,cpt,seen) {
     if (seen == val) {
+      if (variable->cb_rm) (*variable->cb_rm)(name, cpt);
       xbt_dynar_cursor_rm(variable->content,&cpt);
       return no_error;
     }
@@ -809,11 +869,17 @@ xbt_error_t xbt_cfg_rm_double(xbt_cfg_t cfg,const char*name, double val) {
   double seen;
   xbt_error_t errcode;
 
-  TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_double,&variable));
+  if (xbt_dynar_length(variable->content) == variable->min)
+    RAISE3(mismatch_error,
+           "Cannot remove value %f from the config element %s since it's already at its minimal size (=%d)",
+           val,name,variable->min); 
+
+  TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_double,&variable));
   
   xbt_dynar_foreach(variable->content,cpt,seen) {
     if (seen == val) {
       xbt_dynar_cursor_rm(variable->content,&cpt);
+      if (variable->cb_rm) (*variable->cb_rm)(name, cpt);
       return no_error;
     }
   }
@@ -836,10 +902,16 @@ xbt_cfg_rm_string(xbt_cfg_t cfg,const char*name, const char *val) {
   char *seen;
   xbt_error_t errcode;
 
-  TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_string,&variable));
+  if (xbt_dynar_length(variable->content) == variable->min)
+    RAISE3(mismatch_error,
+           "Cannot remove value %s from the config element %s since it's already at its minimal size (=%d)",
+           name,val,variable->min); 
+           
+  TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_string,&variable));
   
   xbt_dynar_foreach(variable->content,cpt,seen) {
     if (!strcpy(seen,val)) {
+      if (variable->cb_rm) (*variable->cb_rm)(name, cpt);
       xbt_dynar_cursor_rm(variable->content,&cpt);
       return no_error;
     }
@@ -865,10 +937,16 @@ xbt_cfg_rm_host(xbt_cfg_t cfg,const char*name, const char *host,int port) {
   xbt_host_t *seen;
   xbt_error_t errcode;
 
-  TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_host,&variable));
+  if (xbt_dynar_length(variable->content) == variable->min)
+    RAISE4(mismatch_error,
+           "Cannot remove value %s:%d from the config element %s since it's already at its minimal size (=%d)",
+           host,port,name,variable->min); 
+           
+  TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_host,&variable));
   
   xbt_dynar_foreach(variable->content,cpt,seen) {
     if (!strcpy(seen->name,host) && seen->port == port) {
+      if (variable->cb_rm) (*variable->cb_rm)(name, cpt);
       xbt_dynar_cursor_rm(variable->content,&cpt);
       return no_error;
     }
@@ -879,6 +957,28 @@ xbt_cfg_rm_host(xbt_cfg_t cfg,const char*name, const char *host,int port) {
   return mismatch_error;
 }
 
+/** @brief Remove the \e pos th value from the provided variable */
+
+xbt_error_t xbt_cfg_rm_at   (xbt_cfg_t cfg, const char *name, int pos) {
+
+  xbt_cfgelm_t variable;
+  int cpt;
+  xbt_host_t *seen;
+  xbt_error_t errcode;
+
+  if (xbt_dynar_length(variable->content) == variable->min)
+    RAISE3(mismatch_error,
+           "Cannot remove %dth value from the config element %s since it's already at its minimal size (=%d)",
+           pos,name,variable->min); 
+           
+  TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_any,&variable));
+  
+  if (variable->cb_rm) (*variable->cb_rm)(name, pos);    
+  xbt_dynar_remove_at(variable->content, pos, NULL);
+
+  return mismatch_error;
+}
+
 /** @brief Remove all the values from a variable
  * 
  * \arg cfg the config set
@@ -900,6 +1000,13 @@ xbt_cfg_empty(xbt_cfg_t cfg,const char*name) {
   }
 
   if (variable) {
+    if (variable->cb_rm) {
+      int cpt;
+      void *ignored;
+      xbt_dynar_foreach(variable->content,cpt,ignored) {
+        (*variable->cb_rm)(name, cpt);
+      }
+    }
     xbt_dynar_reset(variable->content);
   }
   return no_error;
@@ -926,7 +1033,7 @@ xbt_cfg_get_int   (xbt_cfg_t  cfg,
   xbt_cfgelm_t variable;
   xbt_error_t errcode;
 
-  TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_int,&variable));
+  TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_int,&variable));
 
   if (xbt_dynar_length(variable->content) > 1) {
     WARN2("You asked for the first value of the config element '%s', but there is %lu values",
@@ -957,7 +1064,7 @@ xbt_cfg_get_double(xbt_cfg_t  cfg,
   xbt_cfgelm_t variable;
   xbt_error_t  errcode;
 
-  TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_double,&variable));
+  TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_double,&variable));
 
   if (xbt_dynar_length(variable->content) > 1) {
     WARN2("You asked for the first value of the config element '%s', but there is %lu values\n",
@@ -989,7 +1096,7 @@ xbt_error_t xbt_cfg_get_string(xbt_cfg_t  cfg,
 
   *val=NULL;
 
-  TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_string,&variable));
+  TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_string,&variable));
 
   if (xbt_dynar_length(variable->content) > 1) {
     WARN2("You asked for the first value of the config element '%s', but there is %lu values\n",
@@ -1022,7 +1129,7 @@ xbt_error_t xbt_cfg_get_host  (xbt_cfg_t  cfg,
   xbt_error_t  errcode;
   xbt_host_t  *val;
 
-  TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_host,&variable));
+  TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_host,&variable));
 
   if (xbt_dynar_length(variable->content) > 1) {
     WARN2("You asked for the first value of the config element '%s', but there is %lu values\n",
@@ -1065,3 +1172,68 @@ xbt_error_t xbt_cfg_get_dynar (xbt_cfg_t    cfg,
   return no_error;
 }
 
+
+/** @brief Retrieve one of the integer value of a variable */
+xbt_error_t
+xbt_cfg_get_int_at(xbt_cfg_t   cfg,
+                   const char *name,
+                   int         pos,
+                   int        *val) {
+                  
+  xbt_cfgelm_t variable;
+  xbt_error_t errcode;
+
+  TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_int,&variable));
+  *val = xbt_dynar_get_as(variable->content, pos, int);
+  return no_error; 
+}
+
+/** @brief Retrieve one of the double value of a variable */
+xbt_error_t
+xbt_cfg_get_double_at(xbt_cfg_t   cfg,
+                      const char *name,
+                      int         pos,
+                      double     *val) {
+                  
+  xbt_cfgelm_t variable;
+  xbt_error_t errcode;
+
+  TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_double,&variable));
+  *val = xbt_dynar_get_as(variable->content, pos, double);
+  return no_error; 
+}
+
+
+/** @brief Retrieve one of the string value of a variable */
+xbt_error_t
+xbt_cfg_get_string_at(xbt_cfg_t   cfg,
+                      const char *name,
+                      int         pos,
+                      char      **val) {
+                  
+  xbt_cfgelm_t variable;
+  xbt_error_t errcode;
+
+  TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_string,&variable));
+  *val = xbt_dynar_get_as(variable->content, pos, char*);
+  return no_error; 
+}
+
+/** @brief Retrieve one of the host value of a variable */
+xbt_error_t
+xbt_cfg_get_host_at(xbt_cfg_t   cfg,
+                    const char *name,
+                    int         pos,
+                    char      **host,
+                    int        *port) {
+                  
+  xbt_cfgelm_t variable;
+  xbt_error_t errcode;
+  xbt_host_t *val;
+
+  TRYOLD(xbt_cfgelm_get(cfg,name,xbt_cfgelm_int,&variable));
+  val = xbt_dynar_get_ptr(variable->content, pos);
+  *port = val->port;
+  *host = val->name;
+  return no_error; 
+}