📄 hooks.c
字号:
} 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((int) 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 UNA(a) (UnknownVal(XStack[a]) || NotApplicVal(XStack[a]))#define C1(x) (UNA(XSN-1) ? _UNK.cval : (x))#define C2(x) (UNA(XSN-1) || UNA(XSN-2) ? _UNK.cval : (x))#define D2(x) (UNA(XSN-1) || UNA(XSN-2) ? _UNK.dval : (x))#define D2(x) (UNA(XSN-1) || UNA(XSN-2) ? _UNK.dval : (x))#define SetCVal#define SetDValAttValue EvaluateDef(Definition D, Description Case)/* ----------- */{ AttValue XStack[100]; /* allows 100-level nesting */ int XSN=0, DN, bv1, bv2, Mult; double cv1, cv2; String sv1, sv2; Attribute Att; DefElt DElt; for ( DN = 0 ; ; DN++) { switch ( DefOp((DElt = D[DN])) ) { case OP_ATT: Att = (int) DefSVal(DElt); if ( Continuous(Att) ) { XStack[XSN++].cval = ( NotApplic(Case, Att) ? _NA.cval : Unknown(Case, Att) ? _UNK.cval : CVal(Case, Att) ); SetDVal; } else { XStack[XSN++].sval = ( Unknown(Case, Att) && ! NotApplic(Case, Att) ? 0 : AttValName[Att][XDVal(Case, Att)] ); SetCVal; } break; case OP_NUM: XStack[XSN++].cval = DefNVal(DElt); SetDVal; break; case OP_STR: XStack[XSN++].sval = DefSVal(DElt); SetCVal; 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--; SetCVal; 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--; SetCVal; break; case OP_EQ: cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; XStack[XSN-2].dval = ( cv1 == cv2 ? 2 : 3 ); XSN--; SetCVal; break; case OP_NE: cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; XStack[XSN-2].dval = ( cv1 != cv2 ? 2 : 3 ); XSN--; SetCVal; break; case OP_GT: cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; XStack[XSN-2].dval = D2(cv1 > cv2 ? 2 : 3); XSN--; SetCVal; break; case OP_GE: cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; XStack[XSN-2].dval = D2(cv1 >= cv2 ? 2 : 3); XSN--; SetCVal; break; case OP_LT: cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; XStack[XSN-2].dval = D2(cv1 < cv2 ? 2 : 3); XSN--; SetCVal; break; case OP_LE: cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; XStack[XSN-2].dval = D2(cv1 <= cv2 ? 2 : 3); XSN--; SetCVal; 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--; SetCVal; 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--; SetCVal; break; case OP_PLUS: cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; XStack[XSN-2].cval = C2(cv1 + cv2); XSN--; SetDVal; break; case OP_MINUS: cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; XStack[XSN-2].cval = C2(cv1 - cv2); XSN--; SetDVal; break; case OP_MULT: cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; XStack[XSN-2].cval = C2(cv1 * cv2); XSN--; SetDVal; break; case OP_DIV: /* Note: have to set precision of result */ cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; if ( ! cv2 || UnknownVal(XStack[XSN-2]) || UnknownVal(XStack[XSN-1]) || NotApplicVal(XStack[XSN-2]) || NotApplicVal(XStack[XSN-1]) ) { XStack[XSN-2] = _UNK; } else { Mult = Denominator(cv1); cv1 = cv1 / cv2; while ( fabs(cv2) > 1 ) { Mult *= 10; cv2 /= 10; } XStack[XSN-2].cval = rint(cv1 * Mult) / Mult; } XSN--; SetDVal; break; case OP_MOD: cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; XStack[XSN-2].cval = C2(fmod(cv1, cv2)); XSN--; SetDVal; break; case OP_POW: cv1 = XStack[XSN-2].cval; cv2 = XStack[XSN-1].cval; XStack[XSN-2].cval = ( UNA(XSN-1) || UNA(XSN-2) || ( cv1 < 0 && ceil(cv2) != cv2 ) ? _UNK.cval : pow(cv1, cv2) ); XSN--; SetDVal; break; case OP_UMINUS: cv1 = XStack[XSN-1].cval; XStack[XSN-1].cval = C1(-cv1); SetDVal; break; case OP_SIN: cv1 = XStack[XSN-1].cval; XStack[XSN-1].cval = C1(sin(cv1)); SetDVal; break; case OP_COS: cv1 = XStack[XSN-1].cval; XStack[XSN-1].cval = C1(cos(cv1)); SetDVal; break; case OP_TAN: cv1 = XStack[XSN-1].cval; XStack[XSN-1].cval = C1(tan(cv1)); SetDVal; break; case OP_LOG: cv1 = XStack[XSN-1].cval; XStack[XSN-1].cval = ( UNA(XSN-1) || cv1 <= 0 ? _UNK.cval : log(cv1) ); SetDVal; break; case OP_EXP: cv1 = XStack[XSN-1].cval; XStack[XSN-1].cval = C1(exp(cv1)); SetDVal; break; case OP_INT: cv1 = XStack[XSN-1].cval; XStack[XSN-1].cval = C1(rint(cv1)); SetDVal; break; case OP_END: return XStack[0]; } }}/*************************************************************************//* *//* 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], *PropVal=Nil, *Unquoted;int PropValSize=0;#define PROPS 23#define ERRORP 0#define ATTP 1#define CLASSP 2#define CUTP 3#define CONDSP 4#define ELTSP 5#define ENTRIESP 6#define FORKSP 7#define FREQP 8#define IDP 9#define TYPEP 10#define LOWP 11#define MIDP 12#define HIGHP 13#define RESULTP 14#define RULESP 15#define VALP 16#define LIFTP 17#define COVERP 18#define OKP 19#define DEFAULTP 20#define COSTSP 21/*************************************************************************//* *//* Read header information and decide whether model files are *//* in ASCII or binary format *//* *//*************************************************************************/void ReadFilePrefix(String Extension)/* -------------- */{#if defined WIN32 || defined _CONSOLE if ( ! (TRf = GetFile(Extension, "rb")) ) Error(NOFILE, Fn, "");#else if ( ! (TRf = GetFile(Extension, "r")) ) Error(NOFILE, Fn, "");#endif StreamIn((char *) &TRIALS, sizeof(int)); if ( memcmp((char *) &TRIALS, "id=", 3) != 0 ) { BINARY = true; BinRecoverDiscreteNames(); } else { BINARY = false; rewind(TRf); ReadHeader(); }}/*************************************************************************//* *//* Read the header information (id, saved names, models) *//* *//*************************************************************************/void ReadHeader()/* --------- */{ Attribute Att; DiscrValue v; char *p, Dummy; int Year, Month, Day; FILE *F; while ( true ) { switch ( ReadProp(&Dummy) ) { case ERRORP: return; case IDP: /* Recover year run and set base date for timestamps */ if ( sscanf(PropVal + strlen(PropVal) - 11, "%d-%d-%d\"", &Year, &Month, &Day) == 3 ) { SetTSBase(Year); } break; case COSTSP: /* Recover costs file used to generate model */ if ( (F = GetFile(".costs", "r")) ) { GetMCosts(F);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -