📄 hooks.c
字号:
Dv = Which(Name, AttValName[Att], 1, MaxAttVal[Att]); if ( ! Dv ) { if ( StatBit(Att, DISCRETE) ) { if ( Train ) { /* Add value to list */ if ( MaxAttVal[Att] >= (long) AttValName[Att][0] ) { XError(TOOMANYVALS, AttName[Att], (char *) AttValName[Att][0] - 1); Dv = MaxAttVal[Att]; } else { Dv = ++MaxAttVal[Att]; AttValName[Att][Dv] = strdup(Name); AttValName[Att][Dv+1] = "<other>"; /* no free */ } } else { /* Set value to "<other>" */ Dv = MaxAttVal[Att] + 1; } } else { XError(BADATTVAL, AttName[Att], Name); Dv = UNKNOWN; } } DVal(DVec, Att) = Dv; } else { /* Continuous value */ if ( TStampVal(Att) ) { CVal(DVec, Att) = Cv = TStampToMins(Name); if ( Cv >= 1E9 ) /* long time in future */ { XError(BADTSTMP, AttName[Att], Name); DVal(DVec, Att) = UNKNOWN; } } else if ( DateVal(Att) ) { CVal(DVec, Att) = Cv = DateToDay(Name); if ( Cv < 1 ) { XError(BADDATE, AttName[Att], Name); DVal(DVec, Att) = UNKNOWN; } } else if ( TimeVal(Att) ) { CVal(DVec, Att) = Cv = TimeToSecs(Name); if ( Cv < 0 ) { XError(BADTIME, AttName[Att], Name); DVal(DVec, Att) = UNKNOWN; } } else { CVal(DVec, Att) = strtod(Name, &EndName); if ( EndName == Name || *EndName != '\0' ) { XError(BADATTVAL, AttName[Att], Name); DVal(DVec, Att) = UNKNOWN; } } CheckValue(DVec, Att); } } if ( ClassAtt ) { if ( Discrete(ClassAtt) ) { Class(DVec) = XDVal(DVec, ClassAtt); } else if ( Unknown(DVec, ClassAtt) || NotApplic(DVec, ClassAtt) ) { Class(DVec) = 0; } else { /* Find appropriate segment using class thresholds */ Cv = CVal(DVec, ClassAtt); for ( Dv = 1 ; Dv < MaxClass && Cv > ClassThresh[Dv] ; Dv++ ) ; Class(DVec) = Dv; } } else { if ( ! ReadName(Df, Name, 1000, '\00') ) { XError(HITEOF, Fn, ""); FreeLastCase(DVec); return Nil; } Class(DVec) = Dv = Which(Name, ClassName, 1, MaxClass); } return DVec; } else { return Nil; }}/*************************************************************************//* *//* Store a label or ignored value in IValStore *//* *//*************************************************************************/int StoreIVal(String S)/* --------- */{ int StartIx, Length; if ( (Length=strlen(S) + 1) + IValsOffset > IValsSize ) { if ( IgnoredVals ) { Realloc(IgnoredVals, IValsSize += 32768, char); } else { IValsSize = 32768; IValsOffset = 0; IgnoredVals = Alloc(IValsSize, char); } } StartIx = IValsOffset; strcpy(IgnoredVals + StartIx, S); IValsOffset += Length; return StartIx;}/*************************************************************************//* *//* Check for bad continuous value *//* *//*************************************************************************/void CheckValue(Description DVec, Attribute Att)/* ---------- */{ ContValue Cv; Cv = CVal(DVec, Att); if ( ! finite(Cv) ) { Error(BADNUMBER, AttName[Att], ""); CVal(DVec, Att) = UNKNOWN; }}/*************************************************************************//* *//* Routines to handle implicitly-defined attributes *//* *//*************************************************************************/char *Buff; /* buffer for input characters */int BuffSize, BN; /* size and index of next character */EltRec *TStack; /* expression stack model */int TStackSize, TSN; /* size of stack and index of next entry */int DefSize, DN; /* size of definition and next element */Boolean PreviousError; /* to avoid parasytic errors */AttValue _UNK, /* quasi-constant for unknown value */ _NA; /* ditto for not applicable */#define FailSyn(Msg) {DefSyntaxError(Msg); return false;}#define FailSem(Msg) {DefSemanticsError(Fi, Msg, OpCode); return false;}typedef union _xstack_elt { DiscrValue _discr_val; ContValue _cont_val; String _string_val; } XStackElt;#define cval _cont_val#define sval _string_val#define dval _discr_val/*************************************************************************//* *//* A definition is handled in two stages: *//* - The definition is read (up to a line ending with a period) *//* replacing multiple whitespace characters with one space *//* - The definition is then read (using a recursive descent *//* parser), building up a reverse polish expression *//* Syntax and semantics errors are flagged *//* *//*************************************************************************/void ImplicitAtt(FILE *Nf)/* ----------- */{#ifdef CUBIST _UNK.cval = UNKNOWN;#else _UNK.dval = UNKNOWN;#endif _NA.dval = NA; /* Get definition as a string in Buff */ ReadDefinition(Nf); PreviousError = false; BN = 0; /* Allocate initial stack and attribute definition */ TStack = Alloc(TStackSize=50, EltRec); TSN = 0; AttDef[MaxAtt] = Alloc(DefSize = 100, DefElt); DN = 0; /* Parse Buff as an expression terminated by a period */ Expression(); if ( ! Find(".") ) DefSyntaxError("'.' ending definition"); /* Final check -- defined attribute must not be of type String */ if ( ! PreviousError ) { if ( DN == 1 && DefOp(AttDef[MaxAtt][0]) == OP_ATT ) { Error(SAMEATT, AttName[ (long) DefSVal(AttDef[MaxAtt][0]) ], Nil); PreviousError = true; } if ( TStack[0].Type == 'B' ) { /* Defined attributes should never have a value N/A */ MaxAttVal[MaxAtt] = 3; AttValName[MaxAtt] = AllocZero(4, String); AttValName[MaxAtt][1] = strdup("??"); AttValName[MaxAtt][2] = strdup("t"); AttValName[MaxAtt][3] = strdup("f"); } else { MaxAttVal[MaxAtt] = 0; } } if ( PreviousError ) { DN = 0; SpecialStatus[MaxAtt] = EXCLUDE; } /* Write a terminating marker */ DefOp(AttDef[MaxAtt][DN]) = OP_END; Free(Buff); Free(TStack);}/*************************************************************************//* *//* Read the text of a definition. Skip comments, collapse *//* multiple whitespace characters. *//* *//*************************************************************************/void ReadDefinition(FILE *f)/* -------------- */{ Boolean LastWasPeriod=false; char c; Buff = Alloc(BuffSize=50, char); BN = 0; while ( true ) { c = InChar(f); if ( c == '|' ) SkipComment; if ( c == EOF || c == '\n' && LastWasPeriod ) { /* The definition is complete. Add a period if it's not there already and terminate the string */ if ( ! LastWasPeriod ) Append('.'); Append(0); return; } if ( Space(c) ) { Append(' '); } else if ( c == '\\' ) { /* Escaped character -- bypass any special meaning */ Append(InChar(f)); } else { LastWasPeriod = ( c == '.' ); Append(c); } }}/*************************************************************************//* *//* Append a character to Buff, resizing it if necessary *//* *//*************************************************************************/void Append(char c)/* ------ */{ if ( c == ' ' && (! BN || Buff[BN-1] == ' ' ) ) return; if ( BN >= BuffSize ) { Realloc(Buff, BuffSize += 50, char); } Buff[BN++] = c;}/*************************************************************************//* *//* Recursive descent parser with syntax error checking. *//* The reverse polish is built up by calls to Dump() and DumpOp(), *//* which also check for semantic validity. *//* *//* For possible error messages, each routine also keeps track of *//* the beginning of the construct that it recognises (in Fi). *//* *//*************************************************************************/Boolean Expression()/* ---------- */{ int Fi=BN; if ( Buff[BN] == ' ' ) BN++; if ( ! Conjunct() ) FailSyn("expression"); while ( Find("or") ) { BN += 2; if ( ! Conjunct() ) FailSyn("expression"); DumpOp(OP_OR, Fi); } return true;}Boolean Conjunct()/* -------- */{ int Fi=BN; if ( ! SExpression() ) FailSyn("expression"); while ( Find("and") ) { BN += 3; if ( ! SExpression() ) FailSyn("expression"); DumpOp(OP_AND, Fi); } return true;}String RelOps[] = {">=", "<=", "!=", "<>", ">", "<", "=", (String) 0};Boolean SExpression()/* ----------- */{ int o, Fi=BN; if ( ! AExpression() ) FailSyn("expression"); if ( (o = FindOne(RelOps)) >= 0 ) { BN += strlen(RelOps[o]); if ( ! AExpression() ) FailSyn("expression"); DumpOp(( o == 0 ? OP_GE : o == 1 ? OP_LE : o == 4 ? OP_GT : o == 5 ? OP_LT : o == 2 || o == 3 ? ( TStack[TSN-1].Type == 'S' ? OP_SNE : OP_NE ) : ( TStack[TSN-1].Type == 'S' ? OP_SEQ : OP_EQ ) ), Fi); } return true;}String AddOps[] = {"+", "-", (String) 0};Boolean AExpression()/* ----------- */{ int o, Fi=BN; if ( Buff[BN] == ' ' ) BN++; if ( (o = FindOne(AddOps)) >= 0 ) { BN += 1; } if ( ! Term() ) FailSyn("expression"); if ( o == 1 ) DumpOp(OP_UMINUS, Fi); while ( (o = FindOne(AddOps)) >= 0 ) { BN += 1; if ( ! Term() ) FailSyn("arithmetic expression"); DumpOp((char)(OP_PLUS + o), Fi); } return true;}String MultOps[] = {"*", "/", "%", (String) 0};Boolean Term()/* ---- */{ int o, Fi=BN; if ( ! Factor() ) FailSyn("expression"); while ( (o = FindOne(MultOps)) >= 0 ) { BN += 1; if ( ! Factor() ) FailSyn("arithmetic expression"); DumpOp((char)(OP_MULT + o), Fi); } return true;}Boolean Factor()/* ---- */{ int Fi=BN; if ( ! Primary() ) FailSyn("value"); while ( Find("^") ) { BN += 1; if ( ! Primary() ) FailSyn("exponent"); DumpOp(OP_POW, Fi); } return true;}Boolean Primary()/* ------- */{ if ( Atom() ) { return true; } else if ( Find("(") ) { BN++; if ( ! Expression() ) FailSyn("expression in parentheses"); if ( ! Find(")") ) FailSyn("')'"); BN++; return true; } else { FailSyn("attribute, value, or '('"); }}String Funcs[] = {"sin", "cos", "tan", "log", "exp", "int", (String) 0};Boolean Atom()/* ---- */{ char *EndPtr, *Str, Date[11], Time[9]; int o, FirstBN, Fi=BN; ContValue F; Attribute Att; if ( Buff[BN] == ' ' ) BN++; if ( Buff[BN] == '"' ) { FirstBN = ++BN; while ( Buff[BN] != '"' ) { if ( ! Buff[BN] ) FailSyn("closing '\"'"); BN++; } /* Make a copy of the string without double quotes */ Buff[BN] = '\00'; Str = strdup(Buff + FirstBN); Buff[BN++] = '"'; Dump(OP_STR, 0, Str, Fi); } else if ( (Att = FindAttName()) ) { BN += strlen(AttName[Att]); Dump(OP_ATT, 0, (String) (long) Att, Fi); } else if ( isdigit(Buff[BN]) ) { /* Check for date or time first */ if ( ( Buff[BN+4] == '/' && Buff[BN+7] == '/' || Buff[BN+4] == '-' && Buff[BN+7] == '-' )&& isdigit(Buff[BN+1]) && isdigit(Buff[BN+2]) && isdigit(Buff[BN+3]) && isdigit(Buff[BN+5]) && isdigit(Buff[BN+6]) && isdigit(Buff[BN+8]) && isdigit(Buff[BN+9]) ) { memcpy(Date, Buff+BN, 10); Date[10] = '\00'; if ( (F = DateToDay(Date)) == 0 ) { Error(BADDEF1, Date, "date"); } BN += 10; } else if ( Buff[BN+2] == ':' && Buff[BN+5] == ':' && isdigit(Buff[BN+1]) && isdigit(Buff[BN+3]) && isdigit(Buff[BN+4]) && isdigit(Buff[BN+6]) && isdigit(Buff[BN+7]) ) { memcpy(Time, Buff+BN, 8); Time[8] = '\00'; if ( (F = TimeToSecs(Time)) == 0 ) { Error(BADDEF1, Time, "time"); } BN += 8; } else { F = strtod(Buff+BN, &EndPtr); /* Check for period after integer */ if ( EndPtr > Buff+BN+1 && *(EndPtr-1) == '.' ) { EndPtr--; } BN = EndPtr - Buff;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -