symbolviewer.cxx

Go to the documentation of this file.
00001 #include <cxxtls/symbolviewer.h>
00002 #include <cxxtls/viewermanager.h>
00003 #include <cxxtls/file.h>
00004 #include <portable_io.h>   // for popen()
00005 #include <cxxtls/options.h>
00006 #include <stdlib.h>
00007 
00008 using namespace std;
00009 
00010 #ifdef _MSC_VER
00011 #define SLASH '\\'
00012 #else
00013 #define SLASH '/'
00014 #endif
00015 
00016 namespace cxxtls
00017 {
00018 //---------------------------------------------------------------------------------
00019 
00020 
00021 SymbolViewer::
00022 SymbolViewer(ViewerManager *vm, std::string databaseFilename)
00023 :  TreeViewer(vm)
00024 ,  databaseName_( (databaseFilename.empty() ? "TAGPP.tagpp" : databaseFilename.c_str() ) )
00025 {
00026      using namespace CppTagDB;
00027 
00028     bool generateDirectly = false; // the database name is not a real file
00029 
00030     if(databaseName_.size() > 9)
00031     {
00032        
00033 
00034        char const *p = databaseName_.data();
00035 
00036        p += databaseName_.size()-9;
00037 
00038        if(memcmp(p, ".cpptagdb", 9) == 0)
00039        {
00040           generateDirectly = true; // we have something like:   /home/dir/fred.cpp.cpptagdb
00041 
00042           databaseName_ = databaseName_.substr(0, databaseName_.size()-9);
00043        }
00044 
00045 
00046     }
00047 
00048     if(!generateDirectly)
00049     {
00050         char const *etagsPath = getenv("ETAGSPATH");
00051         
00052         char const *sourcePath= getenv("SOURCEPATH");
00053         
00054         if(!FileName(databaseName_).exists())
00055         {
00056             FileName location(databaseName_);
00057         
00058             if(etagsPath)
00059                 location = location.find_file_in_path(databaseName_, etagsPath);
00060         
00061             if(location == databaseName_)
00062             {
00063                if(sourcePath == 0)
00064                {
00065                   sourcePath=".:..:../..:../../..:../../../..";
00066                }
00067         
00068                 location = location.find_file_in_path(databaseName_, sourcePath);
00069             }
00070         
00071             databaseName_ = location;
00072         
00073         }
00074     }
00075 
00076     TreeViewer *me = this;
00077     me->setApplicationName(string("SymbolViewer: ") + databaseFilename);
00078 
00079     me->setRootDir(databaseName_.dirname());
00080 
00081     int errorLine=0;
00082 
00083     if(generateDirectly)
00084     {
00085         FileName curdir = FileName::getcwd();   // save current directory for later return
00086 
00087         string cpptagdb_executable = "cpptagdb.exe";
00088       
00089         if(ProgramOptions::global_options_)
00090         {
00091            FileName myProgram = ProgramOptions::global_options_->argv[0];  // 0 is known to exist
00092       
00093            FileName myDir = myProgram.dirname();
00094       
00095            FileName exeFile = myDir;
00096            
00097            exeFile += SLASH;
00098            
00099            exeFile += cpptagdb_executable;
00100       
00101            if(exeFile.exists())
00102            {
00103               cpptagdb_executable = exeFile;
00104            }
00105       
00106         }
00107 
00108         static string quote("\"");
00109 
00110         
00111         string cmd = quote + cpptagdb_executable + quote;
00112 
00113         if(databaseName_.size() > 2
00114            && databaseName_[ databaseName_.size() - 1] == '!'
00115           )
00116         {
00117            // the databaseName_ is a directory reference -- 
00118            // instead of using the normal command, let us
00119            // find the names of files in the specified directory
00120            // that are expected to be C++ and generate the
00121            // tag information for all of them.
00122 
00123            string dirname = databaseName_.substr(0, databaseName_.size()-2); 
00124               // everything up to the trailing /!
00125 
00126 
00127 
00128 
00129 #ifdef _MSC_VER
00130 
00131            chdir(dirname.c_str());
00132 
00133            string searchCmd(" dir ");
00134            string searchOption(" /s /b ");
00135            string fileTypes("*.h *.hpp *.hxx *.h++ *.c *.cpp *.cxx *.c++ | ");
00136 
00137            cmd = searchCmd + searchOption + fileTypes + quote + cpptagdb_executable + quote + " -stdin ";
00138 
00139 #else
00140            string searchCmd("find ");
00141            string searchOption(" ");
00142            string fileTypes("\\( -name '*.h' -o -name '*.hpp' -o -name '*.hxx' -o -name '*.h++' -o -name '*.c' -o -name '*.cpp' -o -name '*.cxx' -o -name '*.c++' \\) | ");
00143            cmd = searchCmd + quote + dirname + quote + searchOption + fileTypes + quote + cpptagdb_executable + quote + " -stdin ";
00144 
00145 #endif
00146 
00147 
00148 
00149 
00150         }
00151         else
00152         {
00153             cmd += " \"";
00154             cmd += databaseName_;
00155             cmd += "\"";
00156 
00157         }
00158 
00159 
00160         vm->close();
00161 
00162 
00163         FILE *f=popen(cmd.c_str(), "r");
00164         
00165         database_.populate(f, errorLine);
00166 
00167         pclose(f);
00168 
00169         int rv=chdir(curdir.c_str());  // return to current directory (dos in particualar)
00170 
00171         rv=rv; // ingore chdir return value gosh darn it!
00172 
00173         vm->open();
00174 
00175 
00176     }
00177     else
00178         database_.populate(databaseName_, errorLine);
00179 
00180     TreeViewerNode &topNode = this->topNode();
00181     topNode.setName(databaseName_);
00182     
00183     { // populate node tree
00184 
00185         TreeViewerNode &Symbols           = topNode.addChild("SYMBOLS");
00186 
00187        SymbolInfo::const_iterator first= database_.symbols_.children_.begin(),
00188                                   last = database_.symbols_.children_.end();
00189 
00190        while(first != last)
00191        {
00192           addChild(Symbols, first->second);
00193 
00194           ++first;
00195        }
00196 
00197 
00198         
00199     } // populate node tree
00200 
00201 }
00202 
00203 //-----------------------------------------------------------------------------------
00204 
00205 void SymbolViewer::
00206 addChild(TreeViewerNode &parent, CppTagDB::SymbolInfo const &symbol)
00207 {
00208     using namespace CppTagDB;
00209 
00210     TreeViewerNode &child = parent.addChild(symbol.annotatedName(true));
00211 
00212     if(symbol.line_ != 0)
00213     {
00214         child.adoptInfo(  new SymbolViewerNodeInformation(symbol.file_,
00215                                                           symbol.line_
00216                                                           )
00217                         );
00218 
00219     }
00220     else
00221     {
00222        child.setHighlighted();
00223     }
00224 
00225     if(!symbol.children_.empty())
00226     {
00227 
00228     
00229         SymbolInfo::Children::const_iterator first = symbol.children_.begin(),
00230                                              last  = symbol.children_.end();
00231 
00232         while(first != last)
00233         {
00234            SymbolInfo::Children::value_type const &cur = *first++;
00235 
00236            addChild(child, cur.second);
00237 
00238         }
00239 
00240     }
00241 
00242 }
00243 
00244 
00245 //-----------------------------------------------------------------------------------
00246 
00247 bool 
00248 SymbolViewerNodeInformation::
00249 operator() (ViewerManager*vm, CursorWindow::viewport *vp, int command, FileName const &rootDir)
00250 {
00251     FileName fileName(filename_);
00252 
00253     if(!fileName.is_absolute_path())
00254     {
00255         fileName = rootDir + fileName;
00256     }
00257 
00258 
00259     Viewer* oldie = vm->find_viewer(fileName);
00260 
00261     if(oldie)
00262     {
00263       oldie->set_row_col_hint(lineNumber_-1,0);
00264       vm->activate(oldie);
00265     }
00266     else
00267     {
00268 
00269       Viewer* newbie = vm->edit(fileName);
00270 
00271       if(newbie)
00272       {
00273         newbie->set_row_col_hint(lineNumber_-1,0);
00274 
00275         vm->vsplit(newbie, fileName);
00276 
00277       }
00278       else
00279         vm->active_viewport()->beep();
00280     }
00281 
00282     return false; // don't exit the browser
00283 }
00284    
00285 
00286 //-----------------------------------------------------------------------------------
00287 
00288 Viewer* 
00289 SymbolViewer::
00290 app(ViewerManager*vm, std::string &fullname)
00291 {
00292    SymbolViewer *rv =new SymbolViewer(vm, fullname);  
00293 
00294 
00295 
00296    return rv;
00297 }
00298 //-----------------------------------------------------------------------------------
00299 
00300 void
00301 SymbolViewer::
00302 helpHeader(std::list<std::string> &help_text)
00303 {
00304    help_text.push_back( "Viewing Symbols" );
00305    help_text.push_back("");
00306    help_text.push_back("  This window contains a hierarchy of symbols read from");
00307    help_text.push_back("  file or directory (or subtree) by the cpptagdb.exe");
00308    help_text.push_back("  program.  It lists the locations at which symbols are");
00309    help_text.push_back("  defined in files (not just declared, but defined.)");
00310    help_text.push_back("");
00311    help_text.push_back("  Each symbol is identified by name and type:");
00312    help_text.push_back("");
00313    help_text.push_back("    type names (classes, typedefs) etc are postfixed with {}");
00314    help_text.push_back("");
00315    help_text.push_back("    enums and #defines are postfixed with #");
00316    help_text.push_back("");
00317    help_text.push_back("    variables are identified by @");
00318    help_text.push_back("");
00319    help_text.push_back("    functions are annotated with ()");
00320    help_text.push_back("");
00321    help_text.push_back("  Use the Enter key to show the actual source of the symbol.");
00322    help_text.push_back("");
00323    help_text.push_back("  Use the =/+ keys to open and close one level of hierarchy");
00324    help_text.push_back("");
00325    help_text.push_back("  See below for more key definitions");
00326 }
00327 
00328 
00329 //-----------------------------------------------------------------------------------
00330 
00331 
00332 }; // namespace cxxtls
00333 
Generated on Wed Feb 29 22:50:05 2012 for CXXUtilities by  doxygen 1.6.3