//Replace the unparsing of expanded macro calls with the actual macro call wherever possible void unparseMacroCalls(SgNode* searchTree) { //Traverse AST to find all macro calls and the nodes they are attached to findPreprocInfo findPre; findPre.traverse(searchTree, preorder); std::vector< std::pair<SgNode*, PreprocessingInfo*> >& wherePreprocIsAttached = findPre.wherePreprocIsAttached; //Replace expanded macro calls with actual macro call from pre-cpp wherever possible for( std::vector< std::pair<SgNode*, PreprocessingInfo*> >::iterator iItr = wherePreprocIsAttached.begin(); iItr != wherePreprocIsAttached.end(); ++iItr) { SgStatement* currentNode = isSgStatement( (*iItr).first ); PreprocessingInfo* curPreproc = (*iItr).second; ROSE_ASSERT(currentNode != NULL); std::vector<SgNode*> matchingSubTree; if ( matchMacroToSubtrees(currentNode->get_scope(), curPreproc, matchingSubTree) ) { for(unsigned int i = 0; i < matchingSubTree.size(); i++) { SgLocatedNode* macroNode = isSgLocatedNode(matchingSubTree[i]); ROSE_ASSERT(macroNode != NULL); std::string replacementString = ( i ==0 ? curPreproc->getString() : "" ); if( isSgExpression(macroNode) == NULL ) { #ifndef USE_ROSE #ifndef ROSE_SKIP_COMPILATION_OF_WAVE // If we are using ROSE to compile ROSE source code then the Wave support is not present. PreprocessingInfo::rose_macro_call* macroCall = curPreproc->get_macro_call(); if(macroCall->expanded_macro.size() > 0 && boost::wave::token_id(macroCall->expanded_macro.back()) != boost::wave::T_COLON) replacementString +=";"; #endif #endif } std::cout << "Doing line replacement " << macroNode->unparseToString() << " with " << replacementString << std::endl; #if 0 std::string pos; curPreproc->display(pos); std::cout << macroNode->class_name() << " "<< pos << std::endl; #endif macroNode->addToAttachedPreprocessingInfo(new PreprocessingInfo(PreprocessingInfo::LineReplacement, replacementString,macroNode->get_file_info()->get_filenameString(),1,1,1,PreprocessingInfo::before)); } }; } };
void mlmTransform::insertHeaders(SgProject* project) { Rose_STL_Container<SgNode*> globalList = NodeQuery::querySubTree (project,V_SgGlobal); for(Rose_STL_Container<SgNode*>::iterator i = globalList.begin(); i != globalList.end(); i++) { SgGlobal* global = isSgGlobal(*i); ROSE_ASSERT(global); PreprocessingInfo* headerInfo = insertHeader("mlm.h",PreprocessingInfo::after,false,global); headerInfo->set_file_info(global->get_file_info()); } return; //assume always successful currently }
virtual void visit(SgNode *n) { SgDeclarationStatement *ds = isSgDeclarationStatement(n); if (!Doxygen::isRecognizedDeclaration(ds)) return; list<DoxygenComment *> *commentList = Doxygen::getCommentList(ds); if (commentList->size() > 1) { for (list<DoxygenComment *>::iterator i = commentList->begin(); i != commentList->end(); ++i) { PreprocessingInfo *pi = (*i)->originalComment; cout << pi->get_file_info()->get_filenameString() << ":" << pi->get_file_info()->get_line() << ": warning: multiple documentation entries for " << getQualifiedPrototype(ds) << endl; } } }
virtual void visit(SgNode *n) { SgDeclarationStatement *st = isSgDeclarationStatement(n); if (!st) { return; } if (!isRecognizedDeclaration(st)) { return; } string proto = getProtoName(st); SgDeclarationStatement *dxSt = getDoxygenAttachedDeclaration(st); if ((*symTab)[proto].count(dxSt) == 0) { DoxygenCommentListAttribute *attr = new DoxygenCommentListAttribute(); // King84 (2010.08.03) : This seems to be called with the same node multiple times. // From what I can tell, this is because a single function has been documented multiple times. // At the moment this function is AssemblerX86::AssemblerX86() from src/frontend/Disassemblers/AssemblerX86.h // For now, we will print out a warning and use the new documentation (instead of addNewAttribute we use setAttribute). if (dxSt->attributeExists("DoxygenCommentList")) { std::cerr << "Warning: Multiple Doxygen comments found for function " << dxSt->get_mangled_name().getString() << " at file " << dxSt->get_file_info()->get_filenameString() << ":" << dxSt->get_file_info()->get_line() << "," << dxSt->get_file_info()->get_col() << ". Picking the last." << std::endl; } dxSt->setAttribute("DoxygenCommentList", attr); // dxSt->addNewAttribute("DoxygenCommentList", attr); (*symTab)[proto][dxSt] = &(attr->commentList); } list<DoxygenComment *> *commentList = (*symTab)[proto][dxSt]; AttachedPreprocessingInfoType *info = st->getAttachedPreprocessingInfo(); if (info) { for (AttachedPreprocessingInfoType::iterator i = info->begin(); i != info->end(); ++i) { PreprocessingInfo *pi = *i; if (pi->getRelativePosition() == PreprocessingInfo::before && DoxygenComment::isDoxygenComment(pi)) { commentList->push_back(new DoxygenComment(st, pi)); } } } }
void print_out_all_macros(std::ostream& outStream, SgProject* project){ typedef std::map<std::string, std::vector<PreprocessingInfo*>* > attached_attr_type; typedef std::vector<PreprocessingInfo*> rose_attr_list_type; for( std::map<std::string,ROSEAttributesList* > ::iterator it_files = mapFilenameToAttributes.begin(); it_files != mapFilenameToAttributes.end(); ++it_files){ std::string filename = it_files->first; if(SgProject::get_verbose() >= 1){ std::cout << "Filename to check " << filename << std::endl; } //If the filename is in the exclude path list skip it SgStringList & excludePathList = project->get_excludePathList(); bool excludePath = false; for( SgStringList::iterator iItr = excludePathList.begin(); iItr != excludePathList.end(); iItr++) if( filename.find(*iItr) != std::string::npos ) { excludePath = true; break; } if(excludePath == true) continue; filename = StringUtility::stripPathFromFileName(filename); if(filename.size()<1 || (filename.size()==1 && ( filename.substr(0,1) == ".") )) continue; for (rose_attr_list_type::iterator it_1 = it_files->second->getList().begin(); it_1 != it_files->second->getList().end(); ++it_1) { PreprocessingInfo *currentInfo = *it_1; ROSE_ASSERT(currentInfo != NULL); PreprocessingInfo::DirectiveType typeOfDirective = currentInfo->getTypeOfDirective (); std::string macroDefFilename = currentInfo->getString(); macroDefFilename = StringUtility::stripPathFromFileName(macroDefFilename); // Here attach include directives to a separate graph switch(typeOfDirective) { case PreprocessingInfo::CpreprocessorUnknownDeclaration: case PreprocessingInfo::C_StyleComment: case PreprocessingInfo::CplusplusStyleComment: case PreprocessingInfo::FortranStyleComment: case PreprocessingInfo::CpreprocessorBlankLine: case PreprocessingInfo::CpreprocessorIncludeDeclaration: case PreprocessingInfo::CpreprocessorIncludeNextDeclaration: case PreprocessingInfo::CpreprocessorDefineDeclaration: case PreprocessingInfo::CpreprocessorUndefDeclaration: case PreprocessingInfo::CpreprocessorIfdefDeclaration: case PreprocessingInfo::CpreprocessorIfndefDeclaration: case PreprocessingInfo::CpreprocessorIfDeclaration: case PreprocessingInfo::CpreprocessorDeadIfDeclaration: case PreprocessingInfo::CpreprocessorElseDeclaration: case PreprocessingInfo::CpreprocessorElifDeclaration: case PreprocessingInfo::CpreprocessorEndifDeclaration: case PreprocessingInfo::CpreprocessorLineDeclaration: case PreprocessingInfo::CpreprocessorErrorDeclaration: case PreprocessingInfo::CpreprocessorWarningDeclaration: case PreprocessingInfo::CpreprocessorEmptyDeclaration: case PreprocessingInfo::CSkippedToken: case PreprocessingInfo::CMacroCall: { outStream << "PreprocessingInfo " << filename << " line " << currentInfo->getLineNumber() << " col " << currentInfo->getColumnNumber() << " : " << currentInfo->getString(); if(typeOfDirective == PreprocessingInfo::CMacroCall) outStream << " expanded: " << currentInfo->get_macro_call()->get_expanded_string(); outStream << std::endl; break; } default: break; } } } };
//build the map of macro defs to macro calls to that def //using the global map of filenames to PreprocessingInfo's. macro_def_call_type allCallsToMacro2( std::list<std::string> internalIncludePathList ){ std::cout << "allCallsToMacro" << std::endl; // Build the traversal object and call "traverse" member function macro_def_call_type mapOfDefsToCalls; typedef std::map<std::string, std::vector<PreprocessingInfo*>* > attached_attr_type; typedef std::vector<PreprocessingInfo*> rose_attr_list_type; std::cout << "The size:" << mapFilenameToAttributes.size() << std::endl; for( std::map<std::string,ROSEAttributesList* > ::iterator it_files = mapFilenameToAttributes.begin(); it_files != mapFilenameToAttributes.end(); ++it_files){ std::string filename = it_files->first; if(SgProject::get_verbose() >= 1){ std::cout << "Filename to check " << filename << std::endl; } for (rose_attr_list_type::iterator it_1 = it_files->second->getList().begin(); it_1 != it_files->second->getList().end(); ++it_1) { PreprocessingInfo *currentInfo = *it_1; PreprocessingInfo::DirectiveType typeOfDirective = currentInfo->getTypeOfDirective (); // Here attach include directives to a separate graph if (typeOfDirective == PreprocessingInfo::CMacroCall) { PreprocessingInfo::rose_macro_call* macro_call = currentInfo->get_macro_call(); const token_container* tok_cont = currentInfo->get_token_stream(); //Handle macro expansions which maps to tokens without a located node //Examples: types bool streamPossiblyMapsToAST = true; //Ignore macro calls in system header files or rose_edg_macros_and_functions_required_for_gnu std::string filenameMacroCall = currentInfo->get_file_info()->get_filenameString(); if(filenameMacroCall.find("rose_edg_required_macros_and_functions.h") != std::string::npos) streamPossiblyMapsToAST = false; for(std::list<std::string>::iterator it_beg = internalIncludePathList.begin(); it_beg != internalIncludePathList.end(); ++it_beg){ //std::cout << filenameMacroCall << std::endl; if(filenameMacroCall.find(*it_beg) != std::string::npos) streamPossiblyMapsToAST = false; } if(streamPossiblyMapsToAST == true){ streamPossiblyMapsToAST = false; for(token_container::const_iterator it_tok = macro_call->expanded_macro.begin(); it_tok != macro_call->expanded_macro.end(); ++it_tok){ if( tokenHasNoCorrespondingASTLocatedConstruct(*it_tok) == false ){ streamPossiblyMapsToAST = true; if(SgProject::get_verbose() >= 1) std::cout << it_tok->get_value() << " maps to AST" << std::endl; break; }else{ using namespace boost::wave; if(SgProject::get_verbose() >= 1) std::cout << get_token_name(token_id(*it_tok)) << " do not match to AST" << std::endl; } }; } if( streamPossiblyMapsToAST == true ){ PreprocessingInfo* macro_def = macro_call->macro_def; /*if(SgProject::get_verbose() >= 1)*/{ std::cout << "macro def: " << macro_def->get_file_info()->get_filenameString() << " l" << macro_def->get_file_info()->get_line() << " c" << macro_def->get_file_info()->get_col() << std::endl; std::cout << macro_def->getString() << std::endl; std::cout << "macro call: " << currentInfo->get_file_info()->get_filenameString() << " l" << currentInfo->get_file_info()->get_line() << " c" << currentInfo->get_file_info()->get_col() << std::endl; std::cout << currentInfo->getString() << std::endl; token_list_container& macroDefinition = macro_def->get_macro_def()->definition; for(token_list_container::iterator expMacroIt = macroDefinition.begin(); expMacroIt != macroDefinition.end(); ++expMacroIt){ std::cout << "\nPosition:" << expMacroIt->get_value() << " l" << expMacroIt->get_position().get_line() << " c" << expMacroIt->get_position().get_column() << std::endl; } } ROSE_ASSERT(macro_def!=NULL); macro_def_call_type::iterator current_def = mapOfDefsToCalls.find(macro_def); if( current_def != mapOfDefsToCalls.end() ){ current_def->second.push_back(currentInfo); }else{ mapOfDefsToCalls[macro_def] = ( std::list<PreprocessingInfo*>()/*.push_back(currentInfo)*/ ); mapOfDefsToCalls.find(macro_def)->second.push_back(currentInfo); } } }else if (typeOfDirective == PreprocessingInfo::CpreprocessorDefineDeclaration) { //Macro defs with no macro calls if( mapOfDefsToCalls.find(currentInfo) == mapOfDefsToCalls.end() ){ //std::cout << "Adding def" << currentInfo << std::endl; mapOfDefsToCalls[currentInfo] = ( std::list<PreprocessingInfo*>()); token_list_container& macroDefinition = currentInfo->get_macro_def()->definition; for(token_list_container::iterator expMacroIt = macroDefinition.begin(); expMacroIt != macroDefinition.end(); ++expMacroIt){ std::cout << "\nPosition1:" << expMacroIt->get_value() << " l" << expMacroIt->get_position().get_line() << " c" << expMacroIt->get_position().get_column() << std::endl; } } } } } std::cout << "The mapOfDefsToCalls SIZE " << mapOfDefsToCalls.size() << std::endl; return mapOfDefsToCalls; };
void f2cTraversal::visit(SgNode* n) { /* 1. The following switch statement search for the Fortran-specific AST nodes and transform them into C nodes. 2. The new C nodes are created first. Attributes and details are then copied from original Fortran nodes. After the copy, original Fortran nodes are deleted. */ switch(n->variantT()) { case V_SgSourceFile: { SgFile* fileNode = isSgFile(n); translateFileName(fileNode); break; } case V_SgProgramHeaderStatement: { SgProgramHeaderStatement* ProgramHeaderStatement = isSgProgramHeaderStatement(n); ROSE_ASSERT(ProgramHeaderStatement); translateProgramHeaderStatement(ProgramHeaderStatement); // Deep delete the original Fortran SgProgramHeaderStatement removeList.push_back(ProgramHeaderStatement); break; } case V_SgProcedureHeaderStatement: { SgProcedureHeaderStatement* procedureHeaderStatement = isSgProcedureHeaderStatement(n); ROSE_ASSERT(procedureHeaderStatement); translateProcedureHeaderStatement(procedureHeaderStatement); // Deep delete the original Fortran procedureHeaderStatement. removeList.push_back(procedureHeaderStatement); break; } case V_SgFortranDo: { SgFortranDo* fortranDo = isSgFortranDo(n); ROSE_ASSERT(fortranDo); translateFortranDoLoop(fortranDo); // Deep delete the original fortranDo . removeList.push_back(fortranDo); break; } case V_SgFunctionCallExp: { SgFunctionCallExp* functionCallExp = isSgFunctionCallExp(n); ROSE_ASSERT(functionCallExp); translateImplicitFunctionCallExp(functionCallExp); break; } case V_SgExponentiationOp: { SgExponentiationOp* expOp = isSgExponentiationOp(n); ROSE_ASSERT(expOp); translateExponentiationOp(expOp); break; } case V_SgFloatVal: { SgFloatVal* floatVal = isSgFloatVal(n); ROSE_ASSERT(floatVal); translateDoubleVal(floatVal); break; } case V_SgCommonBlock: { SgCommonBlock* commonBlock = isSgCommonBlock(n); ROSE_ASSERT(commonBlock); //translateCommonBlock(commonBlock); break; } case V_SgGlobal: { SgGlobal* global = isSgGlobal(n); ROSE_ASSERT(global); removeFortranMaxMinFunction(global); PreprocessingInfo* defMaxInfo = new PreprocessingInfo(PreprocessingInfo::CpreprocessorDefineDeclaration, "#define max(a,b) (((a)>(b))?(a):(b))", "Transformation generated", 0, 0, 0, PreprocessingInfo::before); defMaxInfo->set_file_info(global->get_file_info()); global->addToAttachedPreprocessingInfo(defMaxInfo,PreprocessingInfo::before); PreprocessingInfo* defMinInfo = new PreprocessingInfo(PreprocessingInfo::CpreprocessorDefineDeclaration, "#define min(a,b) (((a)<(b))?(a):(b))", "Transformation generated", 0, 0, 0, PreprocessingInfo::before); defMinInfo->set_file_info(global->get_file_info()); global->addToAttachedPreprocessingInfo(defMinInfo,PreprocessingInfo::before); break; } default: break; } }