static int CALLBACK PathWordBreakProc(LPCWSTR lpch, int ichCurrent, int cch, int code) { if (code == WB_ISDELIMITER) return IsDelimiter(lpch[ichCurrent]); else { int dir = (code == WB_LEFT) ? -1 : 1; for(; 0 <= ichCurrent && ichCurrent < cch; ichCurrent += dir) if (IsDelimiter(lpch[ichCurrent])) return ichCurrent; } return ichCurrent; }
void StringTokenizer::GetNextToken() { // skip till end of token while( !AtEnd() && IsWhitespace(*mCurrentPos) ) mCurrentPos++; // this is the start of the token mCurToken = (char*)mCurrentPos; // skip till end of token for(; !AtEnd(); ++mCurrentPos) { if( IsWhitespace(*mCurrentPos) ) break; if( IsDelimiter(*mCurrentPos) ) { if( mCurrentPos == (Byte*)mCurToken ) ++mCurrentPos; break; } } // end of search condition if( mCurrentPos == (Byte*)mCurToken ) { mCurToken = 0; mCurTokenLength = 0; } else { mCurTokenLength = mCurrentPos - (Byte*)mCurToken; } }
char *ReadWord_by_value(char *text,int curLoc,char specificDelimiter) { char *tempItem=NULL,*tempText=NULL; enum Boolean delimiterFound=FALSE,inQuotes=FALSE; int i; /* if(specificDelimiter==NULL) specificDelimiter=' ';*/ tempText = StringTrim(text+curLoc); if(strlen(tempText)==0) return NULL; for(i=0;delimiterFound==FALSE;i++) { if(tempText[i]=='\"') if(inQuotes==TRUE) inQuotes=FALSE; else inQuotes=TRUE; else if(IsDelimiter(tempText[i],specificDelimiter)==TRUE) { delimiterFound=TRUE; if(i==0) { delimiterFound=FALSE; break; } if(tempText[i]==':') { tempItem=(char*)realloc(tempItem,(i+1)*sizeof(char)); tempItem[i]=tempText[i]; i++; } else if(tempText[i]==' ' && inQuotes==TRUE) { delimiterFound=FALSE; tempItem=(char*)realloc(tempItem,(i+1)*sizeof(char)); tempItem[i]=tempText[i]; continue; } tempItem=(char*)realloc(tempItem,(i+1)*sizeof(char)); tempItem[i]='\0'; break; } if(delimiterFound==FALSE) { tempItem=(char*)realloc(tempItem,(i+1)*sizeof(char)); tempItem[i]=tempText[i]; } } return tempItem; }
int CubeLexer::SortText(char *SourceText) { unsigned long Offset=0; if (m_Sources) { free(m_Sources); m_SourceOffset=0; m_SortStatus=SORT_STATUS_NORMAL; } if ((m_Sources=(char *)malloc(strlen(SourceText)+1))==NULL) { return FALSE; } m_SortStatus=SORT_STATUS_NEWLINE; while(*SourceText) { if (NextChar(*SourceText)) { if(IsNewLine(*SourceText)&&IsSpacer(m_Sources[Offset-1])) Offset--; if(IsCommentStart(*SourceText)&&IsSpacer(m_Sources[Offset-1])) Offset--; if(IsDelimiter(*SourceText)&&IsSpacer(m_Sources[Offset-1])) Offset--; if(IsSpacer(*SourceText)&&IsDelimiter(m_Sources[Offset-1])) { SourceText++; continue; } m_Sources[Offset++]=*(SourceText); } SourceText++; } m_Sources[Offset]='\0'; return TRUE; }
bool WLex::GetValue(String *pStr) { if(m_bEOF) { return false; } m_bEOL = false; pStr->resize(0); int ch; for(;;) { ch = getc(m_File); if(ch == EOF) { m_bEOL = m_bEOF = true; break; } if(ch == '\n') { m_bEOL = true; break; } if(IsEscape(ch)) { int chx = getc(m_File); if(chx == EOF) { m_bEOF = true; break; } pStr->append(1, char(ch)); continue; } if(IsDelimiter(ch)) { break; } pStr->append(1, char(ch)); } return pStr->length() > 0; }
void CmdUart_t::IProcessByte(uint8_t b) { uint8_t d=0; if(b == '#') RxState = rsCmdCode1; // If # is received anywhere, start again else switch(RxState) { case rsCmdCode1: if(TryConvertToDigit(b, &d)) { CmdCode = d << 4; RxState = rsCmdCode2; } else IResetCmd(); break; case rsCmdCode2: if(TryConvertToDigit(b, &d)) { CmdCode |= d; RxState = rsData1; } else IResetCmd(); break; case rsData1: if(TryConvertToDigit(b, &d)) { *PCmdWrite = d << 4; RxState = rsData2; } else if(IsDelimiter(b)) return; // skip delimiters else if(IsEnd(b)) { UartCmdCallback(CmdCode, CmdData, (PCmdWrite - CmdData)); IResetCmd(); } else IResetCmd(); break; case rsData2: if(TryConvertToDigit(b, &d)) { *PCmdWrite |= d; RxState = rsData1; // Prepare to rx next byte if(PCmdWrite < (CmdData + (UART_CMDDATA_SZ-1))) PCmdWrite++; } else IResetCmd(); // Delimiters and End symbols are not allowed in the middle of byte break; default: break; } // switch }
void StringTokenizer::GetPreviousToken() { Byte* pEndOfToken; // move to end of string if we are out of it. if( *mCurrentPos == 0 ) --mCurrentPos; // skip till end of previous token while( mCurrentPos > mStartPos && IsWhitespace(*mCurrentPos) ) mCurrentPos--; pEndOfToken = mCurrentPos; // skip till start of previous token for( ; mCurrentPos > mStartPos; --mCurrentPos ) { if( IsWhitespace(*mCurrentPos) ) break; if( IsDelimiter(*mCurrentPos) ) { if( pEndOfToken == mCurrentPos ) --mCurrentPos; break; } } if( pEndOfToken == mCurrentPos ) { mCurToken = 0; mCurTokenLength = 0; } else { mCurToken = (char*)mCurrentPos+1; mCurTokenLength = pEndOfToken - mCurrentPos; } }
OdbcExpected<bool> SqlLexer::Shift() { if (IsEod()) { SetEod(); return false; } TokenType::Type tokenType = TokenType::EOD; while (!IsEod()) { int32_t tokenBegin = pos; switch (sql[pos]) { case '-': { // Full-line comment. if (HaveData(1) && sql[pos + 1] == '-') { pos += 2; while (!IsEod() && sql[pos] != '\n' && sql[pos] != '\r') ++pos; continue; } // Minus. tokenType = TokenType::MINUS; break; } case '"': { // Quoted string. while (true) { ++pos; if (IsEod()) return OdbcError(SqlState::SHY000_GENERAL_ERROR, "Unclosed quoted identifier."); if (sql[pos] == '"') { if (!HaveData(2) || sql[pos + 1] != '"') break; ++pos; } } tokenType = TokenType::QUOTED; break; } case '\'': { // String literal. while (true) { ++pos; if (IsEod()) return OdbcError(SqlState::SHY000_GENERAL_ERROR, "Unclosed string literal."); if (sql[pos] == '\'') { if (!HaveData(2) || sql[pos + 1] != '\'') break; ++pos; } } tokenType = TokenType::STRING; break; } case '.': { tokenType = TokenType::DOT; break; } case ',': { tokenType = TokenType::COMMA; break; } case ';': { tokenType = TokenType::SEMICOLON; break; } case '(': { tokenType = TokenType::PARENTHESIS_LEFT; break; } case ')': { tokenType = TokenType::PARENTHESIS_RIGHT; break; } default: { // Skipping spaces. if (iscntrl(sql[pos]) || isspace(sql[pos])) { do { ++pos; } while (!IsEod() && (iscntrl(sql[pos]) || isspace(sql[pos]))); continue; } // Word. while (!IsEod() && !IsDelimiter(sql[pos])) ++pos; --pos; tokenType = TokenType::WORD; break; } } ++pos; if (tokenType != TokenType::EOD) { currentToken = SqlToken(&sql[tokenBegin], pos - tokenBegin, tokenType); return true; } } SetEod(); return false; }
bool wxPdfTokenizer::IsDelimiterOrWhitespace(int ch) { return IsWhitespace(ch) || IsDelimiter(ch) || (ch == -1); }
static void MoveNextWord( LPCLASSDATA lpcd ) { /* * Obtain current caret column and a * pointer to the line. */ int nPos = lpcd->ptCaretPos.x; LPLINE lpLine = GETLINE( lpcd ); /* * Are we at the end of the line? */ if ( nPos == lpLine->nLength ) { /* * Yes go down one line and to the * first word on that line. */ if ( lpcd->ptCaretPos.y < ArrayGetSize( lpcd->lpLines ) - 1 ) { /* * Start at 0 */ nPos = 0; /* * Go down. */ lpcd->ptCaretPos.y++; /* * Skip spaces. */ lpLine = GETLINE( lpcd ); if ( lpLine->pcText ) { while ( _istspace( lpLine->pcText[ nPos ] ) && nPos < GETLINE( lpcd )->nLength ) nPos++; } /* * Store new column position. */ lpcd->ptCaretPos.x = nPos; } } else { BOOL bBreakOnNonSpace = FALSE; /* * Are we on a white space? */ if ( _istspace( lpLine->pcText[ nPos ] )) { /* * Skip spaces... */ while ( _istspace( lpLine->pcText[ nPos ] ) && nPos < lpLine->nLength ) nPos++; } else if ( IsDelimiter( lpcd, lpLine->pcText [ nPos ] )) /* A delimiter? */ { /* * Skip all delimiters and white spaces. */ while (( IsDelimiter( lpcd, lpLine->pcText[ nPos ] ) || _istspace( lpLine->pcText[ nPos ] )) && nPos < lpLine->nLength ) { /* * White space? */ if ( _istspace( lpLine->pcText[ nPos ] )) /* * Yes. Break on the next non-white space. */ bBreakOnNonSpace = TRUE; else if ( bBreakOnNonSpace ) /* * Stop at this non-white space. */ break; nPos++; } } else { /* * Skip all non delimiters and white spaces. */ while (( IsDelimiter( lpcd, lpLine->pcText[ nPos ] ) == FALSE || _istspace( lpLine->pcText[ nPos ] )) && nPos < lpLine->nLength ) { /* * White space? */ if ( _istspace( lpLine->pcText[ nPos ] )) /* * Yes. Break on the next non-white space. */ bBreakOnNonSpace = TRUE; else if ( bBreakOnNonSpace ) /* * Stop at this non-white space. */ break; nPos++; } } /* * Store position. */ lpcd->ptCaretPos.x = nPos; } /* * Save this position. */ lpcd->nLastColumnPos = GetCaretOffset( lpcd, lpcd->ptCaretPos.x ); /* * Make sure the caret is in the view. */ MakeCaretVisible( lpcd ); /* * Update caret position. */ UpdateCaret( lpcd ); }
void HandleCommand(char *line,int* curPos,opcode thisOpcode,char* label) { BinaryMachineCode bmc; int decimal; char *binaryValue=NULL,*base12code=NULL,*param1=NULL,*param2=NULL; int addressingType1=NULL,addressingType2=NULL; enum Boolean errorFound=FALSE; Cmd tempCommand; char* errmsg=NULL; switch(thisOpcode.operand_count) { case 0: param1=ReadWord(line,curPos,' '); if(param1==NULL) FIX_NULL_STRING(param1); param1=StringTrim(param1); if(strlen(param1)>0 && IsDelimiter(param1[0],' ')==FALSE) { ALLOCATE_STRING(errmsg,50); strcpy(errmsg,thisOpcode.op); strcat(errmsg," - too many arguments for command "); ErrorHandler(CompilingError,errmsg); printf("b"); return; } decimal=OctalToDecimal(thisOpcode.value_8); FIX_NULL_STRING(binaryValue); strcpy(binaryValue,ConvertIntToCharByBase(0,ConversionToBmcType,2)); bmc = CreateBmcCode(binaryValue); bmc=AlterBmcValue(BmcOperationCode,OctalToDecimal(thisOpcode.value_8),bmc); /*strcpy(,convertBinaryMachineCodeToString(bmc,PrintStyle)); strcpy(binaryValue,ConvertIntToCharByBase(decimal,ConversionToBmcType,2)); ALLOCATE_STRING(bmcString,BMC_LENGTH+2); strcpy(bmcString,binaryValue); for(i=strlen(binaryValue);i<BMC_LENGTH;i++) bmcString[i]='0'; bmcString[i]='\0'; */ FIX_NULL_STRING(label); /*bmc=CreateBmcCode(bmcString);*/ FIX_NULL_STRING(base12code); strcpy(base12code,ConvertBinaryStringToBase12(convertBinaryMachineCodeToString(bmc,BmcStyle))); tempCommand=CreateCmdObject(label,ConvertIntToCharByBase(IC,ConversionToAddress,10),ConvertIntToCharByBase(IC,ConversionToAddress,12),thisOpcode.op,"",bmc,base12code,'a'); IC++; CmdQueue_AddRecord(tempCommand,computerLanguage); break; case 1: param2=ReadWord(line,curPos,' '); if(param2==NULL) { ALLOCATE_STRING(errmsg,50); strcpy(errmsg,thisOpcode.op); strcat(errmsg," - too few arguments for command "); ErrorHandler(CompilingError,errmsg); return; } addressingType2=IdentifyAddressing(param2); if(IsAddressingAllowedForCommand(addressingType2, thisOpcode.adddressing_type_dst)==FALSE) { ErrorHandler(CompilingError,"operand is not allowed for this command"); errorFound=TRUE; return; } param1=ReadWord(line,curPos,' '); if(param1!=NULL && strlen(param1)>0) { ALLOCATE_STRING(errmsg,50); strcpy(errmsg,thisOpcode.op); strcat(errmsg," - too many arguments for command "); ErrorHandler(CompilingError,errmsg); return; } CreateBmcForCommand(line,label,thisOpcode,param1,param2,NULL,addressingType2); break; case 2: param1=ReadWord(line,curPos,' '); param2=ReadWord(line,curPos,' '); if(param1==NULL || param2==NULL) { ALLOCATE_STRING(errmsg,50); strcpy(errmsg,thisOpcode.op); strcat(errmsg," - too few arguments for command: "); ErrorHandler(CompilingError,errmsg); return; } if(ReadWord(line,curPos,' ') !=NULL) { ALLOCATE_STRING(errmsg,50); strcpy(errmsg,thisOpcode.op); strcat(errmsg," - too many arguments for command: "); ErrorHandler(CompilingError,errmsg); return; } addressingType1=IdentifyAddressing(param1);/* source */ addressingType2=IdentifyAddressing(param2);/* destination */ if(IsAddressingAllowedForCommand(addressingType1, thisOpcode.adddressing_type_src)==FALSE) { ErrorHandler(CompilingError,"operand is not allowed for this command"); errorFound=TRUE; } if(IsAddressingAllowedForCommand(addressingType2, thisOpcode.adddressing_type_dst)==FALSE) { errorFound=TRUE; ErrorHandler(CompilingError,"operand is not allowed for this command"); } if(errorFound==TRUE) return; CreateBmcForCommand(line,label,thisOpcode,param1,param2,addressingType1,addressingType2); break; default: break; } }
char *ReadWord(char *text,int* curLoc,char specificDelimiter) /* white space fix (bug fix: input changed to "by reference") */ { char *tempItem=NULL,*tempText=NULL; enum Boolean delimiterFound=FALSE,inQuotes=FALSE; int i,newstr_index=0,t; /*if(specificDelimiter==NULL) specificDelimiter=' ';*/ if(text==NULL || strlen(text)==0) return NULL; tempText = StringTrim(text+(*curLoc)); if(strlen(tempText)==0 || *curLoc>strlen(text)) return NULL; t=strlen(tempText); for(i=0;IsDelimiter(tempText[i],' ')==TRUE && i<strlen(tempText);i++,(*curLoc)++) { continue; } tempText+=i; for(i=0;delimiterFound==FALSE;i++) { if(tempText[i]=='\"') if(inQuotes==TRUE) inQuotes=FALSE; else inQuotes=TRUE; else if(IsDelimiter(tempText[i],specificDelimiter)==TRUE) { delimiterFound=TRUE; if(i==0) { delimiterFound=FALSE; continue; } if(tempText[i]==':') { ALLOCATE_STRING(tempItem,++newstr_index); tempItem[newstr_index-1]=tempText[i]; i++; } else if(tempText[i]==' ' && inQuotes==TRUE) { delimiterFound=FALSE; ALLOCATE_STRING(tempItem,++newstr_index); tempItem[newstr_index-1]=tempText[i]; continue; } ALLOCATE_STRING(tempItem,++newstr_index); tempItem[newstr_index-1]='\0'; break; } if(delimiterFound==FALSE) { ALLOCATE_STRING(tempItem,++newstr_index); tempItem[newstr_index-1]=tempText[i]; } } if(tempText[i-1]!=':') (*curLoc)+=++i; else (*curLoc)+=i++; /* include the ':' in the return string to identify it as a label */ return tempItem; }
// native sscanf(const data[], const format[], (Float,_}:...); static cell AMX_NATIVE_CALL n_sscanf(AMX * amx, cell * params) { if (g_iTrueMax == 0) { logprintf("sscanf error: System not initialised."); return SSCANF_FAIL_RETURN; } // Friendly note, the most complex set of specifier additions is: // // A<i>(10, 11)[5] // // In that exact order - type, default, size. It's very opposite to how // it's done in code, where you would do the eqivalent to: // // <i>[5] = {10, 11} // // But this method is vastly simpler to parse in this context! Technically // you can, due to legacy support for 'p', do: // // Ai(10, 11)[5] // // But you will get an sscanf warning, and I may remove that ability from // the start - that will mean a new function, but an easy to write one. // In fact the most complex will probably be something like: // // E<ifs[32]s[8]d>(10, 12.3, Hello there, Hi, 42) // // Get the number of parameters passed. We add one as the indexes are out // by one (OBOE - Out By One Error) due to params[0] being the parameter // count, not an actual parameter. const int paramCount = ((int)params[0] / 4) + 1; // Could add a check for only 3 parameters here - I can't think of a time // when you would not want any return values at all, but that doesn't mean // they don't exist - you could just want to check but not save the format. // Update - that is now a possibility with the '{...}' specifiers. if (paramCount < (2 + 1)) { logprintf("sscanf error: Missing required parameters."); return SSCANF_FAIL_RETURN; } //else if (paramCount == (2 + 1)) //{ // Only have an input and a specifier - better hope the whole specifier // is quite (i.e. enclosed in '{...}'). //} // Set up function wide values. // Get and check the main data. // Pointer to the current input data. char * string; STR_PARAM(amx, params[1], string); // Pointer to the current format specifier. char * format; STR_PARAM(amx, params[2], format); // Check for CallRemoteFunction style null strings and correct. if (string[0] == '\1' && string[1] == '\0') { string[0] = '\0'; } // Current parameter to save data to. int paramPos = 3; cell * cptr; InitialiseDelimiter(); // Skip leading space. SkipWhitespace(&string); bool doSave; // Code for the rare cases where the WHOLE format is quiet. if (*format == '{') { ++format; doSave = false; } else { doSave = true; } // Now do the main loop as long as there are variables to store the data in // and input string remaining to get the data from. while (*string && (paramPos < paramCount || !doSave)) { if (!*format) { // End of the format string - if we're here we've got all the // parameters but there is extra string or variables, which may // indicate their code needs fixing, for example: // sscanf(data, "ii", var0, var1, var3, var4); // There is only two format specifiers, but four returns. This may // also be reached if there is too much input data, but that is // considered OK as that is likely a user's fault. if (paramPos < paramCount) { logprintf("sscanf warning: Format specifier does not match parameter count."); } if (!doSave) { // Started a quiet section but never explicitly ended it. logprintf("sscanf warning: Unclosed quiet section."); } return SSCANF_TRUE_RETURN; } else if (IsWhitespace(*format)) { ++format; } else { switch (*format++) { case 'L': DX(bool, L) // FALLTHROUGH case 'l': DOV(bool, L) break; case 'B': DX(int, B) // FALLTHROUGH case 'b': DO(int, B) case 'N': DX(int, N) // FALLTHROUGH case 'n': DO(int, N) case 'C': DX(char, C) // FALLTHROUGH case 'c': DO(char, C) case 'I': case 'D': DX(int, I) // FALLTHROUGH case 'i': case 'd': DO(int, I) case 'H': case 'X': DX(int, H) // FALLTHROUGH case 'h': case 'x': DO(int, H) case 'O': DX(int, O) // FALLTHROUGH case 'o': DO(int, O) case 'F': DXF(double, F) // FALLTHROUGH case 'f': DOF(double, F) case 'G': DXF(double, G) // FALLTHROUGH case 'g': DOF(double, G) case '{': if (doSave) { doSave = false; } else { // Already in a quiet section. logprintf("sscanf warning: Can't have nestled quiet sections."); } continue; case '}': if (doSave) { logprintf("sscanf warning: Not in a quiet section."); } else { doSave = true; } continue; case 'P': logprintf("sscanf warning: You can't have an optional delimiter."); // FALLTHROUGH case 'p': // 'P' doesn't exist. // Theoretically, for compatibility, this should be: // p<delimiter>, but that will break backwards // compatibility with anyone doing "p<" to use '<' as a // delimiter (doesn't matter how rare that may be). Also, // writing deprecation code and both the new and old code // is more trouble than it's worth, and it's slow. // UPDATE: I wrote the "GetSingleType" code for 'a' and // figured out a way to support legacy and new code, while // still maintaining support for the legacy "p<" separator, // so here it is: ResetDelimiter(); AddDelimiter(GetSingleType(&format)); continue; case 'Z': logprintf("sscanf warning: 'Z' doesn't exist - that would be an optional, deprecated optional string!."); // FALLTHROUGH case 'z': logprintf("sscanf warning: 'z' is deprecated, consider using 'S' instead."); // FALLTHROUGH case 'S': if (IsDelimiter(*string)) { char * dest; int length; if (DoSD(&format, &dest, &length)) { // Send the string to PAWN. if (doSave) { amx_GetAddr(amx, params[paramPos++], &cptr); amx_SetString(cptr, dest, 0, 0, length); } } break; } // Implicit "else". SkipDefaultEx(&format); // FALLTHROUGH case 's': { // Get the length. int length = GetLength(&format, false); char * dest; DoS(&string, &dest, length, IsEnd(*format)); // Send the string to PAWN. if (doSave) { amx_GetAddr(amx, params[paramPos++], &cptr); amx_SetString(cptr, dest, 0, 0, length); } } break; case 'U': DX(int, U) // FALLTHROUGH case 'u': DOV(int, U) break; case 'Q': DX(int, Q) // FALLTHROUGH case 'q': DOV(int, Q) break; case 'R': DX(int, R) // FALLTHROUGH case 'r': DOV(int, R) break; case 'A': // We need the default values here. if (doSave) { amx_GetAddr(amx, params[paramPos++], &cptr); if (DoA(&format, &string, cptr, true)) { break; } } else { // Pass a NULL pointer so data isn't saved anywhere. if (DoA(&format, &string, NULL, true)) { break; } } return SSCANF_FAIL_RETURN; case 'a': if (doSave) { amx_GetAddr(amx, params[paramPos++], &cptr); if (DoA(&format, &string, cptr, false)) { break; } } else { // Pass a NULL pointer so data isn't saved anywhere. if (DoA(&format, &string, NULL, false)) { break; } } return SSCANF_FAIL_RETURN; case 'E': // We need the default values here. if (doSave) { amx_GetAddr(amx, params[paramPos++], &cptr); if (DoE(&format, &string, cptr, true)) { break; } } else { // Pass a NULL pointer so data isn't saved anywhere. if (DoE(&format, &string, NULL, true)) { break; } } return SSCANF_FAIL_RETURN; case 'e': if (doSave) { amx_GetAddr(amx, params[paramPos++], &cptr); if (DoE(&format, &string, cptr, false)) { break; } } else { // Pass a NULL pointer so data isn't saved anywhere. if (DoE(&format, &string, NULL, false)) { break; } } return SSCANF_FAIL_RETURN; case 'K': // We need the default values here. if (doSave) { amx_GetAddr(amx, params[paramPos++], &cptr); if (DoK(amx, &format, &string, cptr, true)) { break; } } else { // Pass a NULL pointer so data isn't saved anywhere. if (DoK(amx, &format, &string, NULL, true)) { break; } } return SSCANF_FAIL_RETURN; case 'k': if (doSave) { amx_GetAddr(amx, params[paramPos++], &cptr); if (DoK(amx, &format, &string, cptr, false)) { break; } } else { // Pass a NULL pointer so data isn't saved anywhere. if (DoK(amx, &format, &string, NULL, false)) { break; } } return SSCANF_FAIL_RETURN; case '\'': // Find the end of the literal. { char * str = format, * write = format; bool escape = false; while (!IsEnd(*str) && (escape || *str != '\'')) { if (*str == '\\') { if (escape) { // "\\" - Go back a step to write this // character over the last character (which // just happens to be the same character). --write; } escape = !escape; } else { if (*str == '\'') { // Overwrite the escape character with the // quote character. Must have been // preceeded by a slash or it wouldn't have // got to here in the loop. --write; } escape = false; } // Copy the string over itself to get rid of excess // escape characters. // Not sure if it's faster in the average case to // always do the copy or check if it's needed. // This write is always safe as it makes the string // shorter, so we'll never run out of space. It // will also not overwrite the original string. *write++ = *str++; } if (*str == '\'') { // Correct end. Make a shorter string to search // for. *write = '\0'; // Find the current section of format in string. char * find = strstr(string, format); if (!find) { // Didn't find the string return SSCANF_FAIL_RETURN; } // Found the string. Update the current string // position to the length of the search term // further along from the start of the term. Use // "write" here as we want the escaped string // length. string = find + (write - format); // Move to after the end of the search string. Use // "str" here as we want the unescaped string // length. format = str + 1; } else { logprintf("sscanf warning: Unclosed string literal."); char * find = strstr(string, format); if (!find) { return SSCANF_FAIL_RETURN; } string = find + (write - format); format = str; } } break; case '%': logprintf("sscanf warning: sscanf specifiers do not require '%' before them."); continue; default: logprintf("sscanf warning: Unknown format specifier '%c', skipping.", *(format - 1)); continue; } // Loop cleanup - only skip one spacer so that we can detect // multiple explicit delimiters in a row, for example: // // hi there // // is NOT multiple explicit delimiters in a row (they're // whitespace). This however is: // // hi , , , there // SkipOneSpacer(&string); } } // Temporary to the end of the code. ResetDelimiter(); AddDelimiter(')'); // We don't need code here to handle the case where paramPos was reached, // but the end of the string wasn't - if that's the case there's no // problem as we just ignore excess string data. while (paramPos < paramCount || !doSave) { // Loop through if there's still parameters remaining. if (!*format) { logprintf("sscanf warning: Format specifier does not match parameter count."); if (!doSave) { // Started a quiet section but never explicitly ended it. logprintf("sscanf warning: Unclosed quiet section."); } return SSCANF_TRUE_RETURN; } else if (IsWhitespace(*format)) { ++format; } else { // Do the main switch again. switch (*format++) { case 'L': DE(bool, L) case 'B': DE(int, B) case 'N': DE(int, N) case 'C': DE(char, C) case 'I': case 'D': DE(int, I) case 'H': case 'X': DE(int, H) case 'O': DE(int, O) case 'F': DEF(double, F) case 'G': DEF(double, G) case 'U': DE(int, U) case 'Q': DE(int, Q) case 'R': DE(int, R) case 'A': if (doSave) { amx_GetAddr(amx, params[paramPos++], &cptr); if (DoA(&format, NULL, cptr, true)) { break; } } else { // Pass a NULL pointer so data isn't saved anywhere. // Also pass NULL data so it knows to only collect the // default values. if (DoA(&format, NULL, NULL, true)) { break; } } return SSCANF_FAIL_RETURN; case 'E': if (doSave) { amx_GetAddr(amx, params[paramPos++], &cptr); if (DoE(&format, NULL, cptr, true)) { break; } } else { // Pass a NULL pointer so data isn't saved anywhere. // Also pass NULL data so it knows to only collect the // default values. if (DoE(&format, NULL, NULL, true)) { break; } } return SSCANF_FAIL_RETURN; case 'K': if (doSave) { amx_GetAddr(amx, params[paramPos++], &cptr); if (DoK(amx, &format, NULL, cptr, true)) { break; } } else { // Pass a NULL pointer so data isn't saved anywhere. // Also pass NULL data so it knows to only collect the // default values. if (DoK(amx, &format, NULL, NULL, true)) { break; } } return SSCANF_FAIL_RETURN; case '{': if (doSave) { doSave = false; } else { // Already in a quiet section. logprintf("sscanf warning: Can't have nestled quiet sections."); } break; case '}': if (doSave) { logprintf("sscanf warning: Not in a quiet section."); } else { doSave = true; } break; case 'Z': logprintf("sscanf warning: 'Z' doesn't exist - that would be an optional, deprecated optional string!."); // FALLTHROUGH case 'z': logprintf("sscanf warning: 'z' is deprecated, consider using 'S' instead."); // FALLTHROUGH case 'S': { char * dest; int length; if (DoSD(&format, &dest, &length)) { // Send the string to PAWN. if (doSave) { amx_GetAddr(amx, params[paramPos++], &cptr); amx_SetString(cptr, dest, 0, 0, length); } } } break; case 'P': logprintf("sscanf warning: You can't have an optional delimiter."); // FALLTHROUGH case 'p': // Discard delimiter. This only matters when they have // real inputs, not the default ones used here. GetSingleType(&format); continue; case '\'': // Implicitly optional if the specifiers after it are // optional. { bool escape = false; while (!IsEnd(*format) && (escape || *format != '\'')) { if (*format == '\\') { escape = !escape; } else { escape = false; } ++format; } if (*format == '\'') { ++format; } else { logprintf("sscanf warning: Unclosed string literal."); } } break; // Large block of specifiers all together. case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'k': case 'l': case 'n': case 'o': case 'q': case 'r': case 's': case 'u': case 'x': // These are non optional items, but the input string // didn't include them, so we fail - this is in fact the // most basic definition of a fail (the original)! We // don't need any text warnings here - admittedly we don't // know if the format specifier is well formed (there may // not be enough return variables for example), but it // doesn't matter - the coder should have tested for those // things, and the more important thing is that the user // didn't enter the correct data. return SSCANF_FAIL_RETURN; case '%': logprintf("sscanf warning: sscanf specifiers do not require '%' before them."); break; default: logprintf("sscanf warning: Unknown format specifier '%c', skipping.", *(format - 1)); break; } // Don't need any cleanup here. } } if (*format) { do { if (!IsWhitespace(*format)) { // Only print this warning if the remaining characters are not // spaces - spaces are allowed, and sometimes required, on the // ends of formats (e.g. to stop the final 's' specifier // collecting all remaining characters and only get one word). // We could check that the remaining specifier is a valid one, // but this is only a guide - they shouldn't even have other // characters IN the specifier so it doesn't matter - it will // point to a bug, which is the important thing. if (doSave) { if (*format == '}') { logprintf("sscanf warning: Not in a quiet section."); } else if (*format != '{') { // Fix the bad display bug. logprintf("sscanf warning: Format specifier does not match parameter count."); } // Only display it once. break; } else { if (*format == '}') { doSave = true; } else { logprintf("sscanf warning: Format specifier does not match parameter count."); break; } } } ++format; } while (*format); } if (!doSave) { // Started a quiet section but never explicitly ended it. logprintf("sscanf warning: Unclosed quiet section."); } // No more parameters and no more format specifiers which could be read // from - this is a valid return! return SSCANF_TRUE_RETURN; }
/* * Is this the end of a block? */ static BOOL BlockEnd( LPCLASSDATA lpcd, LPBLOCK lpb, TCHAR *pcText, int nIndex, int nLength ) { /* * End String valid? */ if ( lpb->nEnd || lpb->pszEnd == END_OF_LINE ) { /* * Block terminator at eol? */ if ( lpb->pszEnd == END_OF_LINE ) { if ( nIndex == nLength ) { /* * Match. Is it preceeded by an * escape character? */ if ( nIndex > 0 && Parser->cEscape && pcText[ nIndex - 1 ] == Parser->cEscape ) { /* * Escape character escaped? */ if ( nIndex > 1 && Parser->cEscape && pcText[ nIndex - 2 ] == Parser->cEscape ) /* * Still a match. */ return TRUE; /* * This means no match. */ return FALSE; } /* * OK. */ return TRUE; } } /* * Is this the block terminator? */ else if ( ! ( Parser->bCaseOn ? _tcsncmp : _tcsnicmp )( lpb->pszEnd, &pcText[ nIndex ], lpb->nEnd )) { /* * Match. Is it preceeded by an * escape character? */ if ( nIndex > 0 && Parser->cEscape && pcText[ nIndex - 1 ] == Parser->cEscape ) { /* * Escape character escaped? */ if ( nIndex > 1 && Parser->cEscape && pcText[ nIndex - 2 ] == Parser->cEscape ) /* * Still a match. */ return TRUE; /* * This means no match. */ return FALSE; } /* * Match! */ return TRUE; } } /* * If we do not have a block terminator we * terminate the block at the first white * space/delimiter or at the end of the line. */ else if ( nIndex == nLength ) /* * End the block. */ return TRUE; else if ( nIndex < nLength && ( _istspace( pcText[ nIndex ] ) || IsDelimiter( lpcd, pcText[ nIndex ] ))) /* * End the block. */ return TRUE; return FALSE; }
unsigned int CubeLexer::GetNextLexeme() { int iLem=0; char chBegin; if (m_Sources[m_SourceOffset]=='\0') { //printf("<End>\n"); m_Symbol='0'; m_CurLexeme[0]='\0'; return CUBE_LEXER_LEXEME_TYPE_END; } if (IsSpacer(m_Sources[m_SourceOffset])) { m_Symbol=m_Sources[m_SourceOffset]; m_CurLexeme[0]=m_Sources[m_SourceOffset]; m_CurLexeme[1]='\0'; m_SourceOffset++; //printf("<Spacer>\n"); return CUBE_LEXER_LEXEME_TYPE_SPACER; } if (IsNewLine(m_Sources[m_SourceOffset])) { m_Symbol=m_Sources[m_SourceOffset]; m_CurLexeme[0]=m_Sources[m_SourceOffset]; m_CurLexeme[1]='\0'; m_SourceOffset++; //printf("<New line>\n"); return CUBE_LEXER_LEXEME_TYPE_NEWLINE; } if (IsContainerStart((chBegin=m_Sources[m_SourceOffset]))) { iLem=0; m_CurLexeme[iLem++]=m_Sources[m_SourceOffset]; m_SourceOffset++; while (!IsSourcsEnd()&&!IsContainerEnd(chBegin,m_Sources[m_SourceOffset])) { m_CurLexeme[iLem++]=m_Sources[m_SourceOffset++]; } m_CurLexeme[iLem++]=m_Sources[m_SourceOffset]; m_CurLexeme[iLem]='\0'; m_SourceOffset++; //printf("<Container> %s\n",m_CurLexeme); return CUBE_LEXER_LEXEME_TYPE_CONATINER; } if (IsDelimiter(m_Sources[m_SourceOffset])) { m_Symbol=m_Sources[m_SourceOffset]; m_CurLexeme[0]=m_Sources[m_SourceOffset]; m_CurLexeme[1]='\0'; //printf("<Delimiter> %c\n",m_Sources[m_SourceOffset]); m_SourceOffset++; return CUBE_LEXER_LEXEME_TYPE_DELIMITER; } iLem=0; m_Symbol='\0'; while (!IsSourcsEnd()&&!IsDelimiter(m_Sources[m_SourceOffset])&&!IsSpacer(m_Sources[m_SourceOffset])&&!IsNewLine(m_Sources[m_SourceOffset])&&!IsContainerStart(m_Sources[m_SourceOffset])) { m_CurLexeme[iLem++]=m_Sources[m_SourceOffset++]; } m_CurLexeme[iLem]='\0'; //printf("<Token> %s\n",m_CurLexeme); return CUBE_LEXER_LEXEME_TYPE_TOKEN; }
static void MovePrevWord( LPCLASSDATA lpcd ) { /* * Obtain current caret column and * the line were on. */ int nPos = lpcd->ptCaretPos.x; LPLINE lpLine = GETLINE( lpcd ); /* * Are we at the start of the line? */ if ( nPos == 0 ) { /* * Yes go down one line and to the * end of that line. */ if ( lpcd->ptCaretPos.y > 0 ) { /* * Go up. */ lpcd->ptCaretPos.y--; /* * Put the caret at the end. */ lpcd->ptCaretPos.x = GETLINE( lpcd )->nLength; if ( lpcd->ptCaretPos.x ) /* * Recursivly call ourselves. */ MovePrevWord( lpcd ); } } else { /* * Previous character. */ nPos--; /* * Are we on a white space? */ if ( _istspace( lpLine->pcText[ nPos ] )) { /* * Skip spaces... */ while ( _istspace( lpLine->pcText[ nPos ] ) && nPos ) nPos--; } /* * Start of the line? */ if ( nPos ) { /* * Did we reach a delimiter? */ if ( IsDelimiter( lpcd, lpLine->pcText[ nPos ] )) /* A delimiter? */ { /* * Skip all delimiters. */ while ( IsDelimiter( lpcd, lpLine->pcText[ nPos ] )) { /* * White space? */ if ( _istspace( lpLine->pcText[ nPos ] )) break; /* * Start of the line? */ if ( nPos == 0 ) { /* * Will force the caret at position 0 */ nPos = -1; break; } nPos--; } nPos++; } else { /* * Skip all non delimiters. */ while ( IsDelimiter( lpcd, lpLine->pcText[ nPos ] ) == FALSE ) { /* * White space? */ if ( _istspace( lpLine->pcText[ nPos ] )) break; /* * Start of the line */ if ( nPos == 0 ) { /* * Will force the caret at position 0 */ nPos = -1; break; } nPos--; } nPos++; } } /* * Store position. */ lpcd->ptCaretPos.x = nPos; } /* * Save this position. */ lpcd->nLastColumnPos = GetCaretOffset( lpcd, lpcd->ptCaretPos.x ); /* * Make sure the care is in the view. */ MakeCaretVisible( lpcd ); /* * Update caret position. */ UpdateCaret( lpcd ); }
static VOID DoCommand( PCONSOLE_STATE State, LPSTR line) { CHAR com[MAX_PATH]; /* the first word in the command */ LPSTR cp = com; // LPSTR cstart; LPSTR rest = line; /* pointer to the rest of the command line */ // INT cl; LPCOMMAND cmdptr; DPRINT1("DoCommand: (\'%s\')\n", line); /* Skip over initial white space */ while (isspace(*rest)) rest++; // cstart = rest; /* Anything to do ? */ if (*rest) { /* Copy over 1st word as lower case */ while (!IsDelimiter(*rest)) *cp++ = tolower(*rest++); /* Terminate first word */ *cp = '\0'; /* Skip over whitespace to rest of line */ while (isspace (*rest)) rest++; /* Scan internal command table */ for (cmdptr = Commands; ; cmdptr++) { /* If end of table execute ext cmd */ if (cmdptr->name == NULL) { CONSOLE_ConOutPuts("Unknown command. Enter HELP to get a list of commands."); break; } if (stricmp(com, cmdptr->name) == 0) { cmdptr->func(State, rest); break; } #if 0 /* The following code handles the case of commands like CD which * are recognised even when the command name and parameter are * not space separated. * * e.g dir.. * cd\freda */ /* Get length of command name */ cl = strlen(cmdptr->name); if ((cmdptr->flags & CMD_SPECIAL) && (!strncmp (cmdptr->name, com, cl)) && (strchr("\\.-", *(com + cl)))) { /* OK its one of the specials...*/ /* Call with new rest */ cmdptr->func(State, cstart + cl); break; } #endif } } }
int ParseLine( LPCLASSDATA lpcd, int nInBlock, TCHAR *pcText, int nLength, SYNTAX_COLOR *scColors, int *lpnBlocks, int nNumBlocks, int nLine ) { LPPARSER lpp = Parser; LPKEYHASH lpHash; LPBLOCK lpBlock; COLORREF crText = Parser->crColors[ CARR_TEXT ]; int nIndex = 0, nBlock = 0, nSize, i, nMatchX1 = 0, nMatchX2 = 0; BOOL bContinue = FALSE, bStartOfLine = TRUE, bHasInit = FALSE; int nHyperLength; // Modified by Stephan (2005-06-12) // To allow unquoted paths with space like c:\program files /* * Compute match columns. */ if ( lpcd->ptBracket1.y >= 0 ) nMatchX1 = CaretOffsetLine( lpcd, lpcd->ptBracket1.y, lpcd->ptBracket1.x ); if ( lpcd->ptBracket2.y >= 0 ) nMatchX2 = CaretOffsetLine( lpcd, lpcd->ptBracket2.y, lpcd->ptBracket2.x ); /* * Any text to parse? */ if ( nLength == 0 ) /* * Return the block we are in. */ return nInBlock; /* * Start with a normal text * color block... */ if ( scColors ) { /* * Enough text blocks? */ CHECK_BLOCKS; scColors[ nBlock ].nColumn = nLength; scColors[ nBlock ].crColor = crText; scColors[ nBlock ].crBgColor = CLR_DEFAULT; scColors[ nBlock ].pHash = NULL; scColors[ nBlock ].wFlags = 0; } /* * Parser active? */ if ( lpp == NULL ) { /* * A single text color block. */ *lpnBlocks = 1; return -1; } /* * Are we in a block? */ if ( nInBlock != -1 ) { /* * Get the block. */ lpBlock = ArrayGetAt( lpp->lpaBlocks, nInBlock ); /* * Setup the color. */ if ( scColors ) { /* * Enough text blocks? */ CHECK_BLOCKS; scColors[ nBlock ].nColumn = nLength; scColors[ nBlock ].crColor = lpBlock->crColor; scColors[ nBlock ].crBgColor = lpBlock->crBgColor; scColors[ nBlock ].pHash = NULL; scColors[ nBlock ].wFlags = 0; } /* * End the block with a string? */ if ( lpBlock->nEnd ) { /* * See if the terminator string occures * on the line. */ LPCTSTR pszStr = ( lpp->bCaseOn ? StrStr : StrStrI )( pcText, lpBlock->pszEnd ); /* * Terminator found? */ if( pszStr == NULL ) { /* * Are we parsing hyperlinks? */ if ( Parser->bParseHyperLinks && scColors && lpnBlocks ) { /* * Find all hyperlinks in the line starting * at offset 'nIndex'. */ *lpnBlocks = FindHyperlinksInBlock( lpcd, pcText, nIndex, nLength, 0, nNumBlocks, lpnBlocks, scColors ) + 1; scColors[ *lpnBlocks - 1 ].nColumn = nLength; } else if ( lpnBlocks ) /* * Uses a single block. */ *lpnBlocks = 1; /* * Remain in the text block. */ return nInBlock; } else if ( Parser->bParseHyperLinks && scColors && lpnBlocks ) /* * Find all hyperlinks from offset 'nIndex' * up to the block end marker. */ nBlock = FindHyperlinksInBlock( lpcd, pcText, nIndex, ( int )( pszStr - pcText ), 0, nNumBlocks, lpnBlocks, scColors ); /* * Skip to the index at which * the terminator was found. */ nIndex = ( int )( pszStr - pcText ); } } else { /* * If we are not yet inside a block we determine * if any of the block initiators occure in this * line and, if so, at which offset. */ for ( i = 0; ; i++ ) { /* * Get the block. */ lpBlock = ArrayGetAt( lpp->lpaBlocks, i ); /* * Done? */ if ( lpBlock == NULL ) break; /* * By default this block initiator is not on * this line. */ lpBlock->bInLine = FALSE; /* * Will the initiator fit at all? */ if ( lpBlock->nStart && lpBlock->nStart <= nLength ) { /* * Look up the block initiator on the line. */ LPCTSTR pszStr = ( lpp->bCaseOn ? StrStr : StrStrI )( pcText, lpBlock->pszStart ); /* * Found? */ if ( pszStr != NULL ) { /* * We have a block initializer. */ bHasInit = TRUE; /* * This block initiator is located * on this line. */ lpBlock->bInLine = TRUE; } } } } /* * First we skip the leading blanks... */ while ( _istspace( pcText[ nIndex ] ) && nIndex <= nLength ) nIndex++; /* * Iterate text. */ for ( /*nIndex = 0*/; nIndex <= nLength; nIndex++ ) { /* * Clear continue flag. */ bContinue = FALSE; /* * In a block? */ if ( nInBlock != -1 ) { /* * Get block. */ lpBlock = ArrayGetAt( lpp->lpaBlocks, nInBlock ); /* * Does the block terminate with a string? */ if ( lpBlock->nEnd ) { /* * Does the terminator occure in the text? */ LPCTSTR pszStr = ( lpp->bCaseOn ? StrStr : StrStrI )( &pcText[ nIndex ], lpBlock->pszEnd ); /* * No. Return the block number. */ if ( pszStr == NULL ) { /* * Are we parsing hyperlinks? */ if ( Parser->bParseHyperLinks && scColors && lpnBlocks ) { /* * Find the hyperlinks starting at offset 'nIndex'. */ *lpnBlocks = FindHyperlinksInBlock( lpcd, pcText, nIndex, nLength, nBlock, nNumBlocks, lpnBlocks, scColors ) + 1; scColors[ *lpnBlocks - 1 ].nColumn = nLength; } else if ( lpnBlocks ) /* * Store the block number. */ *lpnBlocks = nBlock + 1; return nInBlock; } else if ( Parser->bParseHyperLinks && scColors && lpnBlocks ) /* * Find all hyperlinks from offset 'nIndex' * up to the block end marker. */ nBlock = FindHyperlinksInBlock( lpcd, pcText, nIndex, ( int )( pszStr - pcText ), nBlock, nNumBlocks, lpnBlocks, scColors ); /* * Skip through to the index at which the * terminator was found. */ nIndex = ( int )( pszStr - pcText ); } /* * Will the terminator fit? */ if ( nLength - nIndex >= lpBlock->nEnd || lpBlock->pszEnd == END_OF_LINE ) { /* * End a block? */ if ( BlockEnd( lpcd, lpBlock, pcText, nIndex, nLength )) { /* * Color array present? */ if ( scColors ) { /* * Enough room? */ CHECK_BLOCKS; /* * Yes. Terminate current color. */ scColors[ nBlock++ ].nColumn = nIndex + lpBlock->nEnd; /* * Start a new color. */ scColors[ nBlock ].nColumn = nLength; scColors[ nBlock ].crColor = crText; scColors[ nBlock ].crBgColor = CLR_DEFAULT; scColors[ nBlock ].pHash = NULL; scColors[ nBlock ].wFlags = 0; } /* * Skip the block terminator. */ if ( lpBlock->pszEnd != END_OF_LINE ) nIndex += lpBlock->nEnd - 1; else nIndex = nLength; /* * No longer in the block. */ nInBlock = -1; /* * Continue parse... */ continue; } } } /* * Keep looking for the terminator if * we are still inside a block. */ if ( nInBlock != -1 ) { if ( scColors && nIndex >= nLength ) scColors[ nBlock ].nColumn = nIndex; continue; } /* * Do we have an initiator? */ if ( bHasInit ) { /* * Look up the block * initiators. */ for ( i = 0; ; i++ ) { /* * Valid block? */ if (( lpBlock = ArrayGetAt( lpp->lpaBlocks, i )) == NULL ) break; /* * Block initiator in this * line? */ if ( ! lpBlock->bInLine ) continue; /* * Block found? */ if ( ! BlockStart( lpcd, lpBlock, pcText, nIndex, nLength, bStartOfLine )) continue; /* * Colors present? */ if ( scColors ) { /* * Enough room? */ CHECK_BLOCKS; /* * Yes. Terminate current color. */ scColors[ nBlock++ ].nColumn = nIndex; /* * Start a new color. */ scColors[ nBlock ].nColumn = nLength; scColors[ nBlock ].crColor = lpBlock->crColor; scColors[ nBlock ].crBgColor = lpBlock->crBgColor; scColors[ nBlock ].pHash = NULL; scColors[ nBlock ].wFlags = 0; } /* * Mark us as being in the block. */ nInBlock = i; /* * Does this block terminate at eol? */ if ( lpBlock->pszEnd == END_OF_LINE ) { /* * Look at the rest of the line * for hyperlinks. */ if ( Parser->bParseHyperLinks && scColors && lpnBlocks ) nBlock = FindHyperlinksInBlock( lpcd, pcText, nIndex, nLength, nBlock, nNumBlocks, lpnBlocks, scColors ); /* * Skip everything except * the last terminator length * plus the escape character. */ nIndex = max( 0, nLength - 2 ); } else /* * Skip the block initiator. */ nIndex += lpBlock->nStart - 1; /* * Break the loop and * continue parsing. */ bContinue = TRUE; break; } } /* * No longer at the start * of the line... */ bStartOfLine = FALSE; /* * Continue? */ if ( bContinue || scColors == NULL ) continue; /* * Skip spaces. */ if ( _istspace( pcText[ nIndex ] )) { /* * Make a new block. */ if ( scColors[ nBlock ].crBgColor != CLR_DEFAULT || scColors[ nBlock ].crColor != crText || scColors[ nBlock ].wFlags ) { /* * Enough room? */ CHECK_BLOCKS; /* * Terminate current color. */ scColors[ nBlock++ ].nColumn = nIndex; /* * Setup new color. */ scColors[ nBlock ].crColor = crText; scColors[ nBlock ].crBgColor = CLR_DEFAULT; scColors[ nBlock ].nColumn = nLength; scColors[ nBlock ].pHash = NULL; scColors[ nBlock ].wFlags = 0; } continue; } if ( Parser->bParseHyperLinks && scColors ) { nHyperLength = IsHyperlink( pcText, nIndex, nLength ); // Modified by Stephan (2005-06-12) if (nHyperLength) { /* * Enough room? */ CHECK_BLOCKS; /* * Yes. Terminate current color. */ scColors[ nBlock++ ].nColumn = nIndex; /* * Start a new color. */ scColors[ nBlock ].nColumn = nLength; scColors[ nBlock ].crColor = Parser->crColors[ CARR_HYPERLINK ]; scColors[ nBlock ].crBgColor = Parser->crColors[ CARR_BACKGROUND_HYPERLINK ]; scColors[ nBlock ].pHash = NULL; scColors[ nBlock ].wFlags = SCF_HYPERLINK; /* * Is it a quoted hyperlink? */ if ( nIndex && (pcText[ nIndex - 1 ] == _T( '"' ) || pcText[ nIndex - 1 ] == _T( '\'' ))) // Modified by Stephan (2005-05-30) { /* * Look up the next quote. */ while ( nIndex < nLength && pcText[ nIndex ] != _T( '"' ) && pcText[ nIndex ] != _T( '\'' )) // Modified by Stephan (2005-05-30) nIndex++; if ( pcText[ nIndex ] == _T( '"' ) || pcText[ nIndex ] == _T( '\'' )) // Modified by Stephan (2005-05-30) nIndex--; } else { /* * Look up the next white space. */ nIndex += nHyperLength; // Modified by Stephan while ( nIndex < nLength && ! _istspace( pcText[ nIndex ] ) && pcText[ nIndex ] != _T('(') && pcText[ nIndex ] != _T(',') && pcText[ nIndex ] != _T(';') && pcText[ nIndex ] != _T(')') && pcText[ nIndex ] != _T('\'')) // Modified by Stephan (2005-05-28) nIndex++; if ( _istspace( pcText[ nIndex ] ) || pcText[ nIndex ] == _T('(') || pcText[ nIndex ] == _T(',') || pcText[ nIndex ] == _T(';') || pcText[ nIndex ] == _T(')') || pcText[ nIndex ] == _T('\'')) // Modified by Stephan (2005-05-28) nIndex--; } continue; } } /* * Delimiter? */ if ( IsDelimiter( lpcd, pcText[ nIndex ] )) { /* * Any change in color? */ if (( scColors[ nBlock ].crColor != Parser->crColors[ CARR_DELIMITER ] ) || ( scColors[ nBlock ].crBgColor != Parser->crColors[ CARR_BACKGROUND_DELIMITER ] ) || ( scColors[ nBlock ].wFlags )) { /* * Enough room? */ CHECK_BLOCKS; /* * Terminate current color. */ scColors[ nBlock++ ].nColumn = nIndex; /* * Setup delimiter color. */ scColors[ nBlock ].crColor = Parser->crColors[ CARR_DELIMITER ]; scColors[ nBlock ].crBgColor = Parser->crColors[ CARR_BACKGROUND_DELIMITER ]; scColors[ nBlock ].nColumn = nLength; scColors[ nBlock ].pHash = NULL; scColors[ nBlock ].wFlags = 0; } /* * Do we have matched brackets? */ if (( nLine == lpcd->ptBracket1.y && nIndex == nMatchX1 ) || ( nLine == lpcd->ptBracket2.y && nIndex == nMatchX2 )) { /* * Enough room? */ CHECK_BLOCKS; /* * Terminate current color. */ scColors[ nBlock++ ].nColumn = nIndex; /* * Setup match color. */ scColors[ nBlock ].crColor = scColors[ nBlock - 1 ].crColor; scColors[ nBlock ].crBgColor = lpp->crColors[ CARR_BRACKET_MATCH ]; scColors[ nBlock ].nColumn = nLength; scColors[ nBlock ].pHash = NULL; scColors[ nBlock ].wFlags = 0; } /* * Continue parsing. */ continue; } else /* * Is it a number? This check is a bit * to simple but it should not pose * any problems... */ if ( _istdigit( pcText[ nIndex ] )) { /* * Color changes? */ if (( scColors[ nBlock ].crColor != Parser->crColors[ CARR_NUMBER ] ) || ( scColors[ nBlock ].crBgColor != Parser->crColors[ CARR_BACKGROUND_NUMBER ] ) || ( scColors[ nBlock ].wFlags )) { /* * Enough room? */ CHECK_BLOCKS; /* * Terminate the current color. */ scColors[ nBlock++ ].nColumn = nIndex; /* * Setup the number colors. */ scColors[ nBlock ].nColumn = nLength; scColors[ nBlock ].crColor = Parser->crColors[ CARR_NUMBER ]; scColors[ nBlock ].crBgColor = Parser->crColors[ CARR_BACKGROUND_NUMBER ]; scColors[ nBlock ].pHash = NULL; scColors[ nBlock ].wFlags = 0; } } else { /* * Do we have bracket matches? */ if (( nLine == lpcd->ptBracket1.y && nIndex == nMatchX1 ) || ( nLine == lpcd->ptBracket2.y && nIndex == nMatchX2 )) { /* * Enough room? */ CHECK_BLOCKS; /* * Terminate current color. */ scColors[ nBlock++ ].nColumn = nIndex; /* * Setup match color. */ scColors[ nBlock ].crColor = crText; scColors[ nBlock ].crBgColor = lpp->crColors[ CARR_BRACKET_MATCH ]; scColors[ nBlock ].nColumn = nLength; scColors[ nBlock ].pHash = NULL; scColors[ nBlock ].wFlags = 0; /* * Continue parsing. */ continue; } else if ( scColors[ nBlock ].crColor != crText || scColors[ nBlock ].crBgColor != CLR_DEFAULT || scColors[ nBlock ].wFlags ) { /* * Enough room? */ CHECK_BLOCKS; /* * Terminate current color. */ scColors[ nBlock++ ].nColumn = nIndex; /* * Setup text color. */ scColors[ nBlock ].crColor = crText; scColors[ nBlock ].crBgColor = CLR_DEFAULT; scColors[ nBlock ].nColumn = nLength; scColors[ nBlock ].pHash = NULL; scColors[ nBlock ].wFlags = 0; } } /* * Count the characters up until * the next space or delimiter. */ nSize = nIndex; while ( nSize < nLength && ! _istspace( pcText[ nSize ] ) && ! IsDelimiter( lpcd, pcText[ nSize ] )) { /* * Do we have bracket matches? */ if (( nLine == lpcd->ptBracket1.y && nSize == nMatchX1 ) || ( nLine == lpcd->ptBracket2.y && nSize == nMatchX2 )) { /* * Enough room? */ CHECK_BLOCKS; /* * Terminate current color. */ scColors[ nBlock++ ].nColumn = nSize; /* * Setup match colors. */ scColors[ nBlock ].crColor = crText; scColors[ nBlock ].crBgColor = lpp->crColors[ CARR_BRACKET_MATCH ]; scColors[ nBlock ].nColumn = nLength; scColors[ nBlock ].pHash = NULL; scColors[ nBlock ].wFlags = 0; /* * Continue parsing. */ break; } nSize++; } /* * Is the previous character a space/delimiter or are * we at the start of the line? */ if ( nIndex == 0 || _istspace( pcText[ nIndex - 1 ] ) || IsDelimiter( lpcd, pcText[ nIndex - 1 ] )) { /* * Is it a keyword */ if (( lpHash = IsKeyword( lpcd, &pcText[ nIndex ], nSize - nIndex )) != NULL ) { /* * Color changes? * NOTE: Removed to accomodate case-fixing. */ /*if ( scColors[ nBlock ].crColor != lpHash->crColor )*/ { /* * Enough room? */ CHECK_BLOCKS; /* * Terminate the current color. */ scColors[ nBlock++ ].nColumn = nIndex; /* * Setup the keyword color and the hash. We use the hash * when a text line is edited to fix the casing when * case-fixing is turned on. */ scColors[ nBlock ].nColumn = nLength; scColors[ nBlock ].crColor = lpHash->crColor; scColors[ nBlock ].crBgColor = lpHash->crBkColor; scColors[ nBlock ].pHash = lpHash; scColors[ nBlock ].wFlags = 0; } } } /* * Are we at the end? */ if ( nSize >= nLength ) break; /* * Adjust the index. */ nIndex = nSize - 1; } /* * Store the number of syntax * color block that are valid. */ if ( lpnBlocks ) *lpnBlocks = nBlock + 1; return nInBlock; }
bool WLex::IsSpecial(int ch) const { return IsDelimiter(ch) || IsEscape(ch) || ch == '\n'; }