10 #include "kconfig/lkc.h"
11 #include "lcp_utils.h"
29 printf("kconfig2sat [ options ]\n"
32 "-b, --baseconf <.config> Linux .config file with base configuration\n"
33 "--env <.conf.mk> .conf.mk file for setting variables such as ARCH\n"
34 "-k, --kconfig <Kconfig> Kconfig file (with path)\n"
35 "--varfile <file> File listing variable options (one option per line)\n"
36 "--cnf <file> Generate CNF representation to <file>\n"
40 int main(int argc, char **argv)
44 char *baseconf = NULL;
51 static struct option long_options[] = {
52 {"baseconf", required_argument, 0, OPT_BASECONFIG },
53 {"cnf", required_argument, 0, OPT_CNF },
54 {"env", required_argument, 0, OPT_ENV },
55 {"help", no_argument, 0, OPT_HELP },
56 {"kconfig", required_argument, 0, OPT_KCONFIG },
57 {"varfile", required_argument, 0, OPT_VARFILE },
58 // {"varopt", required_argument, 0, OPT_VAROPTION },
59 {"verbose", no_argument, 0, OPT_VERBOSE },
63 c = getopt_long(argc, argv, "b:hk:v",
64 long_options, &option_index);
77 set_missing_env(optarg);
98 printf("?? getopt returned character code 0%o ??\n", c);
103 fprintf(stderr, "Unexpected option '%s'\n", argv[optind]);
109 if (kconfig == NULL) {
110 fprintf(stderr, "--kconfig option missing\n");
114 setlocale(LC_ALL, "");
115 bindtextdomain(PACKAGE, LOCALEDIR);
118 conf_parse_path(kconfig);
120 // char *rules_file, *symbol_map_file, *variable_count_file;
121 // asprintf(&rules_file, "%s/%s", folder, DEFAULT_RULES_FILE);
122 // asprintf(&symbol_map_file, "%s/%s", folder, DEFAULT_SYMBOL_MAP_FILE);
123 // asprintf(&variable_count_file, "%s/%s", folder,
124 // DEFAULT_VARIABLE_COUNT_FILE);
125 // output_init(rules_file, symbol_map_file);
130 // output_write_variable_count(variable_count_file,
131 // gsymlist->lastsym - 1, gsymlist->pos);
139 void build_symlist() {
142 struct property *prop;
143 for_all_symbols(i, sym) {
144 if (sym->type == S_BOOLEAN || sym->type == S_TRISTATE) {
145 if (sym->name == NULL)
146 asprintf(&sym->name, "NONAMEGEN%d", noname_num++);
148 symlist_add(gsymlist, sym->name);
151 symlist_closesym(gsymlist);
154 /* TODO: Split to smaller functions with meaningful names */
158 struct property *prop;
159 struct symlist_el *el;
161 struct boolexpr *boolsym;
162 for_all_symbols(i, sym) {
163 if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
165 el_id = symlist_id(gsymlist, sym->name);
166 el = &(gsymlist->array[el_id - 1]);
167 boolsym = boolexpr_sym(gsymlist, sym, false, NULL);
168 Iprintf("Processing: %s\n", sym->name);
170 for_all_prompts(sym, prop) {
171 Dprintf(" Prompt: %s\n", prop->text);
172 if (prop->visible.expr != NULL) {
173 doutput_expr(prop->visible.expr);
174 struct boolexpr *vis =
175 boolexpr_kconfig(gsymlist, prop->visible.expr,
177 if (el->vis == NULL) {
180 el->vis = boolexpr_or(el->vis, vis);
182 } else if (el->vis == NULL) {
183 el->vis = boolexpr_true();
187 el->vis = boolexpr_false();
188 // Symbol is choice.. special treatment required
189 if (sym_is_choice(sym)) {
190 Dprintf(" Is Choice\n");
191 goto choice_exception;
194 struct boolexpr **defexpr = NULL;
195 size_t defexpr_size = 0;
197 bool exitdef = false;
198 for_all_defaults(sym, prop) {
199 Dprintf(" Default value:\n");
200 doutput_expr(prop->expr);
201 struct boolexpr *def =
202 boolexpr_kconfig(gsymlist, prop->expr, true, NULL);
203 struct boolexpr *vis;
204 if (prop->visible.expr != NULL)
205 vis = boolexpr_kconfig(gsymlist, prop->visible.expr,
208 vis = boolexpr_true();
209 if (vis->type != BT_TRUE) {
210 defexpr = realloc(defexpr,
211 ++defexpr_size * sizeof(struct boolexpr *));
212 defexpr[defexpr_size - 1] = boolexpr_copy(vis);
217 def = boolexpr_and(def, vis);
218 for (z = 0; z < ((int)defexpr_size - 1); z++) {
219 def = boolexpr_and(def, boolexpr_not(
220 boolexpr_copy(defexpr[z])));
225 el->def = boolexpr_or(el->def, def);
229 if (defexpr != NULL) {
230 for (z = 0; z < defexpr_size - 1; z++) {
231 boolexpr_free(defexpr[z]);
236 el->def = boolexpr_false();
237 // Dependency expression
238 if (sym->dir_dep.expr != NULL) {
239 Dprintf(" Dependency:\n");
240 doutput_expr(sym->dir_dep.expr);
242 boolexpr_kconfig(gsymlist, sym->dir_dep.expr, false, NULL);
244 el->dep = boolexpr_true();
245 // Reverse dependency expression
246 if (sym->rev_dep.expr != NULL) {
247 Dprintf(" Reverse dependency:\n");
248 doutput_expr(sym->rev_dep.expr);
250 boolexpr_kconfig(gsymlist, sym->rev_dep.expr, false, NULL);
252 el->rev_dep = boolexpr_false();
254 if (el->dep->type != BT_FALSE && el->dep->type != BT_TRUE)
255 cnf_boolexpr(gsymlist, el->dep);
256 if (el->rev_dep->type != BT_FALSE
257 && el->rev_dep->type != BT_TRUE)
258 cnf_boolexpr(gsymlist, el->rev_dep);
259 if (el->def->type != BT_FALSE && el->def->type != BT_TRUE)
260 cnf_boolexpr(gsymlist, el->def);
261 if (el->vis->type != BT_FALSE && el->vis->type != BT_TRUE)
262 cnf_boolexpr(gsymlist, el->vis);
263 // (!sym || dep) && (sym || !rev_dep) &&
264 // && (sym || !dep || !def || vis) &&
265 // (!sym || rev_dep || def || vis)
266 if (el->dep->type != BT_TRUE) {
267 output_rules_symbol(-1 * boolsym->id);
268 if (el->dep->type != BT_FALSE) {
269 output_rules_symbol(el->dep->id);
271 output_rules_endterm();
273 if (el->rev_dep->type != BT_FALSE) {
274 output_rules_symbol(boolsym->id);
275 if (el->rev_dep->type != BT_TRUE) {
276 output_rules_symbol(-1 * el->rev_dep->id);
278 output_rules_endterm();
280 if (el->dep->type != BT_FALSE && el->def->type != BT_FALSE
281 && el->vis->type != BT_TRUE) {
282 output_rules_symbol(boolsym->id);
283 if (el->dep->type != BT_TRUE) {
284 output_rules_symbol(-1 * el->dep->id);
286 if (el->def->type != BT_TRUE) {
287 output_rules_symbol(-1 * el->def->id);
289 if (el->vis->type != BT_FALSE) {
290 output_rules_symbol(el->vis->id);
292 output_rules_endterm();
294 if (el->rev_dep->type != BT_TRUE && el->def->type != BT_TRUE
295 && el->vis->type != BT_TRUE) {
296 output_rules_symbol(-1 * boolsym->id);
297 if (el->rev_dep->type != BT_FALSE) {
298 output_rules_symbol(el->rev_dep->id);
300 if (el->def->type != BT_FALSE) {
301 output_rules_symbol(el->def->id);
303 if (el->vis->type != BT_FALSE) {
304 output_rules_symbol(el->vis->id);
306 output_rules_endterm();
309 boolexpr_free(el->def);
310 boolexpr_free(el->vis);
311 boolexpr_free(el->dep);
312 boolexpr_free(el->rev_dep);
317 // Add exclusive rules for choice symbol
318 if (sym->rev_dep.expr != NULL) {
319 Dprintf(" Dependency:\n");
320 doutput_expr(sym->rev_dep.expr);
322 boolexpr_kconfig(gsymlist, sym->rev_dep.expr, true, NULL);
324 el->rev_dep = boolexpr_true();
325 for_all_choices(sym, prop) {
328 unsigned *symx = NULL;
329 size_t symx_size = 0;
331 expr_list_for_each_sym(prop->expr, exprw, symw) {
333 symx = realloc(symx, symx_size * sizeof(unsigned));
334 symx[symx_size - 1] = symlist_id(gsymlist, symw->name);
335 output_rules_symbol(symx[symx_size - 1]);
337 output_rules_symbol(-(int)
339 output_rules_endterm();
340 for (x = 0; x < symx_size - 1; x++) {
341 for (y = x + 1; y < symx_size; y++) {
342 output_rules_symbol(-(int)
344 output_rules_symbol(-(int)
346 output_rules_endterm();
352 if (el->rev_dep->type != BT_FALSE && el->rev_dep->type != BT_TRUE)
353 cnf_boolexpr(gsymlist, el->rev_dep);
354 if (el->vis->type != BT_FALSE && el->vis->type != BT_TRUE)
355 cnf_boolexpr(gsymlist, el->vis);
356 // (!sym || rev_dep) && (!sym || !rev_dep || vis)
357 // For nonoptional per list symbol add:
358 // (sym || !rev_dep || !vis || !dir_dep_of_list))
359 if (el->rev_dep->type != BT_TRUE) {
360 output_rules_symbol(-1 * boolsym->id);
361 if (el->rev_dep->type != BT_FALSE) {
362 output_rules_symbol(el->rev_dep->id);
364 output_rules_endterm();
366 if (el->rev_dep->type != BT_FALSE && el->vis->type != BT_TRUE) {
367 output_rules_symbol(-1 * boolsym->id);
368 if (el->rev_dep->type != BT_TRUE) {
369 output_rules_symbol(-1 * el->rev_dep->id);
371 if (el->vis != BT_FALSE) {
372 output_rules_symbol(el->vis->id);
374 output_rules_endterm();
376 if (!sym_is_optional(sym)) {
377 for_all_choices(sym, prop) {
380 expr_list_for_each_sym(prop->expr, exprw, symw) {
381 struct boolexpr *wdep;
382 if (symw->dir_dep.expr != NULL) {
383 struct symbol *settrue[] = {sym, NULL};
385 boolexpr_kconfig(gsymlist, symw->dir_dep.expr,
388 wdep = boolexpr_true();
389 cnf_boolexpr(gsymlist, wdep);
390 if (el->rev_dep->type != BT_FALSE
391 && el->vis->type != BT_FALSE
392 && wdep->type != BT_FALSE) {
393 output_rules_symbol(boolsym->id);
394 if (el->rev_dep->type != BT_TRUE) {
395 output_rules_symbol(-1 * el->rev_dep->id);
397 if (el->vis->type != BT_TRUE) {
398 output_rules_symbol(-1 * el->vis->id);
400 if (wdep->type != BT_TRUE
401 && wdep->id != boolsym->id) {
402 output_rules_symbol(-1 * wdep->id);
404 output_rules_endterm();