Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TApplication.cxx
Go to the documentation of this file.
1// @(#)root/base:$Id$
2// Author: Fons Rademakers 22/12/95
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class TApplication
13\ingroup Base
14
15This class creates the ROOT Application Environment that interfaces
16to the windowing system eventloop and eventhandlers.
17This class must be instantiated exactly once in any given
18application. Normally the specific application class inherits from
19TApplication (see TRint).
20*/
21
22#include "RConfigure.h"
23#include "TApplication.h"
24#include "TException.h"
25#include "TGuiFactory.h"
26#include "TVirtualX.h"
27#include "TROOT.h"
28#include "TSystem.h"
29#include "TString.h"
30#include "TError.h"
31#include "TObjArray.h"
32#include "TObjString.h"
33#include "TTimer.h"
34#include "TInterpreter.h"
35#include "TStyle.h"
36#include "TVirtualPad.h"
37#include "TEnv.h"
38#include "TColor.h"
39#include "TPluginManager.h"
40#include "TClassTable.h"
41#include "TBrowser.h"
42#include "TUrl.h"
43#include "TVirtualMutex.h"
44#include "TClassEdit.h"
45#include "TMethod.h"
46#include "TDataMember.h"
47#include "optparse.hxx"
48#include "TPRegexp.h"
49#include <ROOT/StringUtils.hxx>
50#include <cstdlib>
51#include <iostream>
52#include <fstream>
54
58TList *TApplication::fgApplications = nullptr; // List of available applications
59
60////////////////////////////////////////////////////////////////////////////////
61
62class TIdleTimer : public TTimer {
63public:
65 Bool_t Notify() override;
66};
67
68////////////////////////////////////////////////////////////////////////////////
69/// Notify handler.
70
77
78
79
81{
82 // Insure that the files, canvases and sockets are closed.
83
84 // If we get here, the tear down has started. We have no way to know what
85 // has or has not yet been done. In particular on Ubuntu, this was called
86 // after the function static in TSystem.cxx has been destructed. So we
87 // set gROOT in its end-of-life mode which prevents executing code, like
88 // autoloading libraries (!) that is pointless ...
89 if (gROOT) {
90 gROOT->SetBit(kInvalidObject);
91 gROOT->EndOfProcessCleanups();
92 }
93}
94
95////////////////////////////////////////////////////////////////////////////////
96/// Default ctor. Can be used by classes deriving from TApplication.
97
99 fArgc(0), fArgv(nullptr), fAppImp(nullptr), fIsRunning(kFALSE), fReturnFromRun(kFALSE),
100 fNoLog(kFALSE), fNoLogo(kFALSE), fQuit(kFALSE),
101 fFiles(nullptr), fIdleTimer(nullptr), fSigHandler(nullptr), fExitOnException(kDontExit),
102 fAppRemote(nullptr)
103{
105}
106
107////////////////////////////////////////////////////////////////////////////////
108/// Create an application environment. The application environment
109/// provides an interface to the graphics system and eventloop
110/// (be it X, Windows, macOS or BeOS). After creating the application
111/// object start the eventloop by calling its Run() method. The command
112/// line options recognized by TApplication are described in the GetOptions()
113/// method. The recognized options are removed from the argument array.
114/// The original list of argument options can be retrieved via the Argc()
115/// and Argv() methods. The "options" and "numOptions" arguments are not used,
116/// except if you want to by-pass the argv processing by GetOptions()
117/// in which case you should specify numOptions<0. All options will
118/// still be available via the Argv() method for later use.
119
120TApplication::TApplication(const char *appClassName, Int_t *argc, char **argv,
121 void * /*options*/, Int_t numOptions) :
122 fArgc(0), fArgv(nullptr), fAppImp(nullptr), fIsRunning(kFALSE), fReturnFromRun(kFALSE),
123 fNoLog(kFALSE), fNoLogo(kFALSE), fQuit(kFALSE),
124 fFiles(nullptr), fIdleTimer(nullptr), fSigHandler(nullptr), fExitOnException(kDontExit),
125 fAppRemote(nullptr)
126{
128
129 // Create the list of applications the first time
130 if (!fgApplications)
131 fgApplications = new TList;
132
133 // Add the new TApplication early, so that the destructor of the
134 // default TApplication (if it is called in the block of code below)
135 // will not destroy the files, socket or TColor that have already been
136 // created.
137 fgApplications->Add(this);
138
140 // allow default TApplication to be replaced by a "real" TApplication
141 delete gApplication;
142 gApplication = nullptr;
143 gROOT->SetBatch(kFALSE);
145 }
146
147 if (gApplication) {
148 Error("TApplication", "only one instance of TApplication allowed");
149 fgApplications->Remove(this);
150 return;
151 }
152
153 if (!gROOT)
154 ::Fatal("TApplication::TApplication", "ROOT system not initialized");
155
156 if (!gSystem)
157 ::Fatal("TApplication::TApplication", "gSystem not initialized");
158
159 static Bool_t hasRegisterAtExit(kFALSE);
160 if (!hasRegisterAtExit) {
161 // If we are the first TApplication register the atexit)
163 hasRegisterAtExit = kTRUE;
164 }
165 gROOT->SetName(appClassName);
166
167 // copy command line arguments, can be later accessed via Argc() and Argv()
168 if (argc && *argc > 0) {
169 fArgc = *argc;
170 fArgv = (char **)new char*[fArgc];
171 }
172
173 for (int i = 0; i < fArgc; i++)
174 fArgv[i] = StrDup(argv[i]);
175
176 if (numOptions >= 0)
177 GetOptions(argc, argv);
178
179 if (fArgv)
181
182 // Alternative to '-b' command line switch (i.e. for pyROOT)
183 if (gSystem->Getenv("ROOT_BATCH"))
184 MakeBatch();
185
186 // Tell TSystem the TApplication has been created
188
189 fAppImp = gGuiFactory->CreateApplicationImp(appClassName, argc, argv);
191
192 // Initialize the graphics environment
193 if (gClassTable->GetDict("TPad")) {
195 InitializeGraphics(gROOT->IsWebDisplay());
196 }
197
198 // Save current interpreter context
199 gInterpreter->SaveContext();
200 gInterpreter->SaveGlobalsContext();
201
202 // to allow user to interact with TCanvas's under WIN32
203 gROOT->SetLineHasBeenProcessed();
204
205 //Needs to be done last
206 gApplication = this;
207 gROOT->SetApplication(this);
208
209}
210
211////////////////////////////////////////////////////////////////////////////////
212/// TApplication dtor.
213
215{
216 for (int i = 0; i < fArgc; i++)
217 if (fArgv[i]) delete [] fArgv[i];
218 delete [] fArgv;
219
220 if (fgApplications)
221 fgApplications->Remove(this);
222
223 // Reduce the risk of the files or sockets being closed after the
224 // end of 'main' (or more exactly before the library start being
225 // unloaded).
226 if (fgApplications == nullptr || fgApplications->FirstLink() == nullptr ) {
228 }
229
230 // Now that all the canvases and files have been closed we can
231 // delete the implementation.
233}
234
235////////////////////////////////////////////////////////////////////////////////
236/// Static method. This method should be called from static library
237/// initializers if the library needs the low level graphics system.
238
243
244////////////////////////////////////////////////////////////////////////////////
245/// Initialize the graphics environment.
246/// If @param only_web is specified, only web-related part of graphics is loaded
247
249{
251 return;
252
253 Bool_t use_x11 = kFALSE;
254
255 if (!only_web) {
256 // Load the graphics related libraries
258
259 use_x11 = gGuiFactory->UseVirtualX();
260
261 if (use_x11) {
262 // Try to load TrueType font renderer. Only try to load if not in batch
263 // mode and Root.UseTTFonts is true and Root.TTFontPath exists. Abort silently
264 // if libttf or libGX11TTF are not found in $ROOTSYS/lib or $ROOTSYS/ttf/lib.
265 const char *ttpath = gEnv->GetValue("Root.TTFontPath",
267 char *ttfont = gSystem->Which(ttpath, "arialbd.ttf", kReadPermission);
268 // Check for use of DFSG - fonts
269 if (!ttfont)
270 ttfont = gSystem->Which(ttpath, "FreeSansBold.ttf", kReadPermission);
271
272 #if !defined(R__WIN32)
273 if (!gROOT->IsBatch() && !strcmp(gVirtualX->GetName(), "X11") &&
274 ttfont && gEnv->GetValue("Root.UseTTFonts", 1)) {
275 if (gClassTable->GetDict("TGX11TTF")) {
276 // in principle we should not have linked anything against libGX11TTF
277 // but with ACLiC this can happen, initialize TGX11TTF by hand
278 // (normally this is done by the static library initializer)
279 ProcessLine("TGX11TTF::Activate();");
280 } else {
281 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualX", "x11ttf"))
282 if (h->LoadPlugin() == -1)
283 Info("InitializeGraphics", "no TTF support");
284 }
285 }
286 #endif
287 delete [] ttfont;
288 }
289 }
290
291 if (!only_web || !fAppImp) {
292 // Create WM dependent application environment
293 if (fAppImp)
294 delete fAppImp;
296 if (!fAppImp) {
297 MakeBatch();
299 }
300 }
301
302 // Create the canvas colors early so they are allocated before
303 // any color table expensive bitmaps get allocated in GUI routines (like
304 // creation of XPM bitmaps).
306
307 // Hook for further initializing the WM dependent application environment
308 Init();
309
310 // Set default screen factor (if not disabled in rc file)
311 if (use_x11 && gVirtualX && gEnv->GetValue("Canvas.UseScreenFactor", 1)) {
312 Int_t x, y;
313 UInt_t w, h;
314 gVirtualX->GetGeometry(-1, x, y, w, h);
315 if (h > 0)
316 gStyle->SetScreenFactor(0.001 * h);
317 }
318}
319
320////////////////////////////////////////////////////////////////////////////////
321/// Clear list containing macro files passed as program arguments.
322/// This method is called from TRint::Run() to ensure that the macro
323/// files are only executed the first time Run() is called.
324
326{
327 if (fFiles) {
328 fFiles->Delete();
330 }
331}
332
333////////////////////////////////////////////////////////////////////////////////
334/// Return specified argument.
335
337{
338 if (fArgv) {
339 if (index >= fArgc) {
340 Error("Argv", "index (%d) >= number of arguments (%d)", index, fArgc);
341 return nullptr;
342 }
343 return fArgv[index];
344 }
345 return nullptr;
346}
347
348////////////////////////////////////////////////////////////////////////////////
349/// Get and handle command line options. Arguments handled are removed
350/// from the argument array. See CommandLineOptionsHelp.h for options.
351
352void TApplication::GetOptions(Int_t *argc, char **argv)
353{
354 fNoLog = kFALSE;
355 fQuit = kFALSE;
356 fFiles = nullptr;
357
358 if (!argc)
359 return;
360
361 // Due to --web accepting 0 or 1 arguments we can't process it with RCmdLineOpts, so do a preprocessing for it.
362 for (int i = 1; i < *argc; ++i) {
363 if (strcmp(argv[i], "--web") != 0)
364 continue;
365
366 Warning("TApplication", "Flag `--web` without arguments is deprecated, use `--web=on` instead.");
367 if (argv[i][5] == '=') {
368 gROOT->SetWebDisplay(argv[i] + 6);
369 } else {
370 gROOT->SetWebDisplay("");
371 }
372
373 // Remove this flag from argc/argv, otherwise TRint's ctor will complain.
374 for (int j = i + 1; j < *argc; ++j) {
375 argv[j - 1] = argv[j];
376 }
377 *argc -= 1;
378 break;
379 }
380
381 ROOT::RCmdLineOpts::RSettings settings;
382 settings.fIgnoreUnknownFlags = true;
383 ROOT::RCmdLineOpts opts{settings};
384 opts.AddFlag({"-b", "--batch"});
385 opts.AddFlag({"-x", "--exit-on-exceptions"});
386 opts.AddFlag({"-e", "--execute"}, ROOT::RCmdLineOpts::EFlagType::kWithArg, "",
387 ROOT::RCmdLineOpts::kFlagAllowMultiple);
388 opts.AddFlag({"-n", "--no-logon-logoff"});
389 opts.AddFlag({"-t", "--enable-threading"});
390 opts.AddFlag({"-q", "--quit-after-processing"});
391 opts.AddFlag({"-l", "--no-banner"});
392 opts.AddFlag({"-a"});
393 opts.AddFlag({"-splash"}); // this option is ignored.
394 opts.AddFlag({"-config", "--config"});
395 opts.AddFlag({"-h", "-?", "--help"});
396 // This is a hack to disallow `--web on` and similar, which cannot be disambiguated easily with the arg-less `--web`.
397 // This way we force --web to be called with the equal sign like `--web=on` and no space in between (like it was
398 // before using the optparse lib).
399 // Downside: this makes `--web==on` legal, but that's not really a big deal.
400 opts.AddFlag({"--web="}, ROOT::RCmdLineOpts::EFlagType::kWithArg, "", ROOT::RCmdLineOpts::kFlagPrefixArg);
401 opts.AddFlag({"--version"});
402
403 opts.Parse(argv + 1, *argc - 1);
404 for (const auto &err : opts.GetErrors()) {
405 fprintf(stderr, "%s\n", err.c_str());
406 }
407 if (!opts.GetErrors().empty())
408 Terminate(0);
409
410 if (opts.GetSwitch("help")) {
411 fprintf(stderr, kCommandLineOptionsHelp);
412 Terminate(0);
413 }
414 if (opts.GetSwitch("version")) {
415 fprintf(stderr, "ROOT Version: %s\n", gROOT->GetVersion());
416 fprintf(stderr, "Built for %s on %s\n",
418 gROOT->GetGitDate());
419 fprintf(stderr, "From %s@%s\n",
420 gROOT->GetGitBranch(),
421 gROOT->GetGitCommit());
422 Terminate(0);
423 }
424 if (opts.GetSwitch("config")) {
425 fprintf(stderr, "ROOT ./configure options:\n%s\n", gROOT->GetConfigOptions());
426 Terminate(0);
427 }
428 if (opts.GetSwitch("a")) {
429 fprintf(stderr, "ROOT splash screen is not visible with root.exe, use root instead.\n");
430 Terminate(0);
431 }
432 if (opts.GetSwitch("b")) {
433 MakeBatch();
434 }
435 if (opts.GetSwitch("n")) {
436 fNoLog = kTRUE;
437 }
438 if (opts.GetSwitch("t")) {
440 // EnableImplicitMT() only enables thread safety if IMT was configured;
441 // enable thread safety even with IMT off:
443 }
444 if (opts.GetSwitch("q")) {
445 fQuit = kTRUE;
446 }
447 if (opts.GetSwitch("l")) {
448 // used by front-end program to not display splash screen
449 fNoLogo = kTRUE;
450 }
451 if (opts.GetSwitch("x")) {
453 }
454 if (opts.GetSwitch("splash")) {
455 Warning("TApplication", "Flag `-splash` is deprecated and ignored.");
456 }
457
458 if (auto web = opts.GetFlagValue("web="); !web.empty()) {
459 gROOT->SetWebDisplay(std::string(web).c_str());
460 }
461
462 std::vector<std::pair<std::size_t, TObject *>> filesToAdd;
463 // NOTE: "-e" expressions and positional arguments (actual files) must be added in exact order of appearance, so
464 // we cannot process them separately right away. We instead add them to the `filesToAdd` vector and sort them
465 // by appearance order before adding them to fFiles.
466 for (const auto &flag : opts.GetFlags()) {
467 if (flag.fName == "e" || flag.fName == "execute") {
468 auto *expr = new TObjString(std::string(flag.fValue).c_str());
469 expr->SetBit(kExpression);
470 filesToAdd.emplace_back(flag.fIndex, expr);
471 }
472 }
473
474 const auto positionalArgsWithIndices = opts.GetArgsWithIndices();
475 const auto lastArgBeforeDashDash = opts.GetFirstPostDashDashArg().value_or(positionalArgsWithIndices.size());
476
477 TString pwd;
478
479 // Process all positional arguments before `--`
480 for (std::size_t i = 0; i < lastArgBeforeDashDash; ++i) {
481 const auto [argIdx, arg] = positionalArgsWithIndices[i];
483 Long_t id, flags, modtime;
484
485 auto [argPreParens, argPostParens] = ROOT::SplitAt(arg, '(');
486 TString expandedDir(argPreParens);
487 if (gSystem->ExpandPathName(expandedDir)) {
488 // ROOT-9959: we do not continue if we could not expand the path
489 continue;
490 }
491 TUrl udir(expandedDir, kTRUE);
492 // remove options and anchor to check the path
493 TString sfx = udir.GetFileAndOptions();
494 TString fln = udir.GetFile();
495 sfx.Replace(sfx.Index(fln), fln.Length(), "");
496 // 'path' is the full URL without suffixes (options and/or anchor)
497 TString path = udir.GetFile();
498 if (strcmp(udir.GetProtocol(), "file")) {
499 path = udir.GetUrl();
500 path.Replace(path.Index(sfx), sfx.Length(), "");
501 }
502
503 if (argPostParens.empty() && !gSystem->GetPathInfo(path.Data(), &id, &size, &flags, &modtime)) {
504 if ((flags & 2)) {
505 // if directory set it in fWorkDir
506 if (pwd == "") {
507 pwd = gSystem->WorkingDirectory();
508 fWorkDir = expandedDir;
509 gSystem->ChangeDirectory(expandedDir);
510 } else if (!strcmp(gROOT->GetName(), "Rint")) {
511 Warning("GetOptions", "only one directory argument can be specified (%s)", expandedDir.Data());
512 }
513 } else if (size > 0) {
514 // if file add to list of files to be processed
515 filesToAdd.emplace_back(argIdx, new TObjString(path.Data()));
516 } else {
517 Warning("GetOptions", "file %s has size 0, skipping", expandedDir.Data());
518 }
519 } else {
520 if (TString(udir.GetFile()).EndsWith(".root")) {
521 if (!strcmp(udir.GetProtocol(), "file")) {
522 // file ending on .root but does not exist, likely a typo
523 // warn user if plain root...
524 if (!strcmp(gROOT->GetName(), "Rint"))
525 Warning("GetOptions", "file %s not found", expandedDir.Data());
526 } else {
527 // remote file, give it the benefit of the doubt and add it to list of files
528 filesToAdd.emplace_back(argIdx, new TObjString(arg.c_str()));
529 }
530 } else {
531 TString mode,fargs,io;
532 TString fname = gSystem->SplitAclicMode(expandedDir,mode,fargs,io);
533 char *mac;
534 if ((mac = gSystem->Which(TROOT::GetMacroPath(), fname,
535 kReadPermission))) {
536 // if file add to list of files to be processed
537 filesToAdd.emplace_back(argIdx, new TObjString(arg.c_str()));
538 delete [] mac;
539 } else {
540 // if file add an invalid entry to list of files to be processed
541 filesToAdd.emplace_back(argIdx, new TNamed("NOT FOUND!", arg.c_str()));
542 // only warn if we're plain root,
543 // other progs might have their own params
544 if (!strcmp(gROOT->GetName(), "Rint")) {
545 Error("GetOptions", "macro %s not found", fname.Data());
546 // Return 2 as the Python interpreter does in case the macro
547 // is not found.
548 Terminate(2);
549 }
550 }
551 }
552 }
553 }
554
555 if (!filesToAdd.empty()) {
556 std::sort(filesToAdd.begin(), filesToAdd.end(), [](const auto &a, const auto &b) { return a.first < b.first; });
557 assert(!fFiles);
558 fFiles = new TObjArray;
559 for (const auto &[_idx, file] : filesToAdd) {
560 fFiles->Add(file);
561 }
562 }
563
564 // Process positional arguments after `--` as arguments for the macro.
565 // This is only valid if we passed at least one macro and will be considered arguments for the last one passed.
566 if (lastArgBeforeDashDash != positionalArgsWithIndices.size()) {
567 TObjString* macro = nullptr;
568 bool warnShown = false;
569 if (fFiles) {
570 for (auto f: *fFiles) {
571 TObjString *file = dynamic_cast<TObjString *>(f);
572 if (!file) {
573 if (!dynamic_cast<TNamed*>(f)) {
574 Error("GetOptions()", "Inconsistent file entry (not a TObjString)!");
575 if (f)
576 f->Dump();
577 } // else we did not find the file.
578 continue;
579 }
580
581 if (file->TestBit(kExpression))
582 continue;
583 if (file->String().EndsWith(".root"))
584 continue;
585 if (file->String().Contains('('))
586 continue;
587
588 if (macro && !warnShown) {
589 warnShown = true;
590 Warning("GetOptions", "-- is used with several macros. "
591 "The arguments will be passed to the last one.");
592 }
593
594 macro = file;
595 }
596 }
597
598 if (macro) {
599 TString& str = macro->String();
600 const auto &positionalArgs = opts.GetArgs();
601 str += '(' + ROOT::Join(",", positionalArgs.begin() + lastArgBeforeDashDash, positionalArgs.end()) + ')';
602 } else {
603 Warning("GetOptions", "no macro to pass arguments to was provided. "
604 "Everything after the -- will be ignored.");
605 }
606 }
607
608 // go back to startup directory
609 if (pwd != "")
611
612 // remove handled arguments from argument array
613 int j = 1;
614 for (std::size_t idx : opts.GetUnprocessedArgsIndices()) {
615 argv[j++] = argv[idx + 1];
616 }
617 // Last argv must be null (see https://en.cppreference.com/cpp/language/main_function)
618 argv[j] = nullptr;
619 *argc = j;
620}
621
622////////////////////////////////////////////////////////////////////////////////
623/// Handle idle timeout. When this timer expires the registered idle command
624/// will be executed by this routine and a signal will be emitted.
625
627{
628 if (!fIdleCommand.IsNull())
630
631 Emit("HandleIdleTimer()");
632}
633
634////////////////////////////////////////////////////////////////////////////////
635/// Handle exceptions (kSigBus, kSigSegmentationViolation,
636/// kSigIllegalInstruction and kSigFloatingException) trapped in TSystem.
637/// Specific TApplication implementations may want something different here.
638
640{
641 if (TROOT::Initialized()) {
642 if (gException) {
643 gInterpreter->RewindDictionary();
644 gInterpreter->ClearFileBusy();
645 }
646 if (fExitOnException == kExit)
647 gSystem->Exit(128 + sig);
648 else if (fExitOnException == kAbort)
649 gSystem->Abort();
650 else
651 Throw(sig);
652 }
653 gSystem->Exit(128 + sig);
654}
655
656////////////////////////////////////////////////////////////////////////////////
657/// Set the exit on exception option. Setting this option determines what
658/// happens in HandleException() in case an exception (kSigBus,
659/// kSigSegmentationViolation, kSigIllegalInstruction or kSigFloatingException)
660/// is trapped. Choices are: kDontExit (default), kExit or kAbort.
661/// Returns the previous value.
662
669
670/////////////////////////////////////////////////////////////////////////////////
671/// The function generates and executes a command that loads the Doxygen URL in
672/// a browser. It works for Mac, Windows and Linux. In the case of Linux, the
673/// function also checks if the DISPLAY is set. If it isn't, a warning message
674/// and the URL will be displayed on the terminal. In all OS, if the system command
675/// fails, the URL will be also displayed on the terminal.
676///
677/// \param[in] url web page to be displayed in a browser
678
680{
681 // We check what operating system the user has.
682#ifdef R__MACOSX
683 // Command for opening a browser on Mac.
684 TString cMac("open ");
685 // We generate the full command and execute it.
686 cMac.Append(url);
687 auto res = gSystem->Exec(cMac);
688#elif defined(R__WIN32)
689 // Command for opening a browser on Windows.
690 TString cWindows("start \"\" ");
691 cWindows.Append(url);
692 auto res = gSystem->Exec(cWindows);
693#else
694 // For Linux we check first if the DISPLAY is set.
695 if (!gSystem->Getenv("DISPLAY")) {
696 // The user will have a warning and the URL in the terminal.
697 Warning("OpenInBrowser", "The $DISPLAY is not set! Please manually open (e.g. Ctrl-click) %s\n", url.Data());
698 return;
699 }
700 // Command for opening a browser in Linux. Since the DISPLAY is set, it will open the browser.
701 TString cLinux("xdg-open ");
702 cLinux.Append(url);
703 auto res = gSystem->Exec(cLinux);
704#endif
705 if (res != EXIT_SUCCESS) {
706 Warning("OpenInBrowser", "Could not automatically open web browser (e.g. due to missing X11)! Please manually open (e.g. Ctrl-click) %s\n", url.Data());
707 return;
708 }
709 Info("OpenInBrowser", "A new tab should have opened in your browser.");
710}
711
712namespace {
713enum EUrl { kURLforClass, kURLforNameSpace, kURLforStruct };
714////////////////////////////////////////////////////////////////////////////////
715/// The function generates a URL address for class or namespace (scopeName).
716/// This is the URL to the online reference guide, generated by Doxygen.
717/// With the enumeration "EUrl" we pick which case we need - the one for
718/// class (kURLforClass) or the one for namespace (kURLforNameSpace).
719///
720/// \param[in] scopeName the name of the class or the namespace
721/// \param[in] scopeType the enumerator for class or namespace
722
723static TString UrlGenerator(TString scopeName, EUrl scopeType)
724{
725 // We start the URL with a static part, the same for all scopes and members.
726 TString url = "https://root.cern/doc/";
727 // Then we check the ROOT version used.
728 TPRegexp re4(R"(.*/(v\d)-(\d\d)-00-patches)");
729 const char *branchName = gROOT->GetGitBranch();
730 TObjArray *objarr = re4.MatchS(branchName);
731 TString version;
732 // We extract the correct version name for the URL.
733 if (objarr && objarr->GetEntries() == 3) {
734 // We have a valid version of ROOT and we will extract the correct name for the URL.
735 version = ((TObjString *)objarr->At(1))->GetString() + ((TObjString *)objarr->At(2))->GetString();
736 } else {
737 // If it's not a supported version, we will go to "master" branch.
738 version = "master";
739 }
740 delete objarr;
741 url.Append(version);
742 url.Append("/");
743 // We will replace all "::" with "_1_1" and all "_" with "__" in the
744 // classes definitions, due to Doxygen syntax requirements.
745 scopeName.ReplaceAll("_", "__");
746 scopeName.ReplaceAll("::", "_1_1");
747 // We build the URL for the correct scope type and name.
748 if (scopeType == kURLforClass) {
749 url.Append("class");
750 } else if (scopeType == kURLforStruct) {
751 url.Append("struct");
752 } else {
753 url.Append("namespace");
754 }
755 url.Append(scopeName);
756 url.Append(".html");
757 return url;
758}
759} // namespace
760
761namespace {
762////////////////////////////////////////////////////////////////////////////////
763/// The function returns a TString with the arguments of a method from the
764/// scope (scopeName), but modified with respect to Doxygen syntax - spacing
765/// around special symbols and adding the missing scopes ("std::").
766/// "FormatMethodArgsForDoxygen" works for functions defined inside namespaces
767/// as well. We avoid looking up twice for the TFunction by passing "func".
768///
769/// \param[in] scopeName the name of the class/namespace/struct
770/// \param[in] func pointer to the method
771
772static TString FormatMethodArgsForDoxygen(const TString &scopeName, TFunction *func)
773{
774 // With "GetSignature" we get the arguments of the method and put them in a TString.
775 TString methodArguments = func->GetSignature();
776 // "methodArguments" is modified with respect of Doxygen requirements.
777 methodArguments.ReplaceAll(" = ", "=");
778 methodArguments.ReplaceAll("* ", " *");
779 methodArguments.ReplaceAll("*=", " *=");
780 methodArguments.ReplaceAll("*)", " *)");
781 methodArguments.ReplaceAll("*,", " *,");
782 methodArguments.ReplaceAll("*& ", " *&");
783 methodArguments.ReplaceAll("& ", " &");
784 // TODO: prepend "std::" to all stdlib classes!
785 methodArguments.ReplaceAll("ostream", "std::ostream");
786 methodArguments.ReplaceAll("istream", "std::istream");
787 methodArguments.ReplaceAll("map", "std::map");
788 methodArguments.ReplaceAll("vector", "std::vector");
789 // We need to replace the "currentClass::foo" with "foo" in the arguments.
790 // TODO: protect the global functions.
791 TString scopeNameRE("\\b");
792 scopeNameRE.Append(scopeName);
793 scopeNameRE.Append("::\\b");
794 TPRegexp argFix(scopeNameRE);
795 argFix.Substitute(methodArguments, "");
796 return methodArguments;
797}
798} // namespace
799
800namespace {
801////////////////////////////////////////////////////////////////////////////////
802/// The function returns a TString with the text as an encoded url so that it
803/// can be passed to the function OpenInBrowser
804///
805/// \param[in] text the input text
806/// \return the text appropriately escaped
807
808static TString FormatHttpUrl(TString text)
809{
810 text.ReplaceAll("\n","%0A");
811 text.ReplaceAll("#","%23");
812 text.ReplaceAll(";","%3B");
813 text.ReplaceAll("\"","%22");
814 text.ReplaceAll("`","%60");
815 text.ReplaceAll("+","%2B");
816 text.ReplaceAll("/","%2F");
817 return text;
818}
819} // namespace
820
821namespace {
822////////////////////////////////////////////////////////////////////////////////
823/// The function checks if a member function of a scope is defined as inline.
824/// If so, it also checks if it is virtual. Then the return type of "func" is
825/// modified for the need of Doxygen and with respect to the function
826/// definition. We pass pointer to the method (func) to not re-do the
827/// TFunction lookup.
828///
829/// \param[in] scopeName the name of the class/namespace/struct
830/// \param[in] func pointer to the method
831
832static TString FormatReturnTypeForDoxygen(const TString &scopeName, TFunction *func)
833{
834 // We put the return type of "func" in a TString "returnType".
835 TString returnType = func->GetReturnTypeName();
836 // If the return type is a type nested in the current class, it will appear scoped (Class::Enumeration).
837 // Below we make sure to remove the current class, because the syntax of Doxygen requires it.
838 TString scopeNameRE("\\b");
839 scopeNameRE.Append(scopeName);
840 scopeNameRE.Append("::\\b");
841 TPRegexp returnFix(scopeNameRE);
842 returnFix.Substitute(returnType, "");
843 // We check is if the method is defined as inline.
844 if (func->ExtraProperty() & kIsInlined) {
845 // We check if the function is defined as virtual.
846 if (func->Property() & kIsVirtual) {
847 // If the function is virtual, we append "virtual" before the return type.
848 returnType.Prepend("virtual ");
849 }
850 returnType.ReplaceAll(" *", "*");
851 } else {
852 // If the function is not inline we only change the spacing in "returnType"
853 returnType.ReplaceAll("*", " *");
854 }
855 // In any case (with no respect to virtual/inline check) we need to change
856 // the return type as following.
857 // TODO: prepend "std::" to all stdlib classes!
858 returnType.ReplaceAll("istream", "std::istream");
859 returnType.ReplaceAll("ostream", "std::ostream");
860 returnType.ReplaceAll("map", "std::map");
861 returnType.ReplaceAll("vector", "std::vector");
862 returnType.ReplaceAll("&", " &");
863 return returnType;
864}
865} // namespace
866
867namespace {
868////////////////////////////////////////////////////////////////////////////////
869/// The function generates a URL for "dataMemberName" defined in "scopeName".
870/// It returns a TString with the URL used in the online reference guide,
871/// generated with Doxygen. For data members the URL consist of 2 parts -
872/// URL for "scopeName" and a part for "dataMemberName".
873/// For enumerator, the URL could be separated into 3 parts - URL for
874/// "scopeName", part for the enumeration and a part for the enumerator.
875///
876/// \param[in] scopeName the name of the class/namespace/struct
877/// \param[in] dataMemberName the name of the data member/enumerator
878/// \param[in] dataMember pointer to the data member/enumerator
879/// \param[in] scopeType enumerator to the scope type
880
881static TString
882GetUrlForDataMember(const TString &scopeName, const TString &dataMemberName, TDataMember *dataMember, EUrl scopeType)
883{
884 // We first check if the data member is not enumerator.
885 if (!dataMember->IsEnum()) {
886 // If we work with data members, we have to append a hashed with MD5 text, consisting of:
887 // "Type ClassName::DataMemberNameDataMemberName(arguments)".
888 // We first get the type of the data member.
889 TString md5DataMember(dataMember->GetFullTypeName());
890 md5DataMember.Append(" ");
891 // We append the scopeName and "::".
892 md5DataMember.Append(scopeName);
893 md5DataMember.Append("::");
894 // We append the dataMemberName twice.
895 md5DataMember.Append(dataMemberName);
896 md5DataMember.Append(dataMemberName);
897 // We call UrlGenerator for the scopeName.
898 TString urlForDataMember = UrlGenerator(scopeName, scopeType);
899 // Then we append "#a" and the hashed text.
900 urlForDataMember.Append("#a");
901 urlForDataMember.Append(md5DataMember.MD5());
902 return urlForDataMember;
903 }
904 // If the data member is enumerator, then we first have to check if the enumeration is anonymous.
905 // Doxygen requires different syntax for anonymous enumeration ("scopeName::@1@1").
906 // We create a TString with the name of the scope and the enumeration from which the enumerator is.
907 TString scopeEnumeration = dataMember->GetTrueTypeName();
908 TString md5EnumClass;
909 if (scopeEnumeration.Contains("(unnamed)")) {
910 // FIXME: need to investigate the numbering scheme.
911 md5EnumClass.Append(scopeName);
912 md5EnumClass.Append("::@1@1");
913 } else {
914 // If the enumeration is not anonymous we put "scopeName::Enumeration" in a TString,
915 // which will be hashed with MD5 later.
916 md5EnumClass.Append(scopeEnumeration);
917 // We extract the part after "::" (this is the enumerator name).
918 TString enumOnlyName = TClassEdit::GetUnqualifiedName(scopeEnumeration);
919 // The syntax is "Class::EnumeratorEnumerator
920 md5EnumClass.Append(enumOnlyName);
921 }
922 // The next part of the URL is hashed "@ scopeName::EnumeratorEnumerator".
923 TString md5Enumerator("@ ");
924 md5Enumerator.Append(scopeName);
925 md5Enumerator.Append("::");
926 md5Enumerator.Append(dataMemberName);
927 md5Enumerator.Append(dataMemberName);
928 // We make the URL for the "scopeName".
929 TString url = UrlGenerator(scopeName, scopeType);
930 // Then we have to append the hashed text for the enumerator.
931 url.Append("#a");
932 url.Append(md5EnumClass.MD5());
933 // We append "a" and then the next hashed text.
934 url.Append("a");
935 url.Append(md5Enumerator.MD5());
936 return url;
937}
938} // namespace
939
940namespace {
941////////////////////////////////////////////////////////////////////////////////
942/// The function generates URL for enumeration. The hashed text consist of:
943/// "Class::EnumerationEnumeration".
944///
945/// \param[in] scopeName the name of the class/namespace/struct
946/// \param[in] enumeration the name of the enumeration
947/// \param[in] scopeType enumerator for class/namespace/struct
948
949static TString GetUrlForEnumeration(TString scopeName, const TString &enumeration, EUrl scopeType)
950{
951 // The URL consists of URL for the "scopeName", "#a" and hashed as MD5 text.
952 // The text is "Class::EnumerationEnumeration.
953 TString md5Enumeration(scopeName);
954 md5Enumeration.Append("::");
955 md5Enumeration.Append(enumeration);
956 md5Enumeration.Append(enumeration);
957 // We make the URL for the scope "scopeName".
958 TString url(UrlGenerator(scopeName, scopeType));
959 // Then we have to append "#a" and the hashed text.
960 url.Append("#a");
961 url.Append(md5Enumeration.MD5());
962 return url;
963}
964} // namespace
965
966namespace {
967enum EMethodKind { kURLforMethod, kURLforStructor };
968////////////////////////////////////////////////////////////////////////////////
969/// The function generates URL for any member function (including Constructor/
970/// Destructor) of "scopeName". Doxygen first generates the URL for the scope.
971/// We do that with the help of "UrlGenerator". Then we append "#a" and a
972/// hashed with MD5 text. It consists of:
973/// "ReturnType ScopeName::MethodNameMethodName(Method arguments)".
974/// For constructor/destructor of a class, the return type is not appended.
975///
976/// \param[in] scopeName the name of the class/namespace/struct
977/// \param[in] methodName the name of the method from the scope
978/// \param[in] func pointer to the method
979/// \param[in] methodType enumerator for method or constructor
980/// \param[in] scopeType enumerator for class/namespace/struct
981
982static TString GetUrlForMethod(const TString &scopeName, const TString &methodName, TFunction *func,
983 EMethodKind methodType, EUrl scopeType)
984{
985 TString md5Text;
986 if (methodType == kURLforMethod) {
987 // In the case of method, we append the return type too.
988 // "FormatReturnTypeForDoxygen" modifies the return type with respect to Doxygen's requirement.
989 md5Text.Append((FormatReturnTypeForDoxygen(scopeName, func)));
990 if (scopeType == kURLforNameSpace) {
991 // We need to append "constexpr" if we work with constexpr functions in namespaces.
992 if (func->Property() & kIsConstexpr) {
993 md5Text.Prepend("constexpr ");
994 }
995 }
996 md5Text.Append(" ");
997 }
998 // We append ScopeName::MethodNameMethodName.
999 md5Text.Append(scopeName);
1000 md5Text.Append("::");
1001 md5Text.Append(methodName);
1002 md5Text.Append(methodName);
1003 // We use "FormatMethodArgsForDoxygen" to modify the arguments of Method with respect of Doxygen.
1004 md5Text.Append(FormatMethodArgsForDoxygen(scopeName, func));
1005 // We generate the URL for the class/namespace/struct.
1006 TString url = UrlGenerator(scopeName, scopeType);
1007 url.Append("#a");
1008 // We append the hashed text.
1009 url.Append(md5Text.MD5());
1010 return url;
1011}
1012} // namespace
1013
1014////////////////////////////////////////////////////////////////////////////////
1015/// It gets the ROOT installation setup as TString
1016///
1017/// \return a string with several lines
1018///
1020{
1021 std::vector<TString> lines;
1022 lines.emplace_back("```");
1023 lines.emplace_back(TString::Format("ROOT v%s",
1024 gROOT->GetVersion()));
1025 lines.emplace_back(TString::Format("Built for %s on %s", gSystem->GetBuildArch(), gROOT->GetGitDate()));
1026 if (!strcmp(gROOT->GetGitBranch(), gROOT->GetGitCommit())) {
1027 static const char *months[] = {"January","February","March","April","May",
1028 "June","July","August","September","October",
1029 "November","December"};
1030 Int_t idatqq = gROOT->GetVersionDate();
1031 Int_t iday = idatqq%100;
1032 Int_t imonth = (idatqq/100)%100;
1033 Int_t iyear = (idatqq/10000);
1034
1035 lines.emplace_back(TString::Format("From tag %s, %d %s %4d",
1036 gROOT->GetGitBranch(),
1037 iday,months[imonth-1],iyear));
1038 } else {
1039 // If branch and commit are identical - e.g. "v5-34-18" - then we have
1040 // a release build. Else specify the git hash this build was made from.
1041 lines.emplace_back(TString::Format("From %s@%s",
1042 gROOT->GetGitBranch(),
1043 gROOT->GetGitCommit()));
1044 }
1045 lines.emplace_back(TString::Format("With %s std%ld",
1046 gSystem->GetBuildCompilerVersionStr(), __cplusplus));
1047 lines.emplace_back("Binary directory: "+ gROOT->GetBinDir());
1048 lines.emplace_back("```");
1049 TString setup = "";
1050 for (auto& line : lines) {
1051 setup.Append(line);
1052 setup.Append('\n');
1053 }
1054 setup.Chop(); // trim final `\n`
1055 return setup;
1056}
1057
1058////////////////////////////////////////////////////////////////////////////////
1059/// It opens a Forum topic in a web browser with prefilled ROOT version
1060///
1061/// \param[in] type the issue type (only bug supported right now)
1062
1064{
1065 // https://meta.discourse.org/t/how-to-create-a-post-clicking-a-link/96197
1066
1067 if (type == "bug") {
1068 //OpenInBrowser("\"https://root-forum.cern.ch/new-topic?title=topic%20title&body=topic%20body&category=category/subcategory&tags=email,planned\"");
1069 TString report_template =
1070R"(___
1071_Please read [tips for efficient and successful posting](https://root-forum.cern.ch/t/tips-for-efficient-and-successful-posting/28292) and [posting code](https://root-forum.cern.ch/t/posting-code-read-this-first/28293)_
1072
1073### Describe the bug
1074<!--
1075A clear and concise description of what the wrong behavior is.
1076-->
1077### Expected behavior
1078<!--
1079A clear and concise description of what you expected to happen.
1080-->
1081
1082### To Reproduce
1083<!--
1084Steps to reproduce the behavior:
10851. Your code that triggers the issue: at least a part; ideally something we can run ourselves.
10862. Don't forget to attach the required input files!
10873. How to run your code and / or build it, e.g. `root myMacro.C`, ...
1088-->
1089
1090### Setup
1091)"+GetSetup()+
1092R"(
1093<!--
1094Please specify also how you obtained ROOT, such as `dnf install` / binary download / you built it yourself.
1095-->
1096
1097### Additional context
1098<!--
1099Add any other context about the problem here.
1100-->)";
1101 report_template = FormatHttpUrl(report_template);
1102
1103 OpenInBrowser("\"https://root-forum.cern.ch/new-topic?category=ROOT&tags=bug&body="+report_template+"&\"");
1104 } else {
1105 Warning("OpenForumTopic", "cannot find \"%s\" as type for a Forum topic\n"
1106 "Available types are 'bug'.", type.Data());
1107 }
1108}
1109
1110////////////////////////////////////////////////////////////////////////////////
1111/// It opens a GitHub issue in a web browser with prefilled ROOT version
1112///
1113/// \param[in] type the issue type (bug, feature or improvement)
1114
1116{
1117 // https://docs.github.com/en/issues/tracking-your-work-with-issues/creating-an-issue#creating-an-issue-from-a-url-query
1118
1119 if (type == "bug") {
1121 "\"https://github.com/root-project/root/issues/new?labels=bug&template=bug_report.yml&root-version=" +
1122 FormatHttpUrl(GetSetup()) + "\"");
1123 } else if (type == "improvement") {
1124 OpenInBrowser("\"https://github.com/root-project/root/issues/"
1125 "new?labels=improvement&template=improvement_report.yml&root-version=" +
1126 FormatHttpUrl(GetSetup()) + "\"");
1127 } else if (type == "feature") {
1129 "\"https://github.com/root-project/root/issues/new?labels=new+feature&template=feature_request.yml\"");
1130 } else {
1131 Warning("OpenGitHubIssue",
1132 "Cannot find GitHub issue type \"%s\".\n"
1133 "Available types are 'bug', 'feature' and 'improvement'.",
1134 type.Data());
1135 }
1136}
1137
1138////////////////////////////////////////////////////////////////////////////////
1139/// It opens the online reference guide, generated with Doxygen, for the
1140/// chosen scope (class/namespace/struct) or member (method/function/
1141/// data member/enumeration/enumerator. If the user types incorrect value,
1142/// it will return an error or warning.
1143///
1144/// \param[in] strippedClass the scope or scope::member
1145
1146void TApplication::OpenReferenceGuideFor(const TString &strippedClass)
1147{
1148 // We check if the user is searching for a scope and if the scope exists.
1149 if (TClass *clas = TClass::GetClass(strippedClass)) {
1150 // We check what scope he is searching for (class/namespace/struct).
1151 // Enumerators will switch between the possible cases.
1152 EUrl scopeType;
1153 if (clas->Property() & kIsNamespace) {
1154 scopeType = kURLforNameSpace;
1155 } else if (clas->Property() & kIsStruct) {
1156 scopeType = kURLforStruct;
1157 } else {
1158 scopeType = kURLforClass;
1159 }
1160 // If the user search directly for a scope we open the URL for him with OpenInBrowser.
1161 OpenInBrowser(UrlGenerator(strippedClass, scopeType));
1162 return;
1163 }
1164 // Else we subtract the name of the method and remove it from the command.
1165 TString memberName = TClassEdit::GetUnqualifiedName(strippedClass);
1166 // Error out if "strippedClass" is un-scoped (and it's not a class, see `TClass::GetClass(strippedClass)` above).
1167 // TODO: Global functions.
1168 if (strippedClass == memberName) {
1169 Error("OpenReferenceGuideFor", "Unknown entity \"%s\" - global variables / functions not supported yet!",
1170 strippedClass.Data());
1171 return;
1172 }
1173 // Else we remove the member name to be left with the scope.
1174 TString scopeName = strippedClass(0, strippedClass.Length() - memberName.Length() - 2);
1175 // We check if the scope exists in ROOT.
1176 TClass *cl = TClass::GetClass(scopeName);
1177 if (!cl) {
1178 // That's a member of something ROOT doesn't know.
1179 Warning("OpenReferenceGuideFor", "\"%s\" does not exist in ROOT!", scopeName.Data());
1180 return;
1181 }
1182 // We have enumerators for the three available cases - class, namespace and struct.
1183 EUrl scopeType;
1184 if (cl->Property() & kIsNamespace) {
1185 scopeType = kURLforNameSpace;
1186 } else if (cl->Property() & kIsStruct) {
1187 scopeType = kURLforStruct;
1188 } else {
1189 scopeType = kURLforClass;
1190 }
1191 // If the user wants to search for a method, we take its name (memberName) and
1192 // modify it - we delete everything starting at the first "(" so the user won't have to
1193 // do it by hand when they use Tab.
1194 int bracket = memberName.First("(");
1195 if (bracket > 0) {
1196 memberName.Remove(bracket);
1197 }
1198 // We check if "memberName" is a member function of "cl" or any of its base classes.
1199 if (TFunction *func = cl->GetMethodAllAny(memberName)) {
1200 // If so we find the name of the class that it belongs to.
1201 TString baseClName = ((TMethod *)func)->GetClass()->GetName();
1202 // We define an enumerator to distinguish between structor and method.
1203 EMethodKind methodType;
1204 // We check if "memberName" is a constructor.
1205 if (baseClName == memberName) {
1206 methodType = kURLforStructor;
1207 // We check if "memberName" is a destructor.
1208 } else if (memberName[0] == '~') {
1209 methodType = kURLforStructor;
1210 // We check if "memberName" is a method.
1211 } else {
1212 methodType = kURLforMethod;
1213 }
1214 // We call "GetUrlForMethod" for the correct class and scope.
1215 OpenInBrowser(GetUrlForMethod(baseClName, memberName, func, methodType, scopeType));
1216 return;
1218 // We check if "memberName" is an enumeration.
1219 if (cl->GetListOfEnums()->FindObject(memberName)) {
1220 // If so with OpenInBrowser we open the URL generated with GetUrlForEnumeration
1221 // with respect to the "scopeType".
1222 OpenInBrowser(GetUrlForEnumeration(scopeName, memberName, scopeType));
1223 return;
1224 }
1225
1226 // We check if "memberName" is enumerator defined in one the base classes of "scopeName".
1227 if (auto enumerator = (TDataMember *)cl->GetListOfAllPublicDataMembers()->FindObject(memberName)) {
1228 // We find the actual scope (might be in a base) and open the URL in a browser.
1229 TString baseClName = ((TMethod *)enumerator->GetClass())->GetName();
1230 OpenInBrowser(GetUrlForDataMember(baseClName, memberName, enumerator, scopeType));
1231 return;
1232 }
1233
1234 // Warning message will appear if the user types the function name incorrectly
1235 // or the function is not a member function of "cl" or any of its base classes.
1236 Warning("OpenReferenceGuideFor", "cannot find \"%s\" as member of %s or its base classes! Check %s\n", memberName.Data(),
1237 scopeName.Data(), UrlGenerator(scopeName, scopeType).Data());
1239
1240////////////////////////////////////////////////////////////////////////////////
1241/// The function (".forum <type>") submits a new post on the ROOT forum
1242/// via web browser.
1243/// \note You can use "bug" as <type>.
1244/// \param[in] line command from the command line
1245
1246void TApplication::Forum(const char *line)
1247{
1248 // We first check if the user chose a correct syntax.
1249 TString strippedCommand = TString(line).Strip(TString::kBoth);
1250 if (!strippedCommand.BeginsWith(".forum ")) {
1251 Error("Forum", "Unknown command! Use 'bug' after '.forum '");
1252 return;
1253 }
1254 // We remove the command ".forum" from the TString.
1255 strippedCommand.Remove(0, 7);
1256 // We strip the command line after removing ".help" or ".?".
1257 strippedCommand = strippedCommand.Strip(TString::kBoth);
1258
1259 OpenForumTopic(strippedCommand);
1261
1262////////////////////////////////////////////////////////////////////////////////
1263/// The function (".gh <type>") submits a new issue on GitHub via web browser.
1264/// \note You can use "bug", "feature" or "improvement" as <type>.
1265/// \param[in] line command from the command line
1266
1267void TApplication::GitHub(const char *line)
1268{
1269 // We first check if the user chose a correct syntax.
1270 TString strippedCommand = TString(line).Strip(TString::kBoth);
1271 if (!strippedCommand.BeginsWith(".gh ")) {
1272 Error("GitHub", "Unknown command! Use 'bug', 'feature' or 'improvement' after '.gh '");
1273 return;
1274 }
1275 // We remove the command ".gh" from the TString.
1276 strippedCommand.Remove(0, 4);
1277 // We strip the command line after removing ".help" or ".?".
1278 strippedCommand = strippedCommand.Strip(TString::kBoth);
1279
1280 OpenGitHubIssue(strippedCommand);
1281}
1282
1283////////////////////////////////////////////////////////////////////////////////
1284/// The function lists useful commands (".help") or opens the online reference
1285/// guide, generated with Doxygen (".help scope" or ".help scope::member").
1286/// \note You can use ".?" as the short version of ".help"
1287/// \param[in] line command from the command line
1288
1289void TApplication::Help(const char *line)
1290{
1291 // We first check if the user wants to print the help on the interpreter.
1292 TString strippedCommand = TString(line).Strip(TString::kBoth);
1293 // If the user chooses ".help" or ".?".
1294 if ((strippedCommand == ".help") || (strippedCommand == ".?")) {
1295 gInterpreter->ProcessLine(line);
1296 Printf("\n ROOT special commands.");
1297 Printf(" ==============================================================================");
1298 Printf(" .L <filename>[flags]: load the given file with optional flags like\n"
1299 " + to compile or ++ to force recompile.\n"
1300 " Type .? TSystem::CompileMacro for a list of all flags.\n"
1301 " <filename> can also be a shared library; skip flags.");
1302 Printf(" .(x|X) <filename>[flags](args) :\n"
1303 " same as .L <filename>[flags] and runs then a function\n"
1304 " with signature: ret_type filename(args).");
1305 Printf(" .credits : show credits");
1306 Printf(" .demo : launch GUI demo");
1307 Printf(" .forum bug : ask for help with a bug or crash at the ROOT forum.");
1308 Printf(" .gh [bug|feature|improvement]\n"
1309 " : submit a bug report, feature or improvement suggestion");
1310 Printf(" .help Class::Member : open reference guide for that class member (or .?).\n"
1311 " Specifying '::Member' is optional.");
1312 Printf(" .help edit : show line editing shortcuts (or .?)");
1313 Printf(" .license : show license");
1314 Printf(" .libraries : show loaded libraries");
1315 Printf(" .ls : list contents of current TDirectory");
1316 Printf(" .pwd : show current TDirectory, pad and style");
1317 Printf(" .quit (or .exit) : quit ROOT (long form of .q)");
1318 Printf(" .R [user@]host[:dir] [-l user] [-d dbg] [script] :\n"
1319 " launch process in a remote host");
1320 Printf(" .qqq : quit ROOT - mandatory");
1321 Printf(" .qqqqq : exit process immediately");
1322 Printf(" .qqqqqqq : abort process");
1323 Printf(" .which [file] : show path of macro file");
1324 Printf(" .![OS_command] : execute OS-specific shell command");
1325 Printf(" .!root -? : print ROOT usage (CLI options)");
1326 return;
1327 } else {
1328 // If the user wants to use the extended ".help scopeName" command to access
1329 // the online reference guide, we first check if the command starts correctly.
1330 if ((!strippedCommand.BeginsWith(".help ")) && (!strippedCommand.BeginsWith(".? "))) {
1331 Error("Help", "Unknown command!");
1332 return;
1333 }
1334 // We remove the command ".help" or ".?" from the TString.
1335 if (strippedCommand.BeginsWith(".? ")) {
1336 strippedCommand.Remove(0, 3);
1337 } else {
1338 strippedCommand.Remove(0, 5);
1339 }
1340 // We strip the command line after removing ".help" or ".?".
1341 strippedCommand = strippedCommand.Strip(TString::kBoth);
1342
1343 if (strippedCommand == "edit") {
1344 Printf("\n ROOT terminal keyboard shortcuts (GNU-readline style).");
1345 #ifdef R__MACOSX
1346 #define FOOTNOTE " *"
1347 Printf("* Some of these commands might be intercepted by macOS predefined system shortcuts.");
1348 // https://apple.stackexchange.com/questions/18043/how-can-i-make-ctrlright-left-arrow-stop-changing-desktops-in-lion
1349 #else
1350 #define FOOTNOTE ""
1351 #endif
1352 Printf(" ==============================================================================");
1353 Printf(" Arrow_Left : move cursor left [Ctrl+B]");
1354 Printf(" Arrow_Right : move cursor right [Ctrl+F] [Ctrl+G]");
1355 #ifdef R__MACOSX
1356 Printf(" Fn+Arrow_Left : move cursor to beginning of line [Ctrl+A]");
1357 #else
1358 Printf(" Home : move cursor to beginning of line [Ctrl+A]");
1359 #endif
1360 #ifdef R__MACOSX
1361 Printf(" Fn+Arrow_Right : move cursor to end of line [Ctrl+E]");
1362 #else
1363 Printf(" End : move cursor to end of line [Ctrl+E]");
1364 #endif
1365 Printf(" Ctrl+Arrow_Left : jump to previous word [Esc,B] [Alt,B]" FOOTNOTE);
1366 Printf(" Ctrl+Arrow_Right : jump to next word [Esc,F] [Alt,F]" FOOTNOTE);
1367
1368 Printf(" Backspace : delete previous character [Ctrl+H]");
1369 Printf(" Del : delete next character [Ctrl+D]");
1370 Printf(" Esc,Backspace : delete previous word [Ctrl+W] [Esc,Ctrl+H] [Alt+Backspace] [Esc,Del] [Esc,Ctrl+Del]" FOOTNOTE);// Del is 0x7F on macOS
1371 Printf(" Ctrl+Del : delete next word [Esc,D] [Alt,D]" FOOTNOTE);
1372 Printf(" Ctrl+U : cut all characters between cursor and start of line");
1373 Printf(" Ctrl+K : cut all characters between cursor and end of line");
1374
1375 Printf(" Ctrl+T : transpose characters");
1376 Printf(" Esc,C : character to upper and jump to next word");
1377 Printf(" Esc,L : word to lower case and jump to its end");
1378 Printf(" Esc,U : word to upper case and jump to its end");
1379 Printf(" Ctrl+Shift+C : copy clipboard content");
1380 Printf(" Ctrl+Shift+V : paste clipboard content [Ctrl+Y] [Alt+Y]");
1381 #ifdef R__MACOSX
1382 Printf(" Fn+Enter : toggle overwrite mode");
1383 #else
1384 Printf(" Ins : toggle overwrite mode");
1385 #endif
1387 Printf(" Ctrl+_ : undo last keypress action");
1388 Printf(" Tab : autocomplete command or print suggestions [Ctrl+I] [Esc,Tab]");
1389 Printf(" Enter : execute command [Ctrl+J] [Ctrl+M]");
1390 Printf(" Ctrl+L : clear prompt screen");
1391 Printf(" Ctrl+D : quit ROOT (if empty line)");
1392 Printf(" Ctrl+C : send kSigInt interrupt signal");
1393 Printf(" Ctrl+Z : send kSigStop pause job signal");
1394 Printf(" Ctrl+\\ : send kSigQuit quit job signal");
1395
1396 Printf(" Arrow_Down : navigate downwards in command history [Ctrl+N]");
1397 Printf(" Arrow_Up : navigate upwards in command history [Ctrl+P]");
1398 Printf(" Ctrl+R ; Ctrl+S : search command in your history by typing a string.\n"
1399 " Use Backspace if you mistyped (but not arrows).\n"
1400 " Press Ctrl+R (Ctrl+S) repeateadly to navigate matches in reverse (forward) order");
1401 Printf(" Arrow_Right : after Ctrl+R (Ctrl+S), select current match of the history search\n"
1402 " [Ctrl+O] [Enter] [Ctrl+J] [Ctrl+M] [Arrow_Left] [Esc,Esc].\n"
1403 " Use Ctrl+F or Ctrl+G to cancel search and revert original line");
1404
1405 return;
1406 }
1407 // We call the function what handles the extended ".help scopeName" command.
1408 OpenReferenceGuideFor(strippedCommand);
1409 }
1410}
1411
1412/// Load shared libs necessary for graphics. These libraries are only
1413/// loaded when gROOT->IsBatch() is kFALSE.
1414
1416{
1417 if (gROOT->IsBatch())
1418 return;
1419
1420 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualPad"))
1421 if (h->LoadPlugin() == -1)
1422 return;
1423
1424 TString guiFactory = gEnv->GetValue("Gui.Factory", "native");
1425 guiFactory.ToLower();
1426 if (guiFactory == "native")
1427 guiFactory = "root";
1428
1429 if (auto h = gROOT->GetPluginManager()->FindHandler("TGuiFactory", guiFactory)) {
1430 if (h->LoadPlugin() == -1) {
1431 gROOT->SetBatch(kTRUE);
1432 return;
1433 }
1434 gGuiFactory = (TGuiFactory *) h->ExecPlugin(0);
1435
1437 return;
1438 }
1439
1440
1441 TString name;
1442 TString title1 = "ROOT interface to ";
1443 TString nativex, title;
1444
1445#ifdef R__WIN32
1446 nativex = "win32gdk";
1447 name = "Win32gdk";
1448 title = title1 + "Win32gdk";
1449#elif defined(R__HAS_COCOA)
1450 nativex = "quartz";
1451 name = "quartz";
1452 title = title1 + "Quartz";
1453#else
1454 nativex = "x11";
1455 name = "X11";
1456 title = title1 + "X11";
1457#endif
1458
1459 TString guiBackend = gEnv->GetValue("Gui.Backend", "native");
1460 guiBackend.ToLower();
1461 if (guiBackend == "native") {
1462 guiBackend = nativex;
1463 } else {
1464 name = guiBackend;
1465 title = title1 + guiBackend;
1466 }
1467
1468 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualX", guiBackend)) {
1469 if (h->LoadPlugin() == -1) {
1470 gROOT->SetBatch(kTRUE);
1471 return;
1472 }
1473 gVirtualX = (TVirtualX *) h->ExecPlugin(2, name.Data(), title.Data());
1475 }
1477
1478////////////////////////////////////////////////////////////////////////////////
1479/// Switch to batch mode.
1480
1482{
1483 gROOT->SetBatch();
1486#ifndef R__WIN32
1487 if (gVirtualX != gGXBatch) delete gVirtualX;
1488#endif
1490}
1491
1492////////////////////////////////////////////////////////////////////////////////
1493/// Parse the content of a line starting with ".R" (already stripped-off)
1494/// The format is
1495/// ~~~ {.cpp}
1496/// [user@]host[:dir] [-l user] [-d dbg] [script]
1497/// ~~~
1498/// The variable 'dir' is the remote directory to be used as working dir.
1499/// The username can be specified in two ways, "-l" having the priority
1500/// (as in ssh).
1501/// A 'dbg' value > 0 gives increasing verbosity.
1502/// The last argument 'script' allows to specify an alternative script to
1503/// be executed remotely to startup the session.
1504
1506 TString &hostdir, TString &user,
1507 Int_t &dbg, TString &script)
1508{
1509 if (!ln || strlen(ln) <= 0)
1510 return 0;
1511
1512 Int_t rc = 0;
1513 Bool_t isHostDir = kTRUE;
1514 Bool_t isScript = kFALSE;
1515 Bool_t isUser = kFALSE;
1516 Bool_t isDbg = kFALSE;
1517
1518 TString line(ln);
1519 TString tkn;
1520 Int_t from = 0;
1521 while (line.Tokenize(tkn, from, " ")) {
1522 if (tkn == "-l") {
1523 // Next is a user name
1524 isUser = kTRUE;
1525 } else if (tkn == "-d") {
1526 isDbg = kTRUE;
1527 } else if (tkn == "-close") {
1528 rc = 1;
1529 } else if (tkn.BeginsWith("-")) {
1530 ::Warning("TApplication::ParseRemoteLine","unknown option: %s", tkn.Data());
1531 } else {
1532 if (isUser) {
1533 user = tkn;
1534 isUser = kFALSE;
1535 } else if (isDbg) {
1536 dbg = tkn.Atoi();
1537 isDbg = kFALSE;
1538 } else if (isHostDir) {
1539 hostdir = tkn;
1540 hostdir.ReplaceAll(":","/");
1541 isHostDir = kFALSE;
1542 isScript = kTRUE;
1543 } else if (isScript) {
1544 // Add everything left
1545 script = tkn;
1546 script.Insert(0, "\"");
1547 script += "\"";
1548 // isScript = kFALSE; // [clang-tidy] never read
1549 break;
1550 }
1551 }
1552 }
1553
1554 // Done
1555 return rc;
1556}
1557
1558////////////////////////////////////////////////////////////////////////////////
1559/// Process the content of a line starting with ".R" (already stripped-off)
1560/// The format is
1561/// ~~~ {.cpp}
1562/// [user@]host[:dir] [-l user] [-d dbg] [script] | [host] -close
1563/// ~~~
1564/// The variable 'dir' is the remote directory to be used as working dir.
1565/// The username can be specified in two ways, "-l" having the priority
1566/// (as in ssh).
1567/// A 'dbg' value > 0 gives increasing verbosity.
1568/// The last argument 'script' allows to specify an alternative script to
1569/// be executed remotely to startup the session.
1570
1572{
1573 if (!line) return 0;
1574
1575 if (!strncmp(line, "-?", 2) || !strncmp(line, "-h", 2) ||
1576 !strncmp(line, "--help", 6)) {
1577 Info("ProcessRemote", "remote session help:");
1578 Printf(".R [user@]host[:dir] [-l user] [-d dbg] [[<]script] | [host] -close");
1579 Printf("Create a ROOT session on the specified remote host.");
1580 Printf("The variable \"dir\" is the remote directory to be used as working dir.");
1581 Printf("The username can be specified in two ways, \"-l\" having the priority");
1582 Printf("(as in ssh). A \"dbg\" value > 0 gives increasing verbosity.");
1583 Printf("The last argument \"script\" allows to specify an alternative script to");
1584 Printf("be executed remotely to startup the session, \"roots\" being");
1585 Printf("the default. If the script is preceded by a \"<\" the script will be");
1586 Printf("sourced, after which \"roots\" is executed. The sourced script can be ");
1587 Printf("used to change the PATH and other variables, allowing an alternative");
1588 Printf("\"roots\" script to be found.");
1589 Printf("To close down a session do \".R host -close\".");
1590 Printf("To switch between sessions do \".R host\", to switch to the local");
1591 Printf("session do \".R\".");
1592 Printf("To list all open sessions do \"gApplication->GetApplications()->Print()\".");
1593 return 0;
1594 }
1595
1596 TString hostdir, user, script;
1597 Int_t dbg = 0;
1598 Int_t rc = ParseRemoteLine(line, hostdir, user, dbg, script);
1599 if (hostdir.Length() <= 0) {
1600 // Close the remote application if required
1601 if (rc == 1) {
1603 delete fAppRemote;
1604 }
1605 // Return to local run
1606 fAppRemote = nullptr;
1607 // Done
1608 return 1;
1609 } else if (rc == 1) {
1610 // close an existing remote application
1611 TApplication *ap = TApplication::Open(hostdir, 0, nullptr);
1612 if (ap) {
1614 delete ap;
1615 }
1616 }
1617 // Attach or start a remote application
1618 if (user.Length() > 0)
1619 hostdir.Insert(0, TString::Format("%s@", user.Data()));
1620 const char *sc = (script.Length() > 0) ? script.Data() : nullptr;
1621 TApplication *ap = TApplication::Open(hostdir, dbg, sc);
1622 if (ap) {
1623 fAppRemote = ap;
1624 }
1625
1626 // Done
1627 return 1;
1628}
1629
1630namespace {
1631 static int PrintFile(const char* filename) {
1632 TString sFileName(filename);
1633 gSystem->ExpandPathName(sFileName);
1634 if (gSystem->AccessPathName(sFileName)) {
1635 Error("ProcessLine()", "Cannot find file %s", filename);
1636 return 1;
1637 }
1638 std::ifstream instr(sFileName);
1639 TString content;
1640 content.ReadFile(instr);
1641 Printf("%s", content.Data());
1642 return 0;
1643 }
1644 } // namespace
1645
1646////////////////////////////////////////////////////////////////////////////////
1647/// Process a single command line, either a C++ statement or an interpreter
1648/// command starting with a ".".
1649/// Return the return value of the command cast to a long.
1650
1651Longptr_t TApplication::ProcessLine(const char *line, Bool_t sync, Int_t *err)
1652{
1653 if (!line || !*line) return 0;
1654
1655 // If we are asked to go remote do it
1656 if (!strncmp(line, ".R", 2)) {
1657 Int_t n = 2;
1658 while (*(line+n) == ' ')
1659 n++;
1660 return ProcessRemote(line+n, err);
1661 }
1662
1663 // Redirect, if requested
1666 return fAppRemote->ProcessLine(line, err);
1667 }
1668
1669 if (!strncasecmp(line, ".qqqqqqq", 7)) {
1670 gSystem->Abort();
1671 } else if (!strncasecmp(line, ".qqqqq", 5)) {
1672 Info("ProcessLine", "Bye... (try '.qqqqqqq' if still running)");
1673 gSystem->Exit(1);
1674 } else if (!strncasecmp(line, ".exit", 4) || !strncasecmp(line, ".quit", 2)) {
1675 Terminate(0);
1676 return 0;
1677 }
1678
1679 if (!strncmp(line, ".gh", 3)) {
1680 GitHub(line);
1681 return 1;
1682 }
1683
1684 if (!strncmp(line, ".forum", 6)) {
1685 Forum(line);
1686 return 1;
1687 }
1688
1689 if (!strncmp(line, ".?", 2) || !strncmp(line, ".help", 5)) {
1690 Help(line);
1691 return 1;
1692 }
1693
1694 if (!strncmp(line, ".demo", 5)) {
1695 if (gROOT->IsBatch()) {
1696 Error("ProcessLine", "Cannot show demos in batch mode!");
1697 return 1;
1698 }
1699 ProcessLine(".x " + TROOT::GetTutorialDir() + "/demos.C");
1700 return 0;
1701 }
1702
1703 if (!strncmp(line, ".license", 8)) {
1704 return PrintFile(TROOT::GetDocDir() + "/LICENSE");
1705 }
1706
1707 if (!strncmp(line, ".credits", 8)) {
1708 TString credits = TROOT::GetDocDir() + "/CREDITS";
1709 if (gSystem->AccessPathName(credits, kReadPermission))
1710 credits = TROOT::GetDocDir() + "/README/CREDITS";
1711 return PrintFile(credits);
1712 }
1713
1714 if (!strncmp(line, ".pwd", 4)) {
1715 if (gDirectory)
1716 Printf("Current directory: %s", gDirectory->GetPath());
1717 if (gPad)
1718 Printf("Current pad: %s", gPad->GetName());
1719 if (gStyle)
1720 Printf("Current style: %s", gStyle->GetName());
1721 return 1;
1722 }
1723
1724 if (!strncmp(line, ".ls", 3)) {
1725 const char *opt = nullptr;
1726 if (line[3]) opt = &line[3];
1727 if (gDirectory) gDirectory->ls(opt);
1728 return 1;
1729 }
1730
1731 if (!strncmp(line, ".which", 6)) {
1732 char *fn = Strip(line+7);
1733 char *s = strtok(fn, "+("); // this method does not need to be reentrant
1735 if (!mac)
1736 Printf("No macro %s in path %s", s, TROOT::GetMacroPath());
1737 else
1738 Printf("%s", mac);
1739 delete [] fn;
1740 delete [] mac;
1741 return mac ? 1 : 0;
1742 }
1743
1744 if (!strncmp(line, ".L", 2) || !strncmp(line, ".U", 2)) {
1745 TString aclicMode, arguments, io;
1746 TString fname = gSystem->SplitAclicMode(line+3, aclicMode, arguments, io);
1747
1748 char *mac = gSystem->Which(TROOT::GetMacroPath(), fname, kReadPermission);
1749 if (arguments.Length())
1750 Warning("ProcessLine", "argument(s) \"%s\" ignored with .%c", arguments.Data(), line[1]);
1751 Longptr_t retval = 0;
1752 if (!mac) {
1753 Error("ProcessLine", "macro %s not found in path %s", fname.Data(), TROOT::GetMacroPath());
1754 } else {
1755 TString cmd(line + 1);
1756 Ssiz_t posSpace = cmd.Index(' ');
1757 if (posSpace == kNPOS)
1758 cmd.Remove(1);
1759 else
1760 cmd.Remove(posSpace);
1761 auto tempbuf = TString::Format(".%s %s%s%s", cmd.Data(), mac, aclicMode.Data(), io.Data());
1762 delete[] mac;
1763 if (sync)
1764 retval = gInterpreter->ProcessLineSynch(tempbuf.Data(), (TInterpreter::EErrorCode *)err);
1765 else
1766 retval = gInterpreter->ProcessLine(tempbuf.Data(), (TInterpreter::EErrorCode *)err);
1767 }
1768
1769 InitializeGraphics(gROOT->IsWebDisplay());
1770
1771 return retval;
1772 }
1773
1774 if (!strncmp(line, ".X", 2) || !strncmp(line, ".x", 2)) {
1775 return ProcessFile(line+3, err, line[2] == 'k');
1776 }
1778 if (!strcmp(line, ".reset")) {
1779 // Do nothing, .reset disabled in Cling because too many side effects
1780 Printf("*** .reset not allowed, please use gROOT->Reset() ***");
1781 return 0;
1782
1783#if 0
1784 // delete the ROOT dictionary since CINT will destroy all objects
1785 // referenced by the dictionary classes (TClass et. al.)
1786 gROOT->GetListOfClasses()->Delete();
1787 // fall through
1788#endif
1789 }
1790
1791 if (!strcmp(line, ".libraries")) {
1792 // List the loaded libraries
1794 return 0;
1795 }
1796
1797 if (sync)
1798 return gInterpreter->ProcessLineSynch(line, (TInterpreter::EErrorCode*)err);
1799 else
1800 return gInterpreter->ProcessLine(line, (TInterpreter::EErrorCode*)err);
1801}
1802
1803////////////////////////////////////////////////////////////////////////////////
1804/// Process a file containing a C++ macro.
1805
1806Longptr_t TApplication::ProcessFile(const char *file, Int_t *error, Bool_t keep)
1807{
1808 return ExecuteFile(file, error, keep);
1809}
1810
1811////////////////////////////////////////////////////////////////////////////////
1812/// Execute a file containing a C++ macro (static method). Can be used
1813/// while TApplication is not yet created.
1814
1815Longptr_t TApplication::ExecuteFile(const char *file, Int_t *error, Bool_t keep)
1816{
1817 static const Int_t kBufSize = 1024;
1818
1819 if (!file || !*file) return 0;
1820
1821 TString aclicMode;
1822 TString arguments;
1823 TString io;
1824 TString fname = gSystem->SplitAclicMode(file, aclicMode, arguments, io);
1825
1826 char *exnam = gSystem->Which(TROOT::GetMacroPath(), fname, kReadPermission);
1827 if (!exnam) {
1828 ::Error("TApplication::ExecuteFile", "macro %s not found in path %s", fname.Data(),
1830 delete [] exnam;
1831 if (error)
1833 return 0;
1834 }
1835
1836 ::std::ifstream macro(exnam, std::ios::in);
1837 if (!macro.good()) {
1838 ::Error("TApplication::ExecuteFile", "%s no such file", exnam);
1839 if (error)
1841 delete [] exnam;
1842 return 0;
1843 }
1844
1845 char currentline[kBufSize];
1846 char dummyline[kBufSize];
1847 int tempfile = 0;
1848 int comment = 0;
1849 int ifndefc = 0;
1850 int ifdef = 0;
1851 char *s = nullptr;
1852 Bool_t execute = kFALSE;
1853 Longptr_t retval = 0;
1854
1855 while (1) {
1856 bool res = (bool)macro.getline(currentline, kBufSize);
1857 if (macro.eof()) break;
1858 if (!res) {
1859 // Probably only read kBufSize, let's ignore the remainder of
1860 // the line.
1861 macro.clear();
1862 while (!macro.getline(dummyline, kBufSize) && !macro.eof()) {
1863 macro.clear();
1864 }
1865 }
1866 s = currentline;
1867 while (s && (*s == ' ' || *s == '\t')) s++; // strip-off leading blanks
1868
1869 // very simple minded pre-processor parsing, only works in case macro file
1870 // starts with "#ifndef __CLING__" (__CINT__ for backward compatibility).
1871 // In that case everything till next "#else" or "#endif" will be skipped.
1872 if (*s == '#') {
1873 char *cs = Compress(currentline);
1874 if (strstr(cs, "#ifndef__CLING__") || strstr(cs, "#ifndef__CINT__") ||
1875 strstr(cs, "#if!defined(__CLING__)") || strstr(cs, "#if!defined(__CINT__)"))
1876 ifndefc = 1;
1877 else if (ifndefc && (strstr(cs, "#ifdef") || strstr(cs, "#ifndef") ||
1878 strstr(cs, "#ifdefined") || strstr(cs, "#if!defined")))
1879 ifdef++;
1880 else if (ifndefc && strstr(cs, "#endif")) {
1881 if (ifdef)
1882 ifdef--;
1883 else
1884 ifndefc = 0;
1885 } else if (ifndefc && !ifdef && strstr(cs, "#else"))
1886 ifndefc = 0;
1887 delete [] cs;
1888 }
1889 if (!*s || *s == '#' || ifndefc || !strncmp(s, "//", 2)) continue;
1890
1891 if (!comment && (!strncmp(s, ".X", 2) || !strncmp(s, ".x", 2))) {
1892 retval = ExecuteFile(s+3);
1893 execute = kTRUE;
1894 continue;
1895 }
1896
1897 if (!strncmp(s, "/*", 2)) comment = 1;
1898 if (comment) {
1899 // handle slightly more complex cases like: /* */ /*
1900again:
1901 s = strstr(s, "*/");
1902 if (s) {
1903 comment = 0;
1904 s += 2;
1905
1906 while (s && (*s == ' ' || *s == '\t')) s++; // strip-off leading blanks
1907 if (!*s) continue;
1908 if (!strncmp(s, "//", 2)) continue;
1909 if (!strncmp(s, "/*", 2)) {
1910 comment = 1;
1911 goto again;
1912 }
1913 }
1914 }
1915 if (!comment && *s == '{') tempfile = 1;
1916 if (!comment) break;
1918 macro.close();
1919
1920 if (!execute) {
1921 TString exname = exnam;
1922 if (!tempfile) {
1923 // We have a script that does NOT contain an unnamed macro,
1924 // so we can call the script compiler on it.
1925 exname += aclicMode;
1926 }
1927 exname += arguments;
1928 exname += io;
1929
1930 TString tempbuf;
1931 if (tempfile) {
1932 tempbuf.Form(".x %s", exname.Data());
1933 } else {
1934 tempbuf.Form(".X%s %s", keep ? "k" : " ", exname.Data());
1935 }
1936 retval = gInterpreter->ProcessLineSynch(tempbuf,(TInterpreter::EErrorCode*)error);
1937 }
1938
1939 delete [] exnam;
1940 return retval;
1941}
1943////////////////////////////////////////////////////////////////////////////////
1944/// Main application eventloop. Calls system dependent eventloop via gSystem.
1945
1946void TApplication::Run(Bool_t retrn)
1947{
1948 SetReturnFromRun(retrn);
1949
1950 fIsRunning = kTRUE;
1951
1952 gSystem->Run();
1954}
1955
1956////////////////////////////////////////////////////////////////////////////////
1957/// Set the command to be executed after the system has been idle for
1958/// idleTimeInSec seconds. Normally called via TROOT::Idle(...).
1959
1960void TApplication::SetIdleTimer(UInt_t idleTimeInSec, const char *command)
1961{
1963 fIdleCommand = command;
1964 fIdleTimer = new TIdleTimer(idleTimeInSec*1000);
1966}
1967
1968////////////////////////////////////////////////////////////////////////////////
1969/// Remove idle timer. Normally called via TROOT::Idle(0).
1970
1972{
1973 if (fIdleTimer) {
1974 // timers are removed from the gSystem timer list by their dtor
1976 }
1977}
1978
1979////////////////////////////////////////////////////////////////////////////////
1980/// Called when system starts idleing.
1981
1983{
1985 fIdleTimer->Reset();
1987 }
1988}
1989
1990////////////////////////////////////////////////////////////////////////////////
1991/// Called when system stops idleing.
1992
1994{
1995 if (fIdleTimer)
1997}
1999////////////////////////////////////////////////////////////////////////////////
2000/// What to do when tab is pressed. Re-implemented by TRint.
2001/// See TTabCom::Hook() for meaning of return values.
2002
2003Int_t TApplication::TabCompletionHook(char* /*buf*/, int* /*pLoc*/, std::ostream& /*out*/)
2004{
2005 return -1;
2007
2008
2009////////////////////////////////////////////////////////////////////////////////
2010/// Terminate the application by call TSystem::Exit() unless application has
2011/// been told to return from Run(), by a call to SetReturnFromRun().
2012
2013void TApplication::Terminate(Int_t status)
2015 Emit("Terminate(Int_t)", status);
2016
2017 if (fReturnFromRun)
2018 gSystem->ExitLoop();
2019 else {
2020 gSystem->Exit(status);
2021 }
2022}
2023
2024////////////////////////////////////////////////////////////////////////////////
2025/// Emit signal when a line has been processed.
2026
2027void TApplication::LineProcessed(const char *line)
2028{
2029 Emit("LineProcessed(const char*)", line);
2030}
2031
2032////////////////////////////////////////////////////////////////////////////////
2033/// Emit signal when console keyboard key was pressed.
2034
2036{
2037 Emit("KeyPressed(Int_t)", key);
2038}
2039
2040////////////////////////////////////////////////////////////////////////////////
2041/// Emit signal when return key was pressed.
2042
2044{
2045 Emit("ReturnPressed(char*)", text);
2046}
2047
2048////////////////////////////////////////////////////////////////////////////////
2049/// Set console echo mode:
2050///
2051/// - mode = kTRUE - echo input symbols
2052/// - mode = kFALSE - noecho input symbols
2053
2055{
2057
2058////////////////////////////////////////////////////////////////////////////////
2059/// Static function used to create a default application environment.
2060
2062{
2064 // gApplication is set at the end of 'new TApplication.
2065 if (!gApplication) {
2066 char *a = StrDup("RootApp");
2067 char *b = StrDup("-b");
2068 char *argv[2];
2069 Int_t argc = 2;
2070 argv[0] = a;
2071 argv[1] = b;
2072 new TApplication("RootApp", &argc, argv, nullptr, 0);
2073 if (gDebug > 0)
2074 Printf("<TApplication::CreateApplication>: "
2075 "created default TApplication");
2076 delete [] a; delete [] b;
2078 }
2079}
2080
2081////////////////////////////////////////////////////////////////////////////////
2082/// Static function used to attach to an existing remote application
2083/// or to start one.
2084
2085TApplication *TApplication::Open(const char *url,
2086 Int_t debug, const char *script)
2087{
2088 TApplication *ap = nullptr;
2089 TUrl nu(url);
2090 Int_t nnew = 0;
2091
2092 // Look among the existing ones
2093 if (fgApplications) {
2094 TIter nxa(fgApplications);
2095 while ((ap = (TApplication *) nxa())) {
2096 TString apn(ap->ApplicationName());
2097 if (apn == url) {
2098 // Found matching application
2099 return ap;
2100 } else {
2101 // Check if same machine and user
2102 TUrl au(apn);
2103 if (strlen(au.GetUser()) > 0 && strlen(nu.GetUser()) > 0 &&
2104 !strcmp(au.GetUser(), nu.GetUser())) {
2105 if (!strncmp(au.GetHost(), nu.GetHost(), strlen(nu.GetHost())))
2106 // New session on a known machine
2107 nnew++;
2108 }
2109 }
2110 }
2111 } else {
2112 ::Error("TApplication::Open", "list of applications undefined - protocol error");
2113 return ap;
2114 }
2115
2116 // If new session on a known machine pass the number as option
2117 if (nnew > 0) {
2118 nnew++;
2119 nu.SetOptions(TString::Format("%d", nnew).Data());
2120 }
2121
2122 // Instantiate the TApplication object to be run
2123 TPluginHandler *h = nullptr;
2124 if ((h = gROOT->GetPluginManager()->FindHandler("TApplication","remote"))) {
2125 if (h->LoadPlugin() == 0) {
2126 ap = (TApplication *) h->ExecPlugin(3, nu.GetUrl(), debug, script);
2127 } else {
2128 ::Error("TApplication::Open", "failed to load plugin for TApplicationRemote");
2129 }
2130 } else {
2131 ::Error("TApplication::Open", "failed to find plugin for TApplicationRemote");
2132 }
2133
2134 // Add to the list
2135 if (ap && !(ap->TestBit(kInvalidObject))) {
2136 fgApplications->Add(ap);
2137 gROOT->GetListOfBrowsables()->Add(ap, ap->ApplicationName());
2138 TIter next(gROOT->GetListOfBrowsers());
2139 TBrowser *b;
2140 while ((b = (TBrowser*) next()))
2141 b->Add(ap, ap->ApplicationName());
2142 gROOT->RefreshBrowsers();
2143 } else {
2145 ::Error("TApplication::Open",
2146 "TApplicationRemote for %s could not be instantiated", url);
2147 }
2148
2149 // Done
2150 return ap;
2151}
2152
2153////////////////////////////////////////////////////////////////////////////////
2154/// Static function used to close a remote application
2155
2157{
2158 if (app) {
2159 app->Terminate(0);
2161 gROOT->GetListOfBrowsables()->RecursiveRemove(app);
2162 TIter next(gROOT->GetListOfBrowsers());
2163 TBrowser *b;
2164 while ((b = (TBrowser*) next()))
2165 b->RecursiveRemove(app);
2166 gROOT->RefreshBrowsers();
2167 }
2168}
2169
2170////////////////////////////////////////////////////////////////////////////////
2171/// Show available sessions
2172
2173void TApplication::ls(Option_t *opt) const
2174{
2175 if (fgApplications) {
2176 TIter nxa(fgApplications);
2177 TApplication *a = nullptr;
2178 while ((a = (TApplication *) nxa())) {
2179 a->Print(opt);
2180 }
2181 } else {
2182 Print(opt);
2183 }
2184}
2185
2186////////////////////////////////////////////////////////////////////////////////
2187/// Static method returning the list of available applications
2188
2190{
2191 return fgApplications;
2192}
#define SafeDelete(p)
Definition RConfig.hxx:507
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
bool Bool_t
Boolean (0=false, 1=true) (bool)
Definition RtypesCore.h:78
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
long Longptr_t
Integer large enough to hold a pointer (platform-dependent)
Definition RtypesCore.h:90
int Ssiz_t
String size (currently int)
Definition RtypesCore.h:82
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
Definition RtypesCore.h:69
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:61
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
constexpr Ssiz_t kNPOS
The equivalent of std::string::npos for the ROOT class TString.
Definition RtypesCore.h:132
long long Long64_t
Portable signed long integer 8 bytes.
Definition RtypesCore.h:84
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
const char Option_t
Option string (const char)
Definition RtypesCore.h:81
static constexpr const char * kCommandLineOptionsHelp
static void CallEndOfProcessCleanups()
#define FOOTNOTE
TApplication * gApplication
R__EXTERN TApplication * gApplication
R__EXTERN TClassTable * gClassTable
@ kIsInlined
@ kIsConstexpr
Definition TDictionary.h:93
@ kIsStruct
Definition TDictionary.h:66
@ kIsVirtual
Definition TDictionary.h:72
@ kIsNamespace
Definition TDictionary.h:95
#define gDirectory
Definition TDirectory.h:385
R__EXTERN TEnv * gEnv
Definition TEnv.h:126
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
R__EXTERN ExceptionContext_t * gException
Definition TException.h:69
R__EXTERN void Throw(int code)
If an exception context has been set (using the TRY and RETRY macros) jump back to where it was set.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
Option_t Option_t TPoint TPoint const char text
char name[80]
Definition TGX11.cxx:142
R__EXTERN TGuiFactory * gBatchGuiFactory
Definition TGuiFactory.h:69
R__EXTERN TGuiFactory * gGuiFactory
Definition TGuiFactory.h:68
R__EXTERN TVirtualMutex * gInterpreterMutex
#define gInterpreter
@ kInvalidObject
Definition TObject.h:382
Int_t gDebug
Global variable setting the debug level. Set to 0 to disable, increase it in steps of 1 to increase t...
Definition TROOT.cxx:792
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:417
char * Compress(const char *str)
Remove all blanks from the string str.
Definition TString.cxx:2654
char * Strip(const char *str, char c=' ')
Strip leading and trailing c (blanks by default) from a string.
Definition TString.cxx:2603
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2585
char * StrDup(const char *str)
Duplicate the string str.
Definition TString.cxx:2639
R__EXTERN TStyle * gStyle
Definition TStyle.h:442
@ kReadPermission
Definition TSystem.h:55
R__EXTERN TSystem * gSystem
Definition TSystem.h:582
#define R__LOCKGUARD(mutex)
#define gPad
#define gVirtualX
Definition TVirtualX.h:379
R__EXTERN TVirtualX * gGXBatch
Definition TVirtualX.h:381
This class creates the ROOT Application Environment that interfaces to the windowing system eventloop...
EExitOnException ExitOnException(EExitOnException opt=kExit)
Set the exit on exception option.
virtual void KeyPressed(Int_t key)
Emit signal when console keyboard key was pressed.
virtual Longptr_t ProcessLine(const char *line, Bool_t sync=kFALSE, Int_t *error=nullptr)
Process a single command line, either a C++ statement or an interpreter command starting with a "....
static TList * fgApplications
static void Close(TApplication *app)
Static function used to close a remote application.
virtual void SetEchoMode(Bool_t mode)
Set console echo mode:
virtual void Help(const char *line)
The function lists useful commands (".help") or opens the online reference guide, generated with Doxy...
virtual void LineProcessed(const char *line)
Emit signal when a line has been processed.
void ClearInputFiles()
Clear list containing macro files passed as program arguments.
TApplicationImp * fAppImp
!Window system specific application implementation
static Longptr_t ExecuteFile(const char *file, Int_t *error=nullptr, Bool_t keep=kFALSE)
Execute a file containing a C++ macro (static method).
void InitializeGraphics(Bool_t only_web=kFALSE)
Initialize the graphics environment.
virtual void Open()
virtual void LoadGraphicsLibs()
Load shared libs necessary for graphics.
virtual void StopIdleing()
Called when system stops idleing.
virtual void StartIdleing()
Called when system starts idleing.
virtual void Run(Bool_t retrn=kFALSE)
Main application eventloop. Calls system dependent eventloop via gSystem.
virtual ~TApplication()
TApplication dtor.
void OpenReferenceGuideFor(const TString &strippedClass)
It opens the online reference guide, generated with Doxygen, for the chosen scope (class/namespace/st...
virtual void HandleException(Int_t sig)
Handle exceptions (kSigBus, kSigSegmentationViolation, kSigIllegalInstruction and kSigFloatingExcepti...
virtual void MakeBatch()
Switch to batch mode.
void OpenGitHubIssue(const TString &type)
It opens a GitHub issue in a web browser with prefilled ROOT version.
Bool_t fReturnFromRun
virtual void Init()
TString fIdleCommand
char ** Argv() const
static Bool_t fgGraphNeeded
virtual void Terminate(Int_t status=0)
Terminate the application by call TSystem::Exit() unless application has been told to return from Run...
void OpenInBrowser(const TString &url)
The function generates and executes a command that loads the Doxygen URL in a browser.
virtual const char * ApplicationName() const
virtual void Forum(const char *line)
The function (".forum <type>") submits a new post on the ROOT forum via web browser.
void SetReturnFromRun(Bool_t ret)
virtual Int_t TabCompletionHook(char *buf, int *pLoc, std::ostream &out)
What to do when tab is pressed.
EExitOnException fExitOnException
TObjArray * fFiles
const char * GetIdleCommand() const
TApplication()
Default ctor. Can be used by classes deriving from TApplication.
virtual Longptr_t ProcessFile(const char *file, Int_t *error=nullptr, Bool_t keep=kFALSE)
Process a file containing a C++ macro.
void OpenForumTopic(const TString &type)
It opens a Forum topic in a web browser with prefilled ROOT version.
TString fWorkDir
virtual void ReturnPressed(char *text)
Emit signal when return key was pressed.
static Bool_t fgGraphInit
virtual void RemoveIdleTimer()
Remove idle timer. Normally called via TROOT::Idle(0).
virtual void SetIdleTimer(UInt_t idleTimeInSec, const char *command)
Set the command to be executed after the system has been idle for idleTimeInSec seconds.
virtual void GitHub(const char *line)
The function (".gh <type>") submits a new issue on GitHub via web browser.
static void CreateApplication()
Static function used to create a default application environment.
virtual void GetOptions(Int_t *argc, char **argv)
Get and handle command line options.
static TList * GetApplications()
Static method returning the list of available applications.
std::atomic< bool > fIsRunning
static void NeedGraphicsLibs()
Static method.
static Int_t ParseRemoteLine(const char *ln, TString &hostdir, TString &user, Int_t &dbg, TString &script)
Parse the content of a line starting with ".R" (already stripped-off) The format is.
TTimer * fIdleTimer
void ls(Option_t *option="") const override
Show available sessions.
TString GetSetup()
It gets the ROOT installation setup as TString.
virtual void HandleIdleTimer()
Handle idle timeout.
virtual Longptr_t ProcessRemote(const char *line, Int_t *error=nullptr)
Process the content of a line starting with ".R" (already stripped-off) The format is.
TApplication * fAppRemote
char ** fArgv
Using a TBrowser one can browse all ROOT objects.
Definition TBrowser.h:37
void RecursiveRemove(TObject *obj) override
Recursively remove obj from browser.
Definition TBrowser.cxx:427
void Add(TObject *obj, const char *name=nullptr, Int_t check=-1)
Add object with name to browser.
Definition TBrowser.cxx:302
static DictFuncPtr_t GetDict(const char *cname)
Given the class name returns the Dictionary() function of a class (uses hash of name).
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
TList * GetListOfAllPublicDataMembers(Bool_t load=kTRUE)
Returns a list of all public data members of this class and its base classes.
Definition TClass.cxx:3925
TList * GetListOfEnums(Bool_t load=kTRUE)
Return a list containing the TEnums of a class.
Definition TClass.cxx:3749
Long_t Property() const override
Returns the properties of the TClass as a bit field stored as a Long_t value.
Definition TClass.cxx:6254
TMethod * GetMethodAllAny(const char *method)
Return pointer to method without looking at parameters.
Definition TClass.cxx:4505
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:2999
static void InitializeColors()
Initialize colors used by the TCanvas based graphics (via TColor objects).
Definition TColor.cxx:1185
All ROOT classes may have RTTI (run time type identification) support added.
Definition TDataMember.h:31
const char * GetTrueTypeName() const
Get the desugared type name of this data member, including const and volatile qualifiers.
Bool_t IsEnum() const
Return true if data member is an enum.
const char * GetFullTypeName() const
Get the concrete type name of this data member, including const and volatile qualifiers.
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:511
Global functions class (global functions are obtained from CINT).
Definition TFunction.h:30
Long_t Property() const override
Get property description word. For meaning of bits see EProperty.
const char * GetSignature()
Return signature of function.
Long_t ExtraProperty() const
Get property description word. For meaning of bits see EProperty.
const char * GetReturnTypeName() const
Get full type description of function return type, e,g.: "class TDirectory*".
This ABC is a factory for GUI components.
Definition TGuiFactory.h:42
virtual TApplicationImp * CreateApplicationImp(const char *classname, int *argc, char **argv)
Create a batch version of TApplicationImp.
virtual Bool_t UseVirtualX() const
Definition TGuiFactory.h:48
TIdleTimer(Long_t ms)
Bool_t Notify() override
Notify handler.
void ls(Option_t *option="") const override
List this line with its attributes.
Definition TLine.cxx:241
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:708
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:952
virtual TObjLink * FirstLink() const
Definition TList.h:107
Each ROOT class (see TClass) has a linked list of methods.
Definition TMethod.h:38
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
An array of TObjects.
Definition TObjArray.h:31
Int_t GetEntries() const override
Return the number of objects in array (i.e.
void Delete(Option_t *option="") override
Remove all objects from the array AND delete all heap based objects.
TObject * At(Int_t idx) const override
Definition TObjArray.h:170
void Add(TObject *obj) override
Definition TObjArray.h:68
Collectable string class.
Definition TObjString.h:28
TString & String()
Definition TObjString.h:48
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:461
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
virtual void RecursiveRemove(TObject *obj)
Recursively remove this object from a list.
Definition TObject.cxx:683
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1082
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:886
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1096
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1124
virtual void Print(Option_t *option="") const
This method must be overridden when a class wants to print itself.
Definition TObject.cxx:660
void ResetBit(UInt_t f)
Definition TObject.h:203
@ kInvalidObject
if object ctor succeeded but object should not be used
Definition TObject.h:81
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1070
void Emit(const char *signal, const T &arg)
Activate signal with single parameter.
Definition TQObject.h:164
static const char * GetMacroPath()
Get macro search path. Static utility function.
Definition TROOT.cxx:2932
static void ShutDown()
Shut down ROOT.
Definition TROOT.cxx:3480
static const TString & GetTTFFontDir()
Get the fonts directory in the installation. Static utility function.
Definition TROOT.cxx:3522
static Bool_t Initialized()
Return kTRUE if the TROOT object has been initialized.
Definition TROOT.cxx:3082
static const TString & GetTutorialDir()
Get the tutorials directory in the installation. Static utility function.
Definition TROOT.cxx:3459
static const TString & GetDocDir()
Get the documentation directory in the installation. Static utility function.
Definition TROOT.cxx:3422
Basic string class.
Definition TString.h:137
Ssiz_t Length() const
Definition TString.h:426
void ToLower()
Change string to lower-case.
Definition TString.cxx:1190
TString & Insert(Ssiz_t pos, const char *s)
Definition TString.h:671
Int_t Atoi() const
Return integer value of string.
Definition TString.cxx:2069
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition TString.cxx:2325
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition TString.cxx:1171
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition TString.h:704
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition TString.cxx:546
const char * Data() const
Definition TString.h:385
TString & Chop()
Definition TString.h:701
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:714
TString MD5() const
Return the MD5 digest for this string, in a string representation.
Definition TString.cxx:948
@ kBoth
Definition TString.h:283
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:633
TString & Prepend(const char *cs)
Definition TString.h:683
Bool_t IsNull() const
Definition TString.h:423
std::istream & ReadFile(std::istream &str)
Replace string with the contents of strm, stopping at an EOF.
Definition Stringio.cxx:29
TString & Remove(Ssiz_t pos)
Definition TString.h:695
TString & Append(const char *cs)
Definition TString.h:582
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2460
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2438
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:642
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:661
void SetScreenFactor(Float_t factor=1)
Definition TStyle.h:321
virtual void NotifyApplicationCreated()
Hook to tell TSystem that the TApplication object has been created.
Definition TSystem.cxx:314
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition TSystem.cxx:1296
virtual const char * Getenv(const char *env)
Get environment variable.
Definition TSystem.cxx:1687
virtual TString SplitAclicMode(const char *filename, TString &mode, TString &args, TString &io) const
This method split a filename of the form:
Definition TSystem.cxx:4350
virtual Int_t Exec(const char *shellcmd)
Execute a command.
Definition TSystem.cxx:656
virtual void ListLibraries(const char *regexp="")
List the loaded shared libraries.
Definition TSystem.cxx:2107
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:1420
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition TSystem.cxx:1318
virtual void Run()
System event loop.
Definition TSystem.cxx:346
virtual void ExitLoop()
Exit from event loop.
Definition TSystem.cxx:395
virtual Bool_t ChangeDirectory(const char *path)
Change directory.
Definition TSystem.cxx:877
virtual void AddTimer(TTimer *t)
Add timer to list of system timers.
Definition TSystem.cxx:474
virtual const char * GetBuildCompilerVersionStr() const
Return the build compiler version identifier string.
Definition TSystem.cxx:3989
virtual void Exit(int code, Bool_t mode=kTRUE)
Exit the application.
Definition TSystem.cxx:730
virtual const char * WorkingDirectory()
Return working directory.
Definition TSystem.cxx:886
virtual char * Which(const char *search, const char *file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition TSystem.cxx:1570
virtual void SetProgname(const char *name)
Set the application name (from command line, argv[0]) and copy it in gProgName.
Definition TSystem.cxx:226
virtual const char * GetBuildArch() const
Return the build architecture.
Definition TSystem.cxx:3965
virtual void Abort(int code=0)
Abort the application.
Definition TSystem.cxx:739
virtual TTimer * RemoveTimer(TTimer *t)
Remove timer from list of system timers.
Definition TSystem.cxx:484
Handles synchronous and a-synchronous timer events.
Definition TTimer.h:51
void Reset()
Reset the timer.
Definition TTimer.cxx:162
This class represents a WWW compatible URL.
Definition TUrl.h:33
const char * GetUrl(Bool_t withDeflt=kFALSE) const
Return full URL.
Definition TUrl.cxx:395
const char * GetFileAndOptions() const
Return the file and its options (the string specified behind the ?).
Definition TUrl.cxx:508
const char * GetFile() const
Definition TUrl.h:69
const char * GetProtocol() const
Definition TUrl.h:64
Semi-Abstract base class defining a generic interface to the underlying, low level,...
Definition TVirtualX.h:47
TLine * line
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
void EnableImplicitMT(UInt_t numthreads=0)
Enable ROOT's implicit multi-threading for all objects and methods that provide an internal paralleli...
Definition TROOT.cxx:617
void EnableThreadSafety()
Enable support for multi-threading within the ROOT code in particular, enables the global mutex to ma...
Definition TROOT.cxx:579
std::string Join(const std::string &sep, InputIt_t begin, InputIt_t end)
Concatenate a list of strings with a separator.
std::pair< std::string_view, std::string_view > SplitAt(std::string_view str, char splitter)
Given a string str, returns a pair of string views into it: the first containing the substring preced...
const char * GetUnqualifiedName(const char *name)
Return the start of the unqualified name include in 'original'.