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