Commit d19d346f d19d346f9e9822aa541c4860483045ecf4bea336 by Sergey Poznyakoff

mu: improve query interface.

* include/mailutils/cfg.h (mu_cfg_node) <parent>: New member.
(MU_CFG_FMT_VALUE_ONLY)
(MU_CFG_FMT_PARAM_PATH): New flags.
* libmailutils/cfg/format.c (format_path): New static.
(format_node,format_node_end): Handle new flags.
(mu_cfg_format_node): Clear MU_CFG_FMT_VALUE_ONLY if the
requested node is mu_cfg_node_statement.
* libmailutils/cfg/parser.y: Set node parents.
(mu_cfg_find_node): Fix coredump.
* mu/query.c: New options --value and --path.
1 parent 776056e2
......@@ -69,6 +69,7 @@ struct mu_cfg_node
char *tag;
mu_config_value_t *label;
mu_list_t nodes; /* a list of mu_cfg_node_t */
struct mu_cfg_node *parent; /* parent node */
};
struct mu_cfg_tree
......@@ -250,8 +251,10 @@ 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_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,
......
......@@ -129,6 +129,25 @@ format_value (struct tree_print *tp, mu_config_value_t *val)
}
}
static void
format_path (struct tree_print *tp, const mu_cfg_node_t *node, int delim)
{
char c;
if (node->parent)
format_path (tp, node->parent, MU_CFG_PATH_DELIM);
mu_stream_write (tp->stream, node->tag, strlen (node->tag), NULL);
if (node->type == mu_cfg_node_statement && node->label)
{
mu_stream_write (tp->stream, "=\"", 2, NULL);
format_value (tp, node->label);
mu_stream_write (tp->stream, "\"", 1, NULL);
}
c = delim;
mu_stream_write (tp->stream, &c, 1, NULL);
}
static int
format_node (const mu_cfg_node_t *node, void *data)
{
......@@ -147,25 +166,39 @@ format_node (const mu_cfg_node_t *node, void *data)
break;
case mu_cfg_node_statement:
{
mu_stream_write (tp->stream, node->tag, strlen (node->tag), NULL);
if (node->label)
{
mu_stream_write (tp->stream, " ", 1, NULL);
format_value (tp, node->label);
}
mu_stream_write (tp->stream, " {", 2, NULL);
tp->level++;
}
if (tp->flags & MU_CFG_FMT_PARAM_PATH)
return MU_CFG_ITER_OK;
else
{
mu_stream_write (tp->stream, node->tag, strlen (node->tag), NULL);
if (node->label)
{
mu_stream_write (tp->stream, " ", 1, NULL);
format_value (tp, node->label);
}
mu_stream_write (tp->stream, " {", 2, NULL);
tp->level++;
}
break;
case mu_cfg_node_param:
mu_stream_write (tp->stream, node->tag, strlen (node->tag), NULL);
if (node->label)
if (tp->flags & MU_CFG_FMT_VALUE_ONLY)
format_value (tp, node->label);
else if (tp->flags & MU_CFG_FMT_PARAM_PATH)
{
format_path (tp, node, ':');
mu_stream_write (tp->stream, " ", 1, NULL);
format_value (tp, node->label);
mu_stream_write (tp->stream, ";", 1, NULL);
}
else
{
mu_stream_write (tp->stream, node->tag, strlen (node->tag), NULL);
if (node->label)
{
mu_stream_write (tp->stream, " ", 1, NULL);
format_value (tp, node->label);
mu_stream_write (tp->stream, ";", 1, NULL);
}
}
break;
}
......@@ -177,9 +210,12 @@ static int
format_node_end (const mu_cfg_node_t *node, void *data)
{
struct tree_print *tp = data;
tp->level--;
format_level (tp->stream, tp->level);
mu_stream_write (tp->stream, "};\n", 3, NULL);
if (!(tp->flags & MU_CFG_FMT_PARAM_PATH))
{
tp->level--;
format_level (tp->stream, tp->level);
mu_stream_write (tp->stream, "};\n", 3, NULL);
}
return MU_CFG_ITER_OK;
}
......@@ -205,7 +241,9 @@ void
mu_cfg_format_node (mu_stream_t stream, const mu_cfg_node_t *node, int flags)
{
struct tree_print t;
if (node->type == mu_cfg_node_statement)
flags &= ~MU_CFG_FMT_VALUE_ONLY;
t.flags = flags;
t.level = 0;
t.stream = stream;
......
......@@ -77,6 +77,14 @@ config_value_dup (mu_config_value_t *src)
}
}
static int
_node_set_parent (void *item, void *data)
{
struct mu_cfg_node *node = item;
node->parent = data;
return 0;
}
static mu_cfg_node_t *
mu_cfg_alloc_node (enum mu_cfg_node_type type, struct mu_locus *loc,
const char *tag, mu_config_value_t *label,
......@@ -93,6 +101,7 @@ mu_cfg_alloc_node (enum mu_cfg_node_type type, struct mu_locus *loc,
strcpy (p, tag);
np->label = label;
np->nodes = nodelist;
np->parent = NULL;
return np;
}
......@@ -220,13 +229,12 @@ block : ident tag '{' '}' opt_sc
$$ = mu_cfg_alloc_node (mu_cfg_node_statement, &$1.locus,
$1.name, $2,
NULL);
}
| ident tag '{' stmtlist '}' opt_sc
{
$$ = mu_cfg_alloc_node (mu_cfg_node_statement, &$1.locus,
$1.name, $2, $4);
mu_list_do ($4, _node_set_parent, $$);
}
;
......@@ -1752,23 +1760,27 @@ mu_cfg_find_node (mu_cfg_tree_t *tree, const char *path, mu_cfg_node_t **pval)
{
int rc;
struct find_data data;
struct mu_cfg_iter_closure clos;
rc = split_cfg_path (path, &data.argc, &data.argv);
if (rc)
return rc;
data.tag = 0;
parse_tag (&data);
clos.beg = node_finder;
clos.end = NULL;
clos.data = &data;
rc = mu_cfg_preorder (tree->nodes, &clos);
destroy_value (data.label);
if (rc)
if (data.argc)
{
*pval = (mu_cfg_node_t *) data.node;
return 0;
struct mu_cfg_iter_closure clos;
parse_tag (&data);
clos.beg = node_finder;
clos.end = NULL;
clos.data = &data;
rc = mu_cfg_preorder (tree->nodes, &clos);
destroy_value (data.label);
if (rc)
{
*pval = (mu_cfg_node_t *) data.node;
return 0;
}
}
return MU_ERR_NOENT;
}
......@@ -1798,6 +1810,7 @@ mu_cfg_create_subtree (const char *path, mu_cfg_node_t **pnode)
mu_list_t nodelist = NULL;
mu_config_value_t *label = NULL;
char *q = argv[i], *p;
mu_cfg_node_t *parent;
type = mu_cfg_node_statement;
do
......@@ -1823,7 +1836,10 @@ mu_cfg_create_subtree (const char *path, mu_cfg_node_t **pnode)
mu_cfg_create_node_list (&nodelist);
mu_list_append (nodelist, node);
}
node = mu_cfg_alloc_node (type, &locus, argv[i], label, nodelist);
parent = mu_cfg_alloc_node (type, &locus, argv[i], label, nodelist);
if (node)
node->parent = parent;
node = parent;
}
mu_argcv_free (argc, argv);
......
......@@ -29,12 +29,22 @@ char query_docstring[] = N_("query configuration values");
static char query_args_doc[] = N_("path [path...]");
char *file_name;
int verbose_option;
int fmtflags = 0;
enum {
VALUE_OPTION = 256,
PATH_OPTION
};
static struct argp_option query_options[] = {
{ "file", 'f', N_("FILE"), 0,
N_("query configuration values from FILE (default mailutils.rc)"),
0 },
{ "value", VALUE_OPTION, NULL, 0,
N_("display parameter values only"),
0 },
{ "path", PATH_OPTION, NULL, 0,
N_("display parameters as paths") },
{ "verbose", 'v', NULL, 0,
N_("increase output verbosity"), 0},
{ NULL }
......@@ -50,7 +60,15 @@ query_parse_opt (int key, char *arg, struct argp_state *state)
break;
case 'v':
verbose_option++;
fmtflags |= MU_CFG_FMT_LOCUS;
break;
case VALUE_OPTION:
fmtflags |= MU_CFG_FMT_VALUE_ONLY;
break;
case PATH_OPTION:
fmtflags |= MU_CFG_FMT_PARAM_PATH;
break;
default:
......@@ -74,7 +92,6 @@ mutool_query (int argc, char **argv)
{
int index;
mu_cfg_tree_t *tree = NULL;
int fmtflags = 0;
if (argp_parse (&query_argp, argc, argv, ARGP_IN_ORDER, &index, NULL))
return 1;
......@@ -99,8 +116,6 @@ mutool_query (int argc, char **argv)
return 1;
if (!tree)
return 0;
if (verbose_option)
fmtflags = MU_CFG_FMT_LOCUS;
for ( ; argc > 0; argc--, argv++)
{
char *path = *argv;
......