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 ...@@ -72,6 +72,14 @@ struct mu_cfg_node
72 struct mu_cfg_node *parent; /* parent node */ 72 struct mu_cfg_node *parent; /* parent node */
73 }; 73 };
74 74
75 struct mu_cfg_parse_hints
76 {
77 int flags;
78 char *site_rcfile;
79 char *custom_rcfile;
80 char *program;
81 };
82
75 struct mu_cfg_tree 83 struct mu_cfg_tree
76 { 84 {
77 mu_list_t nodes; /* a list of mu_cfg_node_t */ 85 mu_list_t nodes; /* a list of mu_cfg_node_t */
...@@ -80,7 +88,8 @@ struct mu_cfg_tree ...@@ -80,7 +88,8 @@ struct mu_cfg_tree
80 88
81 int mu_cfg_parse (mu_cfg_tree_t **ptree); 89 int mu_cfg_parse (mu_cfg_tree_t **ptree);
82 int mu_cfg_tree_union (mu_cfg_tree_t **pa, mu_cfg_tree_t **pb); 90 int mu_cfg_tree_union (mu_cfg_tree_t **pa, mu_cfg_tree_t **pb);
83 int mu_cfg_tree_postprocess (mu_cfg_tree_t *tree, int flags); 91 int mu_cfg_tree_postprocess (mu_cfg_tree_t *tree,
92 struct mu_cfg_parse_hints *hints);
84 93
85 extern struct mu_locus mu_cfg_locus; 94 extern struct mu_locus mu_cfg_locus;
86 95
...@@ -231,10 +240,16 @@ int mu_config_register_plain_section (const char *parent_path, ...@@ -231,10 +240,16 @@ int mu_config_register_plain_section (const char *parent_path,
231 const char *ident, 240 const char *ident,
232 struct mu_cfg_param *params); 241 struct mu_cfg_param *params);
233 242
234 #define MU_PARSE_CONFIG_GLOBAL 0x1 243 #define MU_PARSE_CONFIG_GLOBAL 0x001
235 #define MU_PARSE_CONFIG_VERBOSE 0x2 244 #define MU_PARSE_CONFIG_VERBOSE 0x002
236 #define MU_PARSE_CONFIG_DUMP 0x4 245 #define MU_PARSE_CONFIG_DUMP 0x004
237 #define MU_PARSE_CONFIG_PLAIN 0x8 246 #define MU_PARSE_CONFIG_PLAIN 0x008
247 #define MU_CFG_PARSE_SITE_RCFILE 0x010
248 #define MU_CFG_PARSE_CUSTOM_RCFILE 0x020
249 #define MU_CFG_PARSE_PROGRAM 0x040
250 #define MU_CFG_FMT_LOCUS 0x080
251 #define MU_CFG_FMT_VALUE_ONLY 0x100
252 #define MU_CFG_FMT_PARAM_PATH 0x200
238 253
239 #ifdef MU_CFG_COMPATIBILITY 254 #ifdef MU_CFG_COMPATIBILITY
240 # define MU_CFG_DEPRECATED 255 # define MU_CFG_DEPRECATED
...@@ -251,10 +266,6 @@ int mu_cfg_parse_boolean (const char *str, int *res); ...@@ -251,10 +266,6 @@ int mu_cfg_parse_boolean (const char *str, int *res);
251 extern int mu_cfg_parser_verbose; 266 extern int mu_cfg_parser_verbose;
252 extern size_t mu_cfg_error_count; 267 extern size_t mu_cfg_error_count;
253 268
254 #define MU_CFG_FMT_LOCUS 0x01
255 #define MU_CFG_FMT_VALUE_ONLY 0x02
256 #define MU_CFG_FMT_PARAM_PATH 0x04
257
258 void mu_cfg_format_docstring (mu_stream_t stream, const char *docstring, 269 void mu_cfg_format_docstring (mu_stream_t stream, const char *docstring,
259 int level); 270 int level);
260 void mu_cfg_format_parse_tree (mu_stream_t stream, struct mu_cfg_tree *tree, 271 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, ...@@ -295,6 +306,9 @@ int mu_cfg_find_node (mu_cfg_tree_t *tree, const char *path,
295 mu_cfg_node_t **pnode); 306 mu_cfg_node_t **pnode);
296 int mu_cfg_create_subtree (const char *path, mu_cfg_node_t **pnode); 307 int mu_cfg_create_subtree (const char *path, mu_cfg_node_t **pnode);
297 308
309 int mu_cfg_parse_config (mu_cfg_tree_t **ptree,
310 struct mu_cfg_parse_hints *hints);
311
298 #ifdef __cplusplus 312 #ifdef __cplusplus
299 } 313 }
300 #endif 314 #endif
......
...@@ -387,7 +387,12 @@ mu_get_config (const char *file, const char *progname, ...@@ -387,7 +387,12 @@ mu_get_config (const char *file, const char *progname,
387 int rc = mu_cfg_parse_file (&parse_tree, file, flags); 387 int rc = mu_cfg_parse_file (&parse_tree, file, flags);
388 if (rc == 0) 388 if (rc == 0)
389 { 389 {
390 rc = mu_cfg_tree_postprocess (parse_tree, flags); 390 struct mu_cfg_parse_hints hints;
391
392 hints.flags = flags | MU_CFG_PARSE_PROGRAM;
393 hints.program = progname;
394
395 rc = mu_cfg_tree_postprocess (parse_tree, &hints);
391 if (rc == 0) 396 if (rc == 0)
392 rc = mu_cfg_tree_reduce (parse_tree, progname, progparam, flags, 397 rc = mu_cfg_tree_reduce (parse_tree, progname, progparam, flags,
393 target_ptr); 398 target_ptr);
......
...@@ -165,16 +165,16 @@ mu_app_init (struct argp *myargp, const char **capa, ...@@ -165,16 +165,16 @@ mu_app_init (struct argp *myargp, const char **capa,
165 rc = mu_libcfg_parse_config (&parse_tree); 165 rc = mu_libcfg_parse_config (&parse_tree);
166 if (rc == 0) 166 if (rc == 0)
167 { 167 {
168 int cfgflags = MU_PARSE_CONFIG_PLAIN; 168 struct mu_cfg_parse_hints hints = { MU_PARSE_CONFIG_PLAIN };
169 169
170 if (mu_cfg_parser_verbose) 170 if (mu_cfg_parser_verbose)
171 cfgflags |= MU_PARSE_CONFIG_VERBOSE; 171 hints.flags |= MU_PARSE_CONFIG_VERBOSE;
172 if (mu_cfg_parser_verbose > 1) 172 if (mu_cfg_parser_verbose > 1)
173 cfgflags |= MU_PARSE_CONFIG_DUMP; 173 hints.flags |= MU_PARSE_CONFIG_DUMP;
174 mu_cfg_tree_postprocess (mu_argp_tree, cfgflags); 174 mu_cfg_tree_postprocess (mu_argp_tree, &hints);
175 mu_cfg_tree_union (&parse_tree, &mu_argp_tree); 175 mu_cfg_tree_union (&parse_tree, &mu_argp_tree);
176 rc = mu_cfg_tree_reduce (parse_tree, mu_program_name, cfg_param, 176 rc = mu_cfg_tree_reduce (parse_tree, mu_program_name, cfg_param,
177 cfgflags, data); 177 hints.flags, data);
178 } 178 }
179 179
180 if (mu_rcfile_lint) 180 if (mu_rcfile_lint)
......
...@@ -88,77 +88,34 @@ mu_libcfg_init (char **cnames) ...@@ -88,77 +88,34 @@ mu_libcfg_init (char **cnames)
88 int 88 int
89 mu_libcfg_parse_config (mu_cfg_tree_t **ptree) 89 mu_libcfg_parse_config (mu_cfg_tree_t **ptree)
90 { 90 {
91 int flags = 0; 91 struct mu_cfg_parse_hints hints;
92 int rc = 0; 92
93 mu_cfg_tree_t *tree = NULL, *tmp; 93 memset (&hints, 0, sizeof (hints));
94 94
95 if (mu_cfg_parser_verbose) 95 if (mu_cfg_parser_verbose)
96 flags |= MU_PARSE_CONFIG_VERBOSE; 96 hints.flags |= MU_PARSE_CONFIG_VERBOSE;
97 if (mu_cfg_parser_verbose > 1) 97 if (mu_cfg_parser_verbose > 1)
98 flags |= MU_PARSE_CONFIG_DUMP; 98 hints.flags |= MU_PARSE_CONFIG_DUMP;
99 99
100 if (mu_load_site_rcfile) 100 if (mu_load_site_rcfile)
101 { 101 {
102 rc = mu_cfg_parse_file (&tmp, MU_CONFIG_FILE, flags); 102 hints.flags |= MU_CFG_PARSE_SITE_RCFILE;
103 103 hints.site_rcfile = MU_CONFIG_FILE;
104 if (rc == ENOMEM)
105 {
106 mu_error ("%s", mu_strerror (rc));
107 return rc;
108 }
109 else if (rc == 0)
110 {
111 mu_cfg_tree_postprocess (tmp, flags | MU_PARSE_CONFIG_GLOBAL);
112 mu_cfg_tree_union (&tree, &tmp);
113 }
114 } 104 }
115 105
116 if (mu_load_user_rcfile && mu_program_name) 106 if (mu_load_user_rcfile && mu_program_name)
117 { 107 {
118 size_t size = 3 + strlen (mu_program_name) + 1; 108 hints.flags |= MU_CFG_PARSE_PROGRAM;
119 char *file_name = malloc (size); 109 hints.program = (char*) mu_program_name;
120 if (file_name)
121 {
122 strcpy (file_name, "~/.");
123 strcat (file_name, mu_program_name);
124
125 rc = mu_cfg_parse_file (&tmp, file_name, flags);
126 if (rc == ENOMEM)
127 {
128 mu_error ("%s", mu_strerror (rc));
129 mu_cfg_destroy_tree (&tree);
130 return rc;
131 }
132 else if (rc == 0)
133 {
134 mu_cfg_tree_postprocess (tmp, flags);
135 mu_cfg_tree_union (&tree, &tmp);
136 }
137 else if (rc == ENOENT)
138 rc = 0;
139 free (file_name);
140 }
141 } 110 }
142 111
143 if (mu_load_rcfile) 112 if (mu_load_rcfile)
144 { 113 {
145 rc = mu_cfg_parse_file (&tmp, mu_load_rcfile, flags); 114 hints.flags |= MU_CFG_PARSE_CUSTOM_RCFILE;
146 if (rc) 115 hints.custom_rcfile = mu_load_rcfile;
147 {
148 mu_error (_("errors parsing file %s: %s"), mu_load_rcfile,
149 mu_strerror (rc));
150 mu_cfg_destroy_tree (&tree);
151 return rc;
152 }
153 else
154 {
155 mu_cfg_tree_postprocess (tmp, flags);
156 mu_cfg_tree_union (&tree, &tmp);
157 }
158 } 116 }
159 117
160 *ptree = tree; 118 return mu_cfg_parse_config (ptree, &hints);
161 return rc;
162 } 119 }
163 120
164 121
......
...@@ -28,8 +28,8 @@ static char query_doc[] = N_("mu query - query configuration values."); ...@@ -28,8 +28,8 @@ static char query_doc[] = N_("mu query - query configuration values.");
28 char query_docstring[] = N_("query configuration values"); 28 char query_docstring[] = N_("query configuration values");
29 static char query_args_doc[] = N_("path [path...]"); 29 static char query_args_doc[] = N_("path [path...]");
30 30
31 char *file_name; 31 static char *file_name;
32 int fmtflags = 0; 32 static struct mu_cfg_parse_hints hints;
33 33
34 enum { 34 enum {
35 VALUE_OPTION = 256, 35 VALUE_OPTION = 256,
...@@ -43,6 +43,9 @@ static struct argp_option query_options[] = { ...@@ -43,6 +43,9 @@ static struct argp_option query_options[] = {
43 { "value", VALUE_OPTION, NULL, 0, 43 { "value", VALUE_OPTION, NULL, 0,
44 N_("display parameter values only"), 44 N_("display parameter values only"),
45 0 }, 45 0 },
46 { "program", 'p', N_("NAME"), 0,
47 N_("set program name for configuration lookup"),
48 0 },
46 { "path", PATH_OPTION, NULL, 0, 49 { "path", PATH_OPTION, NULL, 0,
47 N_("display parameters as paths") }, 50 N_("display parameters as paths") },
48 { "verbose", 'v', NULL, 0, 51 { "verbose", 'v', NULL, 0,
...@@ -59,16 +62,21 @@ query_parse_opt (int key, char *arg, struct argp_state *state) ...@@ -59,16 +62,21 @@ query_parse_opt (int key, char *arg, struct argp_state *state)
59 file_name = arg; 62 file_name = arg;
60 break; 63 break;
61 64
65 case 'p':
66 hints.flags |= MU_CFG_PARSE_PROGRAM;
67 hints.program = arg;
68 break;
69
62 case 'v': 70 case 'v':
63 fmtflags |= MU_CFG_FMT_LOCUS; 71 hints.flags |= MU_CFG_FMT_LOCUS;
64 break; 72 break;
65 73
66 case VALUE_OPTION: 74 case VALUE_OPTION:
67 fmtflags |= MU_CFG_FMT_VALUE_ONLY; 75 hints.flags |= MU_CFG_FMT_VALUE_ONLY;
68 break; 76 break;
69 77
70 case PATH_OPTION: 78 case PATH_OPTION:
71 fmtflags |= MU_CFG_FMT_PARAM_PATH; 79 hints.flags |= MU_CFG_FMT_PARAM_PATH;
72 break; 80 break;
73 81
74 default: 82 default:
...@@ -105,14 +113,10 @@ mutool_query (int argc, char **argv) ...@@ -105,14 +113,10 @@ mutool_query (int argc, char **argv)
105 return 1; 113 return 1;
106 } 114 }
107 115
108 if (file_name) 116 hints.flags |= MU_CFG_PARSE_SITE_RCFILE | MU_PARSE_CONFIG_GLOBAL;
109 { 117 hints.site_rcfile = file_name ? file_name : MU_CONFIG_FILE;
110 mu_load_site_rcfile = 0;
111 mu_load_user_rcfile = 0;
112 mu_load_rcfile = file_name;
113 }
114 118
115 if (mu_libcfg_parse_config (&tree)) 119 if (mu_cfg_parse_config (&tree, &hints))
116 return 1; 120 return 1;
117 if (!tree) 121 if (!tree)
118 return 0; 122 return 0;
...@@ -122,7 +126,7 @@ mutool_query (int argc, char **argv) ...@@ -122,7 +126,7 @@ mutool_query (int argc, char **argv)
122 mu_cfg_node_t *node; 126 mu_cfg_node_t *node;
123 127
124 if (mu_cfg_find_node (tree, path, &node) == 0) 128 if (mu_cfg_find_node (tree, path, &node) == 0)
125 mu_cfg_format_node (mu_strout, node, fmtflags); 129 mu_cfg_format_node (mu_strout, node, hints.flags);
126 } 130 }
127 return 0; 131 return 0;
128 } 132 }
......