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