Commit 4dda9b21 4dda9b21c67b6d03b852f57325cd0c88d266b463 by Sergey Poznyakoff

Introduce "parser hints", to provide better control over configuration parsing.

* include/mailutils/cfg.h (mu_cfg_parse_hints): New struct.
(mu_cfg_tree_postprocess): Change signature.  Last argument is
struct mu_cfg_parse_hints *.
(MU_CFG_PARSE_SITE_RCFILE,MU_CFG_PARSE_CUSTOM_RCFILE)
(MU_CFG_PARSE_PROGRAM): New flags.
(mu_cfg_parse_config): New proto.
* libmailutils/cfg/lexer.l (mu_get_config): Fix call to
mu_cfg_tree_postprocess.

* libmailutils/cfg/parser.y (do_include): Takes hints as 2nd argument.
(mu_cfg_tree_postprocess): Likewise.
(mu_cfg_parse_config): New function.

* libmu_cfg/init.c (mu_libcfg_parse_config): Rewrite as a wrapper
over mu_cfg_parse_config.
* libmu_argp/muinit.c (mu_app_init): Update.

* mu/query.c: New option --program.
(mutool_query): Use mu_cfg_parse_config interface.
1 parent d19d346f
......@@ -72,6 +72,14 @@ struct mu_cfg_node
struct mu_cfg_node *parent; /* parent node */
};
struct mu_cfg_parse_hints
{
int flags;
char *site_rcfile;
char *custom_rcfile;
char *program;
};
struct mu_cfg_tree
{
mu_list_t nodes; /* a list of mu_cfg_node_t */
......@@ -80,7 +88,8 @@ struct mu_cfg_tree
int mu_cfg_parse (mu_cfg_tree_t **ptree);
int mu_cfg_tree_union (mu_cfg_tree_t **pa, mu_cfg_tree_t **pb);
int mu_cfg_tree_postprocess (mu_cfg_tree_t *tree, int flags);
int mu_cfg_tree_postprocess (mu_cfg_tree_t *tree,
struct mu_cfg_parse_hints *hints);
extern struct mu_locus mu_cfg_locus;
......@@ -231,10 +240,16 @@ int mu_config_register_plain_section (const char *parent_path,
const char *ident,
struct mu_cfg_param *params);
#define MU_PARSE_CONFIG_GLOBAL 0x1
#define MU_PARSE_CONFIG_VERBOSE 0x2
#define MU_PARSE_CONFIG_DUMP 0x4
#define MU_PARSE_CONFIG_PLAIN 0x8
#define MU_PARSE_CONFIG_GLOBAL 0x001
#define MU_PARSE_CONFIG_VERBOSE 0x002
#define MU_PARSE_CONFIG_DUMP 0x004
#define MU_PARSE_CONFIG_PLAIN 0x008
#define MU_CFG_PARSE_SITE_RCFILE 0x010
#define MU_CFG_PARSE_CUSTOM_RCFILE 0x020
#define MU_CFG_PARSE_PROGRAM 0x040
#define MU_CFG_FMT_LOCUS 0x080
#define MU_CFG_FMT_VALUE_ONLY 0x100
#define MU_CFG_FMT_PARAM_PATH 0x200
#ifdef MU_CFG_COMPATIBILITY
# define MU_CFG_DEPRECATED
......@@ -251,10 +266,6 @@ int mu_cfg_parse_boolean (const char *str, int *res);
extern int mu_cfg_parser_verbose;
extern size_t mu_cfg_error_count;
#define MU_CFG_FMT_LOCUS 0x01
#define MU_CFG_FMT_VALUE_ONLY 0x02
#define MU_CFG_FMT_PARAM_PATH 0x04
void mu_cfg_format_docstring (mu_stream_t stream, const char *docstring,
int level);
void mu_cfg_format_parse_tree (mu_stream_t stream, struct mu_cfg_tree *tree,
......@@ -295,6 +306,9 @@ int mu_cfg_find_node (mu_cfg_tree_t *tree, const char *path,
mu_cfg_node_t **pnode);
int mu_cfg_create_subtree (const char *path, mu_cfg_node_t **pnode);
int mu_cfg_parse_config (mu_cfg_tree_t **ptree,
struct mu_cfg_parse_hints *hints);
#ifdef __cplusplus
}
#endif
......
......@@ -387,7 +387,12 @@ mu_get_config (const char *file, const char *progname,
int rc = mu_cfg_parse_file (&parse_tree, file, flags);
if (rc == 0)
{
rc = mu_cfg_tree_postprocess (parse_tree, flags);
struct mu_cfg_parse_hints hints;
hints.flags = flags | MU_CFG_PARSE_PROGRAM;
hints.program = progname;
rc = mu_cfg_tree_postprocess (parse_tree, &hints);
if (rc == 0)
rc = mu_cfg_tree_reduce (parse_tree, progname, progparam, flags,
target_ptr);
......
......@@ -289,16 +289,16 @@ vallist : vlist
;
vlist : value
{
int rc = mu_list_create (&$$);
if (rc)
{
mu_diag_at_locus (MU_LOG_ERROR, &mu_cfg_locus,
_("cannot create list: %s"),
mu_strerror (rc));
abort ();
}
mu_list_append ($$, config_value_dup (&$1)); /* FIXME */
{
int rc = mu_list_create (&$$);
if (rc)
{
mu_diag_at_locus (MU_LOG_ERROR, &mu_cfg_locus,
_("cannot create list: %s"),
mu_strerror (rc));
abort ();
}
mu_list_append ($$, config_value_dup (&$1)); /* FIXME */
}
| vlist value
{
......@@ -480,7 +480,8 @@ mu_cfg_tree_union (mu_cfg_tree_t **pa, mu_cfg_tree_t **pb)
}
static mu_cfg_tree_t *
do_include (const char *name, int flags, struct mu_locus *loc)
do_include (const char *name, struct mu_cfg_parse_hints *hints,
struct mu_locus *loc)
{
struct stat sb;
char *tmpname = NULL;
......@@ -498,21 +499,26 @@ do_include (const char *name, int flags, struct mu_locus *loc)
if (stat (name, &sb) == 0)
{
int rc = 0;
if (S_ISDIR (sb.st_mode))
{
if (flags & MU_PARSE_CONFIG_GLOBAL)
if ((hints->flags & (MU_PARSE_CONFIG_GLOBAL|MU_CFG_PARSE_PROGRAM)) ==
(MU_PARSE_CONFIG_GLOBAL|MU_CFG_PARSE_PROGRAM))
{
char *file = mu_make_file_name (name, mu_program_name);
rc = mu_cfg_parse_file (&tree, file, flags);
char *file = mu_make_file_name (name, hints->program);
rc = mu_cfg_parse_file (&tree, file, hints->flags);
free (file);
}
}
else
rc = mu_cfg_parse_file (&tree, name, flags);
rc = mu_cfg_parse_file (&tree, name, hints->flags);
if (rc == 0 && tree)
mu_cfg_tree_postprocess (tree, flags & ~MU_PARSE_CONFIG_GLOBAL);
{
struct mu_cfg_parse_hints xhints = *hints;
xhints.flags &= ~MU_PARSE_CONFIG_GLOBAL;
mu_cfg_tree_postprocess (tree, &xhints);
}
}
else if (errno == ENOENT)
{
......@@ -527,17 +533,18 @@ do_include (const char *name, int flags, struct mu_locus *loc)
mu_strerror (errno));
mu_cfg_error_count++;
}
free (tmpname);
return tree;
}
int
mu_cfg_tree_postprocess (mu_cfg_tree_t *tree, int flags)
mu_cfg_tree_postprocess (mu_cfg_tree_t *tree,
struct mu_cfg_parse_hints *hints)
{
int rc;
mu_iterator_t itr;
if (!tree->nodes)
return 0;
rc = mu_list_get_iterator (tree->nodes, &itr);
......@@ -547,18 +554,22 @@ mu_cfg_tree_postprocess (mu_cfg_tree_t *tree, int flags)
mu_iterator_next (itr))
{
mu_cfg_node_t *node;
mu_iterator_current (itr, (void**) &node);
if (node->type == mu_cfg_node_statement)
{
if ((flags & MU_PARSE_CONFIG_GLOBAL) &&
if ((hints->flags & MU_PARSE_CONFIG_GLOBAL) &&
strcmp (node->tag, "program") == 0)
{
if (node->label->type == MU_CFG_STRING)
{
if (strcmp (node->label->v.string, mu_program_name) == 0)
if ((hints->flags & MU_CFG_PARSE_PROGRAM)
&& strcmp (node->label->v.string, hints->program) == 0)
{
/* Reset the parent node */
mu_list_do (node->nodes, _node_set_parent,
node->parent);
/* Move all nodes from this block to the topmost
level */
mu_iterator_ctl (itr, mu_itrctl_insert_list,
......@@ -581,7 +592,8 @@ mu_cfg_tree_postprocess (mu_cfg_tree_t *tree, int flags)
{
if (node->label->type == MU_CFG_STRING)
{
mu_cfg_tree_t *t = do_include (node->label->v.string, flags,
mu_cfg_tree_t *t = do_include (node->label->v.string,
hints,
&node->locus);
if (t)
{
......@@ -598,7 +610,7 @@ mu_cfg_tree_postprocess (mu_cfg_tree_t *tree, int flags)
_("argument to `include' is not a string"));
mu_cfg_error_count++;
}
/* Remove node from the list */
mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
}
......@@ -611,12 +623,12 @@ _mu_cfg_preorder_recursive (void *item, void *cbdata)
{
mu_cfg_node_t *node = item;
struct mu_cfg_iter_closure *clos = cbdata;
switch (node->type)
{
case mu_cfg_node_undefined:
abort ();
case mu_cfg_node_statement:
switch (clos->beg (node, clos->data))
{
......@@ -626,15 +638,15 @@ _mu_cfg_preorder_recursive (void *item, void *cbdata)
if (clos->end && clos->end (node, clos->data) == MU_CFG_ITER_STOP)
return 1;
break;
case MU_CFG_ITER_SKIP:
break;
case MU_CFG_ITER_STOP:
return 1;
}
break;
case mu_cfg_node_param:
return clos->beg (node, clos->data) == MU_CFG_ITER_STOP;
}
......@@ -684,17 +696,17 @@ find_container (mu_list_t list, enum mu_cfg_cont_type type,
{
mu_iterator_t iter;
struct mu_cfg_cont *ret = NULL;
if (len == 0)
len = strlen (ident);
mu_list_get_iterator (list, &iter);
for (mu_iterator_first (iter); !mu_iterator_is_done (iter);
mu_iterator_next (iter))
{
struct mu_cfg_cont *cont;
mu_iterator_current (iter, (void**) &cont);
if (cont->type == type
&& strlen (cont->v.ident) == len
&& memcmp (cont->v.ident, ident, len) == 0)
......@@ -771,7 +783,7 @@ pop_section (struct scan_tree_data *dat)
#define STRTONUM(s, type, base, res, limit, d, loc) \
{ \
type sum = 0; \
\
\
for (; *s; s++) \
{ \
type x; \
......@@ -794,7 +806,7 @@ pop_section (struct scan_tree_data *dat)
else if (limit && x > limit) \
{ \
mu_diag_at_locus (MU_LOG_ERROR, loc, \
_("value out of allowed range")); \
_("value out of allowed range")); \
mu_cfg_error_count++; \
return 1; \
} \
......@@ -830,9 +842,9 @@ pop_section (struct scan_tree_data *dat)
STRxTONUM (s, type, tmpres, 0, d, loc); \
if (*s) \
{ \
mu_diag_at_locus (MU_LOG_ERROR, loc, \
_("not a number (stopped near `%s')"), \
s); \
mu_diag_at_locus (MU_LOG_ERROR, loc, \
_("not a number (stopped near `%s')"), \
s); \
mu_cfg_error_count++; \
return 1; \
} \
......@@ -845,7 +857,7 @@ pop_section (struct scan_tree_data *dat)
const char *s = str; \
int sign; \
unsigned type limit; \
\
\
if (*s == '-') \
{ \
sign++; \
......@@ -858,11 +870,11 @@ pop_section (struct scan_tree_data *dat)
sign = 0; \
limit = TYPE_MAXIMUM (type); \
} \
\
\
STRxTONUM (s, unsigned type, tmpres, limit, d, loc); \
if (*s) \
{ \
mu_diag_at_locus (MU_LOG_ERROR, loc, \
mu_diag_at_locus (MU_LOG_ERROR, loc, \
_("not a number (stopped near `%s')"), \
s); \
mu_cfg_error_count++; \
......@@ -918,7 +930,7 @@ parse_cidr (struct scan_tree_data *sdata, const struct mu_locus *locus,
unsigned long mask;
char astr[16];
const char *p, *s;
p = strchr (str, '/');
if (p)
{
......@@ -940,7 +952,7 @@ parse_cidr (struct scan_tree_data *sdata, const struct mu_locus *locus,
return 1;
}
addr.s_addr = ntohl (addr.s_addr);
p++;
s = p;
STRxTONUM (s, unsigned long, mask, 0, sdata->tree->debug, locus);
......@@ -975,7 +987,7 @@ parse_cidr (struct scan_tree_data *sdata, const struct mu_locus *locus,
int i;
unsigned short x;
addr.s_addr = 0;
p = str;
for (i = 0; i < 3; i++)
{
......@@ -984,7 +996,7 @@ parse_cidr (struct scan_tree_data *sdata, const struct mu_locus *locus,
break;
addr.s_addr = (addr.s_addr << 8) + x;
}
if (*p)
{
mu_diag_at_locus (MU_LOG_ERROR, &mu_cfg_locus,
......@@ -993,12 +1005,12 @@ parse_cidr (struct scan_tree_data *sdata, const struct mu_locus *locus,
mu_cfg_error_count++;
return 1;
}
mask = i * 8;
addr.s_addr <<= (4 - i) * 8;
}
res->addr = addr;
res->mask = mask;
return 0;
......@@ -1057,71 +1069,71 @@ valcvt (struct scan_tree_data *sdata, const struct mu_locus *locus,
*(char**)tgt = s;
break;
}
case mu_cfg_short:
GETSNUM (val->v.string, short, *(short*)tgt, sdata->tree->debug, locus);
break;
case mu_cfg_ushort:
GETUNUM (val->v.string, unsigned short, *(unsigned short*)tgt,
sdata->tree->debug, locus);
break;
case mu_cfg_int:
GETSNUM (val->v.string, int, *(int*)tgt, sdata->tree->debug, locus);
break;
case mu_cfg_uint:
GETUNUM (val->v.string, unsigned int, *(unsigned int*)tgt,
sdata->tree->debug, locus);
break;
case mu_cfg_long:
GETSNUM (val->v.string, long, *(long*)tgt,
sdata->tree->debug, locus);
break;
case mu_cfg_ulong:
GETUNUM (val->v.string, unsigned long, *(unsigned long*)tgt,
sdata->tree->debug, locus);
break;
case mu_cfg_size:
GETUNUM (val->v.string, size_t, *(size_t*)tgt,
sdata->tree->debug, locus);
break;
case mu_cfg_off:
mu_diag_at_locus (MU_LOG_ERROR, locus, _("not implemented yet"));
mu_cfg_error_count++;
/* GETSNUM(node->tag_label, off_t, *(off_t*)tgt); */
return 1;
case mu_cfg_time:
GETUNUM (val->v.string, time_t, *(time_t*)tgt,
sdata->tree->debug, locus);
break;
case mu_cfg_bool:
if (parse_bool (sdata, locus, val->v.string, (int*) tgt))
return 1;
break;
case mu_cfg_ipv4:
if (parse_ipv4 (sdata, locus, val->v.string, (struct in_addr *)tgt))
return 1;
break;
case mu_cfg_cidr:
if (parse_cidr (sdata, locus, val->v.string, (mu_cfg_cidr_t *)tgt))
return 1;
break;
case mu_cfg_host:
if (parse_host (sdata, locus, val->v.string, (struct in_addr *)tgt))
return 1;
break;
default:
return 1;
}
......@@ -1153,7 +1165,7 @@ static size_t config_type_size[] = {
sizeof (struct in_addr), /* mu_cfg_host */
0, /* mu_cfg_callback */
0, /* mu_cfg_section */
} ;
};
static int
_set_fun (void *item, void *data)
......@@ -1162,7 +1174,7 @@ _set_fun (void *item, void *data)
struct set_closure *clos = data;
void *tgt;
size_t size;
if (clos->type >= MU_ARRAY_SIZE(config_type_size)
|| (size = config_type_size[clos->type]) == 0)
{
......@@ -1172,7 +1184,7 @@ _set_fun (void *item, void *data)
mu_cfg_error_count++;
return 1;
}
tgt = mu_alloc (size);
if (!tgt)
{
......@@ -1180,7 +1192,7 @@ _set_fun (void *item, void *data)
mu_cfg_error_count++;
return 1;
}
if (valcvt (clos->sdata, clos->locus, &tgt, clos->type, val) == 0)
mu_list_append (clos->list, tgt);
return 0;
......@@ -1193,7 +1205,7 @@ parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node)
struct set_closure clos;
struct mu_cfg_param *param = find_param (sdata->list->sec, node->tag,
0);
if (!param)
{
mu_diag_at_locus (MU_LOG_ERROR, &node->locus,
......@@ -1202,7 +1214,7 @@ parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node)
mu_cfg_error_count++;
return 1;
}
if (param->data)
tgt = param->data;
else if (sdata->list->sec->target)
......@@ -1218,7 +1230,7 @@ parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node)
"%s"), param->ident);
abort ();
}
memset (&clos, 0, sizeof clos);
clos.type = MU_CFG_TYPE (param->type);
if (MU_CFG_IS_LIST (param->type))
......@@ -1229,7 +1241,7 @@ parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node)
{
case MU_CFG_LIST:
break;
case MU_CFG_STRING:
{
mu_list_t list;
......@@ -1239,14 +1251,14 @@ parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node)
node->label->v.list = list;
}
break;
case MU_CFG_ARRAY:
mu_diag_at_locus (MU_LOG_ERROR, &node->locus,
_("expected list, but found array"));
_("expected list, but found array"));
mu_cfg_error_count++;
return 1;
}
mu_list_create (&clos.list);
mu_list_do (node->label->v.list, _set_fun, &clos);
*(mu_list_t*)tgt = clos.list;
......@@ -1261,14 +1273,14 @@ parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node)
abort ();
}
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_LOCUS,
MU_IOCTL_LOGSTREAM_SET_LOCUS,
(void*) &node->locus);
if (param->callback (tgt, node->label))
return 1;
}
else
return valcvt (sdata, &node->locus, tgt, clos.type, node->label);
return 0;
}
......@@ -1278,12 +1290,12 @@ _scan_tree_helper (const mu_cfg_node_t *node, void *data)
{
struct scan_tree_data *sdata = data;
struct mu_cfg_section *sec;
switch (node->type)
{
case mu_cfg_node_undefined:
abort ();
case mu_cfg_node_statement:
sec = find_subsection (sdata->list->sec, node->tag, 0);
if (!sec)
......@@ -1305,7 +1317,7 @@ _scan_tree_helper (const mu_cfg_node_t *node, void *data)
if (sec->parser)
{
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_LOCUS,
MU_IOCTL_LOGSTREAM_SET_LOCUS,
(void*) &node->locus);
if (sec->parser (mu_cfg_section_start, node,
sec->label, &sec->target,
......@@ -1317,7 +1329,7 @@ _scan_tree_helper (const mu_cfg_node_t *node, void *data)
}
push_section(sdata, sec);
break;
case mu_cfg_node_param:
if (parse_param (sdata, node))
{
......@@ -1334,12 +1346,12 @@ _scan_tree_end_helper (const mu_cfg_node_t *node, void *data)
{
struct scan_tree_data *sdata = data;
struct mu_cfg_section *sec;
switch (node->type)
{
default:
abort ();
case mu_cfg_node_statement:
sec = pop_section (sdata);
if (sec && sec->parser)
......@@ -1358,7 +1370,7 @@ _scan_tree_end_helper (const mu_cfg_node_t *node, void *data)
int
mu_cfg_scan_tree (mu_cfg_tree_t *tree, struct mu_cfg_section *sections,
void *target, void *data)
void *target, void *data)
{
struct scan_tree_data dat;
struct mu_cfg_iter_closure clos;
......@@ -1370,15 +1382,15 @@ mu_cfg_scan_tree (mu_cfg_tree_t *tree, struct mu_cfg_section *sections,
dat.error = 0;
dat.call_data = data;
dat.target = target;
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_GET_MODE, &save_mode);
MU_IOCTL_LOGSTREAM_GET_MODE, &save_mode);
mode = save_mode | MU_LOGMODE_LOCUS;
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_GET_LOCUS, &save_locus);
MU_IOCTL_LOGSTREAM_GET_LOCUS, &save_locus);
if (push_section (&dat, sections))
return 1;
clos.beg = _scan_tree_helper;
......@@ -1386,11 +1398,11 @@ mu_cfg_scan_tree (mu_cfg_tree_t *tree, struct mu_cfg_section *sections,
clos.data = &dat;
mu_cfg_preorder (tree->nodes, &clos);
pop_section (&dat);
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_MODE, &save_mode);
MU_IOCTL_LOGSTREAM_SET_MODE, &save_mode);
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_LOCUS, &save_locus);
MU_IOCTL_LOGSTREAM_SET_LOCUS, &save_locus);
free (save_locus.mu_file);
return dat.error;
......@@ -1405,19 +1417,19 @@ mu_cfg_find_section (struct mu_cfg_section *root_sec,
struct mu_cfg_section *sec;
size_t len;
const char *p;
while (*path == MU_CFG_PATH_DELIM)
path++;
if (*path == 0)
return MU_ERR_NOENT;
p = strchr (path, MU_CFG_PATH_DELIM);
if (p)
len = p - path;
else
len = strlen (path);
sec = find_subsection (root_sec, path, len);
if (!sec)
return MU_ERR_NOENT;
......@@ -1452,7 +1464,7 @@ mu_cfg_tree_create_node (struct mu_cfg_tree *tree,
mu_cfg_node_t *np;
size_t size = sizeof *np + strlen (tag) + 1;
mu_config_value_t val;
np = mu_alloc (size);
np->type = type;
if (loc)
......@@ -1512,7 +1524,7 @@ mu_cfg_value_eq (mu_config_value_t *a, mu_config_value_t *b)
if (a->v.string == NULL)
return b->v.string == NULL;
return strcmp (a->v.string, b->v.string) == 0;
case MU_CFG_LIST:
{
int ret = 1;
......@@ -1524,7 +1536,7 @@ mu_cfg_value_eq (mu_config_value_t *a, mu_config_value_t *b)
mu_list_count (b->v.list, &i);
if (i != cnt)
return 1;
mu_list_get_iterator (a->v.list, &aitr);
mu_list_get_iterator (b->v.list, &bitr);
for (i = 0,
......@@ -1546,7 +1558,7 @@ mu_cfg_value_eq (mu_config_value_t *a, mu_config_value_t *b)
mu_iterator_destroy (&bitr);
return ret && i == cnt;
}
case MU_CFG_ARRAY:
if (a->v.arg.c == b->v.arg.c)
{
......@@ -1594,7 +1606,7 @@ split_cfg_path (const char *path, int *pargc, char ***pargv)
path++;
}
ws.ws_delim = delim;
if (mu_wordsplit (path, &ws, MU_WRDSF_DEFFLAGS|MU_WRDSF_DELIM))
{
mu_error (_("cannot split line `%s': %s"), path,
......@@ -1607,10 +1619,10 @@ split_cfg_path (const char *path, int *pargc, char ***pargv)
ws.ws_wordv = NULL;
mu_wordsplit_free (&ws);
}
*pargc = argc;
*pargv = argv;
return 0;
}
......@@ -1667,7 +1679,7 @@ parse_label (const char *str)
if (len > 1 && str[0] == '(' && str[len-1] == ')')
{
mu_list_t lst;
ws.ws_delim = ",";
if (mu_wordsplit_len (str + 1, len - 2, &ws,
MU_WRDSF_DEFFLAGS|MU_WRDSF_DELIM|MU_WRDSF_WS))
......@@ -1676,7 +1688,7 @@ parse_label (const char *str)
mu_wordsplit_strerror (&ws));
return NULL;
}
mu_list_create (&lst);
mu_list_set_destroy_item (lst, destroy_value);
for (i = 0; i < ws.ws_wordc; i++)
......@@ -1760,7 +1772,7 @@ mu_cfg_find_node (mu_cfg_tree_t *tree, const char *path, mu_cfg_node_t **pval)
{
int rc;
struct find_data data;
rc = split_cfg_path (path, &data.argc, &data.argv);
if (rc)
return rc;
......@@ -1768,9 +1780,9 @@ mu_cfg_find_node (mu_cfg_tree_t *tree, const char *path, mu_cfg_node_t **pval)
if (data.argc)
{
struct mu_cfg_iter_closure clos;
parse_tag (&data);
clos.beg = node_finder;
clos.end = NULL;
clos.data = &data;
......@@ -1796,15 +1808,15 @@ mu_cfg_create_subtree (const char *path, mu_cfg_node_t **pnode)
enum mu_cfg_node_type type;
mu_cfg_node_t *node = NULL;
struct mu_locus locus;
locus.mu_file = "<int>";
locus.mu_line = 0;
locus.mu_col = 0;
rc = split_cfg_path (path, &argc, &argv);
if (rc)
return rc;
for (i = argc - 1; i >= 0; i--)
{
mu_list_t nodelist = NULL;
......@@ -1841,12 +1853,84 @@ mu_cfg_create_subtree (const char *path, mu_cfg_node_t **pnode)
node->parent = parent;
node = parent;
}
mu_argcv_free (argc, argv);
*pnode = node;
return 0;
}
int
mu_cfg_parse_config (mu_cfg_tree_t **ptree, struct mu_cfg_parse_hints *hints)
{
int rc = 0;
mu_cfg_tree_t *tree = NULL, *tmp;
if ((hints->flags & MU_CFG_PARSE_SITE_RCFILE) && hints->site_rcfile)
{
rc = mu_cfg_parse_file (&tmp, hints->site_rcfile, hints->flags);
if (rc == ENOMEM)
{
mu_error ("%s", mu_strerror (rc));
return rc;
}
else if (rc == 0)
{
struct mu_cfg_parse_hints xhints = *hints;
xhints.flags |= MU_PARSE_CONFIG_GLOBAL;
mu_cfg_tree_postprocess (tmp, &xhints);
mu_cfg_tree_union (&tree, &tmp);
}
}
if ((hints->flags & MU_CFG_PARSE_PROGRAM) && hints->program)
{
size_t size = 3 + strlen (hints->program) + 1;
char *file_name = malloc (size);
if (file_name)
{
strcpy (file_name, "~/.");
strcat (file_name, hints->program);
rc = mu_cfg_parse_file (&tmp, file_name, hints->flags);
if (rc == ENOMEM)
{
mu_error ("%s", mu_strerror (rc));
mu_cfg_destroy_tree (&tree);
return rc;
}
else if (rc == 0)
{
mu_cfg_tree_postprocess (tmp, hints);
mu_cfg_tree_union (&tree, &tmp);
}
else if (rc == ENOENT)
rc = 0;
free (file_name);
}
}
if ((hints->flags & MU_CFG_PARSE_CUSTOM_RCFILE) && hints->custom_rcfile)
{
rc = mu_cfg_parse_file (&tmp, hints->custom_rcfile, hints->flags);
if (rc)
{
mu_error (_("errors parsing file %s: %s"), hints->custom_rcfile,
mu_strerror (rc));
mu_cfg_destroy_tree (&tree);
return rc;
}
else
{
mu_cfg_tree_postprocess (tmp, hints);
mu_cfg_tree_union (&tree, &tmp);
}
}
*ptree = tree;
return rc;
}
......
......@@ -165,16 +165,16 @@ mu_app_init (struct argp *myargp, const char **capa,
rc = mu_libcfg_parse_config (&parse_tree);
if (rc == 0)
{
int cfgflags = MU_PARSE_CONFIG_PLAIN;
struct mu_cfg_parse_hints hints = { MU_PARSE_CONFIG_PLAIN };
if (mu_cfg_parser_verbose)
cfgflags |= MU_PARSE_CONFIG_VERBOSE;
hints.flags |= MU_PARSE_CONFIG_VERBOSE;
if (mu_cfg_parser_verbose > 1)
cfgflags |= MU_PARSE_CONFIG_DUMP;
mu_cfg_tree_postprocess (mu_argp_tree, cfgflags);
hints.flags |= MU_PARSE_CONFIG_DUMP;
mu_cfg_tree_postprocess (mu_argp_tree, &hints);
mu_cfg_tree_union (&parse_tree, &mu_argp_tree);
rc = mu_cfg_tree_reduce (parse_tree, mu_program_name, cfg_param,
cfgflags, data);
hints.flags, data);
}
if (mu_rcfile_lint)
......
......@@ -88,77 +88,34 @@ mu_libcfg_init (char **cnames)
int
mu_libcfg_parse_config (mu_cfg_tree_t **ptree)
{
int flags = 0;
int rc = 0;
mu_cfg_tree_t *tree = NULL, *tmp;
struct mu_cfg_parse_hints hints;
memset (&hints, 0, sizeof (hints));
if (mu_cfg_parser_verbose)
flags |= MU_PARSE_CONFIG_VERBOSE;
hints.flags |= MU_PARSE_CONFIG_VERBOSE;
if (mu_cfg_parser_verbose > 1)
flags |= MU_PARSE_CONFIG_DUMP;
hints.flags |= MU_PARSE_CONFIG_DUMP;
if (mu_load_site_rcfile)
{
rc = mu_cfg_parse_file (&tmp, MU_CONFIG_FILE, flags);
if (rc == ENOMEM)
{
mu_error ("%s", mu_strerror (rc));
return rc;
}
else if (rc == 0)
{
mu_cfg_tree_postprocess (tmp, flags | MU_PARSE_CONFIG_GLOBAL);
mu_cfg_tree_union (&tree, &tmp);
}
hints.flags |= MU_CFG_PARSE_SITE_RCFILE;
hints.site_rcfile = MU_CONFIG_FILE;
}
if (mu_load_user_rcfile && mu_program_name)
{
size_t size = 3 + strlen (mu_program_name) + 1;
char *file_name = malloc (size);
if (file_name)
{
strcpy (file_name, "~/.");
strcat (file_name, mu_program_name);
rc = mu_cfg_parse_file (&tmp, file_name, flags);
if (rc == ENOMEM)
{
mu_error ("%s", mu_strerror (rc));
mu_cfg_destroy_tree (&tree);
return rc;
}
else if (rc == 0)
{
mu_cfg_tree_postprocess (tmp, flags);
mu_cfg_tree_union (&tree, &tmp);
}
else if (rc == ENOENT)
rc = 0;
free (file_name);
}
hints.flags |= MU_CFG_PARSE_PROGRAM;
hints.program = (char*) mu_program_name;
}
if (mu_load_rcfile)
{
rc = mu_cfg_parse_file (&tmp, mu_load_rcfile, flags);
if (rc)
{
mu_error (_("errors parsing file %s: %s"), mu_load_rcfile,
mu_strerror (rc));
mu_cfg_destroy_tree (&tree);
return rc;
}
else
{
mu_cfg_tree_postprocess (tmp, flags);
mu_cfg_tree_union (&tree, &tmp);
}
hints.flags |= MU_CFG_PARSE_CUSTOM_RCFILE;
hints.custom_rcfile = mu_load_rcfile;
}
*ptree = tree;
return rc;
return mu_cfg_parse_config (ptree, &hints);
}
......
......@@ -28,8 +28,8 @@ static char query_doc[] = N_("mu query - query configuration values.");
char query_docstring[] = N_("query configuration values");
static char query_args_doc[] = N_("path [path...]");
char *file_name;
int fmtflags = 0;
static char *file_name;
static struct mu_cfg_parse_hints hints;
enum {
VALUE_OPTION = 256,
......@@ -43,6 +43,9 @@ static struct argp_option query_options[] = {
{ "value", VALUE_OPTION, NULL, 0,
N_("display parameter values only"),
0 },
{ "program", 'p', N_("NAME"), 0,
N_("set program name for configuration lookup"),
0 },
{ "path", PATH_OPTION, NULL, 0,
N_("display parameters as paths") },
{ "verbose", 'v', NULL, 0,
......@@ -59,16 +62,21 @@ query_parse_opt (int key, char *arg, struct argp_state *state)
file_name = arg;
break;
case 'p':
hints.flags |= MU_CFG_PARSE_PROGRAM;
hints.program = arg;
break;
case 'v':
fmtflags |= MU_CFG_FMT_LOCUS;
hints.flags |= MU_CFG_FMT_LOCUS;
break;
case VALUE_OPTION:
fmtflags |= MU_CFG_FMT_VALUE_ONLY;
hints.flags |= MU_CFG_FMT_VALUE_ONLY;
break;
case PATH_OPTION:
fmtflags |= MU_CFG_FMT_PARAM_PATH;
hints.flags |= MU_CFG_FMT_PARAM_PATH;
break;
default:
......@@ -105,14 +113,10 @@ mutool_query (int argc, char **argv)
return 1;
}
if (file_name)
{
mu_load_site_rcfile = 0;
mu_load_user_rcfile = 0;
mu_load_rcfile = file_name;
}
hints.flags |= MU_CFG_PARSE_SITE_RCFILE | MU_PARSE_CONFIG_GLOBAL;
hints.site_rcfile = file_name ? file_name : MU_CONFIG_FILE;
if (mu_libcfg_parse_config (&tree))
if (mu_cfg_parse_config (&tree, &hints))
return 1;
if (!tree)
return 0;
......@@ -122,7 +126,7 @@ mutool_query (int argc, char **argv)
mu_cfg_node_t *node;
if (mu_cfg_find_node (tree, path, &node) == 0)
mu_cfg_format_node (mu_strout, node, fmtflags);
mu_cfg_format_node (mu_strout, node, hints.flags);
}
return 0;
}
......