]> rtime.felk.cvut.cz Git - linux-conf-perf.git/blob - scripts/parse_kconfig/parse.c
9de456fe94d384079eee11e0750486620ca5e6c5
[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                 sym->name = malloc((9 + 7) * sizeof(char));
83                 sprintf(sym->name, "NONAMEGEN%d", noname_num++);
84             }
85             symlist_add(gsymlist, sym->name);
86         }
87     }
88     symlist_closesym(gsymlist);
89 }
90
91 void cpy_dep() {
92     int i;
93     struct symbol *sym;
94     struct property *prop;
95     struct symlist_el *el;
96     unsigned el_id;
97     struct boolexpr *boolsym;
98     for_all_symbols(i, sym) {
99         if (sym->type == S_BOOLEAN || sym->type == S_TRISTATE) {
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             for_all_defaults(sym, prop) {
130                 Dprintf(" Default value:\n");
131                 doutput_expr(prop->expr);
132                 struct boolexpr *def =
133                     boolexpr_kconfig(gsymlist, prop->expr, true, NULL);
134                 if (prop->visible.expr != NULL)
135                     def =
136                         boolexpr_and(def,
137                                      boolexpr_kconfig(gsymlist,
138                                                       prop->visible.expr,
139                                                       false, NULL));
140                 if (el->def == NULL) {
141                     el->def = def;
142                 } else {
143                     el->def = boolexpr_or(el->def, def);
144                 }
145             }
146             if (el->def == NULL)
147                 el->def = boolexpr_false();
148             // Dependency expression
149             if (sym->dir_dep.expr != NULL) {
150                 Dprintf(" Dependency:\n");
151                 doutput_expr(sym->dir_dep.expr);
152                 el->dep =
153                     boolexpr_kconfig(gsymlist, sym->dir_dep.expr, false, NULL);
154             } else
155                 el->dep = boolexpr_true();
156             // Reverse dependency expression
157             if (sym->rev_dep.expr != NULL) {
158                 Dprintf(" Reverse dependency:\n");
159                 doutput_expr(sym->rev_dep.expr);
160                 el->rev_dep =
161                     boolexpr_kconfig(gsymlist, sym->rev_dep.expr, false, NULL);
162             } else
163                 el->rev_dep = boolexpr_false();
164
165             if (el->dep->type != BT_FALSE && el->dep->type != BT_TRUE)
166                 cnf_boolexpr(gsymlist, el->dep);
167             if (el->rev_dep->type != BT_FALSE
168                 && el->rev_dep->type != BT_TRUE)
169                 cnf_boolexpr(gsymlist, el->rev_dep);
170             if (el->def->type != BT_FALSE && el->def->type != BT_TRUE)
171                 cnf_boolexpr(gsymlist, el->def);
172             if (el->vis->type != BT_FALSE && el->vis->type != BT_TRUE)
173                 cnf_boolexpr(gsymlist, el->vis);
174             // (!sym || dep) && (sym || !rev_dep) &&
175             // && (sym || !dep || !def || vis) &&
176             // (!sym || rev_dep || def || vis)
177             if (el->dep->type != BT_TRUE) {
178                 output_rules_symbol(-1 * boolsym->id);
179                 if (el->dep->type != BT_FALSE) {
180                     output_rules_symbol(el->dep->id);
181                 }
182                 output_rules_endterm();
183             }
184             if (el->rev_dep->type != BT_FALSE) {
185                 output_rules_symbol(boolsym->id);
186                 if (el->rev_dep->type != BT_TRUE) {
187                     output_rules_symbol(-1 * el->rev_dep->id);
188                 }
189                 output_rules_endterm();
190             }
191             if (el->dep->type != BT_FALSE && el->def->type != BT_FALSE
192                 && el->vis->type != BT_TRUE) {
193                 output_rules_symbol(boolsym->id);
194                 if (el->dep->type != BT_TRUE) {
195                     output_rules_symbol(-1 * el->dep->id);
196                 }
197                 if (el->def->type != BT_TRUE) {
198                     output_rules_symbol(-1 * el->def->id);
199                 }
200                 if (el->vis->type != BT_FALSE) {
201                     output_rules_symbol(el->vis->id);
202                 }
203                 output_rules_endterm();
204             }
205             if (el->rev_dep->type != BT_TRUE && el->def->type != BT_TRUE
206                 && el->vis->type != BT_TRUE) {
207                 output_rules_symbol(-1 * boolsym->id);
208                 if (el->rev_dep->type != BT_FALSE) {
209                     output_rules_symbol(el->rev_dep->id);
210                 }
211                 if (el->def->type != BT_FALSE) {
212                     output_rules_symbol(el->def->id);
213                 }
214                 if (el->vis->type != BT_FALSE) {
215                     output_rules_symbol(el->vis->id);
216                 }
217                 output_rules_endterm();
218             }
219
220             boolexpr_free(el->def);
221             boolexpr_free(el->vis);
222             boolexpr_free(el->dep);
223             boolexpr_free(el->rev_dep);
224
225             continue;
226
227           choice_exception:
228             // Add exclusive rules for choice symbol
229             if (sym->rev_dep.expr != NULL) {
230                 Dprintf(" Dependency:\n");
231                 doutput_expr(sym->rev_dep.expr);
232                 el->rev_dep =
233                     boolexpr_kconfig(gsymlist, sym->rev_dep.expr, true, NULL);
234             } else
235                 el->rev_dep = boolexpr_true();
236             for_all_choices(sym, prop) {
237                 struct symbol *symw;
238                 struct expr *exprw;
239                 unsigned *symx = NULL;
240                 size_t symx_size = 0;
241                 int x, y;
242                 expr_list_for_each_sym(prop->expr, exprw, symw) {
243                     symx_size++;
244                     symx = realloc(symx, symx_size * sizeof(unsigned));
245                     symx[symx_size - 1] = symlist_id(gsymlist, symw->name);
246                     output_rules_symbol(symx[symx_size - 1]);
247                 }
248                 output_rules_symbol(-(int)
249                                     el_id);
250                 output_rules_endterm();
251                 for (x = 0; x < symx_size - 1; x++) {
252                     for (y = x + 1; y < symx_size; y++) {
253                         output_rules_symbol(-(int)
254                                             symx[x]);
255                         output_rules_symbol(-(int)
256                                             symx[y]);
257                         output_rules_endterm();
258                     }
259                 }
260                 free(symx);
261                 symx = NULL;
262             }
263             if (el->rev_dep->type != BT_FALSE && el->rev_dep->type != BT_TRUE)
264                 cnf_boolexpr(gsymlist, el->rev_dep);
265             if (el->vis->type != BT_FALSE && el->vis->type != BT_TRUE)
266                 cnf_boolexpr(gsymlist, el->vis);
267             // (!sym || rev_dep) && (!sym || !rev_dep || vis)
268             // For nonoptional per list symbol add:
269             // (sym || !rev_dep || !vis || !dir_dep_of_list))
270             if (el->rev_dep->type != BT_TRUE) {
271                 output_rules_symbol(-1 * boolsym->id);
272                 if (el->rev_dep->type != BT_FALSE) {
273                     output_rules_symbol(el->rev_dep->id);
274                 }
275                 output_rules_endterm();
276             }
277             if (el->rev_dep->type != BT_FALSE && el->vis->type != BT_TRUE) {
278                 output_rules_symbol(-1 * boolsym->id);
279                 if (el->rev_dep->type != BT_TRUE) {
280                     output_rules_symbol(-1 * el->rev_dep->id);
281                 }
282                 if (el->vis != BT_FALSE) {
283                     output_rules_symbol(el->vis->id);
284                 }
285                 output_rules_endterm();
286             }
287             if (!sym_is_optional(sym)) {
288                 for_all_choices(sym, prop) {
289                     struct symbol *symw;
290                     struct expr *exprw;
291                     expr_list_for_each_sym(prop->expr, exprw, symw) {
292                         struct boolexpr *wdep;
293                         if (symw->dir_dep.expr != NULL) {
294                             struct symbol *settrue[] = {sym, NULL};
295                             wdep =
296                                 boolexpr_kconfig(gsymlist, symw->dir_dep.expr,
297                                         false, settrue);
298                         } else
299                             wdep = boolexpr_true();
300                         cnf_boolexpr(gsymlist, wdep);
301                         if (el->rev_dep->type != BT_FALSE
302                             && el->vis->type != BT_FALSE
303                             && wdep->type != BT_FALSE) {
304                             output_rules_symbol(boolsym->id);
305                             if (el->rev_dep->type != BT_TRUE) {
306                                 output_rules_symbol(-1 * el->rev_dep->id);
307                             }
308                             if (el->vis->type != BT_TRUE) {
309                                 output_rules_symbol(-1 * el->vis->id);
310                             }
311                             if (wdep->type != BT_TRUE
312                                 && wdep->id != boolsym->id) {
313                                 output_rules_symbol(-1 * wdep->id);
314                             }
315                             output_rules_endterm();
316                         }
317                     }
318                 }
319             }
320         }
321     }
322 }