📄 hooks.c
字号:
} Dump(OP_NUM, F, Nil, Fi); } else if ( (o = FindOne(Funcs)) >= 0 ) { BN += 3; if ( ! Find("(") ) FailSyn("'(' after function name"); BN++; if ( ! Expression() ) FailSyn("expression"); if ( ! Find(")") ) FailSyn("')' after function argument"); BN++; DumpOp((char)(OP_SIN + o), Fi); } else if ( Buff[BN] == '?' ) { BN++; if ( TStack[TSN-1].Type == 'N' ) { Dump(OP_NUM, _UNK.cval, Nil, Fi); } else { Dump(OP_STR, 0, Nil, Fi); } } else if ( ! memcmp(Buff+BN, "N/A", 3) ) { BN += 3; if ( TStack[TSN-1].Type == 'N' ) { Dump(OP_NUM, _NA.cval, Nil, Fi); } else { Dump(OP_STR, 0, strdup("N/A"), Fi); } } else { return false; } return true;}/*************************************************************************//* *//* Skip spaces and check for specific string *//* *//*************************************************************************/Boolean Find(String S)/* ---- */{ if ( Buff[BN] == ' ' ) BN++; return ( ! Buff[BN] ? false : ! memcmp(Buff+BN, S, strlen(S)) );}/*************************************************************************//* *//* Find one of a zero-terminated list of alternatives *//* *//*************************************************************************/int FindOne(String *Alt)/* ------- */{ int a; for ( a = 0 ; Alt[a] ; a++ ) { if ( Find(Alt[a]) ) return a; } return -1;}/*************************************************************************//* *//* Find an attribute name *//* *//*************************************************************************/Attribute FindAttName()/* ----------- */{ Attribute Att, LongestAtt=0; ForEach(Att, 1, MaxAtt-1) { if ( ! Exclude(Att) && Find(AttName[Att]) ) { if ( ! LongestAtt || strlen(AttName[Att]) > strlen(AttName[LongestAtt]) ) { LongestAtt = Att; } } } if ( ( MaxClass == 1 || ClassThresh ) && ! strcmp(ClassName[1], AttName[LongestAtt]) ) { Error(BADDEF4, Nil, Nil); } return LongestAtt;}/*************************************************************************//* *//* Error message routines. Syntax errors come from the *//* recursive descent parser, semantics errors from the routines *//* that build up the equivalent polish *//* *//*************************************************************************/void DefSyntaxError(String Msg)/* -------------- */{ String RestOfText; int i=10; if ( ! PreviousError ) { RestOfText = Buff + BN; /* Abbreviate text if longer than 12 characters */ if ( CharWidth(RestOfText) > 12 ) {#ifdef UTF8 /* Find beginning of UTF-8 character */ for ( ; (RestOfText[i] & 0x80) ; i++) ;#endif RestOfText[i] = RestOfText[i+1] = '.'; } Error(BADDEF1, RestOfText, Msg); PreviousError = true; }}void DefSemanticsError(int Fi, String Msg, int OpCode)/* ----------------- */{ char Exp[1000], XMsg[1000], Op[1000]; if ( ! PreviousError ) { /* Abbreviate the input if necessary */ if ( BN - Fi > 23 ) { sprintf(Exp, "%.10s...%.10s", Buff+Fi, Buff+BN-10); } else { sprintf(Exp, "%.*s", BN - Fi, Buff+Fi); } switch ( OpCode ) { case OP_AND: sprintf(Op, "%s", "and"); break; case OP_OR: sprintf(Op, "%s", "or"); break; case OP_SEQ: case OP_EQ: sprintf(Op, "%s", "="); break; case OP_SNE: case OP_NE: sprintf(Op, "%s", "<>"); break; case OP_GT: sprintf(Op, "%s", ">"); break; case OP_GE: sprintf(Op, "%s", ">="); break; case OP_LT: sprintf(Op, "%s", "<"); break; case OP_LE: sprintf(Op, "%s", "<="); break; case OP_PLUS: sprintf(Op, "%s", "+"); break; case OP_MINUS: sprintf(Op, "%s", "-"); break; case OP_UMINUS: sprintf(Op, "%s", "unary -"); break; case OP_MULT: sprintf(Op, "%s", "*"); break; case OP_DIV: sprintf(Op, "%s", "/"); break; case OP_MOD: sprintf(Op, "%s", "%"); break; case OP_POW: sprintf(Op, "%s", "^"); break; case OP_SIN: sprintf(Op, "%s", "sin"); break; case OP_COS: sprintf(Op, "%s", "cos"); break; case OP_TAN: sprintf(Op, "%s", "tan"); break; case OP_LOG: sprintf(Op, "%s", "log"); break; case OP_EXP: sprintf(Op, "%s", "exp"); break; case OP_INT: sprintf(Op, "%s", "int"); } sprintf(XMsg, "%s with '%s'", Msg, Op); Error(BADDEF2, Exp, XMsg); PreviousError = true; }}/*************************************************************************//* *//* Reverse polish routines. These use a model of the stack *//* during expression evaluation to detect type conflicts etc *//* *//*************************************************************************/void Dump(char OpCode, ContValue F, String S, int Fi)/* ---- */{ if ( Buff[Fi] == ' ' ) Fi++; if ( ! UpdateTStack(OpCode, F, S, Fi) ) return; /* Make sure enough room for this element */ if ( DN >= DefSize-1 ) { Realloc(AttDef[MaxAtt], DefSize += 100, DefElt); } DefOp(AttDef[MaxAtt][DN]) = OpCode; if ( OpCode == OP_ATT || OpCode == OP_STR ) { DefSVal(AttDef[MaxAtt][DN]) = S; } else { DefNVal(AttDef[MaxAtt][DN]) = F; } DN++;}void DumpOp(char OpCode, int Fi)/* ------ */{ Dump(OpCode, 0, Nil, Fi);}Boolean UpdateTStack(char OpCode, ContValue F, String S, int Fi)/* ------------ */{ if ( TSN >= TStackSize ) { Realloc(TStack, TStackSize += 50, EltRec); } switch ( OpCode ) { case OP_ATT: TStack[TSN].Type = ( Continuous((long) S) ? 'N' : 'S' ); break; case OP_NUM: TStack[TSN].Type = 'N'; break; case OP_STR: TStack[TSN].Type = 'S'; break; case OP_AND: case OP_OR: if ( TStack[TSN-2].Type != 'B' || TStack[TSN-1].Type != 'B' ) { FailSem("non-logical value"); } TSN -= 2; break; case OP_EQ: case OP_NE: if ( TStack[TSN-2].Type != TStack[TSN-1].Type ) { FailSem("incompatible values"); } TSN -= 2; TStack[TSN].Type = 'B'; break; case OP_GT: case OP_GE: case OP_LT: case OP_LE: if ( TStack[TSN-2].Type != 'N' || TStack[TSN-1].Type != 'N' ) { FailSem("non-arithmetic value"); } TSN -= 2; TStack[TSN].Type = 'B'; break; case OP_SEQ: case OP_SNE: if ( TStack[TSN-2].Type != 'S' || TStack[TSN-1].Type != 'S' ) { FailSem("incompatible values"); } TSN -= 2; TStack[TSN].Type = 'B'; break; case OP_PLUS: case OP_MINUS: case OP_MULT: case OP_DIV: case OP_MOD: case OP_POW: if ( TStack[TSN-2].Type != 'N' || TStack[TSN-1].Type != 'N' ) { FailSem("non-arithmetic value"); } TSN -= 2; break; case OP_UMINUS: if ( TStack[TSN-1].Type != 'N' ) { FailSem("non-arithmetic value"); } TSN--; break; case OP_SIN: case OP_COS: case OP_TAN: case OP_LOG: case OP_EXP: case OP_INT: if ( TStack[TSN-1].Type != 'N' ) { FailSem("non-arithmetic argument"); } TSN--; } TStack[TSN].Fi = Fi; TStack[TSN].Li = BN-1; TSN++; return true;}/*************************************************************************//* *//* Evaluate an implicit attribute for a case *//* *//*************************************************************************/#define CUnknownVal(AV) (AV.cval==_UNK.cval)#define DUnknownVal(AV) (! AV.dval)#define DUNA(a) (DUnknownVal(XStack[a]) || NotApplicVal(XStack[a]))#define CUNA(a) (CUnknownVal(XStack[a]) || NotApplicVal(XStack[a]))#define C1(x) (CUNA(XSN-1) ? _UNK.cval : (x))#define C2(x) (CUNA(XSN-1) || CUNA(XSN-2) ? _UNK.cval : (x))#define CD2(x) (CUNA(XSN-1) || CUNA(XSN-2) ? 0 : (x))#define D2(x) (DUNA(XSN-1) || DUNA(XSN-2) ? 0 : (x))AttValue EvaluateDef(Definition D, Description Case)/* ----------- */{ XStackElt XStack[100]; /* allows 100-level nesting */ int XSN=0, DN, bv1, bv2, Mult; double cv1, cv2; String sv1, sv2; Attribute Att; DefElt DElt; AttValue ReturnVal; for ( DN = 0 ; ; DN++) { switch ( DefOp((DElt = D[DN])) ) { case OP_ATT: Att = (long) DefSVal(DElt);#if defined PREDICT || defined SEE5 && defined WIN32 && ! defined _CONSOLE GetValue(Att);#endif if ( Continuous(Att) ) { XStack[XSN++].cval = CVal(Case, Att); } else { XStack[XSN++].sval = ( Unknown(Case, Att) && ! NotApplic(Case, Att) ? 0 : AttValName[Att][XDVal(Case, Att)] ); } break; case OP_NUM: XStack[XSN++].cval = DefNVal(DElt); break; case OP_STR: XStack[XSN++].sval = DefSVal(DElt); break; case OP_AND: bv1 = XStack[XSN-2].dval; bv2 = XStack[XSN-1].dval; XStack[XSN-2].dval = ( bv1 == 3 || bv2 == 3 ? 3 : D2(bv1 == 2 && bv2 == 2 ? 2 : 3) ); XSN--; break; case OP_OR: bv1 = XStack[XSN-2].dval; bv2 = XStack[XSN-1].dval; XStack[XSN-2].dval = ( bv1 == 2 || bv2 == 2 ? 2 : D2(bv1 == 2 || bv2 == 2 ? 2 : 3) ); XSN--; break; case OP_EQ: cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; XStack[XSN-2].dval = ( cv1 == cv2 ? 2 : 3 ); XSN--; break; case OP_NE: cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; XStack[XSN-2].dval = ( cv1 != cv2 ? 2 : 3 ); XSN--; break; case OP_GT: cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; XStack[XSN-2].dval = CD2(cv1 > cv2 ? 2 : 3); XSN--; break; case OP_GE: cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; XStack[XSN-2].dval = CD2(cv1 >= cv2 ? 2 : 3); XSN--; break; case OP_LT: cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; XStack[XSN-2].dval = CD2(cv1 < cv2 ? 2 : 3); XSN--; break; case OP_LE: cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; XStack[XSN-2].dval = CD2(cv1 <= cv2 ? 2 : 3); XSN--; break; case OP_SEQ: sv1 = XStack[XSN-2].sval; sv2 = XStack[XSN-1].sval; XStack[XSN-2].dval = ( ! sv1 && ! sv2 ? 2 : ! sv1 || ! sv2 ? 3 : ! strcmp(sv1, sv2) ? 2 : 3 ); XSN--; break; case OP_SNE: sv1 = XStack[XSN-2].sval; sv2 = XStack[XSN-1].sval; XStack[XSN-2].dval = ( ! sv1 && ! sv2 ? 3 : ! sv1 || ! sv2 ? 2 : strcmp(sv1, sv2) ? 2 : 3 ); XSN--; break; case OP_PLUS: cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; XStack[XSN-2].cval = C2(cv1 + cv2); XSN--; break; case OP_MINUS: cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; XStack[XSN-2].cval = C2(cv1 - cv2); XSN--; break; case OP_MULT: cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; XStack[XSN-2].cval = C2(cv1 * cv2); XSN--; break; case OP_DIV: /* Note: have to set precision of result */ cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; if ( ! cv2 || CUnknownVal(XStack[XSN-2]) || CUnknownVal(XStack[XSN-1]) || NotApplicVal(XStack[XSN-2]) || NotApplicVal(XStack[XSN-1]) ) { XStack[XSN-2].cval = _UNK.cval; } else { Mult = Denominator(cv1); cv1 = cv1 / cv2; while ( fabs(cv2) > 1 ) { Mult *= 10; cv2 /= 10; } XStack[XSN-2].cval = rint(cv1 * Mult) / Mult; } XSN--; break; case OP_MOD: cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; XStack[XSN-2].cval = C2(fmod(cv1, cv2)); XSN--; break; case OP_POW: cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; XStack[XSN-2].cval = ( CUNA(XSN-1) || CUNA(XSN-2) || ( cv1 < 0 && ceil(cv2) != cv2 ) ? _UNK.cval : pow(cv1, cv2) ); XSN--; break; case OP_UMINUS: cv1 = XStack[XSN-1].cval; XStack[XSN-1].cval = C1(-cv1); break; case OP_SIN: cv1 = XStack[XSN-1].cval; XStack[XSN-1].cval = C1(sin(cv1)); break; case OP_COS: cv1 = XStack[XSN-1].cval; XStack[XSN-1].cval = C1(cos(cv1)); break; case OP_TAN: cv1 = XStack[XSN-1].cval; XStack[XSN-1].cval = C1(tan(cv1)); break; case OP_LOG: cv1 = XStack[XSN-1].cval; XStack[XSN-1].cval = ( CUNA(XSN-1) || cv1 <= 0 ? _UNK.cval : log(cv1) ); break; case OP_EXP: cv1 = XStack[XSN-1].cval; XStack[XSN-1].cval = C1(exp(cv1)); break; case OP_INT: cv1 = XStack[XSN-1].cval; XStack[XSN-1].cval = C1(rint(cv1)); break; case OP_END: ReturnVal.dval = XStack[0].dval; return ReturnVal; } }}/*************************************************************************//* *//* Routines for reading model files *//* -------------------------------- *//* *//*************************************************************************/Boolean BINARY=false;int Entry;char* Prop[]={"null", "att", "class", "cut", "conds", "elts", "entries", "forks", "freq", "id", "type", "low", "mid", "high", "result", "rules", "val", "lift", "cover", "ok", "default", "costs", "sample", "init" };char PropName[20],
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -