summaryrefslogtreecommitdiff
path: root/scripts/kconfig/cml1.y
Unidiff
Diffstat (limited to 'scripts/kconfig/cml1.y') (more/less context) (ignore whitespace changes)
-rw-r--r--scripts/kconfig/cml1.y2482
1 files changed, 2482 insertions, 0 deletions
diff --git a/scripts/kconfig/cml1.y b/scripts/kconfig/cml1.y
new file mode 100644
index 0000000..42c4216
--- a/dev/null
+++ b/scripts/kconfig/cml1.y
@@ -0,0 +1,2482 @@
1%{
2/*
3 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
4 * Released under the terms of the GNU GPL v2.0.
5 */
6
7#include <ctype.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
12 #define PRINTD 0x0001
13 #define DEBUG_PARSE0x0002
14 #define DEBUG_OPT0x0004
15 #define DEBUG_OPT10x0008
16 #define DEBUG_OPT20x0010
17 #define DEBUG_OPT30x0020
18 #define DEBUG_OPT40x0040
19 #define DEBUG_OPT50x0080
20 #define DEBUG_DEP0x0100
21
22int cdebug = PRINTD;//DEBUG_OPT|-1;
23
24#define YYERROR_VERBOSE
25%}
26
27%union
28{
29 char *string;
30 struct expr *expr;
31 struct symbol *symbol;
32 struct statement *stmt;
33}
34
35%token <string> T_WORD
36%token <string> T_WORD_QUOTE
37%token <string> T_WORD_DQUOTE
38%token T_MAINMENU_NAME
39%token T_MAINMENU_OPTION
40%token T_NEXT_COMMENT
41%token T_ENDMENU
42%token T_COMMENT
43%token T_BOOL
44%token T_HEX
45%token T_INT
46%token T_STRING
47%token T_TRISTATE
48%token T_DEFINE_BOOL
49%token T_DEFINE_HEX
50%token T_DEFINE_INT
51%token T_DEFINE_STRING
52%token T_DEFINE_TRISTATE
53%token T_DEP_BOOL
54%token T_DEP_MBOOL
55%token T_DEP_TRISTATE
56%token T_UNSET
57%token T_CHOICE
58%token T_SOURCE
59%token T_IF
60%token T_ELSE
61%token T_FI
62%token T_THEN
63%token T_UNEQUAL
64%token <string> T_SH_COMMENT
65
66%type <string> prompt
67%type <string> word
68%type <string> menu_comment
69%type <symbol> symbol
70%type <symbol> symbol_ref
71%type <symbol> symbol_other
72%type <stmt> statement
73%type <expr> expr
74%type <expr> dep
75%type <expr> deps
76%type <stmt> comment_opt
77
78%left T_OR
79%left T_AND
80%nonassoc '!'
81%left '=' T_UNEQUAL
82
83%{
84#include "cml1.h"
85
86extern int cml1lex(void);
87static void cml1error(const char *err);
88extern int lineno(void);
89extern void scan_nextfile(char *file);
90
91struct statement *create_stmt(int token);
92struct statement *add_stmt(struct symbol *sym, int token,
93 char *prompt, struct symbol *def);
94void print_expr(int mask, struct expr *e, int prevtoken);
95void print_dep(int mask, struct statement *stmt);
96
97void eliminate_eq(int token, struct expr **ep1, struct expr **ep2);
98static inline int expr_is_yes(struct expr *e);
99static inline int expr_is_no(struct expr *e);
100struct expr *trans_dep_bool(struct expr *e);
101struct expr *trans_bool_expr(struct expr *e);
102struct expr *fixup_expr(struct expr *e);
103struct expr *trans_expr(struct expr *e);
104void extract_eq(int token, struct expr **ep, struct expr **ep1, struct expr **ep2);
105struct expr *extract_eq_and(struct expr **ep1, struct expr **ep2);
106struct expr *extract_eq_or(struct expr **ep1, struct expr **ep2);
107struct expr *optimize_expr_or(struct expr *e);
108struct expr *eliminate_dups(struct expr *e);
109struct expr *eliminate_yn(struct expr *e);
110void eliminate_dep(struct symbol *sym, struct expr *dep);
111int contains_expr(struct expr *dep, struct expr *e);
112
113#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
114#define fprintd(f, mask, fmt...) if (cdebug & (mask)) fprintf(f, fmt)
115
116static struct expr *if_expr;
117static struct menu root_menu;
118static struct menu *current_menu = &root_menu;
119
120struct symbol *symbol_hash[257];
121%}
122%%
123 input:line
124;
125
126 line:/* empty */
127;
128
129 line:line statement
130;
131
132 line:line '\n'
133;
134
135statement: T_SH_COMMENT
136{
137 $$ = create_stmt(T_SH_COMMENT);
138 $$->text = $1;
139};
140
141statement: T_MAINMENU_NAME prompt '\n'
142{
143 $$ = create_stmt(T_MAINMENU_NAME);
144 $$->text = $2;
145 printd(DEBUG_PARSE, "%d:mainmenu_name: %s\n", lineno(), $2);
146};
147
148statement: T_COMMENT prompt '\n'
149{
150 $$ = create_stmt(T_COMMENT);
151 $$->text = $2;
152 $$->dep = trans_expr(fixup_expr(expr_copy(if_expr)));
153 printd(DEBUG_PARSE, "%d:comment: %s\n", lineno(), $2);
154};
155
156statement: T_BOOL prompt symbol dep '\n'
157{
158 $$ = add_stmt($3, T_BOOL, $2, NULL);
159 printd(DEBUG_PARSE, "%d:bool: %s %s\n", lineno(), $2, $3->name);
160 if ($4) {
161 printf("%s:%d: warning ignoring dependencies\n", current_file->name, current_file->lineno);
162 expr_free($4);
163 }
164 print_dep(DEBUG_PARSE, $$);
165};
166
167statement: T_HEX prompt symbol symbol_other '\n'
168{
169 $$ = add_stmt($3, T_HEX, $2, NULL);
170 add_stmt($3, T_DEFINE_HEX, NULL, $4);
171 printd(DEBUG_PARSE, "%d:hex: %s %s %s\n", lineno(), $2, $3->name, $4->name);
172 print_dep(DEBUG_PARSE, $$);
173};
174
175statement: T_INT prompt symbol symbol_other '\n'
176{
177 $$ = add_stmt($3, T_INT, $2, NULL);
178 add_stmt($3, T_DEFINE_INT, NULL, $4);
179 printd(DEBUG_PARSE, "%d:int: %s %s %s\n", lineno(), $2, $3->name, $4->name);
180 print_dep(DEBUG_PARSE, $$);
181};
182
183statement: T_STRING prompt symbol symbol_other '\n'
184{
185 $$ = add_stmt($3, T_STRING, $2, NULL);
186 add_stmt($3, T_DEFINE_STRING, NULL, $4);
187 printd(DEBUG_PARSE, "%d:string: %s %s %s\n", lineno(), $2, $3->name, $4->name);
188 print_dep(DEBUG_PARSE, $$);
189};
190
191statement: T_TRISTATE prompt symbol dep '\n'
192{
193 $$ = add_stmt($3, T_TRISTATE, $2, NULL);
194 printd(DEBUG_PARSE, "%d:tristate: %s %s\n", lineno(), $2, $3->name);
195 if ($4) {
196 printf("%s:%d: warning ignoring dependencies\n", current_file->name, current_file->lineno);
197 expr_free($4);
198 }
199 print_dep(DEBUG_PARSE, $$);
200};
201
202statement: T_DEFINE_BOOL symbol symbol_ref comment_opt '\n'
203{
204 $$ = add_stmt($2, T_DEFINE_BOOL, NULL, $3);
205 printd(DEBUG_PARSE, "%d:define_bool: %s %s\n", lineno(), $2->name, $3->name);
206 print_dep(DEBUG_PARSE, $$);
207};
208
209statement: T_DEFINE_HEX symbol symbol_other '\n'
210{
211 $$ = add_stmt($2, T_DEFINE_HEX, NULL, $3);
212 printd(DEBUG_PARSE, "%d:define_hex: %s %s\n", lineno(), $2->name, $3->name);
213 print_dep(DEBUG_PARSE, $$);
214};
215
216statement: T_DEFINE_INT symbol symbol_other comment_opt '\n'
217{
218 $$ = add_stmt($2, T_DEFINE_INT, NULL, $3);
219 printd(DEBUG_PARSE, "%d:define_int: %s %s\n", lineno(), $2->name, $3->name);
220 print_dep(DEBUG_PARSE, $$);
221};
222
223statement: T_DEFINE_STRING symbol symbol_other '\n'
224{
225 $$ = add_stmt($2, T_DEFINE_STRING, NULL, $3);
226 printd(DEBUG_PARSE, "%d:define_string: %s %s\n", lineno(), $2->name, $3->name);
227 print_dep(DEBUG_PARSE, $$);
228};
229
230statement: T_DEFINE_TRISTATE symbol symbol_ref '\n'
231{
232 $$ = add_stmt($2, T_DEFINE_TRISTATE, NULL, $3);
233 printd(DEBUG_PARSE, "%d:define_tristate: %s %s\n", lineno(), $2->name, $3->name);
234 print_dep(DEBUG_PARSE, $$);
235};
236
237statement: T_DEP_BOOL prompt symbol dep '\n'
238{
239 $$ = add_stmt($3, T_DEP_BOOL, $2, NULL);
240 if (!($$->dep2 = $4))
241 printf("%s:%d: warning dep_bool without dependencies\n", current_file->name, current_file->lineno);
242 printd(DEBUG_PARSE, "%d:dep_bool: %s %s\n", lineno(), $2, $3->name);
243 print_dep(DEBUG_PARSE, $$);
244};
245
246statement: T_DEP_MBOOL prompt symbol dep '\n'
247{
248 $$ = add_stmt($3, T_DEP_MBOOL, $2, NULL);
249 if (!($$->dep2 = $4))
250 printf("%s:%d: warning dep_mbool without dependencies\n", current_file->name, current_file->lineno);
251 printd(DEBUG_PARSE, "%d:dep_mbool: %s %s\n", lineno(), $2, $3->name);
252 print_dep(DEBUG_PARSE, $$);
253};
254
255statement: T_DEP_TRISTATE prompt symbol dep '\n'
256{
257 $$ = add_stmt($3, T_DEP_TRISTATE, $2, NULL);
258 if (!($$->dep2 = $4))
259 printf("%s:%d: warning dep_tristate without dependencies\n", current_file->name, current_file->lineno);
260 printd(DEBUG_PARSE, "%d:dep_tristate: %s %s\n", lineno(), $2, $3->name);
261 print_dep(DEBUG_PARSE, $$);
262};
263
264statement: T_UNSET deps '\n'
265{
266 //add_stmt($2, T_UNSET, NULL, NULL);
267 printd(DEBUG_PARSE, "%d:unset\n", lineno());
268 print_dep(DEBUG_PARSE, NULL);
269};
270
271statement: T_CHOICE prompt word word '\n'
272{
273 struct statement *stmt;
274 struct symbol *sym;
275 struct expr **depp;
276 char *ptr, *name, *def, end;
277
278 printd(DEBUG_PARSE, "%d:choice: %s %s %s\n", lineno(), $2, $3, $4);
279 $$ = create_stmt('^');
280 $$->text = $2;
281 ptr = $3;
282 depp = &$$->dep;
283 do {
284 while (isspace(*ptr))
285 ptr++;
286 if (!*ptr)
287 break;
288 def = ptr;
289 while (*ptr && !isspace(*ptr))
290 ptr++;
291 *ptr++ = 0;
292 //def = lookup_symbol(name, SYMBOL_OTHER);
293 while (isspace(*ptr))
294 ptr++;
295 if (!*ptr)
296 break;
297 name = ptr;
298 while (*ptr && !isspace(*ptr))
299 ptr++;
300 end = *ptr;
301 *ptr++ = 0;
302 sym = lookup_symbol(name, SYMBOL_BOOLEAN);
303 if (!$$->def) {
304 if (!strncmp(def, $4, strlen($4)))
305 $$->def = sym;
306 }
307 sym->flags |= SYMBOL_CHOICE;
308 stmt = add_stmt(sym, T_BOOL, strdup(def), NULL);
309 if (!stmt->next) {
310 stmt->next = $$;
311 } else
312 printf("warning: unexpected stmt for choice symbol %s\n", sym->name);
313 *depp = expr_alloc_one('^', NULL);
314 (*depp)->right.sym = sym;
315 depp = &(*depp)->left.expr;
316 printd(DEBUG_PARSE, "added symbol: %s %s\n", sym->name, stmt->text);
317 } while (end);
318 print_dep(DEBUG_PARSE, NULL);
319};
320
321statement: T_IF '[' expr ']' semi_or_nl T_THEN comment_opt '\n'
322{
323 struct expr *e;
324 printd(DEBUG_PARSE, "%d:if ", lineno());
325 print_expr(DEBUG_PARSE, $3, 0);
326 printd(DEBUG_PARSE, "\n");
327 e = expr_alloc_one(T_IF, $3);
328 e->right.expr = if_expr;
329 if_expr = e;
330 $$ = NULL;
331};
332
333semi_or_nl: ';' | '\n'
334;
335
336statement: T_ELSE comment_opt '\n'
337{
338 printd(DEBUG_PARSE, "%d:else\n", lineno());
339 if_expr->token = T_ELSE;
340 $$ = NULL;
341};
342
343statement: T_FI comment_opt '\n'
344{
345 struct expr *e;
346 printd(DEBUG_PARSE, "%d:fi\n", lineno());
347 e = if_expr;
348 if (e) {
349 if_expr = e->right.expr;
350 expr_free(e->left.expr);
351 free(e);
352 } else
353 YYABORT;
354 $$ = NULL;
355};
356
357statement: T_MAINMENU_OPTION T_NEXT_COMMENT menu_comment '\n'
358{
359 printd(DEBUG_PARSE, "%d:mainmenu_option: %s\n", lineno(), $3);
360 $$ = create_stmt(T_MAINMENU_OPTION);
361 $$->text = $3;
362 $$->dep = trans_expr(fixup_expr(expr_copy(if_expr)));
363 current_menu = $$->menu;
364};
365
366menu_comment: '\n' T_COMMENT prompt { $$ = $3; }
367 | '\n' menu_comment { $$ = $2; }
368;
369
370statement: T_ENDMENU '\n'
371{
372 $$ = create_stmt(T_ENDMENU);
373 printd(DEBUG_PARSE, "%d:endmenu\n", lineno());
374 current_menu = current_menu->parent;
375};
376
377statement: T_SOURCE word '\n'
378{
379 static char helppath[256];
380 char *p;
381 $$ = create_stmt(T_SOURCE);
382 $$->text = $2;
383 printd(DEBUG_PARSE, "%d:source: %s\n", lineno(), $2);
384 strcpy(helppath, $2);
385 p = strrchr(helppath, '.');
386 if (p) {
387 strcpy(p, ".help");
388 helplex(helppath);
389 }
390 scan_nextfile($2);
391};
392
393 comment_opt: /* empty */{ $$ = NULL; }
394 |T_SH_COMMENT
395{
396 $$ = create_stmt(T_SH_COMMENT);
397 $$->text = $1;
398};
399
400prompt: T_WORD_QUOTE
401 | T_WORD_DQUOTE
402;
403
404 word: T_WORD
405 | T_WORD_QUOTE
406 | T_WORD_DQUOTE
407;
408
409 dep: /* empty */ { $$ = NULL; }
410 | deps { $$ = $1; }
411;
412
413 deps: symbol_ref { $$ = expr_alloc_symbol($1); }
414 | deps symbol_ref{ $$ = expr_alloc_two('&', $1, expr_alloc_symbol($2)); }
415;
416
417 symbol: T_WORD { $$ = lookup_symbol($1, SYMBOL_UNKNOWN); free($1); }
418;
419
420 expr: symbol_ref '=' symbol_ref { $$ = expr_alloc_comp('=', $1, $3); }
421 | symbol_ref T_UNEQUAL symbol_ref{ $$ = expr_alloc_comp(T_UNEQUAL, $1, $3); }
422 | '!' expr { $$ = expr_alloc_one('!', $2); }
423 | expr T_AND expr{ $$ = expr_alloc_two(T_AND, $1, $3); }
424 | expr T_OR expr{ $$ = expr_alloc_two(T_OR, $1, $3); }
425;
426
427 symbol_ref: T_WORD { $$ = lookup_symbol_ref($1); free($1); }
428 | T_WORD_QUOTE{ $$ = lookup_symbol_ref($1); free($1); }
429 | T_WORD_DQUOTE{ $$ = lookup_symbol_ref($1); free($1); }
430;
431
432 symbol_other: T_WORD { $$ = lookup_symbol($1, SYMBOL_OTHER); free($1); }
433 | T_WORD_QUOTE{ $$ = lookup_symbol($1, SYMBOL_OTHER); free($1); }
434 | T_WORD_DQUOTE{ $$ = lookup_symbol($1, SYMBOL_OTHER); free($1); }
435;
436
437%%
438
439static void yyerror(const char *err)
440{
441 printf("%s:%d: %s\n", current_file->name, current_file->lineno + 1, err);
442 exit(1);
443}
444
445void print_dep(int mask, struct statement *stmt)
446{
447 printd(mask, "dep: ");
448 if (stmt) {
449 if (stmt->dep2)
450 printd(mask, "[");
451 print_expr(mask, stmt->dep, 0);
452 if (stmt->dep2) {
453 printd(mask, " & ");
454 print_expr(mask, stmt->dep2, 0);
455 printd(mask, "]");
456 }
457 } else
458 print_expr(mask, if_expr, 0);
459 printd(mask, "\n");
460}
461
462struct symbol *lookup_symbol(char *name, int type)
463{
464 struct symbol *symbol;
465 char *ptr;
466 int hash = 0;
467
468 //printf("lookup: %s -> ", name);
469 if (type != SYMBOL_OTHER && !strncmp(name, "CONFIG_", 7)) {
470 name += 7;
471 } else {
472 //printf("Warning: Invalid symbol name '%s'\n", name);
473 type = SYMBOL_OTHER;
474 }
475
476 for (ptr = name; *ptr; ptr++)
477 hash += *ptr;
478
479 for (symbol = symbol_hash[hash&255]; symbol; symbol = symbol->next) {
480 if (!strcmp(symbol->name, name)) {
481 //printf("h:%p\n", symbol);
482 if (type == SYMBOL_BOOLEAN)
483 symbol->type = SYMBOL_BOOLEAN;
484 return symbol;
485 }
486 }
487
488 symbol = malloc(sizeof(*symbol));
489 memset(symbol, 0, sizeof(*symbol));
490 symbol->name = strdup(name);
491 symbol->type = type;
492
493 symbol->next = symbol_hash[hash&255];
494 symbol_hash[hash&255] = symbol;
495
496 //printf("n:%p\n", symbol);
497 return symbol;
498}
499
500struct symbol *lookup_symbol_ref(char *name)
501{
502 if (name[0] == 'y' && !name[1])
503 return &symbol_yes;
504 if (name[0] == 'm' && !name[1])
505 return &symbol_mod;
506 if (name[0] == 'n' && !name[1])
507 return &symbol_no;
508 if (name[0] == '$')
509 return lookup_symbol(name+1, SYMBOL_UNKNOWN);
510 return lookup_symbol(name, SYMBOL_OTHER);
511}
512
513struct statement *create_stmt(int token)
514{
515 struct statement *stmt;
516 struct menu *menu, **menup;
517
518 stmt = malloc(sizeof(*stmt));
519 memset(stmt, 0, sizeof(*stmt));
520 stmt->token = token;
521 stmt->file = current_file;
522 stmt->lineno = lineno();
523
524 if (!current_file->stmt)
525 current_file->stmt = stmt;
526 if (current_file->last_stmt)
527 current_file->last_stmt->next_pos = stmt;
528 current_file->last_stmt = stmt;
529
530 menu = malloc(sizeof(*menu));
531 memset(menu, 0, sizeof(*menu));
532 menu->prompt = stmt;
533 menu->parent = current_menu;
534 for (menup = &current_menu->list; *menup; menup = &(*menup)->next)
535 ;
536 *menup = menu;
537
538 stmt->menu = menu;
539
540 return stmt;
541}
542
543struct statement *add_stmt(struct symbol *sym, int token, char *prompt, struct symbol *def)
544{
545 struct statement *stmt = create_stmt(token);
546
547 stmt->dep = expr_copy(if_expr);
548 stmt->text = prompt;
549 stmt->def = def;
550
551 stmt->sym = sym;
552 stmt->next = sym->stmt;
553 sym->stmt = stmt;
554
555 return stmt;
556}
557
558void print_quoted_string(FILE *out, const char *str)
559{
560 const char *p;
561 int len;
562
563 putc('"', out);
564 while ((p = strchr(str, '"'))) {
565 len = p - str;
566 if (len)
567 fprintf(out, "%.*s", len, str);
568 fputs("\\\"", out);
569 str += len + 1;
570 }
571 fputs(str, out);
572 putc('"', out);
573}
574
575const char *skip_space(const char *p)
576{
577 while (*p == ' ')
578 p++;
579 return p;
580}
581
582void do_print_symbol(FILE *out, struct symbol *sym)
583{
584 struct statement *zero_stmt, *stmt, *stmt2;
585 struct expr *dep, *dep2;
586
587#define VALID_STMT(s) (s->token && s->token != '^' && s->menu && s->menu->parent == current_menu)
588
589 dep = NULL;
590 for (stmt = sym->stmt; stmt; stmt = stmt->next) {
591 if (!VALID_STMT(stmt))
592 continue;
593 if (!dep) {
594 if (!stmt->dep)
595 break;
596 dep = stmt->dep;
597 stmt->dep = NULL;
598 } else {
599 struct expr *e = dep;
600 if (stmt->dep) {
601 dep = extract_eq_and(&e, &stmt->dep);
602 if (expr_is_yes(e)) {
603 expr_free(e);
604 continue;
605 }
606 } else
607 dep = NULL;
608 for (stmt2 = sym->stmt; stmt != stmt2; stmt2 = stmt2->next) {
609 if (!VALID_STMT(stmt2))
610 continue;
611 stmt2->dep = !stmt2->dep ? expr_copy(e) :
612 expr_alloc_two(T_AND, expr_copy(e), stmt2->dep);
613 }
614 expr_free(e);
615 if (!dep)
616 break;
617 }
618 }
619
620 zero_stmt = NULL;
621 for (stmt = sym->stmt; stmt; stmt = stmt->next) {
622 if (!stmt->token)
623 zero_stmt = stmt;
624 if (VALID_STMT(stmt))
625 break;
626 }
627 if (!stmt) {
628 if (sym->flags & SYMBOL_PRINTED)
629 return;
630 if (!zero_stmt)
631 return;
632 for (stmt = sym->stmt; stmt; stmt = stmt->next) {
633 if (stmt->token)
634 return;
635 }
636 stmt = zero_stmt;
637 }
638
639 fprintf(out, "config %s\n", sym->name);
640
641 switch (sym->type) {
642 case SYMBOL_BOOLEAN: fputs("\tbool", out); break;
643 case SYMBOL_TRISTATE: fputs("\ttristate", out); break;
644 case SYMBOL_INT: fputs("\tint", out); break;
645 case SYMBOL_HEX: fputs("\thex", out); break;
646 case SYMBOL_STRING: fputs("\tstring", out); break;
647 default: fputs("\t#unknown type?", out); break;
648 }
649
650 if (stmt->text) {
651 fputc(' ', out);
652 print_quoted_string(out, skip_space(stmt->text));
653 if (!expr_is_yes(stmt->dep)) {
654 fputs(" if ", out);
655 fprint_expr(out, stmt->dep, 0);
656 }
657 stmt->menu = NULL;
658 stmt = stmt->next;
659 }
660 fputc('\n', out);
661
662 if (sym->dep || dep) {
663 dep = expr_alloc_and(expr_copy(sym->dep), dep);
664 dep = eliminate_yn(dep);
665 if (current_menu->prompt && current_menu->prompt->dep) {
666 dep2 = expr_copy(current_menu->prompt->dep);
667 switch (sym->type) {
668 case SYMBOL_BOOLEAN: case SYMBOL_INT: case SYMBOL_HEX: case SYMBOL_STRING:
669 dep2 = trans_bool_expr(dep2);
670 break;
671 }
672 eliminate_eq(T_AND, &dep, &dep2);
673 dep = eliminate_yn(dep);
674#if 0
675 dep2 = eliminate_yn(dep2);
676 if (!expr_is_yes(dep2)) {
677 printf("Warning, I'm still confused (%s)?\n", sym->name);
678 print_expr(PRINTD, dep, 0);
679 printf(" - ");
680 print_expr(PRINTD, dep2, 0);
681 printf("\n");
682 }
683#endif
684 expr_free(dep2);
685 }
686 if (!expr_is_yes(dep)) {
687 fputs("\tdepends on ", out);
688 fprint_expr(out, eliminate_yn(dep), 0);
689 fputc('\n', out);
690 }
691 }
692 for (; stmt; stmt = stmt->next) {
693 if (!VALID_STMT(stmt))
694 continue;
695 if (stmt->text) {
696 ;
697 } else if (stmt->def) {
698 if (sym->flags & SYMBOL_CHOICE)
699 printf("Choice value %s has default value!\n", sym->name);
700 fputs( "\tdefault ", out);
701 switch (sym->type) {
702 case SYMBOL_BOOLEAN:
703 case SYMBOL_TRISTATE:
704 fputs(stmt->def->name, out);
705 break;
706 default:
707 print_quoted_string(out, stmt->def->name);
708 break;
709 }
710 if (!expr_is_yes(stmt->dep)) {
711 fputs(" if ", out);
712 fprint_expr(out, eliminate_yn(stmt->dep), 0);
713 }
714 fputc('\n', out);
715 stmt->menu = NULL;
716 }
717 }
718 if (sym->help && !(sym->flags & SYMBOL_PRINTED)) {
719 int len = strlen(sym->help);
720 char *p, *p2;
721 int cnt;
722
723 while (sym->help[--len] == '\n')
724 sym->help[len] = 0;
725 for (p = sym->help, cnt = 0; (p = strchr(p, '\n')); p++, cnt++)
726 ;
727 if (cnt >= 9)
728 fprintf(out, "\t---help---\n");
729 else
730 fprintf(out, "\thelp\n");
731 for (p = sym->help;; p = p2 + 1) {
732 while (*p == ' ')
733 p++;
734 if (*p == '\n') {
735 fputc('\n', out);
736 p2 = p;
737 continue;
738 }
739 p2 = strchr(p, '\n');
740 if (!p2)
741 break;
742 fprintf(out, "\t %.*s\n", p2 - p, p);
743 }
744 fprintf(out, "\t %s\n", p);
745 }
746 fputc('\n', out);
747 for (stmt = sym->stmt; stmt; stmt = stmt->next) {
748 if (!VALID_STMT(stmt))
749 continue;
750 if (stmt->text) {
751 fprintf(out, "config %s\n", sym->name);
752 fputs( "\tprompt ", out);
753 print_quoted_string(out, skip_space(stmt->text));
754 fputc('\n', out);
755 dep2 = expr_alloc_and(expr_copy(dep), expr_copy(stmt->dep));
756 dep2 = eliminate_dups(dep2);
757 if (!expr_is_yes(dep2)) {
758 fputs("\tdepends on ", out);
759 fprint_expr(out, dep2, 0);
760 fputc('\n', out);
761 }
762 expr_free(dep2);
763 fputc('\n', out);
764 stmt->menu = NULL;
765 }
766 }
767 sym->flags |= SYMBOL_PRINTED;
768 expr_free(dep);
769}
770
771void print_choice(FILE *out, struct symbol *sym)
772{
773 struct statement *stmt;
774 struct expr *lst, *dep, *tmp, *tmp2;
775
776 if (sym->flags & SYMBOL_PRINTED)
777 return;
778
779 for (stmt = sym->stmt; stmt; stmt = stmt->next)
780 if (stmt->token == '^')
781 break;
782 if (!stmt)
783 //warn?
784 return;
785
786 fputs("choice\n", out);
787 if (stmt->text) {
788 fputs("\tprompt ", out);
789 print_quoted_string(out, skip_space(stmt->text));
790 fputc('\n', out);
791 }
792
793 dep = NULL;
794 for (lst = stmt->dep; lst; lst = lst->left.expr) {
795 sym = lst->right.sym;
796 if (sym == &symbol_no) {
797 fputs("\toptional\n", out);
798 continue;
799 }
800 if (!dep) {
801 if (!sym->dep)
802 break;
803 dep = sym->dep;
804 sym->dep = NULL;
805 } else {
806 tmp = dep;
807 if (sym->dep) {
808 dep = extract_eq_and(&tmp, &sym->dep);
809 if (expr_is_yes(tmp)) {
810 expr_free(tmp);
811 continue;
812 }
813 } else
814 dep = NULL;
815 for (tmp2 = stmt->dep; tmp2 != lst; tmp2 = tmp2->left.expr) {
816 sym = tmp2->right.sym;
817 if (sym == &symbol_no)
818 continue;
819 sym->dep = !sym->dep ? expr_copy(tmp) :
820 expr_alloc_two(T_AND, expr_copy(tmp), sym->dep);
821 sym->dep = eliminate_yn(sym->dep);
822 }
823 expr_free(tmp);
824 if (!dep)
825 break;
826 }
827 }
828 for (;lst; lst = lst->left.expr) {
829 sym = lst->right.sym;
830 if (sym == &symbol_no) {
831 fputs("\toptional\n", out);
832 continue;
833 }
834 }
835 if (!expr_is_yes(dep)) {
836 fputs("\tdepends on ", out);
837 fprint_expr(out, dep, 0);
838 fputc('\n', out);
839 }
840 if (stmt->def)
841 fprintf(out, "\tdefault %s\n", stmt->def->name);
842
843 fputc('\n', out);
844
845 for (lst = stmt->dep; lst; lst = lst->left.expr) {
846 sym = lst->right.sym;
847 if (sym == &symbol_no)
848 continue;
849 do_print_symbol(out, sym);
850 sym->flags |= SYMBOL_PRINTED;
851 }
852
853 fputs("endchoice\n\n", out);
854}
855
856void print_symbols(FILE *out, struct symbol *sym)
857{
858 //if (sym->flags & SYMBOL_PRINTED)
859 //return;
860 //sym->flags |= SYMBOL_PRINTED;
861
862 if (sym->flags & SYMBOL_CHOICE) {
863 print_choice(out, sym);
864 return;
865 }
866 do_print_symbol(out, sym);
867}
868
869char *gen_filename(const char *name)
870{
871 static char newname[128];
872 char *p;
873
874 strcpy(newname, name);
875 p = strrchr(newname, '/');
876 if (!p)
877 p = newname;
878 else
879 p++;
880#if 0
881 p = strrchr(p, '.');
882 if (!p)
883 p = newname + strlen(newname);
884 strcpy(p, ".new");
885#else
886#if 0
887 memcpy(p, "Build", 5);
888 memmove(p + 5, p + 6, strlen(p) - 5);
889 p = strrchr(p, '.');
890 if (!p)
891 p = newname + strlen(newname);
892 strcpy(p, ".conf");
893#else
894 memmove(p + 1, p, strlen(p) + 1);
895 p[0] = 'K';
896 p[1] = 'c';
897 p = strrchr(p, '.');
898 *p = 0;
899#endif
900#endif
901 return newname;
902}
903
904void print_files(FILE *all_out, const char *name)
905{
906 struct file *file;
907 FILE *out = all_out;
908 struct symbol *sym;
909 struct statement *stmt;
910 struct expr *dep1, *dep2;
911 char *p;
912
913 print_type = 0;
914
915 file = lookup_file(name);
916 if (!file) {
917 fprintf(stderr, "# file %s not found!\n\n", file->name);
918 return;
919 } else if (file->flags & FILE_PRINTED) {
920 fprintf(stderr, "# file %s skipped\n\n", file->name);
921 return;
922 }
923
924 if (!out) {
925 p = gen_filename(file->name);
926 strcat(p, ".lkc");
927 out = fopen(p, "w");
928 if (!out) {
929 printf("unable to open %s for writing!\n", p);
930 exit(1);
931 }
932 }
933
934 if (all_out)
935 fprintf(all_out, "# file %s\n\n", file->name);
936 file->flags |= FILE_PRINTED;
937
938 for (stmt = file->stmt; stmt; stmt = stmt->next_pos) {
939 sym = stmt->sym;
940 if (!sym) {
941 switch (stmt->token) {
942 case T_MAINMENU_NAME:
943 fputs("\nmainmenu ", out);
944 print_quoted_string(out, skip_space(stmt->text));
945 fputs("\n\n", out);
946 break;
947 case T_COMMENT:
948 fputs("comment ", out);
949 print_quoted_string(out, skip_space(stmt->text));
950 stmt->dep = eliminate_dups(trans_expr(stmt->dep));
951 dep1 = expr_copy(stmt->dep);
952 if (dep1 && current_menu->prompt && current_menu->prompt->dep) {
953 dep2 = expr_copy(current_menu->prompt->dep);
954 eliminate_eq(T_AND, &dep1, &dep2);
955 dep1 = eliminate_yn(dep1);
956 dep2 = eliminate_yn(dep2);
957 if (!expr_is_yes(dep2)) {
958 printf("Warning, I'm confused!\n");
959 }
960 expr_free(dep2);
961 }
962 if (!expr_is_yes(dep1)) {
963 dep1 = trans_bool_expr(dep1);
964 fputs("\n\tdepends on ", out);
965 fprint_expr(out, dep1, 0);
966 }
967 expr_free(dep1);
968 fputs("\n\n", out);
969 break;
970 case T_SH_COMMENT:
971 fprintf(out, "%s\n", stmt->text);
972 break;
973 case T_MAINMENU_OPTION:
974 fputs("\nmenu ", out);
975 print_quoted_string(out, skip_space(stmt->text));
976 stmt->dep = eliminate_dups(trans_expr(stmt->dep));
977 dep1 = expr_copy(stmt->dep);
978 if (dep1 && current_menu->prompt && current_menu->prompt->dep) {
979 dep2 = expr_copy(current_menu->prompt->dep);
980 eliminate_eq(T_AND, &dep1, &dep2);
981 dep1 = eliminate_yn(dep1);
982 dep2 = eliminate_yn(dep2);
983 if (!expr_is_yes(dep2)) {
984 printf("Warning, I'm confused!\n");
985 }
986 expr_free(dep2);
987 }
988 if (!expr_is_yes(dep1)) {
989 fputs("\n\tdepends on ", out);
990 fprint_expr(out, dep1, 0);
991 }
992 expr_free(dep1);
993 fputs("\n\n", out);
994 current_menu = stmt->menu;
995 break;
996 case T_ENDMENU:
997 fputs("endmenu\n\n", out);
998 current_menu = current_menu->parent;
999 break;
1000 case T_SOURCE:
1001 fprintf(out, "%ssource ", all_out ? "#" : "");
1002 print_quoted_string(out, gen_filename(stmt->text));
1003 fputs("\n\n", out);
1004 print_files(all_out, stmt->text);
1005 break;
1006 }
1007 } else
1008 print_symbols(out, sym);
1009 }
1010
1011 if (all_out)
1012 fprintf(out, "# fileend %s\n\n", file->name);
1013}
1014
1015static int trans_count;
1016
1017void eliminate_eq(int token, struct expr **ep1, struct expr **ep2)
1018{
1019#define e1 (*ep1)
1020#define e2 (*ep2)
1021
1022 if (e1->token == token) {
1023 eliminate_eq(token, &e1->left.expr, &e2);
1024 eliminate_eq(token, &e1->right.expr, &e2);
1025 return;
1026 }
1027 if (e2->token == token) {
1028 eliminate_eq(token, &e1, &e2->left.expr);
1029 eliminate_eq(token, &e1, &e2->right.expr);
1030 return;
1031 }
1032 if (e1->token == T_WORD && e2->token == T_WORD &&
1033 e1->left.sym == e2->left.sym && (e1->left.sym->flags & (SYMBOL_YES|SYMBOL_NO)))
1034 return;
1035 if (!expr_eq(e1, e2))
1036 return;
1037 trans_count++;
1038 expr_free(e1); expr_free(e2);
1039 switch (token) {
1040 case T_OR:
1041 e1 = expr_alloc_symbol(&symbol_no);
1042 e2 = expr_alloc_symbol(&symbol_no);
1043 break;
1044 case T_AND:
1045 e1 = expr_alloc_symbol(&symbol_yes);
1046 e2 = expr_alloc_symbol(&symbol_yes);
1047 break;
1048 }
1049#undef e1
1050#undef e2
1051}
1052
1053int expr_eq(struct expr *e1, struct expr *e2)
1054{
1055 int res, old_count;
1056
1057 if (e1->token != e2->token)
1058 return 0;
1059 switch (e1->token) {
1060 case '=':
1061 case T_UNEQUAL:
1062 return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
1063 case T_WORD:
1064 return e1->left.sym == e2->left.sym;
1065 case '!':
1066 return expr_eq(e1->left.expr, e2->left.expr);
1067 case T_AND:
1068 case T_OR:
1069 e1 = expr_copy(e1);
1070 e2 = expr_copy(e2);
1071 old_count = trans_count;
1072 eliminate_eq(e1->token, &e1, &e2);
1073 e1 = eliminate_yn(e1);
1074 e2 = eliminate_yn(e2);
1075 res = (e1->token == T_WORD &&
1076 e2->token == T_WORD &&
1077 e1->left.sym == e2->left.sym);
1078 expr_free(e1);
1079 expr_free(e2);
1080 trans_count = old_count;
1081 return res;
1082 }
1083 print_expr(PRINTD, e1, 0);
1084 printf(" = ");
1085 print_expr(PRINTD, e2, 0);
1086 printf(" ?\n");
1087 return 0;
1088}
1089
1090/*
1091 * dep_bool FOO -> FOO=y
1092 */
1093struct expr *trans_dep_bool(struct expr *e)
1094{
1095 switch (e->token) {
1096 case '&':
1097 case T_AND:
1098 e->left.expr = trans_dep_bool(e->left.expr);
1099 e->right.expr = trans_dep_bool(e->right.expr);
1100 break;
1101 case T_WORD:
1102 if (e->left.sym->type == SYMBOL_TRISTATE) {
1103 e->token = '=';
1104 e->right.sym = &symbol_yes;
1105 }
1106 break;
1107 }
1108 return e;
1109}
1110
1111/*
1112 * bool FOO!=n => FOO
1113 */
1114struct expr *trans_bool_expr(struct expr *e)
1115{
1116 if (!e)
1117 return NULL;
1118 switch (e->token) {
1119 case T_AND:
1120 case T_OR:
1121 case '!':
1122 e->left.expr = trans_bool_expr(e->left.expr);
1123 e->right.expr = trans_bool_expr(e->right.expr);
1124 break;
1125 case T_UNEQUAL:
1126 // FOO!=n -> FOO
1127 if (e->left.sym->type == SYMBOL_TRISTATE) {
1128 if (e->right.sym == &symbol_no) {
1129 e->token = T_WORD;
1130 e->right.sym = NULL;
1131 }
1132 }
1133 break;
1134 }
1135 return e;
1136}
1137
1138struct expr *fixup_expr(struct expr *e)
1139{
1140 struct expr *tmp;
1141
1142 if (!e)
1143 return NULL;
1144
1145 switch (e->token) {
1146 case T_IF:
1147 // if expr if expr ... -> expr && expr ...
1148 print_expr(DEBUG_OPT1, e, 0);
1149 printd(DEBUG_OPT1, " -> ");
1150 tmp = e->left.expr;
1151 if (!e->right.expr) {
1152 free(e);
1153 e = fixup_expr(tmp);
1154 print_expr(DEBUG_OPT1, e, 0);
1155 printd(DEBUG_OPT1, "\n");
1156 return e;
1157 }
1158 e->left.expr = e->right.expr;
1159 e->right.expr = tmp;
1160 e->token = T_AND;
1161 print_expr(DEBUG_OPT1, e, 0);
1162 printd(DEBUG_OPT1, "\n");
1163 break;
1164 case T_ELSE:
1165 // if expr else expr ... -> expr && !expr ...
1166 print_expr(DEBUG_OPT1, e, 0);
1167 printd(DEBUG_OPT1, " -> ");
1168 e->token = '!';
1169 if (!e->right.expr) {
1170 print_expr(DEBUG_OPT1, e, 0);
1171 printd(DEBUG_OPT1, "\n");
1172 break;
1173 }
1174 tmp = e;
1175 e = expr_alloc_two(T_AND, e->right.expr, e);
1176 tmp->right.expr = NULL;
1177 print_expr(DEBUG_OPT1, e, 0);
1178 printd(DEBUG_OPT1, "\n");
1179 break;
1180 case '&':
1181 // expr & expr -> expr && expr
1182 print_expr(DEBUG_OPT1, e, 0);
1183 printd(DEBUG_OPT1, " -> ");
1184 e->token = T_AND;
1185 print_expr(DEBUG_OPT1, e, 0);
1186 printd(DEBUG_OPT1, "\n");
1187 break;
1188 case '=':
1189 case T_UNEQUAL:
1190 if (!(e->left.sym->flags & SYMBOL_CONST))
1191 return e;
1192 if (e->right.sym->flags & SYMBOL_CONST) {
1193 if (e->left.sym == e->right.sym) {
1194 e->left.sym = e->token == '=' ? &symbol_yes : &symbol_no;
1195 } else {
1196 e->left.sym = e->token != '=' ? &symbol_yes : &symbol_no;
1197 }
1198 e->token = T_WORD;
1199 e->right.sym = NULL;
1200 } else {
1201 // y/n/m = sym -> sym = y/n/m
1202 struct symbol *sym;
1203 print_expr(DEBUG_OPT1, e, 0);
1204 printd(DEBUG_OPT1, " -> ");
1205 sym = e->left.sym;
1206 e->left.sym = e->right.sym;
1207 e->right.sym = sym;
1208 print_expr(DEBUG_OPT1, e, 0);
1209 printd(DEBUG_OPT1, "\n");
1210 }
1211 return e;
1212 case T_WORD:
1213 case '^':
1214 return e;
1215 }
1216 e->left.expr = fixup_expr(e->left.expr);
1217 e->right.expr = fixup_expr(e->right.expr);
1218 return e;
1219}
1220
1221struct expr *join_or(struct expr *e1, struct expr *e2)
1222{
1223 struct expr *tmp;
1224 struct symbol *sym1, *sym2;
1225
1226 if (expr_eq(e1, e2))
1227 return expr_copy(e1);
1228 if (e1->token != '=' && e1->token != T_UNEQUAL && e1->token != T_WORD && e1->token != '!')
1229 return NULL;
1230 if (e2->token != '=' && e2->token != T_UNEQUAL && e2->token != T_WORD && e2->token != '!')
1231 return NULL;
1232 if (e1->token == '!') {
1233 tmp = e1->left.expr;
1234 if (tmp->token != '=' && tmp->token != T_UNEQUAL && tmp->token != T_WORD)
1235 return NULL;
1236 sym1 = tmp->left.sym;
1237 } else
1238 sym1 = e1->left.sym;
1239 if (e2->token == '!') {
1240 if (e2->left.expr->token != T_WORD)
1241 return NULL;
1242 sym2 = e2->left.expr->left.sym;
1243 } else
1244 sym2 = e2->left.sym;
1245 if (sym1 != sym2)
1246 return NULL;
1247 if (sym1->type != SYMBOL_BOOLEAN && sym1->type != SYMBOL_TRISTATE)
1248 return NULL;
1249 if (sym1->type == SYMBOL_TRISTATE) {
1250 if (e1->token == '=' && e2->token == '=' &&
1251 ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
1252 (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
1253 // (a='y') || (a='m') -> (a!='n')
1254 return expr_alloc_comp(T_UNEQUAL, sym1, &symbol_no);
1255 }
1256 if (e1->token == '=' && e2->token == '=' &&
1257 ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
1258 (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
1259 // (a='y') || (a='n') -> (a!='m')
1260 return expr_alloc_comp(T_UNEQUAL, sym1, &symbol_mod);
1261 }
1262 if (e1->token == '=' && e2->token == '=' &&
1263 ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
1264 (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
1265 // (a='m') || (a='n') -> (a!='y')
1266 return expr_alloc_comp(T_UNEQUAL, sym1, &symbol_yes);
1267 }
1268 }
1269 if (sym1->type == SYMBOL_BOOLEAN && sym1 == sym2) {
1270 if ((e1->token == '!' && e1->left.expr->token == T_WORD && e2->token == T_WORD) ||
1271 (e2->token == '!' && e2->left.expr->token == T_WORD && e1->token == T_WORD))
1272 return expr_alloc_symbol(&symbol_yes);
1273 }
1274
1275 printf("optimize ");
1276 print_expr(PRINTD, e1, 0);
1277 printf(" || ");
1278 print_expr(PRINTD, e2, 0);
1279 printf(" ?\n");
1280 return NULL;
1281}
1282
1283struct expr *join_and(struct expr *e1, struct expr *e2)
1284{
1285 struct expr *tmp;
1286 struct symbol *sym1, *sym2;
1287
1288 if (expr_eq(e1, e2))
1289 return expr_copy(e1);
1290 if (e1->token != '=' && e1->token != T_UNEQUAL && e1->token != T_WORD && e1->token != '!')
1291 return NULL;
1292 if (e2->token != '=' && e2->token != T_UNEQUAL && e2->token != T_WORD && e2->token != '!')
1293 return NULL;
1294 if (e1->token == '!') {
1295 tmp = e1->left.expr;
1296 if (tmp->token != '=' && tmp->token != T_UNEQUAL && tmp->token != T_WORD)
1297 return NULL;
1298 sym1 = tmp->left.sym;
1299 } else
1300 sym1 = e1->left.sym;
1301 if (e2->token == '!') {
1302 if (e2->left.expr->token != T_WORD)
1303 return NULL;
1304 sym2 = e2->left.expr->left.sym;
1305 } else
1306 sym2 = e2->left.sym;
1307 if (sym1 != sym2)
1308 return NULL;
1309 if (sym1->type != SYMBOL_BOOLEAN && sym1->type != SYMBOL_TRISTATE)
1310 return NULL;
1311
1312 if ((e1->token == T_WORD && e2->token == '=' && e2->right.sym == &symbol_yes) ||
1313 (e2->token == T_WORD && e1->token == '=' && e1->right.sym == &symbol_yes))
1314 // (a) && (a='y') -> (a='y')
1315 return expr_alloc_comp('=', sym1, &symbol_yes);
1316
1317 if ((e1->token == T_WORD && e2->token == T_UNEQUAL && e2->right.sym == &symbol_no) ||
1318 (e2->token == T_WORD && e1->token == T_UNEQUAL && e1->right.sym == &symbol_no))
1319 // (a) && (a!='n') -> (a)
1320 return expr_alloc_symbol(sym1);
1321
1322 if (sym1->type == SYMBOL_TRISTATE) {
1323 if (e1->token == '=' && e2->token == T_UNEQUAL) {
1324 // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
1325 sym2 = e1->right.sym;
1326 if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
1327 return sym2 != e2->right.sym ? expr_alloc_comp('=', sym1, sym2)
1328 : expr_alloc_symbol(&symbol_no);
1329 }
1330 if (e1->token == T_UNEQUAL && e2->token == '=') {
1331 // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
1332 sym2 = e2->right.sym;
1333 if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
1334 return sym2 != e1->right.sym ? expr_alloc_comp('=', sym1, sym2)
1335 : expr_alloc_symbol(&symbol_no);
1336 }
1337 if (e1->token == T_UNEQUAL && e2->token == T_UNEQUAL &&
1338 ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
1339 (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
1340 // (a!='y') && (a!='n') -> (a='m')
1341 return expr_alloc_comp('=', sym1, &symbol_mod);
1342
1343 if (e1->token == T_UNEQUAL && e2->token == T_UNEQUAL &&
1344 ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
1345 (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
1346 // (a!='y') && (a!='m') -> (a='n')
1347 return expr_alloc_comp('=', sym1, &symbol_no);
1348
1349 if (e1->token == T_UNEQUAL && e2->token == T_UNEQUAL &&
1350 ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
1351 (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
1352 // (a!='m') && (a!='n') -> (a='m')
1353 return expr_alloc_comp('=', sym1, &symbol_yes);
1354
1355 if ((e1->token == T_WORD && e2->token == '=' && e2->right.sym == &symbol_mod) ||
1356 (e2->token == T_WORD && e1->token == '=' && e1->right.sym == &symbol_mod) ||
1357 (e1->token == T_WORD && e2->token == T_UNEQUAL && e2->right.sym == &symbol_yes) ||
1358 (e2->token == T_WORD && e1->token == T_UNEQUAL && e1->right.sym == &symbol_yes))
1359 return NULL;
1360 }
1361 printf("optimize ");
1362 print_expr(PRINTD, e1, 0);
1363 printf(" && ");
1364 print_expr(PRINTD, e2, 0);
1365 printf(" ?\n");
1366 return NULL;
1367}
1368
1369void eliminate_dups1(int token, struct expr **ep1, struct expr **ep2)
1370{
1371#define e1 (*ep1)
1372#define e2 (*ep2)
1373 struct expr *tmp;
1374
1375 if (e1->token == token) {
1376 eliminate_dups1(token, &e1->left.expr, &e2);
1377 eliminate_dups1(token, &e1->right.expr, &e2);
1378 return;
1379 }
1380 if (e2->token == token) {
1381 eliminate_dups1(token, &e1, &e2->left.expr);
1382 eliminate_dups1(token, &e1, &e2->right.expr);
1383 return;
1384 }
1385 if (e1 == e2)
1386 return;
1387
1388 switch (e1->token) {
1389 case T_OR: case T_AND:
1390 eliminate_dups1(e1->token, &e1, &e1);
1391 }
1392
1393 switch (token) {
1394 case T_OR:
1395 tmp = join_or(e1, e2);
1396 if (tmp) {
1397 expr_free(e1); expr_free(e2);
1398 e1 = expr_alloc_symbol(&symbol_no);
1399 e2 = tmp;
1400 trans_count++;
1401 }
1402 break;
1403 case T_AND:
1404 tmp = join_and(e1, e2);
1405 if (tmp) {
1406 expr_free(e1); expr_free(e2);
1407 e1 = expr_alloc_symbol(&symbol_yes);
1408 e2 = tmp;
1409 trans_count++;
1410 }
1411 break;
1412 }
1413#undef e1
1414#undef e2
1415}
1416
1417void eliminate_dups2(int token, struct expr **ep1, struct expr **ep2)
1418{
1419#define e1 (*ep1)
1420#define e2 (*ep2)
1421 struct expr *tmp, *tmp1, *tmp2;
1422
1423 if (e1->token == token) {
1424 eliminate_dups2(token, &e1->left.expr, &e2);
1425 eliminate_dups2(token, &e1->right.expr, &e2);
1426 return;
1427 }
1428 if (e2->token == token) {
1429 eliminate_dups2(token, &e1, &e2->left.expr);
1430 eliminate_dups2(token, &e1, &e2->right.expr);
1431 }
1432 if (e1 == e2)
1433 return;
1434
1435 switch (e1->token) {
1436 case T_OR:
1437 eliminate_dups2(e1->token, &e1, &e1);
1438 // (FOO || BAR) && (!FOO && !BAR) -> n
1439 tmp1 = trans_expr(expr_alloc_one('!', expr_copy(e1)));
1440 tmp2 = expr_copy(e2);
1441 tmp = extract_eq_and(&tmp1, &tmp2);
1442 if (expr_is_yes(tmp1)) {
1443 expr_free(e1);
1444 e1 = expr_alloc_symbol(&symbol_no);
1445 trans_count++;
1446 }
1447 expr_free(tmp2);
1448 expr_free(tmp1);
1449 expr_free(tmp);
1450 break;
1451 case T_AND:
1452 eliminate_dups2(e1->token, &e1, &e1);
1453 // (FOO && BAR) || (!FOO || !BAR) -> y
1454 tmp1 = trans_expr(expr_alloc_one('!', expr_copy(e1)));
1455 tmp2 = expr_copy(e2);
1456 tmp = extract_eq_or(&tmp1, &tmp2);
1457 if (expr_is_no(tmp1)) {
1458 expr_free(e1);
1459 e1 = expr_alloc_symbol(&symbol_yes);
1460 trans_count++;
1461 }
1462 expr_free(tmp2);
1463 expr_free(tmp1);
1464 expr_free(tmp);
1465 break;
1466 }
1467#undef e1
1468#undef e2
1469}
1470
1471struct expr *eliminate_dups(struct expr *e)
1472{
1473 int oldcount;
1474 if (!e)
1475 return e;
1476
1477 oldcount = trans_count;
1478 while (1) {
1479 trans_count = 0;
1480 switch (e->token) {
1481 case T_OR: case T_AND:
1482 eliminate_dups1(e->token, &e, &e);
1483 eliminate_dups2(e->token, &e, &e);
1484 }
1485 if (!trans_count)
1486 break;
1487 e = eliminate_yn(e);
1488 }
1489 trans_count = oldcount;
1490 return e;
1491}
1492
1493struct expr *eliminate_yn(struct expr *e)
1494{
1495 struct expr *tmp;
1496
1497 if (e) switch (e->token) {
1498 case T_AND:
1499 e->left.expr = eliminate_yn(e->left.expr);
1500 e->right.expr = eliminate_yn(e->right.expr);
1501 if (e->left.expr->token == T_WORD) {
1502 if (e->left.expr->left.sym == &symbol_no) {
1503 expr_free(e->left.expr);
1504 expr_free(e->right.expr);
1505 e->token = T_WORD;
1506 e->left.sym = &symbol_no;
1507 e->right.expr = NULL;
1508 return e;
1509 } else if (e->left.expr->left.sym == &symbol_yes) {
1510 free(e->left.expr);
1511 tmp = e->right.expr;
1512 *e = *(e->right.expr);
1513 free(tmp);
1514 return e;
1515 }
1516 }
1517 if (e->right.expr->token == T_WORD) {
1518 if (e->right.expr->left.sym == &symbol_no) {
1519 expr_free(e->left.expr);
1520 expr_free(e->right.expr);
1521 e->token = T_WORD;
1522 e->left.sym = &symbol_no;
1523 e->right.expr = NULL;
1524 return e;
1525 } else if (e->right.expr->left.sym == &symbol_yes) {
1526 free(e->right.expr);
1527 tmp = e->left.expr;
1528 *e = *(e->left.expr);
1529 free(tmp);
1530 return e;
1531 }
1532 }
1533 break;
1534 case T_OR:
1535 e->left.expr = eliminate_yn(e->left.expr);
1536 e->right.expr = eliminate_yn(e->right.expr);
1537 if (e->left.expr->token == T_WORD) {
1538 if (e->left.expr->left.sym == &symbol_no) {
1539 free(e->left.expr);
1540 tmp = e->right.expr;
1541 *e = *(e->right.expr);
1542 free(tmp);
1543 return e;
1544 } else if (e->left.expr->left.sym == &symbol_yes) {
1545 expr_free(e->left.expr);
1546 expr_free(e->right.expr);
1547 e->token = T_WORD;
1548 e->left.sym = &symbol_yes;
1549 e->right.expr = NULL;
1550 return e;
1551 }
1552 }
1553 if (e->right.expr->token == T_WORD) {
1554 if (e->right.expr->left.sym == &symbol_no) {
1555 free(e->right.expr);
1556 tmp = e->left.expr;
1557 *e = *(e->left.expr);
1558 free(tmp);
1559 return e;
1560 } else if (e->right.expr->left.sym == &symbol_yes) {
1561 expr_free(e->left.expr);
1562 expr_free(e->right.expr);
1563 e->token = T_WORD;
1564 e->left.sym = &symbol_yes;
1565 e->right.expr = NULL;
1566 return e;
1567 }
1568 }
1569 break;
1570 }
1571 return e;
1572}
1573
1574struct expr *trans_expr(struct expr *e)
1575{
1576 struct expr *tmp;
1577
1578 if (!e)
1579 return NULL;
1580 switch (e->token) {
1581 case '=':
1582 case T_UNEQUAL:
1583 case T_WORD:
1584 case '^':
1585 break;
1586 default:
1587 e->left.expr = trans_expr(e->left.expr);
1588 e->right.expr = trans_expr(e->right.expr);
1589 }
1590
1591 switch (e->token) {
1592 case '=':
1593 if (e->left.sym->type != SYMBOL_BOOLEAN)
1594 break;
1595 if (e->right.sym == &symbol_no) {
1596 print_expr(DEBUG_OPT2, e, 0);
1597 printd(DEBUG_OPT2, " -> ");
1598 e->token = '!';
1599 e->left.expr = expr_alloc_symbol(e->left.sym);
1600 e->right.sym = NULL;
1601 print_expr(DEBUG_OPT2, e, 0);
1602 printd(DEBUG_OPT2, "\n");
1603 break;
1604 }
1605 if (e->right.sym == &symbol_mod) {
1606 printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name);
1607 e->token = T_WORD;
1608 e->left.sym = &symbol_no;
1609 e->right.sym = NULL;
1610 break;
1611 }
1612 if (e->right.sym == &symbol_yes) {
1613 print_expr(DEBUG_OPT2, e, 0);
1614 printd(DEBUG_OPT2, " -> ");
1615 e->token = T_WORD;
1616 e->right.sym = NULL;
1617 print_expr(DEBUG_OPT2, e, 0);
1618 printd(DEBUG_OPT2, "\n");
1619 break;
1620 }
1621 break;
1622 case T_UNEQUAL:
1623 if (e->left.sym->type != SYMBOL_BOOLEAN)
1624 break;
1625 if (e->right.sym == &symbol_no) {
1626 print_expr(DEBUG_OPT2, e, 0);
1627 printd(DEBUG_OPT2, " -> ");
1628 e->token = T_WORD;
1629 e->right.sym = NULL;
1630 print_expr(DEBUG_OPT2, e, 0);
1631 printd(DEBUG_OPT2, "\n");
1632 break;
1633 }
1634 if (e->right.sym == &symbol_mod) {
1635 printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name);
1636 e->token = T_WORD;
1637 e->left.sym = &symbol_yes;
1638 e->right.sym = NULL;
1639 break;
1640 }
1641 if (e->right.sym == &symbol_yes) {
1642 print_expr(DEBUG_OPT2, e, 0);
1643 printd(DEBUG_OPT2, " -> ");
1644 e->token = '!';
1645 e->left.expr = expr_alloc_symbol(e->left.sym);
1646 e->right.sym = NULL;
1647 print_expr(DEBUG_OPT2, e, 0);
1648 printd(DEBUG_OPT2, "\n");
1649 break;
1650 }
1651 break;
1652 case '!':
1653 switch (e->left.expr->token) {
1654 case '!':
1655 // !!a -> a
1656 print_expr(DEBUG_OPT2, e, 0);
1657 printd(DEBUG_OPT2, " -> ");
1658 tmp = e->left.expr->left.expr;
1659 free(e->left.expr);
1660 free(e);
1661 e = tmp;
1662 print_expr(DEBUG_OPT2, e, 0);
1663 printd(DEBUG_OPT2, "\n");
1664 e = trans_expr(e);
1665 break;
1666 case '=':
1667 case T_UNEQUAL:
1668 // !a='x' -> a!='x'
1669 print_expr(DEBUG_OPT2, e, 0);
1670 printd(DEBUG_OPT2, " -> ");
1671 tmp = e->left.expr;
1672 free(e);
1673 e = tmp;
1674 if (e->token == '=')
1675 e->token = T_UNEQUAL;
1676 else
1677 e->token = '=';
1678 print_expr(DEBUG_OPT2, e, 0);
1679 printd(DEBUG_OPT2, "\n");
1680 break;
1681 case T_OR:
1682 // !(a || b) -> !a && !b
1683 print_expr(DEBUG_OPT2, e, 0);
1684 printd(DEBUG_OPT2, " -> ");
1685 tmp = e->left.expr;
1686 e->token = T_AND;
1687 e->right.expr = expr_alloc_one('!', tmp->right.expr);
1688 tmp->token = '!';
1689 tmp->right.expr = NULL;
1690 print_expr(DEBUG_OPT2, e, 0);
1691 printd(DEBUG_OPT2, "\n");
1692 e = trans_expr(e);
1693 break;
1694 case T_AND:
1695 // !(a && b) -> !a || !b
1696 print_expr(DEBUG_OPT2, e, 0);
1697 printd(DEBUG_OPT2, " -> ");
1698 tmp = e->left.expr;
1699 e->token = T_OR;
1700 e->right.expr = expr_alloc_one('!', tmp->right.expr);
1701 tmp->token = '!';
1702 tmp->right.expr = NULL;
1703 print_expr(DEBUG_OPT2, e, 0);
1704 printd(DEBUG_OPT2, "\n");
1705 e = trans_expr(e);
1706 break;
1707 case T_WORD:
1708 if (e->left.expr->left.sym == &symbol_yes) {
1709 // !'y' -> 'n'
1710 print_expr(DEBUG_OPT2, e, 0);
1711 printd(DEBUG_OPT2, " -> ");
1712 tmp = e->left.expr;
1713 free(e);
1714 e = tmp;
1715 e->token = T_WORD;
1716 e->left.sym = &symbol_no;
1717 print_expr(DEBUG_OPT2, e, 0);
1718 printd(DEBUG_OPT2, "\n");
1719 break;
1720 }
1721 if (e->left.expr->left.sym == &symbol_no) {
1722 // !'n' -> 'y'
1723 print_expr(DEBUG_OPT2, e, 0);
1724 printd(DEBUG_OPT2, " -> ");
1725 tmp = e->left.expr;
1726 free(e);
1727 e = tmp;
1728 e->token = T_WORD;
1729 e->left.sym = &symbol_yes;
1730 print_expr(DEBUG_OPT2, e, 0);
1731 printd(DEBUG_OPT2, "\n");
1732 break;
1733 }
1734 break;
1735 }
1736 break;
1737 }
1738 return e;
1739}
1740
1741struct expr *extract_eq_and(struct expr **ep1, struct expr **ep2)
1742{
1743 struct expr *tmp = NULL;
1744 extract_eq(T_AND, &tmp, ep1, ep2);
1745 if (tmp) {
1746 *ep1 = eliminate_yn(*ep1);
1747 *ep2 = eliminate_yn(*ep2);
1748 }
1749 return tmp;
1750}
1751
1752struct expr *extract_eq_or(struct expr **ep1, struct expr **ep2)
1753{
1754 struct expr *tmp = NULL;
1755 extract_eq(T_OR, &tmp, ep1, ep2);
1756 if (tmp) {
1757 *ep1 = eliminate_yn(*ep1);
1758 *ep2 = eliminate_yn(*ep2);
1759 }
1760 return tmp;
1761}
1762
1763void extract_eq(int token, struct expr **ep, struct expr **ep1, struct expr **ep2)
1764{
1765#define e1 (*ep1)
1766#define e2 (*ep2)
1767 if (e1->token == token) {
1768 extract_eq(token, ep, &e1->left.expr, &e2);
1769 extract_eq(token, ep, &e1->right.expr, &e2);
1770 return;
1771 }
1772 if (e2->token == token) {
1773 extract_eq(token, ep, ep1, &e2->left.expr);
1774 extract_eq(token, ep, ep1, &e2->right.expr);
1775 return;
1776 }
1777 if (expr_eq(e1, e2)) {
1778 *ep = *ep ? expr_alloc_two(token, *ep, e1) : e1;
1779 expr_free(e2);
1780 if (token == T_AND) {
1781 e1 = expr_alloc_symbol(&symbol_yes);
1782 e2 = expr_alloc_symbol(&symbol_yes);
1783 } else if (token == T_OR) {
1784 e1 = expr_alloc_symbol(&symbol_no);
1785 e2 = expr_alloc_symbol(&symbol_no);
1786 }
1787 }
1788#undef e1
1789#undef e2
1790}
1791
1792struct expr *optimize_expr_or(struct expr *e)
1793{
1794 struct expr *tmp;
1795
1796 if (!e || e->token != T_OR)
1797 return e;
1798
1799 e->left.expr = optimize_expr_or(e->left.expr);
1800 e->right.expr = optimize_expr_or(e->right.expr);
1801
1802 tmp = extract_eq_and(&e->left.expr, &e->right.expr);
1803 if (!tmp)
1804 return e;
1805 return expr_alloc_two(T_AND, tmp, e);
1806}
1807
1808int contains_expr(struct expr *dep, struct expr *e)
1809{
1810 if (!dep)
1811 return 0;
1812 if (dep->token == T_AND)
1813 return contains_expr(dep->left.expr, e) || contains_expr(dep->right.expr, e);
1814 return expr_eq(dep, e);
1815}
1816
1817struct expr *trans_comp_expr(struct expr *e, int token, struct symbol *sym)
1818{
1819 struct expr *e1, *e2;
1820
1821 switch (e->token) {
1822 case T_AND:
1823 e1 = trans_comp_expr(e->left.expr, '=', sym);
1824 e2 = trans_comp_expr(e->right.expr, '=', sym);
1825 if (sym == &symbol_yes)
1826 e = expr_alloc_two(T_AND, e1, e2);
1827 if (sym == &symbol_no)
1828 e = expr_alloc_two(T_OR, e1, e2);
1829 if (token == T_UNEQUAL)
1830 e = expr_alloc_one('!', e);
1831 return e;
1832 case T_OR:
1833 e1 = trans_comp_expr(e->left.expr, '=', sym);
1834 e2 = trans_comp_expr(e->right.expr, '=', sym);
1835 if (sym == &symbol_yes)
1836 e = expr_alloc_two(T_OR, e1, e2);
1837 if (sym == &symbol_no)
1838 e = expr_alloc_two(T_AND, e1, e2);
1839 if (token == T_UNEQUAL)
1840 e = expr_alloc_one('!', e);
1841 return e;
1842 case '!':
1843 switch (token) {
1844 case '=':
1845 return trans_comp_expr(e->left.expr, T_UNEQUAL, sym);
1846 case T_UNEQUAL:
1847 return trans_comp_expr(e->left.expr, '=', sym);
1848 }
1849 break;
1850 case T_UNEQUAL:
1851 case '=':
1852 if (token == '=') {
1853 if (sym == &symbol_yes)
1854 return expr_copy(e);
1855 if (sym == &symbol_mod)
1856 return expr_alloc_symbol(&symbol_no);
1857 if (sym == &symbol_no)
1858 return expr_alloc_one('!', expr_copy(e));
1859 } else {
1860 if (sym == &symbol_yes)
1861 return expr_alloc_one('!', expr_copy(e));
1862 if (sym == &symbol_mod)
1863 return expr_alloc_symbol(&symbol_yes);
1864 if (sym == &symbol_no)
1865 return expr_copy(e);
1866 }
1867 break;
1868 case T_WORD:
1869 return expr_alloc_comp(token, e->left.sym, sym);
1870 }
1871 return NULL;
1872}
1873
1874void eliminate_dep(struct symbol *sym, struct expr *dep)
1875{
1876 struct symbol *sym2;
1877 struct expr *dep2;
1878
1879 if (dep->token == T_AND) {
1880 eliminate_dep(sym, dep->left.expr);
1881 eliminate_dep(sym, dep->right.expr);
1882 }
1883#if 0
1884 if (dep->token == T_WORD ||
1885 (sym->type == SYMBOL_BOOLEAN &&
1886 ((dep->token == T_UNEQUAL && dep->right.sym == &symbol_no) ||
1887 (dep->token == '=' && dep->right.sym == &symbol_yes)))) {
1888 sym2 = dep->left.sym;
1889 if (sym2->dep) {
1890 if (!sym2->dep2)
1891 eliminate_dep(sym2, sym2->dep);
1892 sym->dep2 = !sym->dep2 ? expr_copy(sym2->dep2)
1893 : expr_alloc_two(T_AND, expr_copy(sym2->dep2), sym->dep2);
1894 }
1895 }
1896#else
1897 switch (dep->token) {
1898 case T_WORD:
1899 case T_UNEQUAL:
1900 case '=':
1901 sym2 = dep->left.sym;
1902 if (sym2->type != SYMBOL_BOOLEAN && sym2->type != SYMBOL_TRISTATE)
1903 break;
1904 if (!sym2->dep)
1905 break;
1906 if (!sym2->dep2)
1907 eliminate_dep(sym2, sym2->dep);
1908 if (dep->token == T_WORD) {
1909 if (sym2->type == SYMBOL_BOOLEAN)
1910 dep2 = trans_comp_expr(sym2->dep2, T_UNEQUAL, &symbol_no);
1911 else
1912 dep2 = expr_copy(sym2->dep2);
1913 } else {
1914 //if ((dep->token == T_UNEQUAL && dep->right.sym == &symbol_no) ||
1915 // (sym2->type == SYMBOL_BOOLEAN &&
1916 // dep->token == '=' && dep->right.sym == &symbol_yes))
1917 if ((dep->token == '=' && dep->right.sym == &symbol_yes) ||
1918 (sym2->type == SYMBOL_BOOLEAN &&
1919 dep->token == T_UNEQUAL && dep->right.sym == &symbol_no))
1920 dep2 = trans_comp_expr(sym2->dep2, dep->token, dep->right.sym);
1921 else
1922 break;
1923 }
1924 dep2 = eliminate_yn(trans_expr(fixup_expr(dep2)));
1925 sym->dep2 = !sym->dep2 ? dep2 : expr_alloc_two(T_AND, dep2, sym->dep2);
1926 }
1927#endif
1928 if (sym->dep == dep) {
1929 printd(DEBUG_DEP, "el: %s (", sym->name);
1930 print_expr(DEBUG_DEP, sym->dep, 0);
1931 printd(DEBUG_DEP, ")\n");
1932 if (sym->dep2) {
1933 print_expr(DEBUG_DEP, sym->dep2, 0); printd(DEBUG_DEP, "\n");
1934 sym->dep2 = eliminate_yn(eliminate_dups(sym->dep2));
1935 switch (sym->type) {
1936 case SYMBOL_BOOLEAN: case SYMBOL_INT: case SYMBOL_HEX: case SYMBOL_STRING:
1937 sym->dep2 = trans_bool_expr(sym->dep2);
1938 break;
1939 }
1940 print_expr(DEBUG_DEP, sym->dep2, 0); printd(DEBUG_DEP, "\n");
1941 sym->dep = expr_alloc_two(T_AND, expr_copy(sym->dep2), sym->dep);
1942 sym->dep = eliminate_dups(sym->dep);
1943 print_expr(DEBUG_DEP, sym->dep, 0); printd(DEBUG_DEP, "\n");
1944 dep = expr_copy(sym->dep2);
1945 eliminate_eq(T_AND, &dep, &sym->dep);
1946 sym->dep = eliminate_yn(sym->dep);
1947 sym->dep2 = expr_alloc_two(T_AND, sym->dep2, expr_copy(sym->dep));
1948 } else
1949 sym->dep2 = expr_copy(sym->dep);
1950 printd(DEBUG_DEP, " -> ");
1951 print_expr(DEBUG_DEP, sym->dep2, 0);
1952 printd(DEBUG_DEP, " -> ");
1953 print_expr(DEBUG_DEP, sym->dep, 0);
1954 printd(DEBUG_DEP, "\n");
1955 }
1956}
1957
1958struct symbol * dep_check_symbol(struct symbol *sym);
1959
1960struct symbol *dep_check_expr(struct expr *e)
1961{
1962 struct symbol *sym;
1963 if (!e)
1964 return 0;
1965 switch (e->token) {
1966 case T_WORD:
1967 case T_WORD_QUOTE:
1968 case T_WORD_DQUOTE:
1969 return dep_check_symbol(e->left.sym);
1970 case '=':
1971 case T_UNEQUAL:
1972 sym = dep_check_symbol(e->left.sym);
1973 if (sym)
1974 return sym;
1975 return dep_check_symbol(e->right.sym);
1976 case T_OR:
1977 case T_AND:
1978 sym = dep_check_expr(e->left.expr);
1979 if (sym)
1980 return sym;
1981 return dep_check_expr(e->right.expr);
1982 case '!':
1983 return dep_check_expr(e->left.expr);
1984 }
1985 printf("how to check %d?\n", e->token);
1986 return NULL;
1987}
1988
1989struct symbol *dep_check_symbol(struct symbol *sym)
1990{
1991 struct statement *stmt, *stmt2;
1992 struct symbol *sym2;
1993 struct expr *e1, *e2;
1994
1995 if (sym->flags & SYMBOL_CHECK) {
1996 printf("recursive dependency: %s", sym->name);
1997 return sym;
1998 }
1999
2000 sym->flags |= SYMBOL_CHECK;
2001 sym2 = dep_check_expr(sym->dep);
2002 if (sym2) {
2003 printf(" %s", sym->name);
2004 if (sym->type != sym2->type)
2005 goto out;
2006 switch (sym->type) {
2007 case SYMBOL_TRISTATE:
2008 e1 = expr_alloc_comp(T_UNEQUAL, sym, &symbol_yes);
2009 e2 = expr_alloc_comp(T_UNEQUAL, sym2, &symbol_yes);
2010 break;
2011 case SYMBOL_BOOLEAN:
2012 e1 = expr_alloc_one('!', expr_alloc_symbol(sym));
2013 e2 = expr_alloc_one('!', expr_alloc_symbol(sym2));
2014 break;
2015 default:
2016 goto out;
2017 }
2018 if (contains_expr(sym->dep, e2) && contains_expr(sym2->dep, e1)) {
2019 printf(" (choice(%d) detected)", sym->type);
2020 sym->flags |= SYMBOL_CHOICE;
2021 eliminate_eq(T_AND, &sym->dep, &e2);
2022 sym->dep = eliminate_yn(sym->dep);
2023 sym2->flags |= SYMBOL_CHOICE;
2024 eliminate_eq(T_AND, &sym2->dep, &e1);
2025 sym2->dep = eliminate_yn(sym2->dep);
2026 stmt = malloc(sizeof(*stmt));
2027 memset(stmt, 0, sizeof(*stmt));
2028 stmt->token = '^';
2029 stmt->text = "change me!";
2030 stmt->dep = expr_alloc_one('^', NULL);
2031 stmt->dep->right.sym = sym;
2032 stmt->dep = expr_alloc_one('^', stmt->dep);
2033 stmt->dep->right.sym = sym2;
2034 stmt->dep = expr_alloc_one('^', stmt->dep);
2035 stmt->dep->right.sym = &symbol_no;
2036 for (stmt2 = sym->stmt; stmt2->next; stmt2 = stmt2->next)
2037 ;
2038 if (stmt2->token == '^')
2039 printf("warning: symbol %s has dup choice statement?\n", sym->name);
2040 else
2041 stmt2->next = stmt;
2042 for (stmt2 = sym2->stmt; stmt2->next; stmt2 = stmt2->next)
2043 ;
2044 if (stmt2->token == '^')
2045 printf("warning: symbol %s has dup choice statement?\n", sym->name);
2046 else
2047 stmt2->next = stmt;
2048 }
2049 expr_free(e1);
2050 expr_free(e2);
2051 }
2052 if (!sym2) for (stmt = sym->stmt; stmt; stmt = stmt->next) {
2053 if (!stmt->token || stmt->token == '^')
2054 continue;
2055 sym2 = dep_check_expr(stmt->dep);
2056 if (sym2) {
2057 printf(" %s", sym->name);
2058 break;
2059 }
2060 }
2061out:
2062 sym->flags &= ~SYMBOL_CHECK;
2063
2064 return sym2;
2065}
2066
2067const char *sym_typename(int type)
2068{
2069 switch (type) {
2070 case SYMBOL_UNKNOWN: return "unknown";
2071 case SYMBOL_BOOLEAN: return "bool";
2072 case SYMBOL_TRISTATE: return "tristate";
2073 case SYMBOL_INT: return "integer";
2074 case SYMBOL_HEX: return "hex";
2075 case SYMBOL_STRING: return "string";
2076 case SYMBOL_OTHER: return "other";
2077 default: return "???";
2078 }
2079}
2080
2081void optimize_config(void)
2082{
2083 struct symbol *sym;
2084 struct statement *stmt, *stmt2, **stmtp;
2085 struct expr *e;
2086 int i;
2087
2088 for_all_symbols(i, sym) {
2089 again:
2090 for (stmt = sym->stmt; stmt; stmt = stmt->next) {
2091 switch (stmt->token) {
2092 case '^':
2093 case T_BOOL:
2094 case T_DEP_BOOL:
2095 case T_DEP_MBOOL:
2096 if (sym->type == SYMBOL_UNKNOWN)
2097 sym->type = SYMBOL_BOOLEAN;
2098 if (sym->type != SYMBOL_BOOLEAN)
2099 printf("%s:%d:warning: symbol %s has conflicting types (%s,%s)\n",
2100 stmt->file->name, stmt->lineno, sym->name,
2101 sym_typename(sym->type), sym_typename(SYMBOL_BOOLEAN));
2102 if (sym->type == SYMBOL_TRISTATE) {
2103 printf("%s:%d:Force stmt to dep_tristate\n",
2104 stmt->file->name, stmt->lineno);
2105 stmt->token = T_DEP_TRISTATE;
2106 }
2107 break;
2108 case T_DEFINE_BOOL:
2109 if (stmt->def == &symbol_mod) {
2110 printf("%s:%d:warning: symbol %s set to 'm', force stmt to define_tristate\n",
2111 stmt->file->name, stmt->lineno, sym->name);
2112 stmt->token = T_DEFINE_TRISTATE;
2113 }
2114 break;
2115 case T_HEX:
2116 if (sym->type == SYMBOL_UNKNOWN)
2117 sym->type = SYMBOL_HEX;
2118 if (sym->type != SYMBOL_HEX)
2119 printf("%s:%d:warning: symbol %s has conflicting types (%s,%s)\n",
2120 stmt->file->name, stmt->lineno, sym->name,
2121 sym_typename(sym->type), sym_typename(SYMBOL_HEX));
2122 break;
2123 case T_INT:
2124 if (sym->type == SYMBOL_UNKNOWN)
2125 sym->type = SYMBOL_INT;
2126 if (sym->type != SYMBOL_INT)
2127 printf("%s:%d:warning: symbol %s has conflicting types (%s,%s)\n",
2128 stmt->file->name, stmt->lineno, sym->name,
2129 sym_typename(sym->type), sym_typename(SYMBOL_INT));
2130 break;
2131 case T_STRING:
2132 if (sym->type == SYMBOL_UNKNOWN)
2133 sym->type = SYMBOL_STRING;
2134 if (sym->type != SYMBOL_STRING)
2135 printf("%s:%d:warning: symbol %s has conflicting types (%s,%s)\n",
2136 stmt->file->name, stmt->lineno, sym->name,
2137 sym_typename(sym->type), sym_typename(SYMBOL_STRING));
2138 break;
2139 case T_TRISTATE:
2140 case T_DEP_TRISTATE:
2141 if (sym->type == SYMBOL_UNKNOWN)
2142 sym->type = SYMBOL_TRISTATE;
2143 if (sym->type != SYMBOL_TRISTATE) {
2144 printf("%s:%d:warning: symbol %s has conflicting types (%s,%s), force symbol to tristate\n",
2145 stmt->file->name, stmt->lineno, sym->name,
2146 sym_typename(sym->type), sym_typename(SYMBOL_TRISTATE));
2147 sym->type = SYMBOL_TRISTATE;
2148 goto again;
2149 }
2150 break;
2151 }
2152 }
2153 for (stmt = sym->stmt; stmt; stmt = stmt->next) {
2154 switch (stmt->token) {
2155 case T_DEFINE_BOOL:
2156 if (sym->type == SYMBOL_UNKNOWN)
2157 sym->type = SYMBOL_BOOLEAN;
2158 if (sym->type != SYMBOL_BOOLEAN)
2159 printf("%s:%d:warning: symbol %s has conflicting types (%s,%s)\n",
2160 stmt->file->name, stmt->lineno, sym->name,
2161 sym_typename(sym->type), sym_typename(SYMBOL_BOOLEAN));
2162 if (sym->type == SYMBOL_TRISTATE) {
2163 printf("%s:%d:Force stmt to define_tristate\n",
2164 stmt->file->name, stmt->lineno);
2165 stmt->token = T_DEFINE_TRISTATE;
2166 }
2167 break;
2168 case T_DEFINE_TRISTATE:
2169 if (sym->type == SYMBOL_UNKNOWN)
2170 sym->type = SYMBOL_TRISTATE;
2171 if (sym->type != SYMBOL_TRISTATE) {
2172 printf("%s:%d:warning: symbol %s has conflicting types (%s,%s), force symbol to tristate\n",
2173 stmt->file->name, stmt->lineno, sym->name,
2174 sym_typename(sym->type), sym_typename(SYMBOL_TRISTATE));
2175 sym->type = SYMBOL_TRISTATE;
2176 goto again;
2177 }
2178 break;
2179 case T_DEFINE_HEX:
2180 if (sym->type == SYMBOL_UNKNOWN)
2181 sym->type = SYMBOL_HEX;
2182 if (sym->type != SYMBOL_HEX)
2183 printf("%s:%d:warning: symbol %s has conflicting types (%s,%s)\n",
2184 stmt->file->name, stmt->lineno, sym->name,
2185 sym_typename(sym->type), sym_typename(SYMBOL_HEX));
2186 break;
2187 case T_DEFINE_INT:
2188 if (sym->type == SYMBOL_UNKNOWN)
2189 sym->type = SYMBOL_INT;
2190 if (sym->type != SYMBOL_INT)
2191 printf("%s:%d:warning: symbol %s has conflicting types (%s,%s)\n",
2192 stmt->file->name, stmt->lineno, sym->name,
2193 sym_typename(sym->type), sym_typename(SYMBOL_INT));
2194 break;
2195 case T_DEFINE_STRING:
2196 if (sym->type == SYMBOL_UNKNOWN)
2197 sym->type = SYMBOL_STRING;
2198 if (sym->type != SYMBOL_STRING)
2199 printf("%s:%d:warning: symbol %s has conflicting types (%s,%s)\n",
2200 stmt->file->name, stmt->lineno, sym->name,
2201 sym_typename(sym->type), sym_typename(SYMBOL_STRING));
2202 break;
2203 }
2204 }
2205 }
2206 for_all_symbols(i, sym) {
2207 printd(DEBUG_OPT1, "o1: %s\n", sym->name);
2208 for (stmt = sym->stmt; stmt; stmt = stmt->next) {
2209 print_expr(DEBUG_OPT1, stmt->dep, 0);
2210 printd(DEBUG_OPT1, " & ");
2211 print_expr(DEBUG_OPT1, stmt->dep2, 0);
2212 printd(DEBUG_OPT1, "\n");
2213 if (stmt->dep || stmt->dep2) {
2214 struct expr *e = stmt->dep2;
2215 if (stmt->token == T_DEP_BOOL) {
2216 e = trans_dep_bool(e);
2217 stmt->token = T_DEP_MBOOL;
2218 }
2219 if (stmt->dep && e) {
2220 stmt->dep = expr_alloc_two(T_AND, stmt->dep, e);
2221 } else if (e)
2222 stmt->dep = e;
2223 stmt->dep2 = NULL;
2224 switch (stmt->token) {
2225 case T_DEP_MBOOL:stmt->token = T_BOOL; break;
2226 case T_DEP_TRISTATE:stmt->token = T_TRISTATE; break;
2227 }
2228 }
2229 stmt->dep = fixup_expr(stmt->dep);
2230 print_expr(DEBUG_OPT1, stmt->dep, 0);
2231 printd(DEBUG_OPT1, "\n");
2232 }
2233 }
2234 for_all_symbols(i, sym) {
2235 printd(DEBUG_OPT3, "o3: %s\n", sym->name);
2236 for (stmt = sym->stmt; stmt; stmt = stmt->next) {
2237 print_expr(DEBUG_OPT3, stmt->dep, 0);
2238 printd(DEBUG_OPT3, "\n");
2239 stmt->dep = eliminate_dups(trans_expr(stmt->dep));
2240 switch (sym->type) {
2241 case SYMBOL_BOOLEAN: case SYMBOL_INT: case SYMBOL_HEX: case SYMBOL_STRING:
2242 stmt->dep = trans_bool_expr(stmt->dep);
2243 break;
2244 }
2245 print_expr(DEBUG_OPT3, stmt->dep, 0);
2246 printd(DEBUG_OPT3, "\n");
2247 }
2248 }
2249 for_all_symbols(i, sym) {
2250 sym->dep = eliminate_yn(sym->dep);
2251 for (stmt = sym->stmt; stmt; stmt = stmt->next) {
2252 stmt->dep = eliminate_yn(stmt->dep);
2253 if (expr_is_no(stmt->dep)) {
2254 printf("%s:%d: stmt can never be reached, removed!\n", stmt->file->name, stmt->lineno);
2255 stmt->token = 0;
2256 }
2257 }
2258 }
2259 for_all_symbols(i, sym) {
2260 stmtp = &sym->stmt;
2261 stmt = *stmtp;
2262 if (!stmt) {
2263 printf("undefined symbol %s\n", sym->name);
2264 continue;
2265 }
2266 //if (sym->flags & SYMBOL_CHOICE)
2267 //continue;
2268 while (stmt) {
2269 if (!stmt->token || stmt->token == '^') {
2270 stmtp = &stmt->next;
2271 stmt = *stmtp;
2272 continue;
2273 }
2274#if 1
2275 if ((stmt->token == T_DEFINE_BOOL || stmt->token == T_DEFINE_TRISTATE) &&
2276 (stmt->def == &symbol_no || expr_is_no(stmt->dep))) {
2277 stmt->token = 0;
2278 stmt->def = NULL;
2279 expr_free(stmt->dep);
2280 stmt->dep = NULL;
2281 continue;
2282 }
2283#endif
2284 //if (stmt->text && stmt != sym->stmt) {
2285 //if (sym->stmt->text)
2286 // printf("warning: another stmt with prompt for %s????\n", sym->name);
2287 //*stmtp = stmt->next;
2288 //stmt->next = sym->stmt;
2289 //sym->stmt = stmt;
2290 //}
2291 for (stmt2 = stmt->next; stmt2; stmt2 = stmt2->next) {
2292 if (stmt->token != stmt2->token || stmt->def != stmt2->def ||
2293 stmt->menu->parent != stmt2->menu->parent)
2294 continue;
2295 if (stmt->text) {
2296 if (strcmp(skip_space(stmt->text), skip_space(stmt2->text))) {
2297 printf("warning: prompts differ for %s?\n", sym->name);
2298 continue;
2299 }
2300 }
2301 if (!stmt->dep)
2302 stmt->dep = expr_alloc_symbol(&symbol_yes);
2303 if (!stmt2->dep)
2304 stmt2->dep = expr_alloc_symbol(&symbol_yes);
2305 stmt->dep = optimize_expr_or(expr_alloc_two(T_OR, stmt->dep, stmt2->dep));
2306 stmt2->token = 0;
2307 free((void *)stmt2->text);
2308 stmt2->text = NULL;
2309 stmt2->def = NULL;
2310 stmt2->dep = NULL;
2311 }
2312 if (stmt->text && stmt != sym->stmt) {
2313 *stmtp = stmt->next;
2314 stmt->next = sym->stmt;
2315 sym->stmt = stmt;
2316 } else
2317 stmtp = &stmt->next;
2318 stmt = *stmtp;
2319 }
2320 for (stmt = sym->stmt; stmt; stmt = stmt->next) {
2321 if (!stmt->token || stmt->token == '^')
2322 continue;
2323 if (!sym->dep) {
2324 if (!stmt->dep)
2325 break;
2326 sym->dep = stmt->dep;
2327 stmt->dep = NULL;
2328 } else {
2329 e = sym->dep;
2330 if (stmt->dep) {
2331 sym->dep = extract_eq_and(&e, &stmt->dep);
2332 if (expr_is_yes(e)) {
2333 expr_free(e);
2334 continue;
2335 }
2336 } else
2337 sym->dep = NULL;
2338 for (stmt2 = sym->stmt; stmt != stmt2; stmt2 = stmt2->next) {
2339 if (!stmt2->token || stmt2->token == '^')
2340 continue;
2341 stmt2->dep = !stmt2->dep ? expr_copy(e) :
2342 expr_alloc_two(T_AND, expr_copy(e), stmt2->dep);
2343 }
2344 expr_free(e);
2345 if (!sym->dep)
2346 break;
2347 }
2348 }
2349#if 0
2350 for (stmt1 = sym->stmt; stmt1; stmt1 = stmt1->next)
2351 if (stmt1->token && stmt1->token != '^')
2352 break;
2353 if (stmt1 && !expr_is_yes(stmt1->dep)) {
2354 e = trans_expr(expr_alloc_one('!', stmt1->dep));
2355 stmt1->dep = NULL;
2356 for (stmt = stmt1->next; stmt; stmt = stmt->next) {
2357 if (!stmt->token || stmt->token == '^')
2358 continue;
2359 if (stmt->dep) {
2360 tmp = extract_eq_and(&e, &stmt->dep);
2361 if (expr_is_yes(e)) {
2362 expr_free(e);
2363 e = tmp;
2364 continue;
2365 }
2366 if (tmp) {
2367 e = expr_alloc_two(T_AND, expr_copy(tmp), e);
2368 stmt->dep = expr_alloc_two(T_AND, tmp, stmt->dep);
2369 }
2370 }
2371 for (stmt2 = stmt1->next; stmt != stmt2; stmt2 = stmt2->next) {
2372 if (!stmt2->token || stmt2->token == '^')
2373 continue;
2374 stmt2->dep = !stmt2->dep ? expr_copy(e) :
2375 expr_alloc_two(T_AND, expr_copy(e), stmt2->dep);
2376 }
2377 stmt1->dep = trans_expr(expr_alloc_one('!', e));
2378 break;
2379 }
2380 if (!stmt1->dep) {
2381 e = trans_expr(expr_alloc_one('!', e));
2382 //sym->dep = sym->dep ? expr_alloc_two(T_AND, sym->dep, e) : e;
2383 stmt1->dep = e;
2384 }
2385 }
2386 for (stmtp = &sym->stmt; *stmtp; stmtp = &stmt->next) {
2387 stmt = *stmtp;
2388 if (!stmt->token || stmt->token == '^')
2389 continue;
2390 if (!stmt->dep || stmt->text)
2391 continue;
2392 for (stmt2 = stmt->next; stmt2; stmt2 = stmt2->next) {
2393 trans_count = 0;
2394 if (!stmt2->dep || stmt2->text)
2395 continue;
2396 e = trans_expr(expr_alloc_one('!', expr_copy(stmt->dep)));
2397 tmp = extract_eq_and(&e, &stmt2->dep);
2398 if (expr_is_yes(e)) {
2399 expr_free(e);
2400 expr_free(tmp);
2401 continue;
2402 }
2403 if (tmp)
2404 stmt2->dep = expr_alloc_two(T_AND, tmp, stmt2->dep);
2405 e = trans_expr(expr_alloc_one('!', expr_copy(stmt2->dep)));
2406 tmp = extract_eq_and(&e, &stmt->dep);
2407 if (expr_is_yes(e)) {
2408 expr_free(e);
2409 expr_free(tmp);
2410 while (stmt->next != stmt2)
2411 stmt = stmt->next;
2412 stmt->next = *stmtp;
2413 *stmtp = stmt2;
2414 stmt = stmt->next;
2415 stmt2 = stmt->next;
2416 stmt->next = (*stmtp)->next;
2417 (*stmtp)->next = stmt2;
2418 continue;
2419 }
2420 if (tmp)
2421 stmt->dep = expr_alloc_two(T_AND, tmp, stmt->dep);
2422 }
2423 }
2424#endif
2425 }
2426 for_all_symbols(i, sym) {
2427 printd(DEBUG_OPT4, "o4: %s\n", sym->name);
2428 print_expr(DEBUG_OPT4, sym->dep, 0); printd(DEBUG_OPT4, "\n");
2429 sym->dep = eliminate_dups(sym->dep);
2430 sym->dep = eliminate_yn(sym->dep);
2431 print_expr(DEBUG_OPT4, sym->dep, 0); printd(DEBUG_OPT4, "\n");
2432 for (stmt = sym->stmt; stmt; stmt = stmt->next) {
2433 print_expr(DEBUG_OPT4, stmt->dep, 0); printd(DEBUG_OPT4, "\n");
2434 stmt->dep = eliminate_dups(stmt->dep);
2435 stmt->dep = eliminate_yn(stmt->dep);
2436 print_expr(DEBUG_OPT4, stmt->dep, 0); printd(DEBUG_OPT4, "\n");
2437 }
2438 }
2439 for_all_symbols(i, sym) {
2440 if (dep_check_symbol(sym))
2441 printf("\n");
2442 }
2443 for_all_symbols(i, sym) {
2444 if (sym->dep && !sym->dep2) {
2445 printd(DEBUG_OPT5, "o5: %s\n", sym->name);
2446 print_expr(DEBUG_OPT5, sym->dep, 0); printd(DEBUG_OPT5, "\n");
2447 eliminate_dep(sym, sym->dep);
2448 print_expr(DEBUG_OPT5, sym->dep, 0); printd(DEBUG_OPT5, "\n");
2449 }
2450 }
2451}
2452
2453int main(int ac, char **av)
2454{
2455 FILE *out = NULL;
2456 char name[128];
2457 struct symbol *sym;
2458 struct statement *stmt;
2459
2460 if (ac > 2)
2461 cml1debug = 1;
2462 helplex("Documentation/Configure.help");
2463 sprintf(name, "arch/%s/Config.help", av[1]);
2464 helplex(name);
2465 sprintf(name, "arch/%s/config.in", av[1]);
2466 scan_init(name);
2467 sym = lookup_symbol("CONFIG_ARCH", SYMBOL_STRING);
2468 stmt = add_stmt(sym, T_DEFINE_STRING, NULL, lookup_symbol(av[1], SYMBOL_OTHER));
2469 stmt->menu = NULL;
2470 cml1parse();
2471 optimize_config();
2472#if 0
2473 out = fopen("config.new", "w");
2474 if (!out) {
2475 printf("unable to open config.new!\n");
2476 exit(1);
2477 }
2478#endif
2479 print_files(out, name);
2480
2481 return 0;
2482}