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