///////////////////////////////////////////////////////////////////// // executive.cpp - will implement Calls requirements using // // ver 1.3 modules listed below // // // // Language: Visual C++, ver 7.0 // // Platfrom: Dell Dimension 8100, Windows 2000, SP 2.0 // // Application: Prototype for CSE687 Pr#2, Spring 2003 // // Author: Jim Fawcett, CST 2-187, Syracuse University // // (315) 443-3948, jfawcett@twcny.rr.com // ///////////////////////////////////////////////////////////////////// /* Program Operation: ================== In its current state of completion, CallsExec demonstrates: 1. Reading commandline in the form of path and file patterns, e.g., .. *.cpp. 2. Setting and resetting paths in an executive class's ctor and dtor. 3. Cycling through file to analyze, recursively calling header files for each cpp file analyzed, using scanner module. 4. Analyzing each file, using callsProc and grammar modules. The analysis is currently a mix of Calls and Depends processing. It demonstrates most of the grammar tools you will need to do a strong dependency analysis and the tools I will be using to finish my solution to Project #2. So what is not done here? For Calls processing we need to add these items: 1. The using namespace directives are not being saved and used to associate an invocation against candidates from several namespaces. The output of this program shows: a. Each function definition and a list of all the functions it calls. b. The contents of three tables: typeTable, classDecsTable, and classFuncsTable. Scope information is attached to the types, so what is needed is prepend using items to each invocation and compare with the table to show which to which of the namespaces it belongs. Note that type information for template classes is missing in the typeTables. I won't get a chance to fix that until after finishing grading, so I won't count problems with templatized classes against you, but will include one such class in my test code. I will award bonus points if you are able to fix that. 2. Build a tree using the calls information and, using depth first search, format calls according to the requirements. For Depends processing add: 1. same as above. 2. Tables used here simply hold type and function information. They do not save file information needed for dependency analysis. It will be straightforward to have scan pass to process the name of the current file. 3. Build a dependency graph, and put the files in dependency order using topological sorting, after removing mutual dependencies by finding strong components. */ // ///////////////////////////////////////////////////////////////////// // Build Process ///////////////////////// // Required Files: // executive.cpp, fileInfo.h, fileInfo.cpp, // scanner.h, scanner.cpp, callsProc.h, callsProc.cpp, // grammar.h, grammar.cpp, semi.h, semi.cpp, tok.h, tok.cpp // // Compiler command: // cl /GX /GR executive.cpp fileInfo.cpp scanner.cpp \ // callsproc.cpp grammar.cpp semi.cpp tok.cpp // // Run command: // executive .. *.cpp ///////////////////////////////////////////////////////////////////// /* Maintenance History: ==================== ver 1.3 : 28 Apr 2003 - updated manual page ver 1.2 : 28 Apr 2003 - removed some redundant output ver 1.1 : 26 Apr 2003 - demonstrates type analysis toolbox capabilities, e.g.: > most of the parts needed to do type analysis > most of the parts needed to do calling analysis ver 1.0 : 02 Apr 2003 - demonstrates scope analysis */ // #include "callsProc.h" #include "scanner.h" #include "grammar.h" #include "display.h" #include "semi.h" #include "tok.h" #include "fileInfo.h" #include #include #include #include using namespace std; typedef std::string sstr; ///////////////////////////////////////////////////////////////////// // executive class - handles commandline and directory management class executive { public: executive(const sstr& path); ~executive(); sstr commandLineArgs(int numArgs, char* args[]); sstr path(); void run(int numArgs, char* args[]); private: sstr _origPath; sstr _path; }; //----< constructor sets path >-------------------------------------- executive::executive(const sstr& path) { _path = path; const int bufSize = 256; char buffer[bufSize]; for(int i=0; i<(int)_path.size(); ++i) _path[i] = tolower(_path[i]); GetCurrentDirectory(bufSize,buffer); _origPath = sstr(buffer); SetCurrentDirectory(_path.c_str()); GetCurrentDirectory(bufSize,buffer); _path = sstr(buffer); } //----< destructor restores original path >-------------------------- executive::~executive() { SetCurrentDirectory(_origPath.c_str()); } // //----< returns string to display commandline >---------------------- sstr executive::commandLineArgs(int argc, char* argv[]) { sstr temp = sstr("\n Executing: ") + sstr(argv[0]) + "\n with arguments: "; for(int i=1; i--------------------------------------- sstr executive::path() { return _path; } //----< builds analysis objects and starts analysis >---------------- void executive::run(int numArgs, char* args[]) { scanner s; callsProc cp(s); s.Register(&cp); fileInfo fi(path()); for(int i=0; i-------------- int main(int argc, char *argv[]) { if(argc < 3) { cout << "\n please enter path and names of files or file patterns" << " to process\n on the command line\n\n"; return 1; } try { executive exec(argv[1]); std::cout << exec.commandLineArgs(argc, argv); exec.run(argc-2, &argv[2]); } catch(exception &e) { std::cout << "\n " << typeid(e).name() << ": " << e.what() << "\n\n"; } }