22 #include "RConfigure.h"
49 #include "TApplicationCommandLineOptionsHelp.h"
53 TApplication *gApplication = 0;
54 Bool_t TApplication::fgGraphNeeded = kFALSE;
55 Bool_t TApplication::fgGraphInit = kFALSE;
56 TList *TApplication::fgApplications = 0;
60 class TIdleTimer :
public TTimer {
62 TIdleTimer(Long_t ms) : TTimer(ms, kTRUE) { }
69 Bool_t TIdleTimer::Notify()
71 gApplication->HandleIdleTimer();
77 ClassImp(TApplication);
79 static void CallEndOfProcessCleanups()
89 gROOT->SetBit(kInvalidObject);
90 gROOT->EndOfProcessCleanups();
97 TApplication::TApplication() :
98 fArgc(0), fArgv(0), fAppImp(0), fIsRunning(kFALSE), fReturnFromRun(kFALSE),
99 fNoLog(kFALSE), fNoLogo(kFALSE), fQuit(kFALSE), fUseMemstat(kFALSE),
100 fFiles(0), fIdleTimer(0), fSigHandler(0), fExitOnException(kDontExit),
103 ResetBit(kProcessRemotely);
120 TApplication::TApplication(
const char *appClassName, Int_t *argc,
char **argv,
121 void * , Int_t numOptions) :
122 fArgc(0), fArgv(0), fAppImp(0), fIsRunning(kFALSE), fReturnFromRun(kFALSE),
123 fNoLog(kFALSE), fNoLogo(kFALSE), fQuit(kFALSE), fUseMemstat(kFALSE),
124 fFiles(0), fIdleTimer(0), fSigHandler(0), fExitOnException(kDontExit),
127 R__LOCKGUARD(gInterpreterMutex);
131 fgApplications =
new TList;
137 fgApplications->Add(
this);
139 if (gApplication && gApplication->TestBit(kDefaultApplication)) {
143 gROOT->SetBatch(kFALSE);
144 fgGraphInit = kFALSE;
148 Error(
"TApplication",
"only one instance of TApplication allowed");
149 fgApplications->Remove(
this);
154 ::Fatal(
"TApplication::TApplication",
"ROOT system not initialized");
157 ::Fatal(
"TApplication::TApplication",
"gSystem not initialized");
159 static Bool_t hasRegisterAtExit(kFALSE);
160 if (!hasRegisterAtExit) {
162 atexit(CallEndOfProcessCleanups);
163 hasRegisterAtExit = kTRUE;
165 gROOT->SetName(appClassName);
168 if (argc && *argc > 0) {
170 fArgv = (
char **)
new char*[fArgc];
173 for (
int i = 0; i < fArgc; i++)
174 fArgv[i] = StrDup(argv[i]);
177 GetOptions(argc, argv);
180 gSystem->SetProgname(fArgv[0]);
183 gSystem->NotifyApplicationCreated();
185 fAppImp = gGuiFactory->CreateApplicationImp(appClassName, argc, argv);
186 ResetBit(kProcessRemotely);
189 if (gClassTable->GetDict(
"TPad")) {
190 fgGraphNeeded = kTRUE;
191 InitializeGraphics();
195 gInterpreter->SaveContext();
196 gInterpreter->SaveGlobalsContext();
199 gROOT->SetLineHasBeenProcessed();
202 if (fUseMemstat || gEnv->GetValue(
"Root.TMemStat", 0)) {
204 Int_t buffersize = gEnv->GetValue(
"Root.TMemStat.buffersize", 100000);
205 Int_t maxcalls = gEnv->GetValue(
"Root.TMemStat.maxcalls", 5000000);
206 const char *ssystem = gEnv->GetValue(
"Root.TMemStat.system",
"gnubuiltin");
208 gROOT->ProcessLine(Form(
"new TMemStat(\"%s\",%d,%d);",ssystem,buffersize,maxcalls));
214 gROOT->SetApplication(
this);
221 TApplication::~TApplication()
223 for (
int i = 0; i < fArgc; i++)
224 if (fArgv[i])
delete [] fArgv[i];
228 fgApplications->Remove(
this);
232 ProcessLine(
"TMemStat::Close()");
233 fUseMemstat = kFALSE;
239 if (fgApplications == 0 || fgApplications->FirstLink() == 0 ) {
252 void TApplication::NeedGraphicsLibs()
254 fgGraphNeeded = kTRUE;
260 void TApplication::InitializeGraphics()
262 if (fgGraphInit || !fgGraphNeeded)
return;
270 const char *ttpath = gEnv->GetValue(
"Root.TTFontPath",
271 TROOT::GetTTFFontDir());
272 char *ttfont = gSystem->Which(ttpath,
"arialbd.ttf", kReadPermission);
275 ttfont = gSystem->Which(ttpath,
"FreeSansBold.ttf", kReadPermission);
277 #if !defined(R__WIN32)
278 if (!gROOT->IsBatch() && !strcmp(gVirtualX->GetName(),
"X11") &&
279 ttfont && gEnv->GetValue(
"Root.UseTTFonts", 1)) {
280 if (gClassTable->GetDict(
"TGX11TTF")) {
284 ProcessLine(
"TGX11TTF::Activate();");
287 if ((h = gROOT->GetPluginManager()->FindHandler(
"TVirtualX",
"x11ttf")))
288 if (h->LoadPlugin() == -1)
289 Info(
"InitializeGraphics",
"no TTF support");
298 fAppImp = gGuiFactory->CreateApplicationImp(gROOT->GetName(), &fArgc, fArgv);
301 fAppImp = gGuiFactory->CreateApplicationImp(gROOT->GetName(), &fArgc, fArgv);
307 TColor::InitializeColors();
313 if (gEnv->GetValue(
"Canvas.UseScreenFactor", 1)) {
317 gVirtualX->GetGeometry(-1, x, y, w, h);
318 if (h > 0 && h < 1000) gStyle->SetScreenFactor(0.0011*h);
328 void TApplication::ClearInputFiles()
339 char *TApplication::Argv(Int_t index)
const
342 if (index >= fArgc) {
343 Error(
"Argv",
"index (%d) >= number of arguments (%d)", index, fArgc);
355 void TApplication::GetOptions(Int_t *argc,
char **argv)
357 static char null[1] = {
"" };
369 for (i = 1; i < *argc; i++) {
370 if (!strcmp(argv[i],
"-?") || !strncmp(argv[i],
"-h", 2) ||
371 !strncmp(argv[i],
"--help", 6)) {
372 fprintf(stderr, kCommandLineOptionsHelp);
374 }
else if (!strncmp(argv[i],
"--version", 9)) {
375 fprintf(stderr,
"ROOT Version: %s\n", gROOT->GetVersion());
376 fprintf(stderr,
"Built for %s on %s\n",
377 gSystem->GetBuildArch(),
378 gROOT->GetGitDate());
380 fprintf(stderr,
"From %s@%s\n",
381 gROOT->GetGitBranch(),
382 gROOT->GetGitCommit());
385 }
else if (!strcmp(argv[i],
"-config")) {
386 fprintf(stderr,
"ROOT ./configure options:\n%s\n", gROOT->GetConfigOptions());
388 }
else if (!strcmp(argv[i],
"-memstat")) {
391 }
else if (!strcmp(argv[i],
"-b")) {
394 }
else if (!strcmp(argv[i],
"-n")) {
397 }
else if (!strcmp(argv[i],
"-t")) {
398 ROOT::EnableImplicitMT();
401 ROOT::EnableThreadSafety();
403 }
else if (!strcmp(argv[i],
"-q")) {
406 }
else if (!strcmp(argv[i],
"-l")) {
410 }
else if (!strcmp(argv[i],
"-x")) {
411 fExitOnException = kExit;
413 }
else if (!strcmp(argv[i],
"-splash")) {
417 }
else if (strncmp(argv[i],
"--web", 5) == 0) {
419 const char *opt = argv[i] + 5;
422 if (gROOT->IsBatch()) argw =
"batch";
423 if (*opt ==
'=') argw.Append(opt+1);
424 if (gSystem->Load(
"libROOTWebDisplay") >= 0) {
425 gROOT->SetWebDisplay(argw.Data());
426 gEnv->SetValue(
"Gui.Factory",
"web");
428 Error(
"GetOptions",
"--web option not supported, ROOT should be built with at least c++14 enabled");
430 }
else if (!strcmp(argv[i],
"-e")) {
435 if (!fFiles) fFiles =
new TObjArray;
436 TObjString *expr =
new TObjString(argv[i]);
437 expr->SetBit(kExpression);
441 Warning(
"GetOptions",
"-e must be followed by an expression.");
443 }
else if (!strcmp(argv[i],
"--")) {
444 TObjString* macro =
nullptr;
445 bool warnShown =
false;
448 for (
auto f: *fFiles) {
449 TObjString* file =
dynamic_cast<TObjString*
>(f);
451 if (!dynamic_cast<TNamed*>(f)) {
452 Error(
"GetOptions()",
"Inconsistent file entry (not a TObjString)!");
458 if (file->TestBit(kExpression))
460 if (file->String().EndsWith(
".root"))
462 if (file->String().Contains(
'('))
465 if (macro && !warnShown && (warnShown =
true))
466 Warning(
"GetOptions",
"-- is used with several macros. "
467 "The arguments will be passed to the last one.");
476 TString& str = macro->String();
479 for (; i < *argc; i++) {
484 str.EndsWith(
",") ? str[str.Length() - 1] =
')' : str +=
')';
486 Warning(
"GetOptions",
"no macro to pass arguments to was provided. "
487 "Everything after the -- will be ignored.");
488 for (; i < *argc; i++)
491 }
else if (argv[i][0] !=
'-' && argv[i][0] !=
'+') {
493 Long_t id, flags, modtime;
494 char *arg = strchr(argv[i],
'(');
495 if (arg) *arg =
'\0';
496 char *dir = gSystem->ExpandPathName(argv[i]);
499 TUrl udir(dir, kTRUE);
501 TString sfx = udir.GetFileAndOptions();
502 TString fln = udir.GetFile();
503 sfx.Replace(sfx.Index(fln), fln.Length(),
"");
504 TString path = udir.GetFile();
505 if (strcmp(udir.GetProtocol(),
"file")) {
506 path = udir.GetUrl();
507 path.Replace(path.Index(sfx), sfx.Length(),
"");
511 if (!arg && !gSystem->GetPathInfo(path.Data(), &id, &size, &flags, &modtime)) {
515 pwd = gSystem->WorkingDirectory();
517 gSystem->ChangeDirectory(dir);
519 }
else if (!strcmp(gROOT->GetName(),
"Rint")) {
520 Warning(
"GetOptions",
"only one directory argument can be specified (%s)", dir);
522 }
else if (size > 0) {
524 if (!fFiles) fFiles =
new TObjArray;
525 fFiles->Add(
new TObjString(path.Data()));
528 Warning(
"GetOptions",
"file %s has size 0, skipping", dir);
531 if (TString(udir.GetFile()).EndsWith(
".root")) {
532 if (!strcmp(udir.GetProtocol(),
"file")) {
535 if (!strcmp(gROOT->GetName(),
"Rint"))
536 Warning(
"GetOptions",
"file %s not found", dir);
539 if (!fFiles) fFiles =
new TObjArray;
540 fFiles->Add(
new TObjString(argv[i]));
544 TString mode,fargs,io;
545 TString fname = gSystem->SplitAclicMode(dir,mode,fargs,io);
547 if (!fFiles) fFiles =
new TObjArray;
548 if ((mac = gSystem->Which(TROOT::GetMacroPath(), fname,
551 fFiles->Add(
new TObjString(argv[i]));
556 fFiles->Add(
new TNamed(
"NOT FOUND!", argv[i]));
559 if (!strcmp(gROOT->GetName(),
"Rint"))
560 Warning(
"GetOptions",
"macro %s not found", fname.Data());
571 gSystem->ChangeDirectory(pwd);
575 for (i = 0; i < *argc; i++) {
576 if (strcmp(argv[i],
"")) {
589 void TApplication::HandleIdleTimer()
591 if (!fIdleCommand.IsNull())
592 ProcessLine(GetIdleCommand());
594 Emit(
"HandleIdleTimer()");
602 void TApplication::HandleException(Int_t sig)
604 if (TROOT::Initialized()) {
606 gInterpreter->RewindDictionary();
607 gInterpreter->ClearFileBusy();
609 if (fExitOnException == kExit)
610 gSystem->Exit(128 + sig);
611 else if (fExitOnException == kAbort)
616 gSystem->Exit(128 + sig);
626 TApplication::EExitOnException TApplication::ExitOnException(TApplication::EExitOnException opt)
628 EExitOnException old = fExitOnException;
629 fExitOnException = opt;
641 void TApplication::OpenInBrowser(
const TString &url)
646 TString cMac(
"open ");
650 #elif defined(R__WIN32)
652 TString cWindows(
"start ");
653 cWindows.Append(url);
654 gSystem->Exec(cWindows);
657 TString cLinux(
"xdg-open ");
659 if (gSystem->Getenv(
"DISPLAY")) {
662 gSystem->Exec(cLinux);
665 Warning(
"OpenInBrowser",
"The $DISPLAY is not set! Please open (e.g. Ctrl-click) %s\n", url.Data());
671 enum EUrl { kURLforClass, kURLforNameSpace, kURLforStruct };
681 static TString UrlGenerator(TString scopeName, EUrl scopeType)
684 TString url =
"https://root.cern/doc/";
686 TPRegexp re4(R
"(.*/v(\d)-(\d\d)-00-patches)");
687 const char *branchName = gROOT->GetGitBranch();
688 TObjArray *objarr = re4.MatchS(branchName);
691 if (objarr && objarr->GetEntries() == 3) {
693 version = ((TObjString *)objarr->At(1))->GetString() + ((TObjString *)objarr->At(2))->GetString();
703 scopeName.ReplaceAll(
"_",
"__");
704 scopeName.ReplaceAll(
"::",
"_1_1");
706 if (scopeType == kURLforClass) {
708 }
else if (scopeType == kURLforStruct) {
709 url.Append(
"struct");
711 url.Append(
"namespace");
713 url.Append(scopeName);
730 static TString FormatMethodArgsForDoxygen(
const TString &scopeName, TFunction *func)
733 TString methodArguments = func->GetSignature();
735 methodArguments.ReplaceAll(
" = ",
"=");
736 methodArguments.ReplaceAll(
"* ",
" *");
737 methodArguments.ReplaceAll(
"*=",
" *=");
738 methodArguments.ReplaceAll(
"*)",
" *)");
739 methodArguments.ReplaceAll(
"*,",
" *,");
740 methodArguments.ReplaceAll(
"*& ",
" *&");
741 methodArguments.ReplaceAll(
"& ",
" &");
743 methodArguments.ReplaceAll(
"ostream",
"std::ostream");
744 methodArguments.ReplaceAll(
"istream",
"std::istream");
745 methodArguments.ReplaceAll(
"map",
"std::map");
746 methodArguments.ReplaceAll(
"vector",
"std::vector");
749 TString scopeNameRE(
"\\b");
750 scopeNameRE.Append(scopeName);
751 scopeNameRE.Append(
"::\\b");
752 TPRegexp argFix(scopeNameRE);
753 argFix.Substitute(methodArguments,
"");
754 return methodArguments;
769 static TString FormatReturnTypeForDoxygen(
const TString &scopeName, TFunction *func)
772 TString returnType = func->GetReturnTypeName();
775 TString scopeNameRE(
"\\b");
776 scopeNameRE.Append(scopeName);
777 scopeNameRE.Append(
"::\\b");
778 TPRegexp returnFix(scopeNameRE);
779 returnFix.Substitute(returnType,
"");
781 if (func->ExtraProperty() & kIsInlined) {
783 if (func->Property() & kIsVirtual) {
785 returnType.Prepend(
"virtual ");
787 returnType.ReplaceAll(
" *",
"*");
790 returnType.ReplaceAll(
"*",
" *");
795 returnType.ReplaceAll(
"istream",
"std::istream");
796 returnType.ReplaceAll(
"ostream",
"std::ostream");
797 returnType.ReplaceAll(
"map",
"std::map");
798 returnType.ReplaceAll(
"vector",
"std::vector");
799 returnType.ReplaceAll(
"&",
" &");
819 GetUrlForDataMember(
const TString &scopeName,
const TString &dataMemberName, TDataMember *dataMember, EUrl scopeType)
822 if (!dataMember->IsEnum()) {
826 TString md5DataMember(dataMember->GetFullTypeName());
827 md5DataMember.Append(
" ");
829 md5DataMember.Append(scopeName);
830 md5DataMember.Append(
"::");
832 md5DataMember.Append(dataMemberName);
833 md5DataMember.Append(dataMemberName);
835 TString urlForDataMember = UrlGenerator(scopeName, scopeType);
837 urlForDataMember.Append(
"#a");
838 urlForDataMember.Append(md5DataMember.MD5());
839 return urlForDataMember;
844 TString scopeEnumeration = dataMember->GetTrueTypeName();
845 TString md5EnumClass;
846 if (scopeEnumeration.Contains(
"(anonymous)")) {
848 md5EnumClass.Append(scopeName);
849 md5EnumClass.Append(
"::@1@1");
853 md5EnumClass.Append(scopeEnumeration);
855 TString enumOnlyName = TClassEdit::GetUnqualifiedName(scopeEnumeration);
857 md5EnumClass.Append(enumOnlyName);
860 TString md5Enumerator(
"@ ");
861 md5Enumerator.Append(scopeName);
862 md5Enumerator.Append(
"::");
863 md5Enumerator.Append(dataMemberName);
864 md5Enumerator.Append(dataMemberName);
866 TString url = UrlGenerator(scopeName, scopeType);
869 url.Append(md5EnumClass.MD5());
872 url.Append(md5Enumerator.MD5());
886 static TString GetUrlForEnumeration(TString scopeName,
const TString &enumeration, EUrl scopeType)
890 TString md5Enumeration(scopeName);
891 md5Enumeration.Append(
"::");
892 md5Enumeration.Append(enumeration);
893 md5Enumeration.Append(enumeration);
895 TString url(UrlGenerator(scopeName, scopeType));
898 url.Append(md5Enumeration.MD5());
904 enum EMethodKind { kURLforMethod, kURLforStructor };
919 static TString GetUrlForMethod(
const TString &scopeName,
const TString &methodName, TFunction *func,
920 EMethodKind methodType, EUrl scopeType)
923 if (methodType == kURLforMethod) {
926 md5Text.Append((FormatReturnTypeForDoxygen(scopeName, func)));
927 if (scopeType == kURLforNameSpace) {
929 if (func->Property() & kIsConstexpr) {
930 md5Text.Prepend(
"constexpr ");
936 md5Text.Append(scopeName);
937 md5Text.Append(
"::");
938 md5Text.Append(methodName);
939 md5Text.Append(methodName);
941 md5Text.Append(FormatMethodArgsForDoxygen(scopeName, func));
943 TString url = UrlGenerator(scopeName, scopeType);
946 url.Append(md5Text.MD5());
960 void TApplication::OpenReferenceGuideFor(
const TString &strippedClass)
963 if (TClass *clas = TClass::GetClass(strippedClass)) {
967 if (clas->Property() & kIsNamespace) {
968 scopeType = kURLforNameSpace;
969 }
else if (clas->Property() & kIsStruct) {
970 scopeType = kURLforStruct;
972 scopeType = kURLforClass;
975 OpenInBrowser(UrlGenerator(strippedClass, scopeType));
979 TString memberName = TClassEdit::GetUnqualifiedName(strippedClass);
982 if (strippedClass == memberName) {
983 Error(
"OpenReferenceGuideFor",
"Unknown entity \"%s\" - global variables / functions not supported yet!",
984 strippedClass.Data());
988 TString scopeName = strippedClass(0, strippedClass.Length() - memberName.Length() - 2);
990 TClass *cl = TClass::GetClass(scopeName);
993 Warning(
"OpenReferenceGuideFor",
"\"%s\" does not exist in ROOT!", scopeName.Data());
998 if (cl->Property() & kIsNamespace) {
999 scopeType = kURLforNameSpace;
1000 }
else if (cl->Property() & kIsStruct) {
1001 scopeType = kURLforStruct;
1003 scopeType = kURLforClass;
1008 int bracket = memberName.First(
"(");
1010 memberName.Remove(bracket);
1013 if (TFunction *func = cl->GetMethodAllAny(memberName)) {
1015 TString baseClName = ((TMethod *)func)->GetClass()->GetName();
1017 EMethodKind methodType;
1019 if (baseClName == memberName) {
1020 methodType = kURLforStructor;
1022 }
else if (memberName[0] ==
'~') {
1023 methodType = kURLforStructor;
1026 methodType = kURLforMethod;
1029 OpenInBrowser(GetUrlForMethod(baseClName, memberName, func, methodType, scopeType));
1033 if (cl->GetListOfEnums()->FindObject(memberName)) {
1036 OpenInBrowser(GetUrlForEnumeration(scopeName, memberName, scopeType));
1041 if (
auto enumerator = (TDataMember *)cl->GetListOfAllPublicDataMembers()->FindObject(memberName)) {
1043 TString baseClName = ((TMethod *)enumerator->GetClass())->GetName();
1044 OpenInBrowser(GetUrlForDataMember(baseClName, memberName, enumerator, scopeType));
1050 Warning(
"Help",
"cannot find \"%s\" as member of %s or its base classes! Check %s\n", memberName.Data(),
1051 scopeName.Data(), UrlGenerator(scopeName, scopeType).Data());
1060 void TApplication::Help(
const char *line)
1063 TString strippedCommand = TString(line).Strip(TString::kBoth);
1065 if ((strippedCommand ==
".help") || (strippedCommand ==
".?")) {
1066 gInterpreter->ProcessLine(line);
1067 Printf(
"\nROOT special commands.");
1068 Printf(
"==========================================================================");
1069 Printf(
" pwd : show current directory, pad and style");
1070 Printf(
" ls : list contents of current directory");
1071 Printf(
" which [file] : shows path of macro file");
1072 Printf(
" .help Class : opens the reference guide for that class");
1073 Printf(
" .help Class::Member : opens the reference guide for function/member");
1078 if ((!strippedCommand.BeginsWith(
".help ")) && (!strippedCommand.BeginsWith(
".? "))) {
1079 Error(
"Help",
"Unknown command!");
1083 if (strippedCommand.BeginsWith(
".? ")) {
1084 strippedCommand.Remove(0, 3);
1086 strippedCommand.Remove(0, 5);
1089 strippedCommand = strippedCommand.Strip(TString::kBoth);
1091 OpenReferenceGuideFor(strippedCommand);
1098 void TApplication::LoadGraphicsLibs()
1100 if (gROOT->IsBatch())
return;
1103 if ((h = gROOT->GetPluginManager()->FindHandler(
"TVirtualPad")))
1104 if (h->LoadPlugin() == -1)
1108 TString title1 =
"ROOT interface to ";
1109 TString nativex, title;
1110 TString nativeg =
"root";
1113 nativex =
"win32gdk";
1115 title = title1 +
"Win32gdk";
1116 #elif defined(R__HAS_COCOA)
1119 title = title1 +
"Quartz";
1123 title = title1 +
"X11";
1126 TString guiBackend(gEnv->GetValue(
"Gui.Backend",
"native"));
1127 guiBackend.ToLower();
1128 if (guiBackend ==
"native") {
1129 guiBackend = nativex;
1132 title = title1 + guiBackend;
1134 TString guiFactory(gEnv->GetValue(
"Gui.Factory",
"native"));
1135 guiFactory.ToLower();
1136 if (guiFactory ==
"native")
1137 guiFactory = nativeg;
1139 if ((h = gROOT->GetPluginManager()->FindHandler(
"TVirtualX", guiBackend))) {
1140 if (h->LoadPlugin() == -1) {
1141 gROOT->SetBatch(kTRUE);
1144 gVirtualX = (TVirtualX *) h->ExecPlugin(2, name.Data(), title.Data());
1145 fgGraphInit = kTRUE;
1147 if ((h = gROOT->GetPluginManager()->FindHandler(
"TGuiFactory", guiFactory))) {
1148 if (h->LoadPlugin() == -1) {
1149 gROOT->SetBatch(kTRUE);
1152 gGuiFactory = (TGuiFactory *) h->ExecPlugin(0);
1159 void TApplication::MakeBatch()
1162 if (gGuiFactory != gBatchGuiFactory)
delete gGuiFactory;
1163 gGuiFactory = gBatchGuiFactory;
1165 if (gVirtualX != gGXBatch)
delete gVirtualX;
1167 gVirtualX = gGXBatch;
1183 Int_t TApplication::ParseRemoteLine(
const char *ln,
1184 TString &hostdir, TString &user,
1185 Int_t &dbg, TString &script)
1187 if (!ln || strlen(ln) <= 0)
1191 Bool_t isHostDir = kTRUE;
1192 Bool_t isScript = kFALSE;
1193 Bool_t isUser = kFALSE;
1194 Bool_t isDbg = kFALSE;
1199 while (line.Tokenize(tkn, from,
" ")) {
1203 }
else if (tkn ==
"-d") {
1205 }
else if (tkn ==
"-close") {
1207 }
else if (tkn.BeginsWith(
"-")) {
1208 ::Warning(
"TApplication::ParseRemoteLine",
"unknown option: %s", tkn.Data());
1216 }
else if (isHostDir) {
1218 hostdir.ReplaceAll(
":",
"/");
1221 }
else if (isScript) {
1224 script.Insert(0,
"\"");
1249 Long_t TApplication::ProcessRemote(
const char *line, Int_t *)
1251 if (!line)
return 0;
1253 if (!strncmp(line,
"-?", 2) || !strncmp(line,
"-h", 2) ||
1254 !strncmp(line,
"--help", 6)) {
1255 Info(
"ProcessRemote",
"remote session help:");
1256 Printf(
".R [user@]host[:dir] [-l user] [-d dbg] [[<]script] | [host] -close");
1257 Printf(
"Create a ROOT session on the specified remote host.");
1258 Printf(
"The variable \"dir\" is the remote directory to be used as working dir.");
1259 Printf(
"The username can be specified in two ways, \"-l\" having the priority");
1260 Printf(
"(as in ssh). A \"dbg\" value > 0 gives increasing verbosity.");
1261 Printf(
"The last argument \"script\" allows to specify an alternative script to");
1262 Printf(
"be executed remotely to startup the session, \"roots\" being");
1263 Printf(
"the default. If the script is preceded by a \"<\" the script will be");
1264 Printf(
"sourced, after which \"roots\" is executed. The sourced script can be ");
1265 Printf(
"used to change the PATH and other variables, allowing an alternative");
1266 Printf(
"\"roots\" script to be found.");
1267 Printf(
"To close down a session do \".R host -close\".");
1268 Printf(
"To switch between sessions do \".R host\", to switch to the local");
1269 Printf(
"session do \".R\".");
1270 Printf(
"To list all open sessions do \"gApplication->GetApplications()->Print()\".");
1274 TString hostdir, user, script;
1276 Int_t rc = ParseRemoteLine(line, hostdir, user, dbg, script);
1277 if (hostdir.Length() <= 0) {
1280 TApplication::Close(fAppRemote);
1287 }
else if (rc == 1) {
1289 TApplication *ap = TApplication::Open(hostdir, 0, 0);
1291 TApplication::Close(ap);
1296 if (user.Length() > 0)
1297 hostdir.Insert(0,Form(
"%s@", user.Data()));
1298 const char *sc = (script.Length() > 0) ? script.Data() : 0;
1299 TApplication *ap = TApplication::Open(hostdir, dbg, sc);
1309 static int PrintFile(
const char* filename) {
1310 TString sFileName(filename);
1311 gSystem->ExpandPathName(sFileName);
1312 if (gSystem->AccessPathName(sFileName)) {
1313 Error(
"ProcessLine()",
"Cannot find file %s", filename);
1316 std::ifstream instr(sFileName);
1318 content.ReadFile(instr);
1319 Printf(
"%s", content.Data());
1329 Long_t TApplication::ProcessLine(
const char *line, Bool_t sync, Int_t *err)
1331 if (!line || !*line)
return 0;
1334 if (!strncmp(line,
".R", 2)) {
1336 while (*(line+n) ==
' ')
1338 return ProcessRemote(line+n, err);
1342 if (fAppRemote && TestBit(kProcessRemotely)) {
1343 ResetBit(kProcessRemotely);
1344 return fAppRemote->ProcessLine(line, err);
1347 if (!strncasecmp(line,
".qqqqqqq", 7)) {
1349 }
else if (!strncasecmp(line,
".qqqqq", 5)) {
1350 Info(
"ProcessLine",
"Bye... (try '.qqqqqqq' if still running)");
1352 }
else if (!strncasecmp(line,
".exit", 4) || !strncasecmp(line,
".quit", 2)) {
1357 if (!strncmp(line,
".?", 2) || !strncmp(line,
".help", 5)) {
1362 if (!strncmp(line,
".demo", 5)) {
1363 if (gROOT->IsBatch()) {
1364 Error(
"ProcessLine",
"Cannot show demos in batch mode!");
1367 ProcessLine(
".x " + TROOT::GetTutorialDir() +
"/demos.C");
1371 if (!strncmp(line,
".license", 8)) {
1372 return PrintFile(TROOT::GetDocDir() +
"/LICENSE");
1375 if (!strncmp(line,
".credits", 8)) {
1376 TString credits = TROOT::GetDocDir() +
"/CREDITS";
1377 if (gSystem->AccessPathName(credits, kReadPermission))
1378 credits = TROOT::GetDocDir() +
"/README/CREDITS";
1379 return PrintFile(credits);
1382 if (!strncmp(line,
".pwd", 4)) {
1384 Printf(
"Current directory: %s", gDirectory->GetPath());
1386 Printf(
"Current pad: %s", gPad->GetName());
1388 Printf(
"Current style: %s", gStyle->GetName());
1392 if (!strncmp(line,
".ls", 3)) {
1393 const char *opt = 0;
1394 if (line[3]) opt = &line[3];
1395 if (gDirectory) gDirectory->ls(opt);
1399 if (!strncmp(line,
".which", 6)) {
1400 char *fn = Strip(line+7);
1401 char *s = strtok(fn,
"+(");
1402 char *mac = gSystem->Which(TROOT::GetMacroPath(), s, kReadPermission);
1404 Printf(
"No macro %s in path %s", s, TROOT::GetMacroPath());
1412 if (!strncmp(line,
".L", 2) || !strncmp(line,
".U", 2)) {
1416 TString fname = gSystem->SplitAclicMode(line+3, aclicMode, arguments, io);
1418 char *mac = gSystem->Which(TROOT::GetMacroPath(), fname, kReadPermission);
1419 if (arguments.Length()) {
1420 Warning(
"ProcessLine",
"argument(s) \"%s\" ignored with .%c", arguments.Data(),
1425 Error(
"ProcessLine",
"macro %s not found in path %s", fname.Data(),
1426 TROOT::GetMacroPath());
1428 TString cmd(line+1);
1429 Ssiz_t posSpace = cmd.Index(
' ');
1430 if (posSpace == -1) cmd.Remove(1);
1431 else cmd.Remove(posSpace);
1434 tempbuf.Form(
".%s %s%s%s", cmd.Data(), mac, aclicMode.Data(),io.Data());
1435 retval = gInterpreter->ProcessLineSynch(tempbuf,
1436 (TInterpreter::EErrorCode*)err);
1438 tempbuf.Form(
".%s %s%s%s", cmd.Data(), mac, aclicMode.Data(),io.Data());
1439 retval = gInterpreter->ProcessLine(tempbuf,
1440 (TInterpreter::EErrorCode*)err);
1446 InitializeGraphics();
1451 if (!strncmp(line,
".X", 2) || !strncmp(line,
".x", 2)) {
1452 return ProcessFile(line+3, err, line[2] ==
'k');
1455 if (!strcmp(line,
".reset")) {
1457 Printf(
"*** .reset not allowed, please use gROOT->Reset() ***");
1463 gROOT->GetListOfClasses()->Delete();
1469 return gInterpreter->ProcessLineSynch(line, (TInterpreter::EErrorCode*)err);
1471 return gInterpreter->ProcessLine(line, (TInterpreter::EErrorCode*)err);
1477 Long_t TApplication::ProcessFile(
const char *file, Int_t *error, Bool_t keep)
1479 return ExecuteFile(file, error, keep);
1486 Long_t TApplication::ExecuteFile(
const char *file, Int_t *error, Bool_t keep)
1488 static const Int_t kBufSize = 1024;
1490 if (!file || !*file)
return 0;
1495 TString fname = gSystem->SplitAclicMode(file, aclicMode, arguments, io);
1497 char *exnam = gSystem->Which(TROOT::GetMacroPath(), fname, kReadPermission);
1499 ::Error(
"TApplication::ExecuteFile",
"macro %s not found in path %s", fname.Data(),
1500 TROOT::GetMacroPath());
1503 *error = (Int_t)TInterpreter::kRecoverable;
1507 ::std::ifstream macro(exnam, std::ios::in);
1508 if (!macro.good()) {
1509 ::Error(
"TApplication::ExecuteFile",
"%s no such file", exnam);
1511 *error = (Int_t)TInterpreter::kRecoverable;
1516 char currentline[kBufSize];
1517 char dummyline[kBufSize];
1523 Bool_t execute = kFALSE;
1527 bool res = (bool)macro.getline(currentline, kBufSize);
1528 if (macro.eof())
break;
1533 while (!macro.getline(dummyline, kBufSize) && !macro.eof()) {
1538 while (s && (*s ==
' ' || *s ==
'\t')) s++;
1544 char *cs = Compress(currentline);
1545 if (strstr(cs,
"#ifndef__CINT__") ||
1546 strstr(cs,
"#if!defined(__CINT__)"))
1548 else if (ifndefc && (strstr(cs,
"#ifdef") || strstr(cs,
"#ifndef") ||
1549 strstr(cs,
"#ifdefined") || strstr(cs,
"#if!defined")))
1551 else if (ifndefc && strstr(cs,
"#endif")) {
1556 }
else if (ifndefc && !ifdef && strstr(cs,
"#else"))
1560 if (!*s || *s ==
'#' || ifndefc || !strncmp(s,
"//", 2))
continue;
1562 if (!comment && (!strncmp(s,
".X", 2) || !strncmp(s,
".x", 2))) {
1563 retval = ExecuteFile(s+3);
1568 if (!strncmp(s,
"/*", 2)) comment = 1;
1572 s = strstr(s,
"*/");
1577 while (s && (*s ==
' ' || *s ==
'\t')) s++;
1579 if (!strncmp(s,
"//", 2))
continue;
1580 if (!strncmp(s,
"/*", 2)) {
1586 if (!comment && *s ==
'{') tempfile = 1;
1587 if (!comment)
break;
1592 TString exname = exnam;
1596 exname += aclicMode;
1598 exname += arguments;
1603 tempbuf.Form(
".x %s", exname.Data());
1605 tempbuf.Form(
".X%s %s", keep ?
"k" :
" ", exname.Data());
1607 retval = gInterpreter->ProcessLineSynch(tempbuf,(TInterpreter::EErrorCode*)error);
1617 void TApplication::Run(Bool_t retrn)
1619 SetReturnFromRun(retrn);
1624 fIsRunning = kFALSE;
1631 void TApplication::SetIdleTimer(UInt_t idleTimeInSec,
const char *command)
1633 if (fIdleTimer) RemoveIdleTimer();
1634 fIdleCommand = command;
1635 fIdleTimer =
new TIdleTimer(idleTimeInSec*1000);
1636 gSystem->AddTimer(fIdleTimer);
1642 void TApplication::RemoveIdleTimer()
1646 SafeDelete(fIdleTimer);
1653 void TApplication::StartIdleing()
1656 fIdleTimer->Reset();
1657 gSystem->AddTimer(fIdleTimer);
1664 void TApplication::StopIdleing()
1667 gSystem->RemoveTimer(fIdleTimer);
1674 Int_t TApplication::TabCompletionHook(
char* ,
int* , std::ostream& )
1684 void TApplication::Terminate(Int_t status)
1686 Emit(
"Terminate(Int_t)", status);
1689 gSystem->ExitLoop();
1693 ProcessLine(
"TMemStat::Close()");
1694 fUseMemstat = kFALSE;
1697 gSystem->Exit(status);
1704 void TApplication::LineProcessed(
const char *line)
1706 Emit(
"LineProcessed(const char*)", line);
1712 void TApplication::KeyPressed(Int_t key)
1714 Emit(
"KeyPressed(Int_t)", key);
1720 void TApplication::ReturnPressed(
char *text )
1722 Emit(
"ReturnPressed(char*)", text);
1731 void TApplication::SetEchoMode(Bool_t)
1738 void TApplication::CreateApplication()
1740 R__LOCKGUARD(gROOTMutex);
1742 if (!gApplication) {
1743 char *a = StrDup(
"RootApp");
1744 char *b = StrDup(
"-b");
1749 new TApplication(
"RootApp", &argc, argv, 0, 0);
1751 Printf(
"<TApplication::CreateApplication>: "
1752 "created default TApplication");
1753 delete [] a;
delete [] b;
1754 gApplication->SetBit(kDefaultApplication);
1762 TApplication *TApplication::Open(
const char *url,
1763 Int_t debug,
const char *script)
1765 TApplication *ap = 0;
1770 if (fgApplications) {
1771 TIter nxa(fgApplications);
1772 while ((ap = (TApplication *) nxa())) {
1773 TString apn(ap->ApplicationName());
1780 if (strlen(au.GetUser()) > 0 && strlen(nu.GetUser()) > 0 &&
1781 !strcmp(au.GetUser(), nu.GetUser())) {
1782 if (!strncmp(au.GetHost(), nu.GetHost(), strlen(nu.GetHost())))
1789 ::Error(
"TApplication::Open",
"list of applications undefined - protocol error");
1796 nu.SetOptions(Form(
"%d", nnew));
1800 TPluginHandler *h = 0;
1801 if ((h = gROOT->GetPluginManager()->FindHandler(
"TApplication",
"remote"))) {
1802 if (h->LoadPlugin() == 0) {
1803 ap = (TApplication *) h->ExecPlugin(3, nu.GetUrl(), debug, script);
1805 ::Error(
"TApplication::Open",
"failed to load plugin for TApplicationRemote");
1808 ::Error(
"TApplication::Open",
"failed to find plugin for TApplicationRemote");
1812 if (ap && !(ap->TestBit(kInvalidObject))) {
1813 fgApplications->Add(ap);
1814 gROOT->GetListOfBrowsables()->Add(ap, ap->ApplicationName());
1815 TIter next(gROOT->GetListOfBrowsers());
1817 while ((b = (TBrowser*) next()))
1818 b->Add(ap, ap->ApplicationName());
1819 gROOT->RefreshBrowsers();
1822 ::Error(
"TApplication::Open",
1823 "TApplicationRemote for %s could not be instantiated", url);
1833 void TApplication::Close(TApplication *app)
1837 fgApplications->Remove(app);
1838 gROOT->GetListOfBrowsables()->RecursiveRemove(app);
1839 TIter next(gROOT->GetListOfBrowsers());
1841 while ((b = (TBrowser*) next()))
1842 b->RecursiveRemove(app);
1843 gROOT->RefreshBrowsers();
1850 void TApplication::ls(Option_t *opt)
const
1852 if (fgApplications) {
1853 TIter nxa(fgApplications);
1854 TApplication *a = 0;
1855 while ((a = (TApplication *) nxa())) {
1866 TList *TApplication::GetApplications()
1868 return fgApplications;