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