127 #include "RConfigure.h"
147 #define BUF_SIZE 1024 // must be smaller than/equal to fgLineBufSize in Getline.cxx and
149 #define IfDebug(x) if(gDebug==TTabCom::kDebug) x
152 const char kDelim =
';';
154 const char kDelim =
':';
163 TTabCom *gTabCom = 0;
175 fPrevInterpMarker(0),
185 fVarIsPointer(kFALSE),
214 void TTabCom::ClearClasses()
226 void TTabCom::ClearCppDirectives()
230 fpDirectives->Delete(0);
238 void TTabCom::ClearEnvVars()
242 fpEnvVars->Delete(0);
250 void TTabCom::ClearFiles()
263 void TTabCom::ClearGlobalFunctions()
271 void TTabCom::ClearGlobals()
278 void TTabCom::ClearPragmas()
282 fpPragmas->Delete(0);
290 void TTabCom::ClearSysIncFiles()
294 fpSysIncFiles->Delete(0);
295 delete fpSysIncFiles;
302 void TTabCom::ClearUsers()
315 void TTabCom::ClearAll()
318 ClearCppDirectives();
321 ClearGlobalFunctions();
331 void TTabCom::RehashClasses()
340 void TTabCom::RehashCppDirectives()
342 ClearCppDirectives();
343 GetListOfCppDirectives();
349 void TTabCom::RehashEnvVars()
358 void TTabCom::RehashFiles()
366 void TTabCom::RehashGlobalFunctions()
368 GetListOfGlobalFunctions();
374 void TTabCom::RehashGlobals()
383 void TTabCom::RehashPragmas()
392 void TTabCom::RehashSysIncFiles()
395 GetListOfSysIncFiles();
401 void TTabCom::RehashUsers()
411 void TTabCom::RehashAll()
414 RehashCppDirectives();
417 RehashGlobalFunctions();
427 const TSeqCollection *TTabCom::GetListOfClasses()
430 fpClasses =
new THashList;
432 THashList* entries = gInterpreter->GetMapfile()->GetTable();
434 while (
const auto key = next()) {
436 const char* className = key->GetName();
437 if (!strncmp(className,
"Library.", 8))
440 if (!strstr(className,
".h"))
441 fpClasses->Add(
new TObjString(className));
447 while (
const char* className = TClassTable::Next()) {
448 if (!fpClasses->FindObject(className)) {
449 fpClasses->Add(
new TObjString(className));
454 if (fPrevInterpMarker != gInterpreter->GetInterpreterStateMarker()) {
455 ClassInfo_t* ci = gInterpreter->ClassInfo_Factory(kFALSE );
456 while (gInterpreter->ClassInfo_Next(ci)) {
457 const char* className = gInterpreter->ClassInfo_FullName(ci);
458 if (strstr(className,
"(anonymous)"))
460 if (!fpClasses->FindObject(className)) {
461 fpClasses->Add(
new TObjString(className));
464 gInterpreter->ClassInfo_Delete(ci);
473 const TSeqCollection *TTabCom::GetListOfCppDirectives()
476 fpDirectives =
new TContainer;
478 fpDirectives->Add(
new TObjString(
"if"));
479 fpDirectives->Add(
new TObjString(
"ifdef"));
480 fpDirectives->Add(
new TObjString(
"ifndef"));
481 fpDirectives->Add(
new TObjString(
"elif"));
482 fpDirectives->Add(
new TObjString(
"else"));
483 fpDirectives->Add(
new TObjString(
"endif"));
484 fpDirectives->Add(
new TObjString(
"include"));
485 fpDirectives->Add(
new TObjString(
"define"));
486 fpDirectives->Add(
new TObjString(
"undef"));
487 fpDirectives->Add(
new TObjString(
"line"));
488 fpDirectives->Add(
new TObjString(
"error"));
489 fpDirectives->Add(
new TObjString(
"pragma"));
499 const TSeqCollection *TTabCom::GetListOfFilesInPath(
const char path[])
501 static TString previousPath;
503 if (path && fpFiles && strcmp(path, previousPath) == 0) {
508 fpFiles = NewListOfFilesInPath(path);
518 const TSeqCollection *TTabCom::GetListOfEnvVars()
521 TString outf =
".TTabCom-";
522 FILE *fout = gSystem->TempFileName(outf);
528 char *env = gSystem->Which(gSystem->Getenv(
"PATH"),
"env", kExecutePermission);
539 gSystem->Exec(cmd.Data());
542 std::ifstream file1(outf);
544 Error(
"TTabCom::GetListOfEnvVars",
"could not open file \"%s\"",
546 gSystem->Unlink(outf);
550 fpEnvVars =
new TContainer;
556 line.ReadToDelim(file1,
'=');
557 file1.ignore(32000,
'\n');
558 fpEnvVars->Add(
new TObjString(line.Data()));
562 gSystem->Unlink(outf);
571 const TSeqCollection *TTabCom::GetListOfGlobals()
573 return (TSeqCollection*)gROOT->GetListOfGlobals(
true);
579 TCollection *TTabCom::GetListOfGlobalFunctions()
581 return gROOT->GetListOfGlobalFunctions(
true);
587 const TSeqCollection *TTabCom::GetListOfPragmas()
590 fpPragmas =
new TContainer;
592 fpPragmas->Add(
new TObjString(
"ANSI "));
593 fpPragmas->Add(
new TObjString(
"autocompile "));
594 fpPragmas->Add(
new TObjString(
"bytecode "));
595 fpPragmas->Add(
new TObjString(
"compile "));
596 fpPragmas->Add(
new TObjString(
"endbytecode "));
597 fpPragmas->Add(
new TObjString(
"endcompile "));
598 fpPragmas->Add(
new TObjString(
"include "));
599 fpPragmas->Add(
new TObjString(
"includepath "));
600 fpPragmas->Add(
new TObjString(
"K&R "));
601 fpPragmas->Add(
new TObjString(
"link "));
602 fpPragmas->Add(
new TObjString(
"preprocess "));
603 fpPragmas->Add(
new TObjString(
"preprocessor "));
604 fpPragmas->Add(
new TObjString(
"security level"));
618 const TSeqCollection *TTabCom::GetListOfSysIncFiles()
620 if (!fpSysIncFiles) {
621 fpSysIncFiles = NewListOfFilesInPath(GetSysIncludePath());
624 return fpSysIncFiles;
630 const TSeqCollection *TTabCom::GetListOfUsers()
633 fpUsers =
new TContainer;
635 std::ifstream passwd;
638 passwd.open(
"/etc/passwd");
640 user.ReadToDelim(passwd,
':');
641 fpUsers->Add(
new TObjString(user));
642 passwd.ignore(32000,
'\n');
676 Char_t TTabCom::AllAgreeOnChar(
int i,
const TSeqCollection * pList,
677 Int_t & nGoodStrings)
686 Bool_t atLeast1GoodString;
690 atLeast1GoodString = kFALSE;
694 if ((pObj = next())) {
696 isGood = !ExcludedByFignore(s);
698 atLeast1GoodString = kTRUE;
706 if (pObj) s = pObj->GetName();
717 if ((pObj = next())) {
719 isGood = !ExcludedByFignore(s);
725 while (((
int) strlen(s) >= i && s[i] == ch0) ||
726 (atLeast1GoodString && !isGood));
741 void TTabCom::AppendListOfFilesInDirectory(
const char dirName[],
742 TSeqCollection * pList)
744 assert(dirName != 0);
748 void *dir = gSystem->OpenDirectory(dirName);
759 while ((tmp_ptr = gSystem->GetDirEntry(dir))) {
763 if (fileName ==
"." || fileName ==
"..")
767 pList->Add(
new TObjString(dirName + fileName.Prepend(
"/")));
776 gSystem->FreeDirectory(dir);
790 TString TTabCom::DetermineClass(
const char varName[])
805 assert(varName != 0);
806 IfDebug(std::cerr <<
"DetermineClass(\"" << varName <<
"\");" << std::endl);
808 TString outf =
".TTabCom-";
809 FILE *fout = gSystem->TempFileName(outf);
810 if (!fout)
return "";
816 gROOT->ProcessLineSync(cmd.Data());
818 cmd =
"gROOT->ProcessLine(\"";
822 gROOT->ProcessLineSync(cmd.Data());
826 gROOT->ProcessLineSync(
".>");
832 std::ifstream file1(outf);
834 Error(
"TTabCom::DetermineClass",
"could not open file \"%s\"",
840 if (!file1 || c <= 0 || c !=
'(') {
841 Error(
"TTabCom::DetermineClass",
"variable \"%s\" not defined?",
845 IfDebug(std::cerr << (
char) c << std::flush);
851 if (type ==
"const" || type ==
"class") {
855 IfDebug(std::cerr << (
char) c << std::flush);
859 type.ReadToDelim(file1,
')');
860 IfDebug(std::cerr << type << std::endl);
864 if (type.EndsWith(
"const"))
865 type.Remove(type.Length() - 5);
870 gSystem->Unlink(outf);
883 Bool_t TTabCom::ExcludedByFignore(TString s)
885 const char *fignore = gEnv->GetValue(
"TabCom.FileIgnore", (
char *) 0);
891 std::istringstream endings((
char *) fignore);
893 std::istrstream endings((
char *) fignore);
897 ending.ReadToDelim(endings, kDelim);
899 while (!ending.IsNull()) {
900 if (s.EndsWith(ending))
903 ending.ReadToDelim(endings, kDelim);
919 TString TTabCom::GetSysIncludePath()
960 TString outf =
".TTabCom-";
961 FILE *fout = gSystem->TempFileName(outf);
962 if (!fout)
return "";
963 gCling->DisplayIncludePath(fout);
967 std::ifstream file1(outf);
969 Error(
"TTabCom::GetSysIncludePath",
"could not open file \"%s\"",
971 gSystem->Unlink(outf);
981 if (!token.IsNull()) {
982 if (path.Length() > 0)
984 path.Append(token.Data() + 2);
990 gSystem->Unlink(outf);
996 TString sCINTSYSDIR(
"$ROOTSYS/cint");
998 TString sCINTSYSDIR(CINTINCDIR);
1000 path.Append(
":" + sCINTSYSDIR +
"/include");
1004 path.Append(
":/usr/include");
1020 Bool_t TTabCom::IsDirectory(
const char fileName[])
1023 if (!gSystem->GetPathInfo(fileName, stat))
1024 return R_ISDIR(stat.fMode);
1040 TSeqCollection *TTabCom::NewListOfFilesInPath(
const char path1[])
1043 if (!path1[0]) path1 =
".";
1045 TContainer *pList =
new TContainer;
1047 std::istringstream path((
char *) path1);
1049 std::istrstream path((
char *) path1);
1055 dirName.ReadToDelim(path, kDelim);
1056 if (dirName.IsNull())
1059 IfDebug(std::cerr <<
"NewListOfFilesInPath(): dirName = " << dirName <<
1062 AppendListOfFilesInDirectory(dirName, pList);
1079 Bool_t TTabCom::PathIsSpecifiedInFileName(
const TString & fileName)
1081 char c1 = (fileName.Length() > 0) ? fileName[0] : 0;
1082 return c1 ==
'/' || c1 ==
'~' || c1 ==
'$' || fileName.BeginsWith(
"./")
1083 || fileName.BeginsWith(
"../");
1099 void TTabCom::NoMsg(Int_t errorLevel)
1114 const Int_t kNotDefined = -2;
1115 static Int_t old_level = kNotDefined;
1119 if (old_level == kNotDefined) {
1120 std::cerr <<
"NoMsg(): ERROR 1. old_level==" << old_level << std::endl;
1124 gErrorIgnoreLevel = old_level;
1125 old_level = kNotDefined;
1128 if (old_level != kNotDefined) {
1129 std::cerr <<
"NoMsg(): ERROR 2. old_level==" << old_level << std::endl;
1133 old_level = gErrorIgnoreLevel;
1134 if (gErrorIgnoreLevel <= errorLevel)
1135 gErrorIgnoreLevel = errorLevel + 1;
1154 Int_t TTabCom::Complete(
const TRegexp & re,
1155 const TSeqCollection * pListOfCandidates,
1156 const char appendage[],
1158 TString::ECaseCompare cmp)
1168 IfDebug(std::cerr <<
"TTabCom::Complete() ..." << std::endl);
1170 assert(pListOfCandidates != 0);
1173 const int loc = *fpLoc;
1186 TString s2 = s1(0, loc);
1187 TString s3 = s2(re);
1189 int start = s2.Index(re);
1191 IfDebug(std::cerr <<
" s1: " << s1 << std::endl);
1192 IfDebug(std::cerr <<
" s2: " << s2 << std::endl);
1193 IfDebug(std::cerr <<
" s3: " << s3 << std::endl);
1194 IfDebug(std::cerr <<
"start: " << start << std::endl);
1195 IfDebug(std::cerr << std::endl);
1201 TList listOfMatches;
1202 TList listOfFullPaths;
1203 listOfMatches.SetOwner();
1204 listOfFullPaths.SetOwner();
1208 TIter next_candidate(pListOfCandidates);
1209 TIter next_match(&listOfMatches);
1210 TIter next_fullpath(&listOfFullPaths);
1213 while ((pObj = next_candidate())) {
1215 const char *s4 = pObj->GetName();
1220 const char *s5 = strrchr(s4,
'/');
1228 if ((cmp == TString::kExact) && (strstr(s5, s3) == s5)) {
1230 listOfMatches.Add(
new TObjString(s5));
1231 listOfFullPaths.Add(
new TObjString(s4));
1232 IfDebug(std::cerr <<
"adding " << s5 <<
'\t' << s4 << std::endl);
1233 }
else if (cmp == TString::kIgnoreCase) {
1235 if (ts5.BeginsWith(s3, cmp))
1238 listOfMatches.Add(
new TObjString(s5));
1239 listOfFullPaths.Add(
new TObjString(s4));
1240 IfDebug(std::cerr <<
"adding " << s5 <<
'\t' << s4 << std::endl);
1254 TString partialMatch =
"";
1256 if (nMatches == 0) {
1265 if (nMatches == 1) {
1267 const char *short_name = next_match()->GetName();
1268 const char *full_name = next_fullpath()->GetName();
1270 pObj = pListOfCandidates->FindObject(short_name);
1272 IfDebug(std::cerr << std::endl <<
"class: " << pObj->ClassName() << std::endl);
1273 TString className = pObj->ClassName();
1275 else if (className ==
"TMethod" || className ==
"TFunction") {
1276 TFunction *pFunc = (TFunction *) pObj;
1277 if (0 == pFunc->GetNargs())
1281 }
else if (className ==
"TDataMember") {
1286 CopyMatch(match, short_name, appendage, full_name);
1293 (ch = AllAgreeOnChar(i, &listOfMatches, nGoodStrings));
1295 IfDebug(std::cerr <<
" i=" << i <<
" ch=" << ch << std::endl);
1296 partialMatch.Append(ch);
1303 if (nGoodStrings == 1) {
1307 s = next_match()->GetName();
1308 s0 = next_fullpath()->GetName();
1310 while (ExcludedByFignore(s));
1313 CopyMatch(match, s, appendage, s0);
1315 IfDebug(std::cerr <<
"more than 1 GoodString" << std::endl);
1317 if (partialMatch.Length() > s3.Length())
1320 CopyMatch(match, partialMatch.Data());
1326 IfDebug(std::cerr <<
"printing ambiguous matches" << std::endl);
1327 std::set<std::string> alreadyPrinted;
1328 while ((pObj = next_match())) {
1329 s = pObj->GetName();
1330 if (alreadyPrinted.insert(s).second) {
1332 s0 = next_fullpath()->GetName();
1333 if (!ExcludedByFignore(s) || nGoodStrings == 0) {
1334 if (IsDirectory(s0))
1335 out << s <<
"/" << std::endl;
1337 out << s << std::endl;
1342 if (cmp == TString::kExact || partialMatch.Length() < s3.Length()) {
1348 CopyMatch(match, partialMatch.Data());
1358 int i = strlen(fBuf);
1359 int l = strlen(match) - (loc - start);
1362 if (strlen(fBuf) + strlen(match) + 1 > BUF_SIZE) {
1363 Error(
"TTabCom::Complete",
"buffer overflow");
1368 IfDebug(std::cerr <<
" i=" << i << std::endl);
1369 IfDebug(std::cerr <<
" L=" << l << std::endl);
1370 IfDebug(std::cerr <<
"loc=" << loc << std::endl);
1373 for (; i >= loc; i -= 1) {
1374 fBuf[i + l] = fBuf[i];
1378 strlcpy(fBuf + start, match, BUF_SIZE - start);
1385 if (cmp == TString::kIgnoreCase && pos < 0) {
1405 void TTabCom::CopyMatch(
char dest[],
const char localName[],
1406 const char appendage[],
1407 const char fullName[])
const
1419 assert(localName != 0);
1422 strcpy(dest, localName);
1424 const char *key =
"filename";
1425 const int key_len = strlen(key);
1427 IfDebug(std::cerr <<
"CopyMatch()." << std::endl);
1428 IfDebug(std::cerr <<
"localName: " << (localName ? localName :
"0") <<
1430 IfDebug(std::cerr <<
"appendage: " << (appendage ? appendage :
"0") <<
1432 IfDebug(std::cerr <<
" fullName: " << (fullName ? fullName :
"0") <<
1437 if (appendage && strncmp(appendage, key, key_len) == 0) {
1439 appendage += key_len;
1440 IfDebug(std::cerr <<
"new appendage: " << appendage << std::endl);
1441 if (IsDirectory(fullName)) {
1443 strcpy(dest + strlen(localName),
"/");
1446 strcpy(dest + strlen(localName), appendage);
1450 strcpy(dest + strlen(localName), appendage);
1457 TTabCom::EContext_t TTabCom::DetermineContext()
const
1464 for (
int context = 0; context < kNUM_PAT; ++context) {
1465 pEnd = Matchs(fBuf, *fpLoc, fPat[context], &pStart);
1467 IfDebug(std::cerr << std::endl
1468 <<
"context=" << context <<
" "
1469 <<
"RegExp=" << fRegExp[context]
1471 return EContext_t(context);
1475 return kUNKNOWN_CONTEXT;
1481 TString TTabCom::DeterminePath(
const TString & fileName,
1482 const char defaultPath[])
const
1484 if (PathIsSpecifiedInFileName(fileName)) {
1485 TString path = fileName;
1486 gSystem->ExpandPathName(path);
1487 Int_t end = path.Length()-1;
1488 if (end>0 && path[end]!=
'/' && path[end]!=
'\\') {
1489 path = gSystem->DirName(path);
1494 TString extendedPath;
1495 if (fileName.Contains(
"/")) {
1496 Int_t end = fileName.Length()-1;
1497 if (fileName[end] !=
'/' && fileName[end] !=
'\\') {
1498 newBase = gSystem->DirName(fileName);
1502 extendedPath = ExtendPath(defaultPath, newBase);
1505 extendedPath = defaultPath;
1507 IfDebug(std::cerr << std::endl);
1508 IfDebug(std::cerr <<
" fileName: " << fileName << std::endl);
1509 IfDebug(std::cerr <<
" pathBase: " << newBase << std::endl);
1511 IfDebug(std::cerr <<
" defaultPath: " << defaultPath << std::endl);
1513 IfDebug(std::cerr <<
" defaultPath: " << std::endl);
1515 IfDebug(std::cerr <<
"extendedPath: " << extendedPath << std::endl);
1516 IfDebug(std::cerr << std::endl);
1518 return extendedPath;
1525 TString TTabCom::ExtendPath(
const char originalPath[], TString newBase)
const
1527 if (newBase.BeginsWith(
"/"))
1528 newBase.Remove(TString::kLeading,
'/');
1530 std::stringstream str;
1536 if (originalPath) str << originalPath;
1541 dir.ReadToDelim(str, kDelim);
1544 newPath.Append(dir);
1545 if (!newPath.EndsWith(
"/"))
1546 newPath.Append(
"/");
1547 newPath.Append(newBase);
1548 newPath.Append(kDelim);
1551 return newPath.Strip(TString::kTrailing, kDelim);
1557 Int_t TTabCom::Hook(
char *buf,
int *pLoc, std::ostream& out)
1570 EContext_t context = DetermineContext();
1573 const char dummy[] =
".";
1574 TRegexp re1(context == kUNKNOWN_CONTEXT ? dummy : fRegExp[context]);
1576 TString s2 = s1(0, *fpLoc);
1577 TString s3 = s2(re1);
1580 case kUNKNOWN_CONTEXT:
1581 std::cerr << std::endl <<
"tab completion not implemented for this context" <<
1588 const TSeqCollection *pListOfUsers = GetListOfUsers();
1590 pos = Complete(
"[^~]*$", pListOfUsers,
"/", out);
1595 const TSeqCollection *pEnv = GetListOfEnvVars();
1597 pos = Complete(
"[^$]*$", pEnv,
"", out);
1605 const TString fileName = s3(
"[^ ><]*$");
1606 const TString filePath = DeterminePath(fileName,0);
1607 const TSeqCollection *pListOfFiles =
1608 GetListOfFilesInPath(filePath.Data());
1611 pos = Complete(
"[^ /]*$", pListOfFiles,
"filename ", out);
1620 const TString fileName = s3(
"[^ ]*$");
1621 const TString macroPath =
1622 DeterminePath(fileName, TROOT::GetMacroPath());
1623 const TSeqCollection *pListOfFiles =
1624 GetListOfFilesInPath(macroPath.Data());
1627 pos = Complete(
"[^ /]*$", pListOfFiles,
"filename ", out);
1633 pos = Complete(
"[^ ]*$", GetListOfPragmas(),
"", out);
1636 case kCINT_includeSYS:
1638 TString fileName = s3(
"[^<]*$");
1639 if (PathIsSpecifiedInFileName(fileName) || fileName.Contains(
"/")) {
1640 TString includePath =
1641 DeterminePath(fileName, GetSysIncludePath());
1645 Complete(
"[^</]*$", GetListOfFilesInPath(includePath),
1650 Complete(
"[^</]*$", GetListOfSysIncFiles(),
"filename> ", out);
1654 case kCINT_includePWD:
1656 const TString fileName = s3(
"[^\"]*$");
1657 const TString includePath = DeterminePath(fileName,
".");
1658 const TSeqCollection *pListOfFiles =
1659 GetListOfFilesInPath(includePath.Data());
1662 pos = Complete(
"[^\"/]*$", pListOfFiles,
"filename\" ", out);
1668 pos = Complete(
"[^# ]*$", GetListOfCppDirectives(),
" ", out);
1674 const TString fileName = s3(
"[^\"]*$");
1675 const TString dynamicPath = DeterminePath(fileName, gSystem->GetDynamicPath());
1676 const TSeqCollection *pListOfFiles = GetListOfFilesInPath(dynamicPath);
1679 pos = Complete(
"[^\"/]*$", pListOfFiles,
"filename\");", out);
1685 const TString fileName = s3(
"[^ \"]*$");
1686 const TString filePath = DeterminePath(fileName,
".");
1687 const TSeqCollection *pListOfFiles = GetListOfFilesInPath(filePath.Data());
1689 pos = Complete(
"[^\" /]*$", pListOfFiles,
"filename\"", out);
1693 case kCXX_ScopeMember:
1695 const EContext_t original_context = context;
1699 TString name = s3(
"^[_a-zA-Z][_a-zA-Z0-9]*");
1701 IfDebug(std::cerr << std::endl);
1702 IfDebug(std::cerr <<
"name: " <<
'"' << name <<
'"' << std::endl);
1707 TString partname = s3(
"[_a-zA-Z][_a-zA-Z0-9]*$");
1714 TString prefix =
"";
1716 str.Remove(str.Length() - partname.Length(), partname.Length());
1718 TString sym = str(
"[_a-zA-Z][_a-zA-Z0-9]*::$");
1719 if (sym.Length() == 0)
1721 str.Remove(str.Length() - sym.Length(), sym.Length());
1722 prefix = sym + prefix;
1727 TString preprefix = prefix;
1728 TString sym = prefix(
"[_a-zA-Z][_a-zA-Z0-9]*::$");
1729 preprefix.Remove(preprefix.Length() - sym.Length(), sym.Length());
1731 IfDebug(std::cerr <<
"prefix: " <<
'"' << prefix <<
'"' << std::endl);
1732 IfDebug(std::cerr <<
"preprefix: " <<
'"' << preprefix <<
'"' << std::endl);
1734 TString namesp = prefix;
1735 if (namesp.Length() >= 2)
1736 namesp.Remove(namesp.Length() - 2, 2);
1737 IfDebug(std::cerr <<
"namesp: " <<
'"' << namesp <<
'"' << std::endl);
1740 TryMakeClassFromClassName(namesp);
1742 TContainer *pList =
new TContainer;
1745 const TSeqCollection *tmp = GetListOfClasses();
1749 for (i = 0; i < tmp->GetSize(); i++) {
1750 TString astr = ((TObjString *) tmp->At(i))->String();
1753 if (astr.Contains(TRegexp(rxp))) {
1754 astr.Remove(0, prefix.Length());
1755 TString s = astr(
"^[^: ]*");
1756 TObjString *ostr =
new TObjString(s);
1757 if (!pList->Contains(ostr))
1767 pClass = TryMakeClassFromClassName(preprefix + name);
1769 pList->AddAll(pClass->GetListOfAllPublicMethods(
true));
1770 pList->AddAll(pClass->GetListOfAllPublicDataMembers(
true));
1773 pos = Complete(
"[^: ]*$", pList,
"", out);
1777 if (context != original_context)
1782 case kCXX_DirectMember:
1783 case kCXX_IndirectMember:
1785 const EContext_t original_context = context;
1795 TString name = s1(
"[_a-zA-Z][-_a-zA-Z0-9<>():.]*$");
1797 IfDebug(std::cerr << std::endl);
1798 IfDebug(std::cerr <<
"name: " <<
'"' << name <<
'"' << std::endl);
1801 case kCXX_DirectMember:
1802 pClass = MakeClassFromVarName(name, context);
1804 case kCXX_IndirectMember:
1805 pClass = MakeClassFromVarName(name, context);
1808 Fatal(
"TTabCom::Hook",
"Conext case %d not handled",context);
1816 TContainer *pList =
new TContainer;
1818 pList->AddAll(pClass->GetListOfAllPublicMethods());
1819 pList->AddAll(pClass->GetListOfAllPublicDataMembers());
1822 case kCXX_DirectMember:
1824 int* store_fpLoc = fpLoc;
1825 char* store_fBuf = fBuf;
1826 pos = Complete(
"[^. ]*$", pList,
"(", out);
1828 fpLoc = store_fpLoc;
1830 pos = Complete(
"[^. ]*$", pList,
"(", out, TString::kIgnoreCase);
1834 case kCXX_IndirectMember:
1835 pos = Complete(
"[^> ]*$", pList,
"(", out);
1838 Fatal(
"TTabCom::Hook",
"Conext case %d not handled",context);
1844 if (context != original_context)
1849 case kCXX_ScopeProto:
1851 const EContext_t original_context = context;
1855 TString name = s3(
"^[_a-zA-Z][_a-zA-Z0-9]*");
1858 IfDebug(std::cerr << std::endl);
1859 IfDebug(std::cerr <<
"name: " <<
'"' << name <<
'"' << std::endl);
1864 TString partname = s3(
"[_a-zA-Z][_a-zA-Z0-9]* *($");
1871 TString prefix =
"";
1873 str.Remove(str.Length() - partname.Length(), partname.Length());
1875 TString sym = str(
"[_a-zA-Z][_a-zA-Z0-9]*::$");
1876 if (sym.Length() == 0)
1878 str.Remove(str.Length() - sym.Length(), sym.Length());
1879 prefix = sym + prefix;
1884 TString preprefix = prefix;
1885 TString sym = prefix(
"[_a-zA-Z][_a-zA-Z0-9]*::$");
1886 preprefix.Remove(preprefix.Length() - sym.Length(), sym.Length());
1888 IfDebug(std::cerr <<
"prefix: " <<
'"' << prefix <<
'"' << std::endl);
1889 IfDebug(std::cerr <<
"preprefix: " <<
'"' << preprefix <<
'"' << std::endl);
1891 pClass = MakeClassFromClassName(preprefix + name);
1900 methodName = s3(
"[^:>\\.(]*($");
1902 methodName.Remove(TString::kTrailing,
' ');
1904 IfDebug(std::cerr << methodName << std::endl);
1907 TContainer *pList =
new TContainer;
1908 pList->AddAll(pClass->GetListOfAllPublicMethods());
1911 Bool_t foundOne = kFALSE;
1912 TIter nextMethod(pList);
1914 while ((pMethod = (TMethod *) nextMethod())) {
1915 if (methodName == pMethod->GetName()) {
1917 out << pMethod->GetReturnTypeName()
1918 <<
" " << pMethod->GetName()
1919 << pMethod->GetSignature();
1920 const char *comment = pMethod->GetCommentString();
1921 if (comment && comment[0] !=
'\0') {
1922 out <<
" \t// " << comment;
1939 if (context != original_context)
1944 case kCXX_DirectProto:
1945 case kCXX_IndirectProto:
1947 case kCXX_ConstructorProto:
1949 const EContext_t original_context = context;
1954 if (context == kCXX_NewProto) {
1955 name = s3(
"[_a-zA-Z][_a-zA-Z0-9:]* *($", 3);
1957 name.Remove(TString::kTrailing,
' ');
1960 name = s3(
"^[_a-zA-Z][_a-zA-Z0-9:]*");
1963 IfDebug(std::cerr << std::endl);
1964 IfDebug(std::cerr <<
"name: " <<
'"' << name <<
'"' << std::endl);
1967 TString namerec = s1;
1970 case kCXX_ScopeProto:
1971 pClass = MakeClassFromClassName(name);
1973 case kCXX_DirectProto:
1974 pClass = MakeClassFromVarName(namerec, context);
1976 case kCXX_IndirectProto:
1977 pClass = MakeClassFromVarName(namerec, context);
1980 pClass = MakeClassFromClassName(name);
1982 case kCXX_ConstructorProto:
1983 pClass = MakeClassFromClassName(name);
1986 Fatal(
"TTabCom::Hook",
"Conext case %d not handled",context);
1995 if (context == kCXX_ConstructorProto || context == kCXX_NewProto) {
1997 methodName = name(
"[_a-zA-Z][_a-zA-Z0-9]*$");
2000 methodName = s3(
"[^:>\\.(]*($");
2002 methodName.Remove(TString::kTrailing,
' ');
2004 IfDebug(std::cerr << methodName << std::endl);
2007 TContainer *pList =
new TContainer;
2008 pList->AddAll(pClass->GetListOfAllPublicMethods());
2011 Bool_t foundOne = kFALSE;
2012 TIter nextMethod(pList);
2014 while ((pMethod = (TMethod *) nextMethod())) {
2015 if (methodName == pMethod->GetName()) {
2017 out << pMethod->GetReturnTypeName()
2018 <<
" " << pMethod->GetName()
2019 << pMethod->GetSignature();
2020 const char *comment = pMethod->GetCommentString();
2021 if (comment && comment[0] !=
'\0') {
2022 out <<
" \t// " << comment;
2039 if (context != original_context)
2047 int l2 = s2.Length(), l3 = s3.Length();
2050 if (l2 > l3 && s2[l2 - l3 - 1] ==
'.') {
2051 std::cerr << std::endl <<
2052 "tab completion not implemented for this context" << std::endl;
2056 if (l2 > l3 + 1 && s2(l2 - l3 - 2, 2) ==
"->") {
2057 std::cerr << std::endl <<
2058 "tab completion not implemented for this context" << std::endl;
2062 TContainer *pList =
new TContainer;
2064 const TSeqCollection *pL2 = GetListOfClasses();
2065 if (pL2) pList->AddAll(pL2);
2068 const TSeqCollection *pC1 = GetListOfGlobals();
2069 if (pC1) pList->AddAll(pC1);
2071 TCollection *pC3 = GetListOfGlobalFunctions();
2072 if (pC3) pList->AddAll(pC3);
2074 pos = Complete(
"[_a-zA-Z][_a-zA-Z0-9]*$", pList,
"", out);
2080 case kCXX_GlobalProto:
2083 TString functionName = s3(
"[_a-zA-Z][_a-zA-Z0-9]*");
2084 IfDebug(std::cerr << functionName << std::endl);
2086 TContainer listOfMatchingGlobalFuncs;
2087 TIter nextGlobalFunc(GetListOfGlobalFunctions());
2089 while ((pObj = nextGlobalFunc())) {
2090 if (strcmp(pObj->GetName(), functionName) == 0) {
2091 listOfMatchingGlobalFuncs.Add(pObj);
2095 if (listOfMatchingGlobalFuncs.IsEmpty()) {
2096 std::cerr << std::endl <<
"no such function: " << dblquote(functionName)
2099 TIter next(&listOfMatchingGlobalFuncs);
2100 TFunction *pFunction;
2101 while ((pFunction = (TFunction *) next())) {
2102 out << pFunction->GetReturnTypeName()
2103 <<
" " << pFunction->GetName()
2104 << pFunction->GetSignature()
2119 Fatal(
"TTabCom::Hook",
"Conext case %d not handled",context);
2129 void TTabCom::InitPatterns()
2146 SetPattern(kSYS_UserName,
"~[_a-zA-Z0-9]*$");
2147 SetPattern(kSYS_EnvVar,
"$[_a-zA-Z0-9]*$");
2149 SetPattern(kCINT_stdout,
"; *>>?.*$");
2150 SetPattern(kCINT_stderr,
"; *2>>?.*$");
2151 SetPattern(kCINT_stdin,
"; *<.*$");
2153 SetPattern(kCINT_Edit,
"^ *\\.E .*$");
2154 SetPattern(kCINT_Load,
"^ *\\.L .*$");
2155 SetPattern(kCINT_Exec,
"^ *\\.x +[-0-9_a-zA-Z~$./]*$");
2156 SetPattern(kCINT_EXec,
"^ *\\.X +[-0-9_a-zA-Z~$./]*$");
2158 SetPattern(kCINT_pragma,
"^# *pragma +[_a-zA-Z0-9]*$");
2159 SetPattern(kCINT_includeSYS,
"^# *include *<[^>]*$");
2160 SetPattern(kCINT_includePWD,
"^# *include *\"[^\"]*$");
2162 SetPattern(kCINT_cpp,
"^# *[_a-zA-Z0-9]*$");
2164 SetPattern(kROOT_Load,
"gSystem *-> *Load *( *\"[^\"]*$");
2166 SetPattern(kCXX_NewProto,
"new +[_a-zA-Z][_a-zA-Z0-9:]* *($");
2167 SetPattern(kCXX_ConstructorProto,
2168 "[_a-zA-Z][_a-zA-Z0-9:]* +[_a-zA-Z][_a-zA-Z0-9]* *($");
2169 SetPattern(kCXX_ScopeProto,
2170 "[_a-zA-Z][_a-zA-Z0-9]* *:: *[_a-zA-Z0-9]* *($");
2171 SetPattern(kCXX_DirectProto,
2172 "[_a-zA-Z][_a-zA-Z0-9()]* *\\. *[_a-zA-Z0-9]* *($");
2173 SetPattern(kCXX_IndirectProto,
2174 "[_a-zA-Z][_a-zA-Z0-9()]* *-> *[_a-zA-Z0-9]* *($");
2176 SetPattern(kCXX_ScopeMember,
2177 "[_a-zA-Z][_a-zA-Z0-9]* *:: *[_a-zA-Z0-9]*$");
2178 SetPattern(kCXX_DirectMember,
2179 "[_a-zA-Z][_a-zA-Z0-9()]* *\\. *[_a-zA-Z0-9()]*$");
2181 SetPattern(kCXX_IndirectMember,
2182 "[_a-zA-Z][_a-zA-Z0-9()]* *-> *[_a-zA-Z0-9()]*$");
2184 SetPattern(kSYS_FileName,
"\"[-0-9_a-zA-Z~$./]*$");
2185 SetPattern(kCXX_Global,
"[_a-zA-Z][_a-zA-Z0-9]*$");
2186 SetPattern(kCXX_GlobalProto,
"[_a-zA-Z][_a-zA-Z0-9]* *($");
2196 TClass *TTabCom::MakeClassFromClassName(
const char className[])
const
2201 TClass *pClass = TClass::GetClass(className);
2205 Error(
"TTabCom::MakeClassFromClassName",
"Unknown class \"%s\"", className);
2211 if (pClass->GetListOfAllPublicMethods()->GetSize() == 0 &&
2212 pClass->GetListOfAllPublicDataMembers()->GetSize() == 0) {
2215 Error(
"TTabCom::MakeClassFromClassName",
"class \"%s\" is not defined.", className);
2225 TClass *TTabCom::TryMakeClassFromClassName(
const char className[])
const
2230 TClass *pClass = TClass::GetClass(className);
2245 TClass *TTabCom::MakeClassFromVarName(
const char varName[],
2246 EContext_t & context,
int iter)
2262 Bool_t varName_exists = GetListOfGlobals()->Contains(varName) ||
2263 (gROOT->FindObject(varName) != 0);
2269 if (0) printf(
"varName is [%s] with iteration [%i]\n", varName, iter);
2272 Int_t cut = ParseReverse(varName, strlen(varName));
2275 if (!varName_exists && cut != 0)
2277 TString parentName = varName;
2278 TString memberName = varName;
2281 if (iter > fLastIter) fLastIter = iter;
2283 parentName[cut] = 0;
2284 if (0) printf(
"Parent string is [%s]\n", parentName.Data());
2290 for(Int_t i = cut-1; i>=0; --i) {
2291 switch (parentName[i]) {
2295 parentName = parentName(i+1,cut-i-1);
2307 if (varName[cut] ==
'.') {
2308 memberName = varName+cut+1;
2309 if (0) printf(
"Member/method is [%s]\n", memberName.Data());
2310 EContext_t subcontext = kCXX_DirectMember;
2311 pclass = MakeClassFromVarName(parentName.Data(), subcontext, iter+1);
2313 memberName = varName+cut+2;
2314 if (0) printf(
"Member/method is [%s]\n", memberName.Data());
2315 EContext_t subcontext = kCXX_IndirectMember;
2316 pclass = MakeClassFromVarName(parentName.Data(), subcontext, iter+1);
2319 if (0) printf(
"I got [%s] from MakeClassFromVarName()\n", pclass->GetName());
2323 if (0) printf(
"Variable [%s] exists!\n", parentName.Data());
2326 if (iter == 0)
return pclass;
2328 if (0) printf(
"Trying data member [%s] of class [%s] ...\n",
2329 memberName.Data(), pclass->GetName());
2332 TDataMember *dmptr = 0;
2333 TIter next(pclass->GetListOfAllPublicDataMembers());
2334 while ((dmptr = (TDataMember *) next())) {
2335 if (memberName == dmptr->GetName())
break;
2339 if (0) printf(
"It's a member!\n");
2341 TString returnName = dmptr->GetTypeName();
2345 TClass *mclass = TClass::GetClass(returnName.Data());
2352 char *parentesis_ptr = (
char*)strrchr(memberName.Data(),
'(');
2353 if (parentesis_ptr) *parentesis_ptr = 0;
2356 if (0) printf(
"Trying method [%s] of class [%s] ...\n",
2357 memberName.Data(), pclass->GetName());
2361 const TList *mlist = pclass->GetListOfAllPublicMethods();
2363 while ((mptr = (TMethod *) next())) {
2364 if (strcmp(memberName.Data(),mptr->GetName())==0)
break;
2368 TString returnName = mptr->GetReturnTypeName();
2370 if (0) printf(
"It's a method called [%s] with return type [%s]\n",
2371 memberName.Data(), returnName.Data());
2374 if (returnName[returnName.Length()-1] ==
'*')
2376 returnName[returnName.Length()-1] = 0;
2377 fVarIsPointer = kTRUE;
2381 fVarIsPointer = kFALSE;
2384 TClass *mclass = TClass::GetClass(returnName.Data());
2396 if (!varName_exists) {
2397 std::cerr << std::endl <<
"variable " << dblquote(varName) <<
" not defined."
2411 TString className = DetermineClass(varName);
2413 if (className.IsNull() || className ==
"*") {
2417 std::cerr << std::endl <<
"problem determining class of " << dblquote(varName)
2422 fVarIsPointer = className[className.Length() - 1] ==
'*';
2426 if (fVarIsPointer || className[className.Length() - 1] ==
'&')
2427 className[className.Length()-1] = 0;
2439 if (fVarIsPointer &&
2440 (context == kCXX_DirectMember || context == kCXX_DirectProto)) {
2449 case kCXX_DirectMember:
2450 context = kCXX_IndirectMember;
2452 case kCXX_DirectProto:
2453 context = kCXX_IndirectProto;
2456 Fatal(
"TTabCom::MakeClassFromVarName",
"Conext case %d not handled",context);
2462 for (i = *fpLoc; fBuf[i] !=
'.'; i -= 1) {
2465 for (i = strlen(fBuf); i >= loc; i -= 1) {
2466 fBuf[i + 1] = fBuf[i];
2469 fBuf[loc + 1] =
'>';
2473 std::cerr << std::endl << dblquote(varName) <<
2474 " is of pointer type. Use this operator: ->" << std::endl;
2478 if (context == kCXX_IndirectMember || context == kCXX_IndirectProto) {
2479 if (fVarIsPointer) {
2483 if (className[className.Length() - 1] ==
'*') {
2484 std::cerr << std::endl <<
"can't handle pointers to pointers." << std::endl;
2496 case kCXX_IndirectMember:
2497 context = kCXX_DirectMember;
2499 case kCXX_IndirectProto:
2500 context = kCXX_DirectProto;
2503 Fatal(
"TTabCom::MakeClassFromVarName",
"Conext case %d not handled",context);
2509 for (i = *fpLoc; fBuf[i - 1] !=
'-' && fBuf[i] !=
'>'; i -= 1) {
2512 int len = strlen(fBuf);
2513 for (; i < len; i += 1) {
2514 fBuf[i] = fBuf[i + 1];
2519 std::cerr << std::endl << dblquote(varName) <<
2520 " is not of pointer type. Use this operator: ." << std::endl;
2525 className.Strip(TString::kBoth);
2527 return TClass::GetClass(className);
2533 void TTabCom::SetPattern(EContext_t handle,
const char regexp[])
2536 if (handle >= kNUM_PAT) {
2537 std::cerr << std::endl
2539 << (int) handle <<
" >= kNUM_PAT=" << (
int) kNUM_PAT << std::endl;
2543 fRegExp[handle] = regexp;
2544 Makepat(regexp, fPat[handle], MAX_LEN_PAT);
2555 int TTabCom::ParseReverse(const
char *var_str,
int start)
2558 if (start > (
int)strlen(var_str)) start = strlen(var_str);
2560 for (
int i = start; i > 0; i--)
2562 if (var_str[i] ==
'.')
return i;
2563 if (var_str[i] ==
'>' && i > 0 && var_str[i-1] ==
'-')
return i-1;