Logo AND Algorithmique Numérique Distribuée

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