54 static Int_t Key_Pressed(Int_t key)
56 gApplication->KeyPressed(key);
62 static Int_t BeepHook()
64 if (!gSystem)
return 0;
72 static void ResetTermAtExit()
74 Getlinem(kCleanUp, 0);
81 class TInterruptHandler :
public TSignalHandler {
83 TInterruptHandler() : TSignalHandler(kSigInterrupt, kFALSE) { }
90 Bool_t TInterruptHandler::Notify()
98 ROOT::Internal::gMmallocDesc = 0;
100 if (TROOT::Initialized() && gROOT->IsLineProcessing()) {
101 Break(
"TInterruptHandler::Notify",
"keyboard interrupt");
102 Getlinem(kInit,
"Root > ");
110 Getlinem(kClear, ((TRint*)gApplication)->GetPrompt());
119 class TTermInputHandler :
public TFileHandler {
121 TTermInputHandler(Int_t fd) : TFileHandler(fd, 1) { }
123 Bool_t ReadNotify() {
return Notify(); }
129 Bool_t TTermInputHandler::Notify()
131 return gApplication->HandleTermInput();
143 TRint::TRint(
const char *appClassName, Int_t *argc,
char **argv,
void *options,
144 Int_t numOptions, Bool_t noLogo):
145 TApplication(appClassName, argc, argv, options, numOptions),
149 fDefaultPrompt =
"root [%d] ";
152 gBenchmark =
new TBenchmark();
154 if (!noLogo && !NoLogoOpt()) {
155 Bool_t lite = (Bool_t) gEnv->GetValue(
"Rint.WelcomeLite", 0);
162 if (!gClassTable->GetDict(
"TRandom"))
163 gSystem->Load(
"libMathCore");
165 if (!gInterpreter->HasPCMForLibrary(
"std")) {
167 Int_t includes = gEnv->GetValue(
"Rint.Includes", 1);
180 code =
"#include <iostream>\n"
181 "#include <string>\n"
182 "#include <DllImport.h>\n";
184 code +=
"#include <vector>\n"
185 "#include <utility>";
187 ProcessLine(code, kTRUE);
193 logon = gEnv->GetValue(
"Rint.Load", (
char*)0);
195 char *mac = gSystem->Which(TROOT::GetMacroPath(), logon, kReadPermission);
197 ProcessLine(Form(
".L %s",logon), kTRUE);
205 gCling->SaveContext();
206 gCling->SaveGlobalsContext();
209 TInterruptHandler *ih =
new TInterruptHandler();
211 SetSignalHandler(ih);
214 fInputHandler =
new TTermInputHandler(0);
215 fInputHandler->Add();
218 char defhist[kMAXPATHLEN];
219 snprintf(defhist,
sizeof(defhist),
"%s/.root_hist", gSystem->HomeDirectory());
220 logon = gEnv->GetValue(
"Rint.History", defhist);
225 int hist_size = gEnv->GetValue(
"Rint.HistorySize", 500);
226 if (hist_size == 500)
227 hist_size = gEnv->GetValue(
"Rint.HistSize", 500);
228 int hist_save = gEnv->GetValue(
"Rint.HistorySave", 400);
229 if (hist_save == 400)
230 hist_save = gEnv->GetValue(
"Rint.HistSave", 400);
231 const char *envHist = gSystem->Getenv(
"ROOT_HIST");
233 hist_size = atoi(envHist);
234 envHist = strchr(envHist,
':');
236 hist_save = atoi(envHist+1);
238 Gl_histsize(hist_size, hist_save);
239 Gl_histinit((
char *)logon);
242 static const char* defaultColorsBW[] = {
243 "bold blue",
"magenta",
"bold green",
"bold red underlined",
"default"
245 static const char* defaultColorsWB[] = {
246 "yellow",
"magenta",
"bold green",
"bold red underlined",
"default"
249 const char** defaultColors = defaultColorsBW;
250 TString revColor = gEnv->GetValue(
"Rint.ReverseColor",
"no");
251 if (revColor.Contains(
"yes", TString::kIgnoreCase)) {
252 defaultColors = defaultColorsWB;
254 TString colorType = gEnv->GetValue(
"Rint.TypeColor", defaultColors[0]);
255 TString colorTabCom = gEnv->GetValue(
"Rint.TabComColor", defaultColors[1]);
256 TString colorBracket = gEnv->GetValue(
"Rint.BracketColor", defaultColors[2]);
257 TString colorBadBracket = gEnv->GetValue(
"Rint.BadBracketColor", defaultColors[3]);
258 TString colorPrompt = gEnv->GetValue(
"Rint.PromptColor", defaultColors[4]);
259 Gl_setColors(colorType, colorTabCom, colorBracket, colorBadBracket, colorPrompt);
263 atexit(ResetTermAtExit);
266 gTabCom =
new TTabCom;
267 Gl_in_key = &Key_Pressed;
268 Gl_beep_hook = &BeepHook;
271 gCling->SetGetline(Getline, Gl_histadd);
283 fInputHandler->Remove();
284 delete fInputHandler;
302 void TRint::ExecLogon()
304 if (NoLogOpt())
return;
306 TString name =
".rootlogon.C";
307 TString sname =
"system";
309 char *s = gSystem->ConcatFileName(TROOT::GetEtcDir(), sname);
310 if (!gSystem->AccessPathName(s, kReadPermission)) {
314 s = gSystem->ConcatFileName(gSystem->HomeDirectory(), name);
315 if (!gSystem->AccessPathName(s, kReadPermission)) {
320 if (strcmp(gSystem->HomeDirectory(), gSystem->WorkingDirectory())) {
321 if (!gSystem->AccessPathName(name, kReadPermission))
326 const char *logon = gEnv->GetValue(
"Rint.Logon", (
char*)0);
328 char *mac = gSystem->Which(TROOT::GetMacroPath(), logon, kReadPermission);
345 void TRint::Run(Bool_t retrn)
349 Getlinem(kInit, GetPrompt());
354 volatile Bool_t needGetlinemInit = kFALSE;
356 if (strlen(WorkingDirectory())) {
358 gSystem->ChangeDirectory(WorkingDirectory());
359 TSystemDirectory *workdir =
new TSystemDirectory(
"workdir", gSystem->WorkingDirectory());
360 TObject *w = gROOT->GetListOfBrowsables()->FindObject(
"workdir");
361 TObjLink *lnk = gROOT->GetListOfBrowsables()->FirstLink();
363 if (lnk->GetObject() == w) {
364 lnk->SetObject(workdir);
365 lnk->SetOption(gSystem->WorkingDirectory());
377 fInputHandler->DeActivate();
378 TIter next(InputFiles());
380 retval = 0; error = 0;
382 while (TObject *fileObj = next()) {
383 if (dynamic_cast<TNamed*>(fileObj)) {
388 TObjString *file = (TObjString *)fileObj;
389 char cmd[kMAXPATHLEN+50];
392 Bool_t rootfile = kFALSE;
394 if (file->TestBit(kExpression)) {
395 snprintf(cmd, kMAXPATHLEN+50,
"%s", (
const char*)file->String());
397 if (file->String().EndsWith(
".root") || file->String().BeginsWith(
"file:")) {
400 rootfile = gROOT->IsRootFile(file->String());
404 if (file->String().BeginsWith(
"\\\\"))
405 file->String().Prepend(
"\\\\");
406 file->String().ReplaceAll(
"\\",
"/");
407 const char *rfile = (
const char*)file->String();
408 Printf(
"Attaching file %s as _file%d...", rfile, nfile);
409 snprintf(cmd, kMAXPATHLEN+50,
"TFile *_file%d = TFile::Open(\"%s\")", nfile++, rfile);
411 Printf(
"Processing %s...", (
const char*)file->String());
412 snprintf(cmd, kMAXPATHLEN+50,
".x %s", (
const char*)file->String());
415 Getlinem(kCleanUp, 0);
422 needGetlinemInit = kFALSE;
423 retval = ProcessLineNr(
"ROOT_cli_", cmd, &error);
424 gCling->EndOfLineAction();
428 needGetlinemInit = kTRUE;
430 if (error != 0 || fCaughtSignal != -1)
break;
438 }
else if (fCaughtSignal != -1) {
439 retval = fCaughtSignal + 128;
442 if (retval < 0 || retval > 255)
449 fInputHandler->Activate();
453 if (needGetlinemInit) Getlinem(kInit, GetPrompt());
459 Terminate(fCaughtSignal != -1 ? fCaughtSignal + 128 : 0);
462 TApplication::Run(retrn);
467 Getlinem(kCleanUp, 0);
473 void TRint::PrintLogo(Bool_t lite)
478 std::vector<TString> lines;
480 lines.emplace_back(TString::Format(
"Welcome to ROOT %s%%shttps://root.cern",
481 gROOT->GetVersion()));
482 lines.emplace_back(TString::Format(
"(c) 1995-2020, The ROOT Team; conception: R. Brun, F. Rademakers%%s"));
483 lines.emplace_back(TString::Format(
"Built for %s on %s%%s", gSystem->GetBuildArch(), gROOT->GetGitDate()));
484 if (!strcmp(gROOT->GetGitBranch(), gROOT->GetGitCommit())) {
485 static const char *months[] = {
"January",
"February",
"March",
"April",
"May",
486 "June",
"July",
"August",
"September",
"October",
487 "November",
"December"};
488 Int_t idatqq = gROOT->GetVersionDate();
489 Int_t iday = idatqq%100;
490 Int_t imonth = (idatqq/100)%100;
491 Int_t iyear = (idatqq/10000);
493 lines.emplace_back(TString::Format(
"From tag %s, %d %s %4d%%s",
494 gROOT->GetGitBranch(),
495 iday,months[imonth-1],iyear));
499 lines.emplace_back(TString::Format(
"From %s@%s %%s",
500 gROOT->GetGitBranch(),
501 gROOT->GetGitCommit()));
503 lines.emplace_back(TString(
"Try '.help', '.demo', '.license', '.credits', '.quit'/'.q'%s"));
506 auto itLongest = std::max_element(lines.begin(), lines.end(),
507 [](
const TString& left,
const TString& right) {
508 return left.Length() < right.Length(); });
509 Ssiz_t lenLongest = itLongest->Length();
512 Printf(
" %s", TString(
'-', lenLongest).Data());
513 for (
const auto& line: lines) {
517 TString::Format(line.Data(),
518 TString(
' ', lenLongest - line.Length()).Data()).Data());
520 Printf(
" %s\n", TString(
'-', lenLongest).Data());
525 for (
int i = 0; i < Argc(); i++)
526 if (!strcmp(Argv(i),
"-splash"))
527 kill(getppid(), SIGUSR1);
534 char *TRint::GetPrompt()
536 char *s = gCling->GetPrompt();
538 strlcpy(fPrompt, s,
sizeof(fPrompt));
540 snprintf(fPrompt,
sizeof(fPrompt), fDefaultPrompt.Data(), fNcmd);
554 const char *TRint::SetPrompt(
const char *newPrompt)
559 if (newPrompt && strlen(newPrompt) <= 55)
560 fDefaultPrompt = newPrompt;
562 Error(
"SetPrompt",
"newPrompt too long (> 55 characters)");
570 Bool_t TRint::HandleTermInput()
572 static TStopwatch timer;
575 if ((line = Getlinem(kOneChar, 0))) {
576 if (line[0] == 0 && Gl_eof())
579 gVirtualX->SetKeyAutoRepeat(kTRUE);
583 TString sline = line;
586 sline = sline.Chop();
587 sline = sline.Strip(TString::kBoth);
588 ReturnPressed((
char*)sline.Data());
592 if (!gCling->GetMore() && !sline.IsNull()) fNcmd++;
595 fInputHandler->DeActivate();
597 if (gROOT->Timer()) timer.Start();
599 TTHREAD_TLS(Bool_t) added;
603 SetBit(kProcessRemotely);
608 LineProcessed(sline);
609 ProcessLineNr(
"ROOT_prompt_", sline);
612 fInputHandler->Activate();
618 catch (std::exception& e) {
620 if (!added) fInputHandler->Activate();
623 char *demangledType_c = TClassEdit::DemangleTypeIdName(
typeid(e), err);
624 const char* demangledType = demangledType_c;
626 demangledType_c =
nullptr;
627 demangledType =
"<UNKNOWN>";
629 Error(
"HandleTermInput()",
"%s caught: %s", demangledType, e.what());
630 free(demangledType_c);
634 if (!added) fInputHandler->Activate();
635 Error(
"HandleTermInput()",
"Exception caught!");
638 if (gROOT->Timer()) timer.Print(
"u");
641 fInputHandler->Activate();
643 if (!sline.BeginsWith(
".reset"))
644 gCling->EndOfLineAction();
647 Getlinem(kInit, GetPrompt());
657 void TRint::HandleException(Int_t sig)
660 if (TROOT::Initialized()) {
662 Getlinem(kCleanUp, 0);
663 Getlinem(kInit,
"Root > ");
666 TApplication::HandleException(sig);
673 void TRint::Terminate(Int_t status)
675 Getlinem(kCleanUp, 0);
677 if (ReturnFromRun()) {
685 logoff = gEnv->GetValue(
"Rint.Logoff", (
char*)0);
686 if (logoff && !NoLogOpt()) {
687 char *mac = gSystem->Which(TROOT::GetMacroPath(), logoff, kReadPermission);
693 TApplication::Terminate(status);
703 void TRint::SetEchoMode(Bool_t mode)
705 Gl_config(
"noecho", mode ? 0 : 1);
719 Long_t TRint::ProcessRemote(
const char *line, Int_t *)
721 Long_t ret = TApplication::ProcessRemote(line);
725 TString prompt; prompt.Form(
"%s:root [%%d] ", fAppRemote->ApplicationName());
728 SetPrompt(
"root [%d] ");
741 Long_t TRint::ProcessLineNr(
const char* filestem,
const char *line, Int_t *error )
746 if (line && line[0] !=
'.') {
747 TString lineWithNr = TString::Format(
"#line 1 \"%s%d\"\n", filestem, fNcmd - 1);
748 int res = ProcessLine(lineWithNr + line, kFALSE, error);
749 if (*error == TInterpreter::kProcessing) {
750 if (!fNonContinuePrompt.Length())
751 fNonContinuePrompt = fDefaultPrompt;
752 SetPrompt(
"root (cont'ed, cancel with .@) [%d]");
753 }
else if (fNonContinuePrompt.Length()) {
754 SetPrompt(fNonContinuePrompt);
755 fNonContinuePrompt.Clear();
759 if (line && line[0] ==
'.' && line[1] ==
'@') {
760 ProcessLine(line, kFALSE, error);
761 SetPrompt(
"root [%d] ");
763 return ProcessLine(line, kFALSE, error);
770 Int_t TRint::TabCompletionHook(
char *buf,
int *pLoc, std::ostream& out)
773 return gTabCom->Hook(buf, pLoc, out);