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