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 const int old_len = strlen(fBuf); // old EOL position is old_len
1368 const int match_len = strlen(match);
1369 const int added_len = match_len - (loc - start); // new EOL position will be old_len+added_len
1370
1371 // first check for overflow
1372 if (old_len + added_len + 1 > BUF_SIZE || start > loc || start + match_len + 1 > BUF_SIZE) {
1373 Error("TTabCom::Complete", "buffer overflow");
1374 pos = -2;
1375 goto done; /* RETURN */
1376 }
1377 // debugging output
1378 IfDebug(std::cerr << " i=" << old_len << std::endl);
1379 IfDebug(std::cerr << " L=" << added_len << std::endl);
1380 IfDebug(std::cerr << "loc=" << loc << std::endl);
1381
1382 // slide everything (including the null terminator) over to make space
1383 for (int i = old_len; i >= loc; i -= 1) {
1384 fBuf[i + added_len] = fBuf[i];
1385 }
1386
1387 // insert match
1388 memcpy(fBuf + start, match, match_len);
1389
1390 // the "get"->"Get" case of TString::kIgnore sets pos to -2
1391 // and falls through to update the buffer; we need to return
1392 // -2 in that case, so check here:
1393 if (pos != -2) {
1394 pos = loc; // position of first change in "fBuf"
1395 if (cmp == TString::kIgnoreCase && pos < 0) {
1396 // We might have changed somthing before loc, due to differences in
1397 // capitalization. So return start:
1398 pos = start;
1399 }
1400 }
1401 *fpLoc = loc + added_len; // new cursor position
1402 }
1403
1404done: // <----- goto label
1405 // un-init
1406 fpLoc = nullptr;
1407 fBuf = nullptr;
1408
1409 return pos;
1410}
1411
1412////////////////////////////////////////////////////////////////////////////////
1413/// [private]
1414
1415void TTabCom::CopyMatch(char *dest, int dest_len,
1416 const char *localName,
1417 const char *appendage,
1418 const char *fullName) const
1419{
1420 // if "appendage" is 0, no appendage is applied.
1421 //
1422 // if "appendage" is of the form "filenameXXX" then,
1423 // "filename" is ignored and "XXX" is taken to be the appendage,
1424 // but it will only be applied if the file is not a directory...
1425 // if the file is a directory, a "/" will be used for the appendage instead.
1426 //
1427 // if "appendage" is of the form "XXX" then "XXX" will be appended to the match.
1428
1429 assert(dest != nullptr);
1430 assert(localName != nullptr);
1431
1432 // potential buffer overflow.
1433 strlcpy(dest, localName, dest_len);
1434
1435 const char *key = "filename";
1436 const int key_len = strlen(key);
1437
1438 IfDebug(std::cerr << "CopyMatch()." << std::endl);
1439 IfDebug(std::cerr << "localName: " << (localName ? localName : "0") <<
1440 std::endl);
1441 IfDebug(std::cerr << "appendage: " << (appendage ? appendage : "0") <<
1442 std::endl);
1443 IfDebug(std::cerr << " fullName: " << (fullName ? fullName : "0") <<
1444 std::endl);
1445
1446
1447 // check to see if "appendage" starts with "key"
1448 if (appendage && strncmp(appendage, key, key_len) == 0) {
1449 // filenames get special treatment
1450 appendage += key_len;
1451 IfDebug(std::cerr << "new appendage: " << appendage << std::endl);
1452 if (IsDirectory(fullName)) {
1453 if (fullName)
1454 strlcat(dest, "/", dest_len);
1455 } else {
1456 if (appendage)
1457 strlcat(dest, appendage, dest_len);
1458 }
1459 } else {
1460 if (appendage)
1461 strlcat(dest, appendage, dest_len);
1462 }
1463}
1464
1465////////////////////////////////////////////////////////////////////////////////
1466/// [private]
1467
1469{
1470 assert(fBuf != nullptr);
1471
1472 const char *pStart; // start of match
1473 const char *pEnd; // end of match
1474
1475 for (int context = 0; context < kNUM_PAT; ++context) {
1476 pEnd = Matchs(fBuf, *fpLoc, fPat[context], &pStart);
1477 if (pEnd) {
1478 IfDebug(std::cerr << std::endl
1479 << "context=" << context << " "
1480 << "RegExp=" << fRegExp[context]
1481 << std::endl);
1482 return EContext_t(context); //* RETURN *//
1483 }
1484 }
1485
1486 return kUNKNOWN_CONTEXT; //* RETURN *//
1487}
1488
1489////////////////////////////////////////////////////////////////////////////////
1490/// [private]
1491
1493 const char defaultPath[]) const
1494{
1495 if (PathIsSpecifiedInFileName(fileName)) {
1496 TString path = fileName;
1497 gSystem->ExpandPathName(path);
1498 Int_t end = path.Length()-1;
1499 if (end>0 && path[end]!='/' && path[end]!='\\') {
1500 path = gSystem->GetDirName(path);
1501 }
1502 return path;
1503 } else {
1504 TString newBase, extendedPath;
1505 if (fileName.Contains("/")) {
1506 Int_t end = fileName.Length()-1;
1507 if (fileName[end] != '/' && fileName[end] != '\\') {
1508 newBase = gSystem->GetDirName(fileName);
1509 } else {
1510 newBase = fileName;
1511 }
1512 extendedPath = ExtendPath(defaultPath, newBase);
1513 } else {
1514 newBase = "";
1515 extendedPath = defaultPath;
1516 }
1517 IfDebug(std::cerr << std::endl);
1518 IfDebug(std::cerr << " fileName: " << fileName << std::endl);
1519 IfDebug(std::cerr << " pathBase: " << newBase << std::endl);
1520 if (defaultPath) {
1521 IfDebug(std::cerr << " defaultPath: " << defaultPath << std::endl);
1522 } else {
1523 IfDebug(std::cerr << " defaultPath: " << std::endl);
1524 }
1525 IfDebug(std::cerr << "extendedPath: " << extendedPath << std::endl);
1526 IfDebug(std::cerr << std::endl);
1527
1528 return extendedPath;
1529 }
1530}
1531
1532////////////////////////////////////////////////////////////////////////////////
1533/// [private]
1534
1535TString TTabCom::ExtendPath(const char originalPath[], TString newBase) const
1536{
1537 if (newBase.BeginsWith("/"))
1538 newBase.Remove(TString::kLeading, '/');
1539#ifdef R__SSTREAM
1540 std::stringstream str;
1541#else
1542 std::strstream str;
1543#endif
1544 TString dir;
1545 TString newPath;
1546 if (originalPath) str << originalPath;
1547
1548 while (str.good())
1549 {
1550 dir = "";
1551 dir.ReadToDelim(str, kDelim);
1552 if (dir.IsNull())
1553 continue; // ignore blank entries
1554 newPath.Append(dir);
1555 if (!newPath.EndsWith("/"))
1556 newPath.Append("/");
1557 newPath.Append(newBase);
1558 newPath.Append(kDelim);
1559 }
1560
1561 return newPath.Strip(TString::kTrailing, kDelim);
1562}
1563
1564////////////////////////////////////////////////////////////////////////////////
1565/// [private]
1566
1567Int_t TTabCom::Hook(char *buf, int *pLoc, std::ostream& out)
1568{
1569 // initialize
1570 fBuf = buf;
1571 fpLoc = pLoc;
1572
1573 // frodo: iteration counter for recursive MakeClassFromVarName
1574 fLastIter = 0;
1575
1576 // default
1577 Int_t pos = -2; // position of the first character that was changed in the buffer (needed for redrawing)
1578
1579 // get the context this tab was triggered in.
1580 EContext_t context = DetermineContext();
1581
1582 // get the substring that triggered this tab (as defined by "SetPattern()")
1583 const char dummy[] = ".";
1584 TRegexp re1(context == kUNKNOWN_CONTEXT ? dummy : fRegExp[context]);
1585 TString s1(fBuf);
1586 TString s2 = s1(0, *fpLoc);
1587 TString s3 = s2(re1);
1588
1589 switch (context) {
1590 case kUNKNOWN_CONTEXT:
1591 std::cerr << std::endl << "tab completion not implemented for this context" <<
1592 std::endl;
1593 pos = -2;
1594 break;
1595
1596 case kSYS_UserName:
1597 {
1598 const TSeqCollection *pListOfUsers = GetListOfUsers();
1599
1600 pos = Complete("[^~]*$", pListOfUsers, "/", out);
1601 }
1602 break;
1603 case kSYS_EnvVar:
1604 {
1605 const TSeqCollection *pEnv = GetListOfEnvVars();
1606
1607 pos = Complete("[^$]*$", pEnv, "", out);
1608 }
1609 break;
1610
1611 case kCINT_stdout:
1612 case kCINT_stderr:
1613 case kCINT_stdin:
1614 {
1615 const TString fileName = s3("[^ ><]*$");
1616 const TString filePath = DeterminePath(fileName,nullptr);
1617 const TSeqCollection *pListOfFiles =
1618 GetListOfFilesInPath(filePath.Data());
1619
1620// pos = Complete( "[^ /]*$", pListOfFiles, " ", out );
1621 pos = Complete("[^ /]*$", pListOfFiles, "filename ", out);
1622 }
1623 break;
1624
1625 case kCINT_Edit:
1626 case kCINT_Load:
1627 case kCINT_Exec:
1628 case kCINT_EXec:
1629 {
1630 const TString fileName = s3("[^ ]*$");
1631 const TString macroPath =
1633 const TSeqCollection *pListOfFiles =
1634 GetListOfFilesInPath(macroPath.Data());
1635
1636// pos = Complete( "[^ /]*$", pListOfFiles, " ", out);
1637 pos = Complete("[^ /]*$", pListOfFiles, "filename ", out);
1638 }
1639 break;
1640
1641 case kCINT_pragma:
1642 {
1643 pos = Complete("[^ ]*$", GetListOfPragmas(), "", out);
1644 }
1645 break;
1646 case kCINT_includeSYS:
1647 {
1648 TString fileName = s3("[^<]*$");
1649 if (PathIsSpecifiedInFileName(fileName) || fileName.Contains("/")) {
1650 TString includePath =
1651 DeterminePath(fileName, GetSysIncludePath());
1652
1653// pos = Complete( "[^</]*$", GetListOfFilesInPath( includePath ), "> ", out);
1654 pos =
1655 Complete("[^</]*$", GetListOfFilesInPath(includePath),
1656 "filename> ", out);
1657 } else {
1658// pos = Complete( "[^</]*$", GetListOfSysIncFiles(), "> ", out);
1659 pos =
1660 Complete("[^</]*$", GetListOfSysIncFiles(), "filename> ", out);
1661 }
1662 }
1663 break;
1664 case kCINT_includePWD:
1665 {
1666 const TString fileName = s3("[^\"]*$");
1667 const TString includePath = DeterminePath(fileName, ".");
1668 const TSeqCollection *pListOfFiles =
1669 GetListOfFilesInPath(includePath.Data());
1670
1671// pos = Complete( "[^\"/]*$", pListOfFiles, "\" ", out);
1672 pos = Complete("[^\"/]*$", pListOfFiles, "filename\" ", out);
1673 }
1674 break;
1675
1676 case kCINT_cpp:
1677 {
1678 pos = Complete("[^# ]*$", GetListOfCppDirectives(), " ", out);
1679 }
1680 break;
1681
1682 case kROOT_Load:
1683 {
1684 const TString fileName = s3("[^\"]*$");
1685 const TString dynamicPath = DeterminePath(fileName, gSystem->GetDynamicPath());
1686 const TSeqCollection *pListOfFiles = GetListOfFilesInPath(dynamicPath);
1687
1688// pos = Complete( "[^\"/]*$", pListOfFiles, "\");", out);
1689 pos = Complete("[^\"/]*$", pListOfFiles, "filename\");", out);
1690 }
1691 break;
1692
1693 case kSYS_FileName:
1694 {
1695 const TString fileName = s3("[^ \"]*$");
1696 const TString filePath = DeterminePath(fileName,".");
1697 const TSeqCollection *pListOfFiles = GetListOfFilesInPath(filePath.Data());
1698
1699 pos = Complete("[^\" /]*$", pListOfFiles, "filename\"", out);
1700 }
1701 break;
1702
1703 case kCXX_ScopeMember:
1704 {
1705 const EContext_t original_context = context; // save this for later
1706
1707 TClass *pClass;
1708 // may be a namespace, class, object, or pointer
1709 TString name = s3("^[_a-zA-Z][_a-zA-Z0-9]*");
1710
1711 IfDebug(std::cerr << std::endl);
1712 IfDebug(std::cerr << "name: " << '"' << name << '"' << std::endl);
1713
1714 // We need to decompose s3 a little more:
1715 // The part name is the partial symbol at the end of ::
1716 // eg. given s3 = "foo::bar::part" , partname = "part"
1717 TString partname = s3("[_a-zA-Z][_a-zA-Z0-9]*$");
1718
1719 // The prefix, considering the s3 = "foo::bar::part" example would be
1720 // prefix = "foo::bar::". prefix equals the empty string if there is only one
1721 // or no set of colons in s3.
1722 // Note: we reconstruct the fully qualified name with a while loop because
1723 // it does not seem that TRegexp can handle something like "([_a-zA-Z][_a-zA-Z0-9]*::)+$"
1724 TString prefix = "";
1725 TString str = s2;
1726 str.Remove(str.Length() - partname.Length(), partname.Length());
1727 while (1) {
1728 TString sym = str("[_a-zA-Z][_a-zA-Z0-9]*::$");
1729 if (sym.Length() == 0)
1730 break;
1731 str.Remove(str.Length() - sym.Length(), sym.Length());
1732 prefix = sym + prefix;
1733 }
1734
1735 // Not the preprefix would be = "foo::" from our previous example or the empty
1736 // string, "" if there is only one or no set of colons in prefix, eg. prefix = "bar::"
1737 TString preprefix = prefix;
1738 TString sym = prefix("[_a-zA-Z][_a-zA-Z0-9]*::$");
1739 preprefix.Remove(preprefix.Length() - sym.Length(), sym.Length());
1740
1741 IfDebug(std::cerr << "prefix: " << '"' << prefix << '"' << std::endl);
1742 IfDebug(std::cerr << "preprefix: " << '"' << preprefix << '"' << std::endl);
1743
1744 TString namesp = prefix;
1745 if (namesp.Length() >= 2)
1746 namesp.Remove(namesp.Length() - 2, 2); // Remove the '::' at the end of the string.
1747 IfDebug(std::cerr << "namesp: " << '"' << namesp << '"' << std::endl);
1748
1749 // Make sure autoloading happens (if it can).
1751
1752 TContainer *pList = new TContainer;
1753 // Add all classes to pList that contain the prefix, i.e. are in the
1754 // specified namespace.
1755 const TSeqCollection *tmp = GetListOfClasses();
1756 if (!tmp) break;
1757
1758 Int_t i;
1759 for (i = 0; i < tmp->GetSize(); i++) {
1760 TString astr = ((TObjString *) tmp->At(i))->String();
1761 TString rxp = "^";
1762 rxp += prefix;
1763 if (astr.Contains(TRegexp(rxp))) {
1764 astr.Remove(0, prefix.Length());
1765 TString s = astr("^[^: ]*");
1766 TObjString *ostr = new TObjString(s);
1767 if (!pList->Contains(ostr))
1768 pList->Add(ostr);
1769 else
1770 delete ostr;
1771 }
1772 }
1773
1774 // If a class with the same name as the Namespace name exists then
1775 // add it to the pList. (I don't think the C++ spec allows for this
1776 // but do this anyway, cant harm).
1777 pClass = TryMakeClassFromClassName(preprefix + name);
1778 if (pClass) {
1779 pList->AddAll(pClass->GetListOfAllPublicMethods(true));
1780 pList->AddAll(pClass->GetListOfAllPublicDataMembers(true));
1781 }
1782
1783 pos = Complete("[^: ]*$", pList, "", out);
1784
1785 delete pList;
1786
1787 if (context != original_context)
1788 pos = -2;
1789 }
1790 break;
1791
1792 case kCXX_DirectMember:
1794 {
1795 const EContext_t original_context = context; // save this for later
1796
1797 TClass *pClass;
1798
1799 // frodo: Instead of just passing the last portion of the string to
1800 // MakeClassFromVarName(), we now pass the all string and let
1801 // it decide how to handle it... I know it's not the best way
1802 // because of the context handling, but I wanted to "minimize"
1803 // the changes to the current code and this seemed the best way
1804 // to do it
1805 TString name = s1("[_a-zA-Z][-_a-zA-Z0-9<>():.]*$");
1806
1807 IfDebug(std::cerr << std::endl);
1808 IfDebug(std::cerr << "name: " << '"' << name << '"' << std::endl);
1809
1810 switch (context) {
1811 case kCXX_DirectMember:
1812 pClass = MakeClassFromVarName(name, context);
1813 break;
1815 pClass = MakeClassFromVarName(name, context);
1816 break;
1817 default:
1818 Fatal("TTabCom::Hook","Conext case %d not handled",context);
1819 return 0; // Avoid warning about uninitialized pClass.
1820 }
1821 if (!pClass) {
1822 pos = -2;
1823 break;
1824 }
1825
1826 TContainer *pList = new TContainer;
1827
1828 pList->AddAll(pClass->GetListOfAllPublicMethods());
1829 pList->AddAll(pClass->GetListOfAllPublicDataMembers());
1830
1831 switch (context) {
1832 case kCXX_DirectMember:
1833 {
1834 int* store_fpLoc = fpLoc;
1835 char* store_fBuf = fBuf;
1836 pos = Complete("[^. ]*$", pList, "(", out);
1837 if (pos == -1) {
1838 fpLoc = store_fpLoc;
1839 fBuf = store_fBuf;
1840 pos = Complete("[^. ]*$", pList, "(", out, TString::kIgnoreCase);
1841 }
1842 break;
1843 }
1845 pos = Complete("[^> ]*$", pList, "(", out);
1846 break;
1847 default:
1848 Fatal("TTabCom::Hook","Conext case %d not handled",context);
1849 return 0; // Avoid warning about uninitialized pClass.
1850 }
1851
1852 delete pList;
1853
1854 if (context != original_context)
1855 pos = -2;
1856 }
1857 break;
1858
1859 case kCXX_ScopeProto:
1860 {
1861 const EContext_t original_context = context; // save this for later
1862
1863 // get class
1864 TClass *pClass;
1865 TString name = s3("^[_a-zA-Z][_a-zA-Z0-9]*");
1866 // "name" may now be the name of a class, object, or pointer
1867
1868 IfDebug(std::cerr << std::endl);
1869 IfDebug(std::cerr << "name: " << '"' << name << '"' << std::endl);
1870
1871 // We need to decompose s3 a little more:
1872 // The partname is the method symbol and a bracket at the end of ::
1873 // eg. given s3 = "foo::bar::part(" , partname = "part("
1874 TString partname = s3("[_a-zA-Z][_a-zA-Z0-9]* *($");
1875
1876 // The prefix, considering the s3 = "foo::bar::part" example would be
1877 // prefix = "foo::bar::". prefix equals the empty string if there is only one
1878 // or no set of colons in s3.
1879 // Note: we reconstruct the fully qualified name with a while loop because
1880 // it does not seem that TRegexp can handle something like "([_a-zA-Z][_a-zA-Z0-9]*::)+$"
1881 TString prefix = "";
1882 TString str = s2;
1883 str.Remove(str.Length() - partname.Length(), partname.Length());
1884 while (1) {
1885 TString sym = str("[_a-zA-Z][_a-zA-Z0-9]*::$");
1886 if (sym.Length() == 0)
1887 break;
1888 str.Remove(str.Length() - sym.Length(), sym.Length());
1889 prefix = sym + prefix;
1890 }
1891
1892 // Not the preprefix would be = "foo::" from our previous example or the empty
1893 // string, "" if there is only one or no set of colons in prefix, eg. prefix = "bar::"
1894 TString preprefix = prefix;
1895 TString sym = prefix("[_a-zA-Z][_a-zA-Z0-9]*::$");
1896 preprefix.Remove(preprefix.Length() - sym.Length(), sym.Length());
1897
1898 IfDebug(std::cerr << "prefix: " << '"' << prefix << '"' << std::endl);
1899 IfDebug(std::cerr << "preprefix: " << '"' << preprefix << '"' << std::endl);
1900
1901 pClass = MakeClassFromClassName(preprefix + name);
1902 if (!pClass) {
1903 pos = -2;
1904 break;
1905 }
1906 // get method name
1907 TString methodName;
1908
1909 // (normal member function)
1910 methodName = s3("[^:>\\.(]*($");
1911 methodName.Chop();
1912 methodName.Remove(TString::kTrailing, ' ');
1913
1914 IfDebug(std::cerr << methodName << std::endl);
1915
1916 // get methods
1917 TContainer *pList = new TContainer;
1918 pList->AddAll(pClass->GetListOfAllPublicMethods());
1919
1920 // print prototypes
1921 Bool_t foundOne = kFALSE;
1922 TIter nextMethod(pList);
1923 TMethod *pMethod;
1924 while ((pMethod = (TMethod *) nextMethod())) {
1925 if (methodName == pMethod->GetName()) {
1926 foundOne = kTRUE;
1927 out << pMethod->GetReturnTypeName()
1928 << " " << pMethod->GetName()
1929 << pMethod->GetSignature();
1930 const char *comment = pMethod->GetCommentString();
1931 if (comment && comment[0] != '\0') {
1932 out << " \t// " << comment;
1933 }
1934 out << std::endl;
1935 }
1936 }
1937
1938 // done
1939 if (foundOne) {
1940 pos = -2;
1941 } else {
1942 gSystem->Beep();
1943 pos = -1;
1944 }
1945
1946 // cleanup
1947 delete pList;
1948
1949 if (context != original_context)
1950 pos = -2;
1951 }
1952 break;
1953
1954 case kCXX_DirectProto:
1955 case kCXX_IndirectProto:
1956 case kCXX_NewProto:
1958 {
1959 const EContext_t original_context = context; // save this for later
1960
1961 // get class
1962 TClass *pClass;
1963 TString name;
1964 if (context == kCXX_NewProto) {
1965 name = s3("[_a-zA-Z][_a-zA-Z0-9:]* *($", 3);
1966 name.Chop();
1967 name.Remove(TString::kTrailing, ' ');
1968 // "name" should now be the name of a class
1969 } else {
1970 name = s3("^[_a-zA-Z][_a-zA-Z0-9:]*");
1971 // "name" may now be the name of a class, object, or pointer
1972 }
1973 IfDebug(std::cerr << std::endl);
1974 IfDebug(std::cerr << "name: " << '"' << name << '"' << std::endl);
1975
1976 // frodo: Again, passing the all string
1977 TString namerec = s1;
1978
1979 switch (context) {
1980 case kCXX_ScopeProto:
1981 pClass = MakeClassFromClassName(name);
1982 break;
1983 case kCXX_DirectProto:
1984 pClass = MakeClassFromVarName(namerec, context); // frodo
1985 break;
1986 case kCXX_IndirectProto:
1987 pClass = MakeClassFromVarName(namerec, context); // frodo
1988 break;
1989 case kCXX_NewProto:
1990 pClass = MakeClassFromClassName(name);
1991 break;
1993 pClass = MakeClassFromClassName(name);
1994 break;
1995 default:
1996 Fatal("TTabCom::Hook","Conext case %d not handled",context);
1997 return 0; // Avoid warning about uninitialized pClass.
1998 }
1999 if (!pClass) {
2000 pos = -2;
2001 break;
2002 }
2003 // get method name
2004 TString methodName;
2005 if (context == kCXX_ConstructorProto || context == kCXX_NewProto) {
2006 // (constructor)
2007 methodName = name("[_a-zA-Z][_a-zA-Z0-9]*$");
2008 } else {
2009 // (normal member function)
2010 methodName = s3("[^:>\\.(]*($");
2011 methodName.Chop();
2012 methodName.Remove(TString::kTrailing, ' ');
2013 }
2014 IfDebug(std::cerr << methodName << std::endl);
2015
2016 // get methods
2017 TContainer *pList = new TContainer;
2018 pList->AddAll(pClass->GetListOfAllPublicMethods());
2019
2020 // print prototypes
2021 Bool_t foundOne = kFALSE;
2022 TIter nextMethod(pList);
2023 TMethod *pMethod;
2024 while ((pMethod = (TMethod *) nextMethod())) {
2025 if (methodName == pMethod->GetName()) {
2026 foundOne = kTRUE;
2027 out << pMethod->GetReturnTypeName()
2028 << " " << pMethod->GetName()
2029 << pMethod->GetSignature();
2030 const char *comment = pMethod->GetCommentString();
2031 if (comment && comment[0] != '\0') {
2032 out << " \t// " << comment;
2033 }
2034 out << std::endl;
2035 }
2036 }
2037
2038 // done
2039 if (foundOne) {
2040 pos = -2;
2041 } else {
2042 gSystem->Beep();
2043 pos = -1;
2044 }
2045
2046 // cleanup
2047 delete pList;
2048
2049 if (context != original_context)
2050 pos = -2;
2051 }
2052 break;
2053
2054 case kCXX_Global:
2055 {
2056 // first need to veto a few possibilities.
2057 int l2 = s2.Length(), l3 = s3.Length();
2058
2059 // "abc().whatever[TAB]"
2060 if (l2 > l3 && s2[l2 - l3 - 1] == '.') {
2061 std::cerr << std::endl <<
2062 "tab completion not implemented for this context" << std::endl;
2063 break; // veto
2064 }
2065 // "abc()->whatever[TAB]"
2066 if (l2 > l3 + 1 && s2(l2 - l3 - 2, 2) == "->") {
2067 std::cerr << std::endl <<
2068 "tab completion not implemented for this context" << std::endl;
2069 break; // veto
2070 }
2071
2072 TContainer *pList = new TContainer;
2073
2074 const TSeqCollection *pL2 = GetListOfClasses();
2075 if (pL2) pList->AddAll(pL2);
2076
2077 //
2078 const TSeqCollection *pC1 = GetListOfGlobals();
2079 if (pC1) pList->AddAll(pC1);
2080 //
2082 if (pC3) pList->AddAll(pC3);
2083
2084 pos = Complete("[_a-zA-Z][_a-zA-Z0-9]*$", pList, "", out);
2085
2086 delete pList;
2087 }
2088 break;
2089
2090 case kCXX_GlobalProto:
2091 {
2092 // get function name
2093 TString functionName = s3("[_a-zA-Z][_a-zA-Z0-9]*");
2094 IfDebug(std::cerr << functionName << std::endl);
2095
2096 TContainer listOfMatchingGlobalFuncs;
2097 TIter nextGlobalFunc(GetListOfGlobalFunctions());
2098 TObject *pObj;
2099 while ((pObj = nextGlobalFunc())) {
2100 if (strcmp(pObj->GetName(), functionName) == 0) {
2101 listOfMatchingGlobalFuncs.Add(pObj);
2102 }
2103 }
2104
2105 if (listOfMatchingGlobalFuncs.IsEmpty()) {
2106 std::cerr << std::endl << "no such function: " << dblquote(functionName)
2107 << std::endl;
2108 } else {
2109 TIter next(&listOfMatchingGlobalFuncs);
2110 TFunction *pFunction;
2111 while ((pFunction = (TFunction *) next())) {
2112 out << pFunction->GetReturnTypeName()
2113 << " " << pFunction->GetName()
2114 << pFunction->GetSignature()
2115 << std::endl;
2116 }
2117 }
2118
2119 pos = -2;
2120 }
2121 break;
2122
2123 /******************************************************************/
2124 /* */
2125 /* default: should never happen */
2126 /* */
2127 /******************************************************************/
2128 default:
2129 Fatal("TTabCom::Hook","Conext case %d not handled",context);
2130 return 0; // Avoid warning about uninitialized pClass.
2131 }
2132
2133 return pos;
2134}
2135
2136////////////////////////////////////////////////////////////////////////////////
2137/// [private]
2138
2140{
2141 // add more patterns somewhere below.
2142 // add corresponding enum to "EContext_t"
2143 //
2144 // note:
2145 // 1. in some cases order is important ...
2146 //
2147 // the order of the "case" statements in "switch( context )" in "TTabCom::Hook()" is Not important.
2148 //
2149 // the order of the "SetPattern()" function calls below is Not important.
2150 //
2151 // the order of the initializers in the "EContext_t" enumeration Is important
2152 // because DetermineContext() goes through the array in order, and returns at the first match.
2153 //
2154 // 2. below, "$" will match cursor position
2155
2156 SetPattern(kSYS_UserName, "~[_a-zA-Z0-9]*$");
2157 SetPattern(kSYS_EnvVar, "$[_a-zA-Z0-9]*$");
2158
2159 SetPattern(kCINT_stdout, "; *>>?.*$"); // stdout
2160 SetPattern(kCINT_stderr, "; *2>>?.*$"); // stderr
2161 SetPattern(kCINT_stdin, "; *<.*$"); // stdin
2162
2163 SetPattern(kCINT_Edit, "^ *\\.E .*$");
2164 SetPattern(kCINT_Load, "^ *\\.L .*$");
2165 SetPattern(kCINT_Exec, "^ *\\.x +[-0-9_a-zA-Z~$./]*$");
2166 SetPattern(kCINT_EXec, "^ *\\.X +[-0-9_a-zA-Z~$./]*$");
2167
2168 SetPattern(kCINT_pragma, "^# *pragma +[_a-zA-Z0-9]*$");
2169 SetPattern(kCINT_includeSYS, "^# *include *<[^>]*$"); // system files
2170 SetPattern(kCINT_includePWD, "^# *include *\"[^\"]*$"); // local files
2171
2172 SetPattern(kCINT_cpp, "^# *[_a-zA-Z0-9]*$");
2173
2174 SetPattern(kROOT_Load, "gSystem *-> *Load *( *\"[^\"]*$");
2175
2176 SetPattern(kCXX_NewProto, "new +[_a-zA-Z][_a-zA-Z0-9:]* *($");
2178 "[_a-zA-Z][_a-zA-Z0-9:]* +[_a-zA-Z][_a-zA-Z0-9]* *($");
2180 "[_a-zA-Z][_a-zA-Z0-9]* *:: *[_a-zA-Z0-9]* *($");
2182 "[_a-zA-Z][_a-zA-Z0-9()]* *\\. *[_a-zA-Z0-9]* *($");
2184 "[_a-zA-Z][_a-zA-Z0-9()]* *-> *[_a-zA-Z0-9]* *($");
2185
2187 "[_a-zA-Z][_a-zA-Z0-9]* *:: *[_a-zA-Z0-9]*$");
2189 "[_a-zA-Z][_a-zA-Z0-9()]* *\\. *[_a-zA-Z0-9()]*$"); //
2190
2192 "[_a-zA-Z][_a-zA-Z0-9()]* *-> *[_a-zA-Z0-9()]*$"); // frodo
2193
2194 SetPattern(kSYS_FileName, "\"[-0-9_a-zA-Z~$./]*$");
2195 SetPattern(kCXX_Global, "[_a-zA-Z][_a-zA-Z0-9]*$");
2196 SetPattern(kCXX_GlobalProto, "[_a-zA-Z][_a-zA-Z0-9]* *($");
2197}
2198
2199////////////////////////////////////////////////////////////////////////////////
2200/// [private]
2201/// (does some specific error handling that makes the function unsuitable for general use.)
2202/// returns a new'd TClass given the name of a class.
2203/// user must delete.
2204/// returns 0 in case of error.
2205
2206TClass *TTabCom::MakeClassFromClassName(const char className[]) const
2207{
2208 // the TClass constructor will print a Warning message for classes that don't exist
2209 // so, ignore warnings temporarily.
2210 NoMsg(kWarning);
2211 TClass *pClass = TClass::GetClass(className);
2212 NoMsg(-1);
2213
2214 if (!pClass){
2215 Error("TTabCom::MakeClassFromClassName", "Unknown class \"%s\"", className);
2216 return nullptr;
2217 }
2218
2219 // make sure "className" exists
2220 // if (pClass->Size() == 0) { //namespace has 0 size
2221 if (pClass->GetListOfAllPublicMethods()->GetSize() == 0 &&
2222 pClass->GetListOfAllPublicDataMembers()->GetSize() == 0) {
2223 // i'm assuming this happens iff there was some error.
2224 // (misspelled the class name, for example)
2225 Error("TTabCom::MakeClassFromClassName", "class \"%s\" is not defined.", className);
2226 return nullptr;
2227 }
2228
2229 return pClass;
2230}
2231
2232////////////////////////////////////////////////////////////////////////////////
2233/// Same as above but does not print the error message.
2234
2235TClass *TTabCom::TryMakeClassFromClassName(const char className[]) const
2236{
2237 // the TClass constructor will print a Warning message for classes that don't exist
2238 // so, ignore warnings temporarily.
2239 NoMsg(kWarning);
2240 TClass *pClass = TClass::GetClass(className);
2241 NoMsg(-1);
2242
2243 return pClass;
2244}
2245
2246////////////////////////////////////////////////////////////////////////////////
2247/// [private]
2248/// (does some specific error handling that makes the function unsuitable for general use.)
2249/// returns a new'd TClass given the name of a variable.
2250/// user must delete.
2251/// returns 0 in case of error.
2252/// if user has operator.() or operator->() backwards, will modify: context, *fpLoc and fBuf.
2253/// context sensitive behavior.
2254
2256 EContext_t & context, int iter)
2257{
2258 // frodo:
2259 // Because of the Member and Proto recursion, this has become a bit
2260 // complicated, so here is how it works:
2261 //
2262 // root [1] var.a.b.c[TAB]
2263 //
2264 // will generate the sucessive calls:
2265 // MakeClassFromVarName("var.a.b.c", context, 0) returns the class of "c"
2266 // MakeClassFromVarName("var.a.b", context, 1) returns the class of "b"
2267 // MakeClassFromVarName("var.a", context, 2) returns the class of "a"
2268 // MakeClassFromVarName("var", context, 3)
2269
2270 // need to make sure "varName" exists
2271 // because "DetermineClass()" prints clumsy error message otherwise.
2272 Bool_t varName_exists = GetListOfGlobals()->Contains(varName) || // check in list of globals first.
2273 (gROOT->FindObject(varName) != nullptr); // then check CINT "shortcut #3"
2274
2275
2276 //
2277 // frodo: Member and Proto recursion code
2278 //
2279 if (0) printf("varName is [%s] with iteration [%i]\n", varName, iter);
2280
2281 // ParseReverse will return 0 if there are no "." or "->" in the varName
2282 Int_t cut = ParseReverse(varName, strlen(varName));
2283
2284 // If it's not a "simple" variable and if there is at least one "." or "->"
2285 if (!varName_exists && cut != 0)
2286 {
2287 TString parentName = varName;
2288 TString memberName = varName;
2289
2290 // Check to see if this is the last call (last member/method)
2291 if (iter > fLastIter) fLastIter = iter;
2292
2293 parentName[cut] = 0;
2294 if (0) printf("Parent string is [%s]\n", parentName.Data());
2295
2296 // We are treating here cases like h->SetXTitle(gROOT->Get<TAB>
2297 // i.e. when the parentName has an unbalanced number of paranthesis.
2298 if (cut>2) {
2299 UInt_t level = 0;
2300 for(Int_t i = cut-1; i>=0; --i) {
2301 switch (parentName[i]) {
2302 case '(':
2303 if (level) --level;
2304 else {
2305 parentName = parentName(i+1,cut-i-1);
2306 i = 0;
2307 }
2308 break;
2309 case ')':
2310 ++level; break;
2311 }
2312 }
2313 }
2314
2315 TClass *pclass;
2316 // Can be "." or "->"
2317 if (varName[cut] == '.') {
2318 memberName = varName+cut+1;
2319 if (0) printf("Member/method is [%s]\n", memberName.Data());
2320 EContext_t subcontext = kCXX_DirectMember;
2321 pclass = MakeClassFromVarName(parentName.Data(), subcontext, iter+1);
2322 } else {
2323 memberName = varName+cut+2;
2324 if (0) printf("Member/method is [%s]\n", memberName.Data());
2325 EContext_t subcontext = kCXX_IndirectMember;
2326 pclass = MakeClassFromVarName(parentName.Data(), subcontext, iter+1);
2327 }
2328
2329 if (0) printf("I got [%s] from MakeClassFromVarName()\n", pclass->GetName());
2330
2331 if (pclass)
2332 {
2333 if (0) printf("Variable [%s] exists!\n", parentName.Data());
2334
2335 // If it's back in the first call of the function, return immediatly
2336 if (iter == 0) return pclass;
2337
2338 if (0) printf("Trying data member [%s] of class [%s] ...\n",
2339 memberName.Data(), pclass->GetName());
2340
2341 // Check if it's a member
2342 TDataMember *dmptr = nullptr; //pclass->GetDataMember(memberName.Data());
2343 TIter next(pclass->GetListOfAllPublicDataMembers());
2344 while ((dmptr = (TDataMember *) next())) {
2345 if (memberName == dmptr->GetName()) break;
2346 }
2347 if (dmptr)
2348 {
2349 if (0) printf("It's a member!\n");
2350
2351 TString returnName = dmptr->GetTypeName();
2352 // if (returnName[returnName.Length()-1] == '*')
2353 // printf("It's a pointer!\n");
2354
2355 TClass *mclass = TClass::GetClass(returnName.Data());
2356 return mclass;
2357 }
2358
2359
2360 // Check if it's a proto: must have ()
2361 // This might not be too safe to use :(
2362 char *parentesis_ptr = (char*)strrchr(memberName.Data(), '(');
2363 if (parentesis_ptr) *parentesis_ptr = 0;
2364
2365
2366 if (0) printf("Trying method [%s] of class [%s] ...\n",
2367 memberName.Data(), pclass->GetName());
2368
2369 // Check if it's a method
2370 TMethod *mptr = nullptr; // pclass->GetMethodAny(memberName.Data());
2371 const TList *mlist = pclass->GetListOfAllPublicMethods();
2372 next = mlist;
2373 while ((mptr = (TMethod *) next())) {
2374 if (strcmp(memberName.Data(),mptr->GetName())==0) break;
2375 }
2376 if (mptr)
2377 {
2378 TString returnName = mptr->GetReturnTypeName();
2379
2380 if (0) printf("It's a method called [%s] with return type [%s]\n",
2381 memberName.Data(), returnName.Data());
2382
2383 // This will handle the methods that returns a pointer to a class
2384 if (returnName[returnName.Length()-1] == '*')
2385 {
2386 returnName[returnName.Length()-1] = 0;
2388 }
2389 else
2390 {
2392 }
2393
2394 TClass *mclass = TClass::GetClass(returnName.Data());
2395 return mclass;
2396 }
2397 }
2398 }
2399
2400 //
2401 // frodo: End of Member and Proto recursion code
2402 //
2403
2404
2405 // not found...
2406 if (!varName_exists) {
2407 std::cerr << std::endl << "variable " << dblquote(varName) << " not defined."
2408 << std::endl;
2409 return nullptr; //* RETURN *//
2410 }
2411
2412 /*****************************************************************************************/
2413 /* */
2414 /* this section is really ugly. */
2415 /* and slow. */
2416 /* it could be made a lot better if there was some way to tell whether or not a given */
2417 /* variable is a pointer or a pointer to a pointer. */
2418 /* */
2419 /*****************************************************************************************/
2420
2421 TString className = DetermineClass(varName);
2422
2423 if (className.IsNull() || className == "*") {
2424 // this will happen if "varName" is a fundamental type (as opposed to class type).
2425 // or a pointer to a pointer.
2426 // or a function pointer.
2427 std::cerr << std::endl << "problem determining class of " << dblquote(varName)
2428 << std::endl;
2429 return nullptr; //* RETURN *//
2430 }
2431
2432 fVarIsPointer = className[className.Length() - 1] == '*';
2433
2434 // frodo: I shouldn't have to do this, but for some reason now I have to
2435 // otherwise the varptr->[TAB] won't work :(
2436 if (fVarIsPointer || className[className.Length() - 1] == '&')
2437 className[className.Length()-1] = 0;
2438
2439 // frodo case '.' dealt with in the previous if statement?!
2440 // frodo: I wasn't able to put the automatic "." to "->" replacing working
2441 // so I just commented out.
2442 //
2443
2444
2445 // Bool_t varIsPointer = className[className.Length() - 1] == '*';
2446
2447 //printf("Context is %i, fContext is %i, pointer is %i\n", context, fContext, fVarIsPointer);
2448
2449 if (fVarIsPointer &&
2450 (context == kCXX_DirectMember || context == kCXX_DirectProto)) {
2451 // user is using operator.() instead of operator->()
2452 // ==>
2453 // 1. we are in wrong context.
2454 // 2. user is lazy
2455 // 3. or maybe confused
2456
2457 // 1. fix the context
2458 switch (context) {
2459 case kCXX_DirectMember:
2460 context = kCXX_IndirectMember;
2461 break;
2462 case kCXX_DirectProto:
2463 context = kCXX_IndirectProto;
2464 break;
2465 default:
2466 Fatal("TTabCom::MakeClassFromVarName","Conext case %d not handled",context);
2467 return nullptr; // Avoid warning about uninitialized pClass.
2468 }
2469
2470 // 2. fix the operator.
2471 int i;
2472 for (i = *fpLoc; fBuf[i] != '.'; i -= 1) {
2473 }
2474 int loc = i;
2475 for (i = strlen(fBuf); i >= loc; i -= 1) {
2476 fBuf[i + 1] = fBuf[i];
2477 }
2478 fBuf[loc] = '-';
2479 fBuf[loc + 1] = '>';
2480 *fpLoc += 1;
2481
2482 // 3. inform the user.
2483 std::cerr << std::endl << dblquote(varName) <<
2484 " is of pointer type. Use this operator: ->" << std::endl;
2485 return nullptr;
2486 }
2487
2488 if (context == kCXX_IndirectMember || context == kCXX_IndirectProto) {
2489 if (fVarIsPointer) {
2490 // frodo: This part no longer makes sense...
2491 className.Chop(); // remove the '*'
2492
2493 if (className[className.Length() - 1] == '*') {
2494 std::cerr << std::endl << "can't handle pointers to pointers." << std::endl;
2495 return nullptr; // RETURN
2496 }
2497 } else {
2498 // user is using operator->() instead of operator.()
2499 // ==>
2500 // 1. we are in wrong context.
2501 // 2. user is lazy
2502 // 3. or maybe confused
2503
2504 // 1. fix the context
2505 switch (context) {
2507 context = kCXX_DirectMember;
2508 break;
2509 case kCXX_IndirectProto:
2510 context = kCXX_DirectProto;
2511 break;
2512 default:
2513 Fatal("TTabCom::MakeClassFromVarName","Conext case %d not handled",context);
2514 return nullptr; // Avoid warning about uninitialized pClass.
2515 }
2516
2517 // 2. fix the operator.
2518 int i;
2519 for (i = *fpLoc; fBuf[i - 1] != '-' && fBuf[i] != '>'; i -= 1) {
2520 }
2521 fBuf[i - 1] = '.';
2522 int len = strlen(fBuf);
2523 for (; i < len; i += 1) {
2524 fBuf[i] = fBuf[i + 1];
2525 }
2526 *fpLoc -= 1;
2527
2528 // 3. inform the user.
2529 std::cerr << std::endl << dblquote(varName) <<
2530 " is not of pointer type. Use this operator: ." << std::endl;
2531 return nullptr;
2532 }
2533 }
2534
2535 className.Strip(TString::kBoth);
2536
2537 return TClass::GetClass(className);
2538}
2539
2540////////////////////////////////////////////////////////////////////////////////
2541/// [private]
2542
2543void TTabCom::SetPattern(EContext_t handle, const char regexp[])
2544{
2545 // prevent overflow
2546 if (handle >= kNUM_PAT) {
2547 std::cerr << std::endl
2548 << "ERROR: handle="
2549 << (int) handle << " >= kNUM_PAT=" << (int) kNUM_PAT << std::endl;
2550 return;
2551 }
2552
2553 fRegExp[handle] = regexp;
2554 Makepat(regexp, fPat[handle], MAX_LEN_PAT);
2555}
2556
2557
2558
2559////////////////////////////////////////////////////////////////////////////////
2560///
2561/// Returns the place in the string where to put the \0, starting the search
2562/// from "start"
2563///
2564
2565int TTabCom::ParseReverse(const char *var_str, int start)
2566{
2567 int end = 0;
2568 if (start > (int)strlen(var_str)) start = strlen(var_str);
2569
2570 for (int i = start; i > 0; i--)
2571 {
2572 if (var_str[i] == '.') return i;
2573 if (var_str[i] == '>' && i > 0 && var_str[i-1] == '-') return i-1;
2574 }
2575
2576 return end;
2577}
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:46
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:185
Int_t gErrorIgnoreLevel
Error handling routines.
Definition TError.cxx:31
void Fatal(const char *location, const char *msgfmt,...)
Use this function in case of a fatal error. It will abort the program.
Definition TError.cxx:244
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t dest
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
char name[80]
Definition TGX11.cxx:110
R__EXTERN TInterpreter * gCling
#define gInterpreter
#define gROOT
Definition TROOT.h:407
@ 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:83
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:438
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:2762
Regular expression class.
Definition TRegexp.h:31
Sequenceable collection abstract base class.
void Add(TObject *obj) override
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:417
std::istream & ReadToDelim(std::istream &str, char delim='\n')
Read up to an EOF, or a delimiting character, whichever comes first.
Definition Stringio.cxx:95
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition TString.cxx:2244
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition TString.cxx:1163
const char * Data() const
Definition TString.h:376
TString & Chop()
Definition TString.h:691
@ kLeading
Definition TString.h:276
@ kTrailing
Definition TString.h:276
@ kBoth
Definition TString.h:276
ECaseCompare
Definition TString.h:277
@ kIgnoreCase
Definition TString.h:277
@ kExact
Definition TString.h:277
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:623
TString & Prepend(const char *cs)
Definition TString.h:673
Bool_t IsNull() const
Definition TString.h:414
TString & Remove(Ssiz_t pos)
Definition TString.h:685
TString & Append(const char *cs)
Definition TString.h:572
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:632
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:651
virtual FILE * TempFileName(TString &base, const char *dir=nullptr, const char *suffix=nullptr)
Create a secure temporary file by appending a unique 6 letter string to base.
Definition TSystem.cxx:1499
void Beep(Int_t freq=-1, Int_t duration=-1, Bool_t setDefault=kFALSE)
Beep for duration milliseconds with a tone of frequency freq.
Definition TSystem.cxx:324
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition TSystem.cxx:1274
virtual void FreeDirectory(void *dirp)
Free a directory.
Definition TSystem.cxx:845
virtual void * OpenDirectory(const char *name)
Open a directory. Returns 0 if directory does not exist.
Definition TSystem.cxx:836
virtual const char * Getenv(const char *env)
Get environment variable.
Definition TSystem.cxx:1665
virtual Int_t Exec(const char *shellcmd)
Execute a command.
Definition TSystem.cxx:653
int GetPathInfo(const char *path, Long_t *id, Long_t *size, Long_t *flags, Long_t *modtime)
Get info about a file: id, size, flags, modification time.
Definition TSystem.cxx:1398
virtual const char * GetDirEntry(void *dirp)
Get a directory entry. Returns 0 if no more entries.
Definition TSystem.cxx:853
virtual const char * GetDynamicPath()
Return the dynamic path (used to find shared libraries).
Definition TSystem.cxx:1795
virtual char * Which(const char *search, const char *file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition TSystem.cxx:1548
virtual TString GetDirName(const char *pathname)
Return the directory name in pathname.
Definition TSystem.cxx:1032
virtual int Unlink(const char *name)
Unlink, i.e.
Definition TSystem.cxx:1381
static void NoMsg(Int_t errorLevel)
[static utility function]/////////////////////////////
Definition TTabCom.cxx: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:1567
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:2139
void CopyMatch(char *dest, int dest_len, const char *localName, const char *appendage=nullptr, const char *fullName=nullptr) const
[private]
Definition TTabCom.cxx:1415
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:1492
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:2255
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:2543
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:2206
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:1535
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:2565
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:1468
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:2235
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