Skip to content

Commit eb34a16

Browse files
committed
tools/zep_dispatch: topogen: allow to pass worldfile
A world file might look like ``` A 5 3 10 B 10 C 20 20 ```
1 parent 1f6a7b4 commit eb34a16

File tree

1 file changed

+128
-5
lines changed

1 file changed

+128
-5
lines changed

dist/tools/zep_dispatch/topogen.c

Lines changed: 128 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
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>
@@ -17,8 +19,12 @@
1719
#define CONFIG_USE_NUMERIC_NAMES 1
1820
#endif
1921

22+
#define DEFAULT_RANGE 25
23+
#define DELIM "\t ;,"
24+
2025
struct 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,115 @@ 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+
if (strlcpy(n->name, name, sizeof(n->name)) >= sizeof(n->name)) {
310+
fprintf(stderr, "warning: '%s' truncated to '%s'\n", name, n->name);
311+
}
312+
313+
/* node definition with pinned MAC */
314+
if (!strcmp(xpos, ":=")) {
315+
strlcpy(n->extra, ypos, sizeof(n->extra));
316+
continue;
317+
}
318+
319+
if (xpos) {
320+
n->x = atoi(xpos);
321+
} else {
322+
fprintf(stderr, "error on line %d: '%s' has no position\n", linenum, name);
323+
return -1;
324+
}
325+
if (ypos) {
326+
n->y = atoi(ypos);
327+
}
328+
if (range) {
329+
n->r = atoi(range);
330+
} else {
331+
n->r = DEFAULT_RANGE;
332+
}
333+
334+
if (n->x + n->r > w->w) {
335+
w->w = n->x + n->r;
336+
}
337+
if (n->y + n->r > w->h) {
338+
w->h = n->y + n->r;
339+
}
340+
}
341+
342+
free(line);
343+
344+
return 0;
345+
}
346+
247347
int main(int argc, char** argv)
248348
{
249349
const char *progname = argv[0];
350+
char *worldmap = NULL;
250351

251352
unsigned width = 100;
252353
unsigned height = 100;
253354
unsigned seed = time(NULL);
254-
unsigned range = 25;
355+
unsigned range = DEFAULT_RANGE;
255356
unsigned var = 0;
256357
unsigned num = 10;
257358
bool binary = false;
258359
bool grid = false;
259360
char c;
260361

261-
while ((c = getopt(argc, argv, "s:w:h:r:v:n:bg")) != -1) {
362+
while ((c = getopt(argc, argv, "s:w:h:r:v:n:f:bg")) != -1) {
262363
switch (c) {
263364
case 'b':
264365
binary = true;
@@ -284,6 +385,9 @@ int main(int argc, char** argv)
284385
case 'n':
285386
num = atoi(optarg);
286387
break;
388+
case 'f':
389+
worldmap = optarg;
390+
break;
287391
default:
288392
_print_help(progname);
289393
exit(1);
@@ -295,7 +399,26 @@ int main(int argc, char** argv)
295399
struct world w = {
296400
.grid = grid,
297401
};
298-
world_gen(&w, num, width, height, range, var);
402+
403+
if (worldmap) {
404+
FILE *file;
405+
if (strcmp(worldmap, "-")) {
406+
file = fopen(worldmap, "r");
407+
} else {
408+
file = stdin;
409+
}
410+
if (!file) {
411+
fprintf(stderr, "can't open %s\n", worldmap);
412+
return -1;
413+
}
414+
int res = _from_file(&w, file);
415+
fclose(file);
416+
if (res) {
417+
return res;
418+
}
419+
} else {
420+
world_gen(&w, num, width, height, range, var);
421+
}
299422

300423
printf("# seed = %u\n", seed);
301424
puts("# Connections");

0 commit comments

Comments
 (0)