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 + -
显示快捷键?