55 * License v2. See the file LICENSE for more details.
66 */
77
8+ #include <ctype.h>
89#include <stdbool.h>
910#include <stdio.h>
1011#include <stdint.h>
1112#include <stdlib.h>
13+ #include <string.h>
1214#include <time.h>
1315#include <math.h>
1416#include <unistd.h>
1719#define CONFIG_USE_NUMERIC_NAMES 1
1820#endif
1921
22+ #define DEFAULT_RANGE 25
23+ #define DELIM "\t ;,"
24+
2025struct node {
21- char name [8 ];
26+ char name [16 ];
27+ char extra [24 ];
2228 int x ;
2329 int y ;
2430 unsigned r ;
@@ -194,7 +200,11 @@ static void _print_distance(struct node *nodes, unsigned num, bool recursive, bo
194200
195201 if (recursive ) {
196202 for (unsigned i = 0 ; i < num ; ++ i ) {
197- printf ("%s\n" , nodes [i ].name );
203+ printf ("%s" , nodes [i ].name );
204+ if (* nodes [i ].extra ) {
205+ printf (" := %s" , nodes [i ].extra );
206+ }
207+ puts ("" );
198208 }
199209 }
200210
@@ -230,6 +240,7 @@ static void _print_help(const char *name)
230240 " [-r <range>]"
231241 " [-v <variance of range>]"
232242 " [-n <nodes>]"
243+ " [-f <file>]"
233244 " [-b][-g]"
234245 "\n" , name );
235246
@@ -240,25 +251,116 @@ static void _print_help(const char *name)
240251 puts ("\t-r <range>\tRadio range of the nodes" );
241252 puts ("\t-v <variance>\tmaximal random variance of radio range" );
242253 puts ("\t-n <nodes>\tnumber of nodes in the topology" );
254+ puts ("\t-f <file>\tread world from file instead of generating it randomly\n" );
243255 puts ("\t-b\t\tbinary links: link quality is rounded to 100% or 0%" );
244256 puts ("\t-g\t\tnodes are organized as a grid" );
245257}
246258
259+ static bool _is_empty (const char * line )
260+ {
261+ while (* line ) {
262+ if (!isspace (* line ++ )) {
263+ return false;
264+ }
265+ }
266+
267+ return true;
268+ }
269+
270+ static struct node * _get_node_by_name (struct world * w , const char * name )
271+ {
272+ for (unsigned i = 0 ; i < w -> num_nodes ; ++ i ) {
273+ if (!strcmp (w -> nodes [i ].name , name )) {
274+ return & w -> nodes [i ];
275+ }
276+ }
277+
278+ return NULL ;
279+ }
280+
281+ static int _from_file (struct world * w , FILE * file )
282+ {
283+ char * line = NULL ;
284+ size_t len = 0 ;
285+
286+
287+ unsigned linenum = 0 ;
288+ while (getline (& line , & len , file ) >= 0 ) {
289+ ++ linenum ;
290+
291+ /* skip comments & empty lines */
292+ if (* line == '#' || _is_empty (line )) {
293+ continue ;
294+ }
295+
296+ char * name = strtok (line , DELIM );
297+ char * xpos = strtok (NULL , DELIM );
298+ char * ypos = strtok (NULL , DELIM );
299+ char * range = strtok (NULL , DELIM );
300+
301+ /* check if node is already stored */
302+ struct node * n = _get_node_by_name (w , name );
303+ if (n == NULL ) {
304+ w -> nodes = reallocarray (w -> nodes , ++ w -> num_nodes , sizeof (* w -> nodes ));
305+ n = & w -> nodes [w -> num_nodes - 1 ];
306+ }
307+
308+ /* store name */
309+ strncpy (n -> name , name , sizeof (n -> name ) - 1 );
310+ if (strlen (name ) >= sizeof (n -> name )) {
311+ fprintf (stderr , "warning: '%s' truncated to '%s'\n" , name , n -> name );
312+ }
313+
314+ /* node definition with pinned MAC */
315+ if (!strcmp (xpos , ":=" )) {
316+ strncpy (n -> extra , ypos , sizeof (n -> extra ) - 1 );
317+ continue ;
318+ }
319+
320+ if (xpos ) {
321+ n -> x = atoi (xpos );
322+ } else {
323+ fprintf (stderr , "error on line %d: '%s' has no position\n" , linenum , name );
324+ return -1 ;
325+ }
326+ if (ypos ) {
327+ n -> y = atoi (ypos );
328+ }
329+ if (range ) {
330+ n -> r = atoi (range );
331+ } else {
332+ n -> r = DEFAULT_RANGE ;
333+ }
334+
335+ if (n -> x + n -> r > w -> w ) {
336+ w -> w = n -> x + n -> r ;
337+ }
338+ if (n -> y + n -> r > w -> h ) {
339+ w -> h = n -> y + n -> r ;
340+ }
341+ }
342+
343+ free (line );
344+
345+ return 0 ;
346+ }
347+
247348int main (int argc , char * * argv )
248349{
249350 const char * progname = argv [0 ];
351+ char * worldmap = NULL ;
250352
251353 unsigned width = 100 ;
252354 unsigned height = 100 ;
253355 unsigned seed = time (NULL );
254- unsigned range = 25 ;
356+ unsigned range = DEFAULT_RANGE ;
255357 unsigned var = 0 ;
256358 unsigned num = 10 ;
257359 bool binary = false;
258360 bool grid = false;
259361 char c ;
260362
261- while ((c = getopt (argc , argv , "s:w:h:r:v:n:bg" )) != -1 ) {
363+ while ((c = getopt (argc , argv , "s:w:h:r:v:n:f: bg" )) != -1 ) {
262364 switch (c ) {
263365 case 'b' :
264366 binary = true;
@@ -284,6 +386,9 @@ int main(int argc, char** argv)
284386 case 'n' :
285387 num = atoi (optarg );
286388 break ;
389+ case 'f' :
390+ worldmap = optarg ;
391+ break ;
287392 default :
288393 _print_help (progname );
289394 exit (1 );
@@ -295,7 +400,26 @@ int main(int argc, char** argv)
295400 struct world w = {
296401 .grid = grid ,
297402 };
298- world_gen (& w , num , width , height , range , var );
403+
404+ if (worldmap ) {
405+ FILE * file ;
406+ if (strcmp (worldmap , "-" )) {
407+ file = fopen (worldmap , "r" );
408+ } else {
409+ file = stdin ;
410+ }
411+ if (!file ) {
412+ fprintf (stderr , "can't open %s\n" , worldmap );
413+ return -1 ;
414+ }
415+ int res = _from_file (& w , file );
416+ fclose (file );
417+ if (res ) {
418+ return res ;
419+ }
420+ } else {
421+ world_gen (& w , num , width , height , range , var );
422+ }
299423
300424 printf ("# seed = %u\n" , seed );
301425 puts ("# Connections" );
0 commit comments