etagsdb.cxx
Go to the documentation of this file.00001
00002
00003
00004
00005 #include <portable_io.h>
00006 #include <string.h>
00007 #include <stdlib.h>
00008
00012
00013 #include <cxxtls/etagsdb.h>
00014
00015 #ifdef _AIX
00016 #include <strings.h>
00017 #endif
00018
00019 #if !defined(_MSC_VER)
00020 #define stricmp strcasecmp
00021 #endif
00022
00023 extern "C"
00024 {
00025 typedef int (*compare_func_t)(char const *l, char const *r);
00026 };
00027
00028 namespace cxxtls
00029 {
00030
00031
00032 EtagsDB::
00033 EtagsDB(std::string filename)
00034 {
00035 filename_ = filename;
00036
00037 file_ = fopen(filename.c_str(), "rb");
00038
00039 }
00040
00041 EtagsDB::
00042 ~EtagsDB()
00043 {
00044 if(file_)
00045 fclose(file_);
00046 }
00047
00048
00049 bool
00050 EtagsDB::
00051 find_first(std::string const &symbol,
00052 std::string *foundFile,
00053 int *foundLine,
00054 std::string *sourceText,
00055 bool case_sensitive
00056 )
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 {
00070
00071 *foundLine = 0;
00072 *foundFile = "";
00073
00074 if(file_ == 0)
00075 return false;
00076
00077 fseek(file_, 0, SEEK_SET);
00078
00079 case_sensitive_ = case_sensitive;
00080
00081 symbol_ = symbol;
00082
00083 return find_next(foundFile, foundLine, sourceText);
00084
00085 }
00086
00087 #define issym(c) ( (c >= 'a' && c <= 'z') || \
00088 (c >= 'A' && c <= 'Z') || \
00089 (c >= '0' && c <= '9') || \
00090 c == ':' || \
00091 c == '_' || \
00092 c == '~' \
00093 )
00094
00095 int
00096 EtagsDB::
00097 searchFor(std::string const &symbol,
00098 std::string *foundFile,
00099 int *foundLine,
00100 std::string *sourceText
00101 )
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 {
00113
00114 char line[5000];
00115 char leader[5000];
00116 char *ptr;
00117 char tagName[5000];
00118 char definitionalLine[5000];
00119 char *scan;
00120
00121 int symLength;
00122 int tagLength;
00123
00124 tagName[0] = 0;
00125 definitionalLine[0] = 0;
00126
00127 if(file_ == 0) return 2;
00128
00129 if(0 == fgets(line, 5000, file_) )
00130 {
00131 most_recent_file_[0] = 0;
00132 return 2;
00133 }
00134
00135 if(line[0] == 0x0c)
00136 {
00137
00138 most_recent_file_[0] = 0;
00139
00140 if(0 == fgets(line, sizeof(line), file_) )
00141 {
00142 return 2;
00143 }
00144
00145 sscanf(line, "%[^,\n]", most_recent_file_);
00146
00147 return 0;
00148
00149 }
00150
00151 for(scan = line, ptr=leader;
00152 *scan != 0 && *scan < 0x7f;
00153 *ptr++ = *scan++
00154 );
00155
00156 *ptr = 0;
00157
00158 ++scan;
00159
00160 if( *scan > '9' )
00161 {
00162
00163 for(ptr = tagName; *scan >= ' '; *ptr++ = *scan++);
00164
00165 *ptr = 0;
00166
00167 ++scan;
00168
00169
00170
00171 for(ptr = definitionalLine; *scan >= ' '; *ptr++ = *scan++);
00172
00173 *ptr = 0;
00174
00175 }
00176 else
00177 {
00178
00179 for(ptr = definitionalLine;
00180 *scan >= ' ' &&
00181 size_t(ptr-definitionalLine) < size_t(sizeof(definitionalLine)-1);
00182 *ptr++ = *scan++);
00183
00184 if( size_t(ptr - definitionalLine) >= size_t(sizeof(definitionalLine)-1) )
00185 {
00186 return 0;
00187 }
00188
00189 *ptr = 0;
00190
00191 ++scan;
00192
00193 for(ptr = tagName;
00194 *scan >= ' ' &&
00195 size_t(ptr-tagName) < size_t(sizeof(tagName)-1);
00196 *ptr++ = *scan++);
00197
00198 *ptr = 0;
00199
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 if(tagName[0] == 0)
00212 {
00213
00214 for(scan=leader + strlen(leader);
00215 scan > leader && !issym(scan[-1]);
00216 --scan
00217 );
00218
00219 while(scan > leader && issym(scan[-1]))
00220 {
00221 --scan;
00222 }
00223
00224 for(ptr = tagName; issym(*scan); *ptr++ = *scan++);
00225
00226
00227 *ptr = 0;
00228
00229 }
00230
00231
00232 compare_func_t compare_func;
00233
00234 if(!case_sensitive_)
00235 compare_func = compare_func_t(stricmp);
00236 else
00237 compare_func = compare_func_t(strcmp);
00238
00239
00240
00241 if(symbol[0] == 0 || (*compare_func)(tagName, symbol.c_str()) == 0)
00242 {
00243 *foundFile = most_recent_file_;
00244
00245 *sourceText = leader;
00246
00247 *foundLine = atoi(definitionalLine);
00248 return 1;
00249 }
00250
00251 {
00252
00253
00254
00255
00256
00257 tagLength = strlen(tagName);
00258 symLength = strlen(symbol.c_str());
00259
00260 bool e1 = tagLength > symLength;
00261
00262 bool e2 = 0 == (*compare_func)(tagName + (tagLength - symLength),
00263 symbol.c_str());
00264
00265 bool e3 = tagName[tagLength - symLength -1] == ':';
00266
00267 if( e1 && e2 && e3 )
00268 {
00269 *foundFile = most_recent_file_;
00270 *sourceText= leader;
00271 *foundLine = atoi(definitionalLine);
00272 return 1;
00273 }
00274 }
00275
00276 return 0;
00277
00278 }
00279
00280 bool
00281 EtagsDB::
00282 find_next(std::string *foundFile,
00283 int *foundLine,
00284 std::string *sourceText
00285 )
00286 {
00287 int rc = 0;
00288
00289 while(rc == 0)
00290 {
00291 rc = searchFor(symbol_, foundFile, foundLine, sourceText);
00292
00293 }
00294
00295 if(rc == 1)
00296 {
00297 return true;
00298 }
00299
00300 return false;
00301 }
00302
00303 EtagsDB::
00304 EtagsDB()
00305 {
00306 file_ = 0;
00307 }
00308
00309 bool
00310 EtagsDB::
00311 set_tags_file(std::string tags_file_name)
00312 {
00313 if(file_)
00314 {
00315 fclose(file_);
00316 }
00317
00318 filename_ = tags_file_name;
00319
00320 file_ = fopen(tags_file_name.c_str(), "rb");
00321
00322 return file_ == 0;
00323 }
00324
00325 int
00326 EtagsDB::
00327 matching_files(std::string relpath, std::list<std::string> *matches) const
00328 {
00329 if(relpath.size() &&
00330 (relpath[0] == '/' ||
00331 ( (relpath.size() > 2) && (relpath[1] == ':' ) )
00332 )
00333 )
00334 {
00335 matches->push_back(relpath);
00336 return 1;
00337 }
00338
00339 if(file_ == 0)
00340 return 0;
00341
00342 fseek(file_, 0, SEEK_SET);
00343
00344 char line[5000];
00345
00346 int count=0;
00347
00348
00349 for(;;)
00350 {
00351
00352 if(0 == fgets(line, 5000, file_) )
00353 {
00354
00355
00356 return count;
00357 }
00358
00359 if(line[0] == 0x0c)
00360 {
00361
00362 if(0 == fgets(line, sizeof(line), file_) )
00363 {
00364
00365
00366 return count;
00367 }
00368
00369 char filename[5000];
00370
00371 sscanf(line, "%[^,\n]", filename);
00372
00373 std::string whole(filename);
00374
00375 size_t rel_len = relpath.size();
00376 size_t whole_len = whole.size();
00377
00378 if(rel_len == 0)
00379 {
00380 ++count;
00381 matches->push_back(whole);
00382 }
00383 else
00384 if(whole_len >= rel_len)
00385 {
00386 size_t offset = whole_len - rel_len;
00387
00388 std::string tail = whole.substr(offset, whole_len);
00389
00390 if(tail == relpath)
00391 {
00392 if(offset == 0 || whole[offset-1] == '/' || whole[offset-1] == '\\')
00393 {
00394 ++count;
00395 matches->push_back(whole);
00396 }
00397
00398 }
00399
00400 }
00401
00402
00403 }
00404 }
00405
00406
00407 }
00408
00409 }