cpptagdb.cxx
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <cxxtls/strtool.h>
00027 #include <BIscan/BIscan.h>
00028 #include <cxxtls/cpptagdb.h>
00029 #include <errno.h>
00030 #include <cxxtls/file.h>
00031 #include <cxxtls/foreach.h>
00032
00033
00034 using namespace std;
00035
00036 namespace cxxtls
00037 {
00038 namespace CppTagDB
00039 {
00040
00041
00042 void
00043 SymbolInfo::
00044 output(std::ostream &s, std::string indent) const
00045 {
00046
00047
00048 s << indent << annotatedName(true) << "\t\t" << file_ << ':' << line_;
00049
00050 const_iterator first= children_.begin(),
00051 last = children_.end();
00052
00053
00054 if(first != last)
00055 {
00056 indent += " ";
00057 }
00058
00059 while(first != last)
00060 {
00061 s << '\n';
00062
00063 first->second.output(s, indent);
00064
00065 ++first;
00066
00067 }
00068
00069 }
00070
00071
00072 SymbolInfo::Type
00073 SymbolInfo::
00074 computeTypeId(std::string const &typeName)
00075 {
00076 using namespace std;
00077
00078 Type scopeType = unknownType;
00079
00080 static string function_id("function");
00081 static string class_id("class");
00082 static string struct_id("struct");
00083 static string enum_id("enum");
00084 static string enumeration_id("enumeration");
00085 static string typedef_id("typename");
00086 static string namespace_id("namespace");
00087 static string used_id("used");
00088 static string variable_id("variable");
00089 static string union_id("union");
00090 static string define_id("define");
00091
00092 if(typeName.empty())
00093 return scopeType;
00094
00095 char firstLetter = typeName[0];
00096
00097 if(firstLetter == 'd' && define_id == typeName)
00098 scopeType = Enumeration;
00099 else
00100 if(firstLetter == 'e' && enum_id == typeName)
00101 scopeType = Enum;
00102 else
00103 if(firstLetter == 'e' && enumeration_id == typeName)
00104 scopeType = Enumeration;
00105 else
00106 if(firstLetter == 'f' && function_id == typeName)
00107 scopeType = Function;
00108 else
00109 if(firstLetter == 's' && struct_id == typeName)
00110 scopeType = Class;
00111 else
00112 if(firstLetter == 'u' && union_id == typeName)
00113 scopeType = Class;
00114 else
00115 if(firstLetter == 'c' && class_id == typeName)
00116 scopeType = Class;
00117 else
00118 if(firstLetter == 't' && typedef_id == typeName)
00119 scopeType = Typedef;
00120 else
00121 if(firstLetter == 'n' && namespace_id == typeName)
00122 scopeType = Namespace;
00123 else
00124 if(firstLetter == 'u' && used_id == typeName)
00125 scopeType = Used;
00126 else
00127 if(firstLetter == 'v' && variable_id == typeName)
00128 scopeType = Variable;
00129
00130 return scopeType;
00131
00132 }
00133
00134
00135 char SymbolInfo::typeChar() const
00136 {
00137 switch(typeId_)
00138 {
00139 case Function: return 'f';
00140 case Variable: return 'v';
00141 case Class: return 'c';
00142 case Enum: return 'e';
00143 case Enumeration: return '#';
00144 case Typedef: return 't';
00145 case Namespace: return 'n';
00146 case FileScope: return 'F';
00147 case Used: return 'u';
00148 case Define: return 'd';
00149
00150 default: break;
00151
00152 }
00153
00154 return '?';
00155 }
00156
00157
00158 std::string
00159 SymbolInfo::
00160 annotatedName(bool member) const
00161 {
00162
00163 using namespace std;
00164
00165 string const *name = &fullname_;
00166
00167 if(member)
00168 name = &member_;
00169
00170 switch(typeId_)
00171 {
00172 case Function: return *name + " ()";
00173 case Variable: return *name + " @";
00174 case Class: return *name + " {}";
00175 case Enum: return *name + " %";
00176 case Enumeration: return *name + " #";
00177 case Typedef: return *name + " {}";
00178 case Namespace: return *name + " {}";
00179 case FileScope: return *name + " /";
00180
00181 default: break;
00182
00183 }
00184
00185 if( name->empty() )
00186 return "::";
00187
00188 return *name;
00189
00190 }
00191
00192 int
00193 Info::
00194 populate(std::string const &filename, int &failedLine)
00195 {
00196 FILE *f = fopen(filename.c_str(), "r");
00197
00198 if(!f)
00199 return -1;
00200
00201 int rc = populate(f, failedLine);
00202
00203 fclose(f);
00204
00205 return rc;
00206 }
00207
00208
00209
00210 int
00211 Info::
00212 populate(FILE *f, int &failedLine)
00213 {
00214
00215 if(!f)
00216 return -1;
00217
00218 using namespace std;
00219
00220 failedLine=0;
00221
00222 char buffer[10000];
00223
00224 errno = 0;
00225
00226 string filename;
00227
00228
00229 while(fgets(buffer, sizeof(buffer)-1, f))
00230 {
00231 ++failedLine;
00232
00233 buffer[ strlen(buffer)-1] = 0;
00234
00235
00236 if(buffer[0] == '+')
00237 {
00238 filename = buffer+1;
00239
00240 directories_.insert( FileName(filename).dirname() );
00241
00242 size_t sep = filename.find_last_of("/\\");
00243
00244 if(sep >= filename.size())
00245 files_.insert( pair<string,string>(filename,filename));
00246 else
00247 {
00248 pair<string,string> entry;
00249
00250 entry.second = filename;
00251 entry.first = filename.substr(sep+1, filename.size() - sep - 1);
00252
00253 files_.insert(entry);
00254
00255
00256
00257
00258 }
00259 }
00260 else
00261 if(buffer[0] == '-')
00262 {
00263
00264 if( populateSymbol(filename, buffer+1) )
00265 return -2;
00266 }
00267
00268 }
00269
00270 if(errno)
00271 return -1;
00272
00273 return 0;
00274 }
00275
00276
00277 void
00278 Info::
00279 findMatchingFiles(string const &fileNodeName, vector<string> &output) const
00280 {
00281 pair<FilesMap::const_iterator, FilesMap::const_iterator> range;
00282
00283 range = files_.equal_range(fileNodeName);
00284
00285 while(range.first != range.second)
00286 {
00287 output.push_back(range.first->second);
00288 ++range.first;
00289 }
00290
00291
00292 }
00293
00294 void
00295 Info::
00296 findRelativeFiles(string const &fileNodeName, vector<string> &output) const
00297 {
00298
00299 CXXTLS_FOREACH(FileName cur, directories_)
00300 {
00301 cur += fileNodeName;
00302
00303
00304 if(cur.exists())
00305 {
00306 output.push_back(cur);
00307 }
00308 }
00309
00310
00311 }
00312
00313
00314 void
00315 Info::
00316 findMatchingMembers(string const &memberName, vector<SymbolInfo const*> &output, bool caseSensitive) const
00317 {
00318 if(caseSensitive)
00319 {
00320 pair<MembersMap::const_iterator, MembersMap::const_iterator> range;
00321
00322 range = members_.equal_range(memberName);
00323
00324 while(range.first != range.second)
00325 {
00326 SymbolInfo const* cur = range.first->second;
00327
00328 if(cur->line_ != 0)
00329 {
00330 output.push_back(cur);
00331 }
00332 ++range.first;
00333 }
00334 }
00335 else
00336 {
00337
00338
00339 pair<MembersMap::const_iterator, MembersMap::const_iterator> range;
00340
00341 range.first = members_.begin();
00342 range.second = members_.end();
00343
00344 while(range.first != range.second)
00345 {
00346 if(StrTool::compareInsensitive(memberName, range.first->first) == 0)
00347 {
00348 SymbolInfo const* cur = range.first->second;
00349
00350 if(cur->line_ != 0)
00351 {
00352 output.push_back(cur);
00353 }
00354 }
00355
00356 ++range.first;
00357 }
00358
00359 }
00360 }
00361
00362
00363 std::ostream &
00364 operator<< (std::ostream &s, Info const &me)
00365 {
00366 SymbolInfo::const_iterator first= me.symbols_.children_.begin(),
00367 last = me.symbols_.children_.end();
00368
00369 while(first != last)
00370 {
00371 s << first->second << std::endl;
00372
00373 ++first;
00374 }
00375
00376
00377 return s;
00378 }
00379
00380 int
00381 Info::
00382 populateSymbol(std::string const &filename, std::string const &info)
00383 {
00384 using namespace std;
00385
00386 string type;
00387 string name;
00388 string operatorTypeOrLineNumber;
00389 string lineNumber;
00390 int line=0;
00391
00392 BIscan::stream(info) >> type >> name >> operatorTypeOrLineNumber >> lineNumber;
00393
00394 if(lineNumber.empty())
00395 {
00396 BIscan::stream(operatorTypeOrLineNumber) >> line;
00397 }
00398 else
00399 {
00400 char c = operatorTypeOrLineNumber[0];
00401
00402 if( isalnum(c) || c == '_')
00403 {
00404 name += ' ';
00405 }
00406
00407 name += operatorTypeOrLineNumber;
00408
00409 BIscan::stream(lineNumber) >> line;
00410 }
00411
00412
00413 vector<string> component;
00414
00415 size_t components = StrTool::splitOnString(name, component, "::");
00416
00417 if(components == 0)
00418 {
00419 return -1;
00420 }
00421
00422
00423
00424 SymbolInfo *parent = &symbols_;
00425
00426 string fullParentName;
00427
00428 for(size_t i = 0; i < components-1; ++i)
00429 {
00430 string const &compName = component[i];
00431
00432 fullParentName += "::";
00433 fullParentName += compName;
00434
00435 SymbolInfo parentInfo(fullParentName, compName, "namespace", "", 0);
00436
00437
00438
00439
00440 SymbolInfo::iterator where;
00441
00442 where = parent->children_.find(compName);
00443
00444 if(where != parent->children_.end())
00445 {
00446
00447
00448 parent = &where->second;
00449
00450 }
00451 else
00452 {
00453 where = parent->children_.insert( SymbolInfo::Children::value_type(compName, parentInfo));
00454
00455 parent = &where->second;
00456
00457 members_.insert( MembersMap::value_type( compName, &where->second ) );
00458
00459
00460 }
00461
00462 }
00463
00464
00465
00466 if(!type.empty() && type[0] == 'n')
00467 {
00468
00469
00470
00471
00472
00473 SymbolInfo::iterator where = parent->children_.find(component.back());
00474
00475 while(where != parent->children_.end())
00476 {
00477 if(where->first != component.back())
00478 break;
00479
00480 if(where->second.typeId_ == SymbolInfo::Namespace
00481 )
00482 {
00483
00484
00485
00486 return 0;
00487 }
00488
00489 ++where;
00490
00491 }
00492
00493
00494 }
00495
00496
00497
00498
00499 SymbolInfo::Children::iterator where;
00500
00501 where =
00502 parent->children_.insert( SymbolInfo::Children::value_type(component.back(),
00503 SymbolInfo(name,
00504 component.back(),
00505 type,
00506 filename,
00507 line
00508 )
00509 )
00510 );
00511
00512 members_.insert( MembersMap::value_type( component.back(), &where->second ) );
00513
00514
00515 return 0;
00516 }
00517
00518
00519
00520 }
00521 }