Commit 6df5da42 authored by Jean-Claude BAU's avatar Jean-Claude BAU Committed by Adam Wujek

Configuration file parsing enhancement

- We can declare now a list of keyword for the parameter name :
it make the declaration of keywords more compact in conf.c and use less
memory (eg. "extension profile" )
- We can declare also a list of keywords for the parameter value
(eg. "true 1 on" = 1)
- Add the possibility to mark parameters set in the config file. It is
very important to know in some cases in order to apply the default value
or not.
- Decode other parameter types: boolean, double
parent ba107c11
......@@ -15,6 +15,7 @@
* Runtime options. Default values can be overridden by command line.
*/
struct pp_runtime_opts {
uint32_t updated_fields_mask;
ClockQuality clock_quality;
Integer32 ttl;
int flags; /* see below */
......@@ -130,6 +131,7 @@ enum { /* The two sockets. They are called "net path" for historical reasons */
* (see lib/conf.c). Actually, protocol and role are in the main ppi.
*/
struct pp_instance_cfg {
uint32_t updated_fields_mask;
char port_name[16];
char iface_name[16];
int profile; /* PPSI_PROFILE_PTP, PPSI_PROFILE_WR, PPSI_PROFILE_HA */
......
......@@ -289,6 +289,7 @@ union pp_cfg_arg {
int i2[2];
int64_t i64;
double d;
Boolean b;
char *s;
struct pp_cfg_time ts;
};
......@@ -315,26 +316,43 @@ enum pp_argtype {
ARG_DOUBLE,
ARG_INT64
};
/* This enumeration gives the list of instance options that should be marked when they are set in the configuration */
enum {
OPT_INST_NO_UPDATE=0,
OPT_INST_UPDATE_DESIRED_STATE, /* desiredState default value for HA is PASSIVE */
};
/* This enumeration gives the list of run-time options that should be marked when they are set in the configuration */
enum {
OPT_RT_NO_UPDATE=0,
};
struct pp_argline {
cfg_handler f;
char *keyword; /* Each line starts with a keyword */
enum pp_argtype t;
struct pp_argname *args;
size_t field_offset;
size_t updated_field_offset;
int updated_field_index; /* 0=not used , >0 = used to build bit mask 1<(index-1) */
int needs_port;
};
/* Below are macros for setting up pp_argline arrays */
#define OFFS(s,f) offsetof(s, f)
#define OPTION(s,func,k,typ,a,field,i) \
#define OPTION(s,func,k,typ,a,field,ufield,findex,np) \
{ \
.f = func, \
.keyword = k, \
.t = typ, \
.args = a, \
.field_offset = OFFS(s,field), \
.needs_port = i, \
.updated_field_offset=OFFS(s,ufield), \
.updated_field_index=findex,\
.needs_port = np, \
}
#define LEGACY_OPTION(func,k,typ) \
......@@ -344,31 +362,62 @@ struct pp_argline {
.t = typ, \
}
#define INST_OPTION(func,k,t,a,field) \
OPTION(struct pp_instance,func,k,t,a,field,1)
#define INST_OPTION(func,k,t,a,field,field_index) \
OPTION(struct pp_instance,func,k,t,a,field,cfg.updated_fields_mask,field_index,1)
#define INST_OPTION_INT_TRACK(k,t,a,field,field_index) \
INST_OPTION(f_simple_int,k,t,a,field,field_index)
#define INST_OPTION_INT(k,t,a,field) \
INST_OPTION(f_simple_int,k,t,a,field)
INST_OPTION_INT_TRACK(k,t,a,field,OPT_INST_NO_UPDATE)
#define INST_OPTION_BOOL_TRACK(k,field,field_index) \
INST_OPTION(f_simple_bool,k,ARG_NAMES,arg_bool,field,field_index)
#define INST_OPTION_BOOL(k,field) \
INST_OPTION_BOOL_TRACK(k,field,OPT_INST_NO_UPDATE)
#define INST_OPTION_INT64_TRACK(k,t,a,field,field_index) \
INST_OPTION(f_simple_int64,k,t,a,field,field_index)
#define INST_OPTION_INT64(k,t,a,field) \
INST_OPTION(f_simple_int64,k,t,a,field)
INST_OPTION_INT64_TRACK(k,t,a,field,OPT_INST_NO_UPDATE)
#define INST_OPTION_DOUBLE_TRACK(k,t,a,field,field_index) \
INST_OPTION(f_simple_double,k,t,a,field,field_index)
#define INST_OPTION_DOUBLE(k,t,a,field) \
INST_OPTION(f_simple_double,k,t,a,field)
INST_OPTION_DOUBLE_TRACK(k,t,a,field,OPT_INST_NO_UPDATE)
#define RT_OPTION(func,k,t,a,field) \
OPTION(struct pp_runtime_opts,func,k,t,a,field,0)
#define RT_OPTION(func,k,t,a,field,field_index) \
OPTION(struct pp_runtime_opts,func,k,t,a,field,updated_fields_mask,field_index,0)
#define GLOB_OPTION(func,k,t,a,field) \
OPTION(struct pp_globals,func,k,t,a,field,0)
OPTION(struct pp_globals,func,k,t,a,field,field,0,0)
#define RT_OPTION_INT_TRACK(k,t,a,field,field_index) \
RT_OPTION(f_simple_int,k,t,a,field,field_index)
#define RT_OPTION_INT(k,t,a,field) \
RT_OPTION(f_simple_int,k,t,a,field)
RT_OPTION_INT_TRACK(k,t,a,field,OPT_RT_NO_UPDATE)
#define RT_OPTION_BOOL_TRACK(k,field,field_index) \
RT_OPTION(f_simple_bool,k,ARG_NAMES,arg_bool,field,field_index)
#define RT_OPTION_BOOL(k,field) \
RT_OPTION(f_simple_bool,k,ARG_NAMES,arg_bool,field,OPT_RT_NO_UPDATE)
#define GLOB_OPTION_INT(k,t,a,field) \
GLOB_OPTION(f_simple_int,k,t,a,field)
#define IS_INST_OPTION_UPDATED(ppi, index) \
(( ppi->cfg.updated_fields_mask & (1 << (index-1)))!=0 )
#define IS_RT_OPTION_UPDATED(ppg, index) \
(( ppg->rt_opts.updated_fields_mask & (1 << (index-1)))!=0 )
/* Both the architecture and the extension can provide config arguments */
extern struct pp_argline pp_arch_arglines[];
extern struct pp_argline pp_ext_arglines[];
......
......@@ -64,12 +64,19 @@ static int f_port(struct pp_argline *l, int lineno, struct pp_globals *ppg,
return -1; \
}})
static inline void MARK_UPDATED_FIELD(struct pp_argline *l, struct pp_globals *ppg) {
if (l->updated_field_index )
*(uint32_t *)(((void *)CUR_PPI(ppg)) + l->updated_field_offset) |= 1<<(l->updated_field_index-1);
}
static inline void ASSIGN_INT_FIELD(struct pp_argline *l,
struct pp_globals *ppg,
int v)
int v)
{
if (l->needs_port)
if (l->needs_port) {
*(int *)(((void *)CUR_PPI(ppg)) + l->field_offset) = v;
MARK_UPDATED_FIELD(l,ppg);
}
else
*(int *)(((void *)GOPTS(ppg)) + l->field_offset) = v;
}
......@@ -86,8 +93,10 @@ static inline void ASSIGN_INT64_FIELD(struct pp_argline *l,
struct pp_globals *ppg,
int64_t v)
{
if (l->needs_port)
if (l->needs_port) {
*(int64_t *)(((void *)CUR_PPI(ppg)) + l->field_offset) = v;
MARK_UPDATED_FIELD(l,ppg);
}
else
*(int64_t *)(((void *)GOPTS(ppg)) + l->field_offset) = v;
}
......@@ -104,8 +113,10 @@ static inline void ASSIGN_DOUBLE_FIELD(struct pp_argline *l,
struct pp_globals *ppg,
double v)
{
if (l->needs_port)
if (l->needs_port) {
*(double *)(((void *)CUR_PPI(ppg)) + l->field_offset) = v;
MARK_UPDATED_FIELD(l,ppg);
}
else
*(double *)(((void *)GOPTS(ppg)) + l->field_offset) = v;
}
......@@ -118,6 +129,27 @@ static int f_simple_double( struct pp_argline *l, int lineno,
return 0;
}
static inline void ASSIGN_BOOL_FIELD(struct pp_argline *l,
struct pp_globals *ppg,
Boolean v)
{
if (l->needs_port) {
*(Boolean *)(((void *)CUR_PPI(ppg)) + l->field_offset) = v;
MARK_UPDATED_FIELD(l,ppg);
}
else
*(Boolean *)(((void *)GOPTS(ppg)) + l->field_offset) = v;
}
static int f_simple_bool( struct pp_argline *l, int lineno,
struct pp_globals *ppg, union pp_cfg_arg *arg)
{
CHECK_PPI(l->needs_port);
ASSIGN_BOOL_FIELD(l, ppg, arg->b);
return 0;
}
static int f_if(struct pp_argline *l, int lineno, struct pp_globals *ppg,
union pp_cfg_arg *arg)
{
......@@ -310,6 +342,13 @@ struct pp_argline pp_ext_arglines[] __attribute__((weak)) = {
{}
};
static struct pp_argline * pp_arglines[] = {
pp_global_arglines,
pp_arch_arglines,
pp_ext_arglines,
NULL
};
/* local implementation of isblank() and isdigit() for bare-metal users */
static int blank(int c)
{
......@@ -345,6 +384,26 @@ static char *first_word(char *line, char **rest)
return ret;
}
static int word_in_list(char *word, char *list) {
char listCopy[64];
char *next,*curr;
if ( strlen(list) > sizeof(listCopy)-1) {
pp_error("%s: List string too big (%d)\n", __func__, strlen(list));
return 0;
}
strcpy(listCopy, list);
next=listCopy;
while ( *next ) {
if ( (curr=first_word(next, &next))!=NULL ) {
if ( strcmp(curr,word)==0)
return 1;
}
}
return 0;
}
static int parse_time(struct pp_cfg_time *ts, char *s)
{
long sign = 1;
......@@ -404,6 +463,7 @@ static int pp_config_line(struct pp_globals *ppg, char *line, int lineno)
struct pp_argline *l;
struct pp_argname *n;
char *word;
int i;
pp_diag(NULL, config, 2, "parsing line %i: \"%s\"\n", lineno, line);
word = first_word(line, &line);
......@@ -430,22 +490,19 @@ static int pp_config_line(struct pp_globals *ppg, char *line, int lineno)
}
/* Look for the configuration keyword in global, arch, ext */
for (l = pp_global_arglines; l->f; l++)
if (!strcmp(word, l->keyword))
break;
if (!l->f)
for (l = pp_arch_arglines; l->f; l++)
if (!strcmp(word, l->keyword))
break;
if (!l->f)
for (l = pp_ext_arglines; l->f; l++)
if (!strcmp(word, l->keyword))
break;
if (!l->f) {
pp_error("line %i: no such keyword \"%s\"\n", lineno, word);
return -1;
for ( i=0; ;) {
if ( !(l=pp_arglines[i++] )) {
pp_error("line %i: no such keyword \"%s\"\n", lineno, word);
return -1;
}
while (l->f ) {
if ( word_in_list(word, l->keyword) )
goto keyword_found;
l++;
}
}
keyword_found:
if ((l->t != ARG_NONE) && (!*line)) {
pp_error("line %i: no argument for option \"%s\"\n", lineno,
......@@ -496,8 +553,8 @@ static int pp_config_line(struct pp_globals *ppg, char *line, int lineno)
case ARG_NAMES:
for (n = l->args; n->name; n++)
if (!strcmp(line, n->name))
break;
if ( word_in_list(line, n->name) )
break;
if (!n->name) {
pp_error("line %i: wrong arg \"%s\" for \"%s\"\n",
lineno, line, word);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment