2 * Copyright (c) 2013, Olivier MATZ <zer0@droids-corp.org>
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the University of California, Berkeley nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include <cfzy_list.h>
36 #include <cfzy_conftree.h>
37 #include <cfzy_dotconfig.h>
38 #include <cfzy_c_hdr.h>
40 #define LOG(level, fmt, args...) \
41 CFZY_LOG("cfzy-basic", level, fmt, ##args)
43 /* Parsed arguments */
44 struct cfzy_arguments {
46 char *input_dotconfig;
47 char *output_dotconfig;
49 char *output_multi_c_hdr;
53 usage(const char *prog, int code)
58 " %s [options]\n", prog);
64 " set debug level (0: no log, 4 noisy)\n");
66 "-c, --input-conftree\n"
67 " path to input configuration tree file "
70 "-i, --input-dotconfig\n"
71 " path to input dotconfig file\n");
73 "-o, --output-dotconfig\n"
74 " path to output dotconfig file\n");
76 "-O, --output-c-hdr\n"
77 " path to output C header file\n");
79 "-m, --output-multi-c-hdr\n"
80 " path to output multiple C header directory\n");
85 free_args(struct cfzy_arguments *cfzy_args)
87 if (cfzy_args->input_conftree != NULL)
88 free(cfzy_args->input_conftree);
89 if (cfzy_args->input_dotconfig != NULL)
90 free(cfzy_args->input_dotconfig);
91 if (cfzy_args->output_dotconfig != NULL)
92 free(cfzy_args->output_dotconfig);
93 if (cfzy_args->output_c_hdr != NULL)
94 free(cfzy_args->output_c_hdr);
95 if (cfzy_args->output_multi_c_hdr != NULL)
96 free(cfzy_args->output_multi_c_hdr);
100 parse_args(struct cfzy_arguments *cfzy_args, int argc, char **argv)
103 const char * prog = argv[0];
106 static struct option lgopts[] = {
108 {"debug-level", 0, 0, 'd'},
109 {"input-conftree", 0, 0, 'c'},
110 {"input-dotconfig", 0, 0, 'i'},
111 {"output-dotconfig", 0, 0, 'o'},
112 {"output-c-hdr", 0, 0, 'O'},
113 {"output-multi-c-hdr", 0, 0, 'm'},
117 while ((ch = getopt_long(argc, argv,
119 "d:" /* debug-level */
120 "c:" /* input-conftree */
121 "i:" /* input-dotconfig */
122 "o:" /* output-dotconfig */
123 "O:" /* output-c-hdr */
124 "m:" /* output-multi-c-hdr */
126 lgopts, &option_index)) != -1) {
129 free_args(cfzy_args);
130 usage(prog, 0); /* will exit */
133 case 'd': /* debug-level */
134 level = atoi(optarg);
135 if (level < 0 || level > CFZY_LOG_DEBUG) {
136 LOG(ERR, "invalid log level\n");
137 free_args(cfzy_args);
141 cfzy_log_set_default_level(level);
144 case 'c': /* input-conftree */
145 cfzy_args->input_conftree = strdup(optarg);
146 if (cfzy_args->input_conftree == NULL) {
147 LOG(ERR, "Cannot alloc input conftree str\n");
148 free_args(cfzy_args);
154 case 'i': /* input-dotconfig */
155 cfzy_args->input_dotconfig = strdup(optarg);
156 if (cfzy_args->input_dotconfig == NULL) {
157 LOG(ERR, "Cannot alloc input dotconfig str\n");
158 free_args(cfzy_args);
164 case 'o': /* output-dotconfig */
165 cfzy_args->output_dotconfig = strdup(optarg);
166 if (cfzy_args->output_dotconfig == NULL) {
167 LOG(ERR, "Cannot alloc output dotconfig str\n");
168 free_args(cfzy_args);
174 case 'O': /* output-c-hdr */
175 cfzy_args->output_c_hdr = strdup(optarg);
176 if (cfzy_args->output_c_hdr == NULL) {
177 LOG(ERR, "Cannot alloc output c_hdr str\n");
178 free_args(cfzy_args);
184 case 'm': /* output-multi-c-hdr */
185 cfzy_args->output_multi_c_hdr = strdup(optarg);
186 if (cfzy_args->output_multi_c_hdr == NULL) {
187 LOG(ERR, "Cannot alloc output multi_c_hdr str\n");
188 free_args(cfzy_args);
195 LOG(ERR, "invalid option\n");
196 free_args(cfzy_args);
198 usage(prog, 1); /* will exit */
202 /* conftree file is mandatory */
203 if (cfzy_args->input_conftree == NULL) {
204 LOG(ERR, "input conftree is mandatory\n");
205 free_args(cfzy_args);
207 usage(prog, 1); /* will exit */
210 /* check that at least one output argument is given */
211 if (cfzy_args->output_dotconfig == NULL &&
212 cfzy_args->output_c_hdr == NULL &&
213 cfzy_args->output_multi_c_hdr == NULL) {
214 LOG(ERR, "at least one output argument is needed\n");
215 free_args(cfzy_args);
217 usage(prog, 1); /* will exit */
234 * ?? output autoconf.h
236 * output config/xxx.h
241 * prompt for options that have no user value
244 * set all options that have no user value to default
253 * set all options to a random value (only for booleans, other
254 * values are set to default)
257 * set all options to y (booleans only)
260 * set all options to n (booleans only)
262 * - ouvrir le fichier conftree
263 * - si -i, ouvrir .config
264 * - effectue les operations
265 * - si -o et/ou ... output
269 do_configuration(struct cfzy_arguments *cfzy_args)
271 struct cfzy_confnode *n;
272 struct cfzy_conftree *conftree;
277 /* parse configuration tree */
278 conftree = cfzy_conftree_new(cfzy_args->input_conftree);
279 if (conftree == NULL) {
280 LOG(ERR, "Cannot parse configuration tree\n");
284 /* parse .config if provided */
285 if (cfzy_args->input_dotconfig != NULL &&
286 cfzy_dotconfig_read(conftree, cfzy_args->input_dotconfig) < 0) {
287 cfzy_conftree_free(conftree);
288 LOG(ERR, "Cannot parse dotconfig <%s>\n",
289 cfzy_args->input_dotconfig);
294 /* evaluate effective values of conftree */
295 if (cfzy_conftree_evaluate(conftree) < 0) {
296 cfzy_conftree_free(conftree);
297 LOG(ERR, "Cannot evaluate configuration tree\n");
302 memset(buf, 0, sizeof(buf));
304 /* browse all nodes following priority list and prompt user */
305 TAILQ_FOREACH(n, &conftree->prio_list, prio_next) {
307 if (n->flags & CFZY_F_INVISIBLE)
309 if (n->flags & CFZY_F_NO_NAME)
312 /* node has a user value or user value cannot be set,
314 if ((n->user_value != NULL) || (n->flags & CFZY_F_NO_SET_VALUE)) {
315 /* XXX we should have a difference between
316 * NO_VALUE (menu for instance) and
318 cfzy_confnode_evaluate(n);
319 printf("%s=%s\n", cfzy_confnode_name(n),
324 /* node cannot be enabled due to deps */
325 ret = cfzy_confnode_check_deps(n);
327 cfzy_confnode_evaluate(n);
328 printf("%s=%s\n", cfzy_confnode_name(n),
333 LOG(ERR, "Cannot check deps\n");
337 /* ok, now prompt user */
339 cfzy_confnode_dump(n, stdout, CFZY_DUMP_MODE_STANDARD);
342 printf("Enter user value for %s > ",
343 cfzy_confnode_name(n));
346 fgets(buf, sizeof(buf) - 1, stdin);
350 /* empty buf means default value */
351 if (strcmp(buf, "") == 0)
354 /* invalid value, prompt again */
355 if (cfzy_confnode_set_uservalue(n, buf) < 0) {
356 printf("invalid value\n");
363 cfzy_confnode_evaluate(n);
364 printf("%s=%s\n", cfzy_confnode_name(n),
368 /* output .config if provided */
369 if (cfzy_args->output_dotconfig != NULL &&
370 cfzy_dotconfig_write(conftree, cfzy_args->output_dotconfig) < 0) {
371 cfzy_conftree_free(conftree);
372 LOG(ERR, "Cannot output dotconfig <%s>\n",
373 cfzy_args->output_dotconfig);
377 /* output C header if provided */
378 if (cfzy_args->output_c_hdr != NULL &&
379 cfzy_c_hdr_write(conftree, cfzy_args->output_c_hdr) < 0) {
380 cfzy_conftree_free(conftree);
381 LOG(ERR, "Cannot output C header <%s>\n",
382 cfzy_args->output_c_hdr);
386 /* output multiple C headers if provided */
387 if (cfzy_args->output_multi_c_hdr != NULL &&
388 cfzy_multi_c_hdr_write(conftree, cfzy_args->output_multi_c_hdr) < 0) {
389 cfzy_conftree_free(conftree);
390 LOG(ERR, "Cannot output multiple C headers <%s>\n",
391 cfzy_args->output_multi_c_hdr);
395 cfzy_conftree_free(conftree);
399 int main(int argc, char **argv)
401 int ret = EXIT_SUCCESS;
402 struct cfzy_arguments cfzy_args;
404 /* XXX a cfzy_init() would be better */
407 memset(&cfzy_args, 0, sizeof(cfzy_args));
409 /* argument parsing is always successful (will exit on error) */
410 parse_args(&cfzy_args, argc, argv);
412 /* do the configuration */
413 if (do_configuration(&cfzy_args) < 0) {
414 LOG(ERR, "Configuration failed");
418 free_args(&cfzy_args);