Logo AND Algorithmique Numérique Distribuée

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