ROSS
tw-opts.c
Go to the documentation of this file.
1 #include <ctype.h>
2 #include <ross.h>
3 
4 static const char *program;
5 static const tw_optdef *all_groups[10];
6 
7 static void need_argument(const tw_optdef *def) NORETURN;
8 static int is_empty(const tw_optdef *def);
9 
10 static const tw_optdef *opt_groups[10];
11 static unsigned int opt_index = 0;
12 
13 void
14 tw_opt_add(const tw_optdef *options)
15 {
16  if(!options || !options->type || is_empty(options))
17  return;
18 
19  opt_groups[opt_index++] = options;
20  opt_groups[opt_index] = NULL;
21 }
22 
23 static void
24 show_help(void)
25 {
26  const tw_optdef **group = all_groups;
27  unsigned cnt = 0;
28 
29  fprintf(stderr, "usage: %s [options] [-- [args]]\n", program);
30  fputc('\n', stderr);
31 
32  for (; *group; group++)
33  {
34  const tw_optdef *def = *group;
35  for (; def->type; def++)
36  {
37  int pos = 0;
38 
39  if (def->type == TWOPTTYPE_GROUP)
40  {
41  if (cnt)
42  fputc('\n', stderr);
43  fprintf(stderr, "%s:\n", def->help);
44  cnt++;
45  continue;
46  }
47 
48  pos += fprintf(stderr, " --%s", def->name);
49  switch (def->type)
50  {
51  case TWOPTTYPE_ULONG:
53  case TWOPTTYPE_UINT:
54  pos += fprintf(stderr, "=n");
55  break;
56 
57  case TWOPTTYPE_DOUBLE:
58  pos += fprintf(stderr, "=dbl");
59  break;
60 
61  case TWOPTTYPE_STIME:
62  pos += fprintf(stderr, "=ts");
63  break;
64 
65  case TWOPTTYPE_CHAR:
66  pos += fprintf(stderr, "=str");
67  break;
68 
69  default:
70  break;
71  }
72 
73  if (def->help)
74  {
75  int col = 22;
76  int pad = col - pos;
77  if (pad > 0)
78  fprintf(stderr, "%*s", col - pos, "");
79  else {
80  fputc('\n', stderr);
81  fprintf(stderr, "%*s", col, "");
82  }
83  fputs(" ", stderr);
84  fputs(def->help, stderr);
85  }
86 
87  if (def->value)
88  {
89  switch (def->type)
90  {
91  case TWOPTTYPE_ULONG:
92  fprintf(stderr, " (default %lu)", *((unsigned long*)def->value));
93  break;
94 
96  fprintf(stderr, " (default %llu)", *((unsigned long long*)def->value));
97  break;
98 
99  case TWOPTTYPE_UINT:
100  fprintf(stderr, " (default %u)", *((unsigned int*)def->value));
101  break;
102 
103  case TWOPTTYPE_DOUBLE:
104  fprintf(stderr, " (default %.2f)", *((double*)def->value));
105  break;
106 
107  case TWOPTTYPE_STIME:
108  fprintf(stderr, " (default %.2f)", *((tw_stime*)def->value));
109  break;
110 
111  case TWOPTTYPE_CHAR:
112  fprintf(stderr, " (default %s)", (char *) def->value);
113  break;
114 
115  case TWOPTTYPE_FLAG:
116  if((*(unsigned int*)def->value) == 0) {
117  fprintf(stderr, " (default off)");
118  } else {
119  fprintf(stderr, " (default on)");
120  }
121  break;
122 
123  default:
124  break;
125  }
126  }
127 
128  fputc('\n', stderr);
129  cnt++;
130  }
131  }
132 
133  // CMake used to pass options by command line flags
134  fprintf(stderr, "ROSS CMake Configuration Options:\n");
135  fprintf(stderr, " (See build-dir/core/config.h)\n");
136 }
137 
138 void tw_opt_settings(FILE *outfile) {
139  const tw_optdef **group = all_groups;
140  unsigned cnt = 0;
141 
142  for (; *group; group++){
143  const tw_optdef *def = *group;
144  for (; def->type; def++){
145  int pos = 0;
146 
147  if (def->type == TWOPTTYPE_GROUP){
148  if (cnt)
149  fputc('\n', outfile);
150  fprintf(outfile, "%s:\n", def->help);
151  cnt++;
152  continue;
153  }
154 
155  pos += fprintf(outfile, " --%s", def->name);
156 
157  if (def->value) {
158  int col = 20;
159  int pad = col - pos;
160  if (pad > 0) {
161  fprintf(outfile, "%*s", col - pos, "");
162  } else {
163  fputc('\n', outfile);
164  fprintf(outfile, "%*s", col, "");
165  }
166  fputs(" ", outfile);
167  }
168 
169  if (def->value){
170  switch (def->type){
171  case TWOPTTYPE_ULONG:
172  fprintf(outfile, "%lu", *((unsigned long*)def->value));
173  break;
174 
175  case TWOPTTYPE_ULONGLONG:
176  fprintf(outfile, "%llu", *((unsigned long long*)def->value));
177  break;
178 
179  case TWOPTTYPE_UINT:
180  fprintf(outfile, "%u", *((unsigned int*)def->value));
181  break;
182 
183  case TWOPTTYPE_DOUBLE:
184  fprintf(outfile, "%.2f", *((double*)def->value));
185  break;
186 
187  case TWOPTTYPE_STIME:
188  fprintf(outfile, "%.2f", *((tw_stime*)def->value));
189  break;
190 
191  case TWOPTTYPE_CHAR:
192  fprintf(outfile, "%s", (char *) def->value);
193  break;
194 
195  case TWOPTTYPE_FLAG:
196  if((*(unsigned int*)def->value) == 0) {
197  fprintf(outfile, "off");
198  } else {
199  fprintf(outfile, "on");
200  }
201  break;
202 
203  default:
204  break;
205  }
206  }
207 
208  fputc('\n', outfile);
209  cnt++;
210  }
211  }
212 }
213 
214 void
216 {
217  FILE *f = g_tw_csv;
218  const tw_optdef **group = all_groups;
219 
220  if(!tw_ismaster() || NULL == f)
221  return;
222 
223  for (; *group; group++)
224  {
225  const tw_optdef *def = *group;
226  for (; def->type; def++)
227  {
228  if (def->type == TWOPTTYPE_GROUP ||
229  (def->name && 0 == strcmp(def->name, "help")))
230  continue;
231 
232  if (def->value)
233  {
234  switch (def->type)
235  {
236  case TWOPTTYPE_ULONG:
237  fprintf(f, "%lu,", *((unsigned long*)def->value));
238  break;
239 
240  case TWOPTTYPE_ULONGLONG:
241  fprintf(f, "%llu,", *((unsigned long long*)def->value));
242  break;
243 
244  case TWOPTTYPE_UINT:
245  fprintf(f, "%u,", *((unsigned int*)def->value));
246  break;
247 
248  case TWOPTTYPE_DOUBLE:
249  fprintf(f, "%.2f,", *((double*)def->value));
250  break;
251 
252  case TWOPTTYPE_STIME:
253  fprintf(f, "%.2f,", *((tw_stime*)def->value));
254  break;
255 
256  case TWOPTTYPE_CHAR:
257  fprintf(f, "%s,", (char *)def->value);
258  break;
259 
260  case TWOPTTYPE_FLAG:
261  fprintf(f, "%s,", (char *)def->name);
262  break;
263 
264  default:
265  break;
266  }
267  } else
268  fprintf(f, "undefined,");
269  }
270  }
271 
272  //print_options(f);
273 }
274 
275 static void
277 {
278  if (tw_ismaster())
279  fprintf(stderr,
280  "%s: option --%s requires a valid argument\n",
281  program, def->name);
282  tw_net_stop();
283  exit(1);
284 }
285 
286 static void
287 apply_opt(const tw_optdef *def, const char *value)
288 {
289  switch (def->type)
290  {
291  case TWOPTTYPE_ULONG:
292  case TWOPTTYPE_ULONGLONG:
293  case TWOPTTYPE_UINT:
294  {
295  unsigned long v;
296  char *end;
297 
298  if (!value)
299  need_argument(def);
300  v = strtoul(value, &end, 10);
301  if (*end)
302  need_argument(def);
303  switch (def->type)
304  {
305  case TWOPTTYPE_ULONG:
306  *((unsigned long*)def->value) = v;
307  break;
308  case TWOPTTYPE_ULONGLONG:
309  *((unsigned long long*)def->value) = v;
310  break;
311 
312  case TWOPTTYPE_UINT:
313  *((unsigned int*)def->value) = (unsigned int)v;
314  break;
315  default:
316  tw_error(TW_LOC, "Option type not supported here.");
317  }
318  break;
319  }
320 
321  case TWOPTTYPE_DOUBLE:
322  {
323  double v;
324  char *end;
325 
326  if (!value)
327  need_argument(def);
328  v = strtod(value, &end);
329  if (*end)
330  need_argument(def);
331  *((double*)def->value) = v;
332  break;
333  }
334 
335  case TWOPTTYPE_STIME:
336  {
337  tw_stime v;
338  char *end;
339 
340  tw_warning(TW_LOC, "Option type stime (TWOPT_STIME) is deprecated. Please use double (TWOPT_DOUBLE).");
341 
342  if (!value)
343  need_argument(def);
344  v = strtod(value, &end);
345  if (*end)
346  need_argument(def);
347  *((tw_stime*)def->value) = v;
348  break;
349  }
350 
351  case TWOPTTYPE_CHAR:
352  {
353  if (!value)
354  need_argument(def);
355 
356  //*((char **)def->value) = tw_calloc(TW_LOC, "string arg", strlen(value) + 1, 1);
357  strcpy((char *) def->value, value);
358  break;
359  }
360 
361  case TWOPTTYPE_FLAG:
362  *((unsigned int*)def->value) = 1;
363  break;
364 
365  case TWOPTTYPE_SHOWHELP:
366  if (tw_ismaster())
367  show_help();
368  tw_net_stop();
369  exit(0);
370  break;
371 
372  default:
373  tw_error(TW_LOC, "Option type not supported here.");
374  }
375 }
376 
377 static void
378 match_opt(const char *arg)
379 {
380  const char *eq = strchr(arg + 2, '=');
381  const tw_optdef **group = all_groups;
382 
383  for (; *group; group++)
384  {
385  const tw_optdef *def = *group;
386  for (; def->type; def++)
387  {
388  if (!def->name || def->type == TWOPTTYPE_GROUP)
389  continue;
390  if (!eq && !strcmp(def->name, arg + 2))
391  {
392  apply_opt(def, NULL);
393  return;
394  }
395  else if (eq && !strncmp(def->name, arg + 2, eq - arg - 2))
396  {
397  apply_opt(def, eq + 1);
398  return;
399  }
400  }
401  }
402 
403  if (tw_ismaster())
404  fprintf(stderr,
405  "%s: option '%s' not recognized; see --help for details\n",
406  program, arg);
407  tw_net_stop();
408  exit(1);
409 }
410 
411 static const tw_optdef basic[] = {
412  { TWOPTTYPE_SHOWHELP, "help", "show this message", NULL },
413  TWOPT_END()
414 };
415 
416 static int is_empty(const tw_optdef *def)
417 {
418  for (; def->type; def++) {
419  if (def->type == TWOPTTYPE_GROUP)
420  continue;
421  return 0;
422  }
423  return 1;
424 }
425 
426 void
427 tw_opt_parse(int *argc_p, char ***argv_p)
428 {
429  int argc = *argc_p;
430  char **argv = *argv_p;
431  unsigned i;
432 
433  program = strrchr(argv[0], '/');
434  if (program)
435  program++;
436  else
437  program = argv[0];
438 
439  for (i = 0; opt_groups[i]; i++)
440  {
441  if (!(opt_groups[i])->type || is_empty(opt_groups[i]))
442  continue;
443  if (i >= ARRAY_SIZE(all_groups))
444  tw_error(TW_LOC, "Too many tw_optdef arrays.");
445  all_groups[i] = opt_groups[i];
446  }
447  all_groups[i++] = basic;
448  all_groups[i] = NULL;
449 
450  while (argc > 1)
451  {
452  const char *s = argv[1];
453  if (strncmp(s, "--", 2))
454  {
455  printf("Warning: found ill-formated argument: %s, stopping arg parsing here!! \n", s );
456  break;
457  }
458  if (strcmp(s, "--"))
459  match_opt(s);
460 
461  argc--;
462  memmove(argv + 1, argv + 2, (argc - 1) * sizeof(*argv));
463 
464  if (!strcmp(s, "--"))
465  break;
466  }
467 
468  *argc_p = argc;
469  *argv_p = argv;
470 }
#define TW_LOC
Definition: ross-extern.h:164
static int is_empty(const tw_optdef *def)
Definition: tw-opts.c:416
static void need_argument(const tw_optdef *def)
Definition: tw-opts.c:276
static void apply_opt(const tw_optdef *def, const char *value)
Definition: tw-opts.c:287
double tw_stime
Definition: ross.h:150
void tw_net_stop(void)
Stops the network library after simulation end.
Definition: network-mpi.c:154
void tw_error(const char *file, int line, const char *fmt,...) NORETURN
Definition: tw-util.c:74
#define ARRAY_SIZE(a)
Definition: ross.h:88
static int tw_ismaster(void)
void tw_warning(const char *file, int line, const char *fmt,...)
Definition: tw-util.c:90
static const tw_optdef * opt_groups[10]
Definition: tw-opts.c:10
static const tw_optdef * all_groups[10]
Definition: tw-opts.c:5
void tw_opt_print(void)
Definition: tw-opts.c:215
static const char * program
Definition: tw-opts.c:4
FILE * g_tw_csv
Definition: ross-global.c:91
#define NORETURN
Definition: ross.h:94
void * value
Definition: tw-opts.h:24
#define TWOPT_END()
Definition: tw-opts.h:35
void tw_opt_add(const tw_optdef *options)
Definition: tw-opts.c:14
const char * help
Definition: tw-opts.h:23
tw_opttype type
Definition: tw-opts.h:21
static void show_help(void)
Definition: tw-opts.c:24
void tw_opt_settings(FILE *outfile)
Definition: tw-opts.c:138
static const tw_optdef basic[]
Definition: tw-opts.c:411
static void match_opt(const char *arg)
Definition: tw-opts.c:378
static unsigned int opt_index
Definition: tw-opts.c:11
void tw_opt_parse(int *argc_p, char ***argv_p)
Definition: tw-opts.c:427
const char * name
Definition: tw-opts.h:22