expr2.c

来自「EPIC IRC客户端。来源于IRCII客户端但做了很多性能和功能的优化。」· C语言 代码 · 共 2,404 行 · 第 1/5 页

C
2,404
字号
			malloc_strcat(&myval, t);			push_string(cx, myval);			add_var_alias(s, myval, 0);			new_free(&myval);			break;		}		case STRPREEQ:		{			char *	myval;			GET_LVAL_RVAL			CHECK_NOEVAL			myval = malloc_strdup(get_token_expanded(cx, w));			t = get_token_expanded(cx, v);			if (x_debug & DEBUG_NEW_MATH_DEBUG) 				yell("O: %s = (%s ## %s) -> %s%s", 					s, t, myval, t, myval);			malloc_strcat(&myval, t);			push_string(cx, myval);			add_var_alias(s, myval, 0);			new_free(&myval);			break;		}		case EQ:		{			GET_LVAL_RVAL			CHECK_NOEVAL			t = get_token_expanded(cx, w);			if (x_debug & DEBUG_NEW_MATH_DEBUG)				yell("O: %s = (%s)", s, t);			push_token(cx, w);			add_var_alias(s, t, 0);			break;		}		case SWAP:		{			const char *sval, *tval;			pop_2_tokens(cx, &v, &w);			CHECK_NOEVAL			if (!(s = get_token_lval(cx, v)))			{				push_token(cx, 0);				break;					}			if (!(t = get_token_lval(cx, w)))			{				push_token(cx, 0);				break;					}			sval = get_token_expanded(cx, v);			tval = get_token_expanded(cx, w);			if (x_debug & DEBUG_NEW_MATH_DEBUG)				yell("O: %s <=> %s", s, t);			add_var_alias(s, tval, 0);			add_var_alias(t, sval, 0);			push_token(cx, w);			break;		}		/* Comparison operators */		case DEQ:		{			pop_2_strings(cx, &s, &t);			CHECK_NOEVAL			c = my_stricmp(s, t) ? 0 : 1;			if (x_debug & DEBUG_NEW_MATH_DEBUG)				yell("O: %s == %s -> %d", s, t, c);			push_boolean(cx, c);			break;		}		case NEQ:		{			pop_2_strings(cx, &s, &t);			CHECK_NOEVAL			c = my_stricmp(s, t) ? 1 : 0;			if (x_debug & DEBUG_NEW_MATH_DEBUG)				yell("O: %s != %s -> %d", s, t, c);			push_boolean(cx, c);			break;		}		case MATCH:		{			pop_2_strings(cx, &s, &t);			CHECK_NOEVAL			c = wild_match(t, s) ? 1 : 0;						if (x_debug & DEBUG_NEW_MATH_DEBUG)				yell("O: %s =~ %s -> %d", s, t, c);			push_boolean(cx, c);			break;		}		case NOMATCH:		{			pop_2_strings(cx, &s, &t);			CHECK_NOEVAL			c = wild_match(t, s) ? 0 : 1;						if (x_debug & DEBUG_NEW_MATH_DEBUG)				yell("O: %s !~ %s -> %d", s, t, c);			push_boolean(cx, c);			break;		}		case LES:	COMPARE(a < b,  my_stricmp(s, t) < 0)		case LEQ:	COMPARE(a <= b, my_stricmp(s, t) <= 0)		case GRE:	COMPARE(a > b,  my_stricmp(s, t) > 0)		case GEQ:	COMPARE(a >= b, my_stricmp(s, t) >= 0)		/* Miscelaneous operators */		case QUEST:		{			pop_3_tokens(cx, &c, &v, &w);			CHECK_NOEVAL			if (x_debug & DEBUG_NEW_MATH_DEBUG)			{				yell("O: %d ? %s : %s -> %s", c,					get_token_expanded(cx, v),					get_token_expanded(cx, w),					(c ? get_token_expanded(cx, v) : 					     get_token_expanded(cx, w)));			}			push_token(cx, c ? v : w);			break;		}		case COLON:			break;		case COMMA:		{			pop_2_tokens(cx, &v, &w);			CHECK_NOEVAL			if (x_debug & DEBUG_NEW_MATH_DEBUG)				yell("O: %s , %s -> %s", 					get_token_expanded(cx, v),					get_token_expanded(cx, w),					get_token_expanded(cx, w));			push_token(cx, w);			break;		}		default:			error("Unknown operator or out of operators");			return;	}}/**************************** EXPRESSION LEXER ******************************/static	int	dummy = 1;static int	lexerr (expr_info *c, const char *format, ...){	char 	buffer[BIG_BUFFER_SIZE + 1];	va_list	a;	va_start(a, format);	vsnprintf(buffer, BIG_BUFFER_SIZE, format, a);	va_end(a);	error("%s", buffer);	c->errflag = 1;	return EOI;}/* * 'operand' is state information that tells us about what the next token * is expected to be.  When a binary operator is lexed, then the next token * is expected to be either a unary operator or an operand.  So in this * case 'operand' is set to 1.  When an operand is lexed, then the next token * is expected to be a binary operator, so 'operand' is set to 0.  */static __inline int	check_implied_arg (expr_info *c){	if (c->operand == 2)	{		push_token(c, MAGIC_TOKEN);	/* XXXX Bleh */		c->operand = 0;		*c->args_flag = 1;		return 0;	}	return c->operand;}static __inline TOKEN 	operator (expr_info *c, const char *x, int y, TOKEN z){	check_implied_arg(c);	if (c->operand)		return lexerr(c, "A binary operator (%s) was found "				 "where an operand was expected", x);	c->ptr += y;	c->operand = 1;	return z;}static __inline TOKEN 	unary (expr_info *c, const char *x, int y, TOKEN z){	if (!c->operand)		return lexerr(c, "A unary operator (%s) was found where "				 "a binary operator was expected", x);	c->ptr += y;	c->operand = dummy;	return z;}/* * This finds and extracts the next token in the expression */static int	zzlex (expr_info *c){	char	*start = c->ptr;#define OPERATOR(x, y, z) return operator(c, x, y, z);#define UNARY(x, y, z) return unary(c, x, y, z);	dummy = 1;	if (x_debug & DEBUG_NEW_MATH_DEBUG)		yell("Parsing next token from: [%s]", c->ptr);	for (;;)	{	    switch (*(c->ptr++)) 	    {		case '(':			c->operand = 1;			return M_INPAR;		case ')':			/*			 * If we get a close paren and the lexer is expecting			 * an operand, then obviously thats a syntax error.			 * But we gently just insert the empty value as the			 * rhs for the last operand and hope it all works out.			 */			if (check_implied_arg(c))				push_token(c, 0);			c->operand = 0;			return M_OUTPAR;		case '+':		{			/*			 * Note:  In general, any operand that depends on 			 * whether it is a unary or binary operator based			 * upon the context is required to call the func			 * 'check_implied_arg' to solidify the context.			 * That is because some operators are ambiguous,			 * And if you see   (# + 4), it can only be determined			 * on the fly how to lex that.			 */			check_implied_arg(c);			if (*c->ptr == '+' && (c->operand || !isalnum(*c->ptr))) 			{				c->ptr++;				return c->operand ? PREPLUS : POSTPLUS;			}			else if (*c->ptr == '=') 				OPERATOR("+=", 1, PLUSEQ)			else if (c->operand)				UNARY("+", 0, UPLUS)			else				OPERATOR("+", 0, PLUS)		}		case '-':		{			check_implied_arg(c);			if (*c->ptr == '-' && (c->operand || !isalnum(*c->ptr)))			{				c->ptr++;				return (c->operand) ? PREMINUS : POSTMINUS;			}			else if (*c->ptr == '=') 				OPERATOR("-=", 1, MINUSEQ)			else if (c->operand)				UNARY("-", 0, UMINUS)			else				OPERATOR("-", 0, MINUS)		}		case '*':		{			if (*c->ptr == '*') 			{				c->ptr++;				if (*c->ptr == '=') 					OPERATOR("**=", 1, POWEREQ)				else					OPERATOR("**", 0, POWER)			}			else if (*c->ptr == '=') 				OPERATOR("*=", 1, MULEQ)			else if (c->operand)			{				dummy = 2;				UNARY("*", 0, DEREF)			}			else				OPERATOR("*", 0, MUL)		}		case '/':		{			if (*c->ptr == '=') 				OPERATOR("/=", 1, DIVEQ)			else				OPERATOR("/", 0, DIV)		}		case '%':		{			if (*c->ptr == '=')				OPERATOR("%=", 1, MODEQ)			else				OPERATOR("%", 0, MOD)		}		case '!':		{			if (*c->ptr == '=')				OPERATOR("!=", 1, NEQ)			else if (*c->ptr == '~')				OPERATOR("!~", 1, NOMATCH)			else				UNARY("!", 0, NOT)		}		case '~':			UNARY("~", 0, COMP)		case '&':		{			if (*c->ptr == '&') 			{				c->ptr++;				if (*c->ptr == '=')					OPERATOR("&&=", 1, DANDEQ)				else					OPERATOR("&&", 0, DAND)			} 			else if (*c->ptr == '=') 				OPERATOR("&=", 1, ANDEQ)			else				OPERATOR("&", 0, AND)		}		case '|':		{			if (*c->ptr == '|') 			{				c->ptr++;				if (*c->ptr == '=') 					OPERATOR("||=", 1, DOREQ)				else					OPERATOR("||", 0, DOR)			} 			else if (*c->ptr == '=')				OPERATOR("|=", 1, OREQ)			else				OPERATOR("|", 0, OR)		}		case '^':		{			if (*c->ptr == '^')			{				c->ptr++;				if (*c->ptr == '=')					OPERATOR("^^=", 1, DXOREQ)				else					OPERATOR("^^", 0, DXOR)			}			else if (*c->ptr == '=')				OPERATOR("^=", 1, XOREQ)			else				OPERATOR("^", 0, XOR)		}		case '#':		{			check_implied_arg(c);			if (*c->ptr == '#') 			{				c->ptr++;				if (*c->ptr == '=')					OPERATOR("##=", 1, STRCATEQ)				else					OPERATOR("##", 0, STRCAT)			}			else if (*c->ptr == '=') 				OPERATOR("#=", 1, STRCATEQ)			else if (*c->ptr == '~')				OPERATOR("#~", 1, STRPREEQ)			else if (c->operand)			{				dummy = 2;				UNARY("#", 0, WORDC)			}			else				OPERATOR("#", 0, STRCAT)		}		case '@':			dummy = 2;			UNARY("@", 0, STRLEN)		case '<':		{			if (*c->ptr == '<') 			{				c->ptr++;				if (*c->ptr == '=')					OPERATOR("<<=", 1, SHLEFTEQ)				else					OPERATOR("<<", 0, SHLEFT)			}			else if (*c->ptr == '=')			{				c->ptr++;				if (*c->ptr == '>')					OPERATOR("<=>", 1, SWAP)				else					OPERATOR("<=", 0, LEQ)			}			else				OPERATOR("<", 0, LES)		}		case '>':		{			if (*c->ptr == '>') 			{				c->ptr++;				if (*c->ptr == '=')					OPERATOR(">>=", 1, SHRIGHTEQ)				else					OPERATOR(">>", 0, SHRIGHT)			} 			else if (*c->ptr == '=') 				OPERATOR(">=", 1, GEQ)			else				OPERATOR(">", 0, GRE)		}		case '=':			if (*c->ptr == '=') 				OPERATOR("==", 1, DEQ)			else if (*c->ptr == '~')				OPERATOR("=~", 1, MATCH)			else				OPERATOR("=", 0, EQ)		case '?':			check_implied_arg(c);			c->operand = 1;			return QUEST;		case ':':			/*			 * I dont want to hear anything from you anti-goto			 * bigots out there. ;-)  If you can't figure out			 * what this does, you ought to give up programming.			 * And a big old :p to everyone who insisted that			 * i support this horrid hack.			 */			if (c->operand)				goto handle_expando;			c->operand = 1;			return COLON;		case ',':			/* Same song, second verse. */			if (c->operand)				goto handle_expando;

⌨️ 快捷键说明

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