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