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>
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;
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;
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();
00086
00087 string cpptagdb_executable = "cpptagdb.exe";
00088
00089 if(ProgramOptions::global_options_)
00090 {
00091 FileName myProgram = ProgramOptions::global_options_->argv[0];
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
00118
00119
00120
00121
00122
00123 string dirname = databaseName_.substr(0, databaseName_.size()-2);
00124
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());
00170
00171 rv=rv;
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 {
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 }
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;
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 };
00333