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