]> rtime.felk.cvut.cz Git - linux-conf-perf.git/blob - scripts/parse_kconfig/parse.c
79c256aba1622cbb9390892e0a1e84a6132a387f
[linux-conf-perf.git] / scripts / parse_kconfig / parse.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <locale.h>
5 #include <stdbool.h>
6 #include <libintl.h>
7
8 #include <kconfig/lkc.h>
9 #include "boolexpr.h"
10 #include "symlist.h"
11 #include "output.h"
12 #include "macros.h"
13 #include "doutput.h"
14
15 int verbose_level;
16 char *file, *folder;
17
18 struct symlist *gsymlist;
19 int noname_num;
20
21 void build_symlist();
22 void cpy_dep();
23
24 int main(int argc, char **argv) {
25     verbose_level = 1;
26     int i;
27     for (i = 1; i < argc; i++) {
28         if (!strcmp(argv[i], "-v"))
29             verbose_level++;
30         else if (file == NULL)
31             file = argv[i];
32         else if (folder == NULL)
33             folder = argv[i];
34         else {
35             Eprintf("Unknown parameter: %s\n", argv[i]);
36             exit(1);
37         }
38     }
39
40     if (file == NULL) {
41         Eprintf("No Kconfig input file specified\n");
42         exit(2);
43     }
44     if (folder == NULL) {
45         Eprintf("No output folder specified\n");
46         exit(3);
47     }
48
49     setlocale(LC_ALL, "");
50     bindtextdomain(PACKAGE, LOCALEDIR);
51     textdomain(PACKAGE);
52
53     conf_parse(file);
54     //sym_clear_all_valid();
55
56     gsymlist = symlist_create();
57
58     char *rules_file, *symbol_map_file, *variable_count_file;
59     asprintf(&rules_file, "%s/%s", folder, DEFAULT_RULES_FILE);
60     asprintf(&symbol_map_file, "%s/%s", folder, DEFAULT_SYMBOL_MAP_FILE);
61     asprintf(&variable_count_file, "%s/%s", folder,
62              DEFAULT_VARIABLE_COUNT_FILE);
63     output_init(rules_file, symbol_map_file);
64
65     build_symlist();
66     cpy_dep();
67
68     output_write_variable_count(variable_count_file,
69                                 gsymlist->lastsym - 1, gsymlist->pos);
70
71     output_finish();
72     return 0;
73 }
74
75 void build_symlist() {
76     int i;
77     struct symbol *sym;
78     struct property *prop;
79     for_all_symbols(i, sym) {
80         if (sym->type == S_BOOLEAN || sym->type == S_TRISTATE) {
81             if (sym->name == NULL)
82                 asprintf(&sym->name, "NONAMEGEN%d", noname_num++);
83
84             symlist_add(gsymlist, sym->name);
85         }
86     }
87     symlist_closesym(gsymlist);
88 }
89
90 void cpy_dep() {
91     int i;
92     struct symbol *sym;
93     struct property *prop;
94     struct symlist_el *el;
95     unsigned el_id;
96     struct boolexpr *boolsym;
97     for_all_symbols(i, sym) {
98         if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
99             continue;
100         el_id = symlist_id(gsymlist, sym->name);
101         el = &(gsymlist->array[el_id - 1]);
102         boolsym = boolexpr_sym(gsymlist, sym, false, NULL);
103         Iprintf("Processing: %s\n", sym->name);
104         // Visibility
105         for_all_prompts(sym, prop) {
106             Dprintf(" Prompt: %s\n", prop->text);
107             if (prop->visible.expr != NULL) {
108                 doutput_expr(prop->visible.expr);
109                 struct boolexpr *vis =
110                     boolexpr_kconfig(gsymlist, prop->visible.expr,
111                                      false, NULL);
112                 if (el->vis == NULL) {
113                     el->vis = vis;
114                 } else {
115                     el->vis = boolexpr_or(el->vis, vis);
116                 }
117             } else if (el->vis == NULL) {
118                 el->vis = boolexpr_true();
119             }
120         }
121         if (el->vis == NULL)
122             el->vis = boolexpr_false();
123         // Symbol is choice.. special treatment required
124         if (sym_is_choice(sym)) {
125             Dprintf(" Is Choice\n");
126             goto choice_exception;
127         }
128         // Default value
129         struct boolexpr **defexpr = NULL;
130         size_t defexpr_size = 0;
131         int z;
132         bool exitdef = false;
133         for_all_defaults(sym, prop) {
134             Dprintf(" Default value:\n");
135             doutput_expr(prop->expr);
136             struct boolexpr *def =
137                 boolexpr_kconfig(gsymlist, prop->expr, true, NULL);
138             struct boolexpr *vis;
139             if (prop->visible.expr != NULL)
140                 vis = boolexpr_kconfig(gsymlist, prop->visible.expr,
141                                        false, NULL);
142             else
143                 vis = boolexpr_true();
144             if (vis->type != BT_TRUE) {
145                 defexpr = realloc(defexpr,
146                                   ++defexpr_size * sizeof(struct boolexpr *));
147                 defexpr[defexpr_size - 1] = boolexpr_copy(vis);
148             } else {
149                 ++defexpr_size;
150                 exitdef = true;
151             }
152             def = boolexpr_and(def, vis);
153             for (z = 0; z < ((int)defexpr_size - 1); z++) {
154                 def = boolexpr_and(def, boolexpr_not(
155                                        boolexpr_copy(defexpr[z])));
156             }
157             if (el->def == NULL)
158                 el->def = def;
159             else
160                 el->def = boolexpr_or(el->def, def);
161             if (exitdef)
162                 break;
163         }
164         if (defexpr != NULL) {
165             for (z = 0; z < defexpr_size - 1; z++) {
166                 boolexpr_free(defexpr[z]);
167             }
168             free(defexpr);
169         }
170         if (el->def == NULL)
171             el->def = boolexpr_false();
172         // Dependency expression
173         if (sym->dir_dep.expr != NULL) {
174             Dprintf(" Dependency:\n");
175             doutput_expr(sym->dir_dep.expr);
176             el->dep =
177                 boolexpr_kconfig(gsymlist, sym->dir_dep.expr, false, NULL);
178         } else
179             el->dep = boolexpr_true();
180         // Reverse dependency expression
181         if (sym->rev_dep.expr != NULL) {
182             Dprintf(" Reverse dependency:\n");
183             doutput_expr(sym->rev_dep.expr);
184             el->rev_dep =
185                 boolexpr_kconfig(gsymlist, sym->rev_dep.expr, false, NULL);
186         } else
187             el->rev_dep = boolexpr_false();
188
189         if (el->dep->type != BT_FALSE && el->dep->type != BT_TRUE)
190             cnf_boolexpr(gsymlist, el->dep);
191         if (el->rev_dep->type != BT_FALSE
192             && el->rev_dep->type != BT_TRUE)
193             cnf_boolexpr(gsymlist, el->rev_dep);
194         if (el->def->type != BT_FALSE && el->def->type != BT_TRUE)
195             cnf_boolexpr(gsymlist, el->def);
196         if (el->vis->type != BT_FALSE && el->vis->type != BT_TRUE)
197             cnf_boolexpr(gsymlist, el->vis);
198         // (!sym || dep) && (sym || !rev_dep) &&
199         // && (sym || !dep || !def || vis) &&
200         // (!sym || rev_dep || def || vis)
201         if (el->dep->type != BT_TRUE) {
202             output_rules_symbol(-1 * boolsym->id);
203             if (el->dep->type != BT_FALSE) {
204                 output_rules_symbol(el->dep->id);
205             }
206             output_rules_endterm();
207         }
208         if (el->rev_dep->type != BT_FALSE) {
209             output_rules_symbol(boolsym->id);
210             if (el->rev_dep->type != BT_TRUE) {
211                 output_rules_symbol(-1 * el->rev_dep->id);
212             }
213             output_rules_endterm();
214         }
215         if (el->dep->type != BT_FALSE && el->def->type != BT_FALSE
216             && el->vis->type != BT_TRUE) {
217             output_rules_symbol(boolsym->id);
218             if (el->dep->type != BT_TRUE) {
219                 output_rules_symbol(-1 * el->dep->id);
220             }
221             if (el->def->type != BT_TRUE) {
222                 output_rules_symbol(-1 * el->def->id);
223             }
224             if (el->vis->type != BT_FALSE) {
225                 output_rules_symbol(el->vis->id);
226             }
227             output_rules_endterm();
228         }
229         if (el->rev_dep->type != BT_TRUE && el->def->type != BT_TRUE
230             && el->vis->type != BT_TRUE) {
231             output_rules_symbol(-1 * boolsym->id);
232             if (el->rev_dep->type != BT_FALSE) {
233                 output_rules_symbol(el->rev_dep->id);
234             }
235             if (el->def->type != BT_FALSE) {
236                 output_rules_symbol(el->def->id);
237             }
238             if (el->vis->type != BT_FALSE) {
239                 output_rules_symbol(el->vis->id);
240             }
241             output_rules_endterm();
242         }
243
244         boolexpr_free(el->def);
245         boolexpr_free(el->vis);
246         boolexpr_free(el->dep);
247         boolexpr_free(el->rev_dep);
248
249         continue;
250
251     choice_exception:
252         // Add exclusive rules for choice symbol
253         if (sym->rev_dep.expr != NULL) {
254             Dprintf(" Dependency:\n");
255             doutput_expr(sym->rev_dep.expr);
256             el->rev_dep =
257                 boolexpr_kconfig(gsymlist, sym->rev_dep.expr, true, NULL);
258         } else
259             el->rev_dep = boolexpr_true();
260         for_all_choices(sym, prop) {
261             struct symbol *symw;
262             struct expr *exprw;
263             unsigned *symx = NULL;
264             size_t symx_size = 0;
265             int x, y;
266             expr_list_for_each_sym(prop->expr, exprw, symw) {
267                 symx_size++;
268                 symx = realloc(symx, symx_size * sizeof(unsigned));
269                 symx[symx_size - 1] = symlist_id(gsymlist, symw->name);
270                 output_rules_symbol(symx[symx_size - 1]);
271             }
272             output_rules_symbol(-(int)
273                                 el_id);
274             output_rules_endterm();
275             for (x = 0; x < symx_size - 1; x++) {
276                 for (y = x + 1; y < symx_size; y++) {
277                     output_rules_symbol(-(int)
278                                         symx[x]);
279                     output_rules_symbol(-(int)
280                                         symx[y]);
281                     output_rules_endterm();
282                 }
283             }
284             free(symx);
285             symx = NULL;
286         }
287         if (el->rev_dep->type != BT_FALSE && el->rev_dep->type != BT_TRUE)
288             cnf_boolexpr(gsymlist, el->rev_dep);
289         if (el->vis->type != BT_FALSE && el->vis->type != BT_TRUE)
290             cnf_boolexpr(gsymlist, el->vis);
291         // (!sym || rev_dep) && (!sym || !rev_dep || vis)
292         // For nonoptional per list symbol add:
293         // (sym || !rev_dep || !vis || !dir_dep_of_list))
294         if (el->rev_dep->type != BT_TRUE) {
295             output_rules_symbol(-1 * boolsym->id);
296             if (el->rev_dep->type != BT_FALSE) {
297                 output_rules_symbol(el->rev_dep->id);
298             }
299             output_rules_endterm();
300         }
301         if (el->rev_dep->type != BT_FALSE && el->vis->type != BT_TRUE) {
302             output_rules_symbol(-1 * boolsym->id);
303             if (el->rev_dep->type != BT_TRUE) {
304                 output_rules_symbol(-1 * el->rev_dep->id);
305             }
306             if (el->vis != BT_FALSE) {
307                 output_rules_symbol(el->vis->id);
308             }
309             output_rules_endterm();
310         }
311         if (!sym_is_optional(sym)) {
312             for_all_choices(sym, prop) {
313                 struct symbol *symw;
314                 struct expr *exprw;
315                 expr_list_for_each_sym(prop->expr, exprw, symw) {
316                     struct boolexpr *wdep;
317                     if (symw->dir_dep.expr != NULL) {
318                         struct symbol *settrue[] = {sym, NULL};
319                         wdep =
320                             boolexpr_kconfig(gsymlist, symw->dir_dep.expr,
321                                              false, settrue);
322                     } else
323                         wdep = boolexpr_true();
324                     cnf_boolexpr(gsymlist, wdep);
325                     if (el->rev_dep->type != BT_FALSE
326                         && el->vis->type != BT_FALSE
327                         && wdep->type != BT_FALSE) {
328                         output_rules_symbol(boolsym->id);
329                         if (el->rev_dep->type != BT_TRUE) {
330                             output_rules_symbol(-1 * el->rev_dep->id);
331                         }
332                         if (el->vis->type != BT_TRUE) {
333                             output_rules_symbol(-1 * el->vis->id);
334                         }
335                         if (wdep->type != BT_TRUE
336                             && wdep->id != boolsym->id) {
337                             output_rules_symbol(-1 * wdep->id);
338                         }
339                         output_rules_endterm();
340                     }
341                 }
342             }
343         }
344     }
345 }