Logo ROOT  
Reference Guide
TSystem.cxx
Go to the documentation of this file.
1 // @(#)root/base:$Id: 8944840ba34631ec28efc779647618db43c0eee5 $
2 // Author: Fons Rademakers 15/09/95
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2019, 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 TSystem
13 \ingroup Base
14 
15 Abstract base class defining a generic interface to the underlying
16 Operating System.
17 This is not an ABC in the strict sense of the (C++) word. For
18 every member function there is an implementation (often not more
19 than a call to AbstractMethod() which prints a warning saying
20 that the method should be overridden in a derived class), which
21 allows a simple partial implementation for new OS'es.
22 */
23 
24 #include <ROOT/FoundationUtils.hxx>
25 #include "Riostream.h"
26 #include "TSystem.h"
27 #include "TApplication.h"
28 #include "TException.h"
29 #include "TROOT.h"
30 #include "TClass.h"
31 #include "TClassTable.h"
32 #include "TEnv.h"
33 #include "TOrdCollection.h"
34 #include "TObject.h"
35 #include "TInterpreter.h"
36 #include "TRegexp.h"
37 #include "TObjString.h"
38 #include "TObjArray.h"
39 #include "TError.h"
40 #include "TPluginManager.h"
41 #include "TUrl.h"
42 #include "TVirtualMutex.h"
43 #include "TVersionCheck.h"
44 #include "compiledata.h"
45 #include "RConfigure.h"
46 #include "THashList.h"
47 #include "ThreadLocalStorage.h"
48 
49 #include <functional>
50 #include <sstream>
51 #include <string>
52 #include <sys/stat.h>
53 #include <set>
54 
55 #ifdef WIN32
56 #include <io.h>
57 #endif
58 
59 const char *gRootDir = nullptr;
60 const char *gProgName = nullptr;
61 const char *gProgPath = nullptr;
62 
63 TSystem *gSystem = nullptr;
64 TFileHandler *gXDisplay = nullptr; // Display server event handler, set in TGClient
65 
66 static Int_t *gLibraryVersion = nullptr; // Set in TVersionCheck, used in Load()
67 static Int_t gLibraryVersionIdx = 0; // Set in TVersionCheck, used in Load()
69 
70 // Pin vtable
73 
74 ////////////////////////////////////////////////////////////////////////////////
75 /// Create async event processor timer. Delay is in milliseconds.
76 
78 {
79  gROOT->SetInterrupt(kFALSE);
80  TurnOn();
81 }
82 
83 ////////////////////////////////////////////////////////////////////////////////
84 /// Process events if timer did time out. Returns kTRUE if interrupt
85 /// flag is set (by hitting a key in the canvas or selecting the
86 /// Interrupt menu item in canvas or some other action).
87 
89 {
90  if (fTimeout) {
91  if (gSystem->ProcessEvents()) {
92  Remove();
93  return kTRUE;
94  } else {
95  Reset();
96  return kFALSE;
97  }
98  }
99  return kFALSE;
100 }
101 
102 
103 
105 
107 
108 
109 
110 ////////////////////////////////////////////////////////////////////////////////
111 /// Strip off protocol string from specified path
112 
113 const char *TSystem::StripOffProto(const char *path, const char *proto)
114 {
115  return !strncmp(path, proto, strlen(proto)) ? path + strlen(proto) : path;
116 }
117 
118 ////////////////////////////////////////////////////////////////////////////////
119 /// Create a new OS interface.
120 
121 TSystem::TSystem(const char *name, const char *title) : TNamed(name, title)
122 {
123  if (gSystem && name[0] != '-' && strcmp(name, "Generic"))
124  Error("TSystem", "only one instance of TSystem allowed");
125 
126  if (!gLibraryVersion) {
128  memset(gLibraryVersion, 0, gLibraryVersionMax*sizeof(Int_t));
129  }
130 }
131 
132 ////////////////////////////////////////////////////////////////////////////////
133 /// Delete the OS interface.
134 
136 {
137  if (fOnExitList) {
138  fOnExitList->Delete();
140  }
141 
142  if (fSignalHandler) {
145  }
146 
147  if (fFileHandler) {
148  fFileHandler->Delete();
150  }
151 
152  if (fStdExceptionHandler) {
155  }
156 
157  if (fTimers) {
158  fTimers->Delete();
160  }
161 
162  if (fCompiled) {
163  fCompiled->Delete();
165  }
166 
167  if (fHelpers) {
168  fHelpers->Delete();
170  }
171 
172  if (gSystem == this)
173  gSystem = nullptr;
174 }
175 
176 ////////////////////////////////////////////////////////////////////////////////
177 /// Initialize the OS interface.
178 
180 {
181  fNfd = 0;
182  fMaxrfd = -1;
183  fMaxwfd = -1;
184 
185  fSigcnt = 0;
186  fLevel = 0;
187 
191  fTimers = new TOrdCollection;
192 
193  fBuildArch = BUILD_ARCH;
194  fBuildCompiler = COMPILER;
195  fBuildCompilerVersion = COMPILERVERS;
196  fBuildNode = BUILD_NODE;
197  fFlagsDebug = CXXDEBUG;
198  fFlagsOpt = CXXOPT;
199  fIncludePath = INCLUDEPATH;
200  fLinkedLibs = LINKEDLIBS;
201  fSoExt = SOEXT;
202  fObjExt = OBJEXT;
204  fMakeSharedLib = MAKESHAREDLIB;
205  fMakeExe = MAKEEXE;
207 
208  if (gEnv && fBeepDuration == 0 && fBeepFreq == 0) {
209  fBeepDuration = gEnv->GetValue("Root.System.BeepDuration", 100);
210  fBeepFreq = gEnv->GetValue("Root.System.BeepFreq", 440);
211  }
212  if (!fName.CompareTo("Generic")) return kTRUE;
213  return kFALSE;
214 }
215 
216 ////////////////////////////////////////////////////////////////////////////////
217 /// Set the application name (from command line, argv[0]) and copy it in
218 /// gProgName.
219 
220 void TSystem::SetProgname(const char *name)
221 {
222  delete [] gProgName;
223  gProgName = StrDup(name);
224 }
225 
226 ////////////////////////////////////////////////////////////////////////////////
227 /// Set DISPLAY environment variable based on utmp entry. Only for UNIX.
228 
230 {
231 }
232 
233 ////////////////////////////////////////////////////////////////////////////////
234 /// Set the system error string. This string will be used by GetError().
235 /// To be used in case one does not want or can use the system error
236 /// string (e.g. because error is generated by a third party POSIX like
237 /// library that does not use standard errno).
238 
239 void TSystem::SetErrorStr(const char *errstr)
240 {
241  ResetErrno(); // so GetError() uses the fLastErrorString
242  GetLastErrorString() = errstr;
243 }
244 
245 ////////////////////////////////////////////////////////////////////////////////
246 /// Return system error string.
247 
248 const char *TSystem::GetError()
249 {
250  if (GetErrno() == 0 && !GetLastErrorString().IsNull())
251  return GetLastErrorString().Data();
252  return Form("errno: %d", GetErrno());
253 }
254 
255 ////////////////////////////////////////////////////////////////////////////////
256 /// Static function returning system error number.
257 
259 {
260 #ifdef _REENTRANT
261  return errno; // errno can be a macro if _REENTRANT is set
262 #else
263 #ifdef R__SOLARIS_CC50
264  return ::errno;
265 #else
266  return errno;
267 #endif
268 #endif
269 }
270 
271 ////////////////////////////////////////////////////////////////////////////////
272 /// Static function resetting system error number.
273 
275 {
276 #ifdef _REENTRANT
277  errno = 0; // errno can be a macro if _REENTRANT is set
278 #else
279 #ifdef R__SOLARIS_CC50
280  ::errno = 0;
281 #else
282  errno = 0;
283 #endif
284 #endif
285 }
286 
287 ////////////////////////////////////////////////////////////////////////////////
288 /// Objects that should be deleted on exit of the OS interface.
289 
291 {
292  if (!fOnExitList)
294  if (!fOnExitList->FindObject(obj))
295  fOnExitList->Add(obj);
296 }
297 
298 ////////////////////////////////////////////////////////////////////////////////
299 /// Return the system's host name.
300 
301 const char *TSystem::HostName()
302 {
303  return "Local host";
304 }
305 
306 ////////////////////////////////////////////////////////////////////////////////
307 /// Hook to tell TSystem that the TApplication object has been created.
308 
310 {
311  // Currently needed only for WinNT interface.
312 }
313 
314 ////////////////////////////////////////////////////////////////////////////////
315 /// Beep for duration milliseconds with a tone of frequency freq.
316 /// Defaults to printing the `\a` character to stdout.
317 /// If freq or duration is <0 respectively, use default value.
318 /// If setDefault is set, only set the frequency and duration as
319 /// new defaults, but don't beep.
320 /// If default freq or duration is <0, never beep (silence)
321 
322 void TSystem::Beep(Int_t freq /*=-1*/, Int_t duration /*=-1*/,
323  Bool_t setDefault /*=kFALSE*/)
324 {
325  if (setDefault) {
326  fBeepFreq = freq;
327  fBeepDuration = duration;
328  return;
329  }
330  if (fBeepDuration < 0 || fBeepFreq < 0) return; // silence
331  if (freq < 0) freq = fBeepFreq;
332  if (duration < 0) duration = fBeepDuration;
333  DoBeep(freq, duration);
334 }
335 
336 //---- EventLoop ---------------------------------------------------------------
337 
338 ////////////////////////////////////////////////////////////////////////////////
339 /// System event loop.
340 
342 {
343  fInControl = kTRUE;
344  fDone = kFALSE;
345 
346 loop_entry:
347  try {
348  RETRY {
349  while (!fDone) {
351  InnerLoop();
353  }
354  } ENDTRY;
355  }
356  catch (std::exception& exc) {
358  TStdExceptionHandler* eh = 0;
359  while ((eh = (TStdExceptionHandler*) next())) {
360  switch (eh->Handle(exc))
361  {
363  break;
365  goto loop_entry;
366  break;
368  Warning("Run", "instructed to abort");
369  goto loop_end;
370  break;
371  }
372  }
373  throw;
374  }
375  catch (const char *str) {
376  printf("%s\n", str);
377  }
378  // handle every exception
379  catch (...) {
380  Warning("Run", "handle uncaugth exception, terminating");
381  }
382 
383 loop_end:
384  fInControl = kFALSE;
385 }
386 
387 ////////////////////////////////////////////////////////////////////////////////
388 /// Exit from event loop.
389 
391 {
392  fDone = kTRUE;
393 }
394 
395 ////////////////////////////////////////////////////////////////////////////////
396 /// Inner event loop.
397 
399 {
400  fLevel++;
402  fLevel--;
403 }
404 
405 ////////////////////////////////////////////////////////////////////////////////
406 /// Process pending events (GUI, timers, sockets). Returns the result of
407 /// TROOT::IsInterrupted(). The interrupt flag (TROOT::SetInterrupt())
408 /// can be set during the handling of the events. This mechanism allows
409 /// macros running in tight calculating loops to be interrupted by some
410 /// GUI event (depending on the interval with which this method is
411 /// called). For example hitting ctrl-c in a canvas will set the
412 /// interrupt flag.
413 
415 {
416  gROOT->SetInterrupt(kFALSE);
417 
418  if (!gROOT->TestBit(TObject::kInvalidObject))
420 
421  return gROOT->IsInterrupted();
422 }
423 
424 ////////////////////////////////////////////////////////////////////////////////
425 /// Dispatch a single event.
426 
428 {
429  AbstractMethod("DispatchOneEvent");
430 }
431 
432 ////////////////////////////////////////////////////////////////////////////////
433 /// Sleep milliSec milli seconds.
434 
436 {
437  AbstractMethod("Sleep");
438 }
439 
440 ////////////////////////////////////////////////////////////////////////////////
441 /// Select on active file descriptors (called by TMonitor).
442 
444 {
445  AbstractMethod("Select");
446  return -1;
447 }
448 ////////////////////////////////////////////////////////////////////////////////
449 /// Select on active file descriptors (called by TMonitor).
450 
452 {
453  AbstractMethod("Select");
454  return -1;
455 }
456 
457 //---- handling of system events -----------------------------------------------
458 ////////////////////////////////////////////////////////////////////////////////
459 /// Get current time in milliseconds since 0:00 Jan 1 1995.
460 
462 {
463  return TTime(0);
464 }
465 
466 ////////////////////////////////////////////////////////////////////////////////
467 /// Add timer to list of system timers.
468 
470 {
471  if (ti && fTimers && (fTimers->FindObject(ti) == nullptr))
472  fTimers->Add(ti);
473 }
474 
475 ////////////////////////////////////////////////////////////////////////////////
476 /// Remove timer from list of system timers. Returns removed timer or 0
477 /// if timer was not active.
478 
480 {
481  if (fTimers) {
482  TTimer *tr = (TTimer*) fTimers->Remove(ti);
483  return tr;
484  }
485  return nullptr;
486 }
487 
488 ////////////////////////////////////////////////////////////////////////////////
489 /// Time when next timer of mode (synchronous=kTRUE or
490 /// asynchronous=kFALSE) will time-out (in ms).
491 
493 {
494  if (!fTimers) return -1;
495 
497  TTimer *t, *to = nullptr;
498  Long64_t tt, tnow = Now();
499  Long_t timeout = -1;
500 
501  while ((t = (TTimer *) it.Next())) {
502  if (t->IsSync() == mode) {
503  tt = (Long64_t)t->GetAbsTime() - tnow;
504  if (tt < 0) tt = 0;
505  if (timeout == -1) {
506  timeout = (Long_t)tt;
507  to = t;
508  }
509  if (tt < timeout) {
510  timeout = (Long_t)tt;
511  to = t;
512  }
513  }
514  }
515 
516  if (to && to->IsAsync() && timeout > 0) {
517  if (to->IsInterruptingSyscalls())
519  else
521  }
522 
523  return timeout;
524 }
525 
526 ////////////////////////////////////////////////////////////////////////////////
527 /// Add a signal handler to list of system signal handlers. Only adds
528 /// the handler if it is not already in the list of signal handlers.
529 
531 {
532  if (h && fSignalHandler && (fSignalHandler->FindObject(h) == nullptr))
533  fSignalHandler->Add(h);
534 }
535 
536 ////////////////////////////////////////////////////////////////////////////////
537 /// Remove a signal handler from list of signal handlers. Returns
538 /// the handler or 0 if the handler was not in the list of signal handlers.
539 
541 {
542  if (fSignalHandler)
544 
545  return nullptr;
546 }
547 
548 ////////////////////////////////////////////////////////////////////////////////
549 /// Add a file handler to the list of system file handlers. Only adds
550 /// the handler if it is not already in the list of file handlers.
551 
553 {
554  if (h && fFileHandler && !fFileHandler->FindObject(h))
555  fFileHandler->Add(h);
556 }
557 
558 ////////////////////////////////////////////////////////////////////////////////
559 /// Remove a file handler from the list of file handlers. Returns
560 /// the handler or 0 if the handler was not in the list of file handlers.
561 
563 {
564  if (fFileHandler)
565  return (TFileHandler *)fFileHandler->Remove(h);
566 
567  return nullptr;
568 }
569 
570 ////////////////////////////////////////////////////////////////////////////////
571 /// If reset is true reset the signal handler for the specified signal
572 /// to the default handler, else restore previous behaviour.
573 
574 void TSystem::ResetSignal(ESignals /*sig*/, Bool_t /*reset*/)
575 {
576  AbstractMethod("ResetSignal");
577 }
578 
579 ////////////////////////////////////////////////////////////////////////////////
580 /// Reset signals handlers to previous behaviour.
581 
583 {
584  AbstractMethod("ResetSignals");
585 }
586 
587 ////////////////////////////////////////////////////////////////////////////////
588 /// If ignore is true ignore the specified signal, else restore previous
589 /// behaviour.
590 
591 void TSystem::IgnoreSignal(ESignals /*sig*/, Bool_t /*ignore*/)
592 {
593  AbstractMethod("IgnoreSignal");
594 }
595 
596 ////////////////////////////////////////////////////////////////////////////////
597 /// If ignore is true ignore the interrupt signal, else restore previous
598 /// behaviour. Typically call ignore interrupt before writing to disk.
599 
601 {
602  IgnoreSignal(kSigInterrupt, ignore);
603 }
604 
605 ////////////////////////////////////////////////////////////////////////////////
606 /// Add an exception handler to list of system exception handlers. Only adds
607 /// the handler if it is not already in the list of exception handlers.
608 
610 {
613 }
614 
615 ////////////////////////////////////////////////////////////////////////////////
616 /// Remove an exception handler from list of exception handlers. Returns
617 /// the handler or 0 if the handler was not in the list of exception handlers.
618 
620 {
623 
624  return nullptr;
625 }
626 
627 ////////////////////////////////////////////////////////////////////////////////
628 /// Return the bitmap of conditions that trigger a floating point exception.
629 
631 {
632  AbstractMethod("GetFPEMask");
633  return 0;
634 }
635 
636 ////////////////////////////////////////////////////////////////////////////////
637 /// Set which conditions trigger a floating point exception.
638 /// Return the previous set of conditions.
639 
641 {
642  AbstractMethod("SetFPEMask");
643  return 0;
644 }
645 
646 //---- Processes ---------------------------------------------------------------
647 
648 ////////////////////////////////////////////////////////////////////////////////
649 /// Execute a command.
650 
651 int TSystem::Exec(const char*)
652 {
653  AbstractMethod("Exec");
654  return -1;
655 }
656 
657 ////////////////////////////////////////////////////////////////////////////////
658 /// Open a pipe.
659 
660 FILE *TSystem::OpenPipe(const char*, const char*)
661 {
662  AbstractMethod("OpenPipe");
663  return nullptr;
664 }
665 
666 ////////////////////////////////////////////////////////////////////////////////
667 /// Close the pipe.
668 
670 {
671  AbstractMethod("ClosePipe");
672  return -1;
673 }
674 
675 ////////////////////////////////////////////////////////////////////////////////
676 /// Execute command and return output in TString.
677 
678 TString TSystem::GetFromPipe(const char *command)
679 {
680  TString out;
681 
682  FILE *pipe = OpenPipe(command, "r");
683  if (!pipe) {
684  SysError("GetFromPipe", "cannot run command \"%s\"", command);
685  return out;
686  }
687 
688  TString line;
689  while (line.Gets(pipe)) {
690  if (out != "")
691  out += "\n";
692  out += line;
693  }
694 
695  Int_t r = ClosePipe(pipe);
696  if (r) {
697  Error("GetFromPipe", "command \"%s\" returned %d", command, r);
698  }
699  return out;
700 }
701 
702 ////////////////////////////////////////////////////////////////////////////////
703 /// Get process id.
704 
706 {
707  AbstractMethod("GetPid");
708  return -1;
709 }
710 
711 ////////////////////////////////////////////////////////////////////////////////
712 /// Exit the application.
713 
715 {
716  AbstractMethod("Exit");
717 }
718 
719 ////////////////////////////////////////////////////////////////////////////////
720 /// Abort the application.
721 
722 void TSystem::Abort(int)
723 {
724  AbstractMethod("Abort");
725 }
726 
727 ////////////////////////////////////////////////////////////////////////////////
728 /// Print a stack trace.
729 
731 {
732  AbstractMethod("StackTrace");
733 }
734 
735 
736 //---- Directories -------------------------------------------------------------
737 
738 ////////////////////////////////////////////////////////////////////////////////
739 /// Create helper TSystem to handle file and directory operations that
740 /// might be special for remote file access.
741 
742 TSystem *TSystem::FindHelper(const char *path, void *dirptr)
743 {
744  TSystem *helper = nullptr;
745  {
747 
748  if (!fHelpers) {
750  fHelpers = new TOrdCollection;
751  }
752 
753  if (path) {
754  if (!GetDirPtr()) {
755  TUrl url(path, kTRUE);
756  if (!strcmp(url.GetProtocol(), "file"))
757  return nullptr;
758  }
759  }
760 
761  // look for existing helpers
762  TIter next(fHelpers);
763  while ((helper = (TSystem*) next()))
764  if (helper->ConsistentWith(path, dirptr))
765  return helper;
766 
767  if (!path)
768  return nullptr;
769  }
770 
771  // create new helper
772  TRegexp re("^root.*:"); // also roots, rootk, etc
773  TString pname = path;
774  TPluginHandler *h;
775  if (pname.BeginsWith("xroot:") || pname.Index(re) != kNPOS) {
776  // (x)rootd daemon ...
777  if ((h = gROOT->GetPluginManager()->FindHandler("TSystem", path))) {
778  if (h->LoadPlugin() == -1)
779  return nullptr;
780  helper = (TSystem*) h->ExecPlugin(2, path, kFALSE);
781  }
782  } else if ((h = gROOT->GetPluginManager()->FindHandler("TSystem", path))) {
783  if (h->LoadPlugin() == -1)
784  return nullptr;
785  helper = (TSystem*) h->ExecPlugin(0);
786  }
787 
788  if (helper) {
790  fHelpers->Add(helper);
791  }
792 
793  return helper;
794 }
795 
796 ////////////////////////////////////////////////////////////////////////////////
797 /// Check consistency of this helper with the one required
798 /// by 'path' or 'dirptr'
799 
800 Bool_t TSystem::ConsistentWith(const char *path, void *dirptr)
801 {
802  Bool_t checkproto = kFALSE;
803  if (path) {
804  if (!GetDirPtr()) {
805  TUrl url(path, kTRUE);
806  if (!strncmp(url.GetProtocol(), GetName(), strlen(GetName())))
807  checkproto = kTRUE;
808  }
809  }
810 
811  Bool_t checkdir = kFALSE;
812  if (GetDirPtr() && GetDirPtr() == dirptr)
813  checkdir = kTRUE;
814 
815  return (checkproto || checkdir);
816 }
817 
818 ////////////////////////////////////////////////////////////////////////////////
819 /// Make a directory. Returns 0 in case of success and
820 /// -1 if the directory could not be created (either already exists or
821 /// illegal path name).
822 
823 int TSystem::MakeDirectory(const char*)
824 {
825  AbstractMethod("MakeDirectory");
826  return 0;
827 }
828 
829 ////////////////////////////////////////////////////////////////////////////////
830 /// Open a directory. Returns 0 if directory does not exist.
831 
832 void *TSystem::OpenDirectory(const char *)
833 {
834  AbstractMethod("OpenDirectory");
835  return nullptr;
836 }
837 
838 ////////////////////////////////////////////////////////////////////////////////
839 /// Free a directory.
840 
842 {
843  AbstractMethod("FreeDirectory");
844 }
845 
846 ////////////////////////////////////////////////////////////////////////////////
847 /// Get a directory entry. Returns 0 if no more entries.
848 
849 const char *TSystem::GetDirEntry(void *)
850 {
851  AbstractMethod("GetDirEntry");
852  return nullptr;
853 }
854 
855 ////////////////////////////////////////////////////////////////////////////////
856 /// Change directory.
857 
859 {
860  AbstractMethod("ChangeDirectory");
861  return kFALSE;
862 }
863 
864 ////////////////////////////////////////////////////////////////////////////////
865 /// Return working directory.
866 
868 {
869  return nullptr;
870 }
871 
872 //////////////////////////////////////////////////////////////////////////////
873 /// Return working directory.
874 
875 std::string TSystem::GetWorkingDirectory() const
876 {
877  return std::string();
878 }
879 
880 ////////////////////////////////////////////////////////////////////////////////
881 /// Return the user's home directory.
882 
883 const char *TSystem::HomeDirectory(const char *)
884 {
885  return nullptr;
886 }
887 
888 //////////////////////////////////////////////////////////////////////////////
889 /// Return the user's home directory.
890 
891 std::string TSystem::GetHomeDirectory(const char*) const
892 {
893  return std::string();
894 }
895 
896 ////////////////////////////////////////////////////////////////////////////////
897 /// Make a file system directory. Returns 0 in case of success and
898 /// -1 if the directory could not be created (either already exists or
899 /// illegal path name).
900 /// If 'recursive' is true, makes parent directories as needed.
901 
902 int TSystem::mkdir(const char *name, Bool_t recursive)
903 {
904  if (recursive) {
905  TString safeName = name; // local copy in case 'name' is output from
906  // TSystem::DirName as it uses static buffers
907  TString dirname = GetDirName(safeName.Data());
908  if (dirname.IsNull()) {
909  // well we should not have to make the root of the file system!
910  // (and this avoid infinite recursions!)
911  return -1;
912  }
913  if (AccessPathName(dirname.Data(), kFileExists)) {
914  int res = mkdir(dirname.Data(), kTRUE);
915  if (res) return res;
916  }
917  if (!AccessPathName(safeName.Data(), kFileExists)) {
918  return -1;
919  }
920  }
921 
922  return MakeDirectory(name);
923 }
924 
925 //---- Paths & Files -----------------------------------------------------------
926 
927 ////////////////////////////////////////////////////////////////////////////////
928 /// Base name of a file name. Base name of /user/root is root.
929 
930 const char *TSystem::BaseName(const char *name)
931 {
932  if (name) {
933  if (name[0] == '/' && name[1] == '\0')
934  return name;
935  char *cp;
936  if ((cp = (char*)strrchr(name, '/')))
937  return ++cp;
938  return name;
939  }
940  Error("BaseName", "name = 0");
941  return nullptr;
942 }
943 
944 ////////////////////////////////////////////////////////////////////////////////
945 /// Return true if dir is an absolute pathname.
946 
948 {
949  if (dir)
950  return dir[0] == '/';
951  return kFALSE;
952 }
953 
954 ////////////////////////////////////////////////////////////////////////////////
955 /// Return true if 'name' is a file that can be found in the ROOT include
956 /// path or the current directory.
957 /// If 'name' contains any ACLiC style information (e.g. trailing +[+][g|O]),
958 /// it will be striped off 'name'.
959 /// If fullpath is != 0, the full path to the file is returned in *fullpath,
960 /// which must be deleted by the caller.
961 
962 Bool_t TSystem::IsFileInIncludePath(const char *name, char **fullpath)
963 {
964  if (!name || !name[0]) return kFALSE;
965 
966  TString aclicMode;
967  TString arguments;
968  TString io;
969  TString realname = SplitAclicMode(name, aclicMode, arguments, io);
970 
971  TString fileLocation = GetDirName(realname);
972 
973  TString incPath = gSystem->GetIncludePath(); // of the form -Idir1 -Idir2 -Idir3
974  incPath.Append(":").Prepend(" ");
975  incPath.ReplaceAll(" -I",":"); // of form :dir1 :dir2:dir3
976  while ( incPath.Index(" :") != -1 ) {
977  incPath.ReplaceAll(" :",":");
978  }
979  // Remove double quotes around path expressions.
980  incPath.ReplaceAll("\":", ":");
981  incPath.ReplaceAll(":\"", ":");
982 
983  incPath.Prepend(fileLocation+":.:");
984 
985  char *actual = Which(incPath,realname);
986 
987  if (!actual) {
988  return kFALSE;
989  } else {
990  if (fullpath)
991  *fullpath = actual;
992  else
993  delete [] actual;
994  return kTRUE;
995  }
996 }
997 
998 ////////////////////////////////////////////////////////////////////////////////
999 /// Return the directory name in pathname. DirName of /user/root is /user.
1000 /// In case no dirname is specified "." is returned.
1001 
1002 const char *TSystem::DirName(const char *pathname)
1003 {
1004  auto res = GetDirName(pathname);
1005  if (res.IsNull() || (res == "."))
1006  return ".";
1007 
1009 
1010  static Ssiz_t len = 0;
1011  static char *buf = nullptr;
1012  if (res.Length() >= len) {
1013  if (buf) delete [] buf;
1014  len = res.Length() + 50;
1015  buf = new char [len];
1016  }
1017  strncpy(buf, res.Data(), len);
1018  return buf;
1019 }
1020 
1021 ////////////////////////////////////////////////////////////////////////////////
1022 /// Return the directory name in pathname.
1023 /// DirName of /user/root is /user.
1024 /// DirName of /user/root/ is also /user.
1025 /// In case no dirname is specified "." is returned.
1026 
1027 TString TSystem::GetDirName(const char *pathname)
1028 {
1029  if (!pathname || !strchr(pathname, '/'))
1030  return ".";
1031 
1032  auto pathlen = strlen(pathname);
1033 
1034  const char *r = pathname + pathlen - 1;
1035  // First skip the trailing '/'
1036  while ((r > pathname) && (*r == '/'))
1037  --r;
1038  // Then find the next non slash
1039  while ((r > pathname) && (*r != '/'))
1040  --r;
1041 
1042  // Then skip duplicate slashes
1043  // Note the 'r>buf' is a strict comparison to allows '/topdir' to return '/'
1044  while ((r > pathname) && (*r == '/'))
1045  --r;
1046  // If all was cut away, we encountered a rel. path like 'subdir/'
1047  // and ended up at '.'.
1048  if ((r == pathname) && (*r != '/'))
1049  return ".";
1050 
1051  return TString(pathname, r + 1 - pathname);
1052 }
1053 
1054 ////////////////////////////////////////////////////////////////////////////////
1055 /// Convert from a local pathname to a Unix pathname. E.g. from `\user\root` to
1056 /// `/user/root`.
1057 
1058 const char *TSystem::UnixPathName(const char *name)
1059 {
1060  return name;
1061 }
1062 
1063 ////////////////////////////////////////////////////////////////////////////////
1064 /// Concatenate a directory and a file name. User must delete returned string.
1065 
1066 char *TSystem::ConcatFileName(const char *dir, const char *name)
1067 {
1068  TString nameString(name);
1069  PrependPathName(dir, nameString);
1070  return StrDup(nameString.Data());
1071 }
1072 
1073 ////////////////////////////////////////////////////////////////////////////////
1074 /// Concatenate a directory and a file name.
1075 
1076 const char *TSystem::PrependPathName(const char *, TString&)
1077 {
1078  AbstractMethod("PrependPathName");
1079  return nullptr;
1080 }
1081 
1082 
1083 //---- Paths & Files -----------------------------------------------------------
1084 
1085 ////////////////////////////////////////////////////////////////////////////////
1086 /// Expand a pathname getting rid of special shell characters like ~.$, etc.
1087 /// For Unix/Win32 compatibility use $(XXX) instead of $XXX when using
1088 /// environment variables in a pathname. If compatibility is not an issue
1089 /// you can use on Unix directly $XXX. This is a protected function called
1090 /// from the OS specific system classes, like TUnixSystem and TWinNTSystem.
1091 /// Returns the expanded filename or 0 in case of error.
1092 
1093 const char *TSystem::ExpandFileName(const char *fname)
1094 {
1095  const int kBufSize = kMAXPATHLEN;
1096  TTHREAD_TLS_ARRAY(char, kBufSize, xname);
1097 
1098  Bool_t res = ExpandFileName(fname, xname, kBufSize);
1099  if (res)
1100  return nullptr;
1101  else
1102  return xname;
1103 }
1104 
1105 //////////////////////////////////////////////////////////////////////////////
1106 /// Expand a pathname getting rid of special shell characters like ~.$, etc.
1107 /// This function is analogous to ExpandFileName(const char *), except that
1108 /// it receives a TString reference of the pathname to be expanded.
1109 /// Returns kTRUE in case of error and kFALSE otherwise.
1110 
1112 {
1113  const int kBufSize = kMAXPATHLEN;
1114  char xname[kBufSize];
1115 
1116  Bool_t res = ExpandFileName(fname.Data(), xname, kBufSize);
1117  if (!res)
1118  fname = xname;
1119 
1120  return res;
1121 }
1122 
1123 ////////////////////////////////////////////////////////////////////////////
1124 /// Private method for pathname expansion.
1125 /// Returns kTRUE in case of error and kFALSE otherwise.
1126 
1127 Bool_t TSystem::ExpandFileName(const char *fname, char *xname, const int kBufSize)
1128 {
1129  int n, ier, iter, lx, ncopy;
1130  char *inp, *out, *x, *t, *buff;
1131  const char *b, *c, *e;
1132  const char *p;
1133  buff = new char[kBufSize * 4];
1134 
1135  iter = 0; xname[0] = 0; inp = buff + kBufSize; out = inp + kBufSize;
1136  inp[-1] = ' '; inp[0] = 0; out[-1] = ' ';
1137  c = fname + strspn(fname, " \t\f\r");
1138  //VP if (isalnum(c[0])) { strcpy(inp, WorkingDirectory()); strcat(inp, "/"); } // add $cwd
1139 
1140  strlcat(inp, c, kBufSize);
1141 
1142 again:
1143  iter++; c = inp; ier = 0;
1144  x = out; x[0] = 0;
1145 
1146  p = 0; e = 0;
1147  if (c[0] == '~' && c[1] == '/') { // ~/ case
1148  std::string hd = GetHomeDirectory();
1149  p = hd.c_str();
1150  e = c + 1;
1151  if (p) { // we have smth to copy
1152  strlcpy(x, p, kBufSize);
1153  x += strlen(p);
1154  c = e;
1155  } else {
1156  ++ier;
1157  ++c;
1158  }
1159  } else if (c[0] == '~' && c[1] != '/') { // ~user case
1160  n = strcspn(c+1, "/ ");
1161  assert((n+1) < kBufSize && "This should have been prevented by the truncation 'strlcat(inp, c, kBufSize)'");
1162  // There is no overlap here as the buffer is segment in 4 strings of at most kBufSize
1163  (void)strlcpy(buff, c+1, n+1); // strlcpy copy 'size-1' characters.
1164  std::string hd = GetHomeDirectory(buff);
1165  e = c+1+n;
1166  if (!hd.empty()) { // we have smth to copy
1167  p = hd.c_str();
1168  strlcpy(x, p, kBufSize);
1169  x += strlen(p);
1170  c = e;
1171  } else {
1172  x++[0] = c[0];
1173  //++ier;
1174  ++c;
1175  }
1176  }
1177 
1178  for ( ; c[0]; c++) {
1179 
1180  p = 0; e = 0;
1181 
1182  if (c[0] == '.' && c[1] == '/' && c[-1] == ' ') { // $cwd
1183  std::string wd = GetWorkingDirectory();
1184  strlcpy(buff, wd.c_str(), kBufSize);
1185  p = buff;
1186  e = c + 1;
1187  }
1188  if (p) { // we have smth to copy */
1189  strlcpy(x, p, kBufSize); x += strlen(p); c = e-1; continue;
1190  }
1191 
1192  if (c[0] != '$') { // not $, simple copy
1193  x++[0] = c[0];
1194  } else { // we have a $
1195  b = c+1;
1196  if (c[1] == '(') b++;
1197  if (c[1] == '{') b++;
1198  if (b[0] == '$')
1199  e = b+1;
1200  else
1201  for (e = b; isalnum(e[0]) || e[0] == '_'; e++) ;
1202  buff[0] = 0; strncat(buff, b, e-b);
1203  p = Getenv(buff);
1204  if (!p) { // too bad, try UPPER case
1205  for (t = buff; (t[0] = toupper(t[0])); t++) ;
1206  p = Getenv(buff);
1207  }
1208  if (!p) { // too bad, try Lower case
1209  for (t = buff; (t[0] = tolower(t[0])); t++) ;
1210  p = Getenv(buff);
1211  }
1212  if (!p && !strcmp(buff, "cwd")) { // it is $cwd
1213  std::string wd = GetWorkingDirectory();
1214  strlcpy(buff, wd.c_str(), kBufSize);
1215  p = buff;
1216  }
1217  if (!p && !strcmp(buff, "$")) { // it is $$ (replace by GetPid())
1218  snprintf(buff,kBufSize*4, "%d", GetPid());
1219  p = buff;
1220  }
1221  if (!p) { // too bad, nothing can help
1222 #ifdef WIN32
1223  // if we're on windows, we can have \\SomeMachine\C$ - don't
1224  // complain about that, if '$' is followed by nothing or a
1225  // path delimiter.
1226  if (c[1] && c[1]!='\\' && c[1]!=';' && c[1]!='/')
1227  ier++;
1228 #else
1229  ier++;
1230 #endif
1231  x++[0] = c[0];
1232  } else { // It is OK, copy result
1233  int lp = strlen(p);
1234  if (lp >= kBufSize) {
1235  // make sure lx will be >= kBufSize (see below)
1236  strlcpy(x, p, kBufSize);
1237  x += kBufSize;
1238  break;
1239  }
1240  strcpy(x,p);
1241  x += lp;
1242  c = (b==c+1) ? e-1 : e;
1243  }
1244  }
1245  }
1246 
1247  x[0] = 0; lx = x - out;
1248  if (ier && iter < 3) { strlcpy(inp, out, kBufSize); goto again; }
1249  ncopy = (lx >= kBufSize) ? kBufSize-1 : lx;
1250  xname[0] = 0; strncat(xname, out, ncopy);
1251 
1252  delete[] buff;
1253 
1254  if (ier || ncopy != lx) {
1255  ::Error("TSystem::ExpandFileName", "input: %s, output: %s", fname, xname);
1256  return kTRUE;
1257  }
1258 
1259  return kFALSE;
1260 }
1261 
1262 
1263 ////////////////////////////////////////////////////////////////////////////////
1264 /// Expand a pathname getting rid of special shell characters like ~.$, etc.
1265 /// For Unix/Win32 compatibility use $(XXX) instead of $XXX when using
1266 /// environment variables in a pathname. If compatibility is not an issue
1267 /// you can use on Unix directly $XXX.
1268 
1270 {
1271  return kFALSE;
1272 }
1273 
1274 ////////////////////////////////////////////////////////////////////////////////
1275 /// Expand a pathname getting rid of special shell characters like ~.$, etc.
1276 /// For Unix/Win32 compatibility use $(XXX) instead of $XXX when using
1277 /// environment variables in a pathname. If compatibility is not an issue
1278 /// you can use on Unix directly $XXX. The user must delete returned string.
1279 
1280 char *TSystem::ExpandPathName(const char *)
1281 {
1282  return nullptr;
1283 }
1284 
1285 ////////////////////////////////////////////////////////////////////////////////
1286 /// Returns FALSE if one can access a file using the specified access mode.
1287 /// The file name must not contain any special shell characters line ~ or $,
1288 /// in those cases first call ExpandPathName().
1289 /// Attention, bizarre convention of return value!!
1290 
1292 {
1293  return kFALSE;
1294 }
1295 
1296 ////////////////////////////////////////////////////////////////////////////////
1297 /// Returns TRUE if the url in 'path' points to the local file system.
1298 /// This is used to avoid going through the NIC card for local operations.
1299 
1300 Bool_t TSystem::IsPathLocal(const char *path)
1301 {
1302  Bool_t localPath = kTRUE;
1303 
1304  TUrl url(path);
1305  if (strlen(url.GetHost()) > 0) {
1306  // Check locality
1307  localPath = kFALSE;
1310  if (!strcmp(a.GetHostName(), b.GetHostName()) ||
1311  !strcmp(a.GetHostAddress(), b.GetHostAddress())) {
1312  // Host OK
1313  localPath = kTRUE;
1314  // Check the user if specified
1315  if (strlen(url.GetUser()) > 0) {
1317  if (u) {
1318  if (strcmp(u->fUser, url.GetUser()))
1319  // Requested a different user
1320  localPath = kFALSE;
1321  delete u;
1322  }
1323  }
1324  }
1325  }
1326  // Done
1327  return localPath;
1328 }
1329 
1330 ////////////////////////////////////////////////////////////////////////////////
1331 /// Copy a file. If overwrite is true and file already exists the
1332 /// file will be overwritten. Returns 0 when successful, -1 in case
1333 /// of file open failure, -2 in case the file already exists and overwrite
1334 /// was false and -3 in case of error during copy.
1335 
1336 int TSystem::CopyFile(const char *, const char *, Bool_t)
1337 {
1338  AbstractMethod("CopyFile");
1339  return -1;
1340 }
1341 
1342 ////////////////////////////////////////////////////////////////////////////////
1343 /// Rename a file.
1344 
1345 int TSystem::Rename(const char *, const char *)
1346 {
1347  AbstractMethod("Rename");
1348  return -1;
1349 }
1350 
1351 ////////////////////////////////////////////////////////////////////////////////
1352 /// Create a link from file1 to file2.
1353 
1354 int TSystem::Link(const char *, const char *)
1355 {
1356  AbstractMethod("Link");
1357  return -1;
1358 }
1359 
1360 ////////////////////////////////////////////////////////////////////////////////
1361 /// Create a symbolic link from file1 to file2.
1362 
1363 int TSystem::Symlink(const char *, const char *)
1364 {
1365  AbstractMethod("Symlink");
1366  return -1;
1367 }
1368 
1369 ////////////////////////////////////////////////////////////////////////////////
1370 /// Unlink, i.e. remove, a file.
1371 ///
1372 /// If the file is currently open by the current or another process, the behavior of this function is
1373 /// implementation-defined (in particular, POSIX systems unlink the file name, while Windows does not allow the
1374 /// file to be deleted and the operation is a no-op).
1375 
1376 int TSystem::Unlink(const char *)
1377 {
1378  AbstractMethod("Unlink");
1379  return -1;
1380 }
1381 
1382 ////////////////////////////////////////////////////////////////////////////////
1383 /// Get info about a file: id, size, flags, modification time.
1384 /// - Id is (statbuf.st_dev << 24) + statbuf.st_ino
1385 /// - Size is the file size
1386 /// - Flags is file type: 0 is regular file, bit 0 set executable,
1387 /// bit 1 set directory, bit 2 set special file
1388 /// (socket, fifo, pipe, etc.)
1389 /// Modtime is modification time.
1390 /// The function returns 0 in case of success and 1 if the file could
1391 /// not be stat'ed.
1392 
1393 int TSystem::GetPathInfo(const char *path, Long_t *id, Long_t *size,
1394  Long_t *flags, Long_t *modtime)
1395 {
1396  Long64_t lsize;
1397 
1398  int res = GetPathInfo(path, id, &lsize, flags, modtime);
1399 
1400  if (res == 0 && size) {
1401  if (sizeof(Long_t) == 4 && lsize > kMaxInt) {
1402  Error("GetPathInfo", "file %s > 2 GB, use GetPathInfo() with Long64_t size", path);
1403  *size = kMaxInt;
1404  } else {
1405  *size = (Long_t)lsize;
1406  }
1407  }
1408 
1409  return res;
1410 }
1411 
1412 ////////////////////////////////////////////////////////////////////////////////
1413 /// Get info about a file: id, size, flags, modification time.
1414 /// - Id is (statbuf.st_dev << 24) + statbuf.st_ino
1415 /// - Size is the file size
1416 /// - Flags is file type: 0 is regular file, bit 0 set executable,
1417 /// bit 1 set directory, bit 2 set special file
1418 /// (socket, fifo, pipe, etc.)
1419 /// Modtime is modification time.
1420 /// The function returns 0 in case of success and 1 if the file could
1421 /// not be stat'ed.
1422 
1423 int TSystem::GetPathInfo(const char *path, Long_t *id, Long64_t *size,
1424  Long_t *flags, Long_t *modtime)
1425 {
1426  FileStat_t buf;
1427 
1428  int res = GetPathInfo(path, buf);
1429 
1430  if (res == 0) {
1431  if (id)
1432  *id = (buf.fDev << 24) + buf.fIno;
1433  if (size)
1434  *size = buf.fSize;
1435  if (modtime)
1436  *modtime = buf.fMtime;
1437  if (flags) {
1438  *flags = 0;
1439  if (buf.fMode & (kS_IXUSR|kS_IXGRP|kS_IXOTH))
1440  *flags |= 1;
1441  if (R_ISDIR(buf.fMode))
1442  *flags |= 2;
1443  if (!R_ISREG(buf.fMode) && !R_ISDIR(buf.fMode))
1444  *flags |= 4;
1445  }
1446  }
1447 
1448  return res;
1449 }
1450 
1451 ////////////////////////////////////////////////////////////////////////////////
1452 /// Get info about a file. Info is returned in the form of a FileStat_t
1453 /// structure (see TSystem.h).
1454 /// The function returns 0 in case of success and 1 if the file could
1455 /// not be stat'ed.
1456 
1457 int TSystem::GetPathInfo(const char *, FileStat_t &)
1458 {
1459  AbstractMethod("GetPathInfo(const char*, FileStat_t&)");
1460  return 1;
1461 }
1462 
1463 ////////////////////////////////////////////////////////////////////////////////
1464 /// Get info about a file system: fs type, block size, number of blocks,
1465 /// number of free blocks.
1466 
1467 int TSystem::GetFsInfo(const char *, Long_t *, Long_t *, Long_t *, Long_t *)
1468 {
1469  AbstractMethod("GetFsInfo");
1470  return 1;
1471 }
1472 
1473 ////////////////////////////////////////////////////////////////////////////////
1474 /// Return a user configured or systemwide directory to create
1475 /// temporary files in.
1476 
1477 const char *TSystem::TempDirectory() const
1478 {
1479  AbstractMethod("TempDirectory");
1480  return nullptr;
1481 }
1482 
1483 ////////////////////////////////////////////////////////////////////////////////
1484 /// Create a secure temporary file by appending a unique
1485 /// 6 letter string to base. The file will be created in
1486 /// a standard (system) directory or in the directory
1487 /// provided in dir. The full filename is returned in base
1488 /// and a filepointer is returned for safely writing to the file
1489 /// (this avoids certain security problems). Returns 0 in case
1490 /// of error.
1491 
1492 FILE *TSystem::TempFileName(TString &, const char *)
1493 {
1494  AbstractMethod("TempFileName");
1495  return nullptr;
1496 }
1497 
1498 ////////////////////////////////////////////////////////////////////////////////
1499 /// Set the file permission bits. Returns -1 in case or error, 0 otherwise.
1500 
1501 int TSystem::Chmod(const char *, UInt_t)
1502 {
1503  AbstractMethod("Chmod");
1504  return -1;
1505 }
1506 
1507 ////////////////////////////////////////////////////////////////////////////////
1508 /// Set the process file creation mode mask.
1509 
1511 {
1512  AbstractMethod("Umask");
1513  return -1;
1514 }
1515 
1516 ////////////////////////////////////////////////////////////////////////////////
1517 /// Set the a files modification and access times. If actime = 0 it will be
1518 /// set to the modtime. Returns 0 on success and -1 in case of error.
1519 
1520 int TSystem::Utime(const char *, Long_t, Long_t)
1521 {
1522  AbstractMethod("Utime");
1523  return -1;
1524 }
1525 
1526 ////////////////////////////////////////////////////////////////////////////////
1527 /// Find location of file in a search path. Return value points to TString for
1528 /// compatibility with Which(const char *, const char *, EAccessMode).
1529 /// Returns 0 in case file is not found.
1530 
1531 const char *TSystem::FindFile(const char *, TString&, EAccessMode)
1532 {
1533  AbstractMethod("FindFile");
1534  return nullptr;
1535 }
1536 
1537 ////////////////////////////////////////////////////////////////////////////////
1538 /// Find location of file in a search path. User must delete returned string.
1539 /// Returns 0 in case file is not found.
1540 
1541 char *TSystem::Which(const char *search, const char *wfil, EAccessMode mode)
1542 {
1543  TString wfilString(wfil);
1544  FindFile(search, wfilString, mode);
1545  if (wfilString.IsNull())
1546  return nullptr;
1547  return StrDup(wfilString.Data());
1548 }
1549 
1550 //---- Users & Groups ----------------------------------------------------------
1551 
1552 ////////////////////////////////////////////////////////////////////////////////
1553 /// Returns the user's id. If user = 0, returns current user's id.
1554 
1555 Int_t TSystem::GetUid(const char * /*user*/)
1556 {
1557  AbstractMethod("GetUid");
1558  return 0;
1559 }
1560 
1561 ////////////////////////////////////////////////////////////////////////////////
1562 /// Returns the effective user id. The effective id corresponds to the
1563 /// set id bit on the file being executed.
1564 
1566 {
1567  AbstractMethod("GetEffectiveUid");
1568  return 0;
1569 }
1570 
1571 ////////////////////////////////////////////////////////////////////////////////
1572 /// Returns the group's id. If group = 0, returns current user's group.
1573 
1574 Int_t TSystem::GetGid(const char * /*group*/)
1575 {
1576  AbstractMethod("GetGid");
1577  return 0;
1578 }
1579 
1580 ////////////////////////////////////////////////////////////////////////////////
1581 /// Returns the effective group id. The effective group id corresponds
1582 /// to the set id bit on the file being executed.
1583 
1585 {
1586  AbstractMethod("GetEffectiveGid");
1587  return 0;
1588 }
1589 
1590 ////////////////////////////////////////////////////////////////////////////////
1591 /// Returns all user info in the UserGroup_t structure. The returned
1592 /// structure must be deleted by the user. In case of error 0 is returned.
1593 
1595 {
1596  AbstractMethod("GetUserInfo");
1597  return nullptr;
1598 }
1599 
1600 ////////////////////////////////////////////////////////////////////////////////
1601 /// Returns all user info in the UserGroup_t structure. If user = 0, returns
1602 /// current user's id info. The returned structure must be deleted by the
1603 /// user. In case of error 0 is returned.
1604 
1605 UserGroup_t *TSystem::GetUserInfo(const char * /*user*/)
1606 {
1607  AbstractMethod("GetUserInfo");
1608  return nullptr;
1609 }
1610 
1611 ////////////////////////////////////////////////////////////////////////////////
1612 /// Returns all group info in the UserGroup_t structure. The only active
1613 /// fields in the UserGroup_t structure for this call are:
1614 /// - fGid and fGroup
1615 /// The returned structure must be deleted by the user. In case of
1616 /// error 0 is returned.
1617 
1619 {
1620  AbstractMethod("GetGroupInfo");
1621  return nullptr;
1622 }
1623 
1624 ////////////////////////////////////////////////////////////////////////////////
1625 /// Returns all group info in the UserGroup_t structure. The only active
1626 /// fields in the UserGroup_t structure for this call are:
1627 /// - fGid and fGroup
1628 /// If group = 0, returns current user's group. The returned structure
1629 /// must be deleted by the user. In case of error 0 is returned.
1630 
1631 UserGroup_t *TSystem::GetGroupInfo(const char * /*group*/)
1632 {
1633  AbstractMethod("GetGroupInfo");
1634  return nullptr;
1635 }
1636 
1637 //---- environment manipulation ------------------------------------------------
1638 
1639 ////////////////////////////////////////////////////////////////////////////////
1640 /// Set environment variable.
1641 
1642 void TSystem::Setenv(const char*, const char*)
1643 {
1644  AbstractMethod("Setenv");
1645 }
1646 
1647 ////////////////////////////////////////////////////////////////////////////////
1648 /// Unset environment variable.
1649 
1650 void TSystem::Unsetenv(const char *name)
1651 {
1652  Setenv(name, "");
1653 }
1654 
1655 ////////////////////////////////////////////////////////////////////////////////
1656 /// Get environment variable.
1657 
1658 const char *TSystem::Getenv(const char*)
1659 {
1660  AbstractMethod("Getenv");
1661  return nullptr;
1662 }
1663 
1664 //---- System Logging ----------------------------------------------------------
1665 
1666 ////////////////////////////////////////////////////////////////////////////////
1667 /// Open connection to system log daemon. For the use of the options and
1668 /// facility see the Unix openlog man page.
1669 
1671 {
1672  AbstractMethod("Openlog");
1673 }
1674 
1675 ////////////////////////////////////////////////////////////////////////////////
1676 /// Send mess to syslog daemon. Level is the logging level and mess the
1677 /// message that will be written on the log.
1678 
1679 void TSystem::Syslog(ELogLevel, const char *)
1680 {
1681  AbstractMethod("Syslog");
1682 }
1683 
1684 ////////////////////////////////////////////////////////////////////////////////
1685 /// Close connection to system log daemon.
1686 
1688 {
1689  AbstractMethod("Closelog");
1690 }
1691 
1692 //---- Standard output redirection ---------------------------------------------
1693 
1694 ////////////////////////////////////////////////////////////////////////////////
1695 /// Redirect standard output (stdout, stderr) to the specified file.
1696 /// If the file argument is 0 the output is set again to stderr, stdout.
1697 /// The second argument specifies whether the output should be added to the
1698 /// file ("a", default) or the file be truncated before ("w").
1699 /// The implementations of this function save internally the current state into
1700 /// a static structure.
1701 ///
1702 /// The call can be made reentrant by specifying the opaque structure pointed
1703 /// by 'h', which is filled with the relevant information. The handle 'h'
1704 /// obtained on the first call must then be used in any subsequent call,
1705 /// included ShowOutput, to display the redirected output.
1706 /// Returns 0 on success, -1 in case of error.
1707 
1708 Int_t TSystem::RedirectOutput(const char *, const char *, RedirectHandle_t *)
1709 {
1710  AbstractMethod("RedirectOutput");
1711  return -1;
1712 }
1713 
1714 ////////////////////////////////////////////////////////////////////////////////
1715 /// Display the content associated with the redirection described by the
1716 /// opaque handle 'h'.
1717 
1719 {
1720  // Check input ...
1721  if (!h) {
1722  Error("ShowOutput", "handle not specified");
1723  return;
1724  }
1725 
1726  // ... and file access
1727  if (gSystem->AccessPathName(h->fFile, kReadPermission)) {
1728  Error("ShowOutput", "file '%s' cannot be read", h->fFile.Data());
1729  return;
1730  }
1731 
1732  // Open the file
1733  FILE *f = nullptr;
1734  if (!(f = fopen(h->fFile.Data(), "r"))) {
1735  Error("ShowOutput", "file '%s' cannot be open", h->fFile.Data());
1736  return;
1737  }
1738 
1739  // Determine the number of bytes to be read from the file.
1740  off_t ltot = lseek(fileno(f), (off_t) 0, SEEK_END);
1741  Int_t begin = (h->fReadOffSet > 0 && h->fReadOffSet < ltot) ? h->fReadOffSet : 0;
1742  lseek(fileno(f), (off_t) begin, SEEK_SET);
1743  Int_t left = ltot - begin;
1744 
1745  // Now readout from file
1746  const Int_t kMAXBUF = 16384;
1747  char buf[kMAXBUF];
1748  Int_t wanted = (left > kMAXBUF-1) ? kMAXBUF-1 : left;
1749  Int_t len;
1750  do {
1751  while ((len = read(fileno(f), buf, wanted)) < 0 &&
1752  TSystem::GetErrno() == EINTR)
1754 
1755  if (len < 0) {
1756  SysError("ShowOutput", "error reading log file");
1757  break;
1758  }
1759 
1760  // Null-terminate
1761  buf[len] = 0;
1762  fprintf(stderr,"%s", buf);
1763 
1764  // Update counters
1765  left -= len;
1766  wanted = (left > kMAXBUF) ? kMAXBUF : left;
1767 
1768  } while (len > 0 && left > 0);
1769 
1770  // Do not display twice the same thing
1771  h->fReadOffSet = ltot;
1772  fclose(f);
1773 }
1774 
1775 //---- Dynamic Loading ---------------------------------------------------------
1776 
1777 ////////////////////////////////////////////////////////////////////////////////
1778 /// Add a new directory to the dynamic path.
1779 
1780 void TSystem::AddDynamicPath(const char *)
1781 {
1782  AbstractMethod("AddDynamicPath");
1783 }
1784 
1785 ////////////////////////////////////////////////////////////////////////////////
1786 /// Return the dynamic path (used to find shared libraries).
1787 
1789 {
1790  AbstractMethod("GetDynamicPath");
1791  return nullptr;
1792 }
1793 
1794 ////////////////////////////////////////////////////////////////////////////////
1795 /// Set the dynamic path to a new value.
1796 /// If the value of 'path' is zero, the dynamic path is reset to its
1797 /// default value.
1798 
1799 void TSystem::SetDynamicPath(const char *)
1800 {
1801  AbstractMethod("SetDynamicPath");
1802 }
1803 
1804 
1805 ////////////////////////////////////////////////////////////////////////////////
1806 /// Figure out if left and right points to the same
1807 /// object in the file system.
1808 
1809 static bool R__MatchFilename(const char *left, const char *right)
1810 {
1811  if (left == right) return kTRUE;
1812 
1813  if (left==0 || right==0) return kFALSE;
1814 
1815  if ( (strcmp(right,left)==0) ) {
1816  return kTRUE;
1817  }
1818 
1819 #ifdef G__WIN32
1820 
1821  char leftname[_MAX_PATH];
1822  char rightname[_MAX_PATH];
1823  _fullpath( leftname, left, _MAX_PATH );
1824  _fullpath( rightname, right, _MAX_PATH );
1825  return ((stricmp(leftname, rightname)==0));
1826 #else
1827  struct stat rightBuf;
1828  struct stat leftBuf;
1829  return ( ( 0 == stat( left, & leftBuf ) )
1830  && ( 0 == stat( right, & rightBuf ) )
1831  && ( leftBuf.st_dev == rightBuf.st_dev ) // Files on same device
1832  && ( leftBuf.st_ino == rightBuf.st_ino ) // Files on same inode (but this is not unique on AFS so we need the next 2 test
1833  && ( leftBuf.st_size == rightBuf.st_size ) // Files of same size
1834  && ( leftBuf.st_mtime == rightBuf.st_mtime ) // Files modified at the same time
1835  );
1836 #endif
1837 }
1838 
1839 
1840 ////////////////////////////////////////////////////////////////////////////////
1841 /// Load a shared library. Returns 0 on successful loading, 1 in
1842 /// case lib was already loaded, -1 in case lib does not exist
1843 /// or in case of error and -2 in case of version mismatch.
1844 /// When entry is specified the loaded lib is
1845 /// searched for this entry point (return -1 when entry does not exist,
1846 /// 0 otherwise). When the system flag is kTRUE, the library is considered
1847 /// a permanent system library that should not be unloaded during the
1848 /// course of the session.
1849 
1850 int TSystem::Load(const char *module, const char *entry, Bool_t system)
1851 {
1852  // don't load libraries that have already been loaded
1853  TString libs( GetLibraries() );
1855 
1856  Ssiz_t idx = l.Last('.');
1857  if (idx != kNPOS) {
1858  l.Remove(idx+1);
1859  }
1860  for (idx = libs.Index(l); idx != kNPOS; idx = libs.Index(l,idx+1)) {
1861  // The libs contains the sub-string 'l', let's make sure it is
1862  // not just part of a larger name.
1863  if (idx == 0 || libs[idx-1] == '/' || libs[idx-1] == '\\') {
1864  Ssiz_t len = libs.Length();
1865  idx += l.Length();
1866  if (!l.EndsWith(".") && libs[idx]=='.')
1867  idx++;
1868  // Skip the soversion.
1869  while (idx < len && isdigit(libs[idx])) {
1870  ++idx;
1871  // No need to test for len here, at worse idx==len and lib[idx]=='\0'
1872  if (libs[idx] == '.') {
1873  ++idx;
1874  }
1875  }
1876  while (idx < len && libs[idx] != '.') {
1877  if (libs[idx] == ' ' || idx+1 == len) {
1878  return 1;
1879  }
1880  ++idx;
1881  }
1882  }
1883  }
1884  if (l[l.Length()-1] == '.') {
1885  l.Remove(l.Length()-1);
1886  }
1887  if (l.BeginsWith("lib")) {
1888  l.Replace(0, 3, "-l");
1889  for(idx = libs.Index(l); idx != kNPOS; idx = libs.Index(l,idx+1)) {
1890  if ((idx == 0 || libs[idx-1] == ' ') &&
1891  (libs[idx+l.Length()] == ' ' || libs[idx+l.Length()] == 0)) {
1892  return 1;
1893  }
1894  }
1895  }
1896 
1897  char *path = DynamicPathName(module);
1898 
1899  int ret = -1;
1900  if (path) {
1901  // load any dependent libraries
1902  TString deplibs = gInterpreter->GetSharedLibDeps(path);
1903  if (!deplibs.IsNull()) {
1904  TString delim(" ");
1905  TObjArray *tokens = deplibs.Tokenize(delim);
1906  for (Int_t i = tokens->GetEntriesFast()-1; i > 0; i--) {
1907  const char *deplib = ((TObjString*)tokens->At(i))->GetName();
1908  if (strcmp(module,deplib)==0) {
1909  continue;
1910  }
1911  if (gDebug > 0)
1912  Info("Load", "loading dependent library %s for library %s",
1913  deplib, ((TObjString*)tokens->At(0))->GetName());
1914  if ((ret = Load(deplib, "", system)) < 0) {
1915  delete tokens;
1916  delete [] path;
1917  return ret;
1918  }
1919  }
1920  delete tokens;
1921  }
1922  if (!system) {
1923  // Mark the library in $ROOTSYS/lib as system.
1924  TString dirname = GetDirName(path);
1925  system = R__MatchFilename(TROOT::GetLibDir(), dirname.Data());
1926 
1927  if (!system) {
1928  system = R__MatchFilename(TROOT::GetBinDir(), dirname.Data());
1929  }
1930  }
1931 
1934  gLibraryVersionMax *= 2;
1936  }
1937  ret = gInterpreter->Load(path, system);
1938  if (ret < 0) ret = -1;
1939  if (gDebug > 0)
1940  Info("Load", "loaded library %s, status %d", path, ret);
1941  if (ret == 0 && gLibraryVersion[gLibraryVersionIdx]) {
1943  Error("Load", "version mismatch, %s = %d, ROOT = %d",
1944  path, v, gROOT->GetVersionInt());
1945  ret = -2;
1947  }
1949  delete [] path;
1950  }
1951 
1952  if (!entry || !entry[0] || ret < 0) return ret;
1953 
1954  Func_t f = DynFindSymbol(module, entry);
1955  if (f) return 0;
1956  return -1;
1957 }
1958 
1959 ///////////////////////////////////////////////////////////////////////////////
1960 /// Load all libraries known to ROOT via the rootmap system.
1961 /// Returns the number of top level libraries successfully loaded.
1962 
1964 {
1965  UInt_t nlibs = 0;
1966 
1967  TEnv* mapfile = gInterpreter->GetMapfile();
1968  if (!mapfile || !mapfile->GetTable()) return 0;
1969 
1970  std::set<std::string> loadedlibs;
1971  std::set<std::string> failedlibs;
1972 
1973  TEnvRec* rec = 0;
1974  TIter iEnvRec(mapfile->GetTable());
1975  while ((rec = (TEnvRec*) iEnvRec())) {
1976  TString libs = rec->GetValue();
1977  TString lib;
1978  Ssiz_t pos = 0;
1979  while (libs.Tokenize(lib, pos)) {
1980  // check that none of the libs failed to load
1981  if (failedlibs.find(lib.Data()) != failedlibs.end()) {
1982  // don't load it or any of its dependencies
1983  libs = "";
1984  break;
1985  }
1986  }
1987  pos = 0;
1988  while (libs.Tokenize(lib, pos)) {
1989  // ignore libCore - it's already loaded
1990  if (lib.BeginsWith("libCore"))
1991  continue;
1992 
1993  if (loadedlibs.find(lib.Data()) == loadedlibs.end()) {
1994  // just load the first library - TSystem will do the rest.
1995  auto res = gSystem->Load(lib);
1996  if (res >=0) {
1997  if (res == 0) ++nlibs;
1998  loadedlibs.insert(lib.Data());
1999  } else {
2000  failedlibs.insert(lib.Data());
2001  }
2002  }
2003  }
2004  }
2005  return nlibs;
2006 }
2007 
2008 ////////////////////////////////////////////////////////////////////////////////
2009 /// Find a dynamic library called lib using the system search paths.
2010 /// Appends known extensions if needed. Returned string must be deleted
2011 /// by the user!
2012 
2013 char *TSystem::DynamicPathName(const char *lib, Bool_t quiet /*=kFALSE*/)
2014 {
2015  TString sLib(lib);
2016  if (FindDynamicLibrary(sLib, quiet))
2017  return StrDup(sLib);
2018  return nullptr;
2019 }
2020 
2021 ////////////////////////////////////////////////////////////////////////////////
2022 /// Find a dynamic library using the system search paths. lib will be updated
2023 /// to contain the absolute filename if found. Returns lib if found, or NULL
2024 /// if a library called lib was not found.
2025 /// This function does not open the library.
2026 
2028 {
2029  AbstractMethod("FindDynamicLibrary");
2030  return nullptr;
2031 }
2032 
2033 ////////////////////////////////////////////////////////////////////////////////
2034 /// Find specific entry point in specified library. Specify "*" for lib
2035 /// to search in all libraries.
2036 
2037 Func_t TSystem::DynFindSymbol(const char * /*lib*/, const char *entry)
2038 {
2039  return (Func_t) gInterpreter->FindSym(entry);
2040 }
2041 
2042 ////////////////////////////////////////////////////////////////////////////////
2043 /// Unload a shared library.
2044 
2045 void TSystem::Unload(const char *module)
2046 {
2047  char *path;
2048  if ((path = DynamicPathName(module))) {
2049  gInterpreter->UnloadFile(path);
2050  delete [] path;
2051  }
2052 }
2053 
2054 ////////////////////////////////////////////////////////////////////////////////
2055 /// List symbols in a shared library.
2056 
2057 void TSystem::ListSymbols(const char *, const char *)
2058 {
2059  AbstractMethod("ListSymbols");
2060 }
2061 
2062 ////////////////////////////////////////////////////////////////////////////////
2063 /// List all loaded shared libraries. Regexp is a wildcard expression,
2064 /// see TRegexp::MakeWildcard.
2065 
2066 void TSystem::ListLibraries(const char *regexp)
2067 {
2068  TString libs = GetLibraries(regexp);
2069  TRegexp separator("[^ \\t\\s]+");
2070  TString s;
2071  Ssiz_t start = 0, index = 0, end = 0;
2072  int i = 0;
2073 
2074  Printf(" ");
2075  Printf("Loaded shared libraries");
2076  Printf("=======================");
2077 
2078  while ((start < libs.Length()) && (index != kNPOS)) {
2079  index = libs.Index(separator, &end, start);
2080  if (index >= 0) {
2081  s = libs(index, end);
2082  if (s.BeginsWith("-")) {
2083  if (s.BeginsWith("-l")) {
2084  Printf("%s", s.Data());
2085  i++;
2086  }
2087  } else {
2088  Printf("%s", s.Data());
2089  i++;
2090  }
2091  }
2092  start += end+1;
2093  }
2094 
2095  Printf("-----------------------");
2096  Printf("%d libraries loaded", i);
2097  Printf("=======================");
2098 }
2099 
2100 ////////////////////////////////////////////////////////////////////////////////
2101 /// Return the thread local storage for the custom last error message
2102 
2104 {
2105  TTHREAD_TLS_DECL( TString, gLastErrorString);
2106  return gLastErrorString;
2107 }
2108 
2109 ////////////////////////////////////////////////////////////////////////////////
2110 /// Return the thread local storage for the custom last error message
2111 
2113 {
2114  return const_cast<TSystem*>(this)->GetLastErrorString();
2115 }
2116 
2117 ////////////////////////////////////////////////////////////////////////////////
2118 /// Get list of shared libraries loaded at the start of the executable.
2119 /// Returns 0 in case list cannot be obtained or in case of error.
2120 
2122 {
2123  return nullptr;
2124 }
2125 
2126 ////////////////////////////////////////////////////////////////////////////////
2127 /// Return a space separated list of loaded shared libraries.
2128 /// Regexp is a wildcard expression, see TRegexp::MakeWildcard.
2129 /// This list is of a format suitable for a linker, i.e it may contain
2130 /// -Lpathname and/or -lNameOfLib.
2131 /// Option can be any of:
2132 /// - S: shared libraries loaded at the start of the executable, because
2133 /// they were specified on the link line.
2134 /// - D: shared libraries dynamically loaded after the start of the program.
2135 /// - L: this option is ignored, and available for backward compatibility.
2136 
2137 const char *TSystem::GetLibraries(const char *regexp, const char *options,
2138  Bool_t isRegexp)
2139 {
2140  fListLibs.Clear();
2141 
2142  TString libs;
2143  TString opt(options);
2144  Bool_t so2dylib = (opt.First('L') != kNPOS);
2145  if (so2dylib)
2146  opt.ReplaceAll("L", "");
2147 
2148  if (opt.IsNull() || opt.First('D') != kNPOS)
2149  libs += gInterpreter->GetSharedLibs();
2150 
2151  // Cint currently register all libraries that
2152  // are loaded and have a dictionary in them, this
2153  // includes all the libraries that are included
2154  // in the list of (hard) linked libraries.
2155 
2156  TString slinked;
2157  const char *linked;
2158  if ((linked = GetLinkedLibraries())) {
2159  if (fLinkedLibs != LINKEDLIBS) {
2160  // This is not the default value, we need to keep the custom part.
2161  TString custom = fLinkedLibs;
2162  custom.ReplaceAll(LINKEDLIBS,linked);
2163  if (custom == fLinkedLibs) {
2164  // no replacement done, let's append linked
2165  slinked.Append(linked);
2166  slinked.Append(" ");
2167  }
2168  slinked.Append(custom);
2169  } else {
2170  slinked.Append(linked);
2171  }
2172  } else {
2173  slinked.Append(fLinkedLibs);
2174  }
2175 
2176  if (opt.IsNull() || opt.First('S') != kNPOS) {
2177  // We are done, the statically linked libraries are already included.
2178  if (libs.Length() == 0) {
2179  libs = slinked;
2180  } else {
2181  // We need to add the missing linked library
2182 
2183  static TString lastLinked;
2184  static TString lastAddMissing;
2185  if ( lastLinked != slinked ) {
2186  // Recalculate only if there was a change.
2187  static TRegexp separator("[^ \\t\\s]+");
2188  lastLinked = slinked;
2189  lastAddMissing.Clear();
2190 
2191  Ssiz_t start, index, end;
2192  start = index = end = 0;
2193 
2194  while ((start < slinked.Length()) && (index != kNPOS)) {
2195  index = slinked.Index(separator,&end,start);
2196  if (index >= 0) {
2197  TString sub = slinked(index,end);
2198  if (sub[0]=='-' && sub[1]=='L') {
2199  lastAddMissing.Prepend(" ");
2200  lastAddMissing.Prepend(sub);
2201  } else {
2202  if (libs.Index(sub) == kNPOS) {
2203  lastAddMissing.Prepend(" ");
2204  lastAddMissing.Prepend(sub);
2205  }
2206  }
2207  }
2208  start += end+1;
2209  }
2210  }
2211  libs.Prepend(lastAddMissing);
2212  }
2213  } else if (libs.Length() != 0) {
2214  // Let remove the statically linked library
2215  // from the list.
2216  static TRegexp separator("[^ \\t\\s]+");
2217  Ssiz_t start, index, end;
2218  start = index = end = 0;
2219 
2220  while ((start < slinked.Length()) && (index != kNPOS)) {
2221  index = slinked.Index(separator,&end,start);
2222  if (index >= 0) {
2223  TString sub = slinked(index,end);
2224  if (sub[0]!='-' && sub[1]!='L') {
2225  libs.ReplaceAll(sub,"");
2226  }
2227  }
2228  start += end+1;
2229  }
2230  libs = libs.Strip(TString::kBoth);
2231  }
2232 
2233  // Select according to regexp
2234  if (regexp && *regexp) {
2235  static TRegexp separator("[^ \\t\\s]+");
2236  TRegexp user_re(regexp, kTRUE);
2237  TString s;
2238  Ssiz_t start, index, end;
2239  start = index = end = 0;
2240 
2241  while ((start < libs.Length()) && (index != kNPOS)) {
2242  index = libs.Index(separator,&end,start);
2243  if (index >= 0) {
2244  s = libs(index,end);
2245  if ((isRegexp && s.Index(user_re) != kNPOS) ||
2246  (!isRegexp && s.Index(regexp) != kNPOS)) {
2247  if (!fListLibs.IsNull())
2248  fListLibs.Append(" ");
2249  fListLibs.Append(s);
2250  }
2251  }
2252  start += end+1;
2253  }
2254  } else
2255  fListLibs = libs;
2256 
2257 #if defined(R__MACOSX)
2258 // We need to remove the libraries that are dynamically loaded and not linked
2259 {
2260  TString libs2 = fListLibs;
2261  TString maclibs;
2262 
2263  static TRegexp separator("[^ \\t\\s]+");
2264  static TRegexp dynload("/lib-dynload/");
2265 
2266  Ssiz_t start, index, end;
2267  start = index = end = 0;
2268 
2269  while ((start < libs2.Length()) && (index != kNPOS)) {
2270  index = libs2.Index(separator, &end, start);
2271  if (index >= 0) {
2272  TString s = libs2(index, end);
2273  if (s.Index(dynload) == kNPOS) {
2274  if (!maclibs.IsNull()) maclibs.Append(" ");
2275  maclibs.Append(s);
2276  }
2277  }
2278  start += end+1;
2279  }
2280  fListLibs = maclibs;
2281 }
2282 #endif
2283 
2284  return fListLibs.Data();
2285 }
2286 
2287 //---- RPC ---------------------------------------------------------------------
2288 
2289 ////////////////////////////////////////////////////////////////////////////////
2290 /// Get Internet Protocol (IP) address of host.
2291 
2293 {
2294  AbstractMethod("GetHostByName");
2295  return TInetAddress();
2296 }
2297 
2298 ////////////////////////////////////////////////////////////////////////////////
2299 /// Get Internet Protocol (IP) address of remote host and port #.
2300 
2302 {
2303  AbstractMethod("GetPeerName");
2304  return TInetAddress();
2305 }
2306 
2307 ////////////////////////////////////////////////////////////////////////////////
2308 /// Get Internet Protocol (IP) address of host and port #.
2309 
2311 {
2312  AbstractMethod("GetSockName");
2313  return TInetAddress();
2314 }
2315 
2316 ////////////////////////////////////////////////////////////////////////////////
2317 /// Get port # of internet service.
2318 
2319 int TSystem::GetServiceByName(const char *)
2320 {
2321  AbstractMethod("GetServiceByName");
2322  return -1;
2323 }
2324 
2325 ////////////////////////////////////////////////////////////////////////////////
2326 /// Get name of internet service.
2327 
2329 {
2330  AbstractMethod("GetServiceByPort");
2331  return nullptr;
2332 }
2333 
2334 ////////////////////////////////////////////////////////////////////////////////
2335 /// Open a connection to another host.
2336 
2337 int TSystem::OpenConnection(const char*, int, int, const char*)
2338 {
2339  AbstractMethod("OpenConnection");
2340  return -1;
2341 }
2342 
2343 ////////////////////////////////////////////////////////////////////////////////
2344 /// Announce TCP/IP service.
2345 
2347 {
2348  AbstractMethod("AnnounceTcpService");
2349  return -1;
2350 }
2351 
2352 ////////////////////////////////////////////////////////////////////////////////
2353 /// Announce UDP service.
2354 
2356 {
2357  AbstractMethod("AnnounceUdpService");
2358  return -1;
2359 }
2360 
2361 ////////////////////////////////////////////////////////////////////////////////
2362 /// Announce unix domain service.
2363 
2365 {
2366  AbstractMethod("AnnounceUnixService");
2367  return -1;
2368 }
2369 
2370 ////////////////////////////////////////////////////////////////////////////////
2371 /// Announce unix domain service.
2372 
2373 int TSystem::AnnounceUnixService(const char *, int)
2374 {
2375  AbstractMethod("AnnounceUnixService");
2376  return -1;
2377 }
2378 
2379 ////////////////////////////////////////////////////////////////////////////////
2380 /// Accept a connection.
2381 
2383 {
2384  AbstractMethod("AcceptConnection");
2385  return -1;
2386 }
2387 
2388 ////////////////////////////////////////////////////////////////////////////////
2389 /// Close socket connection.
2390 
2392 {
2393  AbstractMethod("CloseConnection");
2394 }
2395 
2396 ////////////////////////////////////////////////////////////////////////////////
2397 /// Receive exactly length bytes into buffer. Use opt to receive out-of-band
2398 /// data or to have a peek at what is in the buffer (see TSocket).
2399 
2400 int TSystem::RecvRaw(int, void *, int, int)
2401 {
2402  AbstractMethod("RecvRaw");
2403  return -1;
2404 }
2405 
2406 ////////////////////////////////////////////////////////////////////////////////
2407 /// Send exactly length bytes from buffer. Use opt to send out-of-band
2408 /// data (see TSocket).
2409 
2410 int TSystem::SendRaw(int, const void *, int, int)
2411 {
2412  AbstractMethod("SendRaw");
2413  return -1;
2414 }
2415 
2416 ////////////////////////////////////////////////////////////////////////////////
2417 /// Receive a buffer headed by a length indicator.
2418 
2419 int TSystem::RecvBuf(int, void *, int)
2420 {
2421  AbstractMethod("RecvBuf");
2422  return -1;
2423 }
2424 
2425 ////////////////////////////////////////////////////////////////////////////////
2426 /// Send a buffer headed by a length indicator.
2427 
2428 int TSystem::SendBuf(int, const void *, int)
2429 {
2430  AbstractMethod("SendBuf");
2431  return -1;
2432 }
2433 
2434 ////////////////////////////////////////////////////////////////////////////////
2435 /// Set socket option.
2436 
2437 int TSystem::SetSockOpt(int, int, int)
2438 {
2439  AbstractMethod("SetSockOpt");
2440  return -1;
2441 }
2442 
2443 ////////////////////////////////////////////////////////////////////////////////
2444 /// Get socket option.
2445 
2446 int TSystem::GetSockOpt(int, int, int*)
2447 {
2448  AbstractMethod("GetSockOpt");
2449  return -1;
2450 }
2451 
2452 //---- System, CPU and Memory info ---------------------------------------------
2453 
2454 ////////////////////////////////////////////////////////////////////////////////
2455 /// Returns static system info, like OS type, CPU type, number of CPUs
2456 /// RAM size, etc into the SysInfo_t structure. Returns -1 in case of error,
2457 /// 0 otherwise.
2458 
2460 {
2461  AbstractMethod("GetSysInfo");
2462  return -1;
2463 }
2464 
2465 ////////////////////////////////////////////////////////////////////////////////
2466 /// Returns cpu load average and load info into the CpuInfo_t structure.
2467 /// Returns -1 in case of error, 0 otherwise. Use sampleTime to set the
2468 /// interval over which the CPU load will be measured, in ms (default 1000).
2469 
2471 {
2472  AbstractMethod("GetCpuInfo");
2473  return -1;
2474 }
2475 
2476 ////////////////////////////////////////////////////////////////////////////////
2477 /// Returns ram and swap memory usage info into the MemInfo_t structure.
2478 /// Returns -1 in case of error, 0 otherwise.
2479 
2481 {
2482  AbstractMethod("GetMemInfo");
2483  return -1;
2484 }
2485 
2486 ////////////////////////////////////////////////////////////////////////////////
2487 /// Returns cpu and memory used by this process into the ProcInfo_t structure.
2488 /// Returns -1 in case of error, 0 otherwise.
2489 
2491 {
2492  AbstractMethod("GetProcInfo");
2493  return -1;
2494 }
2495 
2496 //---- Script Compiler ---------------------------------------------------------
2497 
2498 void AssignAndDelete(TString& target, char *tobedeleted)
2499 {
2500  // Assign the char* value to the TString and then delete it.
2501 
2502  target = tobedeleted;
2503  delete [] tobedeleted;
2504 }
2505 
2506 #ifdef WIN32
2507 
2508 static TString R__Exec(const char *cmd)
2509 {
2510  // Execute a command and return the stdout in a string.
2511 
2512  FILE * f = gSystem->OpenPipe(cmd,"r");
2513  if (!f) {
2514  return "";
2515  }
2516  TString result;
2517 
2518  char x;
2519  while ((x = fgetc(f))!=EOF ) {
2520  if (x=='\n' || x=='\r') break;
2521  result += x;
2522  }
2523 
2524  fclose(f);
2525  return result;
2526 }
2527 
2528 static void R__FixLink(TString &cmd)
2529 {
2530  // Replace the call to 'link' by a full path name call based on where cl.exe is.
2531  // This prevents us from using inadvertently the link.exe provided by cygwin.
2532 
2533  // check if link is the microsoft one...
2534  TString res = R__Exec("link 2>&1");
2535  if (res.Length()) {
2536  if (res.Contains("Microsoft (R) Incremental Linker"))
2537  return;
2538  }
2539  // else check availability of cygpath...
2540  res = R__Exec("cygpath . 2>&1");
2541  if (res.Length()) {
2542  if (res != ".")
2543  return;
2544  }
2545 
2546  res = R__Exec("which cl.exe 2>&1|grep cl|sed 's,cl\\.exe$,link\\.exe,' 2>&1");
2547  if (res.Length()) {
2548  res = R__Exec(Form("cygpath -w '%s' 2>&1",res.Data()));
2549  if (res.Length()) {
2550  cmd.ReplaceAll(" link ",Form(" \"%s\" ",res.Data()));
2551  }
2552  }
2553 }
2554 #endif
2555 
2556 #if defined(__CYGWIN__)
2557 static void R__AddPath(TString &target, const TString &path) {
2558  if (path.Length() > 2 && path[1]==':') {
2559  target += TString::Format("/cygdrive/%c",path[0]) + path(2,path.Length()-2);
2560  } else {
2561  target += path;
2562  }
2563 }
2564 #else
2565 static void R__AddPath(TString &target, const TString &path) {
2566  target += path;
2567 }
2568 #endif
2569 
2570 static void R__WriteDependencyFile(const TString & build_loc, const TString &depfilename, const TString &filename, const TString &library, const TString &libname,
2571  const TString &extension, const char *version_var_prefix, const TString &includes, const TString &defines, const TString &incPath)
2572 {
2573  // Generate the dependency via standard output, not searching the
2574  // standard include directories,
2575 
2576 #ifndef WIN32
2577  const char * stderrfile = "/dev/null";
2578 #else
2579  TString stderrfile;
2580  AssignAndDelete( stderrfile, gSystem->ConcatFileName(build_loc,"stderr.tmp") );
2581 #endif
2582  TString bakdepfilename = depfilename + ".bak";
2583 
2584 #ifdef WIN32
2585  TString touch = "echo # > "; touch += "\"" + depfilename + "\"";
2586 #else
2587  TString touch = "echo > "; touch += "\"" + depfilename + "\"";
2588 #endif
2589  TString builddep = "rmkdepend";
2591  builddep += " \"-f";
2592  builddep += depfilename;
2593  builddep += "\" -o_" + extension + "." + gSystem->GetSoExt() + " ";
2594  if (build_loc.BeginsWith(gSystem->WorkingDirectory())) {
2595  Int_t len = strlen(gSystem->WorkingDirectory());
2596  if ( build_loc.Length() > (len+1) ) {
2597  builddep += " \"-p";
2598  if (build_loc[len] == '/' || build_loc[len+1] != '\\' ) {
2599  // Since the path is now ran through TSystem::ExpandPathName the single \ is also possible.
2600  R__AddPath(builddep, build_loc.Data() + len + 1 );
2601  } else {
2602  // Case of dir\\name
2603  R__AddPath(builddep, build_loc.Data() + len + 2 );
2604  }
2605  builddep += "/\" ";
2606  }
2607  } else {
2608  builddep += " \"-p";
2609  R__AddPath(builddep, build_loc);
2610  builddep += "/\" ";
2611  }
2612  builddep += " -Y -- ";
2613  TString rootsysInclude = TROOT::GetIncludeDir();
2614  builddep += " \"-I"+rootsysInclude+"\" "; // cflags
2615  builddep += includes;
2616  builddep += defines;
2617  builddep += " -- \"";
2618  builddep += filename;
2619  builddep += "\" ";
2620  TString targetname;
2621  if (library.BeginsWith(gSystem->WorkingDirectory())) {
2622  Int_t len = strlen(gSystem->WorkingDirectory());
2623  if ( library.Length() > (len+1) ) {
2624  if (library[len] == '/' || library[len+1] != '\\' ) {
2625  targetname = library.Data() + len + 1;
2626  } else {
2627  targetname = library.Data() + len + 2;
2628  }
2629  } else {
2630  targetname = library;
2631  }
2632  } else {
2633  targetname = library;
2634  }
2635  builddep += " \"";
2636  builddep += "-t";
2637  R__AddPath(builddep, targetname);
2638  builddep += "\" > ";
2639  builddep += stderrfile;
2640  builddep += " 2>&1 ";
2641 
2642  TString adddictdep = "echo ";
2643  R__AddPath(adddictdep,targetname);
2644  adddictdep += ": ";
2645 #if defined(R__HAS_CLING_DICTVERSION)
2646  {
2647  char *clingdictversion = gSystem->Which(incPath,"clingdictversion.h");
2648  if (clingdictversion) {
2649  R__AddPath(adddictdep,clingdictversion);
2650  adddictdep += " ";
2651  delete [] clingdictversion;
2652  } else {
2653  R__AddPath(adddictdep,rootsysInclude+"/clingdictversion.h ");
2654  }
2655  }
2656 #endif
2657  {
2658  const char *dictHeaders[] = { "RVersion.h", "RConfig.h", "TClass.h",
2659  "TDictAttributeMap.h","TInterpreter.h","TROOT.h","TBuffer.h",
2660  "TMemberInspector.h","TError.h","RtypesImp.h","TIsAProxy.h",
2661  "TFileMergeInfo.h","TCollectionProxyInfo.h"};
2662 
2663  for (unsigned int h=0; h < sizeof(dictHeaders)/sizeof(dictHeaders[0]); ++h)
2664  {
2665  char *rootVersion = gSystem->Which(incPath,dictHeaders[h]);
2666  if (rootVersion) {
2667  R__AddPath(adddictdep,rootVersion);
2668  delete [] rootVersion;
2669  } else {
2670  R__AddPath(adddictdep,rootsysInclude + "/" + dictHeaders[h]);
2671  }
2672  adddictdep += " ";
2673  }
2674  }
2675  {
2676  // Add dependency on rootcling.
2677  char *rootCling = gSystem->Which(gSystem->Getenv("PATH"),"rootcling");
2678  if (rootCling) {
2679  R__AddPath(adddictdep,rootCling);
2680  adddictdep += " ";
2681  delete [] rootCling;
2682  }
2683  }
2684  adddictdep += " >> \""+depfilename+"\"";
2685 
2686  TString addversiondep( "echo ");
2687  addversiondep += libname + version_var_prefix + " \"" + ROOT_RELEASE + "\" >> \""+depfilename+"\"";
2688 
2689  if (gDebug > 4) {
2690  ::Info("ACLiC", "%s", touch.Data());
2691  ::Info("ACLiC", "%s", builddep.Data());
2692  ::Info("ACLiC", "%s", adddictdep.Data());
2693  }
2694 
2695  Int_t depbuilt = !gSystem->Exec(touch);
2696  if (depbuilt) depbuilt = !gSystem->Exec(builddep);
2697  if (depbuilt) depbuilt = !gSystem->Exec(adddictdep);
2698  if (depbuilt) depbuilt = !gSystem->Exec(addversiondep);
2699 
2700  if (!depbuilt) {
2701  ::Warning("ACLiC","Failed to generate the dependency file for %s",
2702  library.Data());
2703  } else {
2704 #ifdef WIN32
2705  gSystem->Unlink(stderrfile);
2706 #endif
2707  gSystem->Unlink(bakdepfilename);
2708  }
2709 }
2710 
2711 ////////////////////////////////////////////////////////////////////////////////
2712 /// This method compiles and loads a shared library containing
2713 /// the code from the file "filename".
2714 ///
2715 /// The return value is true (1) in case of success and false (0)
2716 /// in case of error.
2717 ///
2718 /// The possible options are:
2719 /// - k : keep the shared library after the session end.
2720 /// - f : force recompilation.
2721 /// - g : compile with debug symbol
2722 /// - O : optimized the code
2723 /// - c : compile only, do not attempt to load the library.
2724 /// - s : silence all informational output
2725 /// - v : output all information output
2726 /// - d : debug ACLiC, keep all the output files.
2727 /// - - : if buildir is set, use a flat structure (see buildir below)
2728 ///
2729 /// If library_specified is specified, CompileMacro generates the file
2730 /// "library_specified".soext where soext is the shared library extension for
2731 /// the current platform.
2732 ///
2733 /// If build_dir is specified, it is used as an alternative 'root' for the
2734 /// generation of the shared library. The library is stored in a sub-directories
2735 /// of 'build_dir' including the full pathname of the script unless a flat
2736 /// directory structure is requested ('-' option). With the '-' option the libraries
2737 /// are created directly in the directory 'build_dir'; in particular this means that
2738 /// 2 scripts with the same name in different source directory will over-write each
2739 /// other's library.
2740 /// See also TSystem::SetBuildDir.
2741 ///
2742 /// If dirmode is not zero and we need to create the target directory, the
2743 /// file mode bit will be change to 'dirmode' using chmod.
2744 ///
2745 /// If library_specified is not specified, CompileMacro generate a default name
2746 /// for library by taking the name of the file "filename" but replacing the
2747 /// dot before the extension by an underscore and by adding the shared
2748 /// library extension for the current platform.
2749 /// For example on most platform, hsimple.cxx will generate hsimple_cxx.so
2750 ///
2751 /// It uses the directive fMakeSharedLibs to create a shared library.
2752 /// If loading the shared library fails, it tries to output a list of missing
2753 /// symbols by creating an executable (on some platforms like OSF, this does
2754 /// not HAVE to be an executable) containing the script. It uses the
2755 /// directive fMakeExe to do so.
2756 /// For both directives, before passing them to TSystem::Exec, it expands the
2757 /// variables $SourceFiles, $SharedLib, $LibName, $IncludePath, $LinkedLibs,
2758 /// $DepLibs, $ExeName and $ObjectFiles. See SetMakeSharedLib() for more
2759 /// information on those variables.
2760 ///
2761 /// This method is used to implement the following feature:
2762 ///
2763 /// Synopsis:
2764 ///
2765 /// The purpose of this addition is to allow the user to use an external
2766 /// compiler to create a shared library from its C++ macro (scripts).
2767 /// Currently in order to execute a script, a user has to type at the root
2768 /// prompt
2769 /// ~~~ {.cpp}
2770 /// .X myfunc.C(arg1,arg2)
2771 /// ~~~
2772 /// We allow them to type:
2773 /// ~~~ {.cpp}
2774 /// .X myfunc.C++(arg1,arg2)
2775 /// ~~~
2776 /// or
2777 /// ~~~ {.cpp}
2778 /// .X myfunc.C+(arg1,arg2)
2779 /// ~~~
2780 /// In which case an external compiler will be called to create a shared
2781 /// library. This shared library will then be loaded and the function
2782 /// myfunc will be called with the two arguments. With '++' the shared library
2783 /// is always recompiled. With '+' the shared library is recompiled only
2784 /// if it does not exist yet or the macro file is newer than the shared
2785 /// library.
2786 ///
2787 /// Of course the + and ++ notation is supported in similar way for .x and .L.
2788 ///
2789 /// Through the function TSystem::SetMakeSharedLib(), the user will be able to
2790 /// indicate, with shell commands, how to build a shared library (a good
2791 /// default will be provided). The most common change, namely where to find
2792 /// header files, will be available through the function
2793 /// TSystem::SetIncludePath().
2794 /// A good default will be provided so that a typical user session should be at
2795 /// most:
2796 /// ~~~ {.cpp}
2797 /// root[1] gSystem->SetIncludePath("-I$ROOTSYS/include
2798 /// -I$HOME/mypackage/include");
2799 /// root[2] .x myfunc.C++(10,20);
2800 /// ~~~
2801 /// The user may sometimes try to compile a script before it has loaded all the
2802 /// needed shared libraries. In this case we want to be helpfull and output a
2803 /// list of the unresolved symbols. So if the loading of the created shared
2804 /// library fails, we will try to build a executable that contains the
2805 /// script. The linker should then output a list of missing symbols.
2806 ///
2807 /// To support this we provide a TSystem::SetMakeExe() function, that sets the
2808 /// directive telling how to create an executable. The loader will need
2809 /// to be informed of all the libraries available. The information about
2810 /// the libraries that has been loaded by .L and TSystem::Load() is accesible
2811 /// to the script compiler. However, the information about
2812 /// the libraries that have been selected at link time by the application
2813 /// builder (like the root libraries for root.exe) are not available and need
2814 /// to be explicitly listed in fLinkedLibs (either by default or by a call to
2815 /// TSystem::SetLinkedLibs()).
2816 ///
2817 /// To simplify customization we could also add to the .rootrc support for the
2818 /// variables
2819 /// ~~~ {.cpp}
2820 /// Unix.*.Root.IncludePath: -I$ROOTSYS/include
2821 /// WinNT.*.Root.IncludePath: -I%ROOTSYS%/include
2822 ///
2823 /// Unix.*.Root.LinkedLibs: -L$ROOTSYS/lib -lBase ....
2824 /// WinNT.*.Root.LinkedLibs: %ROOTSYS%/lib/*.lib msvcrt.lib ....
2825 /// ~~~
2826 /// And also support for MakeSharedLibs() and MakeExe().
2827 ///
2828 /// (the ... have to be replaced by the actual values and are here only to
2829 /// shorten this comment).
2830 
2831 int TSystem::CompileMacro(const char *filename, Option_t *opt,
2832  const char *library_specified,
2833  const char *build_dir,
2834  UInt_t dirmode)
2835 {
2836  static const char *version_var_prefix = "__ROOTBUILDVERSION=";
2837 
2838  // ======= Analyze the options
2839  Bool_t keep = kFALSE;
2840  Bool_t recompile = kFALSE;
2841  EAclicMode mode = fAclicMode;
2842  Bool_t loadLib = kTRUE;
2843  Bool_t withInfo = kTRUE;
2844  Bool_t verbose = kFALSE;
2845  Bool_t internalDebug = kFALSE;
2846  if (opt) {
2847  keep = (strchr(opt,'k')!=0);
2848  recompile = (strchr(opt,'f')!=0);
2849  if (strchr(opt,'O')!=0) {
2850  mode = kOpt;
2851  }
2852  if (strchr(opt,'g')!=0) {
2853  mode = kDebug;
2854  }
2855  if (strchr(opt,'c')!=0) {
2856  loadLib = kFALSE;
2857  }
2858  withInfo = strchr(opt, 's') == nullptr;
2859  verbose = strchr(opt, 'v') != nullptr;
2860  internalDebug = strchr(opt, 'd') != nullptr;
2861  }
2862  if (mode==kDefault) {
2863  TString rootbuild = ROOTBUILD;
2864  if (rootbuild.Index("debug",0,TString::kIgnoreCase)==kNPOS) {
2865  mode=kOpt;
2866  } else {
2867  mode=kDebug;
2868  }
2869  }
2870  UInt_t verboseLevel = verbose ? 7 : gDebug;
2871  Bool_t flatBuildDir = (fAclicProperties & kFlatBuildDir) || (strchr(opt,'-')!=0);
2872 
2873  // if non-zero, build_loc indicates where to build the shared library.
2874  TString build_loc = ExpandFileName(GetBuildDir());
2875  if (build_dir && strlen(build_dir)) build_loc = build_dir;
2876  if (build_loc == ".") {
2877  build_loc = WorkingDirectory();
2878  } else if (build_loc.Length() && (!IsAbsoluteFileName(build_loc)) ) {
2879  AssignAndDelete( build_loc , ConcatFileName( WorkingDirectory(), build_loc ) );
2880  }
2881 
2882  // Get the include directory list in the dir1:dir2:dir3 format
2883  // [Used for generating the .d file and to look for header files for
2884  // the linkdef file]
2885  TString incPath = GetIncludePath(); // of the form -Idir1 -Idir2 -Idir3
2886  incPath.Append(":").Prepend(" ");
2887  if (gEnv) {
2888  TString fromConfig = gEnv->GetValue("ACLiC.IncludePaths","");
2889  incPath.Append(fromConfig);
2890  }
2891  incPath.ReplaceAll(" -I",":"); // of form :dir1 :dir2:dir3
2892  auto posISysRoot = incPath.Index(" -isysroot \"");
2893  if (posISysRoot != kNPOS) {
2894  auto posISysRootEnd = incPath.Index('"', posISysRoot + 12);
2895  if (posISysRootEnd != kNPOS) {
2896  // NOTE: should probably just skip isysroot for dependency analysis.
2897  // (And will, in the future - once we rely on compiler-generated .d files.)
2898  incPath.Insert(posISysRootEnd - 1, "/usr/include/");
2899  incPath.Replace(posISysRoot, 12, ":\"");
2900  }
2901  }
2902  while ( incPath.Index(" :") != -1 ) {
2903  incPath.ReplaceAll(" :",":");
2904  }
2905  incPath.Prepend(":.:");
2906  incPath.Prepend(WorkingDirectory());
2907 
2908  // ======= Get the right file names for the dictionary and the shared library
2909  TString expFileName(filename);
2910  ExpandPathName( expFileName );
2911  expFileName = gSystem->UnixPathName(expFileName);
2912  TString library = expFileName;
2913  if (! IsAbsoluteFileName(library) )
2914  {
2915  const char *whichlibrary = Which(incPath,library);
2916  if (whichlibrary) {
2917  library = whichlibrary;
2918  delete [] whichlibrary;
2919  } else {
2920  ::Error("ACLiC","The file %s can not be found in the include path: %s",filename,incPath.Data());
2921  return kFALSE;
2922  }
2923  } else {
2924  if (gSystem->AccessPathName(library)) {
2925  ::Error("ACLiC","The file %s can not be found.",filename);
2926  return kFALSE;
2927  }
2928  }
2929  { // Remove multiple '/' characters, rootcling treats them as comments.
2930  Ssiz_t pos = 0;
2931  while ((pos = library.Index("//", 2, pos, TString::kExact)) != kNPOS) {
2932  library.Remove(pos, 1);
2933  }
2934  }
2935  library = gSystem->UnixPathName(library);
2936  TString filename_fullpath = library;
2937 
2938  TString file_dirname = GetDirName( filename_fullpath );
2939  // For some probably good reason, DirName on Windows returns the 'name' of
2940  // the directory, omitting the drive letter (even if there was one). In
2941  // consequence the result is not useable as a 'root directory', we need to
2942  // add the drive letter if there was one..
2943  if (library.Length()>1 && isalpha(library[0]) && library[1]==':') {
2944  file_dirname.Prepend(library(0,2));
2945  }
2946  TString file_location( file_dirname ); // Location of the script.
2947  incPath.Prepend( file_location + ":" );
2948 
2949  Ssiz_t dot_pos = library.Last('.');
2950  TString extension = library;
2951  extension.Replace( 0, dot_pos+1, 0 , 0);
2952  TString libname_noext = library;
2953  if (dot_pos>=0) libname_noext.Remove( dot_pos );
2954 
2955  // Extension of shared library is platform dependent!!
2956  library.Replace( dot_pos, library.Length()-dot_pos,
2957  TString("_") + extension + "." + fSoExt );
2958 
2959  TString libname ( BaseName( libname_noext ) );
2960  libname.Append("_").Append(extension);
2961 
2962  if (library_specified && strlen(library_specified) ) {
2963  // Use the specified name instead of the default
2964  libname = BaseName( library_specified );
2965  library = library_specified;
2966  ExpandPathName( library );
2967  if (! IsAbsoluteFileName(library) ) {
2968  AssignAndDelete( library , ConcatFileName( WorkingDirectory(), library ) );
2969  }
2970  library = TString(library) + "." + fSoExt;
2971  }
2972  library = gSystem->UnixPathName(library);
2973 
2974  TString libname_ext ( libname );
2975  libname_ext += "." + fSoExt;
2976 
2977  TString lib_dirname = GetDirName( library );
2978  // For some probably good reason, DirName on Windows returns the 'name' of
2979  // the directory, omitting the drive letter (even if there was one). In
2980  // consequence the result is not useable as a 'root directory', we need to
2981  // add the drive letter if there was one..
2982  if (library.Length()>1 && isalpha(library[0]) && library[1]==':') {
2983  lib_dirname.Prepend(library(0,2));
2984  }
2985  // Strip potential, somewhat redundant '/.' from the pathname ...
2986  if ( strncmp( &(lib_dirname[lib_dirname.Length()-2]), "/.", 2) == 0 ) {
2987  lib_dirname.Remove(lib_dirname.Length()-2);
2988  }
2989  if ( strncmp( &(lib_dirname[lib_dirname.Length()-2]), "\\.", 2) == 0 ) {
2990  lib_dirname.Remove(lib_dirname.Length()-2);
2991  }
2992  TString lib_location( lib_dirname );
2993  Bool_t mkdirFailed = kFALSE;
2994 
2995  if (build_loc.Length()==0) {
2996  build_loc = lib_location;
2997  } else {
2998  // Removes an existing disk specification from the names
2999  TRegexp disk_finder ("[A-z]:");
3000  Int_t pos = library.Index( disk_finder );
3001  if (pos==0) library.Remove(pos,3);
3002  pos = lib_location.Index( disk_finder );
3003  if (pos==0) lib_location.Remove(pos,3);
3004 
3005  if (flatBuildDir) {
3006  AssignAndDelete( library, ConcatFileName( build_loc, libname_ext) );
3007  } else {
3008  AssignAndDelete( library, ConcatFileName( build_loc, library) );
3009  }
3010 
3011  Bool_t canWriteBuild_loc = !gSystem->AccessPathName(build_loc,kWritePermission);
3012  TString build_loc_store( build_loc );
3013  if (!flatBuildDir) {
3014  AssignAndDelete( build_loc, ConcatFileName( build_loc, lib_location) );
3015  }
3016 
3017  if (gSystem->AccessPathName(build_loc,kFileExists)) {
3018  mkdirFailed = (0 != mkdir(build_loc, true));
3019  if (mkdirFailed && !canWriteBuild_loc) {
3020  // The mkdir failed __and__ we can not write to the target directory,
3021  // let make sure the error message will be about the target directory
3022  build_loc = build_loc_store;
3023  mkdirFailed = kFALSE;
3024  } else if (!mkdirFailed && dirmode!=0) {
3025  Chmod(build_loc,dirmode);
3026  }
3027  }
3028  }
3029  library = gSystem->UnixPathName(library);
3030 
3031  // ======= Check if the library need to loaded or compiled
3032  if (!gInterpreter->IsLibraryLoaded(library) && gInterpreter->IsLoaded(expFileName)) {
3033  // the script has already been loaded in interpreted mode
3034  // Let's warn the user and unload it.
3035 
3036  if (withInfo) {
3037  ::Info("ACLiC","script has already been loaded in interpreted mode");
3038  ::Info("ACLiC","unloading %s and compiling it", filename);
3039  }
3040 
3041  if ( gInterpreter->UnloadFile( expFileName ) != 0 ) {
3042  // We can not unload it.
3043  return kFALSE;
3044  }
3045  }
3046 
3047  // Calculate the -I lines
3048  TString includes = GetIncludePath();
3049  includes.Prepend(' ');
3050 
3051  {
3052  // I need to replace the -Isomerelativepath by -I../ (or -I..\ on NT)
3053  TRegexp rel_inc(" -I[^\"/\\$%-][^:-]+");
3054  Int_t len,pos;
3055  pos = rel_inc.Index(includes,&len);
3056  while( len != 0 ) {
3057  TString sub = includes(pos,len);
3058  sub.Remove(0,3); // Remove ' -I'
3060  sub.Prepend(" -I\"");
3061  sub.Chop(); // Remove trailing space (i.e between the -Is ...
3062  sub.Append("\" ");
3063  includes.Replace(pos,len,sub);
3064  pos = rel_inc.Index(includes,&len);
3065  }
3066  }
3067  {
3068  // I need to replace the -I"somerelativepath" by -I"$cwd/ (or -I"$cwd\ on NT)
3069  TRegexp rel_inc(" -I\"[^/\\$%-][^:-]+");
3070  Int_t len,pos;
3071  pos = rel_inc.Index(includes,&len);
3072  while( len != 0 ) {
3073  TString sub = includes(pos,len);
3074  sub.Remove(0,4); // Remove ' -I"'
3076  sub.Prepend(" -I\"");
3077  includes.Replace(pos,len,sub);
3078  pos = rel_inc.Index(includes,&len);
3079  }
3080  }
3081  //includes += " -I\"" + build_loc;
3082  //includes += "\" -I\"";
3083  //includes += WorkingDirectory();
3084 // if (includes[includes.Length()-1] == '\\') {
3085 // // The current directory is (most likely) the root of a windows drive and
3086 // // has a trailing \ which would espace the quote if left by itself.
3087 // includes += '\\';
3088 // }
3089 // includes += "\"";
3090  if (gEnv) {
3091  TString fromConfig = gEnv->GetValue("ACLiC.IncludePaths","");
3092  includes.Append(" ").Append(fromConfig).Append(" ");
3093  }
3094 
3095  // Extract the -D for the dependency generation.
3096  TString defines = " ";
3097  {
3098  TString cmd = GetMakeSharedLib();
3099  TRegexp rel_def("-D[^\\s\\t\\n\\r]*");
3100  Int_t len,pos;
3101  pos = rel_def.Index(cmd,&len);
3102  while( len != 0 ) {
3103  defines += cmd(pos,len);
3104  defines += " ";
3105  pos = rel_def.Index(cmd,&len,pos+1);
3106  }
3107 
3108  }
3109 
3110  TString emergency_loc;
3111  {
3113  if (ug) {
3114  AssignAndDelete( emergency_loc, ConcatFileName( TempDirectory(), ug->fUser ) );
3115  delete ug;
3116  } else {
3117  emergency_loc = TempDirectory();
3118  }
3119  }
3120 
3121  Bool_t canWrite = !gSystem->AccessPathName(build_loc,kWritePermission);
3122 
3123  Bool_t modified = kFALSE;
3124 
3125  // Generate the dependency filename
3126  TString depdir = build_loc;
3127  TString depfilename;
3128  AssignAndDelete( depfilename, ConcatFileName(depdir, BaseName(libname_noext)) );
3129  depfilename += "_" + extension + ".d";
3130 
3131  if ( !recompile ) {
3132 
3133  Long_t lib_time, file_time;
3134 
3135  if ((gSystem->GetPathInfo( library, 0, (Long_t*)0, 0, &lib_time ) != 0) ||
3136  (gSystem->GetPathInfo( expFileName, 0, (Long_t*)0, 0, &file_time ) == 0 &&
3137  (lib_time < file_time))) {
3138 
3139  // the library does not exist or is older than the script.
3140  recompile = kTRUE;
3141  modified = kTRUE;
3142 
3143  } else {
3144 
3145  if ( gSystem->GetPathInfo( depfilename, 0,(Long_t*) 0, 0, &file_time ) != 0 ) {
3146  if (!canWrite) {
3147  depdir = emergency_loc;
3148  AssignAndDelete( depfilename, ConcatFileName(depdir, BaseName(libname_noext)) );
3149  depfilename += "_" + extension + ".d";
3150  }
3151  R__WriteDependencyFile(build_loc, depfilename, filename_fullpath, library, libname, extension, version_var_prefix, includes, defines, incPath);
3152  }
3153  }
3154 
3155  if (!modified) {
3156 
3157  // We need to check the dependencies
3158  FILE * depfile = fopen(depfilename.Data(),"r");
3159  if (depfile==0) {
3160  // there is no accessible dependency file, let's assume the library has been
3161  // modified
3162  modified = kTRUE;
3163  recompile = kTRUE;
3164 
3165  } else {
3166 
3167  TString version_var = libname + version_var_prefix;
3168 
3169  Int_t sz = 256;
3170  char *line = new char[sz];
3171  line[0] = 0;
3172 
3173  int c;
3174  Int_t current = 0;
3175  Int_t nested = 0;
3176  Bool_t hasversion = false;
3177 
3178  while ((c = fgetc(depfile)) != EOF) {
3179  if (c=='#') {
3180  // skip comment
3181  while ((c = fgetc(depfile)) != EOF) {
3182  if (c=='\n') {
3183  break;
3184  }
3185  }
3186  continue;
3187  }
3188  if (current && line[current-1]=='=' && strncmp(version_var.Data(),line,current)==0) {
3189 
3190  // The next word will be the version number.
3191  hasversion = kTRUE;
3192  line[0] = 0;
3193  current = 0;
3194  } else if (isspace(c) && !nested) {
3195  if (current) {
3196  if (line[current-1]!=':') {
3197  // ignore target
3198  line[current] = 0;
3199 
3200  Long_t filetime;
3201  if (hasversion) {
3202  modified |= strcmp(ROOT_RELEASE,line)!=0;
3203  hasversion = kFALSE;
3204  } else if ( gSystem->GetPathInfo( line, 0, (Long_t*)0, 0, &filetime ) == 0 ) {
3205  modified |= ( lib_time <= filetime );
3206  }
3207  }
3208  }
3209  current = 0;
3210  line[0] = 0;
3211  } else {
3212  if (current==sz-1) {
3213  sz = 2*sz;
3214  char *newline = new char[sz];
3215  memcpy(newline,line, current);
3216  delete [] line;
3217  line = newline;
3218  }
3219  if (c=='"') nested = !nested;
3220  else {
3221  line[current] = c;
3222  current++;
3223  }
3224  }
3225  }
3226  delete [] line;
3227  fclose(depfile);
3228  recompile = modified;
3229 
3230  }
3231 
3232  }
3233  }
3234 
3235  if ( gInterpreter->IsLibraryLoaded(library)
3236  || strlen(GetLibraries(library,"D",kFALSE)) != 0 ) {
3237  // The library has already been built and loaded.
3238 
3239  Bool_t reload = kFALSE;
3240  TNamed *libinfo = (TNamed*)fCompiled->FindObject(library);
3241  if (libinfo) {
3242  Long_t load_time = libinfo->GetUniqueID();
3243  Long_t lib_time;
3244  if ( gSystem->GetPathInfo( library, 0, (Long_t*)0, 0, &lib_time ) == 0
3245  && (lib_time>load_time)) {
3246  reload = kTRUE;
3247  }
3248  }
3249 
3250  if ( !recompile && reload ) {
3251 
3252  if (withInfo) {
3253  ::Info("ACLiC","%s has been modified and will be reloaded",
3254  libname.Data());
3255  }
3256  if ( gInterpreter->UnloadFile( library.Data() ) != 0 ) {
3257  // The library is being used. We can not unload it.
3258  return kFALSE;
3259  }
3260  if (libinfo) {
3261  fCompiled->Remove(libinfo);
3262  delete libinfo;
3263  libinfo = 0;
3264  }
3265  TNamed *k = new TNamed(library,library);
3266  Long_t lib_time;
3267  gSystem->GetPathInfo( library, 0, (Long_t*)0, 0, &lib_time );
3268  k->SetUniqueID(lib_time);
3269  if (!keep) k->SetBit(kMustCleanup);
3270  fCompiled->Add(k);
3271 
3272  return !gSystem->Load(library);
3273  }
3274 
3275  if (withInfo) {
3276  ::Info("ACLiC","%s script has already been compiled and loaded",
3277  modified ? "modified" : "unmodified");
3278  }
3279 
3280  if ( !recompile ) {
3281  return kTRUE;
3282  } else {
3283  if (withInfo) {
3284  ::Info("ACLiC","it will be regenerated and reloaded!");
3285  }
3286  if ( gInterpreter->UnloadFile( library.Data() ) != 0 ) {
3287  // The library is being used. We can not unload it.
3288  return kFALSE;
3289  }
3290  if (libinfo) {
3291  fCompiled->Remove(libinfo);
3292  delete libinfo;
3293  libinfo = 0;
3294  }
3295  Unlink(library);
3296  }
3297 
3298  }
3299 
3300  TString libmapfilename;
3301  AssignAndDelete( libmapfilename, ConcatFileName( build_loc, libname ) );
3302  libmapfilename += ".rootmap";
3303 #if (defined(R__MACOSX) && !defined(MAC_OS_X_VERSION_10_5)) || defined(R__WIN32)
3304  Bool_t produceRootmap = kTRUE;
3305 #else
3306  Bool_t produceRootmap = kFALSE;
3307 #endif
3308  Bool_t linkDepLibraries = !produceRootmap;
3309  if (gEnv) {
3310 #if (defined(R__MACOSX) && !defined(MAC_OS_X_VERSION_10_5))
3311  Int_t linkLibs = gEnv->GetValue("ACLiC.LinkLibs",2);
3312 #elif defined(R__WIN32)
3313  Int_t linkLibs = gEnv->GetValue("ACLiC.LinkLibs",3);
3314 #else
3315  Int_t linkLibs = gEnv->GetValue("ACLiC.LinkLibs",1);
3316 #endif
3317  produceRootmap = linkLibs & 0x2;
3318  linkDepLibraries = linkLibs & 0x1;
3319  }
3320 
3321  // FIXME: Triggers clang false positive warning -Wunused-lambda-capture.
3322  /*constexpr const*/ bool useCxxModules =
3323 #ifdef R__USE_CXXMODULES
3324  true;
3325 #else
3326  false;
3327 #endif
3328 
3329  // FIXME: Switch to generic polymorphic when we make c++14 default.
3330  auto ForeachSharedLibDep = [](const char *lib, std::function<bool(const char *)> f) {
3331  using namespace std;
3332  string deps = gInterpreter->GetSharedLibDeps(lib, /*tryDyld*/ true);
3333  istringstream iss(deps);
3334  vector<string> libs{istream_iterator<std::string>{iss}, istream_iterator<string>{}};
3335  // Skip the first element: it is a relative path to `lib`.
3336  for (auto I = libs.begin() + 1, E = libs.end(); I != E; ++I)
3337  if (!f(I->c_str()))
3338  break;
3339  };
3340  auto LoadLibrary = [useCxxModules, produceRootmap, ForeachSharedLibDep](const TString &lib) {
3341  // We have no rootmap files or modules to construct `-l` flags enabling
3342  // explicit linking. We have to resolve the dependencies by ourselves
3343  // taking the job of the dyld.
3344  // FIXME: This is a rare case where we have rootcling running with
3345  // modules disabled. Remove this code once we fully switch to modules,
3346  // or implement a special flag in rootcling which selective enables
3347  // modules for dependent libraries and does not produce a module for
3348  // the ACLiC library.
3349  if (useCxxModules && !produceRootmap) {
3350  std::function<bool(const char *)> LoadLibF = [](const char *dep) {
3351  return gInterpreter->Load(dep, /*skipReload*/ true) >= 0;
3352  };
3353  ForeachSharedLibDep(lib, LoadLibF);
3354  }
3355  return !gSystem->Load(lib);
3356  };
3357 
3358  if (!recompile) {
3359  // The library already exist, let's just load it.
3360  if (loadLib) {
3361  TNamed *k = new TNamed(library,library);
3362  Long_t lib_time;
3363  gSystem->GetPathInfo( library, 0, (Long_t*)0, 0, &lib_time );
3364  k->SetUniqueID(lib_time);
3365  if (!keep) k->SetBit(kMustCleanup);
3366  fCompiled->Add(k);
3367 
3368  gInterpreter->GetSharedLibDeps(library);
3369 
3370  return LoadLibrary(library);
3371  }
3372  else return kTRUE;
3373  }
3374 
3375  if (!canWrite && recompile) {
3376 
3377  if (mkdirFailed) {
3378  ::Warning("ACLiC","Could not create the directory: %s",
3379  build_loc.Data());
3380  } else {
3381  ::Warning("ACLiC","%s is not writable!",
3382  build_loc.Data());
3383  }
3384  if (emergency_loc == build_dir ) {
3385  ::Error("ACLiC","%s is the last resort location (i.e. temp location)",build_loc.Data());
3386  return kFALSE;
3387  }
3388  ::Warning("ACLiC","Output will be written to %s",
3389  emergency_loc.Data());
3390  return CompileMacro(expFileName, opt, library_specified, emergency_loc, dirmode);
3391  }
3392 
3393  if (withInfo) {
3394  Info("ACLiC","creating shared library %s",library.Data());
3395  }
3396 
3397  R__WriteDependencyFile(build_loc, depfilename, filename_fullpath, library, libname, extension, version_var_prefix, includes, defines, incPath);
3398 
3399  // ======= Select the dictionary name
3400  TString dict = libname + "_ACLiC_dict";
3401 
3402  // the file name end up in the file produced
3403  // by rootcling as a variable name so all character need to be valid!
3404  static const int maxforbidden = 27;
3405  static const char *forbidden_chars[maxforbidden] =
3406  { "+","-","*","/","&","%","|","^",">","<",
3407  "=","~",".","(",")","[","]","!",",","$",
3408  " ",":","'","#","@","\\","\"" };
3409  for( int ic = 0; ic < maxforbidden; ic++ ) {
3410  dict.ReplaceAll( forbidden_chars[ic],"_" );
3411  }
3412  if ( dict.Last('.')!=dict.Length()-1 ) dict.Append(".");
3413  AssignAndDelete( dict, ConcatFileName( build_loc, dict ) );
3414  TString dicth = dict;
3415  TString dictObj = dict;
3416  dict += "cxx"; //no need to keep the extension of the original file, any extension will do
3417  dicth += "h";
3418  dictObj += fObjExt;
3419 
3420  // ======= Generate a linkdef file
3421 
3422  TString linkdef;
3423  AssignAndDelete( linkdef, ConcatFileName( build_loc, libname ) );
3424  linkdef += "_ACLiC_linkdef.h";
3425  std::ofstream linkdefFile( linkdef, std::ios::out );
3426  linkdefFile << "// File Automatically generated by the ROOT Script Compiler "
3427  << std::endl;
3428  linkdefFile << std::endl;
3429  linkdefFile << "#ifdef __CINT__" << std::endl;
3430  linkdefFile << std::endl;
3431  linkdefFile << "#pragma link C++ nestedclasses;" << std::endl;
3432  linkdefFile << "#pragma link C++ nestedtypedefs;" << std::endl;
3433  linkdefFile << std::endl;
3434 
3435  // We want to look for a header file that has the same name as the macro
3436 
3437  const char * extensions[] = { ".h", ".hh", ".hpp", ".hxx", ".hPP", ".hXX" };
3438 
3439  int i;
3440  for (i = 0; i < 6; i++ ) {
3441  char * name;
3442  TString extra_linkdef = BaseName( libname_noext );
3443  extra_linkdef.Append(GetLinkdefSuffix());
3444  extra_linkdef.Append(extensions[i]);
3445  name = Which(incPath,extra_linkdef);
3446  if (name) {
3447  if (verboseLevel>4 && withInfo) {
3448  Info("ACLiC","including extra linkdef file: %s",name);
3449  }
3450  linkdefFile << "#include \"" << name << "\"" << std::endl;
3451  delete [] name;
3452  }
3453  }
3454 
3455  if (verboseLevel>5 && withInfo) {
3456  Info("ACLiC","looking for header in: %s",incPath.Data());
3457  }
3458  for (i = 0; i < 6; i++ ) {
3459  char * name;
3460  TString lookup = BaseName( libname_noext );
3461  lookup.Append(extensions[i]);
3462  name = Which(incPath,lookup);
3463  if (name) {
3464  linkdefFile << "#pragma link C++ defined_in "<<gSystem->UnixPathName(name)<<";"<< std::endl;
3465  delete [] name;
3466  }
3467  }
3468  linkdefFile << "#pragma link C++ defined_in \""<<filename_fullpath << "\";" << std::endl;
3469  linkdefFile << std::endl;
3470  linkdefFile << "#endif" << std::endl;
3471  linkdefFile.close();
3472  // ======= Generate the list of rootmap files to be looked at
3473 
3474  TString mapfile;
3475  AssignAndDelete( mapfile, ConcatFileName( build_loc, libname ) );
3476  mapfile += "_ACLiC_map";
3477  TString mapfilein = mapfile + ".in";
3478  TString mapfileout = mapfile + ".out";
3479 
3480  Bool_t needLoadMap = kFALSE;
3481  if (!useCxxModules) {
3482  if (gInterpreter->GetSharedLibDeps(library) != nullptr) {
3483  gInterpreter->UnloadLibraryMap(libname);
3484  needLoadMap = kTRUE;
3485  }
3486  }
3487 
3488  std::ofstream mapfileStream( mapfilein, std::ios::out );
3489  {
3490  TString name = ".rootmap";
3491  TString sname = "system.rootmap";
3492  TString file;
3494  if (gSystem->AccessPathName(file)) {
3495  // for backward compatibility check also $ROOTSYS/system<name> if
3496  // $ROOTSYS/etc/system<name> does not exist
3498  if (gSystem->AccessPathName(file)) {
3499  // for backward compatibility check also $ROOTSYS/<name> if
3500  // $ROOTSYS/system<name> does not exist
3502  }
3503  }
3504  mapfileStream << file << std::endl;
3506  mapfileStream << file << std::endl;
3507  mapfileStream << name << std::endl;
3508  if (gInterpreter->GetRootMapFiles()) {
3509  for (i = 0; i < gInterpreter->GetRootMapFiles()->GetEntriesFast(); i++) {
3510  mapfileStream << ((TNamed*)gInterpreter->GetRootMapFiles()->At(i))->GetTitle() << std::endl;
3511  }
3512  }
3513  }
3514  mapfileStream.close();
3515 
3516  // ======= Generate the rootcling command line
3517  TString rcling = "rootcling";
3518  PrependPathName(TROOT::GetBinDir(), rcling);
3519  rcling += " -v0 \"--lib-list-prefix=";
3520  rcling += mapfile;
3521  rcling += "\" -f \"";
3522  rcling.Append(dict).Append("\" ");
3523 
3524  if (produceRootmap && !useCxxModules) {
3525  rcling += " -rml " + libname + " -rmf \"" + libmapfilename + "\" ";
3526  rcling.Append("-DR__ACLIC_ROOTMAP ");
3527  }
3528  rcling.Append(GetIncludePath()).Append(" -D__ACLIC__ ");
3529  if (gEnv) {
3530  TString fromConfig = gEnv->GetValue("ACLiC.IncludePaths","");
3531  rcling.Append(fromConfig);
3532  TString extraFlags = gEnv->GetValue("ACLiC.ExtraRootclingFlags","");
3533  if (!extraFlags.IsNull()) {
3534  extraFlags.Prepend(" ");
3535  extraFlags.Append(" ");
3536  rcling.Append(extraFlags);
3537  }
3538  }
3539 
3540  // Create a modulemap
3541  // FIXME: Merge the modulemap generation from cmake and here in rootcling.
3542  if (useCxxModules && produceRootmap) {
3543  rcling += " -cxxmodule ";
3544  // TString moduleMapFileName = file_dirname + "/" + libname + ".modulemap";
3545  TString moduleName = libname + "_ACLiC_dict";
3546  if (moduleName.BeginsWith("lib"))
3547  moduleName = moduleName.Remove(0, 3);
3548  TString moduleMapName = moduleName + ".modulemap";
3549  TString moduleMapFullPath = build_loc + "/" + moduleMapName;
3550  // A modulemap may exist from previous runs, overwrite it.
3551  if (verboseLevel > 3 && !AccessPathName(moduleMapFullPath))
3552  ::Info("ACLiC", "File %s already exists!", moduleMapFullPath.Data());
3553 
3554  std::string curDir = ROOT::FoundationUtils::GetCurrentDir();
3555  std::string relative_path = ROOT::FoundationUtils::MakePathRelative(filename_fullpath.Data(), curDir);
3556  std::ofstream moduleMapFile(moduleMapFullPath, std::ios::out);
3557  moduleMapFile << "module \"" << moduleName << "\" {" << std::endl;
3558  moduleMapFile << " header \"" << relative_path << "\"" << std::endl;
3559  moduleMapFile << " export *" << std::endl;
3560  moduleMapFile << " link \"" << libname_ext << "\"" << std::endl;
3561  moduleMapFile << "}" << std::endl;
3562  moduleMapFile.close();
3563  gInterpreter->RegisterPrebuiltModulePath(build_loc.Data(), moduleMapName.Data());
3564  rcling.Append(" \"-fmodule-map-file=" + moduleMapFullPath + "\" ");
3565  }
3566 
3567  rcling.Append(" \"").Append(filename_fullpath).Append("\" ");
3568  rcling.Append("\"").Append(linkdef).Append("\"");
3569 
3570  // ======= Run rootcling
3571  if (withInfo) {
3572  if (verboseLevel>3) {
3573  ::Info("ACLiC","creating the dictionary files");
3574  if (verboseLevel>4) ::Info("ACLiC", "%s", rcling.Data());
3575  }
3576  }
3577 
3578  ///\returns true on success.
3579  auto ExecAndReport = [](TString cmd) -> bool {
3580  Int_t result = gSystem->Exec(cmd);
3581  if (result) {
3582  if (result == 139)
3583  ::Error("ACLiC", "Executing '%s' failed with a core dump!", cmd.Data());
3584  else
3585  ::Error("ACLiC", "Executing '%s' failed!", cmd.Data());
3586  }
3587  return !result;
3588  };
3589 
3590  Bool_t result = ExecAndReport(rcling);
3591  TString depLibraries;
3592 
3593  // ======= Load the library the script might depend on
3594  if (result) {
3595  TString linkedlibs = GetLibraries("", "S");
3596  TString libtoload;
3597  TString all_libtoload;
3598  std::ifstream liblist(mapfileout);
3599 
3600  while ( liblist >> libtoload ) {
3601  // Load the needed library except for the library we are currently building!
3602  if (libtoload == "#") {
3603  // The comment terminates the list of libraries.
3604  std::string toskipcomment;
3605  std::getline(liblist,toskipcomment);
3606  break;
3607  }
3608  if (libtoload != library && libtoload != libname && libtoload != libname_ext) {
3609  if (produceRootmap) {
3610  if (loadLib || linkDepLibraries /* For GetLibraries to Work */) {
3611  result = gROOT->LoadClass("", libtoload) >= 0;
3612  if (!result) {
3613  // We failed to load one of the dependency.
3614  break;
3615  }
3616  }
3617  if (!linkedlibs.Contains(libtoload)) {
3618  all_libtoload.Append(" ").Append(libtoload);
3619  depLibraries.Append(" ");
3620  depLibraries.Append(GetLibraries(libtoload,"DSL",kFALSE));
3621  depLibraries = depLibraries.Strip(); // Remove any trailing spaces.
3622  }
3623  } else {
3624  gROOT->LoadClass("", libtoload);
3625  }
3626  }
3627  unsigned char c = liblist.peek();
3628  if (c=='\n' || c=='\r') {
3629  // Consume the character
3630  liblist.get();
3631  break;
3632  }
3633  }
3634 
3635 // depLibraries = all_libtoload;
3636 // depLibraries.ReplaceAll(" lib"," -l");
3637 // depLibraries.ReplaceAll(TString::Format(".%s",fSoExt.Data()),"");
3638  }
3639 
3640  // ======= Calculate the libraries for linking:
3641  TString linkLibraries;
3642  /*
3643  this is intentionally disabled until it can become useful
3644  if (gEnv) {
3645  linkLibraries = gEnv->GetValue("ACLiC.Libraries","");
3646  linkLibraries.Prepend(" ");
3647  }
3648  */
3649  TString linkLibrariesNoQuotes(GetLibraries("","SDL"));
3650  // We need to enclose the single paths in quotes to account for paths with spaces
3651  TString librariesWithQuotes;
3652  TString singleLibrary;
3653  Bool_t collectingSingleLibraryNameTokens = kFALSE;
3654  for (auto tokenObj : *linkLibrariesNoQuotes.Tokenize(" ")) {
3655  singleLibrary = ((TObjString*)tokenObj)->GetString();
3656  if (singleLibrary[0]=='-' || !AccessPathName(singleLibrary)) {
3657  if (collectingSingleLibraryNameTokens) {
3658  librariesWithQuotes.Chop();
3659  librariesWithQuotes += "\" \"" + singleLibrary + "\"";
3660  collectingSingleLibraryNameTokens = kFALSE;
3661  } else {
3662  librariesWithQuotes += " \"" + singleLibrary + "\"";
3663  }
3664  } else {
3665  if (collectingSingleLibraryNameTokens) {
3666  librariesWithQuotes += singleLibrary + " ";
3667  } else {
3668  collectingSingleLibraryNameTokens = kTRUE;
3669  librariesWithQuotes += " \"" + singleLibrary + " ";
3670  }
3671  }
3672  }
3673 
3674 #ifdef _MSC_VER
3675  linkLibraries.Prepend(linkLibrariesNoQuotes);
3676 #else
3677  linkLibraries.Prepend(librariesWithQuotes);
3678 #endif
3679 
3680  // ======= Generate the build command lines
3681  TString cmd = fMakeSharedLib;
3682  // we do not add filename because it is already included via the dictionary(in dicth) !
3683  // dict.Append(" ").Append(filename);
3684  cmd.ReplaceAll("$SourceFiles","-D__ACLIC__ \"$SourceFiles\"");
3685  cmd.ReplaceAll("$SourceFiles",dict);
3686  cmd.ReplaceAll("$ObjectFiles","\"$ObjectFiles\"");
3687  cmd.ReplaceAll("$ObjectFiles",dictObj);
3688  cmd.ReplaceAll("$IncludePath",includes);
3689  cmd.ReplaceAll("$SharedLib","\"$SharedLib\"");
3690  cmd.ReplaceAll("$SharedLib",library);
3691  if (linkDepLibraries) {
3692  if (produceRootmap) {
3693  cmd.ReplaceAll("$DepLibs",depLibraries);
3694  } else {
3695  cmd.ReplaceAll("$DepLibs",linkLibraries);
3696  }
3697  }
3698  cmd.ReplaceAll("$LinkedLibs",linkLibraries);
3699  cmd.ReplaceAll("$LibName",libname);
3700  cmd.ReplaceAll("\"$BuildDir","$BuildDir");
3701  cmd.ReplaceAll("$BuildDir","\"$BuildDir\"");
3702  cmd.ReplaceAll("$BuildDir",build_loc);
3703  if (mode==kDebug) {
3704  cmd.ReplaceAll("$Opt",fFlagsDebug);
3705  } else {
3706  cmd.ReplaceAll("$Opt",fFlagsOpt);
3707  }
3708 #ifdef WIN32
3709  R__FixLink(cmd);
3710  cmd.ReplaceAll("-std=", "-std:");
3711 #endif
3712 
3713  TString testcmd = fMakeExe;
3714  TString fakeMain;
3715  AssignAndDelete( fakeMain, ConcatFileName( build_loc, libname ) );
3716  fakeMain += "_ACLiC_main";
3717  fakeMain += extension;
3718  std::ofstream fakeMainFile( fakeMain, std::ios::out );
3719  fakeMainFile << "// File Automatically generated by the ROOT Script Compiler "
3720  << std::endl;
3721  fakeMainFile << "int main(char*argc,char**argvv) {};" << std::endl;
3722  fakeMainFile.close();
3723  // We could append this fake main routine to the compilation line.
3724  // But in this case compiler may output the name of the dictionary file
3725  // and of the fakeMain file while it compiles it. (this would be useless
3726  // confusing output).
3727  // We could also the fake main routine to the end of the dictionary file
3728  // however compilation would fail if a main is already there
3729  // (like stress.cxx)
3730  // dict.Append(" ").Append(fakeMain);
3731  TString exec;
3732  AssignAndDelete( exec, ConcatFileName( build_loc, libname ) );
3733  exec += "_ACLiC_exec";
3734  testcmd.ReplaceAll("$SourceFiles","-D__ACLIC__ \"$SourceFiles\"");
3735  testcmd.ReplaceAll("$SourceFiles",dict);
3736  testcmd.ReplaceAll("$ObjectFiles","\"$ObjectFiles\"");
3737  testcmd.ReplaceAll("$ObjectFiles",dictObj);
3738  testcmd.ReplaceAll("$IncludePath",includes);
3739  testcmd.ReplaceAll("$ExeName",exec);
3740  testcmd.ReplaceAll("$LinkedLibs",linkLibraries);
3741  testcmd.ReplaceAll("$BuildDir",build_loc);
3742  if (mode==kDebug)
3743  testcmd.ReplaceAll("$Opt",fFlagsDebug);
3744  else
3745  testcmd.ReplaceAll("$Opt",fFlagsOpt);
3746 
3747 #ifdef WIN32
3748  R__FixLink(testcmd);
3749  testcmd.ReplaceAll("-std=", "-std:");
3750 #endif
3751 
3752  // ======= Build the library
3753  if (result) {
3754  if (verboseLevel>3 && withInfo) {
3755  ::Info("ACLiC","compiling the dictionary and script files");
3756  if (verboseLevel>4) ::Info("ACLiC", "%s", cmd.Data());
3757  }
3758  Int_t success = ExecAndReport(cmd);
3759  if (!success) {
3760  if (produceRootmap) {
3761  gSystem->Unlink(libmapfilename);
3762  }
3763  }
3764  result = success;
3765  }
3766 
3767  if ( result ) {
3768  if (linkDepLibraries) {
3769  // We may have unresolved symbols. Use dyld to resolve the dependent
3770  // libraries and relink.
3771  // FIXME: We will likely have duplicated libraries as we are appending
3772  // FIXME: This likely makes rootcling --lib-list-prefix redundant.
3773  TString depLibsFullPaths;
3774  std::function<bool(const char *)> CollectF = [&depLibsFullPaths](const char *dep) {
3775  TString LibFullPath(dep);
3776  if (!gSystem->FindDynamicLibrary(LibFullPath, /*quiet=*/true)) {
3777  ::Error("TSystem::CompileMacro", "Cannot find library '%s'", dep);
3778  return false; // abort
3779  }
3780  depLibsFullPaths += " " + LibFullPath;
3781  return true;
3782  };
3783  ForeachSharedLibDep(library, CollectF);
3784 
3785  TString relink_cmd = cmd.Strip(TString::kTrailing, ';');
3786  relink_cmd += depLibsFullPaths;
3787  result = ExecAndReport(relink_cmd);
3788  }
3789 
3790  TNamed *k = new TNamed(library,library);
3791  Long_t lib_time;
3792  gSystem->GetPathInfo( library, 0, (Long_t*)0, 0, &lib_time );
3793  k->SetUniqueID(lib_time);
3794  if (!keep) k->SetBit(kMustCleanup);
3795  fCompiled->Add(k);
3796 
3797  if (needLoadMap) {
3798  gInterpreter->LoadLibraryMap(libmapfilename);
3799  }
3800  if (verboseLevel>3 && withInfo) ::Info("ACLiC","loading the shared library");
3801  if (loadLib)
3802  result = LoadLibrary(library);
3803  else
3804  result = kTRUE;
3805 
3806  if ( !result ) {
3807  if (verboseLevel>3 && withInfo) {
3808  ::Info("ACLiC","testing for missing symbols:");
3809  if (verboseLevel>4) ::Info("ACLiC", "%s", testcmd.Data());
3810  }
3811  gSystem->Exec(testcmd);
3812  gSystem->Unlink( exec );
3813  }
3814 
3815  };
3816 
3817  if (verboseLevel<=5 && !internalDebug) {
3818  gSystem->Unlink( dict );
3819  gSystem->Unlink( dicth );
3820  gSystem->Unlink( dictObj );
3821  gSystem->Unlink( linkdef );
3822  gSystem->Unlink( mapfilein );
3823  gSystem->Unlink( mapfileout );
3824  gSystem->Unlink( fakeMain );
3825  gSystem->Unlink( exec );
3826  }
3827  if (verboseLevel>6) {
3828  rcling.Prepend("echo ");
3829  cmd.Prepend("echo \" ").Append(" \" ");
3830  testcmd.Prepend("echo \" ").Append(" \" ");
3831  gSystem->Exec(rcling);
3832  gSystem->Exec( cmd );
3833  gSystem->Exec(testcmd);
3834  }
3835 
3836  return result;
3837 }
3838 
3839 ////////////////////////////////////////////////////////////////////////////////
3840 /// Return the ACLiC properties field. See EAclicProperties for details
3841 /// on the semantic of each bit.
3842 
3844 {
3845  return fAclicProperties;
3846 }
3847 
3848 ////////////////////////////////////////////////////////////////////////////////
3849 /// Return the build architecture.
3850 
3851 const char *TSystem::GetBuildArch() const
3852 {
3853  return fBuildArch;
3854 }
3855 
3856 ////////////////////////////////////////////////////////////////////////////////
3857 /// Return the build compiler
3858 
3859 const char *TSystem::GetBuildCompiler() const
3860 {
3861  return fBuildCompiler;
3862 }
3863 
3864 ////////////////////////////////////////////////////////////////////////////////
3865 /// Return the build compiler version
3866 
3868 {
3869  return fBuildCompilerVersion;
3870 }
3871 
3872 ////////////////////////////////////////////////////////////////////////////////
3873 /// Return the build node name.
3874 
3875 const char *TSystem::GetBuildNode() const
3876 {
3877  return fBuildNode;
3878 }
3879 
3880 ////////////////////////////////////////////////////////////////////////////////
3881 /// Return the path of the build directory.
3882 
3883 const char *TSystem::GetBuildDir() const
3884 {
3885  if (fBuildDir.Length()==0) {
3886  if (!gEnv) return "";
3887  const_cast<TSystem*>(this)->fBuildDir = gEnv->GetValue("ACLiC.BuildDir","");
3888  }
3889  return fBuildDir;
3890 }
3891 
3892 ////////////////////////////////////////////////////////////////////////////////
3893 /// Return the debug flags.
3894 
3895 const char *TSystem::GetFlagsDebug() const
3896 {
3897  return fFlagsDebug;
3898 }
3899 
3900 ////////////////////////////////////////////////////////////////////////////////
3901 /// Return the optimization flags.
3902 
3903 const char *TSystem::GetFlagsOpt() const
3904 {
3905  return fFlagsOpt;
3906 }
3907 
3908 ////////////////////////////////////////////////////////////////////////////////
3909 /// AclicMode indicates whether the library should be built in
3910 /// debug mode or optimized. The values are:
3911 /// - TSystem::kDefault : compile the same as the current ROOT
3912 /// - TSystem::kDebug : compiled in debug mode
3913 /// - TSystem::kOpt : optimized the library
3914 
3916 {
3917  return fAclicMode;
3918 }
3919 
3920 ////////////////////////////////////////////////////////////////////////////////
3921 /// Return the command line use to make a shared library.
3922 /// See TSystem::CompileMacro for more details.
3923 
3924 const char *TSystem::GetMakeSharedLib() const
3925 {
3926  return fMakeSharedLib;
3927 }
3928 
3929 ////////////////////////////////////////////////////////////////////////////////
3930 /// Return the command line use to make an executable.
3931 /// See TSystem::CompileMacro for more details.
3932 
3933 const char *TSystem::GetMakeExe() const
3934 {
3935  return fMakeExe;
3936 }
3937 
3938 ////////////////////////////////////////////////////////////////////////////////
3939 /// Get the list of include path.
3940 
3942 {
3944 #ifndef _MSC_VER
3945  // FIXME: This is a temporary fix for the following error with ACLiC
3946  // (and this is apparently not needed anyway):
3947  // 48: input_line_12:8:38: error: use of undeclared identifier 'IC'
3948  // 48: "C:/Users/bellenot/build/debug/etc" -IC:/Users/bellenot/build/debug/etc//cling -IC:/Users/bellenot/build/debug/include"",
3949  // 48: ^
3950  // 48: Error in <ACLiC>: Dictionary generation failed!
3951  fListPaths.Append(" ").Append(gInterpreter->GetIncludePath());
3952 #endif
3953  return fListPaths;
3954 }
3955 
3956 ////////////////////////////////////////////////////////////////////////////////
3957 /// Return the list of library linked to this executable.
3958 /// See TSystem::CompileMacro for more details.
3959 
3960 const char *TSystem::GetLinkedLibs() const
3961 {
3962  return fLinkedLibs;
3963 }
3964 
3965 ////////////////////////////////////////////////////////////////////////////////
3966 /// Return the linkdef suffix chosen by the user for ACLiC.
3967 /// See TSystem::CompileMacro for more details.
3968 
3969 const char *TSystem::GetLinkdefSuffix() const
3970 {
3971  if (fLinkdefSuffix.Length()==0) {
3972  if (!gEnv) return "_linkdef";
3973  const_cast<TSystem*>(this)->fLinkdefSuffix = gEnv->GetValue("ACLiC.Linkdef","_linkdef");
3974  }
3975  return fLinkdefSuffix;
3976 }
3977 
3978 ////////////////////////////////////////////////////////////////////////////////
3979 /// Get the shared library extension.
3980 
3981 const char *TSystem::GetSoExt() const
3982 {
3983  return fSoExt;
3984 }
3985 
3986 ////////////////////////////////////////////////////////////////////////////////
3987 /// Get the object file extension.
3988 
3989 const char *TSystem::GetObjExt() const
3990 {
3991  return fObjExt;
3992 }
3993 
3994 ////////////////////////////////////////////////////////////////////////////////
3995 /// Set the location where ACLiC will create libraries and use as
3996 /// a scratch area.
3997 ///
3998 /// If isflast is flase, then the libraries are actually stored in
3999 /// sub-directories of 'build_dir' including the full pathname of the
4000 /// script. If the script is location at /full/path/name/macro.C
4001 /// the library will be located at 'build_dir+/full/path/name/macro_C.so'
4002 /// If 'isflat' is true, then no subdirectory is created and the library
4003 /// is created directly in the directory 'build_dir'. Note that in this
4004 /// mode there is a risk than 2 script of the same in different source
4005 /// directory will over-write each other.
4006 
4007 void TSystem::SetBuildDir(const char* build_dir, Bool_t isflat)
4008 {
4009  fBuildDir = build_dir;
4010  if (isflat)
4012  else
4014 }
4015 
4016 ////////////////////////////////////////////////////////////////////////////////
4017 /// FlagsDebug should contain the options to pass to the C++ compiler
4018 /// in order to compile the library in debug mode.
4019 
4020 void TSystem::SetFlagsDebug(const char *flags)
4021 {
4022  fFlagsDebug = flags;
4023 }
4024 
4025 ////////////////////////////////////////////////////////////////////////////////
4026 /// FlagsOpt should contain the options to pass to the C++ compiler
4027 /// in order to compile the library in optimized mode.
4028 
4029 void TSystem::SetFlagsOpt(const char *flags)
4030 {
4031  fFlagsOpt = flags;
4032 }
4033 
4034 ////////////////////////////////////////////////////////////////////////////////
4035 /// AclicMode indicates whether the library should be built in
4036 /// debug mode or optimized. The values are:
4037 /// - TSystem::kDefault : compile the same as the current ROOT
4038 /// - TSystem::kDebug : compiled in debug mode
4039 /// - TSystem::kOpt : optimized the library
4040 
4042 {
4043  fAclicMode = mode;
4044 }
4045 
4046 ////////////////////////////////////////////////////////////////////////////////
4047 /// Directives has the same syntax as the argument of SetMakeSharedLib but is
4048 /// used to create an executable. This creation is used as a means to output
4049 /// a list of unresolved symbols, when loading a shared library has failed.
4050 /// The required variable is $ExeName rather than $SharedLib, e.g.:
4051 /// ~~~ {.cpp}
4052 /// gSystem->SetMakeExe(
4053 /// "g++ -Wall -fPIC $IncludePath $SourceFiles
4054 /// -o $ExeName $LinkedLibs -L/usr/X11R6/lib -lX11 -lm -ldl -rdynamic");
4055 /// ~~~
4056 
4057 void TSystem::SetMakeExe(const char *directives)
4058 {
4059  fMakeExe = directives;
4060  // NOTE: add verification that the directives has the required variables
4061 }
4062 
4063 ////////////////////////////////////////////////////////////////////////////////
4064 /// Directives should contain the description on how to compile and link a
4065 /// shared lib. This description can be any valid shell command, including
4066 /// the use of ';' to separate several instructions. However, shell specific
4067 /// construct should be avoided. In particular this description can contain
4068 /// environment variables, like $ROOTSYS (or %ROOTSYS% on windows).
4069 /// ~~~ {.cpp}
4070 /// Five special variables will be expanded before execution:
4071 /// Variable name Expands to
4072 /// ------------- ----------
4073 /// $SourceFiles Name of source files to be compiled
4074 /// $SharedLib Name of the shared library being created
4075 /// $LibName Name of shared library without extension
4076 /// $BuildDir Directory where the files will be created
4077 /// $IncludePath value of fIncludePath
4078 /// $LinkedLibs value of fLinkedLibs
4079 /// $DepLibs libraries on which this library depends on
4080 /// $ObjectFiles Name of source files to be compiler with
4081 /// their extension changed to .o or .obj
4082 /// $Opt location of the optimization/debug options
4083 /// set fFlagsDebug and fFlagsOpt
4084 /// ~~~
4085 /// e.g.:
4086 /// ~~~ {.cpp}
4087 /// gSystem->SetMakeSharedLib(
4088 /// "KCC -n32 --strict $IncludePath -K0 \$Opt $SourceFile
4089 /// --no_exceptions --signed_chars --display_error_number
4090 /// --diag_suppress 68 -o $SharedLib");
4091 ///
4092 /// gSystem->setMakeSharedLib(
4093 /// "Cxx $IncludePath -c $SourceFile;
4094 /// ld -L/usr/lib/cmplrs/cxx -rpath /usr/lib/cmplrs/cxx -expect_unresolved
4095 /// \$Opt -shared /usr/lib/cmplrs/cc/crt0.o /usr/lib/cmplrs/cxx/_main.o
4096 /// -o $SharedLib $ObjectFile -lcxxstd -lcxx -lexc -lots -lc"
4097 ///
4098 /// gSystem->SetMakeSharedLib(
4099 /// "$HOME/mygcc/bin/g++ \$Opt -Wall -fPIC $IncludePath $SourceFile
4100 /// -shared -o $SharedLib");
4101 ///
4102 /// gSystem->SetMakeSharedLib(
4103 /// "cl -DWIN32 -D_WIN32 -D_MT -D_DLL -MD /O2 /G5 /MD -DWIN32
4104 /// -D_WINDOWS $IncludePath $SourceFile
4105 /// /link -PDB:NONE /NODEFAULTLIB /INCREMENTAL:NO /RELEASE /NOLOGO
4106 /// $LinkedLibs -entry:_DllMainCRTStartup@12 -dll /out:$SharedLib")
4107 /// ~~~
4108 
4109 void TSystem::SetMakeSharedLib(const char *directives)
4110 {
4111  fMakeSharedLib = directives;
4112  // NOTE: add verification that the directives has the required variables
4113 }
4114 
4115 ////////////////////////////////////////////////////////////////////////////////
4116 /// Add includePath to the already set include path.
4117 /// Note: This interface is mostly relevant for ACLiC and it does *not* inform
4118 /// gInterpreter for this include path. If the TInterpreter needs to know about
4119 /// the include path please use \c gInterpreter->AddIncludePath.
4120 
4121 void TSystem::AddIncludePath(const char *includePath)
4122 {
4123  if (includePath) {
4124  fIncludePath += " ";
4125  fIncludePath += includePath;
4126  }
4127 }
4128 
4129 ////////////////////////////////////////////////////////////////////////////////
4130 /// Add linkedLib to already set linked libs.
4131 
4132 void TSystem::AddLinkedLibs(const char *linkedLib)
4133 {
4134  if (linkedLib) {
4135  fLinkedLibs += " ";
4136  fLinkedLibs += linkedLib;
4137  }
4138 }
4139 
4140 ////////////////////////////////////////////////////////////////////////////////
4141 /// IncludePath should contain the list of compiler flags to indicate where
4142 /// to find user defined header files. It is used to expand $IncludePath in
4143 /// the directives given to SetMakeSharedLib() and SetMakeExe(), e.g.:
4144 /// ~~~ {.cpp}
4145 /// gSystem->SetInclude("-I$ROOTSYS/include -Imydirectory/include");
4146 /// ~~~
4147 /// the default value of IncludePath on Unix is:
4148 /// ~~~ {.cpp}
4149 /// "-I$ROOTSYS/include "
4150 /// ~~~
4151 /// and on Windows:
4152 /// ~~~ {.cpp}
4153 /// "/I%ROOTSYS%/include "
4154 /// ~~~
4155 
4156 void TSystem::SetIncludePath(const char *includePath)
4157 {
4158  fIncludePath = includePath;
4159 }
4160 
4161 ////////////////////////////////////////////////////////////////////////////////
4162 /// LinkedLibs should contain the library directory and list of libraries
4163 /// needed to recreate the current executable. It is used to expand $LinkedLibs
4164 /// in the directives given to SetMakeSharedLib() and SetMakeExe()
4165 /// The default value on Unix is: `root-config --glibs`
4166 
4167 void TSystem::SetLinkedLibs(const char *linkedLibs)
4168 {
4169  fLinkedLibs = linkedLibs;
4170 }
4171 
4172 ////////////////////////////////////////////////////////////////////////////////
4173 /// The 'suffix' will be appended to the name of a script loaded by ACLiC
4174 /// and used to locate any eventual additional linkdef information that
4175 /// ACLiC should used to produce the dictionary.
4176 ///
4177 /// So by default, when doing .L MyScript.cxx, ACLiC will look
4178 /// for a file name MyScript_linkdef and having one of the .h (.hpp,
4179 /// etc.) extensions. If such a file exist, it will be added to
4180 /// the end of the linkdef file used to created the ACLiC dictionary.
4181 /// This effectively enable the full customization of the creation
4182 /// of the dictionary. It should be noted that the file is intended
4183 /// as a linkdef `fragment`, so usually you would not list the
4184 /// typical:
4185 /// ~~~ {.cpp}
4186 /// #pragma link off ....
4187 /// ~~~
4188 
4189 void TSystem::SetLinkdefSuffix(const char *suffix)
4190 {
4191  fLinkdefSuffix = suffix;
4192 }
4193 
4194 
4195 ////////////////////////////////////////////////////////////////////////////////
4196 /// Set shared library extension, should be either .so, .sl, .a, .dll, etc.
4197 
4198 void TSystem::SetSoExt(const char *SoExt)
4199 {
4200  fSoExt = SoExt;
4201 }
4202 
4203 ////////////////////////////////////////////////////////////////////////////////
4204 /// Set object files extension, should be either .o, .obj, etc.
4205 
4206 void TSystem::SetObjExt(const char *ObjExt)
4207 {
4208  fObjExt = ObjExt;
4209 }
4210 
4211 ////////////////////////////////////////////////////////////////////////////////
4212 /// This method split a filename of the form:
4213 /// ~~~ {.cpp}
4214 /// [path/]macro.C[+|++[k|f|g|O|c|s|d|v|-]][(args)].
4215 /// ~~~
4216 /// It stores the ACliC mode [+|++[options]] in 'mode',
4217 /// the arguments (including parenthesis) in arg
4218 /// and the I/O indirection in io
4219 
4220 TString TSystem::SplitAclicMode(const char* filename, TString &aclicMode,
4221  TString &arguments, TString &io) const
4222 {
4223  char *fname = Strip(filename);
4224  TString filenameCopy = fname;
4225  filenameCopy = filenameCopy.Strip();
4226 
4227  if (filenameCopy.EndsWith(";")) {
4228  filenameCopy.Remove(filenameCopy.Length() - 1);
4229  filenameCopy = filenameCopy.Strip();
4230  }
4231  if (filenameCopy.EndsWith(")")) {
4232  Ssiz_t posArgEnd = filenameCopy.Length() - 1;
4233  // There is an argument; find its start!
4234  int parenNestCount = 1;
4235  bool inString = false;
4236  Ssiz_t posArgBegin = posArgEnd - 1;
4237  for (; parenNestCount && posArgBegin >= 0; --posArgBegin) {
4238  // Escaped if the previous character is a `\` - but not if it
4239  // itself is preceded by a `\`!
4240  if (posArgBegin > 0 && filenameCopy[posArgBegin] == '\\' &&
4241  (posArgBegin == 1 || filenameCopy[posArgBegin - 1] != '\\')) {
4242  // skip escape.
4243  --posArgBegin;
4244  continue;
4245  }
4246  switch (filenameCopy[posArgBegin]) {
4247  case ')':
4248  if (!inString)
4249  ++parenNestCount;
4250  break;
4251  case '(':
4252  if (!inString)
4253  --parenNestCount;
4254  break;
4255  case '"': inString = !inString; break;
4256  }
4257  }
4258  if (parenNestCount || inString) {
4259  Error("SplitAclicMode", "Cannot parse argument in %s", filename);
4260  } else {
4261  arguments = filenameCopy(posArgBegin + 1, posArgEnd - 1);
4262  fname[posArgBegin + 1] = 0;
4263  }
4264  }
4265 
4266  // strip off I/O redirect tokens from filename
4267  {
4268  char *s2 = nullptr;
4269  char *s3;
4270  s2 = strstr(fname, ">>");
4271  if (!s2) s2 = strstr(fname, "2>");
4272  if (!s2) s2 = strchr(fname, '>');
4273  s3 = strchr(fname, '<');
4274  if (s2 && s3) s2 = s2<s3 ? s2 : s3;
4275  if (s3 && !s2) s2 = s3;
4276  if (s2==fname) {
4277  io = fname;
4278  aclicMode = "";
4279  arguments = "";
4280  delete []fname;
4281  return "";
4282  } else if (s2) {
4283  s2--;
4284  while (s2 && *s2 == ' ') s2--;
4285  s2++;
4286  io = s2; // ssave = *s2;
4287  *s2 = 0;
4288  } else
4289  io = "";
4290  }
4291 
4292  // remove the possible ACLiC + or ++ and g or O etc
4293  aclicMode.Clear();
4294  int len = strlen(fname);
4295  TString mode;
4296  while (len > 1) {
4297  if (strchr("kfgOcsdv-", fname[len - 1])) {
4298  mode += fname[len - 1];
4299  --len;
4300  } else {
4301  break;
4302  }
4303  }
4304  Bool_t compile = len && fname[len - 1] == '+';
4305  Bool_t remove = compile && len > 1 && fname[len - 2] == '+';
4306  if (compile) {
4307  if (mode.Length()) {
4308  fname[len] = 0;
4309  }
4310  if (remove) {
4311  fname[strlen(fname)-2] = 0;
4312  aclicMode = "++";
4313  } else {
4314  fname[strlen(fname)-1] = 0;
4315  aclicMode = "+";
4316  }
4317  if (mode.Length())
4318  aclicMode += mode;
4319  }
4320 
4321  TString resFilename = fname;
4322 
4323  delete []fname;
4324  return resFilename;
4325 }
4326 
4327 ////////////////////////////////////////////////////////////////////////////////
4328 /// Remove the shared libs produced by the CompileMacro() function.
4329 
4331 {
4332  TIter next(fCompiled);
4333  TNamed *lib;
4334  while ((lib = (TNamed*)next())) {
4335  if (lib->TestBit(kMustCleanup)) Unlink(lib->GetTitle());
4336  }
4337 }
4338 
4339 ////////////////////////////////////////////////////////////////////////////////
4340 /// Register version of plugin library.
4341 
4343 {
4344  if (versionCode != TROOT::RootVersionCode() && gLibraryVersion)
4345  gLibraryVersion[gLibraryVersionIdx] = versionCode;
4346 }
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:930
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
virtual void SysError(const char *method, const char *msgfmt,...) const
Issue system error message.
Definition: TObject.cxx:905
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:1291
virtual TObject * Remove(TObject *obj)=0
virtual void Add(TObject *obj)
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition: TObject.cxx:375
TSeqCollection * fCompiled
Definition: TSystem.h:318
TString fBuildCompiler
Definition: TSystem.h:302
virtual Bool_t IsAbsoluteFileName(const char *dir)
Return true if dir is an absolute pathname.
Definition: TSystem.cxx:947
Bool_t fDone
Definition: TSystem.h:290
virtual int GetPid()
Get process id.
Definition: TSystem.cxx:705
An array of TObjects.
Definition: TObjArray.h:37
virtual int GetCpuInfo(CpuInfo_t *info, Int_t sampleTime=1000) const
Returns cpu load average and load info into the CpuInfo_t structure.
Definition: TSystem.cxx:2470
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition: TSystem.cxx:414
virtual void Syslog(ELogLevel level, const char *mess)
Send mess to syslog daemon.
Definition: TSystem.cxx:1679
virtual const char * GetFlagsOpt() const
Return the optimization flags.
Definition: TSystem.cxx:3903
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:865
auto * tt
Definition: textangle.C:16
virtual const char * GetBuildCompilerVersion() const
Return the build compiler version.
Definition: TSystem.cxx:3867
virtual Bool_t IsPathLocal(const char *path)
Returns TRUE if the url in &#39;path&#39; points to the local file system.
Definition: TSystem.cxx:1300
Bool_t ProcessEvents()
Process events if timer did time out.
Definition: TSystem.cxx:88
long long Long64_t
Definition: RtypesCore.h:71
Int_t fSigcnt
Definition: TSystem.h:282
virtual const char * WorkingDirectory()
Return working directory.
Definition: TSystem.cxx:867
virtual void StackTrace()
Print a stack trace.
Definition: TSystem.cxx:730
EAclicMode
Definition: TSystem.h:268
void Reset()
Reset the timer.
Definition: TTimer.cxx:157
virtual void SigAlarmInterruptsSyscalls(Bool_t)
Definition: TSystem.h:328
virtual void SetFlagsDebug(const char *)
FlagsDebug should contain the options to pass to the C++ compiler in order to compile the library in ...
Definition: TSystem.cxx:4020
virtual void NotifyApplicationCreated()
Hook to tell TSystem that the TApplication object has been created.
Definition: TSystem.cxx:309
TLine * line
virtual TString GetDirName(const char *pathname)
Return the directory name in pathname.
Definition: TSystem.cxx:1027
Collectable string class.
Definition: TObjString.h:28
virtual void StartIdleing()
virtual const char * GetLinkedLibs() const
Return the list of library linked to this executable.
Definition: TSystem.cxx:3960
Int_t fLevel
Definition: TSystem.h:291
const char Option_t
Definition: RtypesCore.h:64
virtual int Link(const char *from, const char *to)
Create a link from file1 to file2.
Definition: TSystem.cxx:1354
Int_t fBeepFreq
Definition: TSystem.h:286
virtual TString SplitAclicMode(const char *filename, TString &mode, TString &args, TString &io) const
This method split a filename of the form: ~~~ {.cpp} [path/]macro.C[+|++[k|f|g|O|c|s|d|v|-]][(args)]...
Definition: TSystem.cxx:4220
virtual void SetFlagsOpt(const char *)
FlagsOpt should contain the options to pass to the C++ compiler in order to compile the library in op...
Definition: TSystem.cxx:4029
virtual const char * GetLinkedLibraries()
Get list of shared libraries loaded at the start of the executable.
Definition: TSystem.cxx:2121
TSeqCollection * fOnExitList
Definition: TSystem.h:297
void RemoveOnExit(TObject *obj)
Objects that should be deleted on exit of the OS interface.
Definition: TSystem.cxx:290
virtual Int_t SetFPEMask(Int_t mask=kDefaultMask)
Set which conditions trigger a floating point exception.
Definition: TSystem.cxx:640
const Ssiz_t kNPOS
Definition: RtypesCore.h:113
This class represents a WWW compatible URL.
Definition: TUrl.h:35
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:687
virtual Int_t GetGid(const char *group=nullptr)
Returns the group&#39;s id. If group = 0, returns current user&#39;s group.
Definition: TSystem.cxx:1574
virtual const char * GetBuildNode() const
Return the build node name.
Definition: TSystem.cxx:3875
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:1393
const char * GetProtocol() const
Definition: TUrl.h:66
TString fBuildCompilerVersion
Definition: TSystem.h:303
static Int_t RootVersionCode()
Return ROOT version code as defined in RVersion.h.
Definition: TROOT.cxx:2839
virtual TString GetFromPipe(const char *command)
Execute command and return output in TString.
Definition: TSystem.cxx:678
TString fBuildNode
Definition: TSystem.h:304
virtual void * GetDirPtr() const
Definition: TSystem.h:412
This class represents an Internet Protocol (IP) address.
Definition: TInetAddress.h:36
virtual int MakeDirectory(const char *name)
Make a directory.
Definition: TSystem.cxx:823
virtual void AddSignalHandler(TSignalHandler *sh)
Add a signal handler to list of system signal handlers.
Definition: TSystem.cxx:530
virtual void CloseConnection(int sock, Bool_t force=kFALSE)
Close socket connection.
Definition: TSystem.cxx:2391
Regular expression class.
Definition: TRegexp.h:31
This class implements a mutex interface.
Definition: TVirtualMutex.h:34
virtual Bool_t ChangeDirectory(const char *path)
Change directory.
Definition: TSystem.cxx:858
TVersionCheck(int versionCode)
Register version of plugin library.
Definition: TSystem.cxx:4342
#define gROOT
Definition: TROOT.h:406
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:187
virtual UserGroup_t * GetGroupInfo(Int_t gid)
Returns all group info in the UserGroup_t structure.
Definition: TSystem.cxx:1618
virtual int GetFsInfo(const char *path, Long_t *id, Long_t *bsize, Long_t *blocks, Long_t *bfree)
Get info about a file system: fs type, block size, number of blocks, number of free blocks...
Definition: TSystem.cxx:1467
virtual void SetMakeExe(const char *directives)
Directives has the same syntax as the argument of SetMakeSharedLib but is used to create an executabl...
Definition: TSystem.cxx:4057
virtual Bool_t ConsistentWith(const char *path, void *dirptr=nullptr)
Check consistency of this helper with the one required by &#39;path&#39; or &#39;dirptr&#39;.
Definition: TSystem.cxx:800
virtual FILE * TempFileName(TString &base, const char *dir=nullptr)
Create a secure temporary file by appending a unique 6 letter string to base.
Definition: TSystem.cxx:1492
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition: TSystem.cxx:1850
virtual void AddStdExceptionHandler(TStdExceptionHandler *eh)
Add an exception handler to list of system exception handlers.
Definition: TSystem.cxx:609
std::string GetCurrentDir()
The TEnv class reads config files, by default named .rootrc.
Definition: TEnv.h:125
Basic string class.
Definition: TString.h:131
TSeqCollection * fSignalHandler
Definition: TSystem.h:294
TString fBuildArch
Definition: TSystem.h:301
virtual void ResetSignal(ESignals sig, Bool_t reset=kTRUE)
If reset is true reset the signal handler for the specified signal to the default handler...
Definition: TSystem.cxx:574
virtual int GetMemInfo(MemInfo_t *info) const
Returns ram and swap memory usage info into the MemInfo_t structure.
Definition: TSystem.cxx:2480
const char * GetValue() const
Definition: TEnv.h:111
static void R__AddPath(TString &target, const TString &path)
Definition: TSystem.cxx:2565
#define f(i)
Definition: RSha256.hxx:104
int Int_t
Definition: RtypesCore.h:43
virtual const char * DirName(const char *pathname)
Return the directory name in pathname.
Definition: TSystem.cxx:1002
virtual TTimer * RemoveTimer(TTimer *t)
Remove timer from list of system timers.
Definition: TSystem.cxx:479
#define ENDTRY
Definition: TException.h:69
static const TString & GetRootSys()
Get the rootsys directory in the installation. Static utility function.
Definition: TROOT.cxx:2877
virtual const char * GetSoExt() const
Get the shared library extension.
Definition: TSystem.cxx:3981
#define gInterpreter
Definition: TInterpreter.h:556
virtual char * Which(const char *search, const char *file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition: TSystem.cxx:1541
Long_t fMtime
Definition: TSystem.h:130
virtual void SetMakeSharedLib(const char *directives)
Directives should contain the description on how to compile and link a shared lib.
Definition: TSystem.cxx:4109
virtual int AnnounceUdpService(int port, int backlog)
Announce UDP service.
Definition: TSystem.cxx:2355
virtual FILE * OpenPipe(const char *command, const char *mode)
Open a pipe.
Definition: TSystem.cxx:660
STL namespace.
virtual const char * GetFlagsDebug() const
Return the debug flags.
Definition: TSystem.cxx:3895
TString & Prepend(const char *cs)
Definition: TString.h:656
R__EXTERN TApplication * gApplication
Definition: TApplication.h:166
TObject * At(Int_t idx) const
Definition: TObjArray.h:166
virtual void ResetSignals()
Reset signals handlers to previous behaviour.
Definition: TSystem.cxx:582
virtual void IgnoreInterrupt(Bool_t ignore=kTRUE)
If ignore is true ignore the interrupt signal, else restore previous behaviour.
Definition: TSystem.cxx:600
Basic time type with millisecond precision.
Definition: TTime.h:27
static bool R__MatchFilename(const char *left, const char *right)
Figure out if left and right points to the same object in the file system.
Definition: TSystem.cxx:1809
Long64_t fSize
Definition: TSystem.h:129
virtual TInetAddress GetPeerName(int sock)
Get Internet Protocol (IP) address of remote host and port #.
Definition: TSystem.cxx:2301
TString & Insert(Ssiz_t pos, const char *s)
Definition: TString.h:644
static const TString & GetIncludeDir()
Get the include directory in the installation. Static utility function.
Definition: TROOT.cxx:2929
virtual int SendRaw(int sock, const void *buffer, int length, int flag)
Send exactly length bytes from buffer.
Definition: TSystem.cxx:2410
virtual TFileHandler * RemoveFileHandler(TFileHandler *fh)
Remove a file handler from the list of file handlers.
Definition: TSystem.cxx:562
Bool_t R_ISREG(Int_t mode)
Definition: TSystem.h:117
virtual char * GetServiceByPort(int port)
Get name of internet service.
Definition: TSystem.cxx:2328
virtual int mkdir(const char *name, Bool_t recursive=kFALSE)
Make a file system directory.
Definition: TSystem.cxx:902
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
TVirtualMutex * gSystemMutex
Definition: TSystem.cxx:106
virtual const char * FindFile(const char *search, TString &file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition: TSystem.cxx:1531
virtual const char * UnixPathName(const char *unixpathname)
Convert from a local pathname to a Unix pathname.
Definition: TSystem.cxx:1058
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition: TString.h:677
static Int_t GetErrno()
Static function returning system error number.
Definition: TSystem.cxx:258
TSystem * FindHelper(const char *path, void *dirptr=nullptr)
Create helper TSystem to handle file and directory operations that might be special for remote file a...
Definition: TSystem.cxx:742
Int_t fMode
Definition: TSystem.h:126
TSeqCollection * fStdExceptionHandler
Definition: TSystem.h:296
Bool_t IsInterruptingSyscalls() const
Definition: TTimer.h:82
virtual int Rename(const char *from, const char *to)
Rename a file.
Definition: TSystem.cxx:1345
virtual const char * GetLinkdefSuffix() const
Return the linkdef suffix chosen by the user for ACLiC.
Definition: TSystem.cxx:3969
virtual void Delete(Option_t *option="")=0
Delete this object.
const char * GetHost() const
Definition: TUrl.h:69
virtual const char * GetDirEntry(void *dirp)
Get a directory entry. Returns 0 if no more entries.
Definition: TSystem.cxx:849
TTime GetAbsTime() const
Definition: TTimer.h:78
virtual int Unlink(const char *name)
Unlink, i.e.
Definition: TSystem.cxx:1376
Double_t x[n]
Definition: legend1.C:17
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:2311
virtual int GetSysInfo(SysInfo_t *info) const
Returns static system info, like OS type, CPU type, number of CPUs RAM size, etc into the SysInfo_t s...
Definition: TSystem.cxx:2459
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition: TSystem.cxx:435
TString fBuildDir
Definition: TSystem.h:305
static const std::string separator("@@@")
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
Int_t fMaxrfd
Definition: TSystem.h:280
TSeqCollection * fHelpers
Definition: TSystem.h:319
TString fListPaths
Definition: TSystem.h:308
TString fLinkedLibs
Definition: TSystem.h:310
Bool_t fTimeout
Definition: TTimer.h:56
TObject * Next()
Return next object in collection.
Int_t fNfd
Signals that were trapped.
Definition: TSystem.h:279
virtual const char * GetDynamicPath()
Return the dynamic path (used to find shared libraries).
Definition: TSystem.cxx:1788
void Clear()
Clear string without changing its capacity.
Definition: TString.cxx:1176
#define R__WRITE_LOCKGUARD(mutex)
virtual int CompileMacro(const char *filename, Option_t *opt="", const char *library_name="", const char *build_dir="", UInt_t dirmode=0)
This method compiles and loads a shared library containing the code from the file "filename"...
Definition: TSystem.cxx:2831
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1658
virtual void ListLibraries(const char *regexp="")
List all loaded shared libraries.
Definition: TSystem.cxx:2066
virtual const char * GetMakeExe() const
Return the command line use to make an executable.
Definition: TSystem.cxx:3933
void Info(const char *location, const char *msgfmt,...)
virtual void SetDisplay()
Set DISPLAY environment variable based on utmp entry. Only for UNIX.
Definition: TSystem.cxx:229
TString & Append(const char *cs)
Definition: TString.h:559
virtual const char * PrependPathName(const char *dir, TString &name)
Concatenate a directory and a file name.
Definition: TSystem.cxx:1076
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2177
virtual EAclicMode GetAclicMode() const
AclicMode indicates whether the library should be built in debug mode or optimized.
Definition: TSystem.cxx:3915
virtual void ExitLoop()
Exit from event loop.
Definition: TSystem.cxx:390
R__EXTERN TVirtualRWMutex * gCoreMutex
virtual UserGroup_t * GetUserInfo(Int_t uid)
Returns all user info in the UserGroup_t structure.
Definition: TSystem.cxx:1594
virtual int RecvRaw(int sock, void *buffer, int length, int flag)
Receive exactly length bytes into buffer.
Definition: TSystem.cxx:2400
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:499
virtual ~TSystem()
Delete the OS interface.
Definition: TSystem.cxx:135
virtual void Unload(const char *module)
Unload a shared library.
Definition: TSystem.cxx:2045
static constexpr double s
virtual const char * TempDirectory() const
Return a user configured or systemwide directory to create temporary files in.
Definition: TSystem.cxx:1477
static Int_t gLibraryVersionMax
Definition: TSystem.cxx:68
virtual TInetAddress GetHostByName(const char *server)
Get Internet Protocol (IP) address of host.
Definition: TSystem.cxx:2292
R__EXTERN Int_t gDebug
Definition: RtypesCore.h:117
void Error(const char *location, const char *msgfmt,...)
ELogLevel
Definition: TSystem.h:54
virtual void Closelog()
Close connection to system log daemon.
Definition: TSystem.cxx:1687
virtual const char * GetBuildCompiler() const
Return the build compiler.
Definition: TSystem.cxx:3859
TSeqCollection * fFileHandler
Definition: TSystem.h:295
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition: TObject.cxx:705
TString fLinkdefSuffix
Definition: TSystem.h:316
A doubly linked list.
Definition: TList.h:44
TString & GetLastErrorString()
Return the thread local storage for the custom last error message.
Definition: TSystem.cxx:2103
const char * GetUser() const
Definition: TUrl.h:67
static Int_t * gLibraryVersion
Definition: TSystem.cxx:66
virtual EStatus Handle(std::exception &exc)=0
#define R__READ_LOCKGUARD(mutex)
virtual UInt_t LoadAllLibraries()
Load all libraries known to ROOT via the rootmap system.
Definition: TSystem.cxx:1963
void Remove()
Definition: TTimer.h:85
virtual void AddDynamicPath(const char *pathname)
Add a new directory to the dynamic path.
Definition: TSystem.cxx:1780
ESignals
Definition: TEnv.h:87
TString fUser
Definition: TSystem.h:140
virtual const char * GetBuildArch() const
Return the build architecture.
Definition: TSystem.cxx:3851
virtual TTime Now()
Get current time in milliseconds since 0:00 Jan 1 1995.
Definition: TSystem.cxx:461
virtual void Setenv(const char *name, const char *value)
Set environment variable.
Definition: TSystem.cxx:1642
virtual TStdExceptionHandler * RemoveStdExceptionHandler(TStdExceptionHandler *eh)
Remove an exception handler from list of exception handlers.
Definition: TSystem.cxx:619
static void R__WriteDependencyFile(const TString &build_loc, const TString &depfilename, const TString &filename, const TString &library, const TString &libname, const TString &extension, const char *version_var_prefix, const TString &includes, const TString &defines, const TString &incPath)
Definition: TSystem.cxx:2570
ROOT::R::TRInterface & r
Definition: Object.C:4
virtual Bool_t Init()
Initialize the OS interface.
Definition: TSystem.cxx:179
if object ctor succeeded but object should not be used
Definition: TObject.h:68
virtual const char * GetLibraries(const char *regexp="", const char *option="", Bool_t isRegexp=kTRUE)
Return a space separated list of loaded shared libraries.
Definition: TSystem.cxx:2137
auto * a
Definition: textangle.C:12
THashList * GetTable() const
Definition: TEnv.h:141
const char * gProgName
Definition: TSystem.cxx:60
virtual ~ProcInfo_t()
Definition: TSystem.cxx:71
virtual int AcceptConnection(int sock)
Accept a connection.
Definition: TSystem.cxx:2382
void AssignAndDelete(TString &target, char *tobedeleted)
Definition: TSystem.cxx:2498
virtual Int_t RedirectOutput(const char *name, const char *mode="a", RedirectHandle_t *h=nullptr)
Redirect standard output (stdout, stderr) to the specified file.
Definition: TSystem.cxx:1708
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:610
virtual void SetDynamicPath(const char *pathname)
Set the dynamic path to a new value.
Definition: TSystem.cxx:1799
virtual int AnnounceTcpService(int port, Bool_t reuse, int backlog, int tcpwindowsize=-1)
Announce TCP/IP service.
Definition: TSystem.cxx:2346
virtual const char * GetBuildDir() const
Return the path of the build directory.
Definition: TSystem.cxx:3883
virtual Long_t NextTimeOut(Bool_t mode)
Time when next timer of mode (synchronous=kTRUE or asynchronous=kFALSE) will time-out (in ms)...
Definition: TSystem.cxx:492
Bool_t IsSync() const
Definition: TTimer.h:80
static Int_t ConvertVersionCode2Int(Int_t code)
Convert version code to an integer, i.e. 331527 -> 51507.
Definition: TROOT.cxx:2820
unsigned int UInt_t
Definition: RtypesCore.h:44
Int_t GetEntriesFast() const
Definition: TObjArray.h:64
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:891
char * Form(const char *fmt,...)
Ssiz_t Length() const
Definition: TString.h:405
virtual int Umask(Int_t mask)
Set the process file creation mode mask.
Definition: TSystem.cxx:1510
virtual void SetBuildDir(const char *build_dir, Bool_t isflat=kFALSE)
Set the location where ACLiC will create libraries and use as a scratch area.
Definition: TSystem.cxx:4007
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1106
virtual Int_t GetAclicProperties() const
Return the ACLiC properties field.
Definition: TSystem.cxx:3843
virtual int SendBuf(int sock, const void *buffer, int length)
Send a buffer headed by a length indicator.
Definition: TSystem.cxx:2428
virtual const char * HomeDirectory(const char *userName=nullptr)
Return the user&#39;s home directory.
Definition: TSystem.cxx:883
const char * gProgPath
Definition: TSystem.cxx:61
Handles synchronous and a-synchronous timer events.
Definition: TTimer.h:51
virtual void ListSymbols(const char *module, const char *re="")
List symbols in a shared library.
Definition: TSystem.cxx:2057
TFileHandler * gXDisplay
Definition: TSystem.cxx:64
virtual Int_t Exec(const char *shellcmd)
Execute a command.
Definition: TSystem.cxx:651
TString fMakeExe
Definition: TSystem.h:315
virtual int Utime(const char *file, Long_t modtime, Long_t actime)
Set the a files modification and access times.
Definition: TSystem.cxx:1520
char * Strip(const char *str, char c=' ')
Strip leading and trailing c (blanks by default) from a string.
Definition: TString.cxx:2454
virtual void Abort(int code=0)
Abort the application.
Definition: TSystem.cxx:722
virtual void InnerLoop()
Inner event loop.
Definition: TSystem.cxx:398
virtual const char * GetMakeSharedLib() const
Return the command line use to make a shared library.
Definition: TSystem.cxx:3924
virtual void SetSoExt(const char *soExt)
Set shared library extension, should be either .so, .sl, .a, .dll, etc.
Definition: TSystem.cxx:4198
TString fListLibs
Definition: TSystem.h:299
void Warning(const char *location, const char *msgfmt,...)
TString fName
Definition: TNamed.h:32
virtual void Unsetenv(const char *name)
Unset environment variable.
Definition: TSystem.cxx:1650
Int_t fAclicProperties
Definition: TSystem.h:317
if object destructor must call RecursiveRemove()
Definition: TObject.h:60
virtual void FreeDirectory(void *dirp)
Free a directory.
Definition: TSystem.cxx:841
virtual int ClosePipe(FILE *pipe)
Close the pipe.
Definition: TSystem.cxx:669
constexpr Double_t E()
Base of natural log: .
Definition: TMath.h:97
virtual void Run()
System event loop.
Definition: TSystem.cxx:341
#define h(i)
Definition: RSha256.hxx:106
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2490
#define R__LOCKGUARD2(mutex)
virtual int OpenConnection(const char *server, int port, int tcpwindowsize=-1, const char *protocol="tcp")
Open a connection to another host.
Definition: TSystem.cxx:2337
const Bool_t kFALSE
Definition: RtypesCore.h:90
virtual int SetSockOpt(int sock, int kind, int val)
Set socket option.
Definition: TSystem.cxx:2437
const char * extension
Definition: civetweb.c:7793
virtual Int_t Select(TList *active, Long_t timeout)
Select on active file descriptors (called by TMonitor).
Definition: TSystem.cxx:443
virtual const char * FindDynamicLibrary(TString &lib, Bool_t quiet=kFALSE)
Find a dynamic library using the system search paths.
Definition: TSystem.cxx:2027
#define SafeDelete(p)
Definition: RConfig.hxx:543
TString & Remove(Ssiz_t pos)
Definition: TString.h:668
long Long_t
Definition: RtypesCore.h:52
virtual int Chmod(const char *file, UInt_t mode)
Set the file permission bits. Returns -1 in case or error, 0 otherwise.
Definition: TSystem.cxx:1501
virtual TSignalHandler * RemoveSignalHandler(TSignalHandler *sh)
Remove a signal handler from list of signal handlers.
Definition: TSystem.cxx:540
The file contains utilities which are foundational and could be used across the core component of ROO...
EAclicMode fAclicMode
Definition: TSystem.h:313
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2197
virtual Int_t GetEffectiveUid()
Returns the effective user id.
Definition: TSystem.cxx:1565
virtual const char * GetIncludePath()
Get the list of include path.
Definition: TSystem.cxx:3941
virtual std::string GetHomeDirectory(const char *userName=nullptr) const
Return the user&#39;s home directory.
Definition: TSystem.cxx:891
#define ClassImp(name)
Definition: Rtypes.h:361
virtual Func_t DynFindSymbol(const char *module, const char *entry)
Find specific entry point in specified library.
Definition: TSystem.cxx:2037
virtual const char * HostName()
Return the system&#39;s host name.
Definition: TSystem.cxx:301
virtual Bool_t IsFileInIncludePath(const char *name, char **fullpath=nullptr)
Return true if &#39;name&#39; is a file that can be found in the ROOT include path or the current directory...
Definition: TSystem.cxx:962
virtual int Symlink(const char *from, const char *to)
Create a symbolic link from file1 to file2.
Definition: TSystem.cxx:1363
Ssiz_t Index(const TString &str, Ssiz_t *len, Ssiz_t start=0) const
Find the first occurrence of the regexp in string and return the position, or -1 if there is no match...
Definition: TRegexp.cxx:209
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:892
void Printf(const char *fmt,...)
char * DynamicPathName(const char *lib, Bool_t quiet=kFALSE)
Find a dynamic library called lib using the system search paths.
Definition: TSystem.cxx:2013
ELogFacility
Definition: TSystem.h:65
R__EXTERN TEnv * gEnv
Definition: TEnv.h:171
virtual const char * ExpandFileName(const char *fname)
Expand a pathname getting rid of special shell characters like ~.
Definition: TSystem.cxx:1093
TNamed()
Definition: TNamed.h:36
static const TString & GetEtcDir()
Get the sysconfig directory in the installation. Static utility function.
Definition: TROOT.cxx:2939
TString fObjExt
Definition: TSystem.h:312
virtual void SetProgname(const char *name)
Set the application name (from command line, argv[0]) and copy it in gProgName.
Definition: TSystem.cxx:220
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
TSystem * gSystem
Definition: TSystem.cxx:63
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
void Beep(Int_t freq=-1, Int_t duration=-1, Bool_t setDefault=kFALSE)
Beep for duration milliseconds with a tone of frequency freq.
Definition: TSystem.cxx:322
virtual void DispatchOneEvent(Bool_t pendingOnly=kFALSE)
Dispatch a single event.
Definition: TSystem.cxx:427
virtual void CleanCompiledMacros()
Remove the shared libs produced by the CompileMacro() function.
Definition: TSystem.cxx:4330
int CompareTo(const char *cs, ECaseCompare cmp=kExact) const
Compare a string to char *cs2.
Definition: TString.cxx:418
virtual TInetAddress GetSockName(int sock)
Get Internet Protocol (IP) address of host and port #.
Definition: TSystem.cxx:2310
EAccessMode
Definition: TSystem.h:42
virtual void AddLinkedLibs(const char *linkedLib)
Add linkedLib to already set linked libs.
Definition: TSystem.cxx:4132
Bool_t IsNull() const
Definition: TString.h:402
virtual void SetAclicMode(EAclicMode mode)
AclicMode indicates whether the library should be built in debug mode or optimized.
Definition: TSystem.cxx:4041
std::string MakePathRelative(const std::string &path, const std::string &base, bool isBuildingROOT=false)
virtual void DoBeep(Int_t=-1, Int_t=-1) const
Definition: TSystem.h:330
Mother of all ROOT objects.
Definition: TObject.h:37
virtual void SetObjExt(const char *objExt)
Set object files extension, should be either .o, .obj, etc.
Definition: TSystem.cxx:4206
typedef void((*Func_t)())
Int_t fMaxwfd
Definition: TSystem.h:281
TSeqCollection * fTimers
Definition: TSystem.h:293
virtual int RecvBuf(int sock, void *buffer, int length)
Receive a buffer headed by a length indicator.
Definition: TSystem.cxx:2419
virtual void Openlog(const char *name, Int_t options, ELogFacility facility)
Open connection to system log daemon.
Definition: TSystem.cxx:1670
Bool_t R_ISDIR(Int_t mode)
Definition: TSystem.h:114
virtual int GetServiceByName(const char *service)
Get port # of internet service.
Definition: TSystem.cxx:2319
virtual int AnnounceUnixService(int port, int backlog)
Announce unix domain service.
Definition: TSystem.cxx:2364
auto * l
Definition: textangle.C:4
static const TString & GetLibDir()
Get the library directory in the installation. Static utility function.
Definition: TROOT.cxx:2908
virtual void AddTimer(TTimer *t)
Add timer to list of system timers.
Definition: TSystem.cxx:469
virtual void ShowOutput(RedirectHandle_t *h)
Display the content associated with the redirection described by the opaque handle &#39;h&#39;...
Definition: TSystem.cxx:1718
Definition: file.py:1
Bool_t fInControl
Definition: TSystem.h:289
virtual void SetLinkedLibs(const char *linkedLibs)
LinkedLibs should contain the library directory and list of libraries needed to recreate the current ...
Definition: TSystem.cxx:4167
virtual Int_t GetEffectiveGid()
Returns the effective group id.
Definition: TSystem.cxx:1584
virtual void Exit(int code, Bool_t mode=kTRUE)
Exit the application.
Definition: TSystem.cxx:714
#define ROOT_RELEASE
Definition: RVersion.h:17
TString fFlagsDebug
Definition: TSystem.h:306
virtual std::string GetWorkingDirectory() const
Return working directory.
Definition: TSystem.cxx:875
virtual int GetProcInfo(ProcInfo_t *info) const
Returns cpu and memory used by this process into the ProcInfo_t structure.
Definition: TSystem.cxx:2490
const Int_t kMaxInt
Definition: RtypesCore.h:101
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
Long_t fIno
Definition: TSystem.h:125
#define snprintf
Definition: civetweb.c:1540
TString fFlagsOpt
Definition: TSystem.h:307
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
virtual int CopyFile(const char *from, const char *to, Bool_t overwrite=kFALSE)
Copy a file.
Definition: TSystem.cxx:1336
virtual void * OpenDirectory(const char *name)
Open a directory. Returns 0 if directory does not exist.
Definition: TSystem.cxx:832
const char * proto
Definition: civetweb.c:16604
Iterator of ordered collection.
#define c(i)
Definition: RSha256.hxx:101
virtual void AddIncludePath(const char *includePath)
Add includePath to the already set include path.
Definition: TSystem.cxx:4121
virtual void AddFileHandler(TFileHandler *fh)
Add a file handler to the list of system file handlers.
Definition: TSystem.cxx:552
static void ResetErrno()
Static function resetting system error number.
Definition: TSystem.cxx:274
static const TString & GetBinDir()
Get the binary directory in the installation. Static utility function.
Definition: TROOT.cxx:2887
static const char * StripOffProto(const char *path, const char *proto)
Strip off protocol string from specified path.
Definition: TSystem.cxx:113
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition: TSystem.cxx:1269
TString fMakeSharedLib
Definition: TSystem.h:314
Int_t fBeepDuration
Definition: TSystem.h:287
void SetErrorStr(const char *errstr)
Set the system error string.
Definition: TSystem.cxx:239
Long_t fDev
Definition: TSystem.h:124
#define I(x, y, z)
TString fSoExt
Definition: TSystem.h:311
virtual int GetSockOpt(int sock, int kind, int *val)
Get socket option.
Definition: TSystem.cxx:2446
virtual Int_t GetUid(const char *user=nullptr)
Returns the user&#39;s id. If user = 0, returns current user&#39;s id.
Definition: TSystem.cxx:1555
const char * gRootDir
Definition: TSystem.cxx:59
Abstract base class defining a generic interface to the underlying Operating System.
Definition: TSystem.h:265
Ordered collection.
virtual void SetLinkdefSuffix(const char *suffix)
The &#39;suffix&#39; will be appended to the name of a script loaded by ACLiC and used to locate any eventual...
Definition: TSystem.cxx:4189
virtual Int_t GetFPEMask()
Return the bitmap of conditions that trigger a floating point exception.
Definition: TSystem.cxx:630
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition: TEnv.cxx:491
virtual void TurnOn()
Add the timer to the system timer list.
Definition: TTimer.cxx:241
#define RETRY
Definition: TException.h:49
static Int_t gLibraryVersionIdx
Definition: TSystem.cxx:67
const Bool_t kTRUE
Definition: RtypesCore.h:89
void AbstractMethod(const char *method) const
Use this method to implement an "abstract" method that you don&#39;t want to leave purely abstract...
Definition: TObject.cxx:933
virtual char * ConcatFileName(const char *dir, const char *name)
Concatenate a directory and a file name. User must delete returned string.
Definition: TSystem.cxx:1066
Bool_t IsAsync() const
Definition: TTimer.h:81
const Int_t n
Definition: legend1.C:16
virtual const char * GetObjExt() const
Get the object file extension.
Definition: TSystem.cxx:3989
TString fIncludePath
Definition: TSystem.h:309
virtual const char * GetError()
Return system error string.
Definition: TSystem.cxx:248
char name[80]
Definition: TGX11.cxx:109
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:877
static Int_t * ReAllocInt(Int_t *vp, size_t size, size_t oldsize)
Reallocate (i.e.
Definition: TStorage.cxx:295
virtual void SetIncludePath(const char *includePath)
IncludePath should contain the list of compiler flags to indicate where to find user defined header f...
Definition: TSystem.cxx:4156
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
TString & Chop()
Definition: TString.h:674
TSystem(const TSystem &)=delete
TProcessEventTimer(Long_t delay)
Create async event processor timer. Delay is in milliseconds.
Definition: TSystem.cxx:77
const char * Data() const
Definition: TString.h:364
virtual void IgnoreSignal(ESignals sig, Bool_t ignore=kTRUE)
If ignore is true ignore the specified signal, else restore previous behaviour.
Definition: TSystem.cxx:591
virtual void StopIdleing()