From 80361515b2e2042c790c82e22173c11c2372a302 Mon Sep 17 00:00:00 2001 From: = Date: Sun, 1 Nov 2015 16:02:51 -0500 Subject: [PATCH] Finished integrated a rough API into srcSlice and began writing a test for it. Doesn't test anything yet but... soon. --- CMakeLists.txt | 3 +- src/CMakeLists.txt | 9 +- src/cpp/output.cpp | 189 ++++++++++++++++++++++++++++ src/cpp/srcSlice.cpp | 217 ++++---------------------------- src/cpp/srcSliceHandler.cpp | 14 +-- src/headers/SliceProfile.hpp | 163 +----------------------- src/headers/Utility.hpp | 30 ++++- src/headers/srcSlice.hpp | 141 +++++++++++++++++++++ src/headers/srcSliceHandler.hpp | 36 +++--- src/tests/TestFlatSlice.cpp | 93 ++++++++++++++ src/tests/TestFlatSlice.hpp | 24 ++++ 11 files changed, 537 insertions(+), 382 deletions(-) create mode 100644 src/cpp/output.cpp create mode 100644 src/headers/srcSlice.hpp create mode 100644 src/tests/TestFlatSlice.cpp create mode 100644 src/tests/TestFlatSlice.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 910b166..61f5bf0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,8 @@ cmake_minimum_required(VERSION 2.8) project(srcSlice) - +set(CMAKE_CXX_COMPILER "c++") +set(CMAKE_CXX_FLAGS "-std=c++0x -O3") enable_testing() list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMake) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6d5dadd..a284b0a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,13 @@ file(GLOB SRCSLICEHANDLER_SOURCE cpp/*.cpp) +file(GLOB SRCSLICEHANDLER_SOURCE2 cpp/srcSlice*.cpp) file(GLOB SRCSLICEHANDLER_INCLUDE headers/*.hpp) +file(GLOB SRCSLICETEST_SOURCE tests/*.cpp) +file(GLOB SRCSLICETEST_INCLUDE tests/*.hpp) + +link_directories(/usr/local/lib/) add_executable(srcSlice ${SRCSLICEHANDLER_SOURCE} ${SRCSLICEHANDLER_INCLUDE}) +add_executable(srcslicetest ${SRCSLICEHANDLER_SOURCE2} ${SRCSLICEHANDLER_INCLUDE} ${SRCSLICETEST_SOURCE} ${SRCSLICETEST_INCLUDE}) -target_link_libraries(srcSlice srcsax ${LIBXML2_LIBRARIES}) \ No newline at end of file +target_link_libraries(srcSlice srcsax ${LIBXML2_LIBRARIES}) +target_link_libraries(srcslicetest srcsax srcml ${LIBXML2_LIBRARIES}) \ No newline at end of file diff --git a/src/cpp/output.cpp b/src/cpp/output.cpp new file mode 100644 index 0000000..fd6de8b --- /dev/null +++ b/src/cpp/output.cpp @@ -0,0 +1,189 @@ +/** + * @file srcSlice.cpp + * + * @copyright Copyright (C) 2013-2014 SDML (www.srcML.org) + * + * The srcML Toolkit is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The srcML Toolkit is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the srcML Toolkit; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +void TestSlice2(const VarMap& mp){ + for(VarMap::const_iterator vmIt = mp.begin(); vmIt != mp.end(); ++vmIt){ + std::cerr<<"-------------------------"<first<second.slines){ + std::cerr<second.dvars){ + std::cerr<second.aliases){ + std::cerr<second.cfunctions){ + std::cerr<first<second.begin(); fvmIt != ffvmIt->second.end(); ++fvmIt){ + std::cerr<first<functionTable.find(fvmIt->first)->second<second.begin(); vmIt != fvmIt->second.end(); ++vmIt){ + std::cerr<<"-------------------------"<first<second.slines){ + std::cerr<second.dvars){ + std::cerr<second.aliases){ + std::cerr<second.cfunctions){ + std::cerr<second.def){ + std::cerr<second.use){ + std::cerr<first); + //if(fileNameIt != handler.dictionary.fileTable.end()) + for(FunctionVarMap::const_iterator fvmIt = ffvmIt->second.begin(); fvmIt != ffvmIt->second.end(); ++fvmIt){ + //auto functionNameIt = handler.dictionary.functionTable.find(); + for(VarMap::const_iterator vmIt = fvmIt->second.begin(); vmIt != fvmIt->second.end(); ++vmIt){ + str.append(ffvmIt->first).append(",").append(fvmIt->first).append(",").append(vmIt->first); + str.append(",def{"); + for(unsigned int def : vmIt->second.def){ + std::stringstream ststrm; + ststrm<second.use){ + std::stringstream ststrm; + ststrm<second.dvars){ + str.append(dv.append(",")); + } + if(str.at(str.length()-1) == ',') + str.erase(str.length()-1); + str.append("},"); + str.append("pointers{"); + for(std::string al : vmIt->second.aliases){ + str.append(al.append(",")); + } + if(str.at(str.length()-1) == ',') + str.erase(str.length()-1); + str.append("},"); + str.append("cfuncs{"); + for(auto cfunc : vmIt->second.cfunctions){ + std::stringstream ststrm; + ststrm<find("stack.cpp.xml"); + //handler.ComputeInterprocedural("SlicerTestSample.cpp"); + //TestSlice(handler.sysDict-> handler); + //TestSlice2(handler.sysDict->globalMap); + srcSliceToCsv(sslice); + return 0; +} \ No newline at end of file diff --git a/src/cpp/srcSlice.cpp b/src/cpp/srcSlice.cpp index 08cc245..7558361 100644 --- a/src/cpp/srcSlice.cpp +++ b/src/cpp/srcSlice.cpp @@ -1,196 +1,31 @@ -/** - * @file srcSlice.cpp - * - * @copyright Copyright (C) 2013-2014 SDML (www.srcML.org) - * - * The srcML Toolkit is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The srcML Toolkit is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the srcML Toolkit; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include - -void TestSlice2(const VarMap& mp){ - for(VarMap::const_iterator vmIt = mp.begin(); vmIt != mp.end(); ++vmIt){ - std::cerr<<"-------------------------"<first<second.slines){ - std::cerr<second.dvars){ - std::cerr<second.aliases){ - std::cerr<second.cfunctions){ - std::cerr< +srcSlice::srcSlice(const char* filename, const char* encoding = 0){ + srcSAXController control(filename); + srcSliceHandler handler(&dictionary); + control.parse(&handler); + DoComputation(handler, handler.sysDict->ffvMap); } -void TestSlice(const FileFunctionVarMap& mp, srcSliceHandler handler){ - for(FileFunctionVarMap::const_iterator ffvmIt = mp.begin(); ffvmIt != mp.end(); ++ffvmIt){ - std::cerr<<"FILE: "<first<second.begin(); fvmIt != ffvmIt->second.end(); ++fvmIt){ - std::cerr<first<first)->second<second.begin(); vmIt != fvmIt->second.end(); ++vmIt){ - std::cerr<<"-------------------------"<first<second.slines){ - std::cerr<second.dvars){ - std::cerr<second.aliases){ - std::cerr<second.cfunctions){ - std::cerr<second.def){ - std::cerr<second.use){ - std::cerr<ffvMap); } - -void srcSliceToCsv(const srcSliceHandler& handler){ - std::string str; - for(FileFunctionVarMap::const_iterator ffvmIt = handler.sysDict.dictionary.ffvMap.begin(); ffvmIt != handler.sysDict.dictionary.ffvMap.end(); ++ffvmIt){ - //auto fileNameIt = handler.sysDict.fileTable.find(ffvmIt->first); - //if(fileNameIt != handler.sysDict.fileTable.end()) - for(FunctionVarMap::const_iterator fvmIt = ffvmIt->second.begin(); fvmIt != ffvmIt->second.end(); ++fvmIt){ - //auto functionNameIt = handler.sysDict.functionTable.find(); - for(VarMap::const_iterator vmIt = fvmIt->second.begin(); vmIt != fvmIt->second.end(); ++vmIt){ - str.append(ffvmIt->first).append(",").append(fvmIt->first).append(",").append(vmIt->first); - str.append(",def{"); - for(unsigned int def : vmIt->second.def){ - std::stringstream ststrm; - ststrm<second.use){ - std::stringstream ststrm; - ststrm<second.dvars){ - str.append(dv.append(",")); - } - if(str.at(str.length()-1) == ',') - str.erase(str.length()-1); - str.append("},"); - str.append("pointers{"); - for(std::string al : vmIt->second.aliases){ - str.append(al.append(",")); - } - if(str.at(str.length()-1) == ',') - str.erase(str.length()-1); - str.append("},"); - str.append("cfuncs{"); - for(auto cfunc : vmIt->second.cfunctions){ - std::stringstream ststrm; - ststrm<ffvMap); } -void DoComputation(srcSliceHandler& h, const FileFunctionVarMap& mp){ - for(FileFunctionVarMap::const_iterator ffvmIt = mp.begin(); ffvmIt != mp.end(); ++ffvmIt){ - h.ComputeInterprocedural(ffvmIt->first); - } +srcSlice::srcSlice(int fd, const char* encoding = 0){ + srcSAXController control(fd); + srcSliceHandler handler(&dictionary); + control.parse(&handler); + DoComputation(handler, handler.sysDict->ffvMap); } -/** - * main - * @param argc number of arguments - * @param argv the provided arguments (array of C strings) - * - * Invoke srcSAX handler to count element occurences and print out the resulting element counts. - */ -/* - Type Resolution tool - Def Use Tool as separate thing (same as type res?) - methods - statement # - Consider output to srcML - */ -int main(int argc, char * argv[]) { - - if(argc < 2) { - - std::cerr << "Useage: srcSlice input_file.xml\n"; - exit(1); - - } - //clock_t t; - //t = clock(); - srcSAXController control(argv[1]); - srcSliceHandler handler; - control.parse(&handler); - DoComputation(handler, handler.sysDict.dictionary.ffvMap); - //t = clock() - t; - //std::cerr<<"Time is: "<<((float)t)/CLOCKS_PER_SEC<ffvMap); } \ No newline at end of file diff --git a/src/cpp/srcSliceHandler.cpp b/src/cpp/srcSliceHandler.cpp index fc3356d..60f35ae 100644 --- a/src/cpp/srcSliceHandler.cpp +++ b/src/cpp/srcSliceHandler.cpp @@ -33,8 +33,8 @@ SliceProfile* srcSliceHandler::Find(const std::string& varName){ if(sp != FunctionIt->second.end()){ return &(sp->second); }else{ //check global map - auto sp2 = sysDict.globalMap.find(varName); - if(sp2 != sysDict.globalMap.end()){ + auto sp2 = sysDict->globalMap.find(varName); + if(sp2 != sysDict->globalMap.end()){ return &(sp2->second); } } @@ -99,7 +99,7 @@ void srcSliceHandler::GetParamType(){ unsigned int paramHash = paramTypeHash(currentParamType.first); functionTmplt.params.push_back(paramHash); functionTmplt.functionNumber += paramHash; - sysDict.typeTable.insert(std::make_pair(paramHash, currentParamType.first)); + sysDict->typeTable.insert(std::make_pair(paramHash, currentParamType.first)); currentParamType.first.clear(); } @@ -139,7 +139,7 @@ void srcSliceHandler::GetFunctionDeclData(){ unsigned int paramHash = paramTypeHash(currentParamType.first); functionTmplt.functionNumber += paramHash; functionTmplt.params.push_back(paramHash); - sysDict.typeTable.insert(std::make_pair(paramHash, currentParamType.first)); + sysDict->typeTable.insert(std::make_pair(paramHash, currentParamType.first)); } /** @@ -158,7 +158,7 @@ void srcSliceHandler::GetDeclStmtData(){ varIt = FunctionIt->second.insert(std::make_pair(currentDecl.first, std::move(currentSliceProfile))).first; varIt->second.def.insert(currentDecl.second); }else{ //TODO: Handle def use for globals - sysDict.globalMap.insert(std::make_pair(currentDecl.first, std::move(currentSliceProfile))); + sysDict->globalMap.insert(std::make_pair(currentDecl.first, std::move(currentSliceProfile))); } } @@ -252,8 +252,8 @@ void srcSliceHandler::ProcessDeclCtor(){ */ void srcSliceHandler::ComputeInterprocedural(const std::string& f){ - FileIt = sysDict.dictionary.ffvMap.find(f); - if(FileIt == sysDict.dictionary.ffvMap.end()){ + FileIt = sysDict->ffvMap.find(f); + if(FileIt == sysDict->ffvMap.end()){ std::cerr<<"CAN'T FIND FILE"< dvars;//maybe hash std::unordered_set aliases;//maybe hash }; - - - -struct srcSlice{ - struct SliceDictionary{ - //context can be used to keep track of what function you're searching in. Makes searching faster because I assume you're using that function as the context - struct Context{ - int ln; - std::string fileName; - std::string functionName; - FunctionVarMap::iterator currentFunc; - FileFunctionVarMap::iterator currentFile; - Context():fileName(""), functionName(""), ln(-1){} - bool IsSet() const {return (ln == -1 || functionName == "") ? false : true;} - Context(std::string file, std::string func, unsigned int line, FileFunctionVarMap::iterator fileIt, FunctionVarMap::iterator funcIt) - : fileName(file), functionName(func), ln(line), currentFile(fileIt), currentFunc(funcIt){} - }; - Context currentContext; - FileFunctionVarMap ffvMap; - }; - /*This is a map of file, function/method, and variables. {file, {function, {SliceProfiles}}}*/ - SliceDictionary dictionary; - - VarMap globalMap; - std::unordered_map classTable; - std::unordered_map typeTable; - std::vector> controledges; - - srcSlice(){} - srcSlice(const char*, const char*){} - srcSlice(std::string, const char*){} - srcSlice(FILE*, const char*){} - srcSlice(int, const char*){} - void ReadArchiveFile(std::string){} - - int size()const {return dictionary.ffvMap.size();} - - bool SetContext(std::string fle, std::string fn, int linenumber){ - FileFunctionVarMap::iterator fleIt = dictionary.ffvMap.find(fle); - if(fleIt != dictionary.ffvMap.end()){ - FunctionVarMap::iterator fnIt = fleIt->second.find(fn); - if(fnIt != fleIt->second.end()){ - dictionary.currentContext.currentFile = fleIt; - dictionary.currentContext.currentFunc = fnIt; - dictionary.currentContext.ln = linenumber; - dictionary.currentContext.functionName = fle; - dictionary.currentContext.functionName = fn; - return true; - } - } - return false; - } - - bool SetContext(std::string fn, int linenumber){ - if(dictionary.currentContext.currentFile != dictionary.ffvMap.end()){ - FunctionVarMap::iterator fnIt = dictionary.currentContext.currentFile->second.find(fn); - if(fnIt != dictionary.currentContext.currentFile->second.end()){ - dictionary.currentContext.currentFunc = fnIt; - dictionary.currentContext.ln = linenumber; - dictionary.currentContext.functionName = fn; - return true; - } - } - return false; - } - bool SetContext(int linenumber){ //it enough to just check function? Need to check file? - if(dictionary.currentContext.currentFunc != dictionary.currentContext.currentFile->second.end()){ - dictionary.currentContext.ln = linenumber; - return true; - } - return false; - } - //Definition of find that assumes the user didn't give a context (They should just give a context, though, tbh). - std::pair Find(std::string flename, std::string funcname, std::string varname, int lineNumber)const{ - FileFunctionVarMap::const_iterator ffvmIt = dictionary.ffvMap.find(flename); - if(ffvmIt != dictionary.ffvMap.end()){ - FunctionVarMap::const_iterator fvmIt = ffvmIt->second.find(funcname); - if(fvmIt != ffvmIt->second.end()){ - VarMap::const_iterator vtmIt = fvmIt->second.find(varname); - if(vtmIt != fvmIt->second.end()){ - return std::make_pair(true, vtmIt->second); - } - } - } - - return std::make_pair(false, SliceProfile()); - } - //Definition of find that assumes the user didn't give a context (They should just give a context, though, tbh). - std::pair Find(std::string funcname, std::string varname, int lineNumber)const{ - FunctionVarMap::const_iterator fvmIt = dictionary.currentContext.currentFile->second.find(funcname); - if(fvmIt != dictionary.currentContext.currentFile->second.end()){ - VarMap::const_iterator vtmIt = fvmIt->second.find(varname); - if(vtmIt != fvmIt->second.end()){ - return std::make_pair(true, vtmIt->second); - } - } - return std::make_pair(false, SliceProfile()); - } - //Definition of find that uses the context (so it doesn't need to take a function name as context) - std::pair Find(std::string varname) const{ - if(!dictionary.currentContext.IsSet()){ - throw std::runtime_error("Context not set"); //for now, std exception - }else{ - VarMap::const_iterator it = dictionary.currentContext.currentFunc->second.find(varname); - if(it != dictionary.currentContext.currentFunc->second.end()){ - return std::make_pair(true, it->second); - } - return std::make_pair(false, SliceProfile()); - } - } - bool Insert(std::string flename, std::string funcname, const SliceProfile& np){ - FileFunctionVarMap::iterator ffvmIt = dictionary.ffvMap.find(flename); - if(ffvmIt != dictionary.ffvMap.end()){ - FunctionVarMap::iterator fvmIt = ffvmIt->second.find(funcname); - if(fvmIt != ffvmIt->second.end()){ - VarMap::iterator vtmIt = fvmIt->second.find(np.variableName); - if(vtmIt != fvmIt->second.end()){ - vtmIt->second = np; - return true; - }else{ - fvmIt->second.insert(std::make_pair(np.variableName, np)); - return true; - } - } - } - return false; - } - - bool Insert(std::string funcname, const SliceProfile& np){ - if(dictionary.currentContext.currentFile != dictionary.ffvMap.end()){ - FunctionVarMap::iterator fvmIt = dictionary.currentContext.currentFile->second.find(funcname); - if(fvmIt != dictionary.currentContext.currentFile->second.end()){ - VarMap::iterator vtmIt = fvmIt->second.find(np.variableName); - if(vtmIt != fvmIt->second.end()){ - vtmIt->second = np; - return true; - }else{ - fvmIt->second.insert(std::make_pair(np.variableName, np)); - return true; - } - } - } - return false; - } - - bool Insert(const SliceProfile& np){ - if(dictionary.currentContext.ln == -1){ //TODO: Make better - throw std::runtime_error("Context not set"); //for now, std exception - }else{ - auto it = dictionary.currentContext.currentFunc->second.find(np.variableName); - if(it != dictionary.currentContext.currentFunc->second.end()){ - it->second = np; - return true; - }else{ - dictionary.currentContext.currentFunc->second.insert(std::make_pair(np.variableName, np)); - return true; - } - } - return false; - } - -}; #endif \ No newline at end of file diff --git a/src/headers/Utility.hpp b/src/headers/Utility.hpp index a8f1de4..b19e2fa 100644 --- a/src/headers/Utility.hpp +++ b/src/headers/Utility.hpp @@ -24,28 +24,48 @@ #include #include #include +struct SliceDictionary{ + //context can be used to keep track of what function you're searching in. Makes searching faster because I assume you're using that function as the context + struct Context{ + int ln; + std::string fileName; + std::string functionName; + FunctionVarMap::iterator currentFunc; + FileFunctionVarMap::iterator currentFile; + Context():fileName(""), functionName(""), ln(-1){} + bool IsSet() const {return (ln == -1 || functionName == "") ? false : true;} + Context(std::string file, std::string func, unsigned int line, FileFunctionVarMap::iterator fileIt, FunctionVarMap::iterator funcIt) + : fileName(file), functionName(func), ln(line), currentFile(fileIt), currentFunc(funcIt){} + }; + VarMap globalMap; + std::unordered_map classTable; + std::unordered_map typeTable; + std::vector> controledges; + Context currentContext; + FileFunctionVarMap ffvMap; +}; template -void SetUnion(std::unordered_set& set1, std::unordered_set set2){ +inline void SetUnion(std::unordered_set& set1, std::unordered_set set2){ for(typename std::unordered_set::iterator itr = set2.begin(); itr != set2.end(); ++itr){ set1.insert(*itr); } } template -void SetUnion(std::set& set1, std::set set2){ +inline void SetUnion(std::set& set1, std::set set2){ for(typename std::set::iterator itr = set2.begin(); itr != set2.end(); ++itr){ set1.insert(*itr); } } template -void SetUnion(std::unordered_set& set1, std::unordered_set& set2){ +inline void SetUnion(std::unordered_set& set1, std::unordered_set& set2){ for(typename std::unordered_set::iterator itr = set2.begin(); itr != set2.end(); ++itr){ set1.insert(*itr); } } -std::vector SplitLhsRhs(const std::string& str){ +inline std::vector SplitLhsRhs(const std::string& str){ std::vector expr; expr.push_back(std::string()); for(int i = 0; i SplitLhsRhs(const std::string& str){ } /* Split function for splitting strings by tokens. Works on sets of tokens or just one token*/ -std::vector SplitOnTok(const std::string& str, const char* tok){ +inline std::vector SplitOnTok(const std::string& str, const char* tok){ std::size_t tokPos = str.find_first_of(tok); std::vector result; std::size_t nextPos = 0, curPos = 0; diff --git a/src/headers/srcSlice.hpp b/src/headers/srcSlice.hpp new file mode 100644 index 0000000..199abc9 --- /dev/null +++ b/src/headers/srcSlice.hpp @@ -0,0 +1,141 @@ +#include +#include +#ifndef SRCSLICEHPP +#define SRCSLICEHPP +struct srcSlice{ +/*This is a map of file, function/method, and variables. {file, {function, {SliceProfiles}}}*/ +SliceDictionary dictionary; +srcSlice(){} +srcSlice(const char* filename, const char* encoding); +srcSlice(std::string buffer, const char* encoding); +srcSlice(FILE* file, const char* encoding); +srcSlice(int fd, const char* encoding); +void ReadArchiveFile(std::string filename); + int size()const {return dictionary.ffvMap.size();} + + bool SetContext(std::string fle, std::string fn, int linenumber){ + FileFunctionVarMap::iterator fleIt = dictionary.ffvMap.find(fle); + if(fleIt != dictionary.ffvMap.end()){ + FunctionVarMap::iterator fnIt = fleIt->second.find(fn); + if(fnIt != fleIt->second.end()){ + dictionary.currentContext.currentFile = fleIt; + dictionary.currentContext.currentFunc = fnIt; + dictionary.currentContext.ln = linenumber; + dictionary.currentContext.functionName = fle; + dictionary.currentContext.functionName = fn; + return true; + } + } + return false; + } + + bool SetContext(std::string fn, int linenumber){ + if(dictionary.currentContext.currentFile != dictionary.ffvMap.end()){ + FunctionVarMap::iterator fnIt = dictionary.currentContext.currentFile->second.find(fn); + if(fnIt != dictionary.currentContext.currentFile->second.end()){ + dictionary.currentContext.currentFunc = fnIt; + dictionary.currentContext.ln = linenumber; + dictionary.currentContext.functionName = fn; + return true; + } + } + return false; + } + bool SetContext(int linenumber){ //it enough to just check function? Need to check file? + if(dictionary.currentContext.currentFunc != dictionary.currentContext.currentFile->second.end()){ + dictionary.currentContext.ln = linenumber; + return true; + } + return false; + } + //Definition of find that assumes the user didn't give a context (They should just give a context, though, tbh). + std::pair Find(std::string flename, std::string funcname, std::string varname, int lineNumber)const{ + FileFunctionVarMap::const_iterator ffvmIt = dictionary.ffvMap.find(flename); + if(ffvmIt != dictionary.ffvMap.end()){ + FunctionVarMap::const_iterator fvmIt = ffvmIt->second.find(funcname); + if(fvmIt != ffvmIt->second.end()){ + VarMap::const_iterator vtmIt = fvmIt->second.find(varname); + if(vtmIt != fvmIt->second.end()){ + return std::make_pair(true, vtmIt->second); + } + } + } + + return std::make_pair(false, SliceProfile()); + } + //Definition of find that assumes the user didn't give a context (They should just give a context, though, tbh). + std::pair Find(std::string funcname, std::string varname, int lineNumber)const{ + FunctionVarMap::const_iterator fvmIt = dictionary.currentContext.currentFile->second.find(funcname); + if(fvmIt != dictionary.currentContext.currentFile->second.end()){ + VarMap::const_iterator vtmIt = fvmIt->second.find(varname); + if(vtmIt != fvmIt->second.end()){ + return std::make_pair(true, vtmIt->second); + } + } + return std::make_pair(false, SliceProfile()); + } + //Definition of find that uses the context (so it doesn't need to take a function name as context) + std::pair Find(std::string varname) const{ + if(!dictionary.currentContext.IsSet()){ + throw std::runtime_error("Context not set"); //for now, std exception + }else{ + VarMap::const_iterator it = dictionary.currentContext.currentFunc->second.find(varname); + if(it != dictionary.currentContext.currentFunc->second.end()){ + return std::make_pair(true, it->second); + } + return std::make_pair(false, SliceProfile()); + } + } + bool Insert(std::string flename, std::string funcname, const SliceProfile& np){ + FileFunctionVarMap::iterator ffvmIt = dictionary.ffvMap.find(flename); + if(ffvmIt != dictionary.ffvMap.end()){ + FunctionVarMap::iterator fvmIt = ffvmIt->second.find(funcname); + if(fvmIt != ffvmIt->second.end()){ + VarMap::iterator vtmIt = fvmIt->second.find(np.variableName); + if(vtmIt != fvmIt->second.end()){ + vtmIt->second = np; + return true; + }else{ + fvmIt->second.insert(std::make_pair(np.variableName, np)); + return true; + } + } + } + return false; + } + + bool Insert(std::string funcname, const SliceProfile& np){ + if(dictionary.currentContext.currentFile != dictionary.ffvMap.end()){ + FunctionVarMap::iterator fvmIt = dictionary.currentContext.currentFile->second.find(funcname); + if(fvmIt != dictionary.currentContext.currentFile->second.end()){ + VarMap::iterator vtmIt = fvmIt->second.find(np.variableName); + if(vtmIt != fvmIt->second.end()){ + vtmIt->second = np; + return true; + }else{ + fvmIt->second.insert(std::make_pair(np.variableName, np)); + return true; + } + } + } + return false; + } + + bool Insert(const SliceProfile& np){ + if(dictionary.currentContext.ln == -1){ //TODO: Make better + throw std::runtime_error("Context not set"); //for now, std exception + }else{ + auto it = dictionary.currentContext.currentFunc->second.find(np.variableName); + if(it != dictionary.currentContext.currentFunc->second.end()){ + it->second = np; + return true; + }else{ + dictionary.currentContext.currentFunc->second.insert(std::make_pair(np.variableName, np)); + return true; + } + } + return false; + } + +}; +#endif \ No newline at end of file diff --git a/src/headers/srcSliceHandler.hpp b/src/headers/srcSliceHandler.hpp index a0c50a8..d920103 100644 --- a/src/headers/srcSliceHandler.hpp +++ b/src/headers/srcSliceHandler.hpp @@ -23,14 +23,14 @@ #include #include - +#include +#include #include #include #include #include #include #include - class srcSliceHandler : public srcSAXHandler { private: /*ParserState is a set of enums corresponding to srcML tags. Primarily, they're for addressing into the @@ -149,9 +149,11 @@ class srcSliceHandler : public srcSAXHandler { SliceProfile* Find(const std::string& varName); public: void ComputeInterprocedural(const std::string&); - srcSlice sysDict; + SliceDictionary* sysDict; unsigned int lineNum; - srcSliceHandler(){ + srcSliceHandler(SliceDictionary* dict){ + sysDict = dict; + fileNumber = 0; numArgs = 0; declIndex = 0; @@ -388,19 +390,19 @@ class srcSliceHandler : public srcSAXHandler { } }, { "if", [this](){ - //sysDict.controledges.push_back(std::make_pair(controlFlowLineNum.top()+1, lineNum)); //save line number for beginning and end of control structure + //sysDict->controledges.push_back(std::make_pair(controlFlowLineNum.top()+1, lineNum)); //save line number for beginning and end of control structure //controlFlowLineNum.pop(); --triggerField[ifcond]; } }, { "for", [this](){ - //sysDict.controledges.push_back(std::make_pair(controlFlowLineNum.top()+1, lineNum)); //save line number for beginning and end of control structure + //sysDict->controledges.push_back(std::make_pair(controlFlowLineNum.top()+1, lineNum)); //save line number for beginning and end of control structure //controlFlowLineNum.pop(); --triggerField[forloop]; } }, { "while", [this](){ - //sysDict.controledges.push_back(std::make_pair(controlFlowLineNum.top()+1, lineNum)); //save line number for beginning and end of control structure + //sysDict->controledges.push_back(std::make_pair(controlFlowLineNum.top()+1, lineNum)); //save line number for beginning and end of control structure //controlFlowLineNum.pop(); --triggerField[whileloop]; } }, @@ -475,13 +477,13 @@ class srcSliceHandler : public srcSAXHandler { } }, { "class", [this](){ currentClassName.first.clear(); - //classIt = sysDict.classTable.find("GLOBAL"); + //classIt = sysDict->classTable.find("GLOBAL"); /* - std::cerr<<"Class mfs: "<second.memberFunctions.size()<second.memberVariables.size()<classTable.find("CLASSBRO")->second.memberFunctions.size()<classTable.find("CLASSBRO")->second.memberVariables.size()<second.memberFunctions.size()<second.memberVariables.size()<classTable.find("GLOBAL")->second.memberFunctions.size()<classTable.find("GLOBAL")->second.memberVariables.size()<ffvMap.insert(std::make_pair(std::string(attributes[2].value), FunctionVarMap())).first; //insert and keep track of most recent. //std::cerr<<"val: "<classTable.insert(std::make_pair("GLOBAL", ClassProfile())).first; FunctionIt = FileIt->second.insert(std::make_pair("GLOBAL", VarMap())).first; //for globals. Makes a bad assumption about where globals are. Fix. } /** @@ -868,5 +870,9 @@ class srcSliceHandler : public srcSAXHandler { #pragma GCC diagnostic pop } }; - +inline void DoComputation(srcSliceHandler& h, const FileFunctionVarMap& mp){ + for(FileFunctionVarMap::const_iterator ffvmIt = mp.begin(); ffvmIt != mp.end(); ++ffvmIt){ + h.ComputeInterprocedural(ffvmIt->first); + } +} #endif \ No newline at end of file diff --git a/src/tests/TestFlatSlice.cpp b/src/tests/TestFlatSlice.cpp new file mode 100644 index 0000000..fa7713e --- /dev/null +++ b/src/tests/TestFlatSlice.cpp @@ -0,0 +1,93 @@ +/** + * @file srcSlice.cpp + * + * @copyright Copyright (C) 2013-2014 SDML (www.srcML.org) + * + * The srcML Toolkit is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The srcML Toolkit is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the srcML Toolkit; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include "TestFlatSlice.hpp" +/// +/// Utility function that trims from the right of a string. For now it's just solving a weird issue with srcML +/// and garbage text ending up at the end of the cstring it returns. +/// +inline char* TrimFromEnd(char *s, size_t len){ + for (int i = len - 1; i > 0; --i){ + if (s[i] != '>'){ + s[i] = 0; + }else{ + return s; + } + } + return nullptr; +} +std::string StringToSrcML(std::string str){ + struct srcml_archive* archive; + struct srcml_unit* unit; + size_t size = 0; + + char *ch = new char[str.size()]; + + archive = srcml_archive_create(); + srcml_archive_enable_option(archive, SRCML_OPTION_POSITION); + srcml_archive_write_open_memory(archive, &ch, &size); + + unit = srcml_unit_create(archive); + srcml_unit_set_language(unit, SRCML_LANGUAGE_CXX); + srcml_unit_set_filename(unit, "testsrcSlice.cpp"); + + srcml_unit_parse_memory(unit, str.c_str(), str.size()); + srcml_write_unit(archive, unit); + + srcml_unit_free(unit); + srcml_archive_close(archive); + srcml_archive_free(archive); + TrimFromEnd(ch, size); + return std::string(ch); +} +bool TestPrimitiveTypes(){ + std::string srcmlStr = StringToSrcML(FlatSlicePrograms::FlatSliceOne()); + try{ + std::cerr< +struct FlatSlicePrograms{ + static std::string FlatSliceOne(){ + std::string FlatSliceOneV = + "void fun(int z){\n" + " z++;\n" + "}\n" + "void foo(int &x, int &y){\n" + "fun(x);\n" + "y++;\n" + "}\n" + "int main(){\n" + "int sum = 0;\n" + "int i = 1;\n" + "while (i<=10){\n" + "foo(sum, i);\n" + "}\n" + "std::cout<