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 TString outf = ".TTabCom-";
818 FILE *fout = gSystem->TempFileName(outf);
819 if (!fout) return "";
820 fclose(fout);
821
822 TString cmd(".> ");
823 cmd += outf;
824 //redirect
825 gROOT->ProcessLineSync(cmd.Data());
826
827 cmd = "gROOT->ProcessLine(\"";
828 cmd += varName;
829 cmd += "\");";
830 cmd += "\n";
831 gROOT->ProcessLineSync(cmd.Data());
832 // the type of the variable whose name is "varName"
833 // should now be stored on disk in the file "tmpfile"
834
835 gROOT->ProcessLineSync(".>");
836
837 TString type = "";
838 int c;
839
840 // open the file
841 std::ifstream file1(outf);
842 if (!file1) {
843 Error("TTabCom::DetermineClass", "could not open file \"%s\"",
844 outf.Data());
845 goto cleanup;
846 }
847 // first char should be '(', which we can ignore.
848 c = file1.get();
849 if (!file1 || c <= 0 || c != '(') {
850 Error("TTabCom::DetermineClass", "variable \"%s\" not defined?",
851 varName);
852 goto cleanup;
853 }
854 IfDebug(std::cerr << (char) c << std::flush);
855
856 // in case of success, "class TClassName*)0x12345" remains or TClassName 0x[0-9][a-f]+
857 // in case of objects
858 // since the opening '(' was removed.
859
860 if (type == "const" || type == "class") {
861 file1 >> type;
862 // ignore ' '
863 c = file1.get();
864 IfDebug(std::cerr << (char) c << std::flush);
865 }
866
867 // this is what we want
868 type.ReadToDelim(file1, ')');
869 IfDebug(std::cerr << type << std::endl);
870
871 // new version of CINT returns: "class TClassName*const)0x12345"
872 // so we have to strip off "const"
873 if (type.EndsWith("const"))
874 type.Remove(type.Length() - 5);
875
876cleanup:
877 // done reading from file
878 file1.close();
879 gSystem->Unlink(outf);
880
881 return type;
882}
883
884////////////////////////////////////////////////////////////////////////////////
885///[static utility function]/////////////////////////////
886///
887/// returns true iff "s" ends with one of
888/// the strings listed in the "TabCom.FileIgnore" resource.
889///
890//////////////////////////////////////////////////////////////
891
893{
894 const char *fignore = gEnv->GetValue("TabCom.FileIgnore", (char *) nullptr);
895
896 if (!fignore) {
897 return kFALSE;
898 } else {
899#ifdef R__SSTREAM
900 std::istringstream endings((char *) fignore);
901#else
902 std::istrstream endings((char *) fignore); // do i need to make a copy first?
903#endif
904 TString ending;
905
906 ending.ReadToDelim(endings, kDelim);
907
908 while (!ending.IsNull()) {
909 if (s.EndsWith(ending))
910 return kTRUE;
911 else
912 ending.ReadToDelim(endings, kDelim); // next
913 }
914 return kFALSE;
915 }
916}
917
918////////////////////////////////////////////////////////////////////////////////
919///[static utility function]/////////////////////////////
920///
921/// returns a colon-separated string of directories
922/// that CINT will search when you call `#include<...>`
923///
924/// returns empty string on failure.
925///
926////////////////////////////////////////////////////////////
927
929{
930 // >i noticed that .include doesn't list the standard directories like
931 // >/usr/include or /usr/include/CC.
932 // >
933 // >how can i get a list of all the directories the interpreter will
934 // >search through when the user does a #include<...> ?
935 //
936 // Right now, there is no easy command to tell you about it. Instead, I can
937 // describe it here.
938 //
939 // 1) CINT first searches current working directory for #include "xxx"
940 // (#include <xxx> does not)
941 //
942 // 2) CINT searches include path directories given by -I option
943 //
944 // 3) CINT searches following standard include directories.
945 // $CINTSYSDIR/include
946 // $CINTSYSDIR/stl
947 // $CINTSYSDIR/msdev/include if VC++4.0
948 // $CINTSYSDIR/sc/include if Symantec C++
949 // /usr/include
950 // /usr/include/g++ if gcc,g++
951 // /usr/include/CC if HP-UX
952 // /usr/include/codelibs if HP-UX
953 //
954 // .include command only displays 2).
955 //
956 // Thank you
957 // Masaharu Goto
958
959 // 1) current dir
960 // ----------------------------------------------
961 // N/A
962
963
964 // 2) -I option (and #pragma includepath)
965 // ----------------------------------------------
966
967 // get this part of the include path from the interpreter
968 // and stick it in a tmp file.
969 TString outf = ".TTabCom-";
970 FILE *fout = gSystem->TempFileName(outf);
971 if (!fout) return "";
973 fclose(fout);
974
975 // open the tmp file
976 std::ifstream file1(outf);
977 if (!file1) { // error
978 Error("TTabCom::GetSysIncludePath", "could not open file \"%s\"",
979 outf.Data());
980 gSystem->Unlink(outf);
981 return "";
982 }
983 // parse it.
984 TString token; // input buffer
985 TString path; // all directories so far (colon-separated)
986 file1 >> token; // skip "include"
987 file1 >> token; // skip "path:"
988 while (file1) {
989 file1 >> token;
990 if (!token.IsNull()) {
991 if (path.Length() > 0)
992 path.Append(":");
993 path.Append(token.Data() + 2); // +2 skips "-I"
994 }
995 }
996
997 // done with the tmp file
998 file1.close();
999 gSystem->Unlink(outf);
1000
1001 // 3) standard directories
1002 // ----------------------------------------------
1003
1004#ifndef CINTINCDIR
1005 TString sCINTSYSDIR("$ROOTSYS/cint");
1006#else
1007 TString sCINTSYSDIR(CINTINCDIR);
1008#endif
1009 path.Append(":" + sCINTSYSDIR + "/include");
1010// path.Append(":"+CINTSYSDIR+"/stl");
1011// path.Append(":"+CINTSYSDIR+"/msdev/include");
1012// path.Append(":"+CINTSYSDIR+"/sc/include");
1013 path.Append(":/usr/include");
1014// path.Append(":/usr/include/g++");
1015// path.Append(":/usr/include/CC");
1016// path.Append(":/usr/include/codelibs");
1017
1018 return path;
1019}
1020
1021////////////////////////////////////////////////////////////////////////////////
1022///[static utility function]/////////////////////////////
1023///
1024/// calls TSystem::GetPathInfo() to see if "fileName"
1025/// is a system directory.
1026///
1027////////////////////////////////////////////////////////
1028
1029Bool_t TTabCom::IsDirectory(const char fileName[])
1030{
1031 FileStat_t stat;
1032 if (!gSystem->GetPathInfo(fileName, stat))
1033 return R_ISDIR(stat.fMode);
1034 else
1035 return false;
1036}
1037
1038////////////////////////////////////////////////////////////////////////////////
1039///[static utility function]/////////////////////////////
1040///
1041/// creates a list containing the full path name for each file
1042/// in the (colon separated) string "path1"
1043///
1044/// memory is allocated with "new", so
1045/// whoever calls this function takes responsibility for deleting it.
1046///
1047///////////////////////////////////////////////////////////////////////
1048
1050{
1051 assert(path1 != nullptr);
1052 if (!path1[0]) path1 = ".";
1053
1054 TContainer *pList = new TContainer; // maybe use RTTI here? (since its a static function)
1055#ifdef R__SSTREAM
1056 std::istringstream path((char *) path1);
1057#else
1058 std::istrstream path((char *) path1);
1059#endif
1060
1061 while (path.good())
1062 {
1063 TString dirName;
1064 dirName.ReadToDelim(path, kDelim);
1065 if (dirName.IsNull())
1066 continue;
1067
1068 IfDebug(std::cerr << "NewListOfFilesInPath(): dirName = " << dirName <<
1069 std::endl);
1070
1071 AppendListOfFilesInDirectory(dirName, pList);
1072 }
1073
1074 return pList;
1075}
1076
1077////////////////////////////////////////////////////////////////////////////////
1078///[static utility function]/////////////////////////////
1079///
1080/// true if "fileName"
1081/// 1. is an absolute path ("/tmp/a")
1082/// 2. is a relative path ("../whatever", "./test")
1083/// 3. starts with user name ("~/mail")
1084/// 4. starts with an environment variable ("$ROOTSYS/bin")
1085///
1086///////////////////////////////////////////////////////////////////////////
1087
1089{
1090 char c1 = (fileName.Length() > 0) ? fileName[0] : 0;
1091 return c1 == '/' || c1 == '~' || c1 == '$' || fileName.BeginsWith("./")
1092 || fileName.BeginsWith("../");
1093}
1094
1095////////////////////////////////////////////////////////////////////////////////
1096///[static utility function]/////////////////////////////
1097///
1098/// calling "NoMsg( errorLevel )",
1099/// sets "gErrorIgnoreLevel" to "errorLevel+1" so that
1100/// all errors with "level < errorLevel" will be ignored.
1101///
1102/// calling the function with a negative argument
1103/// (e.g., "NoMsg( -1 )")
1104/// resets gErrorIgnoreLevel to its previous value.
1105///
1106///////////////////////////////////////////////////////////////////
1107
1108void TTabCom::NoMsg(Int_t errorLevel)
1109{
1110 ////////////////////////////////////////////////////////////////
1111 //
1112 // if you call the function twice with a non-negative argument
1113 // (without an intervening call with a negative argument)
1114 // it will complain because it is almost certainly an error
1115 // that will cause the function to loose track of the previous
1116 // value of gErrorIgnoreLevel.
1117 //
1118 // most common causes: 1. suspiciously placed "return;" statement
1119 // 2. calling a function that calls "NoMsg()"
1120 //
1121 //////////////////////////////////////////////////////////////////
1122
1123 const Int_t kNotDefined = -2;
1124 static Int_t old_level = kNotDefined;
1125
1126 if (errorLevel < 0) // reset
1127 {
1128 if (old_level == kNotDefined) {
1129 std::cerr << "NoMsg(): ERROR 1. old_level==" << old_level << std::endl;
1130 return;
1131 }
1132
1133 gErrorIgnoreLevel = old_level; // restore
1134 old_level = kNotDefined;
1135 } else // set
1136 {
1137 if (old_level != kNotDefined) {
1138 std::cerr << "NoMsg(): ERROR 2. old_level==" << old_level << std::endl;
1139 return;
1140 }
1141
1142 old_level = gErrorIgnoreLevel;
1143 if (gErrorIgnoreLevel <= errorLevel)
1144 gErrorIgnoreLevel = errorLevel + 1;
1145 }
1146}
1147
1148//
1149// static utility functions
1150//
1151// ----------------------------------------------------------------------------
1152
1153
1154// ----------------------------------------------------------------------------
1155//
1156// private member functions
1157//
1158//
1159
1160////////////////////////////////////////////////////////////////////////////////
1161/// [private]
1162
1164 const TSeqCollection * pListOfCandidates,
1165 const char appendage[],
1166 std::ostream& out,
1168{
1169 // returns position of first change in buffer
1170 // ------------------------------------------
1171 // -2 ==> new line altogether (whole thing needs to be redrawn, including prompt)
1172 // -1 ==> no changes
1173 // 0 ==> beginning of line
1174 // 1 ==> after 1st char
1175 // n ==> after nth char
1176
1177 IfDebug(std::cerr << "TTabCom::Complete() ..." << std::endl);
1178 assert(fpLoc != nullptr);
1179 assert(pListOfCandidates != nullptr);
1180
1181 Int_t pos = 0; // position of first change
1182 const int loc = *fpLoc; // location where TAB was pressed
1183
1184 // -----------------------------------------
1185 //
1186 // 1. get the substring we need to complete
1187 //
1188 // NOTES:
1189 // s1 = original buffer
1190 // s2 = sub-buffer from 0 to wherever the user hit TAB
1191 // s3 = the actual text that needs completing
1192 //
1193 // -----------------------------------------
1194 TString s1(fBuf);
1195 TString s2 = s1(0, loc);
1196 TString s3 = s2(re);
1197
1198 int start = s2.Index(re);
1199
1200 IfDebug(std::cerr << " s1: " << s1 << std::endl);
1201 IfDebug(std::cerr << " s2: " << s2 << std::endl);
1202 IfDebug(std::cerr << " s3: " << s3 << std::endl);
1203 IfDebug(std::cerr << "start: " << start << std::endl);
1204 IfDebug(std::cerr << std::endl);
1205
1206 // -----------------------------------------
1207 // 2. go through each possible completion,
1208 // keeping track of the number of matches
1209 // -----------------------------------------
1210 TList listOfMatches; // list of matches (local filenames only) (insertion order must agree across these 3 lists)
1211 TList listOfFullPaths; // list of matches (full filenames) (insertion order must agree across these 3 lists)
1212 listOfMatches.SetOwner();
1213 listOfFullPaths.SetOwner();
1214
1215 int nMatches = 0; // number of matches
1216 TObject *pObj; // pointer returned by iterator
1217 TIter next_candidate(pListOfCandidates);
1218 TIter next_match(&listOfMatches);
1219 TIter next_fullpath(&listOfFullPaths);
1220
1221 // stick all matches into "listOfMatches"
1222 while ((pObj = next_candidate())) {
1223 // get the full filename
1224 const char *s4 = pObj->GetName();
1225
1226 assert(s4 != nullptr);
1227
1228 // pick off tail
1229 const char *s5 = strrchr(s4, '/');
1230 if (!s5)
1231 s5 = s4; // no '/' found
1232 else
1233 s5 += 1; // advance past '/'
1234
1235 // if case sensitive (normal behaviour), check for match
1236 // if case insensitive, convert to TString and compare case insensitively
1237 if ((cmp == TString::kExact) && (strstr(s5, s3) == s5)) {
1238 nMatches += 1;
1239 listOfMatches.Add(new TObjString(s5));
1240 listOfFullPaths.Add(new TObjString(s4));
1241 IfDebug(std::cerr << "adding " << s5 << '\t' << s4 << std::endl);
1242 } else if (cmp == TString::kIgnoreCase) {
1243 TString ts5(s5);
1244 if (ts5.BeginsWith(s3, cmp))
1245 {
1246 nMatches += 1;
1247 listOfMatches.Add(new TObjString(s5));
1248 listOfFullPaths.Add(new TObjString(s4));
1249 IfDebug(std::cerr << "adding " << s5 << '\t' << s4 << std::endl);
1250 }
1251 } else {
1252//rdm IfDebug(std::cerr << "considered " << s5 << '\t' << s4 << std::endl);
1253 }
1254
1255 }
1256
1257 // -----------------------------------------
1258 // 3. beep, list, or complete
1259 // depending on how many matches were found
1260 // -----------------------------------------
1261
1262 // 3a. no matches ==> bell
1263 TString partialMatch = "";
1264
1265 if (nMatches == 0) {
1266 // Ring a bell!
1267 gSystem->Beep();
1268 pos = -1;
1269 goto done; //* RETURN *//
1270 }
1271 // 3b. one or more matches.
1272 char match[1024];
1273
1274 if (nMatches == 1) {
1275 // get the (lone) match
1276 const char *short_name = next_match()->GetName();
1277 const char *full_name = next_fullpath()->GetName();
1278
1279 pObj = pListOfCandidates->FindObject(short_name);
1280 if (pObj) {
1281 IfDebug(std::cerr << std::endl << "class: " << pObj->ClassName() << std::endl);
1282 TString className = pObj->ClassName();
1283 if (0);
1284 else if (className == "TMethod" || className == "TFunction") {
1285 TFunction *pFunc = (TFunction *) pObj;
1286 if (0 == pFunc->GetNargs())
1287 appendage = "()"; // no args
1288 else
1289 appendage = "("; // user needs to supply some args
1290 } else if (className == "TDataMember") {
1291 appendage = " ";
1292 }
1293 }
1294
1295 CopyMatch(match, sizeof(match), short_name, appendage, full_name);
1296 } else {
1297 // multiple matches ==> complete as far as possible
1298 Char_t ch;
1299 Int_t nGoodStrings;
1300
1301 for (int i = 0;
1302 (ch = AllAgreeOnChar(i, &listOfMatches, nGoodStrings));
1303 i += 1) {
1304 IfDebug(std::cerr << " i=" << i << " ch=" << ch << std::endl);
1305 partialMatch.Append(ch);
1306 }
1307
1308 const char *s;
1309 const char *s0;
1310
1311 // multiple matches, but maybe only 1 of them is any good.
1312 if (nGoodStrings == 1) {
1313
1314 // find the 1 good match
1315 do {
1316 s = next_match()->GetName();
1317 s0 = next_fullpath()->GetName();
1318 }
1319 while (ExcludedByFignore(s));
1320
1321 // and use it.
1322 CopyMatch(match, sizeof(match), s, appendage, s0);
1323 } else {
1324 IfDebug(std::cerr << "more than 1 GoodString" << std::endl);
1325
1326 if (partialMatch.Length() > s3.Length())
1327 // this partial match is our (partial) completion.
1328 {
1329 CopyMatch(match, sizeof(match), partialMatch.Data());
1330 } else
1331 // couldn't do any completing at all,
1332 // print a list of all the ambiguous matches
1333 // (except for those excluded by "FileIgnore")
1334 {
1335 IfDebug(std::cerr << "printing ambiguous matches" << std::endl);
1336 std::set<std::string> alreadyPrinted;
1337 while ((pObj = next_match())) {
1338 s = pObj->GetName();
1339 if (alreadyPrinted.insert(s).second) {
1340 // Nothing of that name has been printed yet.
1341 s0 = next_fullpath()->GetName();
1342 if (!ExcludedByFignore(s) || nGoodStrings == 0) {
1343 if (IsDirectory(s0))
1344 out << s << "/" << std::endl;
1345 else
1346 out << s << std::endl;
1347 }
1348 }
1349 }
1350 pos = -2;
1351 if (cmp == TString::kExact || partialMatch.Length() < s3.Length()) {
1352 goto done; //* RETURN *//
1353 } // else:
1354 // update the matching part, will have changed
1355 // capitalization because only cmp == TString::kIgnoreCase
1356 // matches.
1357 CopyMatch(match, sizeof(match), partialMatch.Data());
1358 }
1359 }
1360 }
1361
1362
1363 // ---------------------------------------
1364 // 4. finally write text into the buffer.
1365 // ---------------------------------------
1366 {
1367 int i = strlen(fBuf); // old EOL position is i
1368 int l = strlen(match) - (loc - start); // new EOL position will be i+L
1369
1370 // first check for overflow
1371 if (strlen(fBuf) + strlen(match) + 1 > BUF_SIZE) {
1372 Error("TTabCom::Complete", "buffer overflow");
1373 pos = -2;
1374 goto done; /* RETURN */
1375 }
1376 // debugging output
1377 IfDebug(std::cerr << " i=" << i << std::endl);
1378 IfDebug(std::cerr << " L=" << l << std::endl);
1379 IfDebug(std::cerr << "loc=" << loc << std::endl);
1380
1381 // slide everything (including the null terminator) over to make space
1382 for (; i >= loc; i -= 1) {
1383 fBuf[i + l] = fBuf[i];
1384 }
1385
1386 // insert match
1387 strlcpy(fBuf + start, match, BUF_SIZE - start);
1388
1389 // the "get"->"Get" case of TString::kIgnore sets pos to -2
1390 // and falls through to update the buffer; we need to return
1391 // -2 in that case, so check here:
1392 if (pos != -2) {
1393 pos = loc; // position of first change in "fBuf"
1394 if (cmp == TString::kIgnoreCase && pos < 0) {
1395 // We might have changed somthing before loc, due to differences in
1396 // capitalization. So return start:
1397 pos = start;
1398 }
1399 }
1400 *fpLoc = loc + l; // new cursor position
1401 }
1402
1403done: // <----- goto label
1404 // un-init
1405 fpLoc = nullptr;
1406 fBuf = nullptr;
1407
1408 return pos;
1409}
1410
1411////////////////////////////////////////////////////////////////////////////////
1412/// [private]
1413
1414void TTabCom::CopyMatch(char *dest, int dest_len,
1415 const char *localName,
1416 const char *appendage,
1417 const char *fullName) const
1418{
1419 // if "appendage" is 0, no appendage is applied.
1420 //
1421 // if "appendage" is of the form "filenameXXX" then,
1422 // "filename" is ignored and "XXX" is taken to be the appendage,
1423 // but it will only be applied if the file is not a directory...
1424 // if the file is a directory, a "/" will be used for the appendage instead.
1425 //
1426 // if "appendage" is of the form "XXX" then "XXX" will be appended to the match.
1427
1428 assert(dest != nullptr);
1429 assert(localName != nullptr);
1430
1431 // potential buffer overflow.
1432 strlcpy(dest, localName, dest_len);
1433
1434 const char *key = "filename";
1435 const int key_len = strlen(key);
1436
1437 IfDebug(std::cerr << "CopyMatch()." << std::endl);
1438 IfDebug(std::cerr << "localName: " << (localName ? localName : "0") <<
1439 std::endl);
1440 IfDebug(std::cerr << "appendage: " << (appendage ? appendage : "0") <<
1441 std::endl);
1442 IfDebug(std::cerr << " fullName: " << (fullName ? fullName : "0") <<
1443 std::endl);
1444
1445
1446 // check to see if "appendage" starts with "key"
1447 if (appendage && strncmp(appendage, key, key_len) == 0) {
1448 // filenames get special treatment
1449 appendage += key_len;
1450 IfDebug(std::cerr << "new appendage: " << appendage << std::endl);
1451 if (IsDirectory(fullName)) {
1452 if (fullName)
1453 strlcat(dest, "/", dest_len);
1454 } else {
1455 if (appendage)
1456 strlcat(dest, appendage, dest_len);
1457 }
1458 } else {
1459 if (appendage)
1460 strlcat(dest, appendage, dest_len);
1461 }
1462}
1463
1464////////////////////////////////////////////////////////////////////////////////
1465/// [private]
1466
1468{
1469 assert(fBuf != nullptr);
1470
1471 const char *pStart; // start of match
1472 const char *pEnd; // end of match
1473
1474 for (int context = 0; context < kNUM_PAT; ++context) {
1475 pEnd = Matchs(fBuf, *fpLoc, fPat[context], &pStart);
1476 if (pEnd) {
1477 IfDebug(std::cerr << std::endl
1478 << "context=" << context << " "
1479 << "RegExp=" << fRegExp[context]
1480 << std::endl);
1481 return EContext_t(context); //* RETURN *//
1482 }
1483 }
1484
1485 return kUNKNOWN_CONTEXT; //* RETURN *//
1486}
1487
1488////////////////////////////////////////////////////////////////////////////////
1489/// [private]
1490
1492 const char defaultPath[]) const
1493{
1494 if (PathIsSpecifiedInFileName(fileName)) {
1495 TString path = fileName;
1496 gSystem->ExpandPathName(path);
1497 Int_t end = path.Length()-1;
1498 if (end>0 && path[end]!='/' && path[end]!='\\') {
1499 path = gSystem->GetDirName(path);
1500 }
1501 return path;
1502 } else {
1503 TString newBase, extendedPath;
1504 if (fileName.Contains("/")) {
1505 Int_t end = fileName.Length()-1;
1506 if (fileName[end] != '/' && fileName[end] != '\\') {
1507 newBase = gSystem->GetDirName(fileName);
1508 } else {
1509 newBase = fileName;
1510 }
1511 extendedPath = ExtendPath(defaultPath, newBase);
1512 } else {
1513 newBase = "";
1514 extendedPath = defaultPath;
1515 }
1516 IfDebug(std::cerr << std::endl);
1517 IfDebug(std::cerr << " fileName: " << fileName << std::endl);
1518 IfDebug(std::cerr << " pathBase: " << newBase << std::endl);
1519 if (defaultPath) {
1520 IfDebug(std::cerr << " defaultPath: " << defaultPath << std::endl);
1521 } else {
1522 IfDebug(std::cerr << " defaultPath: " << std::endl);
1523 }
1524 IfDebug(std::cerr << "extendedPath: " << extendedPath << std::endl);
1525 IfDebug(std::cerr << std::endl);
1526
1527 return extendedPath;
1528 }
1529}
1530
1531////////////////////////////////////////////////////////////////////////////////
1532/// [private]
1533
1534TString TTabCom::ExtendPath(const char originalPath[], TString newBase) const
1535{
1536 if (newBase.BeginsWith("/"))
1537 newBase.Remove(TString::kLeading, '/');
1538#ifdef R__SSTREAM
1539 std::stringstream str;
1540#else
1541 std::strstream str;
1542#endif
1543 TString dir;
1544 TString newPath;
1545 if (originalPath) str << originalPath;
1546
1547 while (str.good())
1548 {
1549 dir = "";
1550 dir.ReadToDelim(str, kDelim);
1551 if (dir.IsNull())
1552 continue; // ignore blank entries
1553 newPath.Append(dir);
1554 if (!newPath.EndsWith("/"))
1555 newPath.Append("/");
1556 newPath.Append(newBase);
1557 newPath.Append(kDelim);
1558 }
1559
1560 return newPath.Strip(TString::kTrailing, kDelim);
1561}
1562
1563////////////////////////////////////////////////////////////////////////////////
1564/// [private]
1565
1566Int_t TTabCom::Hook(char *buf, int *pLoc, std::ostream& out)
1567{
1568 // initialize
1569 fBuf = buf;
1570 fpLoc = pLoc;
1571
1572 // frodo: iteration counter for recursive MakeClassFromVarName
1573 fLastIter = 0;
1574
1575 // default
1576 Int_t pos = -2; // position of the first character that was changed in the buffer (needed for redrawing)
1577
1578 // get the context this tab was triggered in.
1579 EContext_t context = DetermineContext();
1580
1581 // get the substring that triggered this tab (as defined by "SetPattern()")
1582 const char dummy[] = ".";
1583 TRegexp re1(context == kUNKNOWN_CONTEXT ? dummy : fRegExp[context]);
1584 TString s1(fBuf);
1585 TString s2 = s1(0, *fpLoc);
1586 TString s3 = s2(re1);
1587
1588 switch (context) {
1589 case kUNKNOWN_CONTEXT:
1590 std::cerr << std::endl << "tab completion not implemented for this context" <<
1591 std::endl;
1592 pos = -2;
1593 break;
1594
1595 case kSYS_UserName:
1596 {
1597 const TSeqCollection *pListOfUsers = GetListOfUsers();
1598
1599 pos = Complete("[^~]*$", pListOfUsers, "/", out);
1600 }
1601 break;
1602 case kSYS_EnvVar:
1603 {
1604 const TSeqCollection *pEnv = GetListOfEnvVars();
1605
1606 pos = Complete("[^$]*$", pEnv, "", out);
1607 }
1608 break;
1609
1610 case kCINT_stdout:
1611 case kCINT_stderr:
1612 case kCINT_stdin:
1613 {
1614 const TString fileName = s3("[^ ><]*$");
1615 const TString filePath = DeterminePath(fileName,nullptr);
1616 const TSeqCollection *pListOfFiles =
1617 GetListOfFilesInPath(filePath.Data());
1618
1619// pos = Complete( "[^ /]*$", pListOfFiles, " ", out );
1620 pos = Complete("[^ /]*$", pListOfFiles, "filename ", out);
1621 }
1622 break;
1623
1624 case kCINT_Edit:
1625 case kCINT_Load:
1626 case kCINT_Exec:
1627 case kCINT_EXec:
1628 {
1629 const TString fileName = s3("[^ ]*$");
1630 const TString macroPath =
1632 const TSeqCollection *pListOfFiles =
1633 GetListOfFilesInPath(macroPath.Data());
1634
1635// pos = Complete( "[^ /]*$", pListOfFiles, " ", out);
1636 pos = Complete("[^ /]*$", pListOfFiles, "filename ", out);
1637 }
1638 break;
1639
1640 case kCINT_pragma:
1641 {
1642 pos = Complete("[^ ]*$", GetListOfPragmas(), "", out);
1643 }
1644 break;
1645 case kCINT_includeSYS:
1646 {
1647 TString fileName = s3("[^<]*$");
1648 if (PathIsSpecifiedInFileName(fileName) || fileName.Contains("/")) {
1649 TString includePath =
1650 DeterminePath(fileName, GetSysIncludePath());
1651
1652// pos = Complete( "[^</]*$", GetListOfFilesInPath( includePath ), "> ", out);
1653 pos =
1654 Complete("[^</]*$", GetListOfFilesInPath(includePath),
1655 "filename> ", out);
1656 } else {
1657// pos = Complete( "[^</]*$", GetListOfSysIncFiles(), "> ", out);
1658 pos =
1659 Complete("[^</]*$", GetListOfSysIncFiles(), "filename> ", out);
1660 }
1661 }
1662 break;
1663 case kCINT_includePWD:
1664 {
1665 const TString fileName = s3("[^\"]*$");
1666 const TString includePath = DeterminePath(fileName, ".");
1667 const TSeqCollection *pListOfFiles =
1668 GetListOfFilesInPath(includePath.Data());
1669
1670// pos = Complete( "[^\"/]*$", pListOfFiles, "\" ", out);
1671 pos = Complete("[^\"/]*$", pListOfFiles, "filename\" ", out);
1672 }
1673 break;
1674
1675 case kCINT_cpp:
1676 {
1677 pos = Complete("[^# ]*$", GetListOfCppDirectives(), " ", out);
1678 }
1679 break;
1680
1681 case kROOT_Load:
1682 {
1683 const TString fileName = s3("[^\"]*$");
1684 const TString dynamicPath = DeterminePath(fileName, gSystem->GetDynamicPath());
1685 const TSeqCollection *pListOfFiles = GetListOfFilesInPath(dynamicPath);
1686
1687// pos = Complete( "[^\"/]*$", pListOfFiles, "\");", out);
1688 pos = Complete("[^\"/]*$", pListOfFiles, "filename\");", out);
1689 }
1690 break;
1691
1692 case kSYS_FileName:
1693 {
1694 const TString fileName = s3("[^ \"]*$");
1695 const TString filePath = DeterminePath(fileName,".");
1696 const TSeqCollection *pListOfFiles = GetListOfFilesInPath(filePath.Data());
1697
1698 pos = Complete("[^\" /]*$", pListOfFiles, "filename\"", out);
1699 }
1700 break;
1701
1702 case kCXX_ScopeMember:
1703 {
1704 const EContext_t original_context = context; // save this for later
1705
1706 TClass *pClass;
1707 // may be a namespace, class, object, or pointer
1708 TString name = s3("^[_a-zA-Z][_a-zA-Z0-9]*");
1709
1710 IfDebug(std::cerr << std::endl);
1711 IfDebug(std::cerr << "name: " << '"' << name << '"' << std::endl);
1712
1713 // We need to decompose s3 a little more:
1714 // The part name is the partial symbol at the end of ::
1715 // eg. given s3 = "foo::bar::part" , partname = "part"
1716 TString partname = s3("[_a-zA-Z][_a-zA-Z0-9]*$");
1717
1718 // The prefix, considering the s3 = "foo::bar::part" example would be
1719 // prefix = "foo::bar::". prefix equals the empty string if there is only one
1720 // or no set of colons in s3.
1721 // Note: we reconstruct the fully qualified name with a while loop because
1722 // it does not seem that TRegexp can handle something like "([_a-zA-Z][_a-zA-Z0-9]*::)+$"
1723 TString prefix = "";
1724 TString str = s2;
1725 str.Remove(str.Length() - partname.Length(), partname.Length());
1726 while (1) {
1727 TString sym = str("[_a-zA-Z][_a-zA-Z0-9]*::$");
1728 if (sym.Length() == 0)
1729 break;
1730 str.Remove(str.Length() - sym.Length(), sym.Length());
1731 prefix = sym + prefix;
1732 }
1733
1734 // Not the preprefix would be = "foo::" from our previous example or the empty
1735 // string, "" if there is only one or no set of colons in prefix, eg. prefix = "bar::"
1736 TString preprefix = prefix;
1737 TString sym = prefix("[_a-zA-Z][_a-zA-Z0-9]*::$");
1738 preprefix.Remove(preprefix.Length() - sym.Length(), sym.Length());
1739
1740 IfDebug(std::cerr << "prefix: " << '"' << prefix << '"' << std::endl);
1741 IfDebug(std::cerr << "preprefix: " << '"' << preprefix << '"' << std::endl);
1742
1743 TString namesp = prefix;
1744 if (namesp.Length() >= 2)
1745 namesp.Remove(namesp.Length() - 2, 2); // Remove the '::' at the end of the string.
1746 IfDebug(std::cerr << "namesp: " << '"' << namesp << '"' << std::endl);
1747
1748 // Make sure autoloading happens (if it can).
1750
1751 TContainer *pList = new TContainer;
1752 // Add all classes to pList that contain the prefix, i.e. are in the
1753 // specified namespace.
1754 const TSeqCollection *tmp = GetListOfClasses();
1755 if (!tmp) break;
1756
1757 Int_t i;
1758 for (i = 0; i < tmp->GetSize(); i++) {
1759 TString astr = ((TObjString *) tmp->At(i))->String();
1760 TString rxp = "^";
1761 rxp += prefix;
1762 if (astr.Contains(TRegexp(rxp))) {
1763 astr.Remove(0, prefix.Length());
1764 TString s = astr("^[^: ]*");
1765 TObjString *ostr = new TObjString(s);
1766 if (!pList->Contains(ostr))
1767 pList->Add(ostr);
1768 else
1769 delete ostr;
1770 }
1771 }
1772
1773 // If a class with the same name as the Namespace name exists then
1774 // add it to the pList. (I don't think the C++ spec allows for this
1775 // but do this anyway, cant harm).
1776 pClass = TryMakeClassFromClassName(preprefix + name);
1777 if (pClass) {
1778 pList->AddAll(pClass->GetListOfAllPublicMethods(true));
1779 pList->AddAll(pClass->GetListOfAllPublicDataMembers(true));
1780 }
1781
1782 pos = Complete("[^: ]*$", pList, "", out);
1783
1784 delete pList;
1785
1786 if (context != original_context)
1787 pos = -2;
1788 }
1789 break;
1790
1791 case kCXX_DirectMember:
1793 {
1794 const EContext_t original_context = context; // save this for later
1795
1796 TClass *pClass;
1797
1798 // frodo: Instead of just passing the last portion of the string to
1799 // MakeClassFromVarName(), we now pass the all string and let
1800 // it decide how to handle it... I know it's not the best way
1801 // because of the context handling, but I wanted to "minimize"
1802 // the changes to the current code and this seemed the best way
1803 // to do it
1804 TString name = s1("[_a-zA-Z][-_a-zA-Z0-9<>():.]*$");
1805
1806 IfDebug(std::cerr << std::endl);
1807 IfDebug(std::cerr << "name: " << '"' << name << '"' << std::endl);
1808
1809 switch (context) {
1810 case kCXX_DirectMember:
1811 pClass = MakeClassFromVarName(name, context);
1812 break;
1814 pClass = MakeClassFromVarName(name, context);
1815 break;
1816 default:
1817 Fatal("TTabCom::Hook","Conext case %d not handled",context);
1818 return 0; // Avoid warning about uninitialized pClass.
1819 }
1820 if (!pClass) {
1821 pos = -2;
1822 break;
1823 }
1824
1825 TContainer *pList = new TContainer;
1826
1827 pList->AddAll(pClass->GetListOfAllPublicMethods());
1828 pList->AddAll(pClass->GetListOfAllPublicDataMembers());
1829
1830 switch (context) {
1831 case kCXX_DirectMember:
1832 {
1833 int* store_fpLoc = fpLoc;
1834 char* store_fBuf = fBuf;
1835 pos = Complete("[^. ]*$", pList, "(", out);
1836 if (pos == -1) {
1837 fpLoc = store_fpLoc;
1838 fBuf = store_fBuf;
1839 pos = Complete("[^. ]*$", pList, "(", out, TString::kIgnoreCase);
1840 }
1841 break;
1842 }
1844 pos = Complete("[^> ]*$", pList, "(", out);
1845 break;
1846 default:
1847 Fatal("TTabCom::Hook","Conext case %d not handled",context);
1848 return 0; // Avoid warning about uninitialized pClass.
1849 }
1850
1851 delete pList;
1852
1853 if (context != original_context)
1854 pos = -2;
1855 }
1856 break;
1857
1858 case kCXX_ScopeProto:
1859 {
1860 const EContext_t original_context = context; // save this for later
1861
1862 // get class
1863 TClass *pClass;
1864 TString name = s3("^[_a-zA-Z][_a-zA-Z0-9]*");
1865 // "name" may now be the name of a class, object, or pointer
1866
1867 IfDebug(std::cerr << std::endl);
1868 IfDebug(std::cerr << "name: " << '"' << name << '"' << std::endl);
1869
1870 // We need to decompose s3 a little more:
1871 // The partname is the method symbol and a bracket at the end of ::
1872 // eg. given s3 = "foo::bar::part(" , partname = "part("
1873 TString partname = s3("[_a-zA-Z][_a-zA-Z0-9]* *($");
1874
1875 // The prefix, considering the s3 = "foo::bar::part" example would be
1876 // prefix = "foo::bar::". prefix equals the empty string if there is only one
1877 // or no set of colons in s3.
1878 // Note: we reconstruct the fully qualified name with a while loop because
1879 // it does not seem that TRegexp can handle something like "([_a-zA-Z][_a-zA-Z0-9]*::)+$"
1880 TString prefix = "";
1881 TString str = s2;
1882 str.Remove(str.Length() - partname.Length(), partname.Length());
1883 while (1) {
1884 TString sym = str("[_a-zA-Z][_a-zA-Z0-9]*::$");
1885 if (sym.Length() == 0)
1886 break;
1887 str.Remove(str.Length() - sym.Length(), sym.Length());
1888 prefix = sym + prefix;
1889 }
1890
1891 // Not the preprefix would be = "foo::" from our previous example or the empty
1892 // string, "" if there is only one or no set of colons in prefix, eg. prefix = "bar::"
1893 TString preprefix = prefix;
1894 TString sym = prefix("[_a-zA-Z][_a-zA-Z0-9]*::$");
1895 preprefix.Remove(preprefix.Length() - sym.Length(), sym.Length());
1896
1897 IfDebug(std::cerr << "prefix: " << '"' << prefix << '"' << std::endl);
1898 IfDebug(std::cerr << "preprefix: " << '"' << preprefix << '"' << std::endl);
1899
1900 pClass = MakeClassFromClassName(preprefix + name);
1901 if (!pClass) {
1902 pos = -2;
1903 break;
1904 }
1905 // get method name
1906 TString methodName;
1907
1908 // (normal member function)
1909 methodName = s3("[^:>\\.(]*($");
1910 methodName.Chop();
1911 methodName.Remove(TString::kTrailing, ' ');
1912
1913 IfDebug(std::cerr << methodName << std::endl);
1914
1915 // get methods
1916 TContainer *pList = new TContainer;
1917 pList->AddAll(pClass->GetListOfAllPublicMethods());
1918
1919 // print prototypes
1920 Bool_t foundOne = kFALSE;
1921 TIter nextMethod(pList);
1922 TMethod *pMethod;
1923 while ((pMethod = (TMethod *) nextMethod())) {
1924 if (methodName == pMethod->GetName()) {
1925 foundOne = kTRUE;
1926 out << pMethod->GetReturnTypeName()
1927 << " " << pMethod->GetName()
1928 << pMethod->GetSignature();
1929 const char *comment = pMethod->GetCommentString();
1930 if (comment && comment[0] != '\0') {
1931 out << " \t// " << comment;
1932 }
1933 out << std::endl;
1934 }
1935 }
1936
1937 // done
1938 if (foundOne) {
1939 pos = -2;
1940 } else {
1941 gSystem->Beep();
1942 pos = -1;
1943 }
1944
1945 // cleanup
1946 delete pList;
1947
1948 if (context != original_context)
1949 pos = -2;
1950 }
1951 break;
1952
1953 case kCXX_DirectProto:
1954 case kCXX_IndirectProto:
1955 case kCXX_NewProto:
1957 {
1958 const EContext_t original_context = context; // save this for later
1959
1960 // get class
1961 TClass *pClass;
1962 TString name;
1963 if (context == kCXX_NewProto) {
1964 name = s3("[_a-zA-Z][_a-zA-Z0-9:]* *($", 3);
1965 name.Chop();
1966 name.Remove(TString::kTrailing, ' ');
1967 // "name" should now be the name of a class
1968 } else {
1969 name = s3("^[_a-zA-Z][_a-zA-Z0-9:]*");
1970 // "name" may now be the name of a class, object, or pointer
1971 }
1972 IfDebug(std::cerr << std::endl);
1973 IfDebug(std::cerr << "name: " << '"' << name << '"' << std::endl);
1974
1975 // frodo: Again, passing the all string
1976 TString namerec = s1;
1977
1978 switch (context) {
1979 case kCXX_ScopeProto:
1980 pClass = MakeClassFromClassName(name);
1981 break;
1982 case kCXX_DirectProto:
1983 pClass = MakeClassFromVarName(namerec, context); // frodo
1984 break;
1985 case kCXX_IndirectProto:
1986 pClass = MakeClassFromVarName(namerec, context); // frodo
1987 break;
1988 case kCXX_NewProto:
1989 pClass = MakeClassFromClassName(name);
1990 break;
1992 pClass = MakeClassFromClassName(name);
1993 break;
1994 default:
1995 Fatal("TTabCom::Hook","Conext case %d not handled",context);
1996 return 0; // Avoid warning about uninitialized pClass.
1997 }
1998 if (!pClass) {
1999 pos = -2;
2000 break;
2001 }
2002 // get method name
2003 TString methodName;
2004 if (context == kCXX_ConstructorProto || context == kCXX_NewProto) {
2005 // (constructor)
2006 methodName = name("[_a-zA-Z][_a-zA-Z0-9]*$");
2007 } else {
2008 // (normal member function)
2009 methodName = s3("[^:>\\.(]*($");
2010 methodName.Chop();
2011 methodName.Remove(TString::kTrailing, ' ');
2012 }
2013 IfDebug(std::cerr << methodName << std::endl);
2014
2015 // get methods
2016 TContainer *pList = new TContainer;
2017 pList->AddAll(pClass->GetListOfAllPublicMethods());
2018
2019 // print prototypes
2020 Bool_t foundOne = kFALSE;
2021 TIter nextMethod(pList);
2022 TMethod *pMethod;
2023 while ((pMethod = (TMethod *) nextMethod())) {
2024 if (methodName == pMethod->GetName()) {
2025 foundOne = kTRUE;
2026 out << pMethod->GetReturnTypeName()
2027 << " " << pMethod->GetName()
2028 << pMethod->GetSignature();
2029 const char *comment = pMethod->GetCommentString();
2030 if (comment && comment[0] != '\0') {
2031 out << " \t// " << comment;
2032 }
2033 out << std::endl;
2034 }
2035 }
2036
2037 // done
2038 if (foundOne) {
2039 pos = -2;
2040 } else {
2041 gSystem->Beep();
2042 pos = -1;
2043 }
2044
2045 // cleanup
2046 delete pList;
2047
2048 if (context != original_context)
2049 pos = -2;
2050 }
2051 break;
2052
2053 case kCXX_Global:
2054 {
2055 // first need to veto a few possibilities.
2056 int l2 = s2.Length(), l3 = s3.Length();
2057
2058 // "abc().whatever[TAB]"
2059 if (l2 > l3 && s2[l2 - l3 - 1] == '.') {
2060 std::cerr << std::endl <<
2061 "tab completion not implemented for this context" << std::endl;
2062 break; // veto
2063 }
2064 // "abc()->whatever[TAB]"
2065 if (l2 > l3 + 1 && s2(l2 - l3 - 2, 2) == "->") {
2066 std::cerr << std::endl <<
2067 "tab completion not implemented for this context" << std::endl;
2068 break; // veto
2069 }
2070
2071 TContainer *pList = new TContainer;
2072
2073 const TSeqCollection *pL2 = GetListOfClasses();
2074 if (pL2) pList->AddAll(pL2);
2075
2076 //
2077 const TSeqCollection *pC1 = GetListOfGlobals();
2078 if (pC1) pList->AddAll(pC1);
2079 //
2081 if (pC3) pList->AddAll(pC3);
2082
2083 pos = Complete("[_a-zA-Z][_a-zA-Z0-9]*$", pList, "", out);
2084
2085 delete pList;
2086 }
2087 break;
2088
2089 case kCXX_GlobalProto:
2090 {
2091 // get function name
2092 TString functionName = s3("[_a-zA-Z][_a-zA-Z0-9]*");
2093 IfDebug(std::cerr << functionName << std::endl);
2094
2095 TContainer listOfMatchingGlobalFuncs;
2096 TIter nextGlobalFunc(GetListOfGlobalFunctions());
2097 TObject *pObj;
2098 while ((pObj = nextGlobalFunc())) {
2099 if (strcmp(pObj->GetName(), functionName) == 0) {
2100 listOfMatchingGlobalFuncs.Add(pObj);
2101 }
2102 }
2103
2104 if (listOfMatchingGlobalFuncs.IsEmpty()) {
2105 std::cerr << std::endl << "no such function: " << dblquote(functionName)
2106 << std::endl;
2107 } else {
2108 TIter next(&listOfMatchingGlobalFuncs);
2109 TFunction *pFunction;
2110 while ((pFunction = (TFunction *) next())) {
2111 out << pFunction->GetReturnTypeName()
2112 << " " << pFunction->GetName()
2113 << pFunction->GetSignature()
2114 << std::endl;
2115 }
2116 }
2117
2118 pos = -2;
2119 }
2120 break;
2121
2122 /******************************************************************/
2123 /* */
2124 /* default: should never happen */
2125 /* */
2126 /******************************************************************/
2127 default:
2128 Fatal("TTabCom::Hook","Conext case %d not handled",context);
2129 return 0; // Avoid warning about uninitialized pClass.
2130 }
2131
2132 return pos;
2133}
2134
2135////////////////////////////////////////////////////////////////////////////////
2136/// [private]
2137
2139{
2140 // add more patterns somewhere below.
2141 // add corresponding enum to "EContext_t"
2142 //
2143 // note:
2144 // 1. in some cases order is important ...
2145 //
2146 // the order of the "case" statements in "switch( context )" in "TTabCom::Hook()" is Not important.
2147 //
2148 // the order of the "SetPattern()" function calls below is Not important.
2149 //
2150 // the order of the initializers in the "EContext_t" enumeration Is important
2151 // because DetermineContext() goes through the array in order, and returns at the first match.
2152 //
2153 // 2. below, "$" will match cursor position
2154
2155 SetPattern(kSYS_UserName, "~[_a-zA-Z0-9]*$");
2156 SetPattern(kSYS_EnvVar, "$[_a-zA-Z0-9]*$");
2157
2158 SetPattern(kCINT_stdout, "; *>>?.*$"); // stdout
2159 SetPattern(kCINT_stderr, "; *2>>?.*$"); // stderr
2160 SetPattern(kCINT_stdin, "; *<.*$"); // stdin
2161
2162 SetPattern(kCINT_Edit, "^ *\\.E .*$");
2163 SetPattern(kCINT_Load, "^ *\\.L .*$");
2164 SetPattern(kCINT_Exec, "^ *\\.x +[-0-9_a-zA-Z~$./]*$");
2165 SetPattern(kCINT_EXec, "^ *\\.X +[-0-9_a-zA-Z~$./]*$");
2166
2167 SetPattern(kCINT_pragma, "^# *pragma +[_a-zA-Z0-9]*$");
2168 SetPattern(kCINT_includeSYS, "^# *include *<[^>]*$"); // system files
2169 SetPattern(kCINT_includePWD, "^# *include *\"[^\"]*$"); // local files
2170
2171 SetPattern(kCINT_cpp, "^# *[_a-zA-Z0-9]*$");
2172
2173 SetPattern(kROOT_Load, "gSystem *-> *Load *( *\"[^\"]*$");
2174
2175 SetPattern(kCXX_NewProto, "new +[_a-zA-Z][_a-zA-Z0-9:]* *($");
2177 "[_a-zA-Z][_a-zA-Z0-9:]* +[_a-zA-Z][_a-zA-Z0-9]* *($");
2179 "[_a-zA-Z][_a-zA-Z0-9]* *:: *[_a-zA-Z0-9]* *($");
2181 "[_a-zA-Z][_a-zA-Z0-9()]* *\\. *[_a-zA-Z0-9]* *($");
2183 "[_a-zA-Z][_a-zA-Z0-9()]* *-> *[_a-zA-Z0-9]* *($");
2184
2186 "[_a-zA-Z][_a-zA-Z0-9]* *:: *[_a-zA-Z0-9]*$");
2188 "[_a-zA-Z][_a-zA-Z0-9()]* *\\. *[_a-zA-Z0-9()]*$"); //
2189
2191 "[_a-zA-Z][_a-zA-Z0-9()]* *-> *[_a-zA-Z0-9()]*$"); // frodo
2192
2193 SetPattern(kSYS_FileName, "\"[-0-9_a-zA-Z~$./]*$");
2194 SetPattern(kCXX_Global, "[_a-zA-Z][_a-zA-Z0-9]*$");
2195 SetPattern(kCXX_GlobalProto, "[_a-zA-Z][_a-zA-Z0-9]* *($");
2196}
2197
2198////////////////////////////////////////////////////////////////////////////////
2199/// [private]
2200/// (does some specific error handling that makes the function unsuitable for general use.)
2201/// returns a new'd TClass given the name of a class.
2202/// user must delete.
2203/// returns 0 in case of error.
2204
2205TClass *TTabCom::MakeClassFromClassName(const char className[]) const
2206{
2207 // the TClass constructor will print a Warning message for classes that don't exist
2208 // so, ignore warnings temporarily.
2209 NoMsg(kWarning);
2210 TClass *pClass = TClass::GetClass(className);
2211 NoMsg(-1);
2212
2213 if (!pClass){
2214 Error("TTabCom::MakeClassFromClassName", "Unknown class \"%s\"", className);
2215 return nullptr;
2216 }
2217
2218 // make sure "className" exists
2219 // if (pClass->Size() == 0) { //namespace has 0 size
2220 if (pClass->GetListOfAllPublicMethods()->GetSize() == 0 &&
2221 pClass->GetListOfAllPublicDataMembers()->GetSize() == 0) {
2222 // i'm assuming this happens iff there was some error.
2223 // (misspelled the class name, for example)
2224 Error("TTabCom::MakeClassFromClassName", "class \"%s\" is not defined.", className);
2225 return nullptr;
2226 }
2227
2228 return pClass;
2229}
2230
2231////////////////////////////////////////////////////////////////////////////////
2232/// Same as above but does not print the error message.
2233
2234TClass *TTabCom::TryMakeClassFromClassName(const char className[]) const
2235{
2236 // the TClass constructor will print a Warning message for classes that don't exist
2237 // so, ignore warnings temporarily.
2238 NoMsg(kWarning);
2239 TClass *pClass = TClass::GetClass(className);
2240 NoMsg(-1);
2241
2242 return pClass;
2243}
2244
2245////////////////////////////////////////////////////////////////////////////////
2246/// [private]
2247/// (does some specific error handling that makes the function unsuitable for general use.)
2248/// returns a new'd TClass given the name of a variable.
2249/// user must delete.
2250/// returns 0 in case of error.
2251/// if user has operator.() or operator->() backwards, will modify: context, *fpLoc and fBuf.
2252/// context sensitive behavior.
2253
2255 EContext_t & context, int iter)
2256{
2257 // frodo:
2258 // Because of the Member and Proto recursion, this has become a bit
2259 // complicated, so here is how it works:
2260 //
2261 // root [1] var.a.b.c[TAB]
2262 //
2263 // will generate the sucessive calls:
2264 // MakeClassFromVarName("var.a.b.c", context, 0) returns the class of "c"
2265 // MakeClassFromVarName("var.a.b", context, 1) returns the class of "b"
2266 // MakeClassFromVarName("var.a", context, 2) returns the class of "a"
2267 // MakeClassFromVarName("var", context, 3)
2268
2269 // need to make sure "varName" exists
2270 // because "DetermineClass()" prints clumsy error message otherwise.
2271 Bool_t varName_exists = GetListOfGlobals()->Contains(varName) || // check in list of globals first.
2272 (gROOT->FindObject(varName) != nullptr); // then check CINT "shortcut #3"
2273
2274
2275 //
2276 // frodo: Member and Proto recursion code
2277 //
2278 if (0) printf("varName is [%s] with iteration [%i]\n", varName, iter);
2279
2280 // ParseReverse will return 0 if there are no "." or "->" in the varName
2281 Int_t cut = ParseReverse(varName, strlen(varName));
2282
2283 // If it's not a "simple" variable and if there is at least one "." or "->"
2284 if (!varName_exists && cut != 0)
2285 {
2286 TString parentName = varName;
2287 TString memberName = varName;
2288
2289 // Check to see if this is the last call (last member/method)
2290 if (iter > fLastIter) fLastIter = iter;
2291
2292 parentName[cut] = 0;
2293 if (0) printf("Parent string is [%s]\n", parentName.Data());
2294
2295 // We are treating here cases like h->SetXTitle(gROOT->Get<TAB>
2296 // i.e. when the parentName has an unbalanced number of paranthesis.
2297 if (cut>2) {
2298 UInt_t level = 0;
2299 for(Int_t i = cut-1; i>=0; --i) {
2300 switch (parentName[i]) {
2301 case '(':
2302 if (level) --level;
2303 else {
2304 parentName = parentName(i+1,cut-i-1);
2305 i = 0;
2306 }
2307 break;
2308 case ')':
2309 ++level; break;
2310 }
2311 }
2312 }
2313
2314 TClass *pclass;
2315 // Can be "." or "->"
2316 if (varName[cut] == '.') {
2317 memberName = varName+cut+1;
2318 if (0) printf("Member/method is [%s]\n", memberName.Data());
2319 EContext_t subcontext = kCXX_DirectMember;
2320 pclass = MakeClassFromVarName(parentName.Data(), subcontext, iter+1);
2321 } else {
2322 memberName = varName+cut+2;
2323 if (0) printf("Member/method is [%s]\n", memberName.Data());
2324 EContext_t subcontext = kCXX_IndirectMember;
2325 pclass = MakeClassFromVarName(parentName.Data(), subcontext, iter+1);
2326 }
2327
2328 if (0) printf("I got [%s] from MakeClassFromVarName()\n", pclass->GetName());
2329
2330 if (pclass)
2331 {
2332 if (0) printf("Variable [%s] exists!\n", parentName.Data());
2333
2334 // If it's back in the first call of the function, return immediatly
2335 if (iter == 0) return pclass;
2336
2337 if (0) printf("Trying data member [%s] of class [%s] ...\n",
2338 memberName.Data(), pclass->GetName());
2339
2340 // Check if it's a member
2341 TDataMember *dmptr = nullptr; //pclass->GetDataMember(memberName.Data());
2342 TIter next(pclass->GetListOfAllPublicDataMembers());
2343 while ((dmptr = (TDataMember *) next())) {
2344 if (memberName == dmptr->GetName()) break;
2345 }
2346 if (dmptr)
2347 {
2348 if (0) printf("It's a member!\n");
2349
2350 TString returnName = dmptr->GetTypeName();
2351 // if (returnName[returnName.Length()-1] == '*')
2352 // printf("It's a pointer!\n");
2353
2354 TClass *mclass = TClass::GetClass(returnName.Data());
2355 return mclass;
2356 }
2357
2358
2359 // Check if it's a proto: must have ()
2360 // This might not be too safe to use :(
2361 char *parentesis_ptr = (char*)strrchr(memberName.Data(), '(');
2362 if (parentesis_ptr) *parentesis_ptr = 0;
2363
2364
2365 if (0) printf("Trying method [%s] of class [%s] ...\n",
2366 memberName.Data(), pclass->GetName());
2367
2368 // Check if it's a method
2369 TMethod *mptr = nullptr; // pclass->GetMethodAny(memberName.Data());
2370 const TList *mlist = pclass->GetListOfAllPublicMethods();
2371 next = mlist;
2372 while ((mptr = (TMethod *) next())) {
2373 if (strcmp(memberName.Data(),mptr->GetName())==0) break;
2374 }
2375 if (mptr)
2376 {
2377 TString returnName = mptr->GetReturnTypeName();
2378
2379 if (0) printf("It's a method called [%s] with return type [%s]\n",
2380 memberName.Data(), returnName.Data());
2381
2382 // This will handle the methods that returns a pointer to a class
2383 if (returnName[returnName.Length()-1] == '*')
2384 {
2385 returnName[returnName.Length()-1] = 0;
2387 }
2388 else
2389 {
2391 }
2392
2393 TClass *mclass = TClass::GetClass(returnName.Data());
2394 return mclass;
2395 }
2396 }
2397 }
2398
2399 //
2400 // frodo: End of Member and Proto recursion code
2401 //
2402
2403
2404 // not found...
2405 if (!varName_exists) {
2406 std::cerr << std::endl << "variable " << dblquote(varName) << " not defined."
2407 << std::endl;
2408 return nullptr; //* RETURN *//
2409 }
2410
2411 /*****************************************************************************************/
2412 /* */
2413 /* this section is really ugly. */
2414 /* and slow. */
2415 /* it could be made a lot better if there was some way to tell whether or not a given */
2416 /* variable is a pointer or a pointer to a pointer. */
2417 /* */
2418 /*****************************************************************************************/
2419
2420 TString className = DetermineClass(varName);
2421
2422 if (className.IsNull() || className == "*") {
2423 // this will happen if "varName" is a fundamental type (as opposed to class type).
2424 // or a pointer to a pointer.
2425 // or a function pointer.
2426 std::cerr << std::endl << "problem determining class of " << dblquote(varName)
2427 << std::endl;
2428 return nullptr; //* RETURN *//
2429 }
2430
2431 fVarIsPointer = className[className.Length() - 1] == '*';
2432
2433 // frodo: I shouldn't have to do this, but for some reason now I have to
2434 // otherwise the varptr->[TAB] won't work :(
2435 if (fVarIsPointer || className[className.Length() - 1] == '&')
2436 className[className.Length()-1] = 0;
2437
2438 // frodo case '.' dealt with in the previous if statement?!
2439 // frodo: I wasn't able to put the automatic "." to "->" replacing working
2440 // so I just commented out.
2441 //
2442
2443
2444 // Bool_t varIsPointer = className[className.Length() - 1] == '*';
2445
2446 //printf("Context is %i, fContext is %i, pointer is %i\n", context, fContext, fVarIsPointer);
2447
2448 if (fVarIsPointer &&
2449 (context == kCXX_DirectMember || context == kCXX_DirectProto)) {
2450 // user is using operator.() instead of operator->()
2451 // ==>
2452 // 1. we are in wrong context.
2453 // 2. user is lazy
2454 // 3. or maybe confused
2455
2456 // 1. fix the context
2457 switch (context) {
2458 case kCXX_DirectMember:
2459 context = kCXX_IndirectMember;
2460 break;
2461 case kCXX_DirectProto:
2462 context = kCXX_IndirectProto;
2463 break;
2464 default:
2465 Fatal("TTabCom::MakeClassFromVarName","Conext case %d not handled",context);
2466 return nullptr; // Avoid warning about uninitialized pClass.
2467 }
2468
2469 // 2. fix the operator.
2470 int i;
2471 for (i = *fpLoc; fBuf[i] != '.'; i -= 1) {
2472 }
2473 int loc = i;
2474 for (i = strlen(fBuf); i >= loc; i -= 1) {
2475 fBuf[i + 1] = fBuf[i];
2476 }
2477 fBuf[loc] = '-';
2478 fBuf[loc + 1] = '>';
2479 *fpLoc += 1;
2480
2481 // 3. inform the user.
2482 std::cerr << std::endl << dblquote(varName) <<
2483 " is of pointer type. Use this operator: ->" << std::endl;
2484 return nullptr;
2485 }
2486
2487 if (context == kCXX_IndirectMember || context == kCXX_IndirectProto) {
2488 if (fVarIsPointer) {
2489 // frodo: This part no longer makes sense...
2490 className.Chop(); // remove the '*'
2491
2492 if (className[className.Length() - 1] == '*') {
2493 std::cerr << std::endl << "can't handle pointers to pointers." << std::endl;
2494 return nullptr; // RETURN
2495 }
2496 } else {
2497 // user is using operator->() instead of operator.()
2498 // ==>
2499 // 1. we are in wrong context.
2500 // 2. user is lazy
2501 // 3. or maybe confused
2502
2503 // 1. fix the context
2504 switch (context) {
2506 context = kCXX_DirectMember;
2507 break;
2508 case kCXX_IndirectProto:
2509 context = kCXX_DirectProto;
2510 break;
2511 default:
2512 Fatal("TTabCom::MakeClassFromVarName","Conext case %d not handled",context);
2513 return nullptr; // Avoid warning about uninitialized pClass.
2514 }
2515
2516 // 2. fix the operator.
2517 int i;
2518 for (i = *fpLoc; fBuf[i - 1] != '-' && fBuf[i] != '>'; i -= 1) {
2519 }
2520 fBuf[i - 1] = '.';
2521 int len = strlen(fBuf);
2522 for (; i < len; i += 1) {
2523 fBuf[i] = fBuf[i + 1];
2524 }
2525 *fpLoc -= 1;
2526
2527 // 3. inform the user.
2528 std::cerr << std::endl << dblquote(varName) <<
2529 " is not of pointer type. Use this operator: ." << std::endl;
2530 return nullptr;
2531 }
2532 }
2533
2534 className.Strip(TString::kBoth);
2535
2536 return TClass::GetClass(className);
2537}
2538
2539////////////////////////////////////////////////////////////////////////////////
2540/// [private]
2541
2542void TTabCom::SetPattern(EContext_t handle, const char regexp[])
2543{
2544 // prevent overflow
2545 if (handle >= kNUM_PAT) {
2546 std::cerr << std::endl
2547 << "ERROR: handle="
2548 << (int) handle << " >= kNUM_PAT=" << (int) kNUM_PAT << std::endl;
2549 return;
2550 }
2551
2552 fRegExp[handle] = regexp;
2553 Makepat(regexp, fPat[handle], MAX_LEN_PAT);
2554}
2555
2556
2557
2558////////////////////////////////////////////////////////////////////////////////
2559///
2560/// Returns the place in the string where to put the \0, starting the search
2561/// from "start"
2562///
2563
2564int TTabCom::ParseReverse(const char *var_str, int start)
2565{
2566 int end = 0;
2567 if (start > (int)strlen(var_str)) start = strlen(var_str);
2568
2569 for (int i = start; i > 0; i--)
2570 {
2571 if (var_str[i] == '.') return i;
2572 if (var_str[i] == '>' && i > 0 && var_str[i-1] == '-') return i-1;
2573 }
2574
2575 return end;
2576}
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:101
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
#define ClassImp(name)
Definition Rtypes.h:377
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
constexpr Int_t kWarning
Definition TError.h:45
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:555
#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:3845
TList * GetListOfAllPublicDataMembers(Bool_t load=kTRUE)
Returns a list of all public data members of this class and its base classes.
Definition TClass.cxx:3862
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:2968
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:439
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:207
static const char * GetMacroPath()
Get macro search path. Static utility function.
Definition TROOT.cxx:2734
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:1108
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:1566
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:892
void InitPatterns()
[private]
Definition TTabCom.cxx:2138
void CopyMatch(char *dest, int dest_len, const char *localName, const char *appendage=nullptr, const char *fullName=nullptr) const
[private]
Definition TTabCom.cxx:1414
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:1491
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:1049
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:2254
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:2542
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:2205
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:1088
TString ExtendPath(const char originalPath[], TString newBase) const
[private]
Definition TTabCom.cxx:1534
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:1163
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:2564
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:1029
EContext_t DetermineContext() const
[private]
Definition TTabCom.cxx:1467
static TString GetSysIncludePath()
[static utility function]/////////////////////////////
Definition TTabCom.cxx:928
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:2234
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
TLine l
Definition textangle.C:4