Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TTabCom.cxx
Go to the documentation of this file.
1// @(#)root/rint:$Id$
2// Author: Christian Lacunza <lacunza@cdfsg6.lbl.gov> 27/04/99
3
4// Modified by Artur Szostak <artur@alice.phy.uct.ac.za> : 1 June 2003
5// Added support for namespaces.
6
7/*************************************************************************
8 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
9 * All rights reserved. *
10 * *
11 * For the licensing terms see $ROOTSYS/LICENSE. *
12 * For the list of contributors see $ROOTSYS/README/CREDITS. *
13 *************************************************************************/
14
15////////////////////////////////////////////////////////////////////////////
16// //
17// TTabCom //
18// //
19// This class performs basic tab completion. //
20// You should be able to hit [TAB] to complete a partially typed: //
21// //
22// username //
23// environment variable //
24// preprocessor directive //
25// pragma //
26// filename (with a context-sensitive path) //
27// public member function or data member (including base classes) //
28// global variable, function, or class name //
29// //
30// Also, something like //
31// //
32// someObject->Func([TAB] //
33// someObject.Func([TAB] //
34// someClass::Func([TAB] //
35// someClass var([TAB] //
36// new someClass([TAB] //
37// //
38// will print a list of prototypes for the indicated //
39// method or constructor. //
40// //
41// Current limitations and bugs: //
42// //
43// 1. you can only use one member access operator at a time. //
44// eg, this will work: gROOT->GetListOfG[TAB] //
45// but this will not: gROOT->GetListOfGlobals()->Conta[TAB] //
46// //
47// 2. nothing is guaranteed to work on windows //
48// (for one thing, /bin/env and /etc/passwd are hardcoded) //
49// //
50// 3. CINT shortcut #2 is deliberately not supported. //
51// (using "operator.()" instead of "operator->()") //
52// //
53// 4. most identifiers (including C++ identifiers, usernames, //
54// environment variables, etc) //
55// are restriceted to this character set: [_a-zA-Z0-9] //
56// therefore, you won't be able to complete things like //
57// //
58// operator new //
59// operator+ //
60// etc //
61// //
62// 5. ~whatever[TAB] always tries to complete a username. //
63// use whitespace (~ whatever[TAB]) if you want to complete a global //
64// identifier. //
65// //
66// 6. CINT shortcut #3 is not supported when trying to complete //
67// the name of a global object. (it is supported when trying to //
68// complete a member of a global object) //
69// //
70// 7. the list of #pragma's is hardcoded //
71// (ie not obtained from the interpreter at runtime) //
72// ==> user-defined #pragma's will not be recognized //
73// //
74// 8. the system include directories are also hardcoded //
75// because i don't know how to get them from the interpreter. //
76// fons, maybe they should be #ifdef'd for the different sytems? //
77// //
78// 9. the TabCom.FileIgnore resource is always applied, even if you //
79// are not trying to complete a filename. //
80// //
81// 10. anything in quotes is assumed to be a filename //
82// so (among other things) you can't complete a quoted class name: //
83// eg, TClass class1( "TDict[TAB] //
84// this won't work... looks for a file in pwd starting with TDict //
85// //
86// 11. the prototypes tend to omit the word "const" a lot. //
87// this is a problem with ROOT or CINT. //
88// //
89// 12. when listing ambiguous matches, only one column is used, //
90// even if there are many completions. //
91// //
92// 13. anonymous objects are not currently identified //
93// so, for example, //
94// //
95// root> printf( TString([TAB //
96// //
97// gives an error message instead of listing TString's constructors. //
98// (this could be fixed) //
99// //
100// 14. the routine that adds the "appendage" isn't smart enough to know //
101// if it's already there: //
102// //
103// root> TCanvas::Update() //
104// press [TAB] here ^ //
105// root> TCanvas::Update()() //
106// (this could be fixed) //
107// //
108// 15. the appendage is only applied if there is exactly 1 match. //
109// eg, this //
110// //
111// root> G__at[TAB] //
112// root> G__ateval //
113// //
114// happens instead of this //
115// //
116// root> G__at[TAB] //
117// root> G__ateval( //
118// //
119// because there are several overloaded versions of G__ateval(). //
120// (this could be fixed) //
121// //
122////////////////////////////////////////////////////////////////////////////
123
124#include <cstdio>
125#include <cassert>
126#include <set>
127
128#include "RConfigure.h"
129#include "TTabCom.h"
130#include "TClass.h"
131#include "TClassTable.h"
132#include "TDataMember.h"
133#include "TSystem.h"
134#include "TROOT.h"
135#include "TMethod.h"
136#include "TEnv.h"
137#include "TBenchmark.h"
138#include "TError.h"
139#include "TGlobal.h"
140#include "TList.h"
141#include "THashList.h"
142#include "TObjString.h"
143#include "Getline.h"
144#include "TFunction.h"
145#include "TMethodArg.h"
146#include "TInterpreter.h"
147#include "Riostream.h"
148#include "Rstrstream.h"
149#include "strlcpy.h"
150
151#define BUF_SIZE 1024 // must be smaller than/equal to fgLineBufSize in Getline.cxx and
152 // lineBufSize in cppcompleter.py
153#define IfDebug(x) if(gDebug==TTabCom::kDebug) x
154
155#ifdef R__WIN32
156const char kDelim = ';';
157#else
158const char kDelim = ':';
159#endif
160
161
163// ----------------------------------------------------------------------------
164//
165// global/file scope variables
166//
167TTabCom *gTabCom = nullptr;
168
169// ----------------------------------------------------------------------------
170//
171// constructors
172//
173
174////////////////////////////////////////////////////////////////////////////////
175/// Default constructor.
176
178 fpClasses(nullptr),
179 fPrevInterpMarker(0),
180 fpDirectives(nullptr),
181 fpEnvVars(nullptr),
182 fpFiles(nullptr),
183 fpGlobals(nullptr),
184 fpPragmas(nullptr),
185 fpSysIncFiles(nullptr),
186 fpUsers(nullptr),
187 fBuf(nullptr),
188 fpLoc(nullptr),
189 fVarIsPointer(kFALSE),
190 fLastIter(0)
191{
192 InitPatterns();
193}
194
195//
196// constructors
197//
198// ----------------------------------------------------------------------------
199
201{
202 // Destructor.
203
204 ClearAll();
205 ClearSysIncFiles(); // this one stays cached
206 ClearUsers(); // this one stays cached
207}
208
209// ----------------------------------------------------------------------------
210//
211// public member functions
212//
213
214
215////////////////////////////////////////////////////////////////////////////////
216/// Clear classes and namespace collections.
217
219{
220 if (fpClasses) {
221 delete fpClasses;
222 fpClasses = nullptr;
223 }
224
225}
226
227////////////////////////////////////////////////////////////////////////////////
228/// Forget all Cpp directives seen so far.
229
231{
232 if (!fpDirectives)
233 return;
234 fpDirectives->Delete(nullptr);
235 delete fpDirectives;
236 fpDirectives = nullptr;
237}
238
239////////////////////////////////////////////////////////////////////////////////
240/// Forget all environment variables seen so far.
241
243{
244 if (!fpEnvVars)
245 return;
246 fpEnvVars->Delete(nullptr);
247 delete fpEnvVars;
248 fpEnvVars = nullptr;
249}
250
251////////////////////////////////////////////////////////////////////////////////
252/// Close all files.
253
255{
256 if (!fpFiles)
257 return;
258 fpFiles->Delete(nullptr);
259 delete fpFiles;
260 fpFiles = nullptr;
261}
262
263////////////////////////////////////////////////////////////////////////////////
264/// Forget all global functions seen so far.
265/// Not needed anymore. Use gROOT->GetListOfGlobalFunctions()
266
268{
269}
270
271////////////////////////////////////////////////////////////////////////////////
272/// Forget all global variables seen so far.
273/// With teh new implamentation the list is gROOT->GetListOfGlobals(true).
274
276{
277}
278
279////////////////////////////////////////////////////////////////////////////////
280/// Forget all pragmas seen so far.
281
283{
284 if (!fpPragmas)
285 return;
286 fpPragmas->Delete(nullptr);
287 delete fpPragmas;
288 fpPragmas = nullptr;
289}
290
291////////////////////////////////////////////////////////////////////////////////
292/// Close system files.
293
295{
296 if (!fpSysIncFiles)
297 return;
298 fpSysIncFiles->Delete(nullptr);
299 delete fpSysIncFiles;
300 fpSysIncFiles = nullptr;
301}
302
303////////////////////////////////////////////////////////////////////////////////
304/// Forget all user seen so far.
305
307{
308 if (!fpUsers)
309 return;
310 fpUsers->Delete(nullptr);
311 delete fpUsers;
312 fpUsers = nullptr;
313}
314
315////////////////////////////////////////////////////////////////////////////////
316/// clears all lists
317/// except for user names and system include files.
318
320{
321 ClearClasses();
323 ClearEnvVars();
324 ClearFiles();
326 ClearGlobals();
327 ClearPragmas();
328// ClearSysIncFiles(); <-- this one stays cached
329// ClearUsers(); <-- this one stays cached
330}
331
332////////////////////////////////////////////////////////////////////////////////
333/// Do the class rehash.
334
336{
337 ClearClasses();
339}
340
341////////////////////////////////////////////////////////////////////////////////
342/// Cpp rehashing.
343
345{
348}
349
350////////////////////////////////////////////////////////////////////////////////
351/// Environemnt variables rehashing.
352
354{
355 ClearEnvVars();
357}
358
359////////////////////////////////////////////////////////////////////////////////
360/// Close files.
361
363{
364 ClearFiles(); /* path unknown */
365} // think about this
366
367////////////////////////////////////////////////////////////////////////////////
368/// Reload global functions.
369
371{
373}
374
375////////////////////////////////////////////////////////////////////////////////
376/// Reload globals.
377
379{
380 ClearGlobals();
382}
383
384////////////////////////////////////////////////////////////////////////////////
385/// Reload pragmas.
386
388{
389 ClearPragmas();
391}
392
393////////////////////////////////////////////////////////////////////////////////
394/// Reload system include files.
395
397{
400}
401
402////////////////////////////////////////////////////////////////////////////////
403/// Reload users.
404
406{
407 ClearUsers();
409}
410
411////////////////////////////////////////////////////////////////////////////////
412/// clears and then rebuilds all lists
413/// except for user names and system include files.
414
416{
420 RehashFiles();
424// RehashSysIncFiles(); <-- this one stays cached
425// RehashUsers(); <-- this one stays cached
426}
427
428////////////////////////////////////////////////////////////////////////////////
429/// Return the list of classes.
430
432{
433 if (!fpClasses) {
434 fpClasses = new THashList;
435 // Iterate over the table from the map file.
436 THashList* entries = gInterpreter->GetMapfile()->GetTable();
437 TIter next(entries);
438 while (const auto key = next()) {
439 // This is not needed with the new rootmap format
440 const char* className = key->GetName();
441 if (!strncmp(className, "Library.", 8))
442 className += 8;
443
444 if (!strstr(className, ".h"))
445 fpClasses->Add(new TObjString(className));
446 }
447
448 // We might have autoload entries that don't have a rootmap entry
449 // (libCore) and no interpreter info (not yet loaded).
450 TClassTable::Init(); // reset counter
451 while (const char* className = TClassTable::Next()) {
452 if (!fpClasses->FindObject(className)) {
453 fpClasses->Add(new TObjString(className));
454 }
455 }
456
457 // Add possible identifiers coming from the global module index.
458 // FIXME: Consolidate all this -- we have ultimate source of information
459 // clang's identifier table and the ASTIndentifiers.
460 gInterpreter->AddAvailableIndentifiers(*fpClasses);
461 }
462
463 if (fPrevInterpMarker != gInterpreter->GetInterpreterStateMarker()) {
464 ClassInfo_t* ci = gInterpreter->ClassInfo_Factory(kFALSE /*all*/);
465 while (gInterpreter->ClassInfo_Next(ci)) {
466 const char* className = gInterpreter->ClassInfo_FullName(ci);
467 if (strstr(className, "(anonymous)") || strstr(className, "(unnamed)"))
468 continue;
469 if (!fpClasses->FindObject(className)) {
470 fpClasses->Add(new TObjString(className));
471 }
472 }
473 gInterpreter->ClassInfo_Delete(ci);
474 }
475
476 return fpClasses;
477}
478
479////////////////////////////////////////////////////////////////////////////////
480/// Return the list of CPP directives.
481
483{
484 if (!fpDirectives) {
486
487 fpDirectives->Add(new TObjString("if"));
488 fpDirectives->Add(new TObjString("ifdef"));
489 fpDirectives->Add(new TObjString("ifndef"));
490 fpDirectives->Add(new TObjString("elif"));
491 fpDirectives->Add(new TObjString("else"));
492 fpDirectives->Add(new TObjString("endif"));
493 fpDirectives->Add(new TObjString("include"));
494 fpDirectives->Add(new TObjString("define"));
495 fpDirectives->Add(new TObjString("undef"));
496 fpDirectives->Add(new TObjString("line"));
497 fpDirectives->Add(new TObjString("error"));
498 fpDirectives->Add(new TObjString("pragma"));
499 }
500
501 return fpDirectives;
502}
503
504////////////////////////////////////////////////////////////////////////////////
505/// "path" should be initialized with a colon separated list of
506/// system directories
507
509{
510 static TString previousPath;
511
512 if (path && fpFiles && strcmp(path, previousPath) == 0) {
513 return fpFiles;
514 } else {
515 ClearFiles();
516
518 previousPath = path;
519 }
520
521 return fpFiles;
522}
523
524////////////////////////////////////////////////////////////////////////////////
525/// Uses "env" (Unix) or "set" (Windows) to get list of environment variables.
526
528{
529 if (!fpEnvVars) {
530 TString outf = ".TTabCom-";
531 FILE *fout = gSystem->TempFileName(outf);
532 if (!fout) return nullptr;
533 fclose(fout);
534 TString cmd;
535
536#ifndef WIN32
537 char *env = gSystem->Which(gSystem->Getenv("PATH"), "env", kExecutePermission);
538 if (!env)
539 return nullptr;
540 cmd = env;
541 cmd += " > ";
542 delete [] env;
543#else
544 cmd = "set > ";
545#endif
546 cmd += outf;
547 cmd += "\n";
548 gSystem->Exec(cmd.Data());
549
550 // open the file
551 std::ifstream file1(outf);
552 if (!file1) {
553 Error("TTabCom::GetListOfEnvVars", "could not open file \"%s\"",
554 outf.Data());
555 gSystem->Unlink(outf);
556 return nullptr;
557 }
558 // parse, add
559 fpEnvVars = new TContainer;
561 while (file1) // i think this loop goes one time extra which
562 // results in an empty string in the list, but i don't think it causes any
563 // problems.
564 {
565 line.ReadToDelim(file1, '=');
566 file1.ignore(32000, '\n');
567 fpEnvVars->Add(new TObjString(line.Data()));
568 }
569
570 file1.close();
571 gSystem->Unlink(outf);
572 }
573
574 return fpEnvVars;
575}
576
577////////////////////////////////////////////////////////////////////////////////
578/// Return the list of globals.
579
581{
582 return (TSeqCollection*)gROOT->GetListOfGlobals(true);
583}
584
585////////////////////////////////////////////////////////////////////////////////
586/// Return the list of global functions.
587
589{
590 return gROOT->GetListOfGlobalFunctions(true);
591}
592
593////////////////////////////////////////////////////////////////////////////////
594/// Return the list of pragmas
595
597{
598 if (!fpPragmas) {
599 fpPragmas = new TContainer;
600
601 fpPragmas->Add(new TObjString("ANSI "));
602 fpPragmas->Add(new TObjString("autocompile "));
603 fpPragmas->Add(new TObjString("bytecode "));
604 fpPragmas->Add(new TObjString("compile "));
605 fpPragmas->Add(new TObjString("endbytecode "));
606 fpPragmas->Add(new TObjString("endcompile "));
607 fpPragmas->Add(new TObjString("include "));
608 fpPragmas->Add(new TObjString("includepath "));
609 fpPragmas->Add(new TObjString("K&R "));
610 fpPragmas->Add(new TObjString("link "));
611 fpPragmas->Add(new TObjString("preprocess "));
612 fpPragmas->Add(new TObjString("preprocessor "));
613 fpPragmas->Add(new TObjString("security level"));
614 // "setertti " omitted. Ordinary user should not use this statement
615 // "setstdio " omitted. Ordinary user should not use this statement
616 // "setstream " omitted. Ordinary user should not use this statement
617 // "stub" omitted. Ordinary user should not use this statement
618
619 }
620
621 return fpPragmas;
622}
623
624////////////////////////////////////////////////////////////////////////////////
625/// Return the list of system include files.
626
628{
629 if (!fpSysIncFiles) {
631 }
632
633 return fpSysIncFiles;
634}
635
636////////////////////////////////////////////////////////////////////////////////
637/// reads from "/etc/passwd"
638
640{
641 if (!fpUsers) {
642 fpUsers = new TContainer;
643
644 std::ifstream passwd;
645 TString user;
646
647 passwd.open("/etc/passwd");
648 while (passwd) {
649 user.ReadToDelim(passwd, ':');
650 fpUsers->Add(new TObjString(user));
651 passwd.ignore(32000, '\n');
652 }
653 passwd.close();
654 }
655
656 return fpUsers;
657}
658
659//
660// public member functions
661//
662// ----------------------------------------------------------------------------
663
664// ----------------------------------------------------------------------------
665//
666// static utility functions
667//
668
669////////////////////////////////////////////////////////////////////////////////
670///[static utility function]///////////////////////////////////////////
671///
672/// if all the strings in "*pList" have the same ith character,
673/// that character is returned.
674/// otherwise 0 is returned.
675///
676/// any string "s" for which "ExcludedByFignore(s)" is true
677/// will be ignored unless All the strings in "*pList"
678/// are "ExcludedByFignore()"
679///
680/// in addition, the number of strings which were not
681/// "ExcludedByFignore()" is returned in "nGoodStrings".
682///
683//////////////////////////////////////////////////////////////////////////
684
686 Int_t & nGoodStrings)
687{
688 assert(pList != nullptr);
689
690 TIter next(pList);
691 TObject *pObj;
692 const char *s = "";
693 char ch0;
694 Bool_t isGood;
695 Bool_t atLeast1GoodString;
696
697 // init
698 nGoodStrings = 0;
699 atLeast1GoodString = kFALSE;
700
701 // first look for a good string
702 do {
703 if ((pObj = next())) {
704 s = pObj->GetName();
705 isGood = !ExcludedByFignore(s);
706 if (isGood) {
707 atLeast1GoodString = kTRUE;
708 nGoodStrings += 1;
709 }
710 } else {
711 // reached end of list without finding a single good string.
712 // just use the first one.
713 next.Reset();
714 pObj = next();
715 if (pObj) s = pObj->GetName();
716 break;
717 }
718 }
719 while (!isGood);
720
721 // found a good string...
722 ch0 = s[i];
723
724 // all subsequent good strings must have the same ith char
725 do {
726 if ((pObj = next())) {
727 s = pObj->GetName();
728 isGood = !ExcludedByFignore(s);
729 if (isGood)
730 nGoodStrings += 1;
731 } else
732 return ch0;
733 }
734 while (((int) strlen(s) >= i && s[i] == ch0) ||
735 (atLeast1GoodString && !isGood));
736
737 return 0;
738}
739
740////////////////////////////////////////////////////////////////////////////////
741///[static utility function]/////////////////////////////
742///
743/// adds a TObjString to "*pList"
744/// for each entry found in the system directory "dirName"
745///
746/// directories that do not exist are silently ignored.
747///
748///////////////////////////////////////////////////////////
749
751 TSeqCollection * pList)
752{
753 assert(dirName != nullptr);
754 assert(pList != nullptr);
755
756 // open the directory
757 void *dir = gSystem->OpenDirectory(dirName);
758
759 // it is normal for this function to receive names of directories that do not exist.
760 // they should be ignored and should not generate any error messages.
761 if (!dir)
762 return;
763
764 // put each filename in the list
765 const char *tmp_ptr; // gSystem->GetDirEntry() returns 0 when no more files.
766 TString fileName;
767
768 while ((tmp_ptr = gSystem->GetDirEntry(dir))) {
769 fileName = tmp_ptr;
770
771 // skip "." and ".."
772 if (fileName == "." || fileName == "..")
773 continue;
774
775 // add to list
776 pList->Add(new TObjString(dirName + fileName.Prepend("/")));
777 }
778 // NOTE:
779 // with a path like "/usr/include:/usr/include/CC:$ROOTDIR/include:$ROOTDIR/cint/include:..."
780 // the above loop could get traversed 700 times or more.
781 // ==> keep it minimal or it could cost whole seconds on slower machines.
782 // also: TClonesArray doesn't help.
783
784 // close the directory
786}
787
788// -----\/-------- homemade RTTI ---------------\/------------------------
789////////////////////////////////////////////////////////////////////////////////
790///[static utility function]/////////////////////////////
791///
792/// returns empty string on failure.
793/// otherwise returns something like this: "TROOT*".
794/// fails for non-class types (ie, int, char, etc).
795/// fails for pointers to functions.
796///
797////////////////////////////////////
798
799TString TTabCom::DetermineClass(const char varName[])
800{
801
802 ///////////////////////////////////
803 //
804 // note that because of the strange way this function works,
805 // CINT will print
806 //
807 // Error: No symbol asdf in current scope FILE:/var/tmp/gaaa001HR LINE:1
808 //
809 // if "varName" is not defined. (in this case, varName=="asdf")
810 // i don't know how to suppress this.
811 //
812 ///////////////////////////////////
813
814 assert(varName != nullptr);
815 IfDebug(std::cerr << "DetermineClass(\"" << varName << "\");" << std::endl);
816
817 // @todo This is a long ugly workaround, replace with access via gInterpreter
818 TString outf = ".TTabCom-";
819 FILE *fout = gSystem->TempFileName(outf);
820 if (!fout) return "";
821 fclose(fout);
822
823 TString cmd(".> ");
824 cmd += outf;
825 //redirect
826 gROOT->ProcessLineSync(cmd.Data());
827
828 cmd = "gROOT->ProcessLine(\"";
829 cmd += varName;
830 cmd += "\");";
831 cmd += "\n";
832 gROOT->ProcessLineSync(cmd.Data());
833 // the type of the variable whose name is "varName"
834 // should now be stored on disk in the file "tmpfile"
835
836 gROOT->ProcessLineSync(".>");
837
838 TString type = "";
839 int c;
840
841 // open the file
842 std::ifstream file1(outf);
843 if (!file1) {
844 Error("TTabCom::DetermineClass", "could not open file \"%s\"",
845 outf.Data());
846 goto cleanup;
847 }
848 // first char should be '(', which we can ignore.
849 c = file1.get();
850 if (!file1 || c <= 0 || c != '(') {
851 Error("TTabCom::DetermineClass", "variable \"%s\" not defined?",
852 varName);
853 goto cleanup;
854 }
855 IfDebug(std::cerr << (char) c << std::flush);
856
857 // in case of success, "class TClassName*)0x12345" remains or TClassName 0x[0-9][a-f]+
858 // in case of objects
859 // since the opening '(' was removed.
860
861 if (type == "const" || type == "class") {
862 file1 >> type;
863 // ignore ' '
864 c = file1.get();
865 IfDebug(std::cerr << (char) c << std::flush);
866 }
867
868 // this is what we want
869 type.ReadToDelim(file1, ')');
870 IfDebug(std::cerr << type << std::endl);
871
872 // new version of Cling returns: "qualifiers TClassName *const) 0x12345"
873 // we start stripping off right "const"
874 if (type.EndsWith(" *const"))
875 type.Remove(type.Length() - 5);
876 // we strip off left qualifiers
877 if (type.BeginsWith("const "))
878 type.Remove(0, 6);
879 if (type.BeginsWith("volatile ")) // this automatically takes care of variant "const volatile"
880 type.Remove(0, 9);
881
882cleanup:
883 // done reading from file
884 file1.close();
885 gSystem->Unlink(outf);
886
887 return type;
888}
889
890////////////////////////////////////////////////////////////////////////////////
891///[static utility function]/////////////////////////////
892///
893/// returns true iff "s" ends with one of
894/// the strings listed in the "TabCom.FileIgnore" resource.
895///
896//////////////////////////////////////////////////////////////
897
899{
900 const char *fignore = gEnv->GetValue("TabCom.FileIgnore", (char *) nullptr);
901
902 if (!fignore) {
903 return kFALSE;
904 } else {
905#ifdef R__SSTREAM
906 std::istringstream endings((char *) fignore);
907#else
908 std::istrstream endings((char *) fignore); // do i need to make a copy first?
909#endif
910 TString ending;
911
912 ending.ReadToDelim(endings, kDelim);
913
914 while (!ending.IsNull()) {
915 if (s.EndsWith(ending))
916 return kTRUE;
917 else
918 ending.ReadToDelim(endings, kDelim); // next
919 }
920 return kFALSE;
921 }
922}
923
924////////////////////////////////////////////////////////////////////////////////
925///[static utility function]/////////////////////////////
926///
927/// returns a colon-separated string of directories
928/// that CINT will search when you call `#include<...>`
929///
930/// returns empty string on failure.
931///
932////////////////////////////////////////////////////////////
933
935{
936 // >i noticed that .include doesn't list the standard directories like
937 // >/usr/include or /usr/include/CC.
938 // >
939 // >how can i get a list of all the directories the interpreter will
940 // >search through when the user does a #include<...> ?
941 //
942 // Right now, there is no easy command to tell you about it. Instead, I can
943 // describe it here.
944 //
945 // 1) CINT first searches current working directory for #include "xxx"
946 // (#include <xxx> does not)
947 //
948 // 2) CINT searches include path directories given by -I option
949 //
950 // 3) CINT searches following standard include directories.
951 // $CINTSYSDIR/include
952 // $CINTSYSDIR/stl
953 // $CINTSYSDIR/msdev/include if VC++4.0
954 // $CINTSYSDIR/sc/include if Symantec C++
955 // /usr/include
956 // /usr/include/g++ if gcc,g++
957 // /usr/include/CC if HP-UX
958 // /usr/include/codelibs if HP-UX
959 //
960 // .include command only displays 2).
961 //
962 // Thank you
963 // Masaharu Goto
964
965 // 1) current dir
966 // ----------------------------------------------
967 // N/A
968
969
970 // 2) -I option (and #pragma includepath)
971 // ----------------------------------------------
972
973 // get this part of the include path from the interpreter
974 // and stick it in a tmp file.
975 TString outf = ".TTabCom-";
976 FILE *fout = gSystem->TempFileName(outf);
977 if (!fout) return "";
979 fclose(fout);
980
981 // open the tmp file
982 std::ifstream file1(outf);
983 if (!file1) { // error
984 Error("TTabCom::GetSysIncludePath", "could not open file \"%s\"",
985 outf.Data());
986 gSystem->Unlink(outf);
987 return "";
988 }
989 // parse it.
990 TString token; // input buffer
991 TString path; // all directories so far (colon-separated)
992 file1 >> token; // skip "include"
993 file1 >> token; // skip "path:"
994 while (file1) {
995 file1 >> token;
996 if (!token.IsNull()) {
997 if (path.Length() > 0)
998 path.Append(":");
999 path.Append(token.Data() + 2); // +2 skips "-I"
1000 }
1001 }
1002
1003 // done with the tmp file
1004 file1.close();
1005 gSystem->Unlink(outf);
1006
1007 // 3) standard directories
1008 // ----------------------------------------------
1009
1010#ifndef CINTINCDIR
1011 TString sCINTSYSDIR("$ROOTSYS/cint");
1012#else
1013 TString sCINTSYSDIR(CINTINCDIR);
1014#endif
1015 path.Append(":" + sCINTSYSDIR + "/include");
1016// path.Append(":"+CINTSYSDIR+"/stl");
1017// path.Append(":"+CINTSYSDIR+"/msdev/include");
1018// path.Append(":"+CINTSYSDIR+"/sc/include");
1019 path.Append(":/usr/include");
1020// path.Append(":/usr/include/g++");
1021// path.Append(":/usr/include/CC");
1022// path.Append(":/usr/include/codelibs");
1023
1024 return path;
1025}
1026
1027////////////////////////////////////////////////////////////////////////////////
1028///[static utility function]/////////////////////////////
1029///
1030/// calls TSystem::GetPathInfo() to see if "fileName"
1031/// is a system directory.
1032///
1033////////////////////////////////////////////////////////
1034
1035Bool_t TTabCom::IsDirectory(const char fileName[])
1036{
1037 FileStat_t stat;
1038 if (!gSystem->GetPathInfo(fileName, stat))
1039 return R_ISDIR(stat.fMode);
1040 else
1041 return false;
1042}
1043
1044////////////////////////////////////////////////////////////////////////////////
1045///[static utility function]/////////////////////////////
1046///
1047/// creates a list containing the full path name for each file
1048/// in the (colon separated) string "path1"
1049///
1050/// memory is allocated with "new", so
1051/// whoever calls this function takes responsibility for deleting it.
1052///
1053///////////////////////////////////////////////////////////////////////
1054
1056{
1057 assert(path1 != nullptr);
1058 if (!path1[0]) path1 = ".";
1059
1060 TContainer *pList = new TContainer; // maybe use RTTI here? (since its a static function)
1061#ifdef R__SSTREAM
1062 std::istringstream path((char *) path1);
1063#else
1064 std::istrstream path((char *) path1);
1065#endif
1066
1067 while (path.good())
1068 {
1069 TString dirName;
1070 dirName.ReadToDelim(path, kDelim);
1071 if (dirName.IsNull())
1072 continue;
1073
1074 IfDebug(std::cerr << "NewListOfFilesInPath(): dirName = " << dirName <<
1075 std::endl);
1076
1077 AppendListOfFilesInDirectory(dirName, pList);
1078 }
1079
1080 return pList;
1081}
1082
1083////////////////////////////////////////////////////////////////////////////////
1084///[static utility function]/////////////////////////////
1085///
1086/// true if "fileName"
1087/// 1. is an absolute path ("/tmp/a")
1088/// 2. is a relative path ("../whatever", "./test")
1089/// 3. starts with user name ("~/mail")
1090/// 4. starts with an environment variable ("$ROOTSYS/bin")
1091///
1092///////////////////////////////////////////////////////////////////////////
1093
1095{
1096 char c1 = (fileName.Length() > 0) ? fileName[0] : 0;
1097 return c1 == '/' || c1 == '~' || c1 == '$' || fileName.BeginsWith("./")
1098 || fileName.BeginsWith("../");
1099}
1100
1101////////////////////////////////////////////////////////////////////////////////
1102///[static utility function]/////////////////////////////
1103///
1104/// calling "NoMsg( errorLevel )",
1105/// sets "gErrorIgnoreLevel" to "errorLevel+1" so that
1106/// all errors with "level < errorLevel" will be ignored.
1107///
1108/// calling the function with a negative argument
1109/// (e.g., "NoMsg( -1 )")
1110/// resets gErrorIgnoreLevel to its previous value.
1111///
1112///////////////////////////////////////////////////////////////////
1113
1114void TTabCom::NoMsg(Int_t errorLevel)
1115{
1116 ////////////////////////////////////////////////////////////////
1117 //
1118 // if you call the function twice with a non-negative argument
1119 // (without an intervening call with a negative argument)
1120 // it will complain because it is almost certainly an error
1121 // that will cause the function to loose track of the previous
1122 // value of gErrorIgnoreLevel.
1123 //
1124 // most common causes: 1. suspiciously placed "return;" statement
1125 // 2. calling a function that calls "NoMsg()"
1126 //
1127 //////////////////////////////////////////////////////////////////
1128
1129 const Int_t kNotDefined = -2;
1130 static Int_t old_level = kNotDefined;
1131
1132 if (errorLevel < 0) // reset
1133 {
1134 if (old_level == kNotDefined) {
1135 std::cerr << "NoMsg(): ERROR 1. old_level==" << old_level << std::endl;
1136 return;
1137 }
1138
1139 gErrorIgnoreLevel = old_level; // restore
1140 old_level = kNotDefined;
1141 } else // set
1142 {
1143 if (old_level != kNotDefined) {
1144 std::cerr << "NoMsg(): ERROR 2. old_level==" << old_level << std::endl;
1145 return;
1146 }
1147
1148 old_level = gErrorIgnoreLevel;
1149 if (gErrorIgnoreLevel <= errorLevel)
1150 gErrorIgnoreLevel = errorLevel + 1;
1151 }
1152}
1153
1154//
1155// static utility functions
1156//
1157// ----------------------------------------------------------------------------
1158
1159
1160// ----------------------------------------------------------------------------
1161//
1162// private member functions
1163//
1164//
1165
1166////////////////////////////////////////////////////////////////////////////////
1167/// [private]
1168
1170 const TSeqCollection * pListOfCandidates,
1171 const char appendage[],
1172 std::ostream& out,
1174{
1175 // returns position of first change in buffer
1176 // ------------------------------------------
1177 // -2 ==> new line altogether (whole thing needs to be redrawn, including prompt)
1178 // -1 ==> no changes
1179 // 0 ==> beginning of line
1180 // 1 ==> after 1st char
1181 // n ==> after nth char
1182
1183 IfDebug(std::cerr << "TTabCom::Complete() ..." << std::endl);
1184 assert(fpLoc != nullptr);
1185 assert(pListOfCandidates != nullptr);
1186
1187 Int_t pos = 0; // position of first change
1188 const int loc = *fpLoc; // location where TAB was pressed
1189
1190 // -----------------------------------------
1191 //
1192 // 1. get the substring we need to complete
1193 //
1194 // NOTES:
1195 // s1 = original buffer
1196 // s2 = sub-buffer from 0 to wherever the user hit TAB
1197 // s3 = the actual text that needs completing
1198 //
1199 // -----------------------------------------
1200 TString s1(fBuf);
1201 TString s2 = s1(0, loc);
1202 TString s3 = s2(re);
1203
1204 int start = s2.Index(re);
1205
1206 IfDebug(std::cerr << " s1: " << s1 << std::endl);
1207 IfDebug(std::cerr << " s2: " << s2 << std::endl);
1208 IfDebug(std::cerr << " s3: " << s3 << std::endl);
1209 IfDebug(std::cerr << "start: " << start << std::endl);
1210 IfDebug(std::cerr << std::endl);
1211
1212 // -----------------------------------------
1213 // 2. go through each possible completion,
1214 // keeping track of the number of matches
1215 // -----------------------------------------
1216 TList listOfMatches; // list of matches (local filenames only) (insertion order must agree across these 3 lists)
1217 TList listOfFullPaths; // list of matches (full filenames) (insertion order must agree across these 3 lists)
1218 listOfMatches.SetOwner();
1219 listOfFullPaths.SetOwner();
1220
1221 int nMatches = 0; // number of matches
1222 TObject *pObj; // pointer returned by iterator
1223 TIter next_candidate(pListOfCandidates);
1224 TIter next_match(&listOfMatches);
1225 TIter next_fullpath(&listOfFullPaths);
1226
1227 // stick all matches into "listOfMatches"
1228 while ((pObj = next_candidate())) {
1229 // get the full filename
1230 const char *s4 = pObj->GetName();
1231
1232 assert(s4 != nullptr);
1233
1234 // pick off tail
1235 const char *s5 = strrchr(s4, '/');
1236 if (!s5)
1237 s5 = s4; // no '/' found
1238 else
1239 s5 += 1; // advance past '/'
1240
1241 // if case sensitive (normal behaviour), check for match
1242 // if case insensitive, convert to TString and compare case insensitively
1243 if ((cmp == TString::kExact) && (strstr(s5, s3) == s5)) {
1244 nMatches += 1;
1245 listOfMatches.Add(new TObjString(s5));
1246 listOfFullPaths.Add(new TObjString(s4));
1247 IfDebug(std::cerr << "adding " << s5 << '\t' << s4 << std::endl);
1248 } else if (cmp == TString::kIgnoreCase) {
1249 TString ts5(s5);
1250 if (ts5.BeginsWith(s3, cmp))
1251 {
1252 nMatches += 1;
1253 listOfMatches.Add(new TObjString(s5));
1254 listOfFullPaths.Add(new TObjString(s4));
1255 IfDebug(std::cerr << "adding " << s5 << '\t' << s4 << std::endl);
1256 }
1257 } else {
1258//rdm IfDebug(std::cerr << "considered " << s5 << '\t' << s4 << std::endl);
1259 }
1260
1261 }
1262
1263 // -----------------------------------------
1264 // 3. beep, list, or complete
1265 // depending on how many matches were found
1266 // -----------------------------------------
1267
1268 // 3a. no matches ==> bell
1269 TString partialMatch = "";
1270
1271 if (nMatches == 0) {
1272 // Ring a bell!
1273 gSystem->Beep();
1274 pos = -1;
1275 goto done; //* RETURN *//
1276 }
1277 // 3b. one or more matches.
1278 char match[1024];
1279
1280 if (nMatches == 1) {
1281 // get the (lone) match
1282 const char *short_name = next_match()->GetName();
1283 const char *full_name = next_fullpath()->GetName();
1284
1285 pObj = pListOfCandidates->FindObject(short_name);
1286 if (pObj) {
1287 IfDebug(std::cerr << std::endl << "class: " << pObj->ClassName() << std::endl);
1288 TString className = pObj->ClassName();
1289 if (0);
1290 else if (className == "TMethod" || className == "TFunction") {
1291 TFunction *pFunc = (TFunction *) pObj;
1292 if (0 == pFunc->GetNargs())
1293 appendage = "()"; // no args
1294 else
1295 appendage = "("; // user needs to supply some args
1296 } else if (className == "TDataMember") {
1297 appendage = " ";
1298 }
1299 }
1300
1301 CopyMatch(match, sizeof(match), short_name, appendage, full_name);
1302 } else {
1303 // multiple matches ==> complete as far as possible
1304 Char_t ch;
1305 Int_t nGoodStrings;
1306
1307 for (int i = 0;
1308 (ch = AllAgreeOnChar(i, &listOfMatches, nGoodStrings));
1309 i += 1) {
1310 IfDebug(std::cerr << " i=" << i << " ch=" << ch << std::endl);
1311 partialMatch.Append(ch);
1312 }
1313
1314 const char *s;
1315 const char *s0;
1316
1317 // multiple matches, but maybe only 1 of them is any good.
1318 if (nGoodStrings == 1) {
1319
1320 // find the 1 good match
1321 do {
1322 s = next_match()->GetName();
1323 s0 = next_fullpath()->GetName();
1324 }
1325 while (ExcludedByFignore(s));
1326
1327 // and use it.
1328 CopyMatch(match, sizeof(match), s, appendage, s0);
1329 } else {
1330 IfDebug(std::cerr << "more than 1 GoodString" << std::endl);
1331
1332 if (partialMatch.Length() > s3.Length())
1333 // this partial match is our (partial) completion.
1334 {
1335 CopyMatch(match, sizeof(match), partialMatch.Data());
1336 } else
1337 // couldn't do any completing at all,
1338 // print a list of all the ambiguous matches
1339 // (except for those excluded by "FileIgnore")
1340 {
1341 IfDebug(std::cerr << "printing ambiguous matches" << std::endl);
1342 std::set<std::string> alreadyPrinted;
1343 while ((pObj = next_match())) {
1344 s = pObj->GetName();
1345 if (alreadyPrinted.insert(s).second) {
1346 // Nothing of that name has been printed yet.
1347 s0 = next_fullpath()->GetName();
1348 if (!ExcludedByFignore(s) || nGoodStrings == 0) {
1349 if (IsDirectory(s0))
1350 out << s << "/" << std::endl;
1351 else
1352 out << s << std::endl;
1353 }
1354 }
1355 }
1356 pos = -2;
1357 if (cmp == TString::kExact || partialMatch.Length() < s3.Length()) {
1358 goto done; //* RETURN *//
1359 } // else:
1360 // update the matching part, will have changed
1361 // capitalization because only cmp == TString::kIgnoreCase
1362 // matches.
1363 CopyMatch(match, sizeof(match), partialMatch.Data());
1364 }
1365 }
1366 }
1367
1368
1369 // ---------------------------------------
1370 // 4. finally write text into the buffer.
1371 // ---------------------------------------
1372 {
1373 const int old_len = strlen(fBuf); // old EOL position is old_len
1374 const int match_len = strlen(match);
1375 const int added_len = match_len - (loc - start); // new EOL position will be old_len+added_len
1376
1377 // first check for overflow
1378 if (old_len + added_len + 1 > BUF_SIZE || start > loc || start + match_len + 1 > BUF_SIZE) {
1379 Error("TTabCom::Complete", "buffer overflow");
1380 pos = -2;
1381 goto done; /* RETURN */
1382 }
1383 // debugging output
1384 IfDebug(std::cerr << " i=" << old_len << std::endl);
1385 IfDebug(std::cerr << " L=" << added_len << std::endl);
1386 IfDebug(std::cerr << "loc=" << loc << std::endl);
1387
1388 // slide everything (including the null terminator) over to make space
1389 for (int i = old_len; i >= loc; i -= 1) {
1390 fBuf[i + added_len] = fBuf[i];
1391 }
1392
1393 // insert match
1394 memcpy(fBuf + start, match, match_len);
1395
1396 // the "get"->"Get" case of TString::kIgnore sets pos to -2
1397 // and falls through to update the buffer; we need to return
1398 // -2 in that case, so check here:
1399 if (pos != -2) {
1400 pos = loc; // position of first change in "fBuf"
1401 if (cmp == TString::kIgnoreCase && pos < 0) {
1402 // We might have changed somthing before loc, due to differences in
1403 // capitalization. So return start:
1404 pos = start;
1405 }
1406 }
1407 *fpLoc = loc + added_len; // new cursor position
1408 }
1409
1410done: // <----- goto label
1411 // un-init
1412 fpLoc = nullptr;
1413 fBuf = nullptr;
1414
1415 return pos;
1416}
1417
1418////////////////////////////////////////////////////////////////////////////////
1419/// [private]
1420
1421void TTabCom::CopyMatch(char *dest, int dest_len,
1422 const char *localName,
1423 const char *appendage,
1424 const char *fullName) const
1425{
1426 // if "appendage" is 0, no appendage is applied.
1427 //
1428 // if "appendage" is of the form "filenameXXX" then,
1429 // "filename" is ignored and "XXX" is taken to be the appendage,
1430 // but it will only be applied if the file is not a directory...
1431 // if the file is a directory, a "/" will be used for the appendage instead.
1432 //
1433 // if "appendage" is of the form "XXX" then "XXX" will be appended to the match.
1434
1435 assert(dest != nullptr);
1436 assert(localName != nullptr);
1437
1438 // potential buffer overflow.
1439 strlcpy(dest, localName, dest_len);
1440
1441 const char *key = "filename";
1442 const int key_len = strlen(key);
1443
1444 IfDebug(std::cerr << "CopyMatch()." << std::endl);
1445 IfDebug(std::cerr << "localName: " << (localName ? localName : "0") <<
1446 std::endl);
1447 IfDebug(std::cerr << "appendage: " << (appendage ? appendage : "0") <<
1448 std::endl);
1449 IfDebug(std::cerr << " fullName: " << (fullName ? fullName : "0") <<
1450 std::endl);
1451
1452
1453 // check to see if "appendage" starts with "key"
1454 if (appendage && strncmp(appendage, key, key_len) == 0) {
1455 // filenames get special treatment
1456 appendage += key_len;
1457 IfDebug(std::cerr << "new appendage: " << appendage << std::endl);
1458 if (IsDirectory(fullName)) {
1459 if (fullName)
1460 strlcat(dest, "/", dest_len);
1461 } else {
1462 if (appendage)
1463 strlcat(dest, appendage, dest_len);
1464 }
1465 } else {
1466 if (appendage)
1467 strlcat(dest, appendage, dest_len);
1468 }
1469}
1470
1471////////////////////////////////////////////////////////////////////////////////
1472/// [private]
1473
1475{
1476 assert(fBuf != nullptr);
1477
1478 const char *pStart; // start of match
1479 const char *pEnd; // end of match
1480
1481 for (int context = 0; context < kNUM_PAT; ++context) {
1482 pEnd = Matchs(fBuf, *fpLoc, fPat[context], &pStart);
1483 if (pEnd) {
1484 IfDebug(std::cerr << std::endl
1485 << "context=" << context << " "
1486 << "RegExp=" << fRegExp[context]
1487 << std::endl);
1488 return EContext_t(context); //* RETURN *//
1489 }
1490 }
1491
1492 return kUNKNOWN_CONTEXT; //* RETURN *//
1493}
1494
1495////////////////////////////////////////////////////////////////////////////////
1496/// [private]
1497
1499 const char defaultPath[]) const
1500{
1501 if (PathIsSpecifiedInFileName(fileName)) {
1502 TString path = fileName;
1503 gSystem->ExpandPathName(path);
1504 Int_t end = path.Length()-1;
1505 if (end>0 && path[end]!='/' && path[end]!='\\') {
1506 path = gSystem->GetDirName(path);
1507 }
1508 return path;
1509 } else {
1510 TString newBase, extendedPath;
1511 if (fileName.Contains("/")) {
1512 Int_t end = fileName.Length()-1;
1513 if (fileName[end] != '/' && fileName[end] != '\\') {
1514 newBase = gSystem->GetDirName(fileName);
1515 } else {
1516 newBase = fileName;
1517 }
1518 extendedPath = ExtendPath(defaultPath, newBase);
1519 } else {
1520 newBase = "";
1521 extendedPath = defaultPath;
1522 }
1523 IfDebug(std::cerr << std::endl);
1524 IfDebug(std::cerr << " fileName: " << fileName << std::endl);
1525 IfDebug(std::cerr << " pathBase: " << newBase << std::endl);
1526 if (defaultPath) {
1527 IfDebug(std::cerr << " defaultPath: " << defaultPath << std::endl);
1528 } else {
1529 IfDebug(std::cerr << " defaultPath: " << std::endl);
1530 }
1531 IfDebug(std::cerr << "extendedPath: " << extendedPath << std::endl);
1532 IfDebug(std::cerr << std::endl);
1533
1534 return extendedPath;
1535 }
1536}
1537
1538////////////////////////////////////////////////////////////////////////////////
1539/// [private]
1540
1541TString TTabCom::ExtendPath(const char originalPath[], TString newBase) const
1542{
1543 if (newBase.BeginsWith("/"))
1544 newBase.Remove(TString::kLeading, '/');
1545#ifdef R__SSTREAM
1546 std::stringstream str;
1547#else
1548 std::strstream str;
1549#endif
1550 TString dir;
1551 TString newPath;
1552 if (originalPath) str << originalPath;
1553
1554 while (str.good())
1555 {
1556 dir = "";
1557 dir.ReadToDelim(str, kDelim);
1558 if (dir.IsNull())
1559 continue; // ignore blank entries
1560 newPath.Append(dir);
1561 if (!newPath.EndsWith("/"))
1562 newPath.Append("/");
1563 newPath.Append(newBase);
1564 newPath.Append(kDelim);
1565 }
1566
1567 return newPath.Strip(TString::kTrailing, kDelim);
1568}
1569
1570////////////////////////////////////////////////////////////////////////////////
1571/// [private]
1572
1573Int_t TTabCom::Hook(char *buf, int *pLoc, std::ostream& out)
1574{
1575 // initialize
1576 fBuf = buf;
1577 fpLoc = pLoc;
1578
1579 // frodo: iteration counter for recursive MakeClassFromVarName
1580 fLastIter = 0;
1581
1582 // default
1583 Int_t pos = -2; // position of the first character that was changed in the buffer (needed for redrawing)
1584
1585 // get the context this tab was triggered in.
1586 EContext_t context = DetermineContext();
1587
1588 // get the substring that triggered this tab (as defined by "SetPattern()")
1589 const char dummy[] = ".";
1590 TRegexp re1(context == kUNKNOWN_CONTEXT ? dummy : fRegExp[context]);
1591 TString s1(fBuf);
1592 TString s2 = s1(0, *fpLoc);
1593 TString s3 = s2(re1);
1594
1595 switch (context) {
1596 case kUNKNOWN_CONTEXT:
1597 std::cerr << std::endl << "tab completion not implemented for this context" <<
1598 std::endl;
1599 pos = -2;
1600 break;
1601
1602 case kSYS_UserName:
1603 {
1604 const TSeqCollection *pListOfUsers = GetListOfUsers();
1605
1606 pos = Complete("[^~]*$", pListOfUsers, "/", out);
1607 }
1608 break;
1609 case kSYS_EnvVar:
1610 {
1611 const TSeqCollection *pEnv = GetListOfEnvVars();
1612
1613 pos = Complete("[^$]*$", pEnv, "", out);
1614 }
1615 break;
1616
1617 case kCINT_stdout:
1618 case kCINT_stderr:
1619 case kCINT_stdin:
1620 {
1621 const TString fileName = s3("[^ ><]*$");
1622 const TString filePath = DeterminePath(fileName,nullptr);
1623 const TSeqCollection *pListOfFiles =
1624 GetListOfFilesInPath(filePath.Data());
1625
1626// pos = Complete( "[^ /]*$", pListOfFiles, " ", out );
1627 pos = Complete("[^ /]*$", pListOfFiles, "filename ", out);
1628 }
1629 break;
1630
1631 case kCINT_Edit:
1632 case kCINT_Load:
1633 case kCINT_Exec:
1634 case kCINT_EXec:
1635 {
1636 const TString fileName = s3("[^ ]*$");
1637 const TString macroPath =
1639 const TSeqCollection *pListOfFiles =
1640 GetListOfFilesInPath(macroPath.Data());
1641
1642// pos = Complete( "[^ /]*$", pListOfFiles, " ", out);
1643 pos = Complete("[^ /]*$", pListOfFiles, "filename ", out);
1644 }
1645 break;
1646
1647 case kCINT_pragma:
1648 {
1649 pos = Complete("[^ ]*$", GetListOfPragmas(), "", out);
1650 }
1651 break;
1652 case kCINT_includeSYS:
1653 {
1654 TString fileName = s3("[^<]*$");
1655 if (PathIsSpecifiedInFileName(fileName) || fileName.Contains("/")) {
1656 TString includePath =
1657 DeterminePath(fileName, GetSysIncludePath());
1658
1659// pos = Complete( "[^</]*$", GetListOfFilesInPath( includePath ), "> ", out);
1660 pos =
1661 Complete("[^</]*$", GetListOfFilesInPath(includePath),
1662 "filename> ", out);
1663 } else {
1664// pos = Complete( "[^</]*$", GetListOfSysIncFiles(), "> ", out);
1665 pos =
1666 Complete("[^</]*$", GetListOfSysIncFiles(), "filename> ", out);
1667 }
1668 }
1669 break;
1670 case kCINT_includePWD:
1671 {
1672 const TString fileName = s3("[^\"]*$");
1673 const TString includePath = DeterminePath(fileName, ".");
1674 const TSeqCollection *pListOfFiles =
1675 GetListOfFilesInPath(includePath.Data());
1676
1677// pos = Complete( "[^\"/]*$", pListOfFiles, "\" ", out);
1678 pos = Complete("[^\"/]*$", pListOfFiles, "filename\" ", out);
1679 }
1680 break;
1681
1682 case kCINT_cpp:
1683 {
1684 pos = Complete("[^# ]*$", GetListOfCppDirectives(), " ", out);
1685 }
1686 break;
1687
1688 case kROOT_Load:
1689 {
1690 const TString fileName = s3("[^\"]*$");
1691 const TString dynamicPath = DeterminePath(fileName, gSystem->GetDynamicPath());
1692 const TSeqCollection *pListOfFiles = GetListOfFilesInPath(dynamicPath);
1693
1694// pos = Complete( "[^\"/]*$", pListOfFiles, "\");", out);
1695 pos = Complete("[^\"/]*$", pListOfFiles, "filename\");", out);
1696 }
1697 break;
1698
1699 case kSYS_FileName:
1700 {
1701 const TString fileName = s3("[^ \"]*$");
1702 const TString filePath = DeterminePath(fileName,".");
1703 const TSeqCollection *pListOfFiles = GetListOfFilesInPath(filePath.Data());
1704
1705 pos = Complete("[^\" /]*$", pListOfFiles, "filename\"", out);
1706 }
1707 break;
1708
1709 case kCXX_ScopeMember:
1710 {
1711 const EContext_t original_context = context; // save this for later
1712
1713 TClass *pClass;
1714 // may be a namespace, class, object, or pointer
1715 TString name = s3("^[_a-zA-Z][_a-zA-Z0-9]*");
1716
1717 IfDebug(std::cerr << std::endl);
1718 IfDebug(std::cerr << "name: " << '"' << name << '"' << std::endl);
1719
1720 // We need to decompose s3 a little more:
1721 // The part name is the partial symbol at the end of ::
1722 // eg. given s3 = "foo::bar::part" , partname = "part"
1723 TString partname = s3("[_a-zA-Z][_a-zA-Z0-9]*$");
1724
1725 // The prefix, considering the s3 = "foo::bar::part" example would be
1726 // prefix = "foo::bar::". prefix equals the empty string if there is only one
1727 // or no set of colons in s3.
1728 // Note: we reconstruct the fully qualified name with a while loop because
1729 // it does not seem that TRegexp can handle something like "([_a-zA-Z][_a-zA-Z0-9]*::)+$"
1730 TString prefix = "";
1731 TString str = s2;
1732 str.Remove(str.Length() - partname.Length(), partname.Length());
1733 while (1) {
1734 TString sym = str("[_a-zA-Z][_a-zA-Z0-9]*::$");
1735 if (sym.Length() == 0)
1736 break;
1737 str.Remove(str.Length() - sym.Length(), sym.Length());
1738 prefix = sym + prefix;
1739 }
1740
1741 // Not the preprefix would be = "foo::" from our previous example or the empty
1742 // string, "" if there is only one or no set of colons in prefix, eg. prefix = "bar::"
1743 TString preprefix = prefix;
1744 TString sym = prefix("[_a-zA-Z][_a-zA-Z0-9]*::$");
1745 preprefix.Remove(preprefix.Length() - sym.Length(), sym.Length());
1746
1747 IfDebug(std::cerr << "prefix: " << '"' << prefix << '"' << std::endl);
1748 IfDebug(std::cerr << "preprefix: " << '"' << preprefix << '"' << std::endl);
1749
1750 TString namesp = prefix;
1751 if (namesp.Length() >= 2)
1752 namesp.Remove(namesp.Length() - 2, 2); // Remove the '::' at the end of the string.
1753 IfDebug(std::cerr << "namesp: " << '"' << namesp << '"' << std::endl);
1754
1755 // Make sure autoloading happens (if it can).
1757
1758 TContainer *pList = new TContainer;
1759 // Add all classes to pList that contain the prefix, i.e. are in the
1760 // specified namespace.
1761 const TSeqCollection *tmp = GetListOfClasses();
1762 if (!tmp) break;
1763
1764 Int_t i;
1765 for (i = 0; i < tmp->GetSize(); i++) {
1766 TString astr = ((TObjString *) tmp->At(i))->String();
1767 TString rxp = "^";
1768 rxp += prefix;
1769 if (astr.Contains(TRegexp(rxp))) {
1770 astr.Remove(0, prefix.Length());
1771 TString s = astr("^[^: ]*");
1772 TObjString *ostr = new TObjString(s);
1773 if (!pList->Contains(ostr))
1774 pList->Add(ostr);
1775 else
1776 delete ostr;
1777 }
1778 }
1779
1780 // If a class with the same name as the Namespace name exists then
1781 // add it to the pList. (I don't think the C++ spec allows for this
1782 // but do this anyway, cant harm).
1783 pClass = TryMakeClassFromClassName(preprefix + name);
1784 if (pClass) {
1785 pList->AddAll(pClass->GetListOfAllPublicMethods(true));
1786 pList->AddAll(pClass->GetListOfAllPublicDataMembers(true));
1787 }
1788
1789 pos = Complete("[^: ]*$", pList, "", out);
1790
1791 delete pList;
1792
1793 if (context != original_context)
1794 pos = -2;
1795 }
1796 break;
1797
1798 case kCXX_DirectMember:
1800 {
1801 const EContext_t original_context = context; // save this for later
1802
1803 TClass *pClass;
1804
1805 // frodo: Instead of just passing the last portion of the string to
1806 // MakeClassFromVarName(), we now pass the all string and let
1807 // it decide how to handle it... I know it's not the best way
1808 // because of the context handling, but I wanted to "minimize"
1809 // the changes to the current code and this seemed the best way
1810 // to do it
1811 TString name = s1("[_a-zA-Z][-_a-zA-Z0-9<>():.]*$");
1812
1813 IfDebug(std::cerr << std::endl);
1814 IfDebug(std::cerr << "name: " << '"' << name << '"' << std::endl);
1815
1816 switch (context) {
1817 case kCXX_DirectMember:
1818 pClass = MakeClassFromVarName(name, context);
1819 break;
1821 pClass = MakeClassFromVarName(name, context);
1822 break;
1823 default:
1824 Fatal("TTabCom::Hook","Conext case %d not handled",context);
1825 return 0; // Avoid warning about uninitialized pClass.
1826 }
1827 if (!pClass) {
1828 pos = -2;
1829 break;
1830 }
1831
1832 TContainer *pList = new TContainer;
1833
1834 pList->AddAll(pClass->GetListOfAllPublicMethods());
1835 pList->AddAll(pClass->GetListOfAllPublicDataMembers());
1836
1837 switch (context) {
1838 case kCXX_DirectMember:
1839 {
1840 int* store_fpLoc = fpLoc;
1841 char* store_fBuf = fBuf;
1842 pos = Complete("[^. ]*$", pList, "(", out);
1843 if (pos == -1) {
1844 fpLoc = store_fpLoc;
1845 fBuf = store_fBuf;
1846 pos = Complete("[^. ]*$", pList, "(", out, TString::kIgnoreCase);
1847 }
1848 break;
1849 }
1851 pos = Complete("[^> ]*$", pList, "(", out);
1852 break;
1853 default:
1854 Fatal("TTabCom::Hook","Conext case %d not handled",context);
1855 return 0; // Avoid warning about uninitialized pClass.
1856 }
1857
1858 delete pList;
1859
1860 if (context != original_context)
1861 pos = -2;
1862 }
1863 break;
1864
1865 case kCXX_ScopeProto:
1866 {
1867 const EContext_t original_context = context; // save this for later
1868
1869 // get class
1870 TClass *pClass;
1871 TString name = s3("^[_a-zA-Z][_a-zA-Z0-9]*");
1872 // "name" may now be the name of a class, object, or pointer
1873
1874 IfDebug(std::cerr << std::endl);
1875 IfDebug(std::cerr << "name: " << '"' << name << '"' << std::endl);
1876
1877 // We need to decompose s3 a little more:
1878 // The partname is the method symbol and a bracket at the end of ::
1879 // eg. given s3 = "foo::bar::part(" , partname = "part("
1880 TString partname = s3("[_a-zA-Z][_a-zA-Z0-9]* *($");
1881
1882 // The prefix, considering the s3 = "foo::bar::part" example would be
1883 // prefix = "foo::bar::". prefix equals the empty string if there is only one
1884 // or no set of colons in s3.
1885 // Note: we reconstruct the fully qualified name with a while loop because
1886 // it does not seem that TRegexp can handle something like "([_a-zA-Z][_a-zA-Z0-9]*::)+$"
1887 TString prefix = "";
1888 TString str = s2;
1889 str.Remove(str.Length() - partname.Length(), partname.Length());
1890 while (1) {
1891 TString sym = str("[_a-zA-Z][_a-zA-Z0-9]*::$");
1892 if (sym.Length() == 0)
1893 break;
1894 str.Remove(str.Length() - sym.Length(), sym.Length());
1895 prefix = sym + prefix;
1896 }
1897
1898 // Not the preprefix would be = "foo::" from our previous example or the empty
1899 // string, "" if there is only one or no set of colons in prefix, eg. prefix = "bar::"
1900 TString preprefix = prefix;
1901 TString sym = prefix("[_a-zA-Z][_a-zA-Z0-9]*::$");
1902 preprefix.Remove(preprefix.Length() - sym.Length(), sym.Length());
1903
1904 IfDebug(std::cerr << "prefix: " << '"' << prefix << '"' << std::endl);
1905 IfDebug(std::cerr << "preprefix: " << '"' << preprefix << '"' << std::endl);
1906
1907 pClass = MakeClassFromClassName(preprefix + name);
1908 if (!pClass) {
1909 pos = -2;
1910 break;
1911 }
1912 // get method name
1913 TString methodName;
1914
1915 // (normal member function)
1916 methodName = s3("[^:>\\.(]*($");
1917 methodName.Chop();
1918 methodName.Remove(TString::kTrailing, ' ');
1919
1920 IfDebug(std::cerr << methodName << std::endl);
1921
1922 // get methods
1923 TContainer *pList = new TContainer;
1924 pList->AddAll(pClass->GetListOfAllPublicMethods());
1925
1926 // print prototypes
1927 Bool_t foundOne = kFALSE;
1928 TIter nextMethod(pList);
1929 TMethod *pMethod;
1930 while ((pMethod = (TMethod *) nextMethod())) {
1931 if (methodName == pMethod->GetName()) {
1932 foundOne = kTRUE;
1933 out << pMethod->GetReturnTypeName()
1934 << " " << pMethod->GetName()
1935 << pMethod->GetSignature();
1936 const char *comment = pMethod->GetCommentString();
1937 if (comment && comment[0] != '\0') {
1938 out << " \t// " << comment;
1939 }
1940 out << std::endl;
1941 }
1942 }
1943
1944 // done
1945 if (foundOne) {
1946 pos = -2;
1947 } else {
1948 gSystem->Beep();
1949 pos = -1;
1950 }
1951
1952 // cleanup
1953 delete pList;
1954
1955 if (context != original_context)
1956 pos = -2;
1957 }
1958 break;
1959
1960 case kCXX_DirectProto:
1961 case kCXX_IndirectProto:
1962 case kCXX_NewProto:
1964 {
1965 const EContext_t original_context = context; // save this for later
1966
1967 // get class
1968 TClass *pClass;
1969 TString name;
1970 if (context == kCXX_NewProto) {
1971 name = s3("[_a-zA-Z][_a-zA-Z0-9:]* *($", 3);
1972 name.Chop();
1973 name.Remove(TString::kTrailing, ' ');
1974 // "name" should now be the name of a class
1975 } else {
1976 name = s3("^[_a-zA-Z][_a-zA-Z0-9:]*");
1977 // "name" may now be the name of a class, object, or pointer
1978 }
1979 IfDebug(std::cerr << std::endl);
1980 IfDebug(std::cerr << "name: " << '"' << name << '"' << std::endl);
1981
1982 // frodo: Again, passing the all string
1983 TString namerec = s1;
1984
1985 switch (context) {
1986 case kCXX_ScopeProto:
1987 pClass = MakeClassFromClassName(name);
1988 break;
1989 case kCXX_DirectProto:
1990 pClass = MakeClassFromVarName(namerec, context); // frodo
1991 break;
1992 case kCXX_IndirectProto:
1993 pClass = MakeClassFromVarName(namerec, context); // frodo
1994 break;
1995 case kCXX_NewProto:
1996 pClass = MakeClassFromClassName(name);
1997 break;
1999 pClass = MakeClassFromClassName(name);
2000 break;
2001 default:
2002 Fatal("TTabCom::Hook","Conext case %d not handled",context);
2003 return 0; // Avoid warning about uninitialized pClass.
2004 }
2005 if (!pClass) {
2006 pos = -2;
2007 break;
2008 }
2009 // get method name
2010 TString methodName;
2011 if (context == kCXX_ConstructorProto || context == kCXX_NewProto) {
2012 // (constructor)
2013 methodName = name("[_a-zA-Z][_a-zA-Z0-9]*$");
2014 } else {
2015 // (normal member function)
2016 methodName = s3("[^:>\\.(]*($");
2017 methodName.Chop();
2018 methodName.Remove(TString::kTrailing, ' ');
2019 }
2020 IfDebug(std::cerr << methodName << std::endl);
2021
2022 // get methods
2023 TContainer *pList = new TContainer;
2024 pList->AddAll(pClass->GetListOfAllPublicMethods());
2025
2026 // print prototypes
2027 Bool_t foundOne = kFALSE;
2028 TIter nextMethod(pList);
2029 TMethod *pMethod;
2030 while ((pMethod = (TMethod *) nextMethod())) {
2031 if (methodName == pMethod->GetName()) {
2032 foundOne = kTRUE;
2033 out << pMethod->GetReturnTypeName()
2034 << " " << pMethod->GetName()
2035 << pMethod->GetSignature();
2036 const char *comment = pMethod->GetCommentString();
2037 if (comment && comment[0] != '\0') {
2038 out << " \t// " << comment;
2039 }
2040 out << std::endl;
2041 }
2042 }
2043
2044 // done
2045 if (foundOne) {
2046 pos = -2;
2047 } else {
2048 gSystem->Beep();
2049 pos = -1;
2050 }
2051
2052 // cleanup
2053 delete pList;
2054
2055 if (context != original_context)
2056 pos = -2;
2057 }
2058 break;
2059
2060 case kCXX_Global:
2061 {
2062 // first need to veto a few possibilities.
2063 int l2 = s2.Length(), l3 = s3.Length();
2064
2065 // "abc().whatever[TAB]"
2066 if (l2 > l3 && s2[l2 - l3 - 1] == '.') {
2067 std::cerr << std::endl <<
2068 "tab completion not implemented for this context" << std::endl;
2069 break; // veto
2070 }
2071 // "abc()->whatever[TAB]"
2072 if (l2 > l3 + 1 && s2(l2 - l3 - 2, 2) == "->") {
2073 std::cerr << std::endl <<
2074 "tab completion not implemented for this context" << std::endl;
2075 break; // veto
2076 }
2077
2078 TContainer *pList = new TContainer;
2079
2080 const TSeqCollection *pL2 = GetListOfClasses();
2081 if (pL2) pList->AddAll(pL2);
2082
2083 //
2084 const TSeqCollection *pC1 = GetListOfGlobals();
2085 if (pC1) pList->AddAll(pC1);
2086 //
2088 if (pC3) pList->AddAll(pC3);
2089
2090 pos = Complete("[_a-zA-Z][_a-zA-Z0-9]*$", pList, "", out);
2091
2092 delete pList;
2093 }
2094 break;
2095
2096 case kCXX_GlobalProto:
2097 {
2098 // get function name
2099 TString functionName = s3("[_a-zA-Z][_a-zA-Z0-9]*");
2100 IfDebug(std::cerr << functionName << std::endl);
2101
2102 TContainer listOfMatchingGlobalFuncs;
2103 TIter nextGlobalFunc(GetListOfGlobalFunctions());
2104 TObject *pObj;
2105 while ((pObj = nextGlobalFunc())) {
2106 if (strcmp(pObj->GetName(), functionName) == 0) {
2107 listOfMatchingGlobalFuncs.Add(pObj);
2108 }
2109 }
2110
2111 if (listOfMatchingGlobalFuncs.IsEmpty()) {
2112 std::cerr << std::endl << "no such function: " << dblquote(functionName)
2113 << std::endl;
2114 } else {
2115 TIter next(&listOfMatchingGlobalFuncs);
2116 TFunction *pFunction;
2117 while ((pFunction = (TFunction *) next())) {
2118 out << pFunction->GetReturnTypeName()
2119 << " " << pFunction->GetName()
2120 << pFunction->GetSignature()
2121 << std::endl;
2122 }
2123 }
2124
2125 pos = -2;
2126 }
2127 break;
2128
2129 /******************************************************************/
2130 /* */
2131 /* default: should never happen */
2132 /* */
2133 /******************************************************************/
2134 default:
2135 Fatal("TTabCom::Hook","Conext case %d not handled",context);
2136 return 0; // Avoid warning about uninitialized pClass.
2137 }
2138
2139 return pos;
2140}
2141
2142////////////////////////////////////////////////////////////////////////////////
2143/// [private]
2144
2146{
2147 // add more patterns somewhere below.
2148 // add corresponding enum to "EContext_t"
2149 //
2150 // note:
2151 // 1. in some cases order is important ...
2152 //
2153 // the order of the "case" statements in "switch( context )" in "TTabCom::Hook()" is Not important.
2154 //
2155 // the order of the "SetPattern()" function calls below is Not important.
2156 //
2157 // the order of the initializers in the "EContext_t" enumeration Is important
2158 // because DetermineContext() goes through the array in order, and returns at the first match.
2159 //
2160 // 2. below, "$" will match cursor position
2161
2162 SetPattern(kSYS_UserName, "~[_a-zA-Z0-9]*$");
2163 SetPattern(kSYS_EnvVar, "$[_a-zA-Z0-9]*$");
2164
2165 SetPattern(kCINT_stdout, "; *>>?.*$"); // stdout
2166 SetPattern(kCINT_stderr, "; *2>>?.*$"); // stderr
2167 SetPattern(kCINT_stdin, "; *<.*$"); // stdin
2168
2169 SetPattern(kCINT_Edit, "^ *\\.E .*$");
2170 SetPattern(kCINT_Load, "^ *\\.L .*$");
2171 SetPattern(kCINT_Exec, "^ *\\.x +[-0-9_a-zA-Z~$./]*$");
2172 SetPattern(kCINT_EXec, "^ *\\.X +[-0-9_a-zA-Z~$./]*$");
2173
2174 SetPattern(kCINT_pragma, "^# *pragma +[_a-zA-Z0-9]*$");
2175 SetPattern(kCINT_includeSYS, "^# *include *<[^>]*$"); // system files
2176 SetPattern(kCINT_includePWD, "^# *include *\"[^\"]*$"); // local files
2177
2178 SetPattern(kCINT_cpp, "^# *[_a-zA-Z0-9]*$");
2179
2180 SetPattern(kROOT_Load, "gSystem *-> *Load *( *\"[^\"]*$");
2181
2182 SetPattern(kCXX_NewProto, "new +[_a-zA-Z][_a-zA-Z0-9:]* *($");
2184 "[_a-zA-Z][_a-zA-Z0-9:]* +[_a-zA-Z][_a-zA-Z0-9]* *($");
2186 "[_a-zA-Z][_a-zA-Z0-9]* *:: *[_a-zA-Z0-9]* *($");
2188 "[_a-zA-Z][_a-zA-Z0-9()]* *\\. *[_a-zA-Z0-9]* *($");
2190 "[_a-zA-Z][_a-zA-Z0-9()]* *-> *[_a-zA-Z0-9]* *($");
2191
2193 "[_a-zA-Z][_a-zA-Z0-9]* *:: *[_a-zA-Z0-9]*$");
2195 "[_a-zA-Z][_a-zA-Z0-9()]* *\\. *[_a-zA-Z0-9()]*$"); //
2196
2198 "[_a-zA-Z][_a-zA-Z0-9()]* *-> *[_a-zA-Z0-9()]*$"); // frodo
2199
2200 SetPattern(kSYS_FileName, "\"[-0-9_a-zA-Z~$./]*$");
2201 SetPattern(kCXX_Global, "[_a-zA-Z][_a-zA-Z0-9]*$");
2202 SetPattern(kCXX_GlobalProto, "[_a-zA-Z][_a-zA-Z0-9]* *($");
2203}
2204
2205////////////////////////////////////////////////////////////////////////////////
2206/// [private]
2207/// (does some specific error handling that makes the function unsuitable for general use.)
2208/// returns a new'd TClass given the name of a class.
2209/// user must delete.
2210/// returns 0 in case of error.
2211
2212TClass *TTabCom::MakeClassFromClassName(const char className[]) const
2213{
2214 // the TClass constructor will print a Warning message for classes that don't exist
2215 // so, ignore warnings temporarily.
2216 NoMsg(kWarning);
2217 TClass *pClass = TClass::GetClass(className);
2218 NoMsg(-1);
2219
2220 if (!pClass){
2221 Error("TTabCom::MakeClassFromClassName", "Unknown class \"%s\"", className);
2222 return nullptr;
2223 }
2224
2225 // make sure "className" exists
2226 // if (pClass->Size() == 0) { //namespace has 0 size
2227 if (pClass->GetListOfAllPublicMethods()->GetSize() == 0 &&
2228 pClass->GetListOfAllPublicDataMembers()->GetSize() == 0) {
2229 // i'm assuming this happens iff there was some error.
2230 // (misspelled the class name, for example)
2231 Error("TTabCom::MakeClassFromClassName", "class \"%s\" is not defined.", className);
2232 return nullptr;
2233 }
2234
2235 return pClass;
2236}
2237
2238////////////////////////////////////////////////////////////////////////////////
2239/// Same as above but does not print the error message.
2240
2241TClass *TTabCom::TryMakeClassFromClassName(const char className[]) const
2242{
2243 // the TClass constructor will print a Warning message for classes that don't exist
2244 // so, ignore warnings temporarily.
2245 NoMsg(kWarning);
2246 TClass *pClass = TClass::GetClass(className);
2247 NoMsg(-1);
2248
2249 return pClass;
2250}
2251
2252////////////////////////////////////////////////////////////////////////////////
2253/// [private]
2254/// (does some specific error handling that makes the function unsuitable for general use.)
2255/// returns a new'd TClass given the name of a variable.
2256/// user must delete.
2257/// returns 0 in case of error.
2258/// if user has operator.() or operator->() backwards, will modify: context, *fpLoc and fBuf.
2259/// context sensitive behavior.
2260
2262 EContext_t & context, int iter)
2263{
2264 // frodo:
2265 // Because of the Member and Proto recursion, this has become a bit
2266 // complicated, so here is how it works:
2267 //
2268 // root [1] var.a.b.c[TAB]
2269 //
2270 // will generate the sucessive calls:
2271 // MakeClassFromVarName("var.a.b.c", context, 0) returns the class of "c"
2272 // MakeClassFromVarName("var.a.b", context, 1) returns the class of "b"
2273 // MakeClassFromVarName("var.a", context, 2) returns the class of "a"
2274 // MakeClassFromVarName("var", context, 3)
2275
2276 // need to make sure "varName" exists
2277 // because "DetermineClass()" prints clumsy error message otherwise.
2278 Bool_t varName_exists = GetListOfGlobals()->Contains(varName) || // check in list of globals first.
2279 (gROOT->FindObject(varName) != nullptr); // then check CINT "shortcut #3"
2280
2281
2282 //
2283 // frodo: Member and Proto recursion code
2284 //
2285 if (0) printf("varName is [%s] with iteration [%i]\n", varName, iter);
2286
2287 // ParseReverse will return 0 if there are no "." or "->" in the varName
2288 Int_t cut = ParseReverse(varName, strlen(varName));
2289
2290 // If it's not a "simple" variable and if there is at least one "." or "->"
2291 if (!varName_exists && cut != 0)
2292 {
2293 TString parentName = varName;
2294 TString memberName = varName;
2295
2296 // Check to see if this is the last call (last member/method)
2297 if (iter > fLastIter) fLastIter = iter;
2298
2299 parentName[cut] = 0;
2300 if (0) printf("Parent string is [%s]\n", parentName.Data());
2301
2302 // We are treating here cases like h->SetXTitle(gROOT->Get<TAB>
2303 // i.e. when the parentName has an unbalanced number of paranthesis.
2304 if (cut>2) {
2305 UInt_t level = 0;
2306 for(Int_t i = cut-1; i>=0; --i) {
2307 switch (parentName[i]) {
2308 case '(':
2309 if (level) --level;
2310 else {
2311 parentName = parentName(i+1,cut-i-1);
2312 i = 0;
2313 }
2314 break;
2315 case ')':
2316 ++level; break;
2317 }
2318 }
2319 }
2320
2321 TClass *pclass;
2322 // Can be "." or "->"
2323 if (varName[cut] == '.') {
2324 memberName = varName+cut+1;
2325 if (0) printf("Member/method is [%s]\n", memberName.Data());
2326 EContext_t subcontext = kCXX_DirectMember;
2327 pclass = MakeClassFromVarName(parentName.Data(), subcontext, iter+1);
2328 } else {
2329 memberName = varName+cut+2;
2330 if (0) printf("Member/method is [%s]\n", memberName.Data());
2331 EContext_t subcontext = kCXX_IndirectMember;
2332 pclass = MakeClassFromVarName(parentName.Data(), subcontext, iter+1);
2333 }
2334
2335 if (0) printf("I got [%s] from MakeClassFromVarName()\n", pclass->GetName());
2336
2337 if (pclass)
2338 {
2339 if (0) printf("Variable [%s] exists!\n", parentName.Data());
2340
2341 // If it's back in the first call of the function, return immediatly
2342 if (iter == 0) return pclass;
2343
2344 if (0) printf("Trying data member [%s] of class [%s] ...\n",
2345 memberName.Data(), pclass->GetName());
2346
2347 // Check if it's a member
2348 TDataMember *dmptr = nullptr; //pclass->GetDataMember(memberName.Data());
2349 TIter next(pclass->GetListOfAllPublicDataMembers());
2350 while ((dmptr = (TDataMember *) next())) {
2351 if (memberName == dmptr->GetName()) break;
2352 }
2353 if (dmptr)
2354 {
2355 if (0) printf("It's a member!\n");
2356
2357 TString returnName = dmptr->GetTypeName();
2358 // if (returnName[returnName.Length()-1] == '*')
2359 // printf("It's a pointer!\n");
2360
2361 TClass *mclass = TClass::GetClass(returnName.Data());
2362 return mclass;
2363 }
2364
2365
2366 // Check if it's a proto: must have ()
2367 // This might not be too safe to use :(
2368 char *parentesis_ptr = (char*)strrchr(memberName.Data(), '(');
2369 if (parentesis_ptr) *parentesis_ptr = 0;
2370
2371
2372 if (0) printf("Trying method [%s] of class [%s] ...\n",
2373 memberName.Data(), pclass->GetName());
2374
2375 // Check if it's a method
2376 TMethod *mptr = nullptr; // pclass->GetMethodAny(memberName.Data());
2377 const TList *mlist = pclass->GetListOfAllPublicMethods();
2378 next = mlist;
2379 while ((mptr = (TMethod *) next())) {
2380 if (strcmp(memberName.Data(),mptr->GetName())==0) break;
2381 }
2382 if (mptr)
2383 {
2384 TString returnName = mptr->GetReturnTypeName();
2385
2386 if (0) printf("It's a method called [%s] with return type [%s]\n",
2387 memberName.Data(), returnName.Data());
2388
2389 // This will handle the methods that returns a pointer to a class
2390 if (returnName[returnName.Length()-1] == '*')
2391 {
2392 returnName[returnName.Length()-1] = 0;
2394 }
2395 else
2396 {
2398 }
2399
2400 TClass *mclass = TClass::GetClass(returnName.Data());
2401 return mclass;
2402 }
2403 }
2404 }
2405
2406 //
2407 // frodo: End of Member and Proto recursion code
2408 //
2409
2410
2411 // not found...
2412 if (!varName_exists) {
2413 std::cerr << std::endl << "variable " << dblquote(varName) << " not defined."
2414 << std::endl;
2415 return nullptr; //* RETURN *//
2416 }
2417
2418 /*****************************************************************************************/
2419 /* */
2420 /* this section is really ugly. */
2421 /* and slow. */
2422 /* it could be made a lot better if there was some way to tell whether or not a given */
2423 /* variable is a pointer or a pointer to a pointer. */
2424 /* */
2425 /*****************************************************************************************/
2426
2427 TString className = DetermineClass(varName);
2428
2429 if (className.IsNull() || className == "*") {
2430 // this will happen if "varName" is a fundamental type (as opposed to class type).
2431 // or a pointer to a pointer.
2432 // or a function pointer.
2433 std::cerr << std::endl << "problem determining class of " << dblquote(varName)
2434 << std::endl;
2435 return nullptr; //* RETURN *//
2436 }
2437
2438 fVarIsPointer = className[className.Length() - 1] == '*';
2439
2440 // frodo: I shouldn't have to do this, but for some reason now I have to
2441 // otherwise the varptr->[TAB] won't work :(
2442 if (fVarIsPointer || className[className.Length() - 1] == '&')
2443 className[className.Length()-1] = 0;
2444
2445 // frodo case '.' dealt with in the previous if statement?!
2446 // frodo: I wasn't able to put the automatic "." to "->" replacing working
2447 // so I just commented out.
2448 //
2449
2450
2451 // Bool_t varIsPointer = className[className.Length() - 1] == '*';
2452
2453 //printf("Context is %i, fContext is %i, pointer is %i\n", context, fContext, fVarIsPointer);
2454
2455 if (fVarIsPointer &&
2456 (context == kCXX_DirectMember || context == kCXX_DirectProto)) {
2457 // user is using operator.() instead of operator->()
2458 // ==>
2459 // 1. we are in wrong context.
2460 // 2. user is lazy
2461 // 3. or maybe confused
2462
2463 // 1. fix the context
2464 switch (context) {
2465 case kCXX_DirectMember:
2466 context = kCXX_IndirectMember;
2467 break;
2468 case kCXX_DirectProto:
2469 context = kCXX_IndirectProto;
2470 break;
2471 default:
2472 Fatal("TTabCom::MakeClassFromVarName","Conext case %d not handled",context);
2473 return nullptr; // Avoid warning about uninitialized pClass.
2474 }
2475
2476 // 2. fix the operator.
2477 int i;
2478 for (i = *fpLoc; fBuf[i] != '.'; i -= 1) {
2479 }
2480 int loc = i;
2481 for (i = strlen(fBuf); i >= loc; i -= 1) {
2482 fBuf[i + 1] = fBuf[i];
2483 }
2484 fBuf[loc] = '-';
2485 fBuf[loc + 1] = '>';
2486 *fpLoc += 1;
2487
2488 // 3. inform the user.
2489 std::cerr << std::endl << dblquote(varName) <<
2490 " is of pointer type. Use this operator: ->" << std::endl;
2491 return nullptr;
2492 }
2493
2494 if (context == kCXX_IndirectMember || context == kCXX_IndirectProto) {
2495 if (fVarIsPointer) {
2496 // frodo: This part no longer makes sense...
2497 className.Chop(); // remove the '*'
2498
2499 if (className[className.Length() - 1] == '*') {
2500 std::cerr << std::endl << "can't handle pointers to pointers." << std::endl;
2501 return nullptr; // RETURN
2502 }
2503 } else {
2504 // user is using operator->() instead of operator.()
2505 // ==>
2506 // 1. we are in wrong context.
2507 // 2. user is lazy
2508 // 3. or maybe confused
2509
2510 // 1. fix the context
2511 switch (context) {
2513 context = kCXX_DirectMember;
2514 break;
2515 case kCXX_IndirectProto:
2516 context = kCXX_DirectProto;
2517 break;
2518 default:
2519 Fatal("TTabCom::MakeClassFromVarName","Conext case %d not handled",context);
2520 return nullptr; // Avoid warning about uninitialized pClass.
2521 }
2522
2523 // 2. fix the operator.
2524 int i;
2525 for (i = *fpLoc; fBuf[i - 1] != '-' && fBuf[i] != '>'; i -= 1) {
2526 }
2527 fBuf[i - 1] = '.';
2528 int len = strlen(fBuf);
2529 for (; i < len; i += 1) {
2530 fBuf[i] = fBuf[i + 1];
2531 }
2532 *fpLoc -= 1;
2533
2534 // 3. inform the user.
2535 std::cerr << std::endl << dblquote(varName) <<
2536 " is not of pointer type. Use this operator: ." << std::endl;
2537 return nullptr;
2538 }
2539 }
2540
2541 className.Strip(TString::kBoth);
2542
2543 return TClass::GetClass(className);
2544}
2545
2546////////////////////////////////////////////////////////////////////////////////
2547/// [private]
2548
2549void TTabCom::SetPattern(EContext_t handle, const char regexp[])
2550{
2551 // prevent overflow
2552 if (handle >= kNUM_PAT) {
2553 std::cerr << std::endl
2554 << "ERROR: handle="
2555 << (int) handle << " >= kNUM_PAT=" << (int) kNUM_PAT << std::endl;
2556 return;
2557 }
2558
2559 fRegExp[handle] = regexp;
2560 Makepat(regexp, fPat[handle], MAX_LEN_PAT);
2561}
2562
2563
2564
2565////////////////////////////////////////////////////////////////////////////////
2566///
2567/// Returns the place in the string where to put the \0, starting the search
2568/// from "start"
2569///
2570
2571int TTabCom::ParseReverse(const char *var_str, int start)
2572{
2573 int end = 0;
2574 if (start > (int)strlen(var_str)) start = strlen(var_str);
2575
2576 for (int i = start; i > 0; i--)
2577 {
2578 if (var_str[i] == '.') return i;
2579 if (var_str[i] == '>' && i > 0 && var_str[i-1] == '-') return i-1;
2580 }
2581
2582 return end;
2583}
int Makepat(const char *, Pattern_t *, int)
Make a pattern template from the string pointed to by exp.
Definition Match.cxx:129
const char * Matchs(const char *, size_t len, const Pattern_t *, const char **)
Match a string with a pattern.
Definition Match.cxx:220
#define c(i)
Definition RSha256.hxx:101
#define s0(x)
Definition RSha256.hxx:90
#define s1(x)
Definition RSha256.hxx:91
char Char_t
Definition RtypesCore.h:37
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
#define ClassImp(name)
Definition Rtypes.h:382
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
constexpr Int_t kWarning
Definition TError.h:46
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:185
Int_t gErrorIgnoreLevel
Error handling routines.
Definition TError.cxx:31
void Fatal(const char *location, const char *msgfmt,...)
Use this function in case of a fatal error. It will abort the program.
Definition TError.cxx:244
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t dest
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
char name[80]
Definition TGX11.cxx:110
R__EXTERN TInterpreter * gCling
#define gInterpreter
#define gROOT
Definition TROOT.h:406
@ kExecutePermission
Definition TSystem.h:43
Bool_t R_ISDIR(Int_t mode)
Definition TSystem.h:113
R__EXTERN TSystem * gSystem
Definition TSystem.h:561
#define BUF_SIZE
Definition TTabCom.cxx:151
TTabCom * gTabCom
Definition TTabCom.cxx:167
#define IfDebug(x)
Definition TTabCom.cxx:153
const char kDelim
Definition TTabCom.cxx:158
#define dblquote(x)
Definition TTabCom.h:43
#define MAX_LEN_PAT
Definition TTabCom.h:42
static char * Next()
Returns next class from sorted class table.
static void Init()
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:81
const TList * GetListOfAllPublicMethods(Bool_t load=kTRUE)
Returns a list of all public methods of this class and its base classes.
Definition TClass.cxx:3914
TList * GetListOfAllPublicDataMembers(Bool_t load=kTRUE)
Returns a list of all public data members of this class and its base classes.
Definition TClass.cxx:3931
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:3037
Collection abstract base class.
Definition TCollection.h:65
virtual void AddAll(const TCollection *col)
Add all objects from collection col to this collection.
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
TObject * FindObject(const char *name) const override
Find an object in this collection using its name.
virtual Bool_t IsEmpty() const
void Delete(Option_t *option="") override=0
Delete this object.
Bool_t Contains(const char *name) const
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
All ROOT classes may have RTTI (run time type identification) support added.
Definition TDataMember.h:31
const char * GetTypeName() const
Get the decayed type name of this data member, removing const and volatile qualifiers,...
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:491
Global functions class (global functions are obtained from CINT).
Definition TFunction.h:30
const char * GetSignature()
Return signature of function.
Int_t GetNargs() const
Number of function arguments.
const char * GetReturnTypeName() const
Get full type description of function return type, e,g.: "class TDirectory*".
THashList implements a hybrid collection class consisting of a hash table and a list to store TObject...
Definition THashList.h:34
virtual int DisplayIncludePath(FILE *) const
void Reset()
A doubly linked list.
Definition TList.h:38
void Add(TObject *obj) override
Definition TList.h:81
Each ROOT class (see TClass) has a linked list of methods.
Definition TMethod.h:38
virtual const char * GetCommentString()
Returns a comment string from the class declaration.
Definition TMethod.cxx:107
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
Collectable string class.
Definition TObjString.h:28
Mother of all ROOT objects.
Definition TObject.h:41
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:456
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:225
static const char * GetMacroPath()
Get macro search path. Static utility function.
Definition TROOT.cxx:2762
Regular expression class.
Definition TRegexp.h:31
Sequenceable collection abstract base class.
void Add(TObject *obj) override
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:417
std::istream & ReadToDelim(std::istream &str, char delim='\n')
Read up to an EOF, or a delimiting character, whichever comes first.
Definition Stringio.cxx:95
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition TString.cxx:2244
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition TString.cxx:1163
const char * Data() const
Definition TString.h:376
TString & Chop()
Definition TString.h:691
@ kLeading
Definition TString.h:276
@ kTrailing
Definition TString.h:276
@ kBoth
Definition TString.h:276
ECaseCompare
Definition TString.h:277
@ kIgnoreCase
Definition TString.h:277
@ kExact
Definition TString.h:277
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:623
TString & Prepend(const char *cs)
Definition TString.h:673
Bool_t IsNull() const
Definition TString.h:414
TString & Remove(Ssiz_t pos)
Definition TString.h:685
TString & Append(const char *cs)
Definition TString.h:572
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:632
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:651
virtual FILE * TempFileName(TString &base, const char *dir=nullptr, const char *suffix=nullptr)
Create a secure temporary file by appending a unique 6 letter string to base.
Definition TSystem.cxx:1499
void Beep(Int_t freq=-1, Int_t duration=-1, Bool_t setDefault=kFALSE)
Beep for duration milliseconds with a tone of frequency freq.
Definition TSystem.cxx:324
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition TSystem.cxx:1274
virtual void FreeDirectory(void *dirp)
Free a directory.
Definition TSystem.cxx:845
virtual void * OpenDirectory(const char *name)
Open a directory. Returns 0 if directory does not exist.
Definition TSystem.cxx:836
virtual const char * Getenv(const char *env)
Get environment variable.
Definition TSystem.cxx:1665
virtual Int_t Exec(const char *shellcmd)
Execute a command.
Definition TSystem.cxx:653
int GetPathInfo(const char *path, Long_t *id, Long_t *size, Long_t *flags, Long_t *modtime)
Get info about a file: id, size, flags, modification time.
Definition TSystem.cxx:1398
virtual const char * GetDirEntry(void *dirp)
Get a directory entry. Returns 0 if no more entries.
Definition TSystem.cxx:853
virtual const char * GetDynamicPath()
Return the dynamic path (used to find shared libraries).
Definition TSystem.cxx:1795
virtual char * Which(const char *search, const char *file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition TSystem.cxx:1548
virtual TString GetDirName(const char *pathname)
Return the directory name in pathname.
Definition TSystem.cxx:1032
virtual int Unlink(const char *name)
Unlink, i.e.
Definition TSystem.cxx:1381
static void NoMsg(Int_t errorLevel)
[static utility function]/////////////////////////////
Definition TTabCom.cxx:1114
const TSeqCollection * GetListOfCppDirectives()
Return the list of CPP directives.
Definition TTabCom.cxx:482
Int_t Hook(char *buf, int *pLoc, std::ostream &out)
[private]
Definition TTabCom.cxx:1573
ULong64_t fPrevInterpMarker
Definition TTabCom.h:209
void ClearFiles()
Close all files.
Definition TTabCom.cxx:254
static TString DetermineClass(const char varName[])
[static utility function]/////////////////////////////
Definition TTabCom.cxx:799
static Bool_t ExcludedByFignore(TString s)
[static utility function]/////////////////////////////
Definition TTabCom.cxx:898
void InitPatterns()
[private]
Definition TTabCom.cxx:2145
void CopyMatch(char *dest, int dest_len, const char *localName, const char *appendage=nullptr, const char *fullName=nullptr) const
[private]
Definition TTabCom.cxx:1421
void RehashEnvVars()
Environemnt variables rehashing.
Definition TTabCom.cxx:353
const TSeqCollection * GetListOfSysIncFiles()
Return the list of system include files.
Definition TTabCom.cxx:627
void ClearAll()
clears all lists except for user names and system include files.
Definition TTabCom.cxx:319
TSeqCollection * fpDirectives
Definition TTabCom.h:210
const TSeqCollection * GetListOfFilesInPath(const char path[])
"path" should be initialized with a colon separated list of system directories
Definition TTabCom.cxx:508
TSeqCollection * fpClasses
Definition TTabCom.h:208
TSeqCollection * fpEnvVars
Definition TTabCom.h:211
void ClearSysIncFiles()
Close system files.
Definition TTabCom.cxx:294
const TSeqCollection * GetListOfEnvVars()
Uses "env" (Unix) or "set" (Windows) to get list of environment variables.
Definition TTabCom.cxx:527
int * fpLoc
Definition TTabCom.h:219
TString DeterminePath(const TString &fileName, const char defaultPath[]) const
[private]
Definition TTabCom.cxx:1498
const TSeqCollection * GetListOfPragmas()
Return the list of pragmas.
Definition TTabCom.cxx:596
char * fBuf
Definition TTabCom.h:218
static TSeqCollection * NewListOfFilesInPath(const char path[])
[static utility function]/////////////////////////////
Definition TTabCom.cxx:1055
TClass * MakeClassFromVarName(const char varName[], EContext_t &context, int iter=0)
[private] (does some specific error handling that makes the function unsuitable for general use....
Definition TTabCom.cxx:2261
Int_t fLastIter
Definition TTabCom.h:224
const TSeqCollection * GetListOfGlobals()
Return the list of globals.
Definition TTabCom.cxx:580
void SetPattern(EContext_t handle, const char regexp[])
[private]
Definition TTabCom.cxx:2549
TSeqCollection * fpUsers
Definition TTabCom.h:216
TSeqCollection * fpSysIncFiles
Definition TTabCom.h:215
TSeqCollection * fpFiles
Definition TTabCom.h:212
void RehashGlobals()
Reload globals.
Definition TTabCom.cxx:378
TClass * MakeClassFromClassName(const char className[]) const
[private] (does some specific error handling that makes the function unsuitable for general use....
Definition TTabCom.cxx:2212
void RehashGlobalFunctions()
Reload global functions.
Definition TTabCom.cxx:370
void ClearGlobalFunctions()
Forget all global functions seen so far.
Definition TTabCom.cxx:267
void ClearPragmas()
Forget all pragmas seen so far.
Definition TTabCom.cxx:282
static Bool_t PathIsSpecifiedInFileName(const TString &fileName)
[static utility function]/////////////////////////////
Definition TTabCom.cxx:1094
TString ExtendPath(const char originalPath[], TString newBase) const
[private]
Definition TTabCom.cxx:1541
TTabCom()
Default constructor.
Definition TTabCom.cxx:177
void RehashPragmas()
Reload pragmas.
Definition TTabCom.cxx:387
const TSeqCollection * GetListOfClasses()
Return the list of classes.
Definition TTabCom.cxx:431
void RehashCppDirectives()
Cpp rehashing.
Definition TTabCom.cxx:344
void RehashUsers()
Reload users.
Definition TTabCom.cxx:405
const TSeqCollection * GetListOfUsers()
reads from "/etc/passwd"
Definition TTabCom.cxx:639
static void AppendListOfFilesInDirectory(const char dirName[], TSeqCollection *pList)
[static utility function]/////////////////////////////
Definition TTabCom.cxx:750
void ClearClasses()
Clear classes and namespace collections.
Definition TTabCom.cxx:218
TSeqCollection * fpPragmas
Definition TTabCom.h:214
@ kCXX_Global
Definition TTabCom.h:181
@ kSYS_UserName
Definition TTabCom.h:121
@ kNUM_PAT
Definition TTabCom.h:186
@ kUNKNOWN_CONTEXT
Definition TTabCom.h:114
@ kCXX_IndirectProto
Definition TTabCom.h:171
@ kCXX_IndirectMember
Definition TTabCom.h:177
@ kCINT_Exec
Definition TTabCom.h:134
@ kCXX_ScopeProto
Definition TTabCom.h:169
@ kCINT_cpp
Definition TTabCom.h:147
@ kSYS_EnvVar
Definition TTabCom.h:122
@ kCXX_ScopeMember
Definition TTabCom.h:175
@ kCXX_GlobalProto
Definition TTabCom.h:182
@ kSYS_FileName
Definition TTabCom.h:164
@ kCXX_DirectMember
Definition TTabCom.h:176
@ kCINT_includeSYS
Definition TTabCom.h:139
@ kCINT_Load
Definition TTabCom.h:133
@ kCXX_ConstructorProto
Definition TTabCom.h:168
@ kCINT_pragma
Definition TTabCom.h:138
@ kCINT_includePWD
Definition TTabCom.h:140
@ kCXX_DirectProto
Definition TTabCom.h:170
@ kCINT_Edit
Definition TTabCom.h:132
@ kCXX_NewProto
Definition TTabCom.h:167
@ kCINT_stdin
Definition TTabCom.h:127
@ kROOT_Load
Definition TTabCom.h:151
@ kCINT_stdout
Definition TTabCom.h:125
@ kCINT_stderr
Definition TTabCom.h:126
@ kCINT_EXec
Definition TTabCom.h:135
Int_t Complete(const TRegexp &re, const TSeqCollection *pListOfCandidates, const char appendage[], std::ostream &out, TString::ECaseCompare cmp=TString::kExact)
[private]
Definition TTabCom.cxx:1169
const char * fRegExp[kNUM_PAT]
Definition TTabCom.h:222
int ParseReverse(const char *var_str, int start)
Returns the place in the string where to put the \0, starting the search from "start".
Definition TTabCom.cxx:2571
virtual ~TTabCom()
Definition TTabCom.cxx:200
TCollection * GetListOfGlobalFunctions()
Return the list of global functions.
Definition TTabCom.cxx:588
void RehashSysIncFiles()
Reload system include files.
Definition TTabCom.cxx:396
static Bool_t IsDirectory(const char fileName[])
[static utility function]/////////////////////////////
Definition TTabCom.cxx:1035
EContext_t DetermineContext() const
[private]
Definition TTabCom.cxx:1474
static TString GetSysIncludePath()
[static utility function]/////////////////////////////
Definition TTabCom.cxx:934
void ClearEnvVars()
Forget all environment variables seen so far.
Definition TTabCom.cxx:242
void ClearCppDirectives()
Forget all Cpp directives seen so far.
Definition TTabCom.cxx:230
void ClearGlobals()
Forget all global variables seen so far.
Definition TTabCom.cxx:275
void ClearUsers()
Forget all user seen so far.
Definition TTabCom.cxx:306
TList TContainer
Definition TTabCom.h:59
void RehashAll()
clears and then rebuilds all lists except for user names and system include files.
Definition TTabCom.cxx:415
void RehashFiles()
Close files.
Definition TTabCom.cxx:362
TClass * TryMakeClassFromClassName(const char className[]) const
Same as above but does not print the error message.
Definition TTabCom.cxx:2241
Pattern_t fPat[kNUM_PAT][1024]
Definition TTabCom.h:221
void RehashClasses()
Do the class rehash.
Definition TTabCom.cxx:335
static Char_t AllAgreeOnChar(int i, const TSeqCollection *pList, Int_t &nGoodStrings)
[static utility function]///////////////////////////////////////////
Definition TTabCom.cxx:685
Bool_t fVarIsPointer
Definition TTabCom.h:223
TLine * line
return c1
Definition legend1.C:41
Int_t fMode
Definition TSystem.h:125