Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add unit support in xml files [#14422]
[simgrid.git] / src / surf / surfxml_parse.c
1 /* Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include <stdarg.h> /* va_arg */
8
9 #include "xbt/misc.h"
10 #include "xbt/log.h"
11 #include "xbt/str.h"
12 #include "xbt/dict.h"
13 #include "surf/surfxml_parse.h"
14 #include "surf/surf_private.h"
15 #include "simgrid/sg_config.h"
16
17 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_parse, surf,
18                                 "Logging specific to the SURF parsing module");
19 #undef CLEANUP
20 int ETag_surfxml_include_state(void);
21
22 #include "simgrid_dtd.c"
23
24 char* surf_parsed_filename = NULL; // to locate parse error messages
25
26 xbt_dynar_t parsed_link_list = NULL;   /* temporary store of current list link of a route */
27 extern AS_t current_routing;
28 /*
29  * Helping functions
30  */
31 void surf_parse_error(const char *fmt, ...) {
32   va_list va;
33   va_start(va,fmt);
34   char *msg = bvprintf(fmt,va);
35   va_end(va);
36   xbt_die("Parse error at %s:%d: %s", surf_parsed_filename, surf_parse_lineno, msg);
37 }
38 void surf_parse_warn(const char *fmt, ...) {
39   va_list va;
40   va_start(va,fmt);
41   char *msg = bvprintf(fmt,va);
42   va_end(va);
43     XBT_WARN("%s:%d: %s", surf_parsed_filename, surf_parse_lineno, msg);
44     free(msg);
45 }
46
47 double surf_parse_get_double(const char *string) {
48   double res;
49   int ret = sscanf(string, "%lg", &res);
50   if (ret != 1)
51     surf_parse_error("%s is not a double", string);
52   //printf("Parsed double [%lg] %s\n", res, string);  
53   return res;
54 }
55
56 int surf_parse_get_int(const char *string) {
57   int res;
58   int ret = sscanf(string, "%d", &res);
59   if (ret != 1)
60     surf_parse_error("%s is not an integer", string);
61   return res;
62 }
63
64 double surf_parse_get_time(const char *string) {
65   size_t len = strlen(string);
66   char* tmp = xbt_malloc(sizeof(char) * (len + 1));
67   strcpy(tmp, string);
68   if (!strcmp(tmp + len - 2, "ps")) {
69     tmp[len-2] = 0;
70     return surf_parse_get_double(tmp) * 1E-12;
71   }
72   if (!strcmp(tmp + len - 2, "ns")) {
73     tmp[len-2] = 0;
74     return surf_parse_get_double(tmp) * 1E-9;
75   }
76   if (!strcmp(tmp + len - 2, "us")) {
77     tmp[len-2] = 0;
78     return surf_parse_get_double(tmp) * 1E-6;
79   }
80   if (!strcmp(tmp + len - 2, "ms")) {
81     tmp[len-2] = 0;
82     return surf_parse_get_double(tmp) * 1E-3;
83   }
84   if (!strcmp(tmp + len - 1, "s")) {
85     tmp[len-1] = 0;    
86     return surf_parse_get_double(tmp);
87   }
88   if (!strcmp(tmp + len - 1, "m")) {
89     tmp[len-1] = 0;    
90     return surf_parse_get_double(tmp) * 60;
91   }
92   if (!strcmp(tmp + len - 1, "h")) {
93     tmp[len-1] = 0;    
94     return surf_parse_get_double(tmp) * 3600;
95   }
96   if (!strcmp(tmp + len - 1, "d")) {
97     tmp[len-1] = 0;    
98     return surf_parse_get_double(tmp) * 86400;
99   }
100   if (!strcmp(tmp + len - 1, "w")) {
101     tmp[len-1] = 0;    
102     return surf_parse_get_double(tmp) * 604800;
103   }
104   return surf_parse_get_double(tmp);
105 }
106
107 double surf_parse_get_bandwidth(const char *string) {
108   size_t len = strlen(string);
109   char* tmp = xbt_malloc(sizeof(char) * (len + 1));
110   strcpy(tmp, string);
111   if (!strcmp(tmp + len - 4, "KBps")) {
112     tmp[len-4] = 0;
113     return surf_parse_get_double(tmp) * 1E3;
114   }
115   if (!strcmp(tmp + len - 4, "MBps")) {
116     tmp[len-4] = 0;
117     return surf_parse_get_double(tmp) * 1E6;
118   }
119   if (!strcmp(tmp + len - 4, "GBps")) {
120     tmp[len-4] = 0;
121     return surf_parse_get_double(tmp) * 1E9;
122   }
123   if (!strcmp(tmp + len - 4, "TBps")) {
124     tmp[len-4] = 0;
125     return surf_parse_get_double(tmp) * 1E12;
126   }
127   if (!strcmp(tmp + len - 3, "Bps")) {
128     tmp[len-3] = 0;
129     return surf_parse_get_double(tmp);
130   }
131   if (!strcmp(tmp + len - 4, "kbps")) {
132     tmp[len-4] = 0;
133     return surf_parse_get_double(tmp) * 0.125 * 1E3;
134   }
135   if (!strcmp(tmp + len - 4, "mbps")) {
136     tmp[len-4] = 0;
137     return surf_parse_get_double(tmp) * 0.125 * 1E6;
138   }
139   if (!strcmp(tmp + len - 4, "gbps")) {
140     tmp[len-4] = 0;
141     return surf_parse_get_double(tmp) * 0.125 * 1E9;
142   }
143   if (!strcmp(tmp + len - 4, "tbps")) {
144     tmp[len-4] = 0;
145     return surf_parse_get_double(tmp) * 0.125 * 1E12;
146   }
147   if (!strcmp(tmp + len - 3, "bps")) {
148     tmp[len-3] = 0;
149     return surf_parse_get_double(tmp) * 0.125;
150   }
151   return surf_parse_get_double(tmp);
152 }
153
154 double surf_parse_get_power(const char *string) {
155   size_t len = strlen(string);
156   char* tmp = xbt_malloc(sizeof(char) * (len + 1));
157   strcpy(tmp, string);
158   if (!strcmp(tmp + len - 9, "kiloflops")) {
159     tmp[len-9] = 0;
160     return surf_parse_get_double(tmp) * 1E3;
161   }
162   if (!strcmp(tmp + len - 9, "megaflops")) {
163     tmp[len-9] = 0;
164     return surf_parse_get_double(tmp) * 1E6;
165   }
166   if (!strcmp(tmp + len - 9, "gigaflops")) {
167     tmp[len-9] = 0;
168     return surf_parse_get_double(tmp) * 1E9;
169   }
170   if (!strcmp(tmp + len - 9, "teraflops")) {
171     tmp[len-9] = 0;
172     return surf_parse_get_double(tmp) * 1E12;
173   }
174   if (!strcmp(tmp + len - 9, "petaflops")) {
175     tmp[len-9] = 0;
176     return surf_parse_get_double(tmp) * 1E15;
177   }
178   if (!strcmp(tmp + len - 9, "exaflops")) {
179     tmp[len-9] = 0;
180     return surf_parse_get_double(tmp) * 1E18;
181   }
182   if (!strcmp(tmp + len - 9, "zettaflops")) {
183     tmp[len-9] = 0;
184     return surf_parse_get_double(tmp) * 1E21;
185   }
186   if (!strcmp(tmp + len - 9, "yottaflops")) {
187     tmp[len-9] = 0;
188     return surf_parse_get_double(tmp) * 1E24;
189   }
190   if (!strcmp(tmp + len - 5, "flops")) {
191     tmp[len-5] = 0;
192     return surf_parse_get_double(tmp);
193   }
194   if (!strcmp(tmp + len - 2, "kf")) {
195     tmp[len-2] = 0;
196     return surf_parse_get_double(tmp) * 1E3;
197   }
198   if (!strcmp(tmp + len - 2, "mf")) {
199     tmp[len-2] = 0;
200     return surf_parse_get_double(tmp) * 1E6;
201   }
202   if (!strcmp(tmp + len - 2, "gf")) {
203     tmp[len-2] = 0;
204     return surf_parse_get_double(tmp) * 1E9;
205   }
206   if (!strcmp(tmp + len - 2, "tf")) {
207     tmp[len-2] = 0;
208     return surf_parse_get_double(tmp) * 1E12;
209   }
210   if (!strcmp(tmp + len - 2, "pf")) {
211     tmp[len-2] = 0;
212     return surf_parse_get_double(tmp) * 1E15;
213   }
214   if (!strcmp(tmp + len - 2, "ef")) {
215     tmp[len-2] = 0;
216     return surf_parse_get_double(tmp) * 1E18;
217   }
218   if (!strcmp(tmp + len - 2, "zf")) {
219     tmp[len-2] = 0;
220     return surf_parse_get_double(tmp) * 1E21;
221   }
222   if (!strcmp(tmp + len - 2, "yf")) {
223     tmp[len-2] = 0;
224     return surf_parse_get_double(tmp) * 1E24;
225   }
226   if (!strcmp(tmp + len - 1, "f")) {
227     tmp[len-1] = 0;
228     return surf_parse_get_double(tmp);
229   }
230   return surf_parse_get_double(tmp);
231 }
232
233 /*
234  * All the callback lists that can be overridden anywhere.
235  * (this list should probably be reduced to the bare minimum to allow the models to work)
236  */
237
238 /* make sure these symbols are defined as strong ones in this file so that the linker can resolve them */
239
240 /* The default current property receiver. Setup in the corresponding opening callbacks. */
241 xbt_dict_t current_property_set = NULL;
242 xbt_dict_t as_current_property_set = NULL;
243 int AS_TAG = 0;
244 char* as_name_tab[1024];
245 void* as_dict_tab[1024];
246 int as_prop_nb = 0;
247
248
249 /* dictionary of random generator data */
250 xbt_dict_t random_data_list = NULL;
251
252 YY_BUFFER_STATE surf_input_buffer;
253 FILE *surf_file_to_parse = NULL;
254
255 static void init_randomness(void);
256 static void add_randomness(void);
257
258 /*
259  * Stuff relative to storage
260  */
261 void STag_surfxml_storage(void)
262 {
263   AS_TAG = 0;
264   XBT_DEBUG("STag_surfxml_storage");
265   xbt_assert(current_property_set == NULL, "Someone forgot to reset the property set to NULL in its closing tag (or XML malformed)");
266 }
267 void ETag_surfxml_storage(void)
268 {
269   s_sg_platf_storage_cbarg_t storage;
270   memset(&storage,0,sizeof(storage));
271
272   storage.id = A_surfxml_storage_id;
273   storage.type_id = A_surfxml_storage_typeId;
274   storage.content = A_surfxml_storage_content;
275   storage.properties = current_property_set;
276   sg_platf_new_storage(&storage);
277   current_property_set = NULL;
278 }
279 void STag_surfxml_storage___type(void)
280 {
281   AS_TAG = 0;
282   XBT_DEBUG("STag_surfxml_storage___type");
283   xbt_assert(current_property_set == NULL, "Someone forgot to reset the property set to NULL in its closing tag (or XML malformed)");
284 }
285 void ETag_surfxml_storage___type(void)
286 {
287   s_sg_platf_storage_type_cbarg_t storage_type;
288   memset(&storage_type,0,sizeof(storage_type));
289
290   storage_type.content = A_surfxml_storage___type_content;
291   storage_type.id = A_surfxml_storage___type_id;
292   storage_type.model = A_surfxml_storage___type_model;
293   storage_type.properties = current_property_set;
294   storage_type.size = surf_parse_get_int(A_surfxml_storage___type_size);
295   sg_platf_new_storage_type(&storage_type);
296   current_property_set = NULL;
297 }
298 void STag_surfxml_mstorage(void)
299 {
300   XBT_DEBUG("STag_surfxml_mstorage");
301 }
302 void ETag_surfxml_mstorage(void)
303 {
304   s_sg_platf_mstorage_cbarg_t mstorage;
305   memset(&mstorage,0,sizeof(mstorage));
306
307   mstorage.name = A_surfxml_mstorage_name;
308   mstorage.type_id = A_surfxml_mstorage_typeId;
309   sg_platf_new_mstorage(&mstorage);
310 }
311 void STag_surfxml_mount(void)
312 {
313   XBT_DEBUG("STag_surfxml_mount");
314 }
315 void ETag_surfxml_mount(void)
316 {
317   s_sg_platf_mount_cbarg_t mount;
318   memset(&mount,0,sizeof(mount));
319
320   mount.name = A_surfxml_mount_name;
321   mount.id = A_surfxml_mount_id;
322   sg_platf_new_mount(&mount);
323 }
324
325 /*
326  * Stuff relative to the <include> tag
327  */
328 static xbt_dynar_t surf_input_buffer_stack = NULL;
329 static xbt_dynar_t surf_file_to_parse_stack = NULL;
330 static xbt_dynar_t surf_parsed_filename_stack = NULL;
331
332 void STag_surfxml_include(void)
333 {
334   XBT_DEBUG("STag_surfxml_include '%s'",A_surfxml_include_file);
335   xbt_dynar_push(surf_parsed_filename_stack,&surf_parsed_filename); // save old file name
336   surf_parsed_filename = xbt_strdup(A_surfxml_include_file);
337
338   xbt_dynar_push(surf_file_to_parse_stack, &surf_file_to_parse); //save old file descriptor
339
340   surf_file_to_parse = surf_fopen(A_surfxml_include_file, "r"); // read new file descriptor
341   xbt_assert((surf_file_to_parse), "Unable to open \"%s\"\n",
342               A_surfxml_include_file);
343   xbt_dynar_push(surf_input_buffer_stack,&surf_input_buffer);
344   surf_input_buffer = surf_parse__create_buffer(surf_file_to_parse, YY_BUF_SIZE);
345   surf_parse_push_buffer_state(surf_input_buffer);
346
347   fflush(NULL);
348 }
349
350 void ETag_surfxml_include(void) {
351 /* Nothing to do when done with reading the include tag.
352  * Instead, the handling should be deferred until the EOF of current buffer -- see below */
353 }
354
355 /** @brief When reaching EOF, check whether we are in an include tag, and behave accordingly if yes
356  *
357  * This function is called automatically by sedding the parser in buildtools/Cmake/MaintainerMode.cmake
358  * Every FAIL on "Premature EOF" is preceded by a call to this function, which role is to restore the
359  * previous buffer if we reached the EOF /of an include file/. Its return code is used to avoid the
360  * error message in that case.
361  *
362  * Yeah, that's terribly hackish, but it works. A better solution should be dealed with in flexml
363  * directly: a command line flag could instruct it to do the correct thing when #include is encountered
364  * on a line. One day maybe, if the maya allow it.
365  */
366 int ETag_surfxml_include_state(void)
367 {
368   fflush(NULL);
369   XBT_DEBUG("ETag_surfxml_include_state '%s'",A_surfxml_include_file);
370
371   if(xbt_dynar_is_empty(surf_input_buffer_stack)) // nope, that's a true premature EOF. Let the parser die verbosely.
372     return 0;
373
374   // Yeah, we were in an <include> Restore state and proceed.
375   fclose(surf_file_to_parse);
376   xbt_dynar_pop(surf_file_to_parse_stack, &surf_file_to_parse);
377   surf_parse_pop_buffer_state();
378   xbt_dynar_pop(surf_input_buffer_stack,&surf_input_buffer);
379
380   // Restore the filename for error messages
381   free(surf_parsed_filename);
382   xbt_dynar_pop(surf_parsed_filename_stack,&surf_parsed_filename);
383
384   return 1;
385 }
386
387
388 void surf_parse_init_callbacks(void)
389 {
390     sg_platf_init();
391 }
392
393 void surf_parse_reset_callbacks(void)
394 {
395   surf_parse_free_callbacks();
396   surf_parse_init_callbacks();
397 }
398
399 void surf_parse_free_callbacks(void)
400 {
401   sg_platf_exit();
402 }
403
404 /* Stag and Etag parse functions */
405
406 void STag_surfxml_platform(void) {
407   _XBT_GNUC_UNUSED double version = surf_parse_get_double(A_surfxml_platform_version);
408
409   xbt_assert((version >= 1.0), "******* BIG FAT WARNING *********\n "
410       "You're using an ancient XML file.\n"
411       "Since SimGrid 3.1, units are Bytes, Flops, and seconds "
412       "instead of MBytes, MFlops and seconds.\n"
413
414       "Use simgrid_update_xml to update your file automatically. "
415       "This program is installed automatically with SimGrid, or "
416       "available in the tools/ directory of the source archive.\n"
417
418       "Please check also out the SURF section of the ChangeLog for "
419       "the 3.1 version for more information. \n"
420
421       "Last, do not forget to also update your values for "
422       "the calls to MSG_task_create (if any).");
423   xbt_assert((version >= 3.0), "******* BIG FAT WARNING *********\n "
424       "You're using an old XML file.\n"
425       "Use simgrid_update_xml to update your file automatically. "
426       "This program is installed automatically with SimGrid, or "
427       "available in the tools/ directory of the source archive.");
428
429   sg_platf_begin();
430 }
431 void ETag_surfxml_platform(void){
432   sg_platf_end();
433 }
434
435 void STag_surfxml_host(void){
436   AS_TAG = 0;
437   xbt_assert(current_property_set == NULL, "Someone forgot to reset the property set to NULL in its closing tag (or XML malformed)");
438 }
439
440 void STag_surfxml_prop(void)
441 {
442   if(AS_TAG){
443     if (!as_current_property_set){
444       xbt_assert(as_prop_nb < 1024, "Number of AS property reach the limit!!!");
445       as_current_property_set = xbt_dict_new_homogeneous(xbt_free_f); // Maybe, it should raise an error
446       as_name_tab[as_prop_nb] = xbt_strdup(A_surfxml_AS_id);
447       as_dict_tab[as_prop_nb] = as_current_property_set;
448       XBT_DEBUG("PUSH prop %p for AS '%s'",as_dict_tab[as_prop_nb],as_name_tab[as_prop_nb]);
449       as_prop_nb++;
450     }
451     xbt_dict_set(as_current_property_set, A_surfxml_prop_id, xbt_strdup(A_surfxml_prop_value), NULL);
452   }
453   else{
454     if (!current_property_set)
455       current_property_set = xbt_dict_new_homogeneous(xbt_free_f); // Maybe, it should raise an error
456     xbt_dict_set(current_property_set, A_surfxml_prop_id, xbt_strdup(A_surfxml_prop_value), NULL);
457   }
458 }
459
460 void ETag_surfxml_host(void)    {
461   s_sg_platf_host_cbarg_t host;
462   memset(&host,0,sizeof(host));
463
464   host.properties = current_property_set;
465
466   host.id = A_surfxml_host_id;
467   host.power_peak = get_cpu_power(A_surfxml_host_power);
468   host.power_scale = surf_parse_get_double( A_surfxml_host_availability);
469   host.core_amount = surf_parse_get_int(A_surfxml_host_core);
470   host.power_trace = tmgr_trace_new_from_file(A_surfxml_host_availability___file);
471   host.state_trace = tmgr_trace_new_from_file(A_surfxml_host_state___file);
472   xbt_assert((A_surfxml_host_state == A_surfxml_host_state_ON) ||
473         (A_surfxml_host_state == A_surfxml_host_state_OFF), "Invalid state");
474   if (A_surfxml_host_state == A_surfxml_host_state_ON)
475     host.initial_state = SURF_RESOURCE_ON;
476   if (A_surfxml_host_state == A_surfxml_host_state_OFF)
477     host.initial_state = SURF_RESOURCE_OFF;
478   host.coord = A_surfxml_host_coordinates;
479
480   sg_platf_new_host(&host);
481   current_property_set = NULL;
482 }
483
484 void STag_surfxml_host___link(void){
485   XBT_DEBUG("Create a Host_link for %s",A_surfxml_host___link_id);
486   s_sg_platf_host_link_cbarg_t host_link;
487   memset(&host_link,0,sizeof(host_link));
488
489   host_link.id = A_surfxml_host___link_id;
490   host_link.link_up = A_surfxml_host___link_up;
491   host_link.link_down = A_surfxml_host___link_down;
492   sg_platf_new_host_link(&host_link);
493 }
494
495 void STag_surfxml_router(void){
496   s_sg_platf_router_cbarg_t router;
497   memset(&router, 0, sizeof(router));
498
499   router.id = A_surfxml_router_id;
500   router.coord = A_surfxml_router_coordinates;
501
502   sg_platf_new_router(&router);
503 }
504
505 void STag_surfxml_cluster(void){
506   s_sg_platf_cluster_cbarg_t cluster;
507   memset(&cluster,0,sizeof(cluster));
508   cluster.id = A_surfxml_cluster_id;
509   cluster.prefix = A_surfxml_cluster_prefix;
510   cluster.suffix = A_surfxml_cluster_suffix;
511   cluster.radical = A_surfxml_cluster_radical;
512   cluster.power = surf_parse_get_power(A_surfxml_cluster_power);
513   cluster.core_amount = surf_parse_get_int(A_surfxml_cluster_core);
514   cluster.bw =   surf_parse_get_bandwidth(A_surfxml_cluster_bw);
515   cluster.lat =  surf_parse_get_time(A_surfxml_cluster_lat);
516   if(strcmp(A_surfxml_cluster_bb___bw,""))
517     cluster.bb_bw = surf_parse_get_bandwidth(A_surfxml_cluster_bb___bw);
518   if(strcmp(A_surfxml_cluster_bb___lat,""))
519     cluster.bb_lat = surf_parse_get_time(A_surfxml_cluster_bb___lat);
520   if(strcmp(A_surfxml_cluster_limiter___link,""))
521     cluster.limiter_link = surf_parse_get_double(A_surfxml_cluster_limiter___link);
522   if(strcmp(A_surfxml_cluster_loopback___bw,""))
523     cluster.loopback_bw = surf_parse_get_bandwidth(A_surfxml_cluster_loopback___bw);
524   if(strcmp(A_surfxml_cluster_loopback___lat,""))
525     cluster.loopback_lat = surf_parse_get_time(A_surfxml_cluster_loopback___lat);
526   cluster.router_id = A_surfxml_cluster_router___id;
527
528   switch (AX_surfxml_cluster_sharing___policy) {
529   case A_surfxml_cluster_sharing___policy_SHARED:
530     cluster.sharing_policy = SURF_LINK_SHARED;
531     break;
532   case A_surfxml_cluster_sharing___policy_FULLDUPLEX:
533     cluster.sharing_policy = SURF_LINK_FULLDUPLEX;
534     break;
535   case A_surfxml_cluster_sharing___policy_FATPIPE:
536     cluster.sharing_policy = SURF_LINK_FATPIPE;
537     break;
538   default:
539     surf_parse_error("Invalid cluster sharing policy for cluster %s",
540                      cluster.id);
541     break;
542   }
543   switch (AX_surfxml_cluster_bb___sharing___policy) {
544   case A_surfxml_cluster_bb___sharing___policy_FATPIPE:
545     cluster.bb_sharing_policy = SURF_LINK_FATPIPE;
546     break;
547   case A_surfxml_cluster_bb___sharing___policy_SHARED:
548     cluster.bb_sharing_policy = SURF_LINK_SHARED;
549     break;
550   default:
551     surf_parse_error("Invalid bb sharing policy in cluster %s",
552                      cluster.id);
553     break;
554   }
555
556   cluster.availability_trace = A_surfxml_cluster_availability___file;
557   cluster.state_trace = A_surfxml_cluster_state___file;
558   sg_platf_new_cluster(&cluster);
559 }
560
561 void STag_surfxml_cabinet(void){
562   s_sg_platf_cabinet_cbarg_t cabinet;
563   memset(&cabinet,0,sizeof(cabinet));
564   cabinet.id = A_surfxml_cabinet_id;
565   cabinet.prefix = A_surfxml_cabinet_prefix;
566   cabinet.suffix = A_surfxml_cabinet_suffix;
567   cabinet.power = surf_parse_get_power(A_surfxml_cabinet_power);
568   cabinet.bw = surf_parse_get_bandwidth(A_surfxml_cabinet_bw);
569   cabinet.lat = surf_parse_get_time(A_surfxml_cabinet_lat);
570   cabinet.radical = A_surfxml_cabinet_radical;
571
572   sg_platf_new_cabinet(&cabinet);
573 }
574
575 void STag_surfxml_peer(void){
576   s_sg_platf_peer_cbarg_t peer;
577   memset(&peer,0,sizeof(peer));
578   peer.id = A_surfxml_peer_id;
579   peer.power = surf_parse_get_power(A_surfxml_peer_power);
580   peer.bw_in = surf_parse_get_bandwidth(A_surfxml_peer_bw___in);
581   peer.bw_out = surf_parse_get_bandwidth(A_surfxml_peer_bw___out);
582   peer.lat = surf_parse_get_time(A_surfxml_peer_lat);
583   peer.coord = A_surfxml_peer_coordinates;
584   peer.availability_trace = tmgr_trace_new_from_file(A_surfxml_peer_availability___file);
585   peer.state_trace = tmgr_trace_new_from_file(A_surfxml_peer_state___file);
586
587   sg_platf_new_peer(&peer);
588 }
589
590 void STag_surfxml_link(void){
591   AS_TAG = 0;
592   xbt_assert(current_property_set == NULL, "Someone forgot to reset the property set to NULL in its closing tag (or XML malformed)");
593 }
594
595 void ETag_surfxml_link(void){
596   s_sg_platf_link_cbarg_t link;
597   memset(&link,0,sizeof(link));
598
599   link.properties = current_property_set;
600
601   link.id = A_surfxml_link_id;
602   link.bandwidth = surf_parse_get_bandwidth(A_surfxml_link_bandwidth);
603   //printf("Link bandwidth [%lg]\n", link.bandwidth);  
604   link.bandwidth_trace = tmgr_trace_new_from_file(A_surfxml_link_bandwidth___file);
605   link.latency = surf_parse_get_time(A_surfxml_link_latency);
606   //printf("Link latency [%lg]\n", link.latency);  
607   link.latency_trace = tmgr_trace_new_from_file(A_surfxml_link_latency___file);
608
609   switch (A_surfxml_link_state) {
610   case A_surfxml_link_state_ON:
611     link.state = SURF_RESOURCE_ON;
612     break;
613   case A_surfxml_link_state_OFF:
614     link.state = SURF_RESOURCE_OFF;
615     break;
616   default:
617     surf_parse_error("invalid state for link %s", link.id);
618     break;
619   }
620   link.state_trace = tmgr_trace_new_from_file(A_surfxml_link_state___file);
621
622   switch (A_surfxml_link_sharing___policy) {
623   case A_surfxml_link_sharing___policy_SHARED:
624     link.policy = SURF_LINK_SHARED;
625     break;
626   case A_surfxml_link_sharing___policy_FATPIPE:
627      link.policy = SURF_LINK_FATPIPE;
628      break;
629   case A_surfxml_link_sharing___policy_FULLDUPLEX:
630      link.policy = SURF_LINK_FULLDUPLEX;
631      break;
632   default:
633     surf_parse_error("Invalid sharing policy in link %s", link.id);
634     break;
635   }
636
637   sg_platf_new_link(&link);
638
639   current_property_set = NULL;
640 }
641
642 void STag_surfxml_link___ctn(void){
643
644   char *link_id;
645   switch (A_surfxml_link___ctn_direction) {
646   case AU_surfxml_link___ctn_direction:
647   case A_surfxml_link___ctn_direction_NONE:
648     link_id = xbt_strdup(A_surfxml_link___ctn_id);
649     break;
650   case A_surfxml_link___ctn_direction_UP:
651     link_id = bprintf("%s_UP", A_surfxml_link___ctn_id);
652     break;
653   case A_surfxml_link___ctn_direction_DOWN:
654     link_id = bprintf("%s_DOWN", A_surfxml_link___ctn_id);
655     break;
656   }
657
658   // FIXME we should push the surf link object but it don't
659   // work because of model rulebased
660   xbt_dynar_push(parsed_link_list, &link_id);
661 }
662
663 void ETag_surfxml_backbone(void){
664   s_sg_platf_link_cbarg_t link;
665   memset(&link,0,sizeof(link));
666
667   link.properties = NULL;
668
669   link.id = A_surfxml_backbone_id;
670   link.bandwidth = surf_parse_get_bandwidth(A_surfxml_backbone_bandwidth);
671   link.latency = surf_parse_get_time(A_surfxml_backbone_latency);
672   link.state = SURF_RESOURCE_ON;
673   link.policy = SURF_LINK_SHARED;
674
675   sg_platf_new_link(&link);
676   routing_cluster_add_backbone(xbt_lib_get_or_null(link_lib, A_surfxml_backbone_id, SURF_LINK_LEVEL));
677 }
678
679 void STag_surfxml_route(void){
680   xbt_assert(strlen(A_surfxml_route_src) > 0 || strlen(A_surfxml_route_dst) > 0,
681       "Missing end-points while defining route \"%s\"->\"%s\"",
682       A_surfxml_route_src, A_surfxml_route_dst);
683   parsed_link_list = xbt_dynar_new(sizeof(char *), &xbt_free_ref);
684 }
685
686 void STag_surfxml_ASroute(void){
687   xbt_assert(strlen(A_surfxml_ASroute_src) > 0
688              || strlen(A_surfxml_ASroute_dst) > 0
689              || strlen(A_surfxml_ASroute_gw___src) > 0
690              || strlen(A_surfxml_ASroute_gw___dst) > 0,
691              "Missing end-points while defining route \"%s\"->\"%s\" (with %s and %s as gateways)",
692              A_surfxml_ASroute_src, A_surfxml_ASroute_dst,
693              A_surfxml_ASroute_gw___src, A_surfxml_ASroute_gw___dst);
694   parsed_link_list = xbt_dynar_new(sizeof(char *), &xbt_free_ref);
695 }
696
697 void STag_surfxml_bypassRoute(void){
698   xbt_assert(strlen(A_surfxml_bypassRoute_src) > 0
699              || strlen(A_surfxml_bypassRoute_dst) > 0,
700              "Missing end-points while defining bupass route \"%s\"->\"%s\"",
701              A_surfxml_bypassRoute_src, A_surfxml_bypassRoute_dst);
702   parsed_link_list = xbt_dynar_new(sizeof(char *), &xbt_free_ref);
703 }
704
705 void STag_surfxml_bypassASroute(void){
706   xbt_assert(strlen(A_surfxml_bypassASroute_src) > 0
707              || strlen(A_surfxml_bypassASroute_dst) > 0
708              || strlen(A_surfxml_bypassASroute_gw___src) > 0
709              || strlen(A_surfxml_bypassASroute_gw___dst) > 0,
710              "Missing end-points while defining route \"%s\"->\"%s\" (with %s and %s as gateways)",
711              A_surfxml_bypassASroute_src, A_surfxml_bypassASroute_dst,
712              A_surfxml_bypassASroute_gw___src,A_surfxml_bypassASroute_gw___dst);
713   parsed_link_list = xbt_dynar_new(sizeof(char *), &xbt_free_ref);
714 }
715
716 void ETag_surfxml_route(void){
717   s_sg_platf_route_cbarg_t route;
718   memset(&route,0,sizeof(route));
719
720   route.src = A_surfxml_route_src;
721   route.dst = A_surfxml_route_dst;
722   route.gw_src = NULL;
723   route.gw_dst = NULL;
724   route.link_list = parsed_link_list;
725
726   switch (A_surfxml_route_symmetrical) {
727   case AU_surfxml_route_symmetrical:
728   case A_surfxml_route_symmetrical_YES:
729     route.symmetrical = TRUE;
730     break;
731   case A_surfxml_route_symmetrical_NO:
732     route.symmetrical = FALSE;;
733     break;
734   }
735
736   sg_platf_new_route(&route);
737   parsed_link_list = NULL;
738 }
739
740 void ETag_surfxml_ASroute(void){
741   s_sg_platf_route_cbarg_t ASroute;
742   memset(&ASroute,0,sizeof(ASroute));
743
744   ASroute.src = A_surfxml_ASroute_src;
745   ASroute.dst = A_surfxml_ASroute_dst;
746
747   if (!strcmp(current_routing->model_desc->name,"RuleBased")) {
748     // DIRTY PERL HACK AHEAD: with the rulebased routing, the {src,dst}_gateway fields
749     // store the provided name instead of the entity directly (model_rulebased_parse_ASroute knows)
750     //
751     // This is because the user will provide something like "^AS_(.*)$" instead of the proper name of a given entity
752     ASroute.gw_src = (sg_routing_edge_t) A_surfxml_ASroute_gw___src;
753     ASroute.gw_dst = (sg_routing_edge_t) A_surfxml_ASroute_gw___dst;
754   } else {
755     ASroute.gw_src = sg_routing_edge_by_name_or_null(A_surfxml_ASroute_gw___src);
756     ASroute.gw_dst = sg_routing_edge_by_name_or_null(A_surfxml_ASroute_gw___dst);
757   }
758
759   ASroute.link_list = parsed_link_list;
760
761   switch (A_surfxml_ASroute_symmetrical) {
762   case AU_surfxml_ASroute_symmetrical:
763   case A_surfxml_ASroute_symmetrical_YES:
764     ASroute.symmetrical = TRUE;
765     break;
766   case A_surfxml_ASroute_symmetrical_NO:
767     ASroute.symmetrical = FALSE;
768     break;
769   }
770
771   sg_platf_new_ASroute(&ASroute);
772   parsed_link_list = NULL;
773 }
774
775 void ETag_surfxml_bypassRoute(void){
776   s_sg_platf_route_cbarg_t route;
777   memset(&route,0,sizeof(route));
778
779   route.src = A_surfxml_bypassRoute_src;
780   route.dst = A_surfxml_bypassRoute_dst;
781   route.gw_src = NULL;
782   route.gw_dst = NULL;
783   route.link_list = parsed_link_list;
784   route.symmetrical = FALSE;
785
786   sg_platf_new_bypassRoute(&route);
787   parsed_link_list = NULL;
788 }
789
790 void ETag_surfxml_bypassASroute(void){
791   s_sg_platf_route_cbarg_t ASroute;
792   memset(&ASroute,0,sizeof(ASroute));
793
794   ASroute.src = A_surfxml_bypassASroute_src;
795   ASroute.dst = A_surfxml_bypassASroute_dst;
796   ASroute.link_list = parsed_link_list;
797   ASroute.symmetrical = FALSE;
798
799   if (!strcmp(current_routing->model_desc->name,"RuleBased")) {
800     // DIRTY PERL HACK AHEAD: with the rulebased routing, the {src,dst}_gateway fields
801     // store the provided name instead of the entity directly (model_rulebased_parse_ASroute knows)
802     //
803     // This is because the user will provide something like "^AS_(.*)$" instead of the proper name of a given entity
804     ASroute.gw_src = (sg_routing_edge_t) A_surfxml_bypassASroute_gw___src;
805     ASroute.gw_dst = (sg_routing_edge_t) A_surfxml_bypassASroute_gw___dst;
806   } else {
807     ASroute.gw_src = sg_routing_edge_by_name_or_null(A_surfxml_bypassASroute_gw___src);
808     ASroute.gw_dst = sg_routing_edge_by_name_or_null(A_surfxml_bypassASroute_gw___dst);
809   }
810
811   sg_platf_new_bypassASroute(&ASroute);
812   parsed_link_list = NULL;
813 }
814
815 void ETag_surfxml_trace(void){
816   s_sg_platf_trace_cbarg_t trace;
817   memset(&trace,0,sizeof(trace));
818
819   trace.id = A_surfxml_trace_id;
820   trace.file = A_surfxml_trace_file;
821   trace.periodicity = surf_parse_get_double(A_surfxml_trace_periodicity);
822   trace.pc_data = surfxml_pcdata;
823
824   sg_platf_new_trace(&trace);
825 }
826
827 void STag_surfxml_trace___connect(void){
828   s_sg_platf_trace_connect_cbarg_t trace_connect;
829   memset(&trace_connect,0,sizeof(trace_connect));
830
831   trace_connect.element = A_surfxml_trace___connect_element;
832   trace_connect.trace = A_surfxml_trace___connect_trace;
833
834   switch (A_surfxml_trace___connect_kind) {
835   case AU_surfxml_trace___connect_kind:
836   case A_surfxml_trace___connect_kind_POWER:
837     trace_connect.kind =  SURF_TRACE_CONNECT_KIND_POWER;
838     break;
839   case A_surfxml_trace___connect_kind_BANDWIDTH:
840     trace_connect.kind =  SURF_TRACE_CONNECT_KIND_BANDWIDTH;
841     break;
842   case A_surfxml_trace___connect_kind_HOST___AVAIL:
843     trace_connect.kind =  SURF_TRACE_CONNECT_KIND_HOST_AVAIL;
844     break;
845   case A_surfxml_trace___connect_kind_LATENCY:
846     trace_connect.kind =  SURF_TRACE_CONNECT_KIND_LATENCY;
847     break;
848   case A_surfxml_trace___connect_kind_LINK___AVAIL:
849     trace_connect.kind =  SURF_TRACE_CONNECT_KIND_LINK_AVAIL;
850     break;
851   }
852   sg_platf_trace_connect(&trace_connect);
853 }
854
855 void STag_surfxml_AS(void){
856   AS_TAG = 1;
857   s_sg_platf_AS_cbarg_t AS = SG_PLATF_AS_INITIALIZER;
858   AS.id = A_surfxml_AS_id;
859   AS.routing = (int)A_surfxml_AS_routing;
860
861   as_current_property_set = NULL;
862
863   sg_platf_new_AS_begin(&AS);
864 }
865 void ETag_surfxml_AS(void){
866   if(as_prop_nb){
867     char *name = as_name_tab[as_prop_nb-1];
868     xbt_dict_t dict = as_dict_tab[as_prop_nb-1];
869     as_prop_nb--;
870     XBT_DEBUG("POP prop %p for AS '%s'",dict,name);
871     xbt_lib_set(as_router_lib,
872         name,
873       ROUTING_PROP_ASR_LEVEL,
874       dict);
875     xbt_free(name);
876   }
877   sg_platf_new_AS_end();
878 }
879
880 extern int _sg_init_status; /* FIXME: find a proper way to export this at some point */
881
882 void STag_surfxml_config(void){
883   AS_TAG = 0;
884   xbt_assert(current_property_set == NULL, "Someone forgot to reset the property set to NULL in its closing tag (or XML malformed)");
885   XBT_DEBUG("START configuration name = %s",A_surfxml_config_id);
886   if (_sg_init_status == 2) {
887     surf_parse_error("All <config> tags must be given before any platform elements (such as <AS>, <host>, <cluster>, <link>, etc).");
888   }
889 }
890 void ETag_surfxml_config(void){
891   xbt_dict_cursor_t cursor = NULL;
892   char *key;
893   char *elem;
894   char *cfg;
895   xbt_dict_foreach(current_property_set, cursor, key, elem) {
896     cfg = bprintf("%s:%s",key,elem);
897     if(xbt_cfg_is_default_value(_sg_cfg_set, key))
898       xbt_cfg_set_parse(_sg_cfg_set, cfg);
899     else
900       XBT_INFO("The custom configuration '%s' is already defined by user!",key);
901     free(cfg);
902   }
903   XBT_DEBUG("End configuration name = %s",A_surfxml_config_id);
904   xbt_dict_free(&current_property_set);
905   current_property_set = NULL;
906 }
907
908 static int argc;
909 static char **argv;
910
911 void STag_surfxml_process(void){
912   AS_TAG = 0;
913   argc = 1;
914   argv = xbt_new(char *, 1);
915   argv[0] = xbt_strdup(A_surfxml_process_function);
916   xbt_assert(current_property_set == NULL, "Someone forgot to reset the property set to NULL in its closing tag (or XML malformed)");
917 }
918
919 void ETag_surfxml_process(void){
920   s_sg_platf_process_cbarg_t process;
921   memset(&process,0,sizeof(process));
922
923   process.argc = argc;
924   process.argv = (const char **)argv;
925   process.properties = current_property_set;
926   process.host = A_surfxml_process_host;
927   process.function = A_surfxml_process_function;
928   process.start_time = surf_parse_get_double(A_surfxml_process_start___time);
929   process.kill_time = surf_parse_get_double(A_surfxml_process_kill___time);
930
931   switch (A_surfxml_process_on___failure) {
932   case AU_surfxml_process_on___failure:
933   case A_surfxml_process_on___failure_DIE:
934     process.on_failure =  SURF_PROCESS_ON_FAILURE_DIE;
935     break;
936   case A_surfxml_process_on___failure_RESTART:
937     process.on_failure =  SURF_PROCESS_ON_FAILURE_RESTART;
938     break;
939   }
940
941   sg_platf_new_process(&process);
942   current_property_set = NULL;
943 }
944
945 void STag_surfxml_argument(void){
946   argc++;
947   argv = xbt_realloc(argv, (argc) * sizeof(char *));
948   argv[(argc) - 1] = xbt_strdup(A_surfxml_argument_value);
949 }
950
951 /* ***************************************** */
952 /* TUTORIAL: New TAG                         */
953 void STag_surfxml_gpu(void)
954 {
955   XBT_DEBUG("STag_surfxml_gpu");
956 }
957 void ETag_surfxml_gpu(void)
958 {
959   s_sg_platf_gpu_cbarg_t gpu;
960   memset(&gpu,0,sizeof(gpu));
961
962   gpu.name = A_surfxml_gpu_name;
963
964   sg_platf_new_gpu(&gpu);
965 }
966 /* ***************************************** */
967
968 /* nothing to do in those functions */
969 void ETag_surfxml_prop(void){}
970 void STag_surfxml_random(void){}
971 void ETag_surfxml_random(void){}
972 void ETag_surfxml_trace___connect(void){}
973 void STag_surfxml_trace(void){}
974 void ETag_surfxml_router(void){}
975 void ETag_surfxml_host___link(void){}
976 void ETag_surfxml_cluster(void){}
977 void ETag_surfxml_cabinet(void){}
978 void ETag_surfxml_peer(void){}
979 void STag_surfxml_backbone(void){}
980 void ETag_surfxml_link___ctn(void){}
981 void ETag_surfxml_argument(void){}
982
983 /* Open and Close parse file */
984
985 void surf_parse_open(const char *file)
986 {
987   static int warned = 0;        /* warn only once */
988   if (!file) {
989     if (!warned) {
990       XBT_WARN
991           ("Bypassing the XML parser since surf_parse_open received a NULL pointer. "
992               "If it is not what you want, go fix your code.");
993       warned = 1;
994     }
995     return;
996   }
997
998   if (!surf_input_buffer_stack)
999     surf_input_buffer_stack = xbt_dynar_new(sizeof(YY_BUFFER_STATE), NULL);
1000   if (!surf_file_to_parse_stack)
1001     surf_file_to_parse_stack = xbt_dynar_new(sizeof(FILE *), NULL);
1002
1003   if (!surf_parsed_filename_stack)
1004     surf_parsed_filename_stack = xbt_dynar_new(sizeof(char *), &xbt_free_ref);
1005   surf_parsed_filename = xbt_strdup(file);
1006
1007   surf_file_to_parse = surf_fopen(file, "r");
1008   xbt_assert((surf_file_to_parse), "Unable to open \"%s\"\n", file);
1009   surf_input_buffer = surf_parse__create_buffer(surf_file_to_parse, YY_BUF_SIZE);
1010   surf_parse__switch_to_buffer(surf_input_buffer);
1011   surf_parse_lineno = 1;
1012 }
1013
1014 void surf_parse_close(void)
1015 {
1016   xbt_dynar_free(&surf_input_buffer_stack);
1017   xbt_dynar_free(&surf_file_to_parse_stack);
1018   xbt_dynar_free(&surf_parsed_filename_stack);
1019
1020   free(surf_parsed_filename);
1021   surf_parsed_filename = NULL;
1022
1023   if (surf_file_to_parse) {
1024     surf_parse__delete_buffer(surf_input_buffer);
1025     fclose(surf_file_to_parse);
1026     surf_file_to_parse = NULL; //Must be reset for Bypass
1027   }
1028 }
1029
1030 /* Call the lexer to parse the currently opened file. This pointer to function enables bypassing of the parser */
1031
1032 static int _surf_parse(void) {
1033   return surf_parse_lex();
1034 }
1035 int_f_void_t surf_parse = _surf_parse;
1036
1037
1038 /* Prop tag functions */
1039
1040 /**
1041  * With XML parser
1042  */
1043
1044 /* Random tag functions */
1045
1046 double get_cpu_power(const char *power)
1047 {
1048   double power_scale = 0.0;
1049   const char *p, *q;
1050   char *generator;
1051   random_data_t random = NULL;
1052   /* randomness is inserted like this: power="$rand(my_random)" */
1053   if (((p = strstr(power, "$rand(")) != NULL)
1054       && ((q = strstr(power, ")")) != NULL)) {
1055     if (p < q) {
1056       generator = xbt_malloc(q - (p + 6) + 1);
1057       memcpy(generator, p + 6, q - (p + 6));
1058       generator[q - (p + 6)] = '\0';
1059       random = xbt_dict_get_or_null(random_data_list, generator);
1060       xbt_assert(random, "Random generator %s undefined", generator);
1061       power_scale = random_generate(random);
1062     }
1063   } else {
1064     power_scale = surf_parse_get_power(power);
1065   }
1066   return power_scale;
1067 }
1068
1069 double random_min, random_max, random_mean, random_std_deviation;
1070 e_random_generator_t random_generator;
1071 char *random_id;
1072
1073 static void init_randomness(void)
1074 {
1075   random_id = A_surfxml_random_id;
1076   random_min = surf_parse_get_double(A_surfxml_random_min);
1077   random_max = surf_parse_get_double(A_surfxml_random_max);
1078   random_mean = surf_parse_get_double(A_surfxml_random_mean);
1079   random_std_deviation = surf_parse_get_double(A_surfxml_random_std___deviation);
1080   switch (A_surfxml_random_generator) {
1081   case AU_surfxml_random_generator:
1082   case A_surfxml_random_generator_NONE:
1083     random_generator = NONE;
1084     break;
1085   case A_surfxml_random_generator_DRAND48:
1086     random_generator = DRAND48;
1087     break;
1088   case A_surfxml_random_generator_RAND:
1089     random_generator = RAND;
1090     break;
1091   case A_surfxml_random_generator_RNGSTREAM:
1092     random_generator = RNGSTREAM;
1093     break;
1094   default:
1095     surf_parse_error("Invalid random generator");
1096     break;
1097   }
1098 }
1099
1100 static void add_randomness(void)
1101 {
1102   /* If needed aditional properties can be added by using the prop tag */
1103   random_data_t random =
1104       random_new(random_generator, 0, random_min, random_max, random_mean,
1105                  random_std_deviation);
1106   xbt_dict_set(random_data_list, random_id, (void *) random,
1107                &xbt_free_ref);
1108 }
1109
1110
1111 xbt_dict_t get_as_router_properties(const char* name)
1112 {
1113   return xbt_lib_get_or_null(as_router_lib, name, ROUTING_PROP_ASR_LEVEL);
1114 }
1115