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

📄 eval.c

📁 lcc,一个可变目标c语言编译器的源码
💻 C
字号:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include "cpp.h"#define	NSTAK	32#define	SGN	0#define	UNS	1#define	UND	2#define	UNSMARK	0x1000struct value {	long	val;	int	type;};/* conversion types */#define	RELAT	1#define	ARITH	2#define	LOGIC	3#define	SPCL	4#define	SHIFT	5#define	UNARY	6/* operator priority, arity, and conversion type, indexed by tokentype */struct pri {	char	pri;	char	arity;	char	ctype;} priority[] = {	{ 0, 0, 0 },		/* END */	{ 0, 0, 0 },		/* UNCLASS */	{ 0, 0, 0 },		/* NAME */	{ 0, 0, 0 },		/* NUMBER */	{ 0, 0, 0 },		/* STRING */	{ 0, 0, 0 },		/* CCON */	{ 0, 0, 0 },		/* NL */	{ 0, 0, 0 },		/* WS */	{ 0, 0, 0 },		/* DSHARP */	{ 11, 2, RELAT },	/* EQ */	{ 11, 2, RELAT },	/* NEQ */	{ 12, 2, RELAT },	/* LEQ */	{ 12, 2, RELAT },	/* GEQ */	{ 13, 2, SHIFT },	/* LSH */	{ 13, 2, SHIFT },	/* RSH */	{ 7, 2, LOGIC },	/* LAND */	{ 6, 2, LOGIC },	/* LOR */	{ 0, 0, 0 },		/* PPLUS */	{ 0, 0, 0 },		/* MMINUS */	{ 0, 0, 0 },		/* ARROW */	{ 0, 0, 0 },		/* SBRA */	{ 0, 0, 0 },		/* SKET */	{ 3, 0, 0 },		/* LP */	{ 3, 0, 0 },		/* RP */	{ 0, 0, 0 },		/* DOT */	{ 10, 2, ARITH },	/* AND */	{ 15, 2, ARITH },	/* STAR */	{ 14, 2, ARITH },	/* PLUS */	{ 14, 2, ARITH },	/* MINUS */	{ 16, 1, UNARY },	/* TILDE */	{ 16, 1, UNARY },	/* NOT */	{ 15, 2, ARITH },	/* SLASH */	{ 15, 2, ARITH },	/* PCT */	{ 12, 2, RELAT },	/* LT */	{ 12, 2, RELAT },	/* GT */	{ 9, 2, ARITH },	/* CIRC */	{ 8, 2, ARITH },	/* OR */	{ 5, 2, SPCL },		/* QUEST */	{ 5, 2, SPCL },		/* COLON */	{ 0, 0, 0 },		/* ASGN */	{ 4, 2, 0 },		/* COMMA */	{ 0, 0, 0 },		/* SHARP */	{ 0, 0, 0 },		/* SEMIC */	{ 0, 0, 0 },		/* CBRA */	{ 0, 0, 0 },		/* CKET */	{ 0, 0, 0 },		/* ASPLUS */ 	{ 0, 0, 0 },		/* ASMINUS */ 	{ 0, 0, 0 },		/* ASSTAR */ 	{ 0, 0, 0 },		/* ASSLASH */ 	{ 0, 0, 0 },		/* ASPCT */ 	{ 0, 0, 0 },		/* ASCIRC */ 	{ 0, 0, 0 },		/* ASLSH */	{ 0, 0, 0 },		/* ASRSH */ 	{ 0, 0, 0 },		/* ASOR */ 	{ 0, 0, 0 },		/* ASAND */	{ 0, 0, 0 },		/* ELLIPS */	{ 0, 0, 0 },		/* DSHARP1 */	{ 0, 0, 0 },		/* NAME1 */	{ 16, 1, UNARY },	/* DEFINED */	{ 16, 0, UNARY },	/* UMINUS */};int	evalop(struct pri);struct	value tokval(Token *);struct value vals[NSTAK], *vp;enum toktype ops[NSTAK], *op;/* * Evaluate an #if #elif #ifdef #ifndef line.  trp->tp points to the keyword. */longeval(Tokenrow *trp, int kw){	Token *tp;	Nlist *np;	int ntok, rand;	trp->tp++;	if (kw==KIFDEF || kw==KIFNDEF) {		if (trp->lp - trp->bp != 4 || trp->tp->type!=NAME) {			error(ERROR, "Syntax error in #ifdef/#ifndef");			return 0;		}		np = lookup(trp->tp, 0);		return (kw==KIFDEF) == (np && np->flag&(ISDEFINED|ISMAC));	}	ntok = trp->tp - trp->bp;	kwdefined->val = KDEFINED;	/* activate special meaning of defined */	expandrow(trp, "<if>");	kwdefined->val = NAME;	vp = vals;	op = ops;	*op++ = END;	for (rand=0, tp = trp->bp+ntok; tp < trp->lp; tp++) {		switch(tp->type) {		case WS:		case NL:			continue;		/* nilary */		case NAME:		case NAME1:		case NUMBER:		case CCON:		case STRING:			if (rand)				goto syntax;			if (vp == &vals[NSTAK]) {				error(ERROR, "Eval botch (stack overflow)");				return 0;			}			*vp++ = tokval(tp);			rand = 1;			continue;		/* unary */		case DEFINED:		case TILDE:		case NOT:			if (rand)				goto syntax;			*op++ = tp->type;			continue;		/* unary-binary */		case PLUS: case MINUS: case STAR: case AND:			if (rand==0) {				if (tp->type==MINUS)					*op++ = UMINUS;				if (tp->type==STAR || tp->type==AND) {					error(ERROR, "Illegal operator * or & in #if/#elsif");					return 0;				}				continue;			}			/* flow through */		/* plain binary */		case EQ: case NEQ: case LEQ: case GEQ: case LSH: case RSH:		case LAND: case LOR: case SLASH: case PCT:		case LT: case GT: case CIRC: case OR: case QUEST:		case COLON: case COMMA:			if (rand==0)				goto syntax;			if (evalop(priority[tp->type])!=0)				return 0;			*op++ = tp->type;			rand = 0;			continue;		case LP:			if (rand)				goto syntax;			*op++ = LP;			continue;		case RP:			if (!rand)				goto syntax;			if (evalop(priority[RP])!=0)				return 0;			if (op<=ops || op[-1]!=LP) {				goto syntax;			}			op--;			continue;		default:			error(ERROR,"Bad operator (%t) in #if/#elsif", tp);			return 0;		}	}	if (rand==0)		goto syntax;	if (evalop(priority[END])!=0)		return 0;	if (op!=&ops[1] || vp!=&vals[1]) {		error(ERROR, "Botch in #if/#elsif");		return 0;	}	if (vals[0].type==UND)		error(ERROR, "Undefined expression value");	return vals[0].val;syntax:	error(ERROR, "Syntax error in #if/#elsif");	return 0;}intevalop(struct pri pri){	struct value v1, v2;	long rv1, rv2;	int rtype, oper;	rv2=0;	rtype=0;	while (pri.pri < priority[op[-1]].pri) {		oper = *--op;		if (priority[oper].arity==2) {			v2 = *--vp;			rv2 = v2.val;		}		v1 = *--vp;		rv1 = v1.val;/*lint -e574 -e644 */		switch (priority[oper].ctype) {		case 0:		default:			error(WARNING, "Syntax error in #if/#endif");			return 1;		case ARITH:		case RELAT:			if (v1.type==UNS || v2.type==UNS)				rtype = UNS;			else				rtype = SGN;			if (v1.type==UND || v2.type==UND)				rtype = UND;			if (priority[oper].ctype==RELAT && rtype==UNS) {				oper |= UNSMARK;				rtype = SGN;			}			break;		case SHIFT:			if (v1.type==UND || v2.type==UND)				rtype = UND;			else				rtype = v1.type;			if (rtype==UNS)				oper |= UNSMARK;			break;		case UNARY:			rtype = v1.type;			break;		case LOGIC:		case SPCL:			break;		}		switch (oper) {		case EQ: case EQ|UNSMARK:			rv1 = rv1==rv2; break;		case NEQ: case NEQ|UNSMARK:			rv1 = rv1!=rv2; break;		case LEQ:			rv1 = rv1<=rv2; break;		case GEQ:			rv1 = rv1>=rv2; break;		case LT:			rv1 = rv1<rv2; break;		case GT:			rv1 = rv1>rv2; break;		case LEQ|UNSMARK:			rv1 = (unsigned long)rv1<=rv2; break;		case GEQ|UNSMARK:			rv1 = (unsigned long)rv1>=rv2; break;		case LT|UNSMARK:			rv1 = (unsigned long)rv1<rv2; break;		case GT|UNSMARK:			rv1 = (unsigned long)rv1>rv2; break;		case LSH:			rv1 <<= rv2; break;		case LSH|UNSMARK:			rv1 = (unsigned long)rv1<<rv2; break;		case RSH:			rv1 >>= rv2; break;		case RSH|UNSMARK:			rv1 = (unsigned long)rv1>>rv2; break;		case LAND:			rtype = UND;			if (v1.type==UND)				break;			if (rv1!=0) {				if (v2.type==UND)					break;				rv1 = rv2!=0;			} else				rv1 = 0;			rtype = SGN;			break;		case LOR:			rtype = UND;			if (v1.type==UND)				break;			if (rv1==0) {				if (v2.type==UND)					break;				rv1 = rv2!=0;			} else				rv1 = 1;			rtype = SGN;			break;		case AND:			rv1 &= rv2; break;		case STAR:			rv1 *= rv2; break;		case PLUS:			rv1 += rv2; break;		case MINUS:			rv1 -= rv2; break;		case UMINUS:			if (v1.type==UND)				rtype = UND;			rv1 = -rv1; break;		case OR:			rv1 |= rv2; break;		case CIRC:			rv1 ^= rv2; break;		case TILDE:			rv1 = ~rv1; break;		case NOT:			rv1 = !rv1; if (rtype!=UND) rtype = SGN; break;		case SLASH:			if (rv2==0) {				rtype = UND;				break;			}			if (rtype==UNS)				rv1 /= (unsigned long)rv2;			else				rv1 /= rv2;			break;		case PCT:			if (rv2==0) {				rtype = UND;				break;			}			if (rtype==UNS)				rv1 %= (unsigned long)rv2;			else				rv1 %= rv2;			break;		case COLON:			if (op[-1] != QUEST)				error(ERROR, "Bad ?: in #if/endif");			else {				op--;				if ((--vp)->val==0)					v1 = v2;				rtype = v1.type;				rv1 = v1.val;			}			break;		case DEFINED:			break;		default:			error(ERROR, "Eval botch (unknown operator)");			return 1;		}/*lint +e574 +e644 */		v1.val = rv1;		v1.type = rtype;		if (vp == &vals[NSTAK]) {			error(ERROR, "Eval botch (stack overflow)");			return 0;		}		*vp++ = v1;	}	return 0;}struct valuetokval(Token *tp){	struct value v;	Nlist *np;	int i, base, c;	unsigned long n;	uchar *p;	v.type = SGN;	v.val = 0;	switch (tp->type) {	case NAME:		v.val = 0;		break;	case NAME1:		if ((np = lookup(tp, 0)) != NULL && np->flag&(ISDEFINED|ISMAC))			v.val = 1;		break;	case NUMBER:		n = 0;		base = 10;		p = tp->t;		c = p[tp->len];		p[tp->len] = '\0';		if (*p=='0') {			base = 8;			if (p[1]=='x' || p[1]=='X') {				base = 16;				p++;			}			p++;		}		for (;; p++) {			if ((i = digit(*p)) < 0)				break;			if (i>=base)				error(WARNING,				  "Bad digit in number %t", tp);			n *= base;			n += i;		}		if (n>=0x80000000 && base!=10)			v.type = UNS;		for (; *p; p++) {			if (*p=='u' || *p=='U')				v.type = UNS;			else if (*p=='l' || *p=='L')				;			else {				error(ERROR,				  "Bad number %t in #if/#elsif", tp);				break;			}		}		v.val = n;		tp->t[tp->len] = c;		break;	case CCON:		n = 0;		p = tp->t;		if (*p=='L') {			p += 1;			error(WARNING, "Wide char constant value undefined");		}		p += 1;		if (*p=='\\') {			p += 1;			if ((i = digit(*p))>=0 && i<=7) {				n = i;				p += 1;				if ((i = digit(*p))>=0 && i<=7) {					p += 1;					n <<= 3;					n += i;					if ((i = digit(*p))>=0 && i<=7) {						p += 1;						n <<= 3;						n += i;					}				}			} else if (*p=='x') {				p += 1;				while ((i = digit(*p))>=0 && i<=15) {					p += 1;					n <<= 4;					n += i;				}			} else {				static char cvcon[]				  = "b\bf\fn\nr\rt\tv\v''\"\"??\\\\";				for (i=0; i<sizeof(cvcon); i+=2) {					if (*p == cvcon[i]) {						n = cvcon[i+1];						break;					}				}				p += 1;				if (i>=sizeof(cvcon))					error(WARNING,					 "Undefined escape in character constant");			}		} else if (*p=='\'')			error(ERROR, "Empty character constant");		else			n = *p++;		if (*p!='\'')			error(WARNING, "Multibyte character constant undefined");		else if (n>127)			error(WARNING, "Character constant taken as not signed");		v.val = n;		break;	case STRING:		error(ERROR, "String in #if/#elsif");		break;	}	return v;}intdigit(int i){	if ('0'<=i && i<='9')		i -= '0';	else if ('a'<=i && i<='f')		i -= 'a'-10;	else if ('A'<=i && i<='F')		i -= 'A'-10;	else		i = -1;	return i;}

⌨️ 快捷键说明

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