Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
get rid of the nasty TRYCLEAN
[simgrid.git] / src / xbt / config.c
1 /* $Id$ */
2
3 /* config - Dictionnary where the type of each cell is provided.            */
4
5 /* This is useful to build named structs, like option or property sets.     */
6
7 /* Copyright (c) 2001,2002,2003,2004 Martin Quinson. All rights reserved.   */
8
9 /* This program is free software; you can redistribute it and/or modify it
10  * under the terms of the license (GNU LGPL) which comes with this package. */
11
12 #include "xbt/misc.h"
13 #include "xbt/sysdep.h"
14 #include "xbt/log.h"
15 #include "xbt/error.h"
16 #include "xbt/dynar.h"
17 #include "xbt/dict.h"
18
19 #include "xbt/config.h" /* prototypes of this module */
20
21 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(config,xbt,"configuration support");
22
23 /* xbt_cfgelm_t: the typedef corresponding to a config cell. 
24
25    Both data and DTD are mixed, but fixing it now would prevent me to ever
26    defend my thesis. */
27
28 typedef struct {
29   /* Allowed type of the cell */
30   e_xbt_cfgelm_type_t type;
31   int min,max;
32
33   /* actual content 
34      (cannot be an union because type host uses both str and i) */
35   xbt_dynar_t content;
36 } s_xbt_cfgelm_t,*xbt_cfgelm_t;
37
38 static const char *xbt_cfgelm_type_name[xbt_cfgelm_type_count]=
39   {"int","double","string","host"};
40
41 /* Internal stuff used in cache to free a cell */
42 static void xbt_cfgelm_free(void *data);
43
44 /* Retrieve the cell we'll modify */
45 static xbt_error_t xbt_cfgelm_get(xbt_cfg_t cfg, const char *name,
46                                     e_xbt_cfgelm_type_t type,
47                                     /* OUT */ xbt_cfgelm_t *whereto);
48
49 void xbt_cfg_str_free(void *d);
50 void xbt_cfg_host_free(void *d);
51
52 void xbt_cfg_str_free(void *d){
53   xbt_free(*(void**)d);
54 }
55 void xbt_cfg_host_free(void *d){
56   xbt_host_t *h=(xbt_host_t*) *(void**)d; 
57   if (h) {
58     if (h->name) xbt_free(h->name);
59     xbt_free(h);
60   }
61 }
62
63 /*----[ Memory management ]-----------------------------------------------*/
64
65 /**
66  * xbt_cfg_new:
67  *
68  * \return
69  *
70  * Initialise an config set
71  */
72
73
74 xbt_cfg_t xbt_cfg_new(void) {
75   return (xbt_cfg_t)xbt_dict_new();
76 }
77
78 /**
79  * xbt_cfg_cpy:
80  *
81  * \arg whereto the config set to be created
82  * \arg tocopy the source data
83  *
84  */
85
86 void
87 xbt_cfg_cpy(xbt_cfg_t tocopy,xbt_cfg_t *whereto) {
88   xbt_dict_cursor_t cursor=NULL; 
89   xbt_cfgelm_t cell=NULL;
90   char *name=NULL;
91   
92   *whereto=NULL;
93   xbt_assert0(tocopy,"cannot copy NULL config");
94
95   xbt_dict_foreach((xbt_dict_t)tocopy,cursor,name,cell) {
96     xbt_cfg_register(*whereto, name, cell->type, cell->min, cell->max);
97   }
98 }
99
100 void xbt_cfg_free(xbt_cfg_t *cfg) {
101   xbt_dict_free((xbt_dict_t*)cfg);
102 }
103
104 /**
105  * xbt_cfg_dump:
106  * \arg name The name to give to this config set
107  * \arg indent what to write at the begining of each line (right number of spaces)
108  * \arg cfg the config set
109  *
110  * Dumps a config set for debuging purpose
111  */
112 void
113 xbt_cfg_dump(const char *name,const char *indent,xbt_cfg_t cfg) {
114   xbt_dict_t dict = (xbt_dict_t) cfg;
115   xbt_dict_cursor_t cursor=NULL; 
116   xbt_cfgelm_t cell=NULL;
117   char *key=NULL;
118   int i; 
119   int size;
120   int ival;
121   char *sval;
122   double dval;
123   xbt_host_t *hval;
124
125   if (name)
126     printf("%s>> Dumping of the config set '%s':\n",indent,name);
127   xbt_dict_foreach(dict,cursor,key,cell) {
128
129     printf("%s  %s:",indent,key);
130
131     size = xbt_dynar_length(cell->content);
132     printf("%d_to_%d_%s. Actual size=%d. List of values:\n",
133            cell->min,cell->max,xbt_cfgelm_type_name[cell->type],
134            size);
135
136     switch (cell->type) {
137        
138     case xbt_cfgelm_int:
139       for (i=0; i<size; i++) {
140         ival = xbt_dynar_get_as(cell->content,i,int);
141         printf ("%s    %d\n",indent,ival);
142       }
143       break;
144
145     case xbt_cfgelm_double:
146       for (i=0; i<size; i++) {
147         dval = xbt_dynar_get_as(cell->content,i,double);
148         printf ("%s    %f\n",indent,dval);
149       }
150       break;
151
152     case xbt_cfgelm_string:
153       for (i=0; i<size; i++) {
154         sval = xbt_dynar_get_as(cell->content,i,char*);
155         printf ("%s    %s\n",indent,sval);
156       }
157       break;
158
159     case xbt_cfgelm_host:
160       for (i=0; i<size; i++) {
161         hval = xbt_dynar_get_as(cell->content,i,xbt_host_t*);
162         printf ("%s    %s:%d\n",indent,hval->name,hval->port);
163       }
164       break;
165
166     default:
167       printf("%s    Invalid type!!\n",indent);
168     }
169
170   }
171
172   if (name) printf("%s<< End of the config set '%s'\n",indent,name);
173   fflush(stdout);
174
175   xbt_dict_cursor_free(&cursor);
176   return;
177 }
178
179 /**
180  * xbt_cfgelm_free:
181  *
182  * \arg data the data to be freed (typed as void* to be usable as free funct in dict)
183  *
184  * free an config element
185  */
186
187 void xbt_cfgelm_free(void *data) {
188   xbt_cfgelm_t c=(xbt_cfgelm_t)data;
189
190   if (!c) return;
191   xbt_dynar_free(&(c->content));
192   xbt_free(c);
193 }
194
195 /*----[ Registering stuff ]-----------------------------------------------*/
196
197 /**
198  * xbt_cfg_register:
199  * \arg cfg the config set
200  * \arg type the type of the config element
201  * \arg min the minimum
202  * \arg max the maximum
203  *
204  * register an element within a config set
205  */
206
207 void
208 xbt_cfg_register(xbt_cfg_t cfg,
209                   const char *name, e_xbt_cfgelm_type_t type,
210                   int min, int max){
211   xbt_cfgelm_t res;
212   xbt_error_t errcode;
213
214   DEBUG4("Register cfg elm %s (%d to %d %s)",name,min,max,xbt_cfgelm_type_name[type]);
215   errcode = xbt_dict_get((xbt_dict_t)cfg,name,(void**)&res);
216
217   if (errcode == no_error) {
218     WARN1("Config elem %s registered twice.",name);
219     /* Will be removed by the insertion of the new one */
220   } 
221   xbt_assert_error(mismatch_error);
222
223   res=xbt_new(s_xbt_cfgelm_t,1);
224
225   res->type=type;
226   res->min=min;
227   res->max=max;
228
229   switch (type) {
230   case xbt_cfgelm_int:
231     res->content = xbt_dynar_new(sizeof(int), NULL);
232     break;
233
234   case xbt_cfgelm_double:
235     res->content = xbt_dynar_new(sizeof(double), NULL);
236     break;
237
238   case xbt_cfgelm_string:
239    res->content = xbt_dynar_new(sizeof(char*),&xbt_cfg_str_free);
240    break;
241
242   case xbt_cfgelm_host:
243    res->content = xbt_dynar_new(sizeof(xbt_host_t*),&xbt_cfg_host_free);
244    break;
245
246   default:
247     ERROR1("%d is an invalide type code",type);
248   }
249     
250   xbt_dict_set((xbt_dict_t)cfg,name,res,&xbt_cfgelm_free);
251 }
252
253 /**
254  * xbt_cfg_unregister:
255  * 
256  * \arg cfg the config set
257  * \arg name the name of the elem to be freed
258  * 
259  * unregister an element from a config set. 
260  * Note that it removes both the DTD and the actual content.
261  */
262
263 xbt_error_t
264 xbt_cfg_unregister(xbt_cfg_t cfg,const char *name) {
265   return xbt_dict_remove((xbt_dict_t)cfg,name);
266 }
267
268 /**
269  * xbt_cfg_register_str:
270  *
271  * \arg cfg the config set
272  * \arg entry a string describing the element to register
273  *
274  * Parse a string and register the stuff described.
275  */
276
277 xbt_error_t
278 xbt_cfg_register_str(xbt_cfg_t cfg,const char *entry) {
279   char *entrycpy=xbt_strdup(entry);
280   char *tok;
281
282   int min,max;
283   e_xbt_cfgelm_type_t type;
284
285   tok=strchr(entrycpy, ':');
286   if (!tok) {
287     ERROR3("%s%s%s",
288           "Invalid config element descriptor: ",entry,
289           "; Should be <name>:<min nb>_to_<max nb>_<type>");
290     xbt_free(entrycpy);
291     xbt_abort();
292   }
293   *(tok++)='\0';
294
295   min=strtol(tok, &tok, 10);
296   if (!tok) {
297     ERROR1("Invalid minimum in config element descriptor %s",entry);
298     xbt_free(entrycpy);
299     xbt_abort();
300   }
301
302   if (!strcmp(tok,"_to_")){
303     ERROR3("%s%s%s",
304           "Invalid config element descriptor: ",entry,
305           "; Should be <name>:<min nb>_to_<max nb>_<type>");
306     xbt_free(entrycpy);
307     xbt_abort();
308   }
309   tok += strlen("_to_");
310
311   max=strtol(tok, &tok, 10);
312   if (!tok) {
313     ERROR1("Invalid maximum in config element descriptor %s",entry);
314     xbt_free(entrycpy);
315     xbt_abort();
316   }
317
318   if (*(tok++)!='_') {
319     ERROR3("%s%s%s",
320           "Invalid config element descriptor: ",entry,
321           "; Should be <name>:<min nb>_to_<max nb>_<type>");
322     xbt_free(entrycpy);
323     xbt_abort();
324   }
325
326   for (type=0; 
327        type<xbt_cfgelm_type_count && strcmp(tok,xbt_cfgelm_type_name[type]); 
328        type++);
329   if (type == xbt_cfgelm_type_count) {
330     ERROR3("%s%s%s",
331           "Invalid type in config element descriptor: ",entry,
332           "; Should be one of 'string', 'int', 'host' or 'double'.");
333     xbt_free(entrycpy);
334     xbt_abort();
335   }
336
337   xbt_cfg_register(cfg,entrycpy,type,min,max);
338
339   xbt_free(entrycpy); /* strdup'ed by dict mechanism, but cannot be const */
340   return no_error;
341 }
342
343 /**
344  * xbt_cfg_check:
345  *
346  * \arg cfg the config set
347  * 
348  * Check the config set
349  */
350
351 xbt_error_t
352 xbt_cfg_check(xbt_cfg_t cfg) {
353   xbt_dict_cursor_t cursor; 
354   xbt_cfgelm_t cell;
355   char *name;
356   int size;
357
358   xbt_assert0(cfg,"NULL config set.");
359
360   xbt_dict_foreach((xbt_dict_t)cfg,cursor,name,cell) {
361     size = xbt_dynar_length(cell->content);
362     if (cell->min > size) { 
363       ERROR4("Config elem %s needs at least %d %s, but there is only %d values.",
364              name,
365              cell->min,
366              xbt_cfgelm_type_name[cell->type],
367              size); 
368       xbt_dict_cursor_free(&cursor);
369       return mismatch_error;
370     }
371
372     if (cell->max < size) {
373       ERROR4("Config elem %s accepts at most %d %s, but there is %d values.",
374              name,
375              cell->max,
376              xbt_cfgelm_type_name[cell->type],
377              size);
378       xbt_dict_cursor_free(&cursor);
379       return mismatch_error;
380     }
381
382   }
383
384   xbt_dict_cursor_free(&cursor);
385   return no_error;
386 }
387
388 static xbt_error_t xbt_cfgelm_get(xbt_cfg_t  cfg,
389                                     const char *name,
390                                     e_xbt_cfgelm_type_t type,
391                                     /* OUT */ xbt_cfgelm_t *whereto){
392    
393   xbt_error_t errcode = xbt_dict_get((xbt_dict_t)cfg,name,
394                                        (void**)whereto);
395
396   if (errcode == mismatch_error) {
397     ERROR1("No registered cell %s in this config set",
398            name);
399     return mismatch_error;
400   }
401   if (errcode != no_error)
402      return errcode;
403
404   xbt_assert3((*whereto)->type == type,
405                "You tried to access to the config element %s as an %s, but its type is %s.",
406                name,
407                xbt_cfgelm_type_name[type],
408                xbt_cfgelm_type_name[(*whereto)->type]);
409
410   return no_error;
411 }
412
413 /**
414  * xbt_cfg_get_type:
415  *
416  * \arg cfg the config set
417  * \arg name the name of the element 
418  * \arg type the result
419  *
420  * Give the type of the config element
421  */
422
423 xbt_error_t
424 xbt_cfg_get_type(xbt_cfg_t cfg, const char *name, 
425                       /* OUT */e_xbt_cfgelm_type_t *type) {
426
427   xbt_cfgelm_t cell;
428   xbt_error_t errcode;
429
430   TRYCATCH(mismatch_error,xbt_dict_get((xbt_dict_t)cfg,name,(void**)&cell));
431
432   if (errcode == mismatch_error) {
433     ERROR1("Can't get the type of '%s' since this cell does not exist",
434            name);
435     return mismatch_error;
436   }
437
438   *type=cell->type;
439
440   return no_error;
441 }
442
443 /*----[ Setting ]---------------------------------------------------------*/
444 /** 
445  * xbt_cfg_set_vargs(): 
446  * \arg cfg config set to fill
447  * \arg varargs NULL-terminated list of pairs {(const char*)key, value}
448  *
449  * Add some values to the config set.
450  * \warning if the list isn't NULL terminated, it will segfault. 
451  */
452 xbt_error_t
453 xbt_cfg_set_vargs(xbt_cfg_t cfg, va_list pa) {
454   char *str,*name;
455   int i;
456   double d;
457   e_xbt_cfgelm_type_t type;
458
459   xbt_error_t errcode;
460   
461   while ((name=va_arg(pa,char *))) {
462
463     if (!xbt_cfg_get_type(cfg,name,&type)) {
464       ERROR1("Can't set the property '%s' since it's not registered",name);
465       return mismatch_error;
466     }
467
468     switch (type) {
469     case xbt_cfgelm_host:
470       str = va_arg(pa, char *);
471       i=va_arg(pa,int);
472       TRY(xbt_cfg_set_host(cfg,name,str,i));
473       break;
474       
475     case xbt_cfgelm_string:
476       str=va_arg(pa, char *);
477       TRY(xbt_cfg_set_string(cfg, name, str));
478       break;
479
480     case xbt_cfgelm_int:
481       i=va_arg(pa,int);
482       TRY(xbt_cfg_set_int(cfg,name,i));
483       break;
484
485     case xbt_cfgelm_double:
486       d=va_arg(pa,double);
487       TRY(xbt_cfg_set_double(cfg,name,d));
488       break;
489
490     default: 
491       RAISE1(unknown_error,"Config element cell %s not valid.",name);
492     }
493   }
494   return no_error;
495 }
496
497 /** 
498  * xbt_cfg_set():
499  * \arg cfg config set to fill
500  * \arg varargs NULL-terminated list of pairs {(const char*)key, value}
501  *
502  * Add some values to the config set.
503  * \warning if the list isn't NULL terminated, it will segfault. 
504  */
505 xbt_error_t xbt_cfg_set(xbt_cfg_t cfg, ...) {
506   va_list pa;
507   xbt_error_t errcode;
508
509   va_start(pa,cfg);
510   errcode=xbt_cfg_set_vargs(cfg,pa);
511   va_end(pa);
512   return errcode;
513 }
514
515 /**
516  * xbt_cfg_set_parse():
517  * \arg cfg config set to fill
518  * \arg options a string containing the content to add to the config set. This
519  * is a '\t',' ' or '\n' separated list of cells. Each individual cell is
520  * like "[name]:[value]" where [name] is the name of an already registred 
521  * cell, and [value] conforms to the data type under which this cell was
522  * registred.
523  *
524  * Add the cells described in a string to a config set.
525  */
526
527 xbt_error_t
528 xbt_cfg_set_parse(xbt_cfg_t cfg, const char *options) {
529   int i;
530   double d;
531   char *str;
532
533   xbt_cfgelm_t cell;
534   char *optionlist_cpy;
535   char *option,  *name,*val;
536
537   int len;
538   xbt_error_t errcode;
539
540   XBT_IN;
541   if (!options || !strlen(options)) { /* nothing to do */
542     return no_error;
543   }
544   optionlist_cpy=xbt_strdup(options);
545
546   DEBUG1("List to parse and set:'%s'",options);
547   option=optionlist_cpy;
548   while (1) { /* breaks in the code */
549
550     if (!option) 
551       break;
552     name=option;
553     len=strlen(name);
554     DEBUG3("Still to parse and set: '%s'. len=%d; option-name=%ld",
555            name,len,(long)(option-name));
556
557     /* Pass the value */
558     while (option-name<=(len-1) && *option != ' ' && *option != '\n' && *option != '\t') {
559       /*fprintf(stderr,"Take %c.\n",*option);*/
560       option++;
561     }
562     if (option-name == len) {
563       /*fprintf(stderr,"Boundary=EOL\n");*/
564       option=NULL; /* don't do next iteration */
565
566     } else {
567       /*fprintf(stderr,"Boundary on '%c'. len=%d;option-name=%d\n",*option,len,option-name);*/
568
569       /* Pass the following blank chars */
570       *(option++)='\0';
571       while (option-name<(len-1) && (*option == ' ' || *option == '\n' || *option == '\t')) {
572         /*      fprintf(stderr,"Ignore a blank char.\n");*/
573         option++;
574       }
575       if (option-name == len-1)
576         option=NULL; /* don't do next iteration */
577     }
578     DEBUG2("parse now:'%s'; parse later:'%s'",name,option);
579
580     if (name[0] == ' ' || name[0] == '\n' || name[0] == '\t')
581       continue;
582     if (!strlen(name))
583       break;
584     
585     val=strchr(name,':');
586     if (!val) {
587       xbt_free(optionlist_cpy);
588       xbt_assert1(FALSE,
589                    "Malformated option: '%s'; Should be of the form 'name:value'",
590                    name);
591     }
592     *(val++)='\0';
593
594     DEBUG2("name='%s';val='%s'",name,val);
595
596     errcode=xbt_dict_get((xbt_dict_t)cfg,name,(void**)&cell);
597     switch (errcode) {
598     case no_error:
599       break;
600     case mismatch_error:
601       ERROR1("No registrated cell corresponding to '%s'.",name);
602       xbt_free(optionlist_cpy);
603       return mismatch_error;
604       break;
605     default:
606       xbt_free(optionlist_cpy);
607       return errcode;
608     }
609
610     switch (cell->type) {
611     case xbt_cfgelm_string:
612       errcode = xbt_cfg_set_string(cfg, name, val);
613       if (errcode != no_error) {
614          xbt_free(optionlist_cpy);
615          return errcode;
616       }
617       break;
618
619     case xbt_cfgelm_int:
620       i=strtol(val, &val, 0);
621       if (val==NULL) {
622         xbt_free(optionlist_cpy);       
623         xbt_assert1(FALSE,
624                      "Value of option %s not valid. Should be an integer",
625                      name);
626       }
627
628       errcode = xbt_cfg_set_int(cfg,name,i);
629       if (errcode != no_error) {
630          xbt_free(optionlist_cpy);
631          return errcode;
632       }
633       break;
634
635     case xbt_cfgelm_double:
636       d=strtod(val, &val);
637       if (val==NULL) {
638         xbt_free(optionlist_cpy);       
639         xbt_assert1(FALSE,
640                "Value of option %s not valid. Should be a double",
641                name);
642       }
643
644       errcode = xbt_cfg_set_double(cfg,name,d);
645       if (errcode != no_error) {
646          xbt_free(optionlist_cpy);
647          return errcode;
648       }
649       break;
650
651     case xbt_cfgelm_host:
652       str=val;
653       val=strchr(val,':');
654       if (!val) {
655         xbt_free(optionlist_cpy);       
656         xbt_assert1(FALSE,
657                "Value of option %s not valid. Should be an host (machine:port)",
658                name);
659       }
660
661       *(val++)='\0';
662       i=strtol(val, &val, 0);
663       if (val==NULL) {
664         xbt_free(optionlist_cpy);       
665         xbt_assert1(FALSE,
666                "Value of option %s not valid. Should be an host (machine:port)",
667                name);
668       }
669
670       errcode = xbt_cfg_set_host(cfg,name,str,i);
671       if (errcode != no_error) {
672          xbt_free(optionlist_cpy);
673          return errcode;
674       }
675       break;      
676
677     default: 
678       xbt_free(optionlist_cpy);
679       RAISE1(unknown_error,"Type of config element %s is not valid.",name);
680     }
681     
682   }
683   xbt_free(optionlist_cpy);
684   return no_error;
685 }
686
687 /**
688  * xbt_cfg_set_int:
689  *
690  * \arg cfg the config set
691  * \arg name the name of the cell
692  * \arg val the value of the cell
693  *
694  * Set the value of the cell #name in #cfg with the provided value.
695  */ 
696 xbt_error_t
697 xbt_cfg_set_int(xbt_cfg_t cfg,const char*name, int val) {
698   xbt_cfgelm_t cell;
699   xbt_error_t errcode;
700
701   VERB2("Configuration setting: %s=%d",name,val);
702   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_int,&cell));
703
704   if (cell->max > 1) {
705     xbt_dynar_push(cell->content,&val);
706   } else {
707     xbt_dynar_set(cell->content,0,&val);
708   }
709   return no_error;
710 }
711
712 /**
713  * xbt_cfg_set_double:
714  * \arg cfg the config set
715  * \arg name the name of the cell
716  * \arg val the doule to set
717  * 
718  * Set the value of the cell #name in #cfg with the provided value.
719  */ 
720
721 xbt_error_t
722 xbt_cfg_set_double(xbt_cfg_t cfg,const char*name, double val) {
723   xbt_cfgelm_t cell;
724   xbt_error_t errcode;
725
726   VERB2("Configuration setting: %s=%f",name,val);
727   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_double,&cell));
728
729   if (cell->max > 1) {
730     xbt_dynar_push(cell->content,&val);
731   } else {
732     xbt_dynar_set(cell->content,0,&val);
733   }
734   return no_error;
735 }
736
737 /**
738  * xbt_cfg_set_string:
739  * 
740  * \arg cfg the config set
741  * \arg name the name of the cell
742  * \arg val the value to be added
743  *
744  * Set the value of the cell #name in #cfg with the provided value.
745  */ 
746
747 xbt_error_t
748 xbt_cfg_set_string(xbt_cfg_t cfg,const char*name, const char*val) { 
749   xbt_cfgelm_t cell;
750   xbt_error_t errcode;
751   char *newval = xbt_strdup(val);
752
753   VERB2("Configuration setting: %s=%s",name,val);
754   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_string,&cell));
755
756   if (cell->max > 1) {
757     xbt_dynar_push(cell->content,&newval);
758   } else {
759     xbt_dynar_set(cell->content,0,&newval);
760   }
761   return no_error;
762 }
763
764 /**
765  * xbt_cfg_set_host:
766  * 
767  * \arg cfg the config set
768  * \arg name the name of the cell
769  * \arg host the host
770  * \arg port the port number
771  *
772  * Set the value of the cell #name in #cfg with the provided value 
773  * on the given #host to the given #port
774  */ 
775
776 xbt_error_t 
777 xbt_cfg_set_host(xbt_cfg_t cfg,const char*name, 
778                   const char *host,int port) {
779   xbt_cfgelm_t cell;
780   xbt_error_t errcode;
781   xbt_host_t *val=xbt_new(xbt_host_t,1);
782
783   VERB3("Configuration setting: %s=%s:%d",name,host,port);
784
785   val->name = xbt_strdup(name);
786   val->port = port;
787
788   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_host,&cell));
789
790   if (cell->max > 1) {
791     xbt_dynar_push(cell->content,&val);
792   } else {
793     xbt_dynar_set(cell->content,0,&val);
794   }
795   return no_error;
796 }
797
798 /* ---- [ Removing ] ---- */
799
800 /**
801  * xbt_cfg_rm_int:
802  *
803  * \arg cfg the config set
804  * \arg name the name of the cell
805  * \arg val the value to be removed
806  *
807  * Remove the provided #val from the cell #name in #cfg.
808  */
809 xbt_error_t xbt_cfg_rm_int(xbt_cfg_t cfg,const char*name, int val) {
810
811   xbt_cfgelm_t cell;
812   int cpt,seen;
813   xbt_error_t errcode;
814
815   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_int,&cell));
816   
817   xbt_dynar_foreach(cell->content,cpt,seen) {
818     if (seen == val) {
819       xbt_dynar_cursor_rm(cell->content,&cpt);
820       return no_error;
821     }
822   }
823
824   ERROR2("Can't remove the value %d of config element %s: value not found.",
825          val,name);
826   return mismatch_error;
827 }
828
829 /**
830  * xbt_cfg_rm_double:
831  *
832  * \arg cfg the config set
833  * \arg name the name of the cell
834  * \arg val the value to be removed
835  *
836  * Remove the provided #val from the cell #name in #cfg.
837  */
838
839 xbt_error_t xbt_cfg_rm_double(xbt_cfg_t cfg,const char*name, double val) {
840   xbt_cfgelm_t cell;
841   int cpt;
842   double seen;
843   xbt_error_t errcode;
844
845   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_double,&cell));
846   
847   xbt_dynar_foreach(cell->content,cpt,seen) {
848     if (seen == val) {
849       xbt_dynar_cursor_rm(cell->content,&cpt);
850       return no_error;
851     }
852   }
853
854   ERROR2("Can't remove the value %f of config element %s: value not found.",
855          val,name);
856   return mismatch_error;
857 }
858
859 /**
860  * xbt_cfg_rm_string:
861  *
862  * \arg cfg the config set
863  * \arg name the name of the cell
864  * \arg val the value of the string which will be removed
865  *
866  * Remove the provided #val from the cell #name in #cfg.
867  */
868 xbt_error_t
869 xbt_cfg_rm_string(xbt_cfg_t cfg,const char*name, const char *val) {
870   xbt_cfgelm_t cell;
871   int cpt;
872   char *seen;
873   xbt_error_t errcode;
874
875   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_string,&cell));
876   
877   xbt_dynar_foreach(cell->content,cpt,seen) {
878     if (!strcpy(seen,val)) {
879       xbt_dynar_cursor_rm(cell->content,&cpt);
880       return no_error;
881     }
882   }
883
884   ERROR2("Can't remove the value %s of config element %s: value not found.",
885          val,name);
886   return mismatch_error;
887 }
888
889 /**
890  * xbt_cfg_rm_host:
891  * 
892  * \arg cfg the config set
893  * \arg name the name of the cell
894  * \arg host the hostname
895  * \arg port the port number
896  *
897  * Remove the provided #host:#port from the cell #name in #cfg.
898  */
899
900 xbt_error_t
901 xbt_cfg_rm_host(xbt_cfg_t cfg,const char*name, const char *host,int port) {
902   xbt_cfgelm_t cell;
903   int cpt;
904   xbt_host_t *seen;
905   xbt_error_t errcode;
906
907   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_host,&cell));
908   
909   xbt_dynar_foreach(cell->content,cpt,seen) {
910     if (!strcpy(seen->name,host) && seen->port == port) {
911       xbt_dynar_cursor_rm(cell->content,&cpt);
912       return no_error;
913     }
914   }
915
916   ERROR3("Can't remove the value %s:%d of config element %s: value not found.",
917          host,port,name);
918   return mismatch_error;
919 }
920
921 /* rm everything */
922
923 /**
924  * xbt_cfg_empty:
925  * 
926  * \arg cfg the config set
927  * \arg name the name of the cell
928  *
929  * rm evenything
930  */
931
932 xbt_error_t 
933 xbt_cfg_empty(xbt_cfg_t cfg,const char*name) {
934   xbt_cfgelm_t cell;
935
936   xbt_error_t errcode;
937
938   TRYCATCH(mismatch_error,
939            xbt_dict_get((xbt_dict_t)cfg,name,(void**)&cell));
940   if (errcode == mismatch_error) {
941     ERROR1("Can't empty  '%s' since this config element does not exist",
942            name);
943     return mismatch_error;
944   }
945
946   if (cell) {
947     xbt_dynar_reset(cell->content);
948   }
949   return no_error;
950 }
951
952 /*----[ Getting ]---------------------------------------------------------*/
953
954 /**
955  * xbt_cfg_get_int:
956  * \arg cfg the config set
957  * \arg name the name of the cell
958  * \arg val the wanted value
959  *
960  * Returns the first value from the config set under the given name.
961  * If there is more than one value, it will issue a warning. Consider using xbt_cfg_get_dynar() 
962  * instead.
963  *
964  * \warning the returned value is the actual content of the config set
965  */
966 xbt_error_t
967 xbt_cfg_get_int   (xbt_cfg_t  cfg,
968                     const char *name,
969                     int        *val) {
970   xbt_cfgelm_t cell;
971   xbt_error_t errcode;
972
973   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_int,&cell));
974
975   if (xbt_dynar_length(cell->content) > 1) {
976     WARN2("You asked for the first value of the config element '%s', but there is %lu values",
977              name, xbt_dynar_length(cell->content));
978   }
979
980   *val = xbt_dynar_get_as(cell->content, 0, int);
981   return no_error;
982 }
983
984 /**
985  * xbt_cfg_get_double:
986  * \arg cfg the config set
987  * \arg name the name of the cell
988  * \arg val the wanted value
989  *
990  * Returns the first value from the config set under the given name.
991  * If there is more than one value, it will issue a warning. Consider using xbt_cfg_get_dynar() 
992  * instead.
993  *
994  * \warning the returned value is the actual content of the config set
995  */
996
997 xbt_error_t
998 xbt_cfg_get_double(xbt_cfg_t  cfg,
999                     const char *name,
1000                     double     *val) {
1001   xbt_cfgelm_t cell;
1002   xbt_error_t  errcode;
1003
1004   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_double,&cell));
1005
1006   if (xbt_dynar_length(cell->content) > 1) {
1007     WARN2("You asked for the first value of the config element '%s', but there is %lu values\n",
1008              name, xbt_dynar_length(cell->content));
1009   }
1010
1011   *val = xbt_dynar_get_as(cell->content, 0, double);
1012   return no_error;
1013 }
1014
1015 /**
1016  * xbt_cfg_get_string:
1017  *
1018  * \arg th the config set
1019  * \arg name the name of the cell
1020  * \arg val the wanted value
1021  *
1022  * Returns the first value from the config set under the given name.
1023  * If there is more than one value, it will issue a warning. Consider using xbt_cfg_get_dynar() 
1024  * instead.
1025  *
1026  * \warning the returned value is the actual content of the config set
1027  */
1028
1029 xbt_error_t xbt_cfg_get_string(xbt_cfg_t  cfg,
1030                                  const char *name,
1031                                  char      **val) {
1032   xbt_cfgelm_t  cell;
1033   xbt_error_t errcode;
1034
1035   *val=NULL;
1036
1037   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_string,&cell));
1038
1039   if (xbt_dynar_length(cell->content) > 1) {
1040     WARN2("You asked for the first value of the config element '%s', but there is %lu values\n",
1041              name, xbt_dynar_length(cell->content));
1042   }
1043
1044   *val = xbt_dynar_get_as(cell->content, 0, char *);
1045   return no_error;
1046 }
1047
1048 /**
1049  * xbt_cfg_get_host:
1050  *
1051  * \arg cfg the config set
1052  * \arg name the name of the cell
1053  * \arg host the host
1054  * \arg port the port number
1055  *
1056  * Returns the first value from the config set under the given name.
1057  * If there is more than one value, it will issue a warning. Consider using xbt_cfg_get_dynar() 
1058  * instead.
1059  *
1060  * \warning the returned value is the actual content of the config set
1061  */
1062
1063 xbt_error_t xbt_cfg_get_host  (xbt_cfg_t  cfg,
1064                                  const char *name,
1065                                  char      **host,
1066                                  int        *port) {
1067   xbt_cfgelm_t cell;
1068   xbt_error_t  errcode;
1069   xbt_host_t  *val;
1070
1071   TRY (xbt_cfgelm_get(cfg,name,xbt_cfgelm_host,&cell));
1072
1073   if (xbt_dynar_length(cell->content) > 1) {
1074     WARN2("You asked for the first value of the config element '%s', but there is %lu values\n",
1075              name, xbt_dynar_length(cell->content));
1076   }
1077
1078   val = xbt_dynar_get_as(cell->content, 0, xbt_host_t*);
1079   *host=val->name;
1080   *port=val->port;
1081   
1082   return no_error;
1083 }
1084
1085 /**
1086  * xbt_cfg_get_dynar:
1087  * \arg cfg where to search in
1088  * \arg name what to search for
1089  * \arg dynar result
1090  *
1091  * Get the data stored in the config bag. 
1092  *
1093  * \warning the returned value is the actual content of the config set
1094  */
1095 xbt_error_t xbt_cfg_get_dynar (xbt_cfg_t    cfg,
1096                                  const char   *name,
1097                                  xbt_dynar_t *dynar) {
1098   xbt_cfgelm_t cell;
1099   xbt_error_t  errcode = xbt_dict_get((xbt_dict_t)cfg,name,
1100                                         (void**)&cell);
1101
1102   if (errcode == mismatch_error) {
1103     ERROR1("No registered cell %s in this config set",
1104            name);
1105     return mismatch_error;
1106   }
1107   if (errcode != no_error)
1108      return errcode;
1109
1110   *dynar = cell->content;
1111   return no_error;
1112 }
1113