Release 4.10 scripts/kconfig/expr.c
/*
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
* Released under the terms of the GNU GPL v2.0.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lkc.h"
#define DEBUG_EXPR 0
static int expr_eq(struct expr *e1, struct expr *e2);
static struct expr *expr_eliminate_yn(struct expr *e);
struct expr *expr_alloc_symbol(struct symbol *sym)
{
struct expr *e = xcalloc(1, sizeof(*e));
e->type = E_SYMBOL;
e->left.sym = sym;
return e;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 42 | 93.33% | 1 | 33.33% |
arnaud lacombe | arnaud lacombe | 2 | 4.44% | 1 | 33.33% |
alan cox | alan cox | 1 | 2.22% | 1 | 33.33% |
| Total | 45 | 100.00% | 3 | 100.00% |
struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
{
struct expr *e = xcalloc(1, sizeof(*e));
e->type = type;
e->left.expr = ce;
return e;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 46 | 93.88% | 1 | 33.33% |
arnaud lacombe | arnaud lacombe | 2 | 4.08% | 1 | 33.33% |
alan cox | alan cox | 1 | 2.04% | 1 | 33.33% |
| Total | 49 | 100.00% | 3 | 100.00% |
struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
{
struct expr *e = xcalloc(1, sizeof(*e));
e->type = type;
e->left.expr = e1;
e->right.expr = e2;
return e;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 59 | 95.16% | 1 | 33.33% |
arnaud lacombe | arnaud lacombe | 2 | 3.23% | 1 | 33.33% |
alan cox | alan cox | 1 | 1.61% | 1 | 33.33% |
| Total | 62 | 100.00% | 3 | 100.00% |
struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
{
struct expr *e = xcalloc(1, sizeof(*e));
e->type = type;
e->left.sym = s1;
e->right.sym = s2;
return e;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 59 | 95.16% | 1 | 33.33% |
arnaud lacombe | arnaud lacombe | 2 | 3.23% | 1 | 33.33% |
alan cox | alan cox | 1 | 1.61% | 1 | 33.33% |
| Total | 62 | 100.00% | 3 | 100.00% |
struct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
{
if (!e1)
return e2;
return e2 ? expr_alloc_two(E_AND, e1, e2) : e1;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 39 | 100.00% | 1 | 100.00% |
| Total | 39 | 100.00% | 1 | 100.00% |
struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
{
if (!e1)
return e2;
return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 39 | 100.00% | 1 | 100.00% |
| Total | 39 | 100.00% | 1 | 100.00% |
struct expr *expr_copy(const struct expr *org)
{
struct expr *e;
if (!org)
return NULL;
e = xmalloc(sizeof(*org));
memcpy(e, org, sizeof(*org));
switch (org->type) {
case E_SYMBOL:
e->left = org->left;
break;
case E_NOT:
e->left.expr = expr_copy(org->left.expr);
break;
case E_EQUAL:
case E_GEQ:
case E_GTH:
case E_LEQ:
case E_LTH:
case E_UNEQUAL:
e->left.sym = org->left.sym;
e->right.sym = org->right.sym;
break;
case E_AND:
case E_OR:
case E_LIST:
e->left.expr = expr_copy(org->left.expr);
e->right.expr = expr_copy(org->right.expr);
break;
default:
printf("can't copy type %d\n", e->type);
free(e);
e = NULL;
break;
}
return e;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 181 | 92.82% | 2 | 40.00% |
jan beulich | jan beulich | 12 | 6.15% | 1 | 20.00% |
michal marek | michal marek | 1 | 0.51% | 1 | 20.00% |
alan cox | alan cox | 1 | 0.51% | 1 | 20.00% |
| Total | 195 | 100.00% | 5 | 100.00% |
void expr_free(struct expr *e)
{
if (!e)
return;
switch (e->type) {
case E_SYMBOL:
break;
case E_NOT:
expr_free(e->left.expr);
return;
case E_EQUAL:
case E_GEQ:
case E_GTH:
case E_LEQ:
case E_LTH:
case E_UNEQUAL:
break;
case E_OR:
case E_AND:
expr_free(e->left.expr);
expr_free(e->right.expr);
break;
default:
printf("how to free type %d?\n", e->type);
break;
}
free(e);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 89 | 88.12% | 1 | 50.00% |
jan beulich | jan beulich | 12 | 11.88% | 1 | 50.00% |
| Total | 101 | 100.00% | 2 | 100.00% |
static int trans_count;
#define e1 (*ep1)
#define e2 (*ep2)
static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
{
if (e1->type == type) {
__expr_eliminate_eq(type, &e1->left.expr, &e2);
__expr_eliminate_eq(type, &e1->right.expr, &e2);
return;
}
if (e2->type == type) {
__expr_eliminate_eq(type, &e1, &e2->left.expr);
__expr_eliminate_eq(type, &e1, &e2->right.expr);
return;
}
if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
e1->left.sym == e2->left.sym &&
(e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
return;
if (!expr_eq(e1, e2))
return;
trans_count++;
expr_free(e1); expr_free(e2);
switch (type) {
case E_OR:
e1 = expr_alloc_symbol(&symbol_no);
e2 = expr_alloc_symbol(&symbol_no);
break;
case E_AND:
e1 = expr_alloc_symbol(&symbol_yes);
e2 = expr_alloc_symbol(&symbol_yes);
break;
default:
;
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 223 | 100.00% | 2 | 100.00% |
| Total | 223 | 100.00% | 2 | 100.00% |
void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
{
if (!e1 || !e2)
return;
switch (e1->type) {
case E_OR:
case E_AND:
__expr_eliminate_eq(e1->type, ep1, ep2);
default:
;
}
if (e1->type != e2->type) switch (e2->type) {
case E_OR:
case E_AND:
__expr_eliminate_eq(e2->type, ep1, ep2);
default:
;
}
e1 = expr_eliminate_yn(e1);
e2 = expr_eliminate_yn(e2);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 104 | 100.00% | 2 | 100.00% |
| Total | 104 | 100.00% | 2 | 100.00% |
#undef e1
#undef e2
static int expr_eq(struct expr *e1, struct expr *e2)
{
int res, old_count;
if (e1->type != e2->type)
return 0;
switch (e1->type) {
case E_EQUAL:
case E_GEQ:
case E_GTH:
case E_LEQ:
case E_LTH:
case E_UNEQUAL:
return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
case E_SYMBOL:
return e1->left.sym == e2->left.sym;
case E_NOT:
return expr_eq(e1->left.expr, e2->left.expr);
case E_AND:
case E_OR:
e1 = expr_copy(e1);
e2 = expr_copy(e2);
old_count = trans_count;
expr_eliminate_eq(&e1, &e2);
res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
e1->left.sym == e2->left.sym);
expr_free(e1);
expr_free(e2);
trans_count = old_count;
return res;
case E_LIST:
case E_RANGE:
case E_NONE:
/* panic */;
}
if (DEBUG_EXPR) {
expr_fprint(e1, stdout);
printf(" = ");
expr_fprint(e2, stdout);
printf(" ?\n");
}
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 219 | 90.50% | 3 | 50.00% |
jan beulich | jan beulich | 12 | 4.96% | 1 | 16.67% |
andrew morton | andrew morton | 10 | 4.13% | 1 | 16.67% |
michal marek | michal marek | 1 | 0.41% | 1 | 16.67% |
| Total | 242 | 100.00% | 6 | 100.00% |
static struct expr *expr_eliminate_yn(struct expr *e)
{
struct expr *tmp;
if (e) switch (e->type) {
case E_AND:
e->left.expr = expr_eliminate_yn(e->left.expr);
e->right.expr = expr_eliminate_yn(e->right.expr);
if (e->left.expr->type == E_SYMBOL) {
if (e->left.expr->left.sym == &symbol_no) {
expr_free(e->left.expr);
expr_free(e->right.expr);
e->type = E_SYMBOL;
e->left.sym = &symbol_no;
e->right.expr = NULL;
return e;
} else if (e->left.expr->left.sym == &symbol_yes) {
free(e->left.expr);
tmp = e->right.expr;
*e = *(e->right.expr);
free(tmp);
return e;
}
}
if (e->right.expr->type == E_SYMBOL) {
if (e->right.expr->left.sym == &symbol_no) {
expr_free(e->left.expr);
expr_free(e->right.expr);
e->type = E_SYMBOL;
e->left.sym = &symbol_no;
e->right.expr = NULL;
return e;
} else if (e->right.expr->left.sym == &symbol_yes) {
free(e->right.expr);
tmp = e->left.expr;
*e = *(e->left.expr);
free(tmp);
return e;
}
}
break;
case E_OR:
e->left.expr = expr_eliminate_yn(e->left.expr);
e->right.expr = expr_eliminate_yn(e->right.expr);
if (e->left.expr->type == E_SYMBOL) {
if (e->left.expr->left.sym == &symbol_no) {
free(e->left.expr);
tmp = e->right.expr;
*e = *(e->right.expr);
free(tmp);
return e;
} else if (e->left.expr->left.sym == &symbol_yes) {
expr_free(e->left.expr);
expr_free(e->right.expr);
e->type = E_SYMBOL;
e->left.sym = &symbol_yes;
e->right.expr = NULL;
return e;
}
}
if (e->right.expr->type == E_SYMBOL) {
if (e->right.expr->left.sym == &symbol_no) {
free(e->right.expr);
tmp = e->left.expr;
*e = *(e->left.expr);
free(tmp);
return e;
} else if (e->right.expr->left.sym == &symbol_yes) {
expr_free(e->left.expr);
expr_free(e->right.expr);
e->type = E_SYMBOL;
e->left.sym = &symbol_yes;
e->right.expr = NULL;
return e;
}
}
break;
default:
;
}
return e;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 622 | 99.84% | 1 | 50.00% |
michal marek | michal marek | 1 | 0.16% | 1 | 50.00% |
| Total | 623 | 100.00% | 2 | 100.00% |
/*
* bool FOO!=n => FOO
*/
struct expr *expr_trans_bool(struct expr *e)
{
if (!e)
return NULL;
switch (e->type) {
case E_AND:
case E_OR:
case E_NOT:
e->left.expr = expr_trans_bool(e->left.expr);
e->right.expr = expr_trans_bool(e->right.expr);
break;
case E_UNEQUAL:
// FOO!=n -> FOO
if (e->left.sym->type == S_TRISTATE) {
if (e->right.sym == &symbol_no) {
e->type = E_SYMBOL;
e->right.sym = NULL;
}
}
break;
default:
;
}
return e;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 119 | 100.00% | 1 | 100.00% |
| Total | 119 | 100.00% | 1 | 100.00% |
/*
* e1 || e2 -> ?
*/
static struct expr *expr_join_or(struct expr *e1, struct expr *e2)
{
struct expr *tmp;
struct symbol *sym1, *sym2;
if (expr_eq(e1, e2))
return expr_copy(e1);
if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
return NULL;
if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
return NULL;
if (e1->type == E_NOT) {
tmp = e1->left.expr;
if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
return NULL;
sym1 = tmp->left.sym;
} else
sym1 = e1->left.sym;
if (e2->type == E_NOT) {
if (e2->left.expr->type != E_SYMBOL)
return NULL;
sym2 = e2->left.expr->left.sym;
} else
sym2 = e2->left.sym;
if (sym1 != sym2)
return NULL;
if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
return NULL;
if (sym1->type == S_TRISTATE) {
if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
(e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
// (a='y') || (a='m') -> (a!='n')
return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);
}
if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
(e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
// (a='y') || (a='n') -> (a!='m')
return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);
}
if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
(e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
// (a='m') || (a='n') -> (a!='y')
return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);
}
}
if (sym1->type == S_BOOLEAN && sym1 == sym2) {
if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||
(e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))
return expr_alloc_symbol(&symbol_yes);
}
if (DEBUG_EXPR) {
printf("optimize (");
expr_fprint(e1, stdout);
printf(") || (");
expr_fprint(e2, stdout);
printf(")?\n");
}
return NULL;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
roman zippel | roman zippel | 549 | 97.51% | 1 | 33.33% |
andrew morton | andrew morton | 13 | 2.31% | 1 | 33.33% |
trevor keith | trevor keith | 1 | 0.18% | 1 | 33.33% |
| Total | 563 | 100.00% | 3 | 100.00% |
static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
{
struct expr *tmp;
struct symbol *sym1, *sym2;
if (expr_eq(e1, e2))
return expr_copy(e1);
if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
return NULL;
if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
return NULL;
if (e1->type == E_NOT) {
tmp = e1->left.expr;
if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
return NULL;
sym1 = tmp->left.sym;
} else
sym1 = e1->left.sym;
if (e2->type == E_NOT) {
if (e2->left.expr->type != E_SYMBOL)
return NULL;
sym2 = e2->left.expr->left.sym;
} else
sym2 = e2->left.sym;
if (sym1 != sym2)
return NULL;
if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
return NULL;
if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||
(e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))
// (a) && (a='y') -> (a='y')
return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||
(e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))
// (a) && (a!='n') -> (a)
return expr_alloc_symbol(sym1);
if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||
(e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))
// (a) && (a!='m') -> (a='y')
return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
if (sym1->type == S_TRISTATE) {
if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
sym2 = e1->right.sym;
if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
: expr_alloc_symbol(&symbol_no);
}
if