⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 expr.c

📁 用于生成linux操作系统下的交叉编译工具链和嵌入式linux系统的根文件系统,支持x86、arm、powerpc等处理器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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>#define LKC_DIRECT_LINK#include "lkc.h"#define DEBUG_EXPR	0struct expr *expr_alloc_symbol(struct symbol *sym){	struct expr *e = malloc(sizeof(*e));	memset(e, 0, 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 = malloc(sizeof(*e));	memset(e, 0, 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 = malloc(sizeof(*e));	memset(e, 0, 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 = malloc(sizeof(*e));	memset(e, 0, sizeof(*e));	e->type = type;	e->left.sym = s1;	e->right.sym = s2;	return e;}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;}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(struct expr *org){	struct expr *e;	if (!org)		return NULL;	e = malloc(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_CHOICE:		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){	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->flags & (SYMBOL_YES|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:		;	}}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);}#undef e1#undef e2int 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_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_CHOICE:	case E_RANGE:	case E_NONE:		/* panic */;	}	if (DEBUG_EXPR) {		expr_fprint(e1, stdout);		printf(" = ");		expr_fprint(e2, stdout);		printf(" ?\n");	}	return 0;}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;}/* * 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;}/* * e1 || e2 -> ? */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;}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 (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {			// (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'			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);		}		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)))			// (a!='y') && (a!='n') -> (a='m')			return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);		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)))			// (a!='y') && (a!='m') -> (a='n')			return expr_alloc_comp(E_EQUAL, sym1, &symbol_no);		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)))			// (a!='m') && (a!='n') -> (a='m')			return expr_alloc_comp(E_EQUAL, sym1, &symbol_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");	}	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;	if (e1->type == type) {		expr_eliminate_dups1(type, &e1->left.expr, &e2);		expr_eliminate_dups1(type, &e1->right.expr, &e2);		return;	}	if (e2->type == type) {		expr_eliminate_dups1(type, &e1, &e2->left.expr);		expr_eliminate_dups1(type, &e1, &e2->right.expr);		return;	}	if (e1 == e2)		return;	switch (e1->type) {	case E_OR: case E_AND:		expr_eliminate_dups1(e1->type, &e1, &e1);	default:		;	}	switch (type) {	case E_OR:		tmp = expr_join_or(e1, e2);		if (tmp) {			expr_free(e1); expr_free(e2);			e1 = expr_alloc_symbol(&symbol_no);			e2 = tmp;			trans_count++;		}		break;	case E_AND:		tmp = expr_join_and(e1, e2);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -