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