void CxxPreProcessorScanner::Parse(CxxPreProcessor* pp) throw(CxxLexerException) { CxxLexerToken token; bool searchingForBranch = false; CxxPreProcessorToken::Map_t& ppTable = pp->GetTokens(); while(::LexerNext(m_scanner, token)) { // Pre Processor state switch(token.type) { case T_PP_INCLUDE_FILENAME: { // we found an include statement, recurse into it wxFileName include; if(pp->ExpandInclude(m_filename, token.text, include)) { CxxPreProcessorScanner* scanner = new CxxPreProcessorScanner(include, pp->GetOptions()); try { scanner->Parse(pp); } catch(CxxLexerException& e) { // catch the exception CL_DEBUG("Exception caught: %s\n", e.message); } // make sure we always delete the scanner wxDELETE(scanner); DEBUGMSG("<== Resuming parser on file: %s\n", m_filename.GetFullPath()); } break; } case T_PP_IFDEF: { searchingForBranch = true; // read the identifier ReadUntilMatch(T_PP_IDENTIFIER, token); if(IsTokenExists(ppTable, token)) { DEBUGMSG("=> ifdef condition is TRUE (line: %d)\n", token.lineNumber); searchingForBranch = false; // condition is true Parse(pp); } else { DEBUGMSG("=> ifdef condition is FALSE (line: %d)\n", token.lineNumber); // skip until we find the next: // else, elif, endif (but do not consume these tokens) if(!ConsumeCurrentBranch()) return; } break; } case T_PP_IFNDEF: { searchingForBranch = true; // read the identifier ReadUntilMatch(T_PP_IDENTIFIER, token); if(!IsTokenExists(ppTable, token)) { DEBUGMSG("=> ifndef condition is TRUE (line: %d)\n", token.lineNumber); searchingForBranch = false; // condition is true Parse(pp); } else { DEBUGMSG("=> ifndef condition is FALSE (line: %d)\n", token.lineNumber); // skip until we find the next: // else, elif, endif (but do not consume these tokens) if(!ConsumeCurrentBranch()) return; } break; } case T_PP_IF: searchingForBranch = true; case T_PP_ELIF: { if(searchingForBranch) { // We expect a condition if(!CheckIf(ppTable)) { DEBUGMSG("=> if condition is FALSE (line: %d)\n", token.lineNumber); // skip until we find the next: // else, elif, endif (but do not consume these tokens) if(!ConsumeCurrentBranch()) return; } else { DEBUGMSG("=> if condition is TRUE (line: %d)\n", token.lineNumber); searchingForBranch = false; // condition is true Parse(pp); } } else { ConsumeBlock(); return; } break; } case T_PP_ELSE: { if(searchingForBranch) { // if we reached an else, it means that we could not match // a if/elif/ifdef condition until now - enter it Parse(pp); searchingForBranch = false; } else { // we already found the branch for the current block // this means that the 'else' is a stop sign for us ConsumeBlock(); return; } break; } case T_PP_ENDIF: { return; } case T_PP_DEFINE: { if(!::LexerNext(m_scanner, token) || token.type != T_PP_IDENTIFIER) { // Recover wxString dummy; GetRestOfPPLine(dummy); break; } wxString macroName = token.text; wxString macroValue; // Optionally get the value GetRestOfPPLine(macroValue, m_options & kLexerOpt_CollectMacroValueNumbers); CxxPreProcessorToken pp; pp.name = macroName; pp.value = macroValue; // mark this token for deletion when the entire TU parsing is done pp.deleteOnExit = (m_options & kLexerOpt_DontCollectMacrosDefinedInThisFile); DEBUGMSG("=> Adding macro: %s=%s (line %d)\n", pp.name, pp.value, token.lineNumber); ppTable.insert(std::make_pair(pp.name, pp)); break; } } } }
void CElement::ExecInstructions(const CArray<CInstruction *> *papInstructions, const CParameters *paParameters, bool *pReturned, int *pReturnValue) { *pReturned = false; for(CArray<CInstruction *>::CIterator i = papInstructions->GetIterator(); i.Exists(); i.Next()) { if(m_Removed) break; CInstruction *pBaseInstr = i.Get(); m_pDatabase->SetCurrentInstruction(pBaseInstr->m_LineCount, pBaseInstr->m_Filename); if(pBaseInstr->m_Type == INSTRUCTION_TYPE_SET_ATTRIBUTE) { CSetAttributeInstruction *pInstr = (CSetAttributeInstruction *)pBaseInstr; CAttribute *pAttribute = FindAttribute(pInstr->m_AttributeName); if(!pAttribute) { printf("error: unknown attribute '%s'\n", pInstr->m_AttributeName.GetString()); m_pDatabase->PrintCallstack(); continue; } if(pAttribute->m_Const && pAttribute->m_Defined) { printf("error: attribute const '%s' is already defined\n", pAttribute->m_pName); m_pDatabase->PrintCallstack(); } else { pAttribute->m_Value = ComputeValue(pInstr->m_Value, paParameters); pAttribute->m_Defined = true; #ifdef SPB_DEBUG printf("success: attribute '%s' set to %d\n", pAttribute->m_pName, pAttribute->m_Value); #endif } } else if(pBaseInstr->m_Type == INSTRUCTION_TYPE_RETURN) { CReturnInstruction *pInstr = (CReturnInstruction *)pBaseInstr; *pReturned = true; *pReturnValue = ComputeValue(pInstr->m_Value, paParameters); #ifdef SPB_DEBUG printf("success: returned %d\n", *pReturnValue); #endif return; } else if(pBaseInstr->m_Type == INSTRUCTION_TYPE_IF) { CIfInstruction *pInstr = (CIfInstruction *)pBaseInstr; bool True = CheckIf(&pInstr->m_IfData, paParameters); if(True) ExecInstructions(&pInstr->m_IfData.m_Instructions.m_apList, paParameters, pReturned, pReturnValue); else { for(CArray<CIfData>::CIterator i = pInstr->m_aElsifDatas.GetIterator(); i.Exists(); i.Next()) { CIfData *pElsifData = &i.Get(); m_pDatabase->SetCurrentInstruction(pElsifData->m_LineCount, pBaseInstr->m_Filename); True = CheckIf(pElsifData, paParameters); if(True) { ExecInstructions(&pElsifData->m_Instructions.m_apList, paParameters, pReturned, pReturnValue); break; } } if(!True) ExecInstructions(&pInstr->m_InstructionsElse.m_apList, paParameters, pReturned, pReturnValue); } if(*pReturned) return; } else if(pBaseInstr->m_Type == INSTRUCTION_TYPE_FROM) { CFromInstruction *pInstr = (CFromInstruction *)pBaseInstr; int StartVal = ComputeValue(pInstr->m_StartValue, paParameters); int EndVal = ComputeValue(pInstr->m_EndValue, paParameters); #ifdef SPB_DEBUG printf("success: from %d to %d (reverse %d)\n", StartVal, EndVal, pInstr->m_Reverse); #endif CParameters aFromParameters; paParameters->GetCopy(&aFromParameters); int *pNewParameter = &aFromParameters.Add(); if(pInstr->m_Reverse) { for(int v = StartVal; v >= EndVal; v--) { *pNewParameter = v; ExecInstructions(&pInstr->m_Instructions.m_apList, &aFromParameters, pReturned, pReturnValue); if(*pReturned) return; } } else { for(int v = StartVal; v <= EndVal; v++) { *pNewParameter = v; ExecInstructions(&pInstr->m_Instructions.m_apList, &aFromParameters, pReturned, pReturnValue); if(*pReturned) return; } } } else if(pBaseInstr->m_Type == INSTRUCTION_TYPE_CALL_FUNCTION) { CCallFunctionInstruction *pInstr = (CCallFunctionInstruction *)pBaseInstr; CParameters aFunctionParameters; for(CArray<CExpression>::CIterator p = pInstr->m_aFunctionParameters.GetIterator(); p.Exists(); p.Next()) aFunctionParameters.Add(ComputeValue(p.Get(), paParameters)); if(pInstr->m_This) CallFunction(pInstr->m_FunctionName, &aFunctionParameters); else if(pInstr->m_Super) CallFunction(pInstr->m_FunctionName, &aFunctionParameters, true, pInstr->m_Superclass); else { CParameters aSearchParameters; for(CArray<CExpression>::CIterator p = pInstr->m_aSearchParameters.GetIterator(); p.Exists(); p.Next()) aSearchParameters.Add(ComputeValue(p.Get(), paParameters)); CArray<CElement *> apElements; m_pDatabase->SearchElements(pInstr->m_ElementType, pInstr->m_ElementModelName, pInstr->m_SearchFunction, &aSearchParameters, &apElements); for(CArray<CElement *>::CIterator e = apElements.GetIterator(); e.Exists(); e.Next()) { if(!e.Get()->m_Removed) e.Get()->CallFunction(pInstr->m_FunctionName, &aFunctionParameters); } } } else if(pBaseInstr->m_Type == INSTRUCTION_TYPE_REMOVE) { CRemoveInstruction *pInstr = (CRemoveInstruction *)pBaseInstr; if(pInstr->m_This) m_pDatabase->RemoveElement(this); else { CParameters aSearchParameters; for(CArray<CExpression>::CIterator p = pInstr->m_aSearchParameters.GetIterator(); p.Exists(); p.Next()) aSearchParameters.Add(ComputeValue(p.Get(), paParameters)); CArray<CElement *> apElements; m_pDatabase->SearchElements(pInstr->m_ElementType, pInstr->m_ElementModelName, pInstr->m_SearchFunction, &aSearchParameters, &apElements); bool DeleteThis = false; for(CArray<CElement *>::CIterator e = apElements.GetIterator(); e.Exists(); e.Next()) { CElement *pElement = e.Get(); if(pElement->m_Removed) continue; if(pElement == this) DeleteThis = true; else m_pDatabase->RemoveElement(pElement); } if(DeleteThis) m_pDatabase->RemoveElement(this); } } else if(pBaseInstr->m_Type == INSTRUCTION_TYPE_ADD) { CAddInstruction *pInstr = (CAddInstruction *)pBaseInstr; CParameters aAddParameters; for(CArray<CExpression>::CIterator p = pInstr->m_aAddParameters.GetIterator(); p.Exists(); p.Next()) aAddParameters.Add(ComputeValue(p.Get(), paParameters)); m_pDatabase->AddElement(pInstr->m_ElementType, pInstr->m_ElementModelName, &aAddParameters); } else if(pBaseInstr->m_Type == INSTRUCTION_TYPE_CALL_SYS) { CCallSysInstruction *pInstr = (CCallSysInstruction *)pBaseInstr; CParameters aFunctionParameters; for(CArray<CExpression>::CIterator p = pInstr->m_aFunctionParameters.GetIterator(); p.Exists(); p.Next()) aFunctionParameters.Add(ComputeValue(p.Get(), paParameters)); m_pDatabase->CallSysFunction(pInstr->m_FunctionName, &aFunctionParameters); } } }