MP-Gadget  5.0.1.dev1-76bc7d4726-dirty
paramset.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdint.h>
5 
6 #include "paramset.h"
7 #include "string.h"
8 #include "mymalloc.h"
9 #include "endrun.h"
10 
11 #define INT 1
12 #define DOUBLE 3
13 #define STRING 5
14 #define ENUM 10
15 #define NAMESIZE 128
16 
17 static int parse_enum(ParameterEnum * table, const char * strchoices) {
18  int value = 0;
19  ParameterEnum * p = table;
20  const char * delim = "\",;&| \t";
21  char * token;
22 
23  char * strchoices2 = fastpm_strdup(strchoices);
24  for(token = strtok(strchoices2, delim); token ; token = strtok(NULL, delim)) {
25  for(p = table; p->name; p++) {
26  if(strcasecmp(token, p->name) == 0) {
27  value |= p->value;
28  break;
29  }
30  }
31  if(p->name == NULL) {
32  /* error occured !*/
33  myfree(strchoices2);
34  return 0;
35  }
36  }
37  if(value == 0) {
38  /* none is specified, use default (NULL named entry) */
39  value = p->value;
40  }
41  myfree(strchoices2);
42  return value;
43 }
44 static char * format_enum(ParameterEnum * table, int value) {
45  int btotal = 200;
46  int bleft = btotal;
47  char * buffer = ta_malloc("formatbuffer", char, bleft);
48  ParameterEnum * p;
49  char * c = buffer;
50  int first = 1;
51  for(p = table; p->name && p->name[0]; p++) {
52  if((value & p->value) == p->value) {
53  if(!first) {
54  *(c++) = ' ';
55  *(c++) = '|';
56  *(c++) = ' ';
57  }
58  first = 0;
59  bleft-= strlen(p->name);
60  if (bleft <= 0) {
61  int extra = (- bleft) + btotal;
62  buffer = (char *) myrealloc(buffer, btotal + extra);
63  btotal += extra;
64  bleft += extra;
65  break;
66  }
67  /* The above ensures a large enough buffer*/
68  strcpy(c, p->name);
69  c += strlen(p->name);
70  }
71  }
72  return buffer;
73 }
74 
75 typedef struct ParameterValue {
76  int nil;
77  int i;
78  double d;
79  char * s;
80  int lineno;
82 
83 typedef struct ParameterSchema {
84  int index;
85  char name[NAMESIZE];
86  int type;
88  const char * help;
92  void * action_data;
94 
95 struct ParameterSet {
96  char * content;
97  int size;
100 };
101 
102 static ParameterSchema * param_get_schema(ParameterSet * ps, const char * name)
103 {
104  int i;
105  for(i = 0; i < ps->size; i ++) {
106  if(!strcasecmp(ps->p[i].name, name)) {
107  return &ps->p[i];
108  }
109  }
110  return NULL;
111 }
112 
113 static void
114 param_set_from_string(ParameterSet * ps, const char * name, char * value, int lineno);
115 
116 
117 static int param_emit(ParameterSet * ps, char * start, int size, int lineno)
118 {
119  /* parse a line */
120  if (size == 0) return 0;
121  char * buf = ta_malloc2("line", char, size + 1);
122  static char blanks[] = " \t\r\n=";
123  static char comments[] = "%#";
124  strncpy(buf, start, size);
125  buf[size] = 0;
126 
127  /* blank lines are OK */
128  const char * name = NULL;
129  char * value = NULL;
130  char * ptr = buf;
131 
132  /* parse name */
133  while(*ptr && strchr(blanks, *ptr)) ptr++;
134  if (*ptr == 0 || strchr(comments, *ptr)) {
135  /* This line is fully comment */
136  myfree(buf);
137  return 0;
138  }
139  name = ptr;
140  while(*ptr && !strchr(blanks, *ptr)) ptr++;
141  *ptr = 0;
142  ptr++;
143 
144  /* parse value */
145  while(*ptr && strchr(blanks, *ptr)) ptr++;
146 
147  if (*ptr == 0 || strchr(comments, *ptr)) {
148  /* This line is malformed, must have a value! */
149  strncpy(buf, start, size);
150  message(0, "Line %d : `%s` is malformed.\n", lineno, buf);
151  myfree(buf);
152  return 1;
153  }
154  value = ptr;
155  while(*ptr && !strchr(comments, *ptr)) ptr++;
156  *ptr = 0;
157  ptr++;
158 
159  /* now this line is important */
161  if(!p) {
162  message(0, "Line %d: Parameter `%s` is unknown.\n", lineno, name);
163  myfree(buf);
164  return 1;
165  }
166  param_set_from_string(ps, name, value, lineno);
167  if(p->action) {
168  if(0 != p->action(ps, name, p->action_data)) {
169  message(0, "Triggering Action on `%s` failed.\n", name);
170  myfree(buf);
171  return 1;
172  }
173  }
174  myfree(buf);
175  return 0;
176 }
178 {
179  int i;
180  int flag = 0;
181  /* copy over the default values */
182  for(i = 0; i < ps->size; i ++) {
183  ParameterSchema * p = &ps->p[i];
184  if(p->required == REQUIRED && ps->value[p->index].nil) {
185  message(0, "Parameter `%s` is required, but not set.\n", p->name);
186  flag = 1;
187  }
188  }
189  return flag;
190 }
191 
192 void param_dump(ParameterSet * ps, FILE * stream)
193 {
194  int i;
195  for(i = 0; i < ps->size; i ++) {
196  ParameterSchema * p = &ps->p[i];
197  char * v = param_format_value(ps, p->name);
198  if(ps->value[i].lineno >= 0) {
199  fprintf(stream, "%-31s %-20s # Line %03d # %s \n", p->name, v, ps->value[i].lineno, p->help);
200  } else {
201  fprintf(stream, "%-31s %-20s # Default # %s \n", p->name, v, p->help);
202  }
203  myfree(v);
204  }
205  fflush(stream);
206 }
207 
208 int param_parse (ParameterSet * ps, char * content)
209 {
210  int i;
211  /* copy over the default values, include nil values */
212  for(i = 0; i < ps->size; i ++) {
213  ps->value[ps->p[i].index] = ps->p[i].defvalue;
214  }
215  char * p = content;
216  char * p1 = content; /* begining of a line */
217  int flag = 0;
218  int lineno = 0;
219  while(1) {
220  if(*p == '\n' || *p == 0) {
221  int flag1 = param_emit(ps, p1, p - p1, lineno);
222  flag |= flag1;
223  if(*p == 0) break;
224  p++;
225  p1 = p;
226  lineno ++;
227  } else {
228  p++;
229  }
230  }
231  return flag;
232 }
233 
234 int param_parse_file (ParameterSet * ps, const char * filename)
235 {
236  char * content = fastpm_file_get_content(filename);
237  if(content == NULL) {
238  endrun(1, "Could not read file: %s\n", filename);
239  }
240  int val = param_parse(ps, content);
241 
242  myfree(content);
243  return val;
244 }
245 
246 static ParameterSchema *
247 param_declare(ParameterSet * ps, const char * name, const int type, const enum ParameterFlag required, const char * help)
248 {
249  int free = ps->size;
250  strncpy(ps->p[free].name, name, NAMESIZE);
251  //Make sure null terminated
252  ps->p[free].name[NAMESIZE-1] = '\0';
253  ps->p[free].required = required;
254  ps->p[free].type = type;
255  ps->p[free].index = free;
256  ps->p[free].defvalue.nil = 1;
257  ps->p[free].action = NULL;
258  ps->p[free].defvalue.s = NULL;
259  ps->p[free].defvalue.lineno = -1;
260  if(help)
261  ps->p[free].help = help;
262  ps->size ++;
263  return &ps->p[free];
264 }
265 
266 void
267 param_declare_int(ParameterSet * ps, const char * name, const enum ParameterFlag required, const int defvalue, const char * help)
268 {
269  ParameterSchema * p = param_declare(ps, name, INT, required, help);
270  if(required == OPTIONAL) {
271  p->defvalue.i = defvalue;
272  p->defvalue.nil = 0;
273  } else {
274  p->defvalue.nil = 1;
275  }
276 }
277 void
278 param_declare_double(ParameterSet * ps, const char * name, const enum ParameterFlag required, const double defvalue, const char * help)
279 {
280  ParameterSchema * p = param_declare(ps, name, DOUBLE, required, help);
281  if(required == OPTIONAL) {
282  p->defvalue.d = defvalue;
283  p->defvalue.nil = 0;
284  } else {
285  p->defvalue.nil = 1;
286  }
287 }
288 void
289 param_declare_string(ParameterSet * ps, const char * name, const enum ParameterFlag required, const char * defvalue, const char * help)
290 {
291  ParameterSchema * p = param_declare(ps, name, STRING, required, help);
292  if(required == OPTIONAL) {
293  if(defvalue != NULL) {
294  p->defvalue.s = fastpm_strdup(defvalue);
295  p->defvalue.nil = 0;
296  } else {
297  /* The handling of nil is not consistent yet! Only string can be non-required and have nil value.
298  * blame bad function signature (noway to define nil for int and double. */
299  p->defvalue.s = NULL;
300  p->defvalue.nil = 1;
301  }
302  } else {
303  p->defvalue.nil = 1;
304  }
305 }
306 void
307 param_declare_enum(ParameterSet * ps, const char * name, ParameterEnum * enumtable, const enum ParameterFlag required, const char * defvalue, const char * help)
308 {
309  ParameterSchema * p = param_declare(ps, name, ENUM, required, help);
310  p->enumtable = enumtable;
311  if(required == OPTIONAL) {
312  p->defvalue.i = parse_enum(enumtable, defvalue);
313  /* Watch out, if enumtable is malloced we may core dump if it gets freed */
314  p->defvalue.nil = 0;
315  } else {
316  p->defvalue.nil = 1;
317  }
318 }
319 
320 void
321 param_set_action(ParameterSet * ps, const char * name, ParameterAction action, void * userdata)
322 {
324  p->action = action;
325  p->action_data = userdata;
326 }
327 
328 int
329 param_is_nil(ParameterSet * ps, const char * name)
330 {
332  return ps->value[p->index].nil;
333 }
334 
335 double
336 param_get_double(ParameterSet * ps, const char * name)
337 {
339  if (param_is_nil(ps, name)) {
340  message(0, "Accessing an undefined parameter `%s`.\n", p->name);
341  }
342  return ps->value[p->index].d;
343 }
344 
345 char *
346 param_get_string(ParameterSet * ps, const char * name)
347 {
349  if (param_is_nil(ps, name)) {
350  message(0, "Accessing an undefined parameter `%s`.\n", p->name);
351  }
352  return ps->value[p->index].s;
353 }
354 void
355 param_get_string2(ParameterSet * ps, const char * name, char * dst, size_t len)
356 {
358  if (param_is_nil(ps, name)) {
359  message(0, "Accessing an undefined parameter `%s`.\n", p->name);
360  }
361  if(strlen(ps->value[p->index].s) > len)
362  endrun(1, "Parameter string %s too long for storage (%d)\n", ps->value[p->index].s, len);
363  strncpy(dst, ps->value[p->index].s, len);
364  dst[len-1]='\0';
365 }
366 
367 int
368 param_get_int(ParameterSet * ps, const char * name)
369 {
371  if (param_is_nil(ps, name)) {
372  message(0, "Accessing an undefined parameter `%s`.\n", p->name);
373  }
374  return ps->value[p->index].i;
375 }
376 
377 int
378 param_get_enum(ParameterSet * ps, const char * name)
379 {
381  if (param_is_nil(ps, name)) {
382  message(0, "Accessing an undefined parameter `%s`.\n", p->name);
383  }
384  return ps->value[p->index].i;
385 }
386 
387 char *
389 {
391  if(ps->value[p->index].nil) {
392  return fastpm_strdup("UNDEFINED");
393  }
394  switch(p->type) {
395  case INT:
396  {
397  int i = ps->value[p->index].i;
398  char buf[128];
399  snprintf(buf, 128, "%d", i);
400  return fastpm_strdup(buf);
401  }
402  break;
403  case DOUBLE:
404  {
405  double d = ps->value[p->index].d;
406  char buf[128];
407  snprintf(buf, 128, "%g", d);
408  return fastpm_strdup(buf);
409  }
410  break;
411  case STRING:
412  {
413  return fastpm_strdup(ps->value[p->index].s);
414  }
415  break;
416  case ENUM:
417  {
418  return format_enum(p->enumtable, ps->value[p->index].i);
419  }
420  break;
421  }
422  return fastpm_strdup("UNDEFINED TYPE");
423 }
424 
425 void
426 param_set_from_string(ParameterSet * ps, const char * name, char * value, int lineno)
427 {
429  ps->value[p->index].lineno = lineno;
430  switch(p->type) {
431  case INT:
432  {
433  int i;
434  sscanf(value, "%d", &i);
435  ps->value[p->index].i = i;
436  ps->value[p->index].nil = 0;
437  }
438  break;
439  case DOUBLE:
440  {
441  double d;
442  sscanf(value, "%lf", &d);
443  ps->value[p->index].d = d;
444  ps->value[p->index].nil = 0;
445  }
446  break;
447  case STRING:
448  {
449  while(*value == ' ') value ++;
450  ps->value[p->index].s = fastpm_strdup(value);
451  char * a = ps->value[p->index].s;
452  a += strlen(a) - 1;
453  while(*a == ' ') {
454  *a = 0;
455  a--;
456  }
457  ps->value[p->index].nil = 0;
458  }
459  break;
460  case ENUM:
461  {
462  char * v = fastpm_strdup(value);
463  ps->value[p->index].i = parse_enum(p->enumtable, v);
464  myfree(v);
465  ps->value[p->index].nil = 0;
466  }
467  break;
468  }
469 }
470 
471 ParameterSet *
473 {
474  ParameterSet * ps = ta_malloc("paramset", ParameterSet, 1);
475  ps->size = 0;
476  return ps;
477 }
478 
479 void
481  /* Just reset the temp heap,
482  * since that is where the paramset is allocated*/
483  ta_reset();
484  /* int i;
485  for(i = 0; i < ps->size; i ++) {
486  if(ps->p[i].help) {
487  myfree(ps->p[i].help);
488  }
489  if(ps->p[i].type == STRING) {
490  if(ps->p[i].defvalue.s) {
491  // FIXME: memory corruption
492 // free(ps->p[i].defvalue.s);
493  }
494  if(ps->value[ps->p[i].index].s != ps->p[i].defvalue.s) {
495  if(ps->value[ps->p[i].index].s) {
496 // free(ps->value[ps->p[i].index].s);
497  }
498  }
499  }
500  }
501  myfree(ps);
502  */
503 }
504 
const char * name
Definition: densitykernel.c:93
void message(int where, const char *fmt,...)
Definition: endrun.c:175
void endrun(int where, const char *fmt,...)
Definition: endrun.c:147
#define ta_malloc2(name, type, nele)
Definition: mymalloc.h:26
#define ta_malloc(name, type, nele)
Definition: mymalloc.h:25
#define myrealloc(ptr, size)
Definition: mymalloc.h:18
#define ta_reset()
Definition: mymalloc.h:27
#define myfree(x)
Definition: mymalloc.h:19
#define STRING
Definition: paramset.c:13
struct ParameterSchema ParameterSchema
static int parse_enum(ParameterEnum *table, const char *strchoices)
Definition: paramset.c:17
void param_declare_enum(ParameterSet *ps, const char *name, ParameterEnum *enumtable, const enum ParameterFlag required, const char *defvalue, const char *help)
Definition: paramset.c:307
double param_get_double(ParameterSet *ps, const char *name)
Definition: paramset.c:336
void param_get_string2(ParameterSet *ps, const char *name, char *dst, size_t len)
Definition: paramset.c:355
void parameter_set_free(ParameterSet *ps)
Definition: paramset.c:480
#define ENUM
Definition: paramset.c:14
void param_declare_double(ParameterSet *ps, const char *name, const enum ParameterFlag required, const double defvalue, const char *help)
Definition: paramset.c:278
struct ParameterValue ParameterValue
void param_declare_int(ParameterSet *ps, const char *name, const enum ParameterFlag required, const int defvalue, const char *help)
Definition: paramset.c:267
int param_parse_file(ParameterSet *ps, const char *filename)
Definition: paramset.c:234
static ParameterSchema * param_declare(ParameterSet *ps, const char *name, const int type, const enum ParameterFlag required, const char *help)
Definition: paramset.c:247
int param_get_int(ParameterSet *ps, const char *name)
Definition: paramset.c:368
void param_set_action(ParameterSet *ps, const char *name, ParameterAction action, void *userdata)
Definition: paramset.c:321
static char * format_enum(ParameterEnum *table, int value)
Definition: paramset.c:44
void param_declare_string(ParameterSet *ps, const char *name, const enum ParameterFlag required, const char *defvalue, const char *help)
Definition: paramset.c:289
#define DOUBLE
Definition: paramset.c:12
static int param_emit(ParameterSet *ps, char *start, int size, int lineno)
Definition: paramset.c:117
void param_dump(ParameterSet *ps, FILE *stream)
Definition: paramset.c:192
char * param_get_string(ParameterSet *ps, const char *name)
Definition: paramset.c:346
int param_is_nil(ParameterSet *ps, const char *name)
Definition: paramset.c:329
int param_parse(ParameterSet *ps, char *content)
Definition: paramset.c:208
char * param_format_value(ParameterSet *ps, const char *name)
Definition: paramset.c:388
int param_get_enum(ParameterSet *ps, const char *name)
Definition: paramset.c:378
static ParameterSchema * param_get_schema(ParameterSet *ps, const char *name)
Definition: paramset.c:102
#define NAMESIZE
Definition: paramset.c:15
static void param_set_from_string(ParameterSet *ps, const char *name, char *value, int lineno)
Definition: paramset.c:426
int param_validate(ParameterSet *ps)
Definition: paramset.c:177
ParameterSet * parameter_set_new()
Definition: paramset.c:472
#define INT
Definition: paramset.c:11
ParameterFlag
Definition: paramset.h:6
@ OPTIONAL
Definition: paramset.h:8
@ REQUIRED
Definition: paramset.h:7
int(* ParameterAction)(ParameterSet *ps, const char *name, void *userdata)
Definition: paramset.h:18
char * fastpm_file_get_content(const char *filename)
Definition: string.c:14
char * fastpm_strdup(const char *str)
Definition: string.c:31
const char * name
Definition: paramset.h:13
ParameterEnum * enumtable
Definition: paramset.c:90
enum ParameterFlag required
Definition: paramset.c:89
const char * help
Definition: paramset.c:88
char name[NAMESIZE]
Definition: paramset.c:85
ParameterValue defvalue
Definition: paramset.c:87
ParameterAction action
Definition: paramset.c:91
void * action_data
Definition: paramset.c:92
char * content
Definition: paramset.c:96
ParameterValue value[1024]
Definition: paramset.c:99
ParameterSchema p[1024]
Definition: paramset.c:98
double d
Definition: paramset.c:78
char * s
Definition: paramset.c:79
Definition: power.c:35