From mboxrd@z Thu Jan 1 00:00:00 1970 From: Wei Liu Subject: [PATCH v5 20/24] libxlu: rework internal representation of setting Date: Thu, 12 Feb 2015 19:44:50 +0000 Message-ID: <1423770294-9779-21-git-send-email-wei.liu2@citrix.com> References: <1423770294-9779-1-git-send-email-wei.liu2@citrix.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1423770294-9779-1-git-send-email-wei.liu2@citrix.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel@lists.xen.org Cc: Wei Liu , ian.campbell@citrix.com, andrew.cooper3@citrix.com, dario.faggioli@citrix.com, ian.jackson@eu.citrix.com, JBeulich@suse.com, ufimtseva@gmail.com List-Id: xen-devel@lists.xenproject.org This patches does following things: 1. Properly define a XLU_ConfigList type. Originally it was defined to be XLU_ConfigSetting. 2. Define XLU_ConfigValue type, which can be either a string or a list of XLU_ConfigValue. 3. ConfigSetting now references XLU_ConfigValue. Originally it only worked with **string. 4. Properly construct list where necessary, see changes to .y file. To achieve above changes: 1. xlu__cfg_set_mk and xlu__cfg_set_add are deleted, because they are no more needed in the new code. 2. Introduce xlu__cfg_string_mk to make a XLU_ConfigSetting that points to a XLU_ConfigValue that wraps a string. 3. Introduce xlu__cfg_list_mk to make a XLU_ConfigSetting that points to XLU_ConfigValue that is a list. 4. The parser now generates XLU_ConfigValue instead of XLU_ConfigSetting when construct values, which enables us to recursively generate list of lists. 5. XLU_ConfigSetting is generated in xlu__cfg_set_store. 6. Adapt other functions to use new types. No change to public API. Xl compiles without problem and 'xl create -n guest.cfg' is valgrind clean. This patch is needed because we're going to implement nested list support, which requires support for list of list. Signed-off-by: Wei Liu Cc: Ian Jackson Cc: Ian Campbell --- Changes in v5: 1. Use standard expanding-array pattern. --- tools/libxl/libxlu_cfg.c | 170 ++++++++++++++++++++++++++++++------------ tools/libxl/libxlu_cfg_i.h | 12 ++- tools/libxl/libxlu_cfg_y.c | 24 +++--- tools/libxl/libxlu_cfg_y.h | 2 +- tools/libxl/libxlu_cfg_y.y | 14 ++-- tools/libxl/libxlu_internal.h | 30 ++++++-- 6 files changed, 173 insertions(+), 79 deletions(-) diff --git a/tools/libxl/libxlu_cfg.c b/tools/libxl/libxlu_cfg.c index 22adcb0..f000eed 100644 --- a/tools/libxl/libxlu_cfg.c +++ b/tools/libxl/libxlu_cfg.c @@ -131,14 +131,28 @@ int xlu_cfg_readdata(XLU_Config *cfg, const char *data, int length) { return ctx.err; } -void xlu__cfg_set_free(XLU_ConfigSetting *set) { +void xlu__cfg_value_free(XLU_ConfigValue *value) +{ int i; + if (!value) return; + + switch (value->type) { + case XLU_STRING: + free(value->u.string); + break; + case XLU_LIST: + for (i = 0; i < value->u.list.nvalues; i++) + xlu__cfg_value_free(value->u.list.values[i]); + free(value->u.list.values); + } + free(value); +} + +void xlu__cfg_set_free(XLU_ConfigSetting *set) { if (!set) return; free(set->name); - for (i=0; invalues; i++) - free(set->values[i]); - free(set->values); + xlu__cfg_value_free(set->value); free(set); } @@ -173,7 +187,7 @@ static int find_atom(const XLU_Config *cfg, const char *n, set= find(cfg,n); if (!set) return ESRCH; - if (set->avalues!=1) { + if (set->value->type!=XLU_STRING) { if (!dont_warn) fprintf(cfg->report, "%s:%d: warning: parameter `%s' is" @@ -191,7 +205,7 @@ int xlu_cfg_get_string(const XLU_Config *cfg, const char *n, int e; e= find_atom(cfg,n,&set,dont_warn); if (e) return e; - *value_r= set->values[0]; + *value_r= set->value->u.string; return 0; } @@ -202,7 +216,7 @@ int xlu_cfg_replace_string(const XLU_Config *cfg, const char *n, e= find_atom(cfg,n,&set,dont_warn); if (e) return e; free(*value_r); - *value_r= strdup(set->values[0]); + *value_r= strdup(set->value->u.string); return 0; } @@ -214,7 +228,7 @@ int xlu_cfg_get_long(const XLU_Config *cfg, const char *n, char *ep; e= find_atom(cfg,n,&set,dont_warn); if (e) return e; - errno= 0; l= strtol(set->values[0], &ep, 0); + errno= 0; l= strtol(set->value->u.string, &ep, 0); e= errno; if (errno) { e= errno; @@ -226,7 +240,7 @@ int xlu_cfg_get_long(const XLU_Config *cfg, const char *n, cfg->config_source, set->lineno, n, strerror(e)); return e; } - if (*ep || ep==set->values[0]) { + if (*ep || ep==set->value->u.string) { if (!dont_warn) fprintf(cfg->report, "%s:%d: warning: parameter `%s' is not a valid number\n", @@ -253,7 +267,7 @@ int xlu_cfg_get_list(const XLU_Config *cfg, const char *n, XLU_ConfigList **list_r, int *entries_r, int dont_warn) { XLU_ConfigSetting *set; set= find(cfg,n); if (!set) return ESRCH; - if (set->avalues==1) { + if (set->value->type!=XLU_LIST) { if (!dont_warn) { fprintf(cfg->report, "%s:%d: warning: parameter `%s' is a single value" @@ -262,8 +276,8 @@ int xlu_cfg_get_list(const XLU_Config *cfg, const char *n, } return EINVAL; } - if (list_r) *list_r= set; - if (entries_r) *entries_r= set->nvalues; + if (list_r) *list_r= &set->value->u.list; + if (entries_r) *entries_r= set->value->u.list.nvalues; return 0; } @@ -290,72 +304,130 @@ int xlu_cfg_get_list_as_string_list(const XLU_Config *cfg, const char *n, return 0; } -const char *xlu_cfg_get_listitem(const XLU_ConfigList *set, int entry) { - if (entry < 0 || entry >= set->nvalues) return 0; - return set->values[entry]; +const char *xlu_cfg_get_listitem(const XLU_ConfigList *list, int entry) { + if (entry < 0 || entry >= list->nvalues) return 0; + if (list->values[entry]->type != XLU_STRING) return 0; + return list->values[entry]->u.string; } -XLU_ConfigSetting *xlu__cfg_set_mk(CfgParseContext *ctx, - int alloc, char *atom) { - XLU_ConfigSetting *set= 0; +XLU_ConfigValue *xlu__cfg_string_mk(CfgParseContext *ctx, char *atom) +{ + XLU_ConfigValue *value = NULL; if (ctx->err) goto x; - assert(!!alloc == !!atom); - set= malloc(sizeof(*set)); - if (!set) goto xe; + value = malloc(sizeof(*value)); + if (!value) goto xe; + value->type = XLU_STRING; + value->u.string = atom; + + return value; - set->name= 0; /* tbd */ - set->avalues= alloc; + xe: + ctx->err= errno; + x: + free(value); + free(atom); + return NULL; +} - if (!alloc) { - set->nvalues= 0; - set->values= 0; - } else { - set->values= malloc(sizeof(*set->values) * alloc); - if (!set->values) goto xe; +XLU_ConfigValue *xlu__cfg_list_mk(CfgParseContext *ctx, char *atom) +{ + XLU_ConfigValue *value = NULL; + XLU_ConfigValue **values = NULL; + XLU_ConfigValue *val = NULL; - set->nvalues= 1; - set->values[0]= atom; - } - return set; + if (ctx->err) goto x; + + val = malloc(sizeof(*val)); + if (!val) goto xe; + val->type = XLU_STRING; + val->u.string = atom; + + values = malloc(sizeof(*values)); + if (!values) goto xe; + values[0] = val; + + value = malloc(sizeof(*value)); + if (!value) goto xe; + value->type = XLU_LIST; + value->u.list.nvalues = 1; + value->u.list.avalues = 1; + value->u.list.values = values; + + return value; xe: ctx->err= errno; x: - free(set); + free(value); + free(values); + free(val); free(atom); - return 0; + return NULL; } -void xlu__cfg_set_add(CfgParseContext *ctx, XLU_ConfigSetting *set, - char *atom) { +void xlu__cfg_list_append(CfgParseContext *ctx, + XLU_ConfigValue *list, + char *atom) +{ + XLU_ConfigValue *val = NULL; if (ctx->err) return; assert(atom); + assert(list->type == XLU_LIST); - if (set->nvalues >= set->avalues) { + if (list->u.list.nvalues >= list->u.list.avalues) { int new_avalues; - char **new_values; - - if (set->avalues > INT_MAX / 100) { ctx->err= ERANGE; return; } - new_avalues= set->avalues * 4; - new_values= realloc(set->values, - sizeof(*new_values) * new_avalues); - if (!new_values) { ctx->err= errno; free(atom); return; } - set->values= new_values; - set->avalues= new_avalues; + XLU_ConfigValue **new_values = NULL; + + if (list->u.list.avalues > INT_MAX / 100) { + ctx->err = ERANGE; + free(atom); + return; + } + + new_avalues = list->u.list.avalues * 4; + new_values = realloc(list->u.list.values, + sizeof(*new_values) * new_avalues); + if (!new_values) { + ctx->err = errno; + free(atom); + return; + } + + list->u.list.avalues = new_avalues; + list->u.list.values = new_values; + } + + val = malloc(sizeof(*val)); + if (!val) { + ctx->err = errno; + free(atom); + return; } - set->values[set->nvalues++]= atom; + + val->type = XLU_STRING; + val->u.string = atom; + list->u.list.values[list->u.list.nvalues] = val; + list->u.list.nvalues++; } void xlu__cfg_set_store(CfgParseContext *ctx, char *name, - XLU_ConfigSetting *set, int lineno) { + XLU_ConfigValue *val, int lineno) { + XLU_ConfigSetting *set; + if (ctx->err) return; assert(name); + set = malloc(sizeof(*set)); + if (!set) { + ctx->err = errno; + return; + } set->name= name; + set->value = val; set->lineno= lineno; set->next= ctx->cfg->settings; ctx->cfg->settings= set; diff --git a/tools/libxl/libxlu_cfg_i.h b/tools/libxl/libxlu_cfg_i.h index 54d033c..b71e9fd 100644 --- a/tools/libxl/libxlu_cfg_i.h +++ b/tools/libxl/libxlu_cfg_i.h @@ -23,11 +23,15 @@ #include "libxlu_cfg_y.h" void xlu__cfg_set_free(XLU_ConfigSetting *set); -XLU_ConfigSetting *xlu__cfg_set_mk(CfgParseContext*, int alloc, char *atom); -void xlu__cfg_set_add(CfgParseContext*, XLU_ConfigSetting *set, char *atom); void xlu__cfg_set_store(CfgParseContext*, char *name, - XLU_ConfigSetting *set, int lineno); - + XLU_ConfigValue *val, int lineno); +XLU_ConfigValue *xlu__cfg_string_mk(CfgParseContext *ctx, + char *atom); +XLU_ConfigValue *xlu__cfg_list_mk(CfgParseContext *ctx, char *atom); +void xlu__cfg_list_append(CfgParseContext *ctx, + XLU_ConfigValue *list, + char *atom); +void xlu__cfg_value_free(XLU_ConfigValue *value); char *xlu__cfgl_strdup(CfgParseContext*, const char *src); char *xlu__cfgl_dequote(CfgParseContext*, const char *src); diff --git a/tools/libxl/libxlu_cfg_y.c b/tools/libxl/libxlu_cfg_y.c index 07b5a1d..eb3884f 100644 --- a/tools/libxl/libxlu_cfg_y.c +++ b/tools/libxl/libxlu_cfg_y.c @@ -126,7 +126,7 @@ typedef union YYSTYPE #line 25 "libxlu_cfg_y.y" char *string; - XLU_ConfigSetting *setting; + XLU_ConfigValue *value; @@ -1148,7 +1148,7 @@ yydestruct (yymsg, yytype, yyvaluep, yylocationp, ctx) /* Line 1391 of yacc.c */ #line 43 "libxlu_cfg_y.y" - { xlu__cfg_set_free((yyvaluep->setting)); }; + { xlu__cfg_value_free((yyvaluep->value)); }; /* Line 1391 of yacc.c */ #line 1155 "libxlu_cfg_y.c" @@ -1166,7 +1166,7 @@ yydestruct (yymsg, yytype, yyvaluep, yylocationp, ctx) /* Line 1391 of yacc.c */ #line 43 "libxlu_cfg_y.y" - { xlu__cfg_set_free((yyvaluep->setting)); }; + { xlu__cfg_value_free((yyvaluep->value)); }; /* Line 1391 of yacc.c */ #line 1173 "libxlu_cfg_y.c" @@ -1175,7 +1175,7 @@ yydestruct (yymsg, yytype, yyvaluep, yylocationp, ctx) /* Line 1391 of yacc.c */ #line 43 "libxlu_cfg_y.y" - { xlu__cfg_set_free((yyvaluep->setting)); }; + { xlu__cfg_value_free((yyvaluep->value)); }; /* Line 1391 of yacc.c */ #line 1182 "libxlu_cfg_y.c" @@ -1508,21 +1508,21 @@ yyreduce: /* Line 1806 of yacc.c */ #line 57 "libxlu_cfg_y.y" - { xlu__cfg_set_store(ctx,(yyvsp[(1) - (3)].string),(yyvsp[(3) - (3)].setting),(yylsp[(3) - (3)]).first_line); } + { xlu__cfg_set_store(ctx,(yyvsp[(1) - (3)].string),(yyvsp[(3) - (3)].value),(yylsp[(3) - (3)]).first_line); } break; case 12: /* Line 1806 of yacc.c */ #line 62 "libxlu_cfg_y.y" - { (yyval.setting)= xlu__cfg_set_mk(ctx,1,(yyvsp[(1) - (1)].string)); } + { (yyval.value)= xlu__cfg_string_mk(ctx,(yyvsp[(1) - (1)].string)); } break; case 13: /* Line 1806 of yacc.c */ #line 63 "libxlu_cfg_y.y" - { (yyval.setting)= (yyvsp[(3) - (4)].setting); } + { (yyval.value)= (yyvsp[(3) - (4)].value); } break; case 14: @@ -1543,35 +1543,35 @@ yyreduce: /* Line 1806 of yacc.c */ #line 68 "libxlu_cfg_y.y" - { (yyval.setting)= xlu__cfg_set_mk(ctx,0,0); } + { (yyval.value)= xlu__cfg_list_mk(ctx,NULL); } break; case 17: /* Line 1806 of yacc.c */ #line 69 "libxlu_cfg_y.y" - { (yyval.setting)= (yyvsp[(1) - (1)].setting); } + { (yyval.value)= (yyvsp[(1) - (1)].value); } break; case 18: /* Line 1806 of yacc.c */ #line 70 "libxlu_cfg_y.y" - { (yyval.setting)= (yyvsp[(1) - (3)].setting); } + { (yyval.value)= (yyvsp[(1) - (3)].value); } break; case 19: /* Line 1806 of yacc.c */ #line 72 "libxlu_cfg_y.y" - { (yyval.setting)= xlu__cfg_set_mk(ctx,2,(yyvsp[(1) - (2)].string)); } + { (yyval.value)= xlu__cfg_list_mk(ctx,(yyvsp[(1) - (2)].string)); } break; case 20: /* Line 1806 of yacc.c */ #line 73 "libxlu_cfg_y.y" - { xlu__cfg_set_add(ctx,(yyvsp[(1) - (5)].setting),(yyvsp[(4) - (5)].string)); (yyval.setting)= (yyvsp[(1) - (5)].setting); } + { xlu__cfg_list_append(ctx,(yyvsp[(1) - (5)].value),(yyvsp[(4) - (5)].string)); (yyval.value)= (yyvsp[(1) - (5)].value); } break; diff --git a/tools/libxl/libxlu_cfg_y.h b/tools/libxl/libxlu_cfg_y.h index d7dfaf2..37e8213 100644 --- a/tools/libxl/libxlu_cfg_y.h +++ b/tools/libxl/libxlu_cfg_y.h @@ -54,7 +54,7 @@ typedef union YYSTYPE #line 25 "libxlu_cfg_y.y" char *string; - XLU_ConfigSetting *setting; + XLU_ConfigValue *value; diff --git a/tools/libxl/libxlu_cfg_y.y b/tools/libxl/libxlu_cfg_y.y index 5acd438..6848686 100644 --- a/tools/libxl/libxlu_cfg_y.y +++ b/tools/libxl/libxlu_cfg_y.y @@ -24,7 +24,7 @@ %union { char *string; - XLU_ConfigSetting *setting; + XLU_ConfigValue *value; } %locations @@ -39,8 +39,8 @@ %type atom %destructor { free($$); } atom IDENT STRING NUMBER -%type value valuelist values -%destructor { xlu__cfg_set_free($$); } value valuelist values +%type value valuelist values +%destructor { xlu__cfg_value_free($$); } value valuelist values %% @@ -59,18 +59,18 @@ assignment: IDENT '=' value { xlu__cfg_set_store(ctx,$1,$3,@3.first_line); } endstmt: NEWLINE | ';' -value: atom { $$= xlu__cfg_set_mk(ctx,1,$1); } +value: atom { $$= xlu__cfg_string_mk(ctx,$1); } | '[' nlok valuelist ']' { $$= $3; } atom: STRING { $$= $1; } | NUMBER { $$= $1; } -valuelist: /* empty */ { $$= xlu__cfg_set_mk(ctx,0,0); } +valuelist: /* empty */ { $$= xlu__cfg_list_mk(ctx,NULL); } | values { $$= $1; } | values ',' nlok { $$= $1; } -values: atom nlok { $$= xlu__cfg_set_mk(ctx,2,$1); } - | values ',' nlok atom nlok { xlu__cfg_set_add(ctx,$1,$4); $$= $1; } +values: atom nlok { $$= xlu__cfg_list_mk(ctx,$1); } + | values ',' nlok atom nlok { xlu__cfg_list_append(ctx,$1,$4); $$= $1; } nlok: /* nothing */ diff --git a/tools/libxl/libxlu_internal.h b/tools/libxl/libxlu_internal.h index 7579158..092a17a 100644 --- a/tools/libxl/libxlu_internal.h +++ b/tools/libxl/libxlu_internal.h @@ -23,17 +23,35 @@ #include #include -#define XLU_ConfigList XLU_ConfigSetting - #include "libxlutil.h" -struct XLU_ConfigSetting { /* transparent */ +enum XLU_ConfigValueType { + XLU_STRING, + XLU_LIST, +}; + +typedef struct XLU_ConfigValue XLU_ConfigValue; + +typedef struct XLU_ConfigList { + int avalues; /* available slots */ + int nvalues; /* actual occupied slots */ + XLU_ConfigValue **values; +} XLU_ConfigList; + +struct XLU_ConfigValue { + enum XLU_ConfigValueType type; + union { + char *string; + XLU_ConfigList list; + } u; +}; + +typedef struct XLU_ConfigSetting { /* transparent */ struct XLU_ConfigSetting *next; char *name; - int nvalues, avalues; /* lists have avalues>1 */ - char **values; + XLU_ConfigValue *value; int lineno; -}; +} XLU_ConfigSetting; struct XLU_Config { XLU_ConfigSetting *settings; -- 1.9.1