📄 csparse.c
字号:
bN.max = b->min; bN.min = b->max; } /* check partial ranges (just a min, no max) */ if (!FVal_initialized(&aN.max)) { if (!FVal_initialized(&bN.max)) return FVal_minus(&aN.min, &bN.min); if (FVal_lessThan(&aN.min, &bN.min)) return FVal_minus(&bN.min, &aN.min); if (FVal_lessThan(&bN.max, &aN.min)) return FVal_minus(&bN.max, &aN.min); return ret; } /* we have four values to compare */ { FVal_t minDif = FVal_minus(&bN.min, &aN.min); FVal_t maxDif = FVal_minus(&bN.max, &aN.max); Range_t common; common.min = FVal_lessThan(&bN.min, &aN.min) ? aN.min : bN.min; common.max = FVal_lessThan(&bN.max, &aN.max) ? bN.max : aN.max; if (!FVal_lessThan(&common.max, &common.min)) return ret; /* failure - indicate how far we are off */ return FVal_nearerZero(&minDif, &maxDif) ? minDif : maxDif; }}/* ------------------------------------------------------------------------- *//* C O N S T R U C T O R S */PUBLIC CSParse_t * CSParse_new(void){ CSParse_t * me; if ((me = (CSParse_t *) HT_CALLOC(1, sizeof(CSParse_t))) == NULL) HT_OUTOFMEM("CSParse"); me->nowIn = NowIn_NEEDOPEN; me->token = HTChunk_new(0x10); if ((me->pParseContext = (ParseContext_t *) HT_CALLOC(1, sizeof(ParseContext_t))) == NULL) HT_OUTOFMEM("ParseContext_t"); return me;}PUBLIC void CSParse_delete(CSParse_t * me){ HT_FREE(me->pParseContext); HTChunk_delete(me->token); HT_FREE(me);}/* L A B E L P A R S E R S */PRIVATE StateRet_t callErrorHandler(CSParse_t * pCSParse, const char * errorLocation, char demark, StateRet_t errorCode){ char * token = HTChunk_data(pCSParse->token); pCSParse->pParseContext->pTokenError = errorLocation; return (*pCSParse->pParseContext->pParseErrorHandler)(pCSParse, token, demark, StateRet_ERROR_BAD_CHAR);}/* CSParse_parseChunk - elemental parse engine for all pics nowIns. This passes * tokenized data into the handler functions in the CSParse_t.handlersOf. These * handlers are responsibel for placing the data in the appropriate target. * The text is broken into nowIns and passed a SubParser based on the current * nowIn which is one of: * NowIn_NEEDOPEN - get paren and go to NowIn_ENGINE, text is an error * NowIn_ENGINE - in a containing structure, text goes to engineOf_ * NowIn_NEEDCLOSE - get paren and go to NowIn_ENGINE, text is an error * NowIn_END - expect no more text or parens * NowIn_ERROR - */PUBLIC CSDoMore_t CSParse_parseChunk (CSParse_t * pCSParse, const char * ptr, int len, void * pVoid){ int i; if (!len || !ptr) return CSDoMore_error; for (i = 0; i < len; i++) { pCSParse->offset++; if (pCSParse->quoteState) { if (pCSParse->quoteState == ptr[i]) { pCSParse->quoteState = 0; pCSParse->demark = ' '; } else HTChunk_putb(pCSParse->token, ptr+i, 1); continue; } if (ptr[i] == SQUOTE || ptr[i] == DQUOTE) { if (pCSParse->demark) { while ((pCSParse->nowIn = (*pCSParse->pParseContext->engineOf)(pCSParse, ' ', pVoid)) == NowIn_CHAIN); HTChunk_clear(pCSParse->token); pCSParse->demark = 0; } else if (HTChunk_size(pCSParse->token) && /* && warn(pCSParse, message_UNEXPECTED_CHARACTER, ptr[i])) */ callErrorHandler(pCSParse, ptr+i, ptr[i], StateRet_ERROR_BAD_CHAR) !=StateRet_OK) pCSParse->nowIn = NowIn_ERROR; pCSParse->quoteState = ptr[i]; pCSParse->pParseContext->observedQuotes = YES; continue; } switch (pCSParse->nowIn) { case NowIn_NEEDOPEN: if (ptr[i] == LPAREN) { pCSParse->nowIn = NowIn_ENGINE; continue; } if (isspace((int) ptr[i])) continue;/* if (warn(pCSParse, message_UNEXPECTED_CHARACTER, ptr[i])) pCSParse->nowIn = NowIn_ERROR; */ if (callErrorHandler(pCSParse, ptr+i, ptr[i], StateRet_ERROR_BAD_CHAR) !=StateRet_OK) pCSParse->nowIn = NowIn_ERROR; continue; case NowIn_ENGINE: if (isspace((int) ptr[i])) { if (HTChunk_size(pCSParse->token)) pCSParse->demark = ' '; continue; } if (ptr[i] == LPAREN || ptr[i] == RPAREN || pCSParse->demark) { /* parens override space demarkation */ if (ptr[i] == LPAREN) pCSParse->demark = LPAREN; if (ptr[i] == RPAREN) pCSParse->demark = RPAREN; /* call the engine as long as it wants re-entrance */ while ((pCSParse->nowIn = (*pCSParse->pParseContext->engineOf)(pCSParse, pCSParse->demark, pVoid)) == NowIn_CHAIN); HTChunk_clear(pCSParse->token); pCSParse->demark = 0; if (ptr[i] == LPAREN || ptr[i] == RPAREN) continue; /* continue with next token */ } HTChunk_putb(pCSParse->token, ptr+i, 1); continue; case NowIn_NEEDCLOSE: if (ptr[i] == RPAREN) { pCSParse->nowIn = NowIn_ENGINE; continue; } if (isspace((int) ptr[i])) continue; if (callErrorHandler(pCSParse, ptr+i, ptr[i], StateRet_ERROR_BAD_CHAR) !=StateRet_OK) pCSParse->nowIn = NowIn_ERROR;/* if (warn(pCSParse, message_UNEXPECTED_CHARACTER, ptr[i])) pCSParse->nowIn = NowIn_ERROR; */ continue; case NowIn_END:#if 0 /* enable this to tell the parser to check the remainder of the stream after the parsed object thinks it is done */ if (isspace(ptr[i])) continue;/* if (warn(pCSParse, message_UNEXPECTED_CHARACTER, ptr[i])) pCSParse->nowIn = NowIn_ERROR; */ if (callErrorHandler(pCSParse, ptr+i, ptr[i], StateRet_ERROR_BAD_CHAR) !=StateRet_OK) pCSParse->nowIn = NowIn_ERROR; continue;#else return CSDoMore_done;#endif case NowIn_MATCHCLOSE: if (ptr[i] == RPAREN) { if (!pCSParse->depth) pCSParse->nowIn = NowIn_ENGINE; else pCSParse->depth--; } if (ptr[i] == LPAREN) pCSParse->depth++; continue; case NowIn_ERROR: return CSDoMore_error; break; default: HTTRACE(PICS_TRACE, "PICS: Internal error in parser - bad nowIn:%d.\n" _ pCSParse->nowIn); return CSDoMore_error; } } /* check completion */ return pCSParse->nowIn == NowIn_END ? CSDoMore_done : CSDoMore_more;}PUBLIC BOOL Punct_badDemark(Punct_t validPunctuation, char demark){ switch (demark) { case ' ': return (!(validPunctuation & Punct_WHITE)); case LPAREN: return (!(validPunctuation & Punct_LPAREN)); case RPAREN: return (!(validPunctuation & Punct_RPAREN)); } return YES;}PUBLIC char * CSParse_subState2str(SubState_t subState){ static char space[33]; space[0] = 0; if (subState == SubState_N) strcpy(space, "N"); else if (subState == SubState_X) strcpy(space, "X"); else { int i; SubState_t comp; char ch[] = "A"; for (i = 1, comp = SubState_A; i < (sizeof(SubState_t)*8 - 1); i++, (*ch)++, comp<<=1) if (comp & subState) strcat(space, ch); } return space;}PRIVATE int ParseTrace(const char * fmt, ...){ va_list pArgs; va_start(pArgs, fmt); if (!ParseDebug) return 0; return (vfprintf(stderr, fmt, pArgs));}PUBLIC NowIn_t CSParse_targetParser(CSParse_t * pCSParse, char demark, void * pVoid){/* ParseContext_t * pParseContext = pCSParse->pParseContext; */ TargetObject_t * pTargetObject = pCSParse->pTargetObject; BOOL failedOnPunct = NO; char * token = 0; StateRet_t ret = StateRet_OK; int i;static NowIn_t lastRet = NowIn_END; if (HTChunk_size(pCSParse->token)) { HTChunk_terminate(pCSParse->token); token = HTChunk_data(pCSParse->token); } for (i = 0; i < pTargetObject->stateTokenCount; i++) { StateToken_t * pStateToken = pTargetObject->stateTokens + i; pCSParse->pStateToken = pStateToken; if (!(pCSParse->currentSubState & pStateToken->validSubStates)) continue; if (pStateToken->pCheck) { /* use check function */ StateRet_t checkRes; checkRes = (*pStateToken->pCheck)(pCSParse, pStateToken, token, demark); switch (checkRes) { case StateRet_WARN_BAD_PUNCT: failedOnPunct = YES; case StateRet_WARN_NO_MATCH: continue; case StateRet_ERROR_BAD_CHAR: (*pCSParse->pParseContext->pParseErrorHandler)(pCSParse, token, demark, StateRet_ERROR_BAD_CHAR); /* if (pTargetObject->pDestroy) (*pTargetObject->pDestroy)(pCSParse); */ return NowIn_ERROR; default: break; } } else { /* or match by name[s] */ if (!(pStateToken->command & Command_MATCHANY)) { if (token && pStateToken->name1) { if (strcasecomp(token, pStateToken->name1) && (!pStateToken->name2 || strcasecomp(token, pStateToken->name2))) continue; } else { if (token != pStateToken->name1) continue; } } if (Punct_badDemark(pStateToken->validPunctuation, demark)) { failedOnPunct = YES; continue; } }/* open or close and do the appropriate callbacks */ if (lastRet != NowIn_CHAIN) ParseTrace("%30s %c ", token ? token : "", demark); ParseTrace("%10s - %s:%10s => ", pCSParse->pTargetObject->note, CSParse_subState2str(pCSParse->currentSubState), pStateToken->note); if (pStateToken->command & Command_NOTOKEN) { HTChunk_clear(pCSParse->token); token = 0; } if (pStateToken->command & Command_OPEN && pTargetObject->pOpen) if ((*pTargetObject->pOpen)(pCSParse, token, demark) == StateRet_ERROR) return NowIn_ERROR; if (pStateToken->command & (Command_OPEN|Command_CLOSE) && pCSParse->pParseContext->pTargetChangeCallback) { ParseTrace("%3d", pStateToken->command & Command_CLOSE ? -pTargetObject->targetChange : pTargetObject->targetChange); if ((*pCSParse->pParseContext->pTargetChangeCallback)(pCSParse, pTargetObject, pTargetObject->targetChange, (BOOL)(pStateToken->command & Command_CLOSE), pVoid) == StateRet_ERROR) return NowIn_ERROR; } else ParseTrace(" "); if (pStateToken->command & Command_CLOSE && pTargetObject->pClose) ret = (*pTargetObject->pClose)(pCSParse, token, demark); if (pStateToken->pPrep && ret != NowIn_ERROR) ret = (*pStateToken->pPrep)(pCSParse, token, demark); if (pStateToken->pNextTargetObject) pCSParse->pTargetObject = pStateToken->pNextTargetObject; if (pStateToken->nextSubState != SubState_X) pCSParse->currentSubState = pStateToken->nextSubState; ParseTrace("%10s - %s", pCSParse->pTargetObject->note, CSParse_subState2str(pCSParse->currentSubState)); if (pStateToken->command & Command_CHAIN) { ParseTrace(" -O-O-"); return lastRet = NowIn_CHAIN; } ParseTrace("\n"); return lastRet = ret == StateRet_ERROR_BAD_CHAR ? NowIn_ERROR : ret == StateRet_DONE ? NowIn_END : NowIn_ENGINE; } (*pCSParse->pParseContext->pParseErrorHandler)(pCSParse, token, demark, failedOnPunct ? StateRet_WARN_BAD_PUNCT : StateRet_WARN_NO_MATCH); if (pTargetObject->pDestroy) (*pTargetObject->pDestroy)(pCSParse); return NowIn_ERROR;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -