You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
reptile/src/Reptile/scripts/kconfig/expr.c

1181 lines
34 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* 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 // 调试宏,当前未使用
// 为符号创建一个新的表达式
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; // 返回创建的表达式
}
// 创建一个带有一个子表达式的新表达式
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; // 返回创建的表达式
}
// 创建一个带有两个子表达式的新表达式
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; // 返回创建的表达式
}
// 创建一个带有两个符号的新比较表达式
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; // 返回创建的表达式
}
// 创建一个逻辑与 (AND) 表达式
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; // 否则,创建一个 "与" 表达式
}
// 创建一个逻辑或 (OR) 表达式
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; // 否则,创建一个 "或" 表达式
}
// 复制一个表达式
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_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; // 返回复制后的表达式
}
// 释放表达式的内存
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_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);
}
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)
{
// 如果表达式 e1 或 e2 是 "与" 或 "或" 类型,递归进入左右子表达式
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;
}
// 如果 e1 和 e2 都是符号类型且它们的符号值相同,并且是符号 'yes' 或 'no',则跳过
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;
// 如果 e1 和 e2 不相等,跳过
if (!expr_eq(e1, e2))
return;
// 如果 e1 和 e2 相等,进行处理
trans_count++; // 增加转换计数
expr_free(e1); expr_free(e2); // 释放这两个表达式
// 根据操作类型创建新的符号表达式
switch (type) {
case E_OR:
e1 = expr_alloc_symbol(&symbol_no); // 对于 "或" 操作,创建符号 'no'
e2 = expr_alloc_symbol(&symbol_no); // 对于 "或" 操作,创建符号 'no'
break;
case E_AND:
e1 = expr_alloc_symbol(&symbol_yes); // 对于 "与" 操作,创建符号 'yes'
e2 = expr_alloc_symbol(&symbol_yes); // 对于 "与" 操作,创建符号 'yes'
break;
default:
;
}
}
// 主函数:消除两个表达式中的 "与" 和 "或" 操作,递归处理
void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
{
// 如果任一表达式为空,直接返回
if (!e1 || !e2)
return;
// 如果 e1 是 "与" 或 "或" 类型,递归处理
switch (e1->type) {
case E_OR:
case E_AND:
__expr_eliminate_eq(e1->type, ep1, ep2);
default:
;
}
// 如果 e1 和 e2 类型不同,继续处理 e2
if (e1->type != e2->type) switch (e2->type) {
case E_OR:
case E_AND:
__expr_eliminate_eq(e2->type, ep1, ep2);
default:
;
}
// 消除表达式中的 'yes' 和 'no' 符号
e1 = expr_eliminate_yn(e1);
e2 = expr_eliminate_yn(e2);
}
// 取消宏定义
#undef e1
#undef e2
// 比较两个表达式是否相等
int expr_eq(struct expr *e1, struct expr *e2)
{
int res, old_count;
// 如果两个表达式的类型不同,直接返回 0
if (e1->type != e2->type)
return 0;
// 根据表达式的类型进行比较
switch (e1->type) {
case E_EQUAL:
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; // 默认返回不相等
}
// 消除逻辑表达式中的 'yes' 和 'no' 符号
struct expr *expr_eliminate_yn(struct expr *e)
{
struct expr *tmp;
// 如果表达式不为空,进行处理
if (e) switch (e->type) {
// 对于 "与" (E_AND) 类型的表达式
case E_AND:
// 递归消除左右子表达式中的 'yes' 和 'no' 符号
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) {
// 如果左边是 'no',则整个表达式结果为 'no'
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;
}
// 如果左边是 'yes',则消除左边并返回右边的表达式
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;
// 对于 "或" (E_OR) 类型的表达式
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) {
// 如果左边是 'no',则消除左边并返回右边的表达式
if (e->left.expr->left.sym == &symbol_no) {
free(e->left.expr);
tmp = e->right.expr;
*e = *(e->right.expr);
free(tmp);
return e;
}
// 如果左边是 'yes',则整个表达式结果为 'yes'
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;
}
/*
* 布尔类型转换,消除类似 "FOO != n" 的表达式
* 例如FOO != n => FOO
*/
struct expr *expr_trans_bool(struct expr *e)
{
// 如果表达式为空,直接返回 NULL
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:
// 如果是 "不等" (UNEQUAL) 类型并且左边是布尔三态类型S_TRISTATE
if (e->left.sym->type == S_TRISTATE) {
// 如果右边是 'no',则转换为符号类型
if (e->right.sym == &symbol_no) {
e->type = E_SYMBOL;
e->right.sym = NULL;
}
}
break;
default:
;
}
return e;
}
/*
* 合并两个 "或" (||) 表达式
* 例如,(a='y') || (a='m') -> (a != 'n')
*/
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);
// 如果 e1 或 e2 类型不支持合并,直接返回 NULL
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;
// 对于 e1 为 "非" (E_NOT) 类型,获取其左子表达式的符号
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;
// 对于 e2 为 "非" (E_NOT) 类型,获取其左子表达式的符号
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;
// 如果符号不是布尔类型S_BOOLEAN 或 S_TRISTATE也无法合并
if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
return NULL;
// 如果符号是三态布尔 (S_TRISTATE),则根据不同的组合进行优化
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
// 合并两个 "与" 操作符(&&)的表达式,并优化它们。
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);
// 如果两个表达式的类型不属于 E_EQUAL, E_UNEQUAL, E_SYMBOL 或 E_NOT则无法进行优化
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;
// 处理第一个表达式,如果它是 NOT 类型,获取它的子表达式
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;
// 处理第二个表达式,如果它是 NOT 类型,获取它的子表达式
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;
// 以下是一些常见的优化模式:
// (a) && (a='y') -> (a='y')
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))
return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
// (a) && (a!='n') -> (a)
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))
return expr_alloc_symbol(sym1);
// (a) && (a!='m') -> (a='y')
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))
return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
// 如果符号是三态类型,则进行更多的优化
if (sym1->type == S_TRISTATE) {
// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
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);
}
// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {
sym2 = e2->right.sym;
if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
: expr_alloc_symbol(&symbol_no);
}
// (a!='y') && (a!='n') -> (a='m')
if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
(e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);
// (a!='y') && (a!='m') -> (a='n')
if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
(e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
return expr_alloc_comp(E_EQUAL, sym1, &symbol_no);
// (a!='m') && (a!='n') -> (a='m')
if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
(e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
// 如果存在不可能的组合,如 (a='mod') && (a='yes'),无法优化
if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||
(e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||
(e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||
(e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))
return NULL;
}
// 如果处于调试模式,打印优化信息
if (DEBUG_EXPR) {
printf("optimize (");
expr_fprint(e1, stdout);
printf(") && (");
expr_fprint(e2, stdout);
printf(")?\n");
}
// 如果无法优化,返回 NULL
return NULL;
}
static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
{
#define e1 (*ep1)
#define e2 (*ep2)
struct expr *tmp;
// 如果 e1 是 type 类型(例如 E_OR 或 E_AND递归简化其左右子表达式
if (e1->type == type) {
expr_eliminate_dups1(type, &e1->left.expr, &e2);
expr_eliminate_dups1(type, &e1->right.expr, &e2);
return;
}
// 如果 e2 是 type 类型,递归简化 e1 和 e2 的左右子表达式
if (e2->type == type) {
expr_eliminate_dups1(type, &e1, &e2->left.expr);
expr_eliminate_dups1(type, &e1, &e2->right.expr);
return;
}
// 如果 e1 和 e2 相等,跳过
if (e1 == e2)
return;
// 处理 E_OR 或 E_AND 类型的表达式
switch (e1->type) {
case E_OR: case E_AND:
expr_eliminate_dups1(e1->type, &e1, &e1);
default:
;
}
// 根据给定的类型E_OR 或 E_AND进行处理
switch (type) {
case E_OR:
tmp = expr_join_or(e1, e2); // 尝试将 e1 和 e2 合并为一个 E_OR 表达式
if (tmp) {
expr_free(e1); expr_free(e2);
e1 = expr_alloc_symbol(&symbol_no); // 合并成功e1 设置为 "no"
e2 = tmp;
trans_count++; // 记录转换计数
}
break;
case E_AND:
tmp = expr_join_and(e1, e2); // 尝试将 e1 和 e2 合并为一个 E_AND 表达式
if (tmp) {
expr_free(e1); expr_free(e2);
e1 = expr_alloc_symbol(&symbol_yes); // 合并成功e1 设置为 "yes"
e2 = tmp;
trans_count++; // 记录转换计数
}
break;
default:
;
}
#undef e1
#undef e2
}
static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2)
{
#define e1 (*ep1)
#define e2 (*ep2)
struct expr *tmp, *tmp1, *tmp2;
// 如果 e1 或 e2 是 type 类型,递归简化其左右子表达式
if (e1->type == type) {
expr_eliminate_dups2(type, &e1->left.expr, &e2);
expr_eliminate_dups2(type, &e1->right.expr, &e2);
return;
}
if (e2->type == type) {
expr_eliminate_dups2(type, &e1, &e2->left.expr);
expr_eliminate_dups2(type, &e1, &e2->right.expr);
}
// 如果 e1 和 e2 相等,跳过
if (e1 == e2)
return;
// 处理 E_OR 和 E_AND 类型的表达式
switch (e1->type) {
case E_OR:
expr_eliminate_dups2(e1->type, &e1, &e1);
// 处理 (FOO || BAR) && (!FOO && !BAR) -> n
tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
tmp2 = expr_copy(e2);
tmp = expr_extract_eq_and(&tmp1, &tmp2); // 尝试将其提取为等式与关系
if (expr_is_yes(tmp1)) {
expr_free(e1);
e1 = expr_alloc_symbol(&symbol_no); // 化简为 "no"
trans_count++;
}
expr_free(tmp2);
expr_free(tmp1);
expr_free(tmp);
break;
case E_AND:
expr_eliminate_dups2(e1->type, &e1, &e1);
// 处理 (FOO && BAR) || (!FOO || !BAR) -> y
tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
tmp2 = expr_copy(e2);
tmp = expr_extract_eq_or(&tmp1, &tmp2); // 尝试将其提取为等式或关系
if (expr_is_no(tmp1)) {
expr_free(e1);
e1 = expr_alloc_symbol(&symbol_yes); // 化简为 "yes"
trans_count++;
}
expr_free(tmp2);
expr_free(tmp1);
expr_free(tmp);
break;
default:
;
}
#undef e1
#undef e2
}
struct expr *expr_eliminate_dups(struct expr *e)
{
int oldcount;
if (!e)
return e;
oldcount = trans_count;
while (1) {
trans_count = 0;
// 对表达式进行多轮简化
switch (e->type) {
case E_OR: case E_AND:
expr_eliminate_dups1(e->type, &e, &e);
expr_eliminate_dups2(e->type, &e, &e);
default:
;
}
// 如果没有进行任何转换,则退出
if (!trans_count)
break;
// 否则,继续进行 "yes" 或 "no" 化简
e = expr_eliminate_yn(e);
}
trans_count = oldcount;
return e;
}
struct expr *expr_transform(struct expr *e)
{
struct expr *tmp;
if (!e)
return NULL;
// 递归简化左右子表达式
switch (e->type) {
case E_EQUAL:
case E_UNEQUAL:
case E_SYMBOL:
case E_LIST:
break;
default:
e->left.expr = expr_transform(e->left.expr);
e->right.expr = expr_transform(e->right.expr);
}
// 根据表达式类型进行转换
switch (e->type) {
case E_EQUAL:
// 处理 E_EQUAL 类型的简化规则
if (e->left.sym->type != S_BOOLEAN)
break;
if (e->right.sym == &symbol_no) {
e->type = E_NOT;
e->left.expr = expr_alloc_symbol(e->left.sym);
e->right.sym = NULL;
break;
}
if (e->right.sym == &symbol_mod) {
e->type = E_SYMBOL;
e->left.sym = &symbol
int expr_contains_symbol(struct expr *dep, struct symbol *sym)
{
if (!dep) // 如果表达式为空返回0表示不包含符号
return 0;
switch (dep->type) { // 根据表达式的类型进行处理
case E_AND: // 如果是 AND 类型
case E_OR: // 如果是 OR 类型
// 递归检查左右子表达式是否包含符号
return expr_contains_symbol(dep->left.expr, sym) ||
expr_contains_symbol(dep->right.expr, sym);
case E_SYMBOL: // 如果是符号类型
// 比较符号是否相同
return dep->left.sym == sym;
case E_EQUAL: // 如果是等式类型
case E_UNEQUAL: // 如果是不等式类型
// 检查左右表达式中的符号是否包含目标符号
return dep->left.sym == sym ||
dep->right.sym == sym;
case E_NOT: // 如果是 NOT 类型
// 递归检查左子表达式是否包含符号
return expr_contains_symbol(dep->left.expr, sym);
default:
// 其他类型直接跳过
;
}
return 0; // 默认返回0
}
bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
{
if (!dep) // 如果表达式为空返回false
return false;
switch (dep->type) { // 根据表达式的类型进行处理
case E_AND: // 如果是 AND 类型
// 递归检查左右子表达式是否依赖于符号
return expr_depends_symbol(dep->left.expr, sym) ||
expr_depends_symbol(dep->right.expr, sym);
case E_SYMBOL: // 如果是符号类型
// 检查符号是否匹配
return dep->left.sym == sym;
case E_EQUAL: // 如果是等式类型
if (dep->left.sym == sym) {
// 如果左侧符号是目标符号并且右侧符号是symbol_yes或symbol_mod则表达式依赖于该符号
if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod)
return true;
}
break;
case E_UNEQUAL: // 如果是不等式类型
if (dep->left.sym == sym) {
// 如果左侧符号是目标符号并且右侧符号是symbol_no则表达式依赖于该符号
if (dep->right.sym == &symbol_no)
return true;
}
break;
default:
// 其他类型的处理
;
}
return false; // 默认返回false
}
struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2)
{
struct expr *tmp = NULL;
// 调用通用的提取等式函数,传入 E_AND 类型
expr_extract_eq(E_AND, &tmp, ep1, ep2);
if (tmp) {
// 如果提取成功消除ep1和ep2中的symbol_yes/symbol_no符号
*ep1 = expr_eliminate_yn(*ep1);
*ep2 = expr_eliminate_yn(*ep2);
}
return tmp; // 返回提取后的表达式
}
struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2)
{
struct expr *tmp = NULL;void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2)
{
#define e1 (*ep1)
#define e2 (*ep2)
if (e1->type == type) {
// 如果e1是目标类型递归处理其左右子表达式
expr_extract_eq(type, ep, &e1->left.expr, &e2);
expr_extract_eq(type, ep, &e1->right.expr, &e2);
return;
}
if (e2->type == type) {
// 如果e2是目标类型递归处理其左右子表达式
expr_extract_eq(type, ep, ep1, &e2->left.expr);
expr_extract_eq(type, ep, ep1, &e2->right.expr);
return;
}
if (expr_eq(e1, e2)) {
// 如果e1和e2相等构造一个新的表达式并进行符号替换
*ep = *ep ? expr_alloc_two(type, *ep, e1) : e1;
expr_free(e2);
// 根据类型创建symbol_yes/symbol_no表达式
if (type == E_AND) {
e1 = expr_alloc_symbol(&symbol_yes);
e2 = expr_alloc_symbol(&symbol_yes);
} else if (type == E_OR) {
e1 = expr_alloc_symbol(&symbol_no);
e2 = expr_alloc_symbol(&symbol_no);
}
}
#undef e1
#undef e2
}
// 调用通用的提取等式函数,传入 E_OR 类型
expr_extract_eq(E_OR, &tmp, ep1, ep2);
if (tmp) {
// 如果提取成功消除ep1和ep2中的symbol_yes/symbol_no符号
*ep1 = expr_eliminate_yn(*ep1);
*ep2 = expr_eliminate_yn(*ep2);
}
return tmp; // 返回提取后的表达式
}
struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
{
struct expr *e1, *e2;
if (!e) {
e = expr_alloc_symbol(sym);
if (type == E_UNEQUAL)
e = expr_alloc_one(E_NOT, e);
return e;
}
switch (e->type) {
case E_AND:
e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
if (sym == &symbol_yes)
e = expr_alloc_two(E_AND, e1, e2);
if (sym == &symbol_no)
e = expr_alloc_two(E_OR, e1, e2);
if (type == E_UNEQUAL)
e = expr_alloc_one(E_NOT, e);
return e;
case E_OR:
e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
if (sym == &symbol_yes)
e = expr_alloc_two(E_OR, e1, e2);
if (sym == &symbol_no)
e = expr_alloc_two(E_AND, e1, e2);
if (type == E_UNEQUAL)
e = expr_alloc_one(E_NOT, e);
return e;
case E_NOT:
return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);
case E_UNEQUAL:
case E_EQUAL:
if (type == E_EQUAL) {
if (sym == &symbol_yes)
return expr_copy(e);
if (sym == &symbol_mod)
return expr_alloc_symbol(&symbol_no);
if (sym == &symbol_no)
return expr_alloc_one(E_NOT, expr_copy(e));
} else {
if (sym == &symbol_yes)
return expr_alloc_one(E_NOT, expr_copy(e));
if (sym == &symbol_mod)
return expr_alloc_symbol(&symbol_yes);
if (sym == &symbol_no)
return expr_copy(e);
}
break;
case E_SYMBOL:
return expr_alloc_comp(type, e->left.sym, sym);
case E_LIST:
case E_RANGE:
case E_NONE:
/* panic */;
}
return NULL;
}
tristate expr_calc_value(struct expr *e)
{
tristate val1, val2;
const char *str1, *str2;
if (!e)
return yes;
switch (e->type) {
case E_SYMBOL:
sym_calc_value(e->left.sym);
return e->left.sym->curr.tri;
case E_AND:
val1 = expr_calc_value(e->left.expr);
val2 = expr_calc_value(e->right.expr);
return EXPR_AND(val1, val2);
case E_OR:
val1 = expr_calc_value(e->left.expr);
val2 = expr_calc_value(e->right.expr);
return EXPR_OR(val1, val2);
case E_NOT:
val1 = expr_calc_value(e->left.expr);
return EXPR_NOT(val1);
case E_EQUAL:
sym_calc_value(e->left.sym);
sym_calc_value(e->right.sym);
str1 = sym_get_string_value(e->left.sym);
str2 = sym_get_string_value(e->right.sym);
return !strcmp(str1, str2) ? yes : no;
case E_UNEQUAL:
sym_calc_value(e->left.sym);
sym_calc_value(e->right.sym);
str1 = sym_get_string_value(e->left.sym);
str2 = sym_get_string_value(e->right.sym);
return !strcmp(str1, str2) ? no : yes;
default:
printf("expr_calc_value: %d?\n", e->type);
return no;
}
}
int expr_compare_type(enum expr_type t1, enum expr_type t2)
{
#if 0
return 1;
#else
if (t1 == t2)
return 0;
switch (t1) {
case E_EQUAL:
case E_UNEQUAL:
if (t2 == E_NOT)
return 1;
case E_NOT:
if (t2 == E_AND)
return 1;
case E_AND:
if (t2 == E_OR)
return 1;
case E_OR:
if (t2 == E_LIST)
return 1;
case E_LIST:
if (t2 == 0)
return 1;
default:
return -1;
}
printf("[%dgt%d?]", t1, t2);
return 0;
#endif
}
static inline struct expr *
expr_get_leftmost_symbol(const struct expr *e)
{
if (e == NULL)
return NULL;
while (e->type != E_SYMBOL)
e = e->left.expr;
return expr_copy(e);
}
/*
* Given expression `e1' and `e2', returns the leaf of the longest
* sub-expression of `e1' not containing 'e2.
*/
struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2)
{
struct expr *ret;
switch (e1->type) {
case E_OR:
return expr_alloc_and(
expr_simplify_unmet_dep(e1->left.expr, e2),
expr_simplify_unmet_dep(e1->right.expr, e2));
case E_AND: {
struct expr *e;
e = expr_alloc_and(expr_copy(e1), expr_copy(e2));
e = expr_eliminate_dups(e);
ret = (!expr_eq(e, e1)) ? e1 : NULL;
expr_free(e);
break;
}
default:
ret = e1;
break;
}
return expr_get_leftmost_symbol(ret);
}
void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)
{
if (!e) {
fn(data, NULL, "y");
return;
}
if (expr_compare_type(prevtoken, e->type) > 0)
fn(data, NULL, "(");
switch (e->type) {
case E_SYMBOL:
if (e->left.sym->name)
fn(data, e->left.sym, e->left.sym->name);
else
fn(data, NULL, "<choice>");
break;
case E_NOT:
fn(data, NULL, "!");
expr_print(e->left.expr, fn, data, E_NOT);
break;
case E_EQUAL:
if (e->left.sym->name)
fn(data, e->left.sym, e->left.sym->name);
else
fn(data, NULL, "<choice>");
fn(data, NULL, "=");
fn(data, e->right.sym, e->right.sym->name);
break;
case E_UNEQUAL:
if (e->left.sym->name)
fn(data, e->left.sym, e->left.sym->name);
else
fn(data, NULL, "<choice>");
fn(data, NULL, "!=");
fn(data, e->right.sym, e->right.sym->name);
break;
case E_OR:
expr_print(e->left.expr, fn, data, E_OR);
fn(data, NULL, " || ");
expr_print(e->right.expr, fn, data, E_OR);
break;
case E_AND:
expr_print(e->left.expr, fn, data, E_AND);
fn(data, NULL, " && ");
expr_print(e->right.expr, fn, data, E_AND);
break;
case E_LIST:
fn(data, e->right.sym, e->right.sym->name);
if (e->left.expr) {
fn(data, NULL, " ^ ");
expr_print(e->left.expr, fn, data, E_LIST);
}
break;
case E_RANGE:
fn(data, NULL, "[");
fn(data, e->left.sym, e->left.sym->name);
fn(data, NULL, " ");
fn(data, e->right.sym, e->right.sym->name);
fn(data, NULL, "]");
break;
default:
{
char buf[32];
sprintf(buf, "<unknown type %d>", e->type);
fn(data, NULL, buf);
break;
}
}
if (expr_compare_type(prevtoken, e->type) > 0)
fn(data, NULL, ")");
}
static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
{
xfwrite(str, strlen(str), 1, data);
}
void expr_fprint(struct expr *e, FILE *out)
{
expr_print(e, expr_print_file_helper, out, E_NONE);
}
static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)
{
struct gstr *gs = (struct gstr*)data;
const char *sym_str = NULL;
if (sym)
sym_str = sym_get_string_value(sym);
if (gs->max_width) {
unsigned extra_length = strlen(str);
const char *last_cr = strrchr(gs->s, '\n');
unsigned last_line_length;
if (sym_str)
extra_length += 4 + strlen(sym_str);
if (!last_cr)
last_cr = gs->s;
last_line_length = strlen(gs->s) - (last_cr - gs->s);
if ((last_line_length + extra_length) > gs->max_width)
str_append(gs, "\\\n");
}
str_append(gs, str);
if (sym && sym->type != S_UNKNOWN)
str_printf(gs, " [=%s]", sym_str);
}
void expr_gstr_print(struct expr *e, struct gstr *gs)
{
expr_print(e, expr_print_gstr_helper, gs, E_NONE);
}