TSystem.cxx

Go to the documentation of this file.
00001 // @(#)root/base:$Id: TSystem.cxx 37109 2010-11-30 16:30:58Z pcanal $
00002 // Author: Fons Rademakers   15/09/95
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // TSystem                                                              //
00015 //                                                                      //
00016 // Abstract base class defining a generic interface to the underlying   //
00017 // Operating System.                                                    //
00018 // This is not an ABC in the strict sense of the (C++) word. For        //
00019 // every member function there is an implementation (often not more     //
00020 // than a call to AbstractMethod() which prints a warning saying        //
00021 // that the method should be overridden in a derived class), which      //
00022 // allows a simple partial implementation for new OS'es.                //
00023 //                                                                      //
00024 //////////////////////////////////////////////////////////////////////////
00025 
00026 #ifdef WIN32
00027 #include <io.h>
00028 #endif
00029 #include <stdlib.h>
00030 #include <errno.h>
00031 #include <algorithm>
00032 #include <sys/stat.h>
00033 
00034 #include "Riostream.h"
00035 #include "TSystem.h"
00036 #include "TApplication.h"
00037 #include "TException.h"
00038 #include "TROOT.h"
00039 #include "TClass.h"
00040 #include "TClassTable.h"
00041 #include "TEnv.h"
00042 #include "TBrowser.h"
00043 #include "TString.h"
00044 #include "TOrdCollection.h"
00045 #include "TInterpreter.h"
00046 #include "TRegexp.h"
00047 #include "TTimer.h"
00048 #include "TObjString.h"
00049 #include "TError.h"
00050 #include "TPluginManager.h"
00051 #include "TUrl.h"
00052 #include "TVirtualMutex.h"
00053 #include "compiledata.h"
00054 #include "RConfigure.h"
00055 
00056 const char *gRootDir;
00057 const char *gProgName;
00058 const char *gProgPath;
00059 
00060 TSystem      *gSystem   = 0;
00061 TFileHandler *gXDisplay = 0;  // Display server event handler, set in TGClient
00062 
00063 static Int_t *gLibraryVersion    = 0;   // Set in TVersionCheck, used in Load()
00064 static Int_t  gLibraryVersionIdx = 0;   // Set in TVersionCheck, used in Load()
00065 static Int_t  gLibraryVersionMax = 256;
00066 
00067 ClassImp(TProcessEventTimer)
00068 
00069 //______________________________________________________________________________
00070 TProcessEventTimer::TProcessEventTimer(Long_t delay) : TTimer(delay, kFALSE)
00071 {
00072    // Create async event processor timer. Delay is in milliseconds.
00073 
00074    gROOT->SetInterrupt(kFALSE);
00075    TurnOn();
00076 }
00077 
00078 //______________________________________________________________________________
00079 Bool_t TProcessEventTimer::ProcessEvents()
00080 {
00081    // Process events if timer did time out. Returns kTRUE if interrupt
00082    // flag is set (by hitting a key in the canvas or selecting the
00083    // Interrupt menu item in canvas or some other action).
00084 
00085    if (fTimeout) {
00086       if (gSystem->ProcessEvents()) {
00087          Remove();
00088          return kTRUE;
00089       } else {
00090          Reset();
00091          return kFALSE;
00092       }
00093    }
00094    return kFALSE;
00095 }
00096 
00097 
00098 
00099 ClassImp(TSystem)
00100 
00101 TVirtualMutex* gSystemMutex = 0;
00102 
00103 //______________________________________________________________________________
00104 TSystem::TSystem(const char *name, const char *title) : TNamed(name, title), fAclicProperties(0)
00105 {
00106    // Create a new OS interface.
00107 
00108    if (gSystem && name[0] != '-' && strcmp(name, "Generic"))
00109       Error("TSystem", "only one instance of TSystem allowed");
00110 
00111    fOnExitList          = 0;
00112    fSignalHandler       = 0;
00113    fFileHandler         = 0;
00114    fStdExceptionHandler = 0;
00115    fTimers              = 0;
00116    fCompiled            = 0;
00117    fHelpers             = 0;
00118    fInsideNotify        = kFALSE;
00119    fBeepDuration        = 0;
00120    fBeepFreq            = 0;
00121    fReadmask            = 0;
00122    fWritemask           = 0;
00123    fReadready           = 0;
00124    fWriteready          = 0;
00125    fSignals             = 0;
00126    fDone                = kFALSE;
00127    fAclicMode           = kDefault;
00128    fInControl           = kFALSE;
00129    fLevel               = 0;
00130    fMaxrfd              = -1;
00131    fMaxwfd              = -1;
00132    fNfd                 = 0;
00133    fSigcnt              = 0;
00134 
00135    gLibraryVersion = new Int_t [gLibraryVersionMax];
00136    memset(gLibraryVersion, 0, gLibraryVersionMax*sizeof(Int_t));
00137 }
00138 
00139 //______________________________________________________________________________
00140 TSystem::~TSystem()
00141 {
00142    // Delete the OS interface.
00143 
00144    if (fOnExitList) {
00145       fOnExitList->Delete();
00146       SafeDelete(fOnExitList);
00147    }
00148 
00149    if (fSignalHandler) {
00150       fSignalHandler->Delete();
00151       SafeDelete(fSignalHandler);
00152    }
00153 
00154    if (fFileHandler) {
00155       fFileHandler->Delete();
00156       SafeDelete(fFileHandler);
00157    }
00158 
00159    if (fStdExceptionHandler) {
00160       fStdExceptionHandler->Delete();
00161       SafeDelete(fStdExceptionHandler);
00162    }
00163 
00164    if (fTimers) {
00165       fTimers->Delete();
00166       SafeDelete(fTimers);
00167    }
00168 
00169    if (fCompiled) {
00170       fCompiled->Delete();
00171       SafeDelete(fCompiled);
00172    }
00173 
00174    if (fHelpers) {
00175       fHelpers->Delete();
00176       SafeDelete(fHelpers);
00177    }
00178 
00179    if (gSystem == this)
00180       gSystem = 0;
00181 }
00182 
00183 //______________________________________________________________________________
00184 Bool_t TSystem::Init()
00185 {
00186    // Initialize the OS interface.
00187 
00188    fNfd    = 0;
00189    fMaxrfd = -1;
00190    fMaxwfd = -1;
00191 
00192    fSigcnt = 0;
00193    fLevel  = 0;
00194 
00195    fSignalHandler       = new TOrdCollection;
00196    fFileHandler         = new TOrdCollection;
00197    fStdExceptionHandler = new TOrdCollection;
00198    fTimers              = new TOrdCollection;
00199 
00200    fBuildArch     = BUILD_ARCH;
00201    fBuildCompiler = COMPILER;
00202    fBuildCompilerVersion = COMPILERVERS;
00203    fBuildNode     = BUILD_NODE;
00204    fFlagsDebug    = CXXDEBUG;
00205    fFlagsOpt      = CXXOPT;
00206    fIncludePath   = INCLUDEPATH;
00207    fLinkedLibs    = LINKEDLIBS;
00208    fSoExt         = SOEXT;
00209    fObjExt        = OBJEXT;
00210    fAclicMode     = kDefault;
00211    fMakeSharedLib = MAKESHAREDLIB;
00212    fMakeExe       = MAKEEXE;
00213    fCompiled      = new TOrdCollection;
00214 
00215    if (gEnv && fBeepDuration == 0 && fBeepFreq == 0) {
00216       fBeepDuration = gEnv->GetValue("Root.System.BeepDuration", 100);
00217       fBeepFreq     = gEnv->GetValue("Root.System.BeepFreq", 440);
00218    }
00219    if (!fName.CompareTo("Generic")) return kTRUE;
00220    return kFALSE;
00221 }
00222 
00223 //______________________________________________________________________________
00224 void TSystem::SetProgname(const char *name)
00225 {
00226    // Set the application name (from command line, argv[0]) and copy it in
00227    // gProgName.
00228 
00229    gProgName = StrDup(name);
00230 }
00231 
00232 //______________________________________________________________________________
00233 void TSystem::SetDisplay()
00234 {
00235    // Set DISPLAY environment variable based on utmp entry. Only for UNIX.
00236 }
00237 
00238 //______________________________________________________________________________
00239 void TSystem::SetErrorStr(const char *errstr)
00240 {
00241    // Set the system error string. This string will be used by GetError().
00242    // To be used in case one does not want or can use the system error
00243    // string (e.g. because error is generated by a third party POSIX like
00244    // library that does not use standard errno).
00245 
00246    ResetErrno();   // so GetError() uses the fLastErrorString
00247    fLastErrorString = errstr;
00248 }
00249 
00250 //______________________________________________________________________________
00251 const char *TSystem::GetError()
00252 {
00253    // Return system error string.
00254 
00255    if (GetErrno() == 0 && fLastErrorString != "")
00256       return fLastErrorString;
00257    return Form("errno: %d", GetErrno());
00258 }
00259 
00260 //______________________________________________________________________________
00261 Int_t TSystem::GetErrno()
00262 {
00263    // Static function returning system error number.
00264 
00265 #ifdef _REENTRANT
00266    return errno; // errno can be a macro if _REENTRANT is set
00267 #else
00268 #ifdef R__SOLARIS_CC50
00269    return ::errno;
00270 #else
00271    return errno;
00272 #endif
00273 #endif
00274 }
00275 
00276 //______________________________________________________________________________
00277 void TSystem::ResetErrno()
00278 {
00279    // Static function resetting system error number.
00280 
00281 #ifdef _REENTRANT
00282    errno = 0; // errno can be a macro if _REENTRANT is set
00283 #else
00284 #ifdef R__SOLARIS_CC50
00285    ::errno = 0;
00286 #else
00287    errno = 0;
00288 #endif
00289 #endif
00290 }
00291 
00292 //______________________________________________________________________________
00293 void TSystem::RemoveOnExit(TObject *obj)
00294 {
00295    // Objects that should be deleted on exit of the OS interface.
00296 
00297    if (fOnExitList == 0)
00298       fOnExitList = new TOrdCollection;
00299    if (fOnExitList->FindObject(obj) == 0)
00300       fOnExitList->Add(obj);
00301 }
00302 
00303 //______________________________________________________________________________
00304 const char *TSystem::HostName()
00305 {
00306    // Return the system's host name.
00307 
00308    return "Local host";
00309 }
00310 
00311 //______________________________________________________________________________
00312 void TSystem::NotifyApplicationCreated()
00313 {
00314    // Hook to tell TSystem that the TApplication object has been created.
00315 
00316    // Currently needed only for WinNT interface.
00317 }
00318 
00319 //______________________________________________________________________________
00320 void TSystem::Beep(Int_t freq /*=-1*/, Int_t duration /*=-1*/,
00321                    Bool_t setDefault /*=kFALSE*/)
00322 {
00323    // Beep for duration milliseconds with a tone of freqency freq.
00324    // Defaults to printing the '\a' character to stdout.
00325    // If freq or duration is <0 respectively, use default value.
00326    // If setDefault is set, only set the frequency and duration as
00327    // new defaults, but don't beep.
00328    // If default freq or duration is <0, never beep (silence)
00329 
00330    if (setDefault) {
00331       fBeepFreq     = freq;
00332       fBeepDuration = duration;
00333       return;
00334    }
00335    if (fBeepDuration < 0 || fBeepFreq < 0) return; // silence
00336    if (freq < 0) freq = fBeepFreq;
00337    if (duration < 0) duration = fBeepDuration;
00338    DoBeep(freq, duration);
00339 }
00340 
00341 //---- EventLoop ---------------------------------------------------------------
00342 
00343 //______________________________________________________________________________
00344 void TSystem::Run()
00345 {
00346    // System event loop.
00347 
00348    fInControl = kTRUE;
00349    fDone      = kFALSE;
00350 
00351 loop_entry:
00352    try {
00353       RETRY {
00354          while (!fDone) {
00355             gApplication->StartIdleing();
00356             InnerLoop();
00357             gApplication->StopIdleing();
00358          }
00359       } ENDTRY;
00360    }
00361    catch (std::exception& exc) {
00362       TIter next(fStdExceptionHandler);
00363       TStdExceptionHandler* eh = 0;
00364       while ((eh = (TStdExceptionHandler*) next())) {
00365          switch (eh->Handle(exc))
00366          {
00367             case TStdExceptionHandler::kSEProceed:
00368                break;
00369             case TStdExceptionHandler::kSEHandled:
00370                goto loop_entry;
00371                break;
00372             case TStdExceptionHandler::kSEAbort:
00373                Warning("Run", "instructed to abort");
00374                goto loop_end;
00375                break;
00376          }
00377       }
00378       throw;
00379    }
00380    catch (const char *str) {
00381       printf("%s\n", str);
00382    }
00383    // handle every exception
00384    catch (...) {
00385       Warning("Run", "handle uncaugth exception, terminating");
00386    }
00387 
00388 loop_end:
00389    fInControl = kFALSE;
00390 }
00391 
00392 //______________________________________________________________________________
00393 void TSystem::ExitLoop()
00394 {
00395    // Exit from event loop.
00396 
00397    fDone = kTRUE;
00398 }
00399 
00400 //______________________________________________________________________________
00401 void TSystem::InnerLoop()
00402 {
00403    // Inner event loop.
00404 
00405    fLevel++;
00406    DispatchOneEvent();
00407    fLevel--;
00408 }
00409 
00410 //______________________________________________________________________________
00411 Bool_t TSystem::ProcessEvents()
00412 {
00413    // Process pending events (GUI, timers, sockets). Returns the result of
00414    // TROOT::IsInterrupted(). The interrupt flag (TROOT::SetInterrupt())
00415    // can be set during the handling of the events. This mechanism allows
00416    // macros running in tight calculating loops to be interrupted by some
00417    // GUI event (depending on the interval with which this method is
00418    // called). For example hitting ctrl-c in a canvas will set the
00419    // interrupt flag.
00420 
00421    gROOT->SetInterrupt(kFALSE);
00422 
00423    DispatchOneEvent(kTRUE);
00424 
00425    return gROOT->IsInterrupted();
00426 }
00427 
00428 //______________________________________________________________________________
00429 void TSystem::DispatchOneEvent(Bool_t)
00430 {
00431    // Dispatch a single event.
00432 
00433    AbstractMethod("DispatchOneEvent");
00434 }
00435 
00436 //______________________________________________________________________________
00437 void TSystem::Sleep(UInt_t)
00438 {
00439    // Sleep milliSec milli seconds.
00440 
00441    AbstractMethod("Sleep");
00442 }
00443 
00444 //______________________________________________________________________________
00445 Int_t TSystem::Select(TList *, Long_t)
00446 {
00447    // Select on active file descriptors (called by TMonitor).
00448 
00449    AbstractMethod("Select");
00450    return -1;
00451 }
00452 //______________________________________________________________________________
00453 Int_t TSystem::Select(TFileHandler *, Long_t)
00454 {
00455    // Select on active file descriptors (called by TMonitor).
00456 
00457    AbstractMethod("Select");
00458    return -1;
00459 }
00460 
00461 //---- handling of system events -----------------------------------------------
00462 //______________________________________________________________________________
00463 TTime TSystem::Now()
00464 {
00465    // Get current time in milliseconds since 0:00 Jan 1 1995.
00466 
00467    return TTime(0);
00468 }
00469 
00470 //______________________________________________________________________________
00471 void TSystem::AddTimer(TTimer *ti)
00472 {
00473    // Add timer to list of system timers.
00474 
00475    if (ti && fTimers && (fTimers->FindObject(ti) == 0))
00476       fTimers->Add(ti);
00477 }
00478 
00479 //______________________________________________________________________________
00480 TTimer *TSystem::RemoveTimer(TTimer *ti)
00481 {
00482    // Remove timer from list of system timers. Returns removed timer or 0
00483    // if timer was not active.
00484 
00485    if (fTimers) {
00486       TTimer *tr = (TTimer*) fTimers->Remove(ti);
00487       return tr;
00488    }
00489    return 0;
00490 }
00491 
00492 //______________________________________________________________________________
00493 Long_t TSystem::NextTimeOut(Bool_t mode)
00494 {
00495    // Time when next timer of mode (synchronous=kTRUE or
00496    // asynchronous=kFALSE) will time-out (in ms).
00497 
00498    if (!fTimers) return -1;
00499 
00500    TOrdCollectionIter it((TOrdCollection*)fTimers);
00501    TTimer *t, *to = 0;
00502    Long64_t tt, tnow = Now();
00503    Long_t   timeout = -1;
00504 
00505    while ((t = (TTimer *) it.Next())) {
00506       if (t->IsSync() == mode) {
00507          tt = (Long64_t)t->GetAbsTime() - tnow;
00508          if (tt < 0) tt = 0;
00509          if (timeout == -1) {
00510             timeout = (Long_t)tt;
00511             to = t;
00512          }
00513          if (tt < timeout) {
00514             timeout = (Long_t)tt;
00515             to = t;
00516          }
00517       }
00518    }
00519 
00520    if (to && to->IsAsync() && timeout > 0) {
00521       if (to->IsInterruptingSyscalls())
00522          SigAlarmInterruptsSyscalls(kTRUE);
00523       else
00524          SigAlarmInterruptsSyscalls(kFALSE);
00525    }
00526 
00527    return timeout;
00528 }
00529 
00530 //______________________________________________________________________________
00531 void TSystem::AddSignalHandler(TSignalHandler *h)
00532 {
00533    // Add a signal handler to list of system signal handlers. Only adds
00534    // the handler if it is not already in the list of signal handlers.
00535 
00536    if (h && fSignalHandler && (fSignalHandler->FindObject(h) == 0))
00537       fSignalHandler->Add(h);
00538 }
00539 
00540 //______________________________________________________________________________
00541 TSignalHandler *TSystem::RemoveSignalHandler(TSignalHandler *h)
00542 {
00543    // Remove a signal handler from list of signal handlers. Returns
00544    // the handler or 0 if the handler was not in the list of signal handlers.
00545 
00546    if (fSignalHandler)
00547       return (TSignalHandler *)fSignalHandler->Remove(h);
00548 
00549    return 0;
00550 }
00551 
00552 //______________________________________________________________________________
00553 void TSystem::AddFileHandler(TFileHandler *h)
00554 {
00555    // Add a file handler to the list of system file handlers. Only adds
00556    // the handler if it is not already in the list of file handlers.
00557 
00558    if (h && fFileHandler && (fFileHandler->FindObject(h) == 0))
00559       fFileHandler->Add(h);
00560 }
00561 
00562 //______________________________________________________________________________
00563 TFileHandler *TSystem::RemoveFileHandler(TFileHandler *h)
00564 {
00565    // Remove a file handler from the list of file handlers. Returns
00566    // the handler or 0 if the handler was not in the list of file handlers.
00567 
00568    if (fFileHandler)
00569       return (TFileHandler *)fFileHandler->Remove(h);
00570 
00571    return 0;
00572 }
00573 
00574 //______________________________________________________________________________
00575 void TSystem::ResetSignal(ESignals /*sig*/, Bool_t /*reset*/)
00576 {
00577    // If reset is true reset the signal handler for the specified signal
00578    // to the default handler, else restore previous behaviour.
00579 
00580    AbstractMethod("ResetSignal");
00581 }
00582 
00583 //______________________________________________________________________________
00584 void TSystem::IgnoreSignal(ESignals /*sig*/, Bool_t /*ignore*/)
00585 {
00586    // If ignore is true ignore the specified signal, else restore previous
00587    // behaviour.
00588 
00589    AbstractMethod("IgnoreSignal");
00590 }
00591 
00592 //______________________________________________________________________________
00593 void TSystem::IgnoreInterrupt(Bool_t ignore)
00594 {
00595    // If ignore is true ignore the interrupt signal, else restore previous
00596    // behaviour. Typically call ignore interrupt before writing to disk.
00597 
00598    IgnoreSignal(kSigInterrupt, ignore);
00599 }
00600 
00601 //______________________________________________________________________________
00602 void TSystem::AddStdExceptionHandler(TStdExceptionHandler *eh)
00603 {
00604    // Add an exception handler to list of system exception handlers. Only adds
00605    // the handler if it is not already in the list of exception handlers.
00606 
00607    if (eh && fStdExceptionHandler && (fStdExceptionHandler->FindObject(eh) == 0))
00608       fStdExceptionHandler->Add(eh);
00609 }
00610 
00611 //______________________________________________________________________________
00612 TStdExceptionHandler *TSystem::RemoveStdExceptionHandler(TStdExceptionHandler *eh)
00613 {
00614    // Remove an exception handler from list of exception handlers. Returns
00615    // the handler or 0 if the handler was not in the list of exception handlers.
00616 
00617    if (fStdExceptionHandler)
00618       return (TStdExceptionHandler *)fStdExceptionHandler->Remove(eh);
00619 
00620    return 0;
00621 }
00622 
00623 //______________________________________________________________________________
00624 Int_t TSystem::GetFPEMask()
00625 {
00626    // Return the bitmap of conditions that trigger a floating point exception.
00627 
00628    AbstractMethod("GetFPEMask");
00629    return 0;
00630 }
00631 
00632 //______________________________________________________________________________
00633 Int_t TSystem::SetFPEMask(Int_t)
00634 {
00635    // Set which conditions trigger a floating point exception.
00636    // Return the previous set of conditions.
00637 
00638    AbstractMethod("SetFPEMask");
00639    return 0;
00640 }
00641 
00642 //---- Processes ---------------------------------------------------------------
00643 
00644 //______________________________________________________________________________
00645 int TSystem::Exec(const char*)
00646 {
00647    // Execute a command.
00648 
00649    AbstractMethod("Exec");
00650    return -1;
00651 }
00652 
00653 //______________________________________________________________________________
00654 FILE *TSystem::OpenPipe(const char*, const char*)
00655 {
00656    // Open a pipe.
00657 
00658    AbstractMethod("OpenPipe");
00659    return 0;
00660 }
00661 
00662 //______________________________________________________________________________
00663 int TSystem::ClosePipe(FILE*)
00664 {
00665    // Close the pipe.
00666 
00667    AbstractMethod("ClosePipe");
00668    return -1;
00669 }
00670 
00671 //______________________________________________________________________________
00672 TString TSystem::GetFromPipe(const char *command)
00673 {
00674    // Execute command and return output in TString.
00675 
00676    TString out;
00677 
00678    FILE *pipe = OpenPipe(command, "r");
00679    if (!pipe) {
00680       SysError("GetFromPipe", "cannot run command \"%s\"", command);
00681       return out;
00682    }
00683 
00684    TString line;
00685    while (line.Gets(pipe)) {
00686       if (out != "")
00687          out += "\n";
00688       out += line;
00689    }
00690 
00691    Int_t r = ClosePipe(pipe);
00692    if (r) {
00693       Error("GetFromPipe", "command \"%s\" returned %d", command, r);
00694    }
00695    return out;
00696 }
00697 
00698 //______________________________________________________________________________
00699 int TSystem::GetPid()
00700 {
00701    // Get process id.
00702    AbstractMethod("GetPid");
00703    return -1;
00704 }
00705 
00706 //______________________________________________________________________________
00707 void TSystem::Exit(int, Bool_t)
00708 {
00709    // Exit the application.
00710 
00711    AbstractMethod("Exit");
00712 }
00713 
00714 //______________________________________________________________________________
00715 void TSystem::Abort(int)
00716 {
00717    // Abort the application.
00718 
00719    AbstractMethod("Abort");
00720 }
00721 
00722 //______________________________________________________________________________
00723 void TSystem::StackTrace()
00724 {
00725    // Print a stack trace.
00726 
00727    AbstractMethod("StackTrace");
00728 }
00729 
00730 
00731 //---- Directories -------------------------------------------------------------
00732 
00733 //______________________________________________________________________________
00734 TSystem *TSystem::FindHelper(const char *path, void *dirptr)
00735 {
00736    // Create helper TSystem to handle file and directory operations that
00737    // might be special for remote file access, like via rfiod or rootd.
00738 
00739    if (!fHelpers)
00740       fHelpers = new TOrdCollection;
00741 
00742    TPluginHandler *h;
00743    TSystem *helper = 0;
00744    TUrl url(path, kTRUE);
00745 
00746    // look for existing helpers
00747    TIter next(fHelpers);
00748    while ((helper = (TSystem*) next()))
00749       if (helper->ConsistentWith(path, dirptr))
00750          return helper;
00751 
00752    if (!path)
00753       return 0;
00754 
00755    // create new helper
00756    TRegexp re("^root.*:");  // also roots, rootk, etc
00757    TString pname = path;
00758    if (pname.Index(re) != kNPOS) {
00759       // (x)rootd daemon ...
00760       if ((h = gROOT->GetPluginManager()->FindHandler("TSystem", path))) {
00761          if (h->LoadPlugin() == -1)
00762             return 0;
00763          helper = (TSystem*) h->ExecPlugin(2, path, kFALSE);
00764       }
00765    } else if ((h = gROOT->GetPluginManager()->FindHandler("TSystem", path))) {
00766       if (h->LoadPlugin() == -1)
00767          return 0;
00768       helper = (TSystem*) h->ExecPlugin(0);
00769    }
00770 
00771    if (helper)
00772       fHelpers->Add(helper);
00773 
00774    return helper;
00775 }
00776 
00777 //______________________________________________________________________________
00778 Bool_t TSystem::ConsistentWith(const char *path, void *dirptr)
00779 {
00780    // Check consistency of this helper with the one required
00781    // by 'path' or 'dirptr'
00782 
00783    Bool_t checkproto = kFALSE;
00784    if (path) {
00785       if (!GetDirPtr()) {
00786          TUrl url(path, kTRUE);
00787          if (!strncmp(url.GetProtocol(), GetName(), strlen(GetName())))
00788             checkproto = kTRUE;
00789       }
00790    }
00791 
00792    Bool_t checkdir = kFALSE;
00793    if (GetDirPtr() && GetDirPtr() == dirptr)
00794       checkdir = kTRUE;
00795 
00796    return (checkproto || checkdir);
00797 }
00798 
00799 //______________________________________________________________________________
00800 int TSystem::MakeDirectory(const char*)
00801 {
00802    // Make a directory. Returns 0 in case of success and
00803    // -1 if the directory could not be created (either already exists or
00804    // illegal path name).
00805 
00806    AbstractMethod("MakeDirectory");
00807    return 0;
00808 }
00809 
00810 //______________________________________________________________________________
00811 void *TSystem::OpenDirectory(const char*)
00812 {
00813    // Open a directory. Returns 0 if directory does not exist.
00814 
00815    AbstractMethod("OpenDirectory");
00816    return 0;
00817 }
00818 
00819 //______________________________________________________________________________
00820 void TSystem::FreeDirectory(void*)
00821 {
00822    // Free a directory.
00823 
00824    AbstractMethod("FreeDirectory");
00825 }
00826 
00827 //______________________________________________________________________________
00828 const char *TSystem::GetDirEntry(void*)
00829 {
00830    // Get a directory entry. Returns 0 if no more entries.
00831 
00832    AbstractMethod("GetDirEntry");
00833    return 0;
00834 }
00835 
00836 //______________________________________________________________________________
00837 Bool_t TSystem::ChangeDirectory(const char*)
00838 {
00839    // Change directory.
00840 
00841    AbstractMethod("ChangeDirectory");
00842    return kFALSE;
00843 }
00844 
00845 //______________________________________________________________________________
00846 const char *TSystem::WorkingDirectory()
00847 {
00848    // Return working directory.
00849 
00850    return 0;
00851 }
00852 
00853 //______________________________________________________________________________
00854 const char *TSystem::HomeDirectory(const char*)
00855 {
00856    // Return the user's home directory.
00857 
00858    return 0;
00859 }
00860 
00861 //______________________________________________________________________________
00862 int TSystem::mkdir(const char *name, Bool_t recursive)
00863 {
00864    // Make a file system directory. Returns 0 in case of success and
00865    // -1 if the directory could not be created (either already exists or
00866    // illegal path name).
00867    // If 'recursive' is true, makes parent directories as needed.
00868 
00869    if (recursive) {
00870       TString safeName = name; // local copy in case 'name' is output from
00871                                // TSystem::DirName as it uses static buffers
00872       TString dirname = DirName(safeName);
00873       if (!dirname.Length()) {
00874          // well we should not have to make the root of the file system!
00875          // (and this avoid infinite recursions!)
00876          return -1;
00877       }
00878       if (AccessPathName(dirname, kFileExists)) {
00879          int res = mkdir(dirname, kTRUE);
00880          if (res) return res;
00881       }
00882       if (!AccessPathName(safeName, kFileExists)) {
00883          return -1;
00884       }
00885    }
00886 
00887    return MakeDirectory(name);
00888 }
00889 
00890 //---- Paths & Files -----------------------------------------------------------
00891 
00892 //______________________________________________________________________________
00893 const char *TSystem::BaseName(const char *name)
00894 {
00895    // Base name of a file name. Base name of /user/root is root.
00896 
00897    if (name) {
00898       if (name[0] == '/' && name[1] == '\0')
00899          return name;
00900       char *cp;
00901       if ((cp = (char*)strrchr(name, '/')))
00902          return ++cp;
00903       return name;
00904    }
00905    Error("BaseName", "name = 0");
00906    return 0;
00907 }
00908 
00909 //______________________________________________________________________________
00910 Bool_t TSystem::IsAbsoluteFileName(const char *dir)
00911 {
00912    // Return true if dir is an absolute pathname.
00913 
00914    if (dir)
00915       return dir[0] == '/';
00916    return kFALSE;
00917 }
00918 
00919 //______________________________________________________________________________
00920 Bool_t TSystem::IsFileInIncludePath(const char *name, char **fullpath)
00921 {
00922    // Return true if 'name' is a file that can be found in the ROOT include
00923    // path or the current directory.
00924    // If 'name' contains any ACLiC style information (e.g. trailing +[+][g|O]),
00925    // it will be striped off 'name'.
00926    // If fullpath is != 0, the full path to the file is returned in *fullpath,
00927    // which must be deleted by the caller.
00928 
00929    if (!name || !strlen(name)) return kFALSE;
00930 
00931    TString aclicMode;
00932    TString arguments;
00933    TString io;
00934    TString realname = SplitAclicMode(name, aclicMode, arguments, io);
00935 
00936    TString fileLocation = DirName(realname);
00937 
00938    TString incPath = gSystem->GetIncludePath(); // of the form -Idir1  -Idir2 -Idir3
00939    incPath.Append(":").Prepend(" ");
00940    incPath.ReplaceAll(" -I",":");       // of form :dir1 :dir2:dir3
00941    while ( incPath.Index(" :") != -1 ) {
00942       incPath.ReplaceAll(" :",":");
00943    }
00944    incPath.Prepend(fileLocation+":.:");
00945 
00946    char *actual = Which(incPath,realname);
00947 
00948    if (!actual) {
00949       return kFALSE;
00950    } else {
00951       if (fullpath)
00952          *fullpath = actual;
00953       else
00954          delete [] actual;
00955       return kTRUE;
00956    }
00957 }
00958 
00959 //______________________________________________________________________________
00960 const char *TSystem::DirName(const char *pathname)
00961 {
00962    // Return the directory name in pathname. DirName of /user/root is /user.
00963    // In case no dirname is specified "." is returned.
00964 
00965    if (pathname && strchr(pathname, '/')) {
00966       R__LOCKGUARD2(gSystemMutex);
00967 
00968       static int len = 0;
00969       static char *buf = 0;
00970       int pathlen = strlen(pathname);
00971       if (pathlen > len) {
00972          delete [] buf;
00973          len = pathlen;
00974          buf = new char [len+1];
00975       }
00976       strcpy(buf, pathname);
00977 
00978       char *r = buf+pathlen-1;
00979       // First skip the trailing '/'
00980       while ( r>buf && *(r)=='/') { --r; }
00981       // Then find the next non slash
00982       while ( r>buf && *(r)!='/') { --r; }
00983       // Then skip duplicate slashes
00984       // Note the 'r>buf' is a strict comparison to allows '/topdir' to return '/'
00985       while ( r>buf && *(r)=='/') { --r; }
00986       // And finally terminate the string to drop off the filename
00987       *(r+1) = '\0';
00988 
00989       return buf;
00990    }
00991    return ".";
00992 }
00993 
00994 //______________________________________________________________________________
00995 const char *TSystem::UnixPathName(const char *name)
00996 {
00997    // Convert from a Unix pathname to a local pathname. E.g. from /user/root to \user\root.
00998 
00999    return name;
01000 }
01001 
01002 //______________________________________________________________________________
01003 char *TSystem::ConcatFileName(const char *dir, const char *name)
01004 {
01005    // Concatenate a directory and a file name. User must delete returned string.
01006 
01007    TString nameString(name);
01008    PrependPathName(dir, nameString);
01009    return StrDup(nameString.Data());
01010 }
01011 
01012 //______________________________________________________________________________
01013 const char *TSystem::PrependPathName(const char *, TString&)
01014 {
01015    // Concatenate a directory and a file name.
01016 
01017    AbstractMethod("PrependPathName");
01018    return 0;
01019 }
01020 
01021 
01022 //---- Paths & Files -----------------------------------------------------------
01023 
01024 //______________________________________________________________________________
01025 const char *TSystem::ExpandFileName(const char *fname)
01026 {
01027    // Expand a pathname getting rid of special shell characters like ~.$, etc.
01028    // For Unix/Win32 compatibility use $(XXX) instead of $XXX when using
01029    // environment variables in a pathname. If compatibility is not an issue
01030    // you can use on Unix directly $XXX. This is a protected function called
01031    // from the OS specific system classes, like TUnixSystem and TWinNTSystem.
01032    // Returns the expanded filename or 0 in case of error.
01033 
01034    const int   kBufSize = kMAXPATHLEN;
01035    int         n, ier, iter, lx, ncopy;
01036    char       *inp, *out, *x, *t, buff[kBufSize*4];
01037    const char *b, *c, *e;
01038    const char *p;
01039    static char xname[kBufSize];
01040 
01041    R__LOCKGUARD2(gSystemMutex);
01042 
01043    iter = 0; xname[0] = 0; inp = buff + kBufSize; out = inp + kBufSize;
01044    inp[-1] = ' '; inp[0] = 0; out[-1] = ' ';
01045    c = fname + strspn(fname, " \t\f\r");
01046    //VP  if (isalnum(c[0])) { strcpy(inp, WorkingDirectory()); strcat(inp, "/"); } // add $cwd
01047 
01048    strlcat(inp, c, kBufSize);
01049 
01050 again:
01051    iter++; c = inp; ier = 0;
01052    x = out; x[0] = 0;
01053 
01054    for ( ; c[0]; c++) {
01055 
01056       p = 0; e = 0;
01057       if (c[0] == '~' && c[1] == '/') { // ~/ case
01058          p = HomeDirectory(); e = c + 1; if (!p) ier++;
01059       }
01060       if (p) {                         // we have smth to copy
01061          strlcpy(x, p, kBufSize); x += strlen(p); c = e-1; continue;
01062       }
01063 
01064       p = 0;
01065       if (c[0] == '~' && c[1] != '/') { // ~user case
01066          n = strcspn(c+1, "/ "); buff[0] = 0; strncat(buff, c+1, n);
01067          p = HomeDirectory(buff); e = c+1+n; if (!p) ier++;
01068       }
01069       if (p) {                          // we have smth to copy
01070          strlcpy(x, p, kBufSize); x += strlen(p); c = e-1; continue;
01071       }
01072 
01073       p = 0;
01074       if (c[0] == '.' && c[1] == '/' && c[-1] == ' ') { // $cwd
01075          strlcpy(buff, WorkingDirectory(), kBufSize);
01076          p = buff;
01077          e = c + 1;
01078       }
01079       if (p) {                          // we have smth to copy */
01080          strlcpy(x, p, kBufSize); x += strlen(p); c = e-1; continue;
01081       }
01082 
01083       if (c[0] != '$') {                // not $, simple copy
01084          x++[0] = c[0];
01085       } else {                          // we have a $
01086          b = c+1;
01087          if (c[1] == '(') b++;
01088          if (c[1] == '{') b++;
01089          if (b[0] == '$')
01090             e = b+1;
01091          else
01092             for (e = b; isalnum(e[0]) || e[0] == '_'; e++) ;
01093          buff[0] = 0; strncat(buff, b, e-b);
01094          p = Getenv(buff);
01095          if (!p) {                      // too bad, try UPPER case
01096             for (t = buff; (t[0] = toupper(t[0])); t++) ;
01097             p = Getenv(buff);
01098          }
01099          if (!p) {                      // too bad, try Lower case
01100             for (t = buff; (t[0] = tolower(t[0])); t++) ;
01101             p = Getenv(buff);
01102          }
01103          if (!p && !strcmp(buff, "cwd")) { // it is $cwd
01104             strlcpy(buff, WorkingDirectory(), kBufSize);
01105             p = buff;
01106          }
01107          if (!p && !strcmp(buff, "$")) { // it is $$ (replace by GetPid())
01108             snprintf(buff,kBufSize*4, "%d", GetPid());
01109             p = buff;
01110          }
01111          if (!p) {                      // too bad, nothing can help
01112 #ifdef WIN32
01113             // if we're on windows, we can have \\SomeMachine\C$ - don't
01114             // complain about that, if '$' is followed by nothing or a
01115             // path delimiter.
01116             if (c[1] && c[1]!='\\' && c[1]!=';' && c[1]!='/')
01117                ier++;
01118 #else
01119             ier++;
01120 #endif
01121             x++[0] = c[0];
01122          } else {                       // It is OK, copy result
01123             int lp = strlen(p);
01124             if (lp >= kBufSize) {
01125                // make sure lx will be >= kBufSize (see below)
01126                strlcpy(x, p, kBufSize);
01127                x += kBufSize;
01128                break;
01129             } else
01130                strcpy(x,p); x += lp; c = (b==c+1) ? e-1 : e;
01131          }
01132       }
01133    }
01134 
01135    x[0] = 0; lx = x - out;
01136    if (ier && iter < 3) { strlcpy(inp, out, kBufSize); goto again; }
01137    ncopy = (lx >= kBufSize) ? kBufSize-1 : lx;
01138    xname[0] = 0; strncat(xname, out, ncopy);
01139 
01140    if (ier || ncopy != lx) {
01141       ::Error("TSystem::ExpandFileName", "input: %s, output: %s", fname, xname);
01142       return 0;
01143    }
01144 
01145    return xname;
01146 }
01147 
01148 //______________________________________________________________________________
01149 Bool_t TSystem::ExpandPathName(TString&)
01150 {
01151    // Expand a pathname getting rid of special shell characaters like ~.$, etc.
01152    // For Unix/Win32 compatibility use $(XXX) instead of $XXX when using
01153    // environment variables in a pathname. If compatibility is not an issue
01154    // you can use on Unix directly $XXX.
01155 
01156    return kFALSE;
01157 }
01158 
01159 //______________________________________________________________________________
01160 char *TSystem::ExpandPathName(const char *)
01161 {
01162    // Expand a pathname getting rid of special shell characaters like ~.$, etc.
01163    // For Unix/Win32 compatibility use $(XXX) instead of $XXX when using
01164    // environment variables in a pathname. If compatibility is not an issue
01165    // you can use on Unix directly $XXX. The user must delete returned string.
01166 
01167    return 0;
01168 }
01169 
01170 //______________________________________________________________________________
01171 Bool_t TSystem::AccessPathName(const char *, EAccessMode)
01172 {
01173    // Returns FALSE if one can access a file using the specified access mode.
01174    // The file name must not contain any special shell characters line ~ or $,
01175    // in those cases first call ExpandPathName().
01176    // Attention, bizarre convention of return value!!
01177 
01178    return kFALSE;
01179 }
01180 
01181 //______________________________________________________________________________
01182 Bool_t TSystem::IsPathLocal(const char *path)
01183 {
01184    // Returns TRUE if the url in 'path' points to the local file system.
01185    // This is used to avoid going through the NIC card for local operations.
01186 
01187    Bool_t localPath = kTRUE;
01188 
01189    TUrl url(path);
01190    if (strlen(url.GetHost()) > 0) {
01191       // Check locality
01192       localPath = kFALSE;
01193       TInetAddress a(gSystem->GetHostByName(url.GetHost()));
01194       TInetAddress b(gSystem->GetHostByName(gSystem->HostName()));
01195       if (!strcmp(a.GetHostName(), b.GetHostName()) ||
01196           !strcmp(a.GetHostAddress(), b.GetHostAddress())) {
01197          // Host OK
01198          localPath = kTRUE;
01199          // Check the user if specified
01200          if (strlen(url.GetUser()) > 0) {
01201             UserGroup_t *u = gSystem->GetUserInfo();
01202             if (u) {
01203                if (strcmp(u->fUser, url.GetUser()))
01204                   // Requested a different user
01205                   localPath = kFALSE;
01206                delete u;
01207             }
01208          }
01209       }
01210    }
01211    // Done
01212    return localPath;
01213 }
01214 
01215 //______________________________________________________________________________
01216 int TSystem::CopyFile(const char *, const char *, Bool_t)
01217 {
01218    // Copy a file. If overwrite is true and file already exists the
01219    // file will be overwritten. Returns 0 when successful, -1 in case
01220    // of file open failure, -2 in case the file already exists and overwrite
01221    // was false and -3 in case of error during copy.
01222 
01223    AbstractMethod("CopyFile");
01224    return -1;
01225 }
01226 
01227 //______________________________________________________________________________
01228 int TSystem::Rename(const char *, const char *)
01229 {
01230    // Rename a file.
01231 
01232    AbstractMethod("Rename");
01233    return -1;
01234 }
01235 
01236 //______________________________________________________________________________
01237 int TSystem::Link(const char *, const char *)
01238 {
01239    // Create a link from file1 to file2.
01240 
01241    AbstractMethod("Link");
01242    return -1;
01243 }
01244 
01245 //______________________________________________________________________________
01246 int TSystem::Symlink(const char *, const char *)
01247 {
01248    // Create a symbolic link from file1 to file2.
01249 
01250    AbstractMethod("Symlink");
01251    return -1;
01252 }
01253 
01254 //______________________________________________________________________________
01255 int TSystem::Unlink(const char *)
01256 {
01257    // Unlink, i.e. remove, a file.
01258 
01259    AbstractMethod("Unlink");
01260    return -1;
01261 }
01262 
01263 //______________________________________________________________________________
01264 int TSystem::GetPathInfo(const char *path, Long_t *id, Long_t *size,
01265                          Long_t *flags, Long_t *modtime)
01266 {
01267    // Get info about a file: id, size, flags, modification time.
01268    // Id      is (statbuf.st_dev << 24) + statbuf.st_ino
01269    // Size    is the file size
01270    // Flags   is file type: 0 is regular file, bit 0 set executable,
01271    //                       bit 1 set directory, bit 2 set special file
01272    //                       (socket, fifo, pipe, etc.)
01273    // Modtime is modification time.
01274    // The function returns 0 in case of success and 1 if the file could
01275    // not be stat'ed.
01276 
01277    Long64_t lsize;
01278 
01279    int res = GetPathInfo(path, id, &lsize, flags, modtime);
01280 
01281    if (res == 0 && size) {
01282       if (sizeof(Long_t) == 4 && lsize > kMaxInt) {
01283          Error("GetPathInfo", "file %s > 2 GB, use GetPathInfo() with Long64_t size", path);
01284          *size = kMaxInt;
01285       } else {
01286          *size = (Long_t)lsize;
01287       }
01288    }
01289 
01290    return res;
01291 }
01292 
01293 //______________________________________________________________________________
01294 int TSystem::GetPathInfo(const char *path, Long_t *id, Long64_t *size,
01295                          Long_t *flags, Long_t *modtime)
01296 {
01297    // Get info about a file: id, size, flags, modification time.
01298    // Id      is (statbuf.st_dev << 24) + statbuf.st_ino
01299    // Size    is the file size
01300    // Flags   is file type: 0 is regular file, bit 0 set executable,
01301    //                       bit 1 set directory, bit 2 set special file
01302    //                       (socket, fifo, pipe, etc.)
01303    // Modtime is modification time.
01304    // The function returns 0 in case of success and 1 if the file could
01305    // not be stat'ed.
01306 
01307    FileStat_t buf;
01308 
01309    int res = GetPathInfo(path, buf);
01310 
01311    if (res == 0) {
01312       if (id)
01313          *id = (buf.fDev << 24) + buf.fIno;
01314       if (size)
01315          *size = buf.fSize;
01316       if (modtime)
01317          *modtime = buf.fMtime;
01318       if (flags) {
01319          *flags = 0;
01320          if (buf.fMode & (kS_IXUSR|kS_IXGRP|kS_IXOTH))
01321             *flags |= 1;
01322          if (R_ISDIR(buf.fMode))
01323             *flags |= 2;
01324          if (!R_ISREG(buf.fMode) && !R_ISDIR(buf.fMode))
01325             *flags |= 4;
01326       }
01327    }
01328 
01329    return res;
01330 }
01331 
01332 //______________________________________________________________________________
01333 int TSystem::GetPathInfo(const char *, FileStat_t &)
01334 {
01335    // Get info about a file. Info is returned in the form of a FileStat_t
01336    // structure (see TSystem.h).
01337    // The function returns 0 in case of success and 1 if the file could
01338    // not be stat'ed.
01339 
01340    AbstractMethod("GetPathInfo(const char*, FileStat_t&)");
01341    return 1;
01342 }
01343 
01344 //______________________________________________________________________________
01345 int TSystem::GetFsInfo(const char *, Long_t *, Long_t *, Long_t *, Long_t *)
01346 {
01347    // Get info about a file system: fs type, block size, number of blocks,
01348    // number of free blocks.
01349 
01350    AbstractMethod("GetFsInfo");
01351    return 1;
01352 }
01353 
01354 //______________________________________________________________________________
01355 const char *TSystem::TempDirectory() const
01356 {
01357    // Return a user configured or systemwide directory to create
01358    // temporary files in.
01359 
01360    AbstractMethod("TempDirectory");
01361    return 0;
01362 }
01363 
01364 //______________________________________________________________________________
01365 FILE *TSystem::TempFileName(TString &, const char *)
01366 {
01367    // Create a secure temporary file by appending a unique
01368    // 6 letter string to base. The file will be created in
01369    // a standard (system) directory or in the directory
01370    // provided in dir. The full filename is returned in base
01371    // and a filepointer is returned for safely writing to the file
01372    // (this avoids certain security problems). Returns 0 in case
01373    // of error.
01374 
01375    AbstractMethod("TempFileName");
01376    return 0;
01377 }
01378 
01379 //______________________________________________________________________________
01380 int TSystem::Chmod(const char *, UInt_t)
01381 {
01382    // Set the file permission bits. Returns -1 in case or error, 0 otherwise.
01383 
01384    AbstractMethod("Chmod");
01385    return -1;
01386 }
01387 
01388 //______________________________________________________________________________
01389 int TSystem::Umask(Int_t)
01390 {
01391    // Set the process file creation mode mask.
01392 
01393    AbstractMethod("Umask");
01394    return -1;
01395 }
01396 
01397 //______________________________________________________________________________
01398 int TSystem::Utime(const char *, Long_t, Long_t)
01399 {
01400    // Set the a files modification and access times. If actime = 0 it will be
01401    // set to the modtime. Returns 0 on success and -1 in case of error.
01402 
01403    AbstractMethod("Utime");
01404    return -1;
01405 }
01406 
01407 //______________________________________________________________________________
01408 const char *TSystem::FindFile(const char *, TString&, EAccessMode)
01409 {
01410    // Find location of file in a search path. Return value points to TString for
01411    // compatibility with Which(const char *, const char *, EAccessMode).
01412    // Returns 0 in case file is not found.
01413 
01414    AbstractMethod("FindFile");
01415    return 0;
01416 }
01417 
01418 //______________________________________________________________________________
01419 char *TSystem::Which(const char *search, const char *wfil, EAccessMode mode)
01420 {
01421    // Find location of file in a search path. User must delete returned string.
01422    // Returns 0 in case file is not found.
01423 
01424    TString wfilString(wfil);
01425    FindFile(search, wfilString, mode);
01426    if (wfilString.IsNull()) return 0;
01427    return StrDup(wfilString.Data());
01428 }
01429 
01430 //---- Users & Groups ----------------------------------------------------------
01431 
01432 //______________________________________________________________________________
01433 Int_t TSystem::GetUid(const char * /*user*/)
01434 {
01435    // Returns the user's id. If user = 0, returns current user's id.
01436 
01437    AbstractMethod("GetUid");
01438    return 0;
01439 }
01440 
01441 //______________________________________________________________________________
01442 Int_t TSystem::GetEffectiveUid()
01443 {
01444    // Returns the effective user id. The effective id corresponds to the
01445    // set id bit on the file being executed.
01446 
01447    AbstractMethod("GetEffectiveUid");
01448    return 0;
01449 }
01450 
01451 //______________________________________________________________________________
01452 Int_t TSystem::GetGid(const char * /*group*/)
01453 {
01454    // Returns the group's id. If group = 0, returns current user's group.
01455 
01456    AbstractMethod("GetGid");
01457    return 0;
01458 }
01459 
01460 //______________________________________________________________________________
01461 Int_t TSystem::GetEffectiveGid()
01462 {
01463    // Returns the effective group id. The effective group id corresponds
01464    // to the set id bit on the file being executed.
01465 
01466    AbstractMethod("GetEffectiveGid");
01467    return 0;
01468 }
01469 
01470 //______________________________________________________________________________
01471 UserGroup_t *TSystem::GetUserInfo(Int_t /*uid*/)
01472 {
01473    // Returns all user info in the UserGroup_t structure. The returned
01474    // structure must be deleted by the user. In case of error 0 is returned.
01475 
01476    AbstractMethod("GetUserInfo");
01477    return 0;
01478 }
01479 
01480 //______________________________________________________________________________
01481 UserGroup_t *TSystem::GetUserInfo(const char * /*user*/)
01482 {
01483    // Returns all user info in the UserGroup_t structure. If user = 0, returns
01484    // current user's id info. The returned structure must be deleted by the
01485    // user. In case of error 0 is returned.
01486 
01487    AbstractMethod("GetUserInfo");
01488    return 0;
01489 }
01490 
01491 //______________________________________________________________________________
01492 UserGroup_t *TSystem::GetGroupInfo(Int_t /*gid*/)
01493 {
01494    // Returns all group info in the UserGroup_t structure. The only active
01495    // fields in the UserGroup_t structure for this call are:
01496    //    fGid and fGroup
01497    // The returned structure must be deleted by the user. In case of
01498    // error 0 is returned.
01499 
01500    AbstractMethod("GetGroupInfo");
01501    return 0;
01502 }
01503 
01504 //______________________________________________________________________________
01505 UserGroup_t *TSystem::GetGroupInfo(const char * /*group*/)
01506 {
01507    // Returns all group info in the UserGroup_t structure. The only active
01508    // fields in the UserGroup_t structure for this call are:
01509    //    fGid and fGroup
01510    // If group = 0, returns current user's group. The returned structure
01511    // must be deleted by the user. In case of error 0 is returned.
01512 
01513    AbstractMethod("GetGroupInfo");
01514    return 0;
01515 }
01516 
01517 //---- environment manipulation ------------------------------------------------
01518 
01519 //______________________________________________________________________________
01520 void TSystem::Setenv(const char*, const char*)
01521 {
01522    // Set environment variable.
01523 
01524    AbstractMethod("Setenv");
01525 }
01526 
01527 //______________________________________________________________________________
01528 void TSystem::Unsetenv(const char *name)
01529 {
01530    // Unset environment variable.
01531 
01532    Setenv(name, "");
01533 }
01534 
01535 //______________________________________________________________________________
01536 const char *TSystem::Getenv(const char*)
01537 {
01538    // Get environment variable.
01539 
01540    AbstractMethod("Getenv");
01541    return 0;
01542 }
01543 
01544 //---- System Logging ----------------------------------------------------------
01545 
01546 //______________________________________________________________________________
01547 void TSystem::Openlog(const char *, Int_t, ELogFacility)
01548 {
01549    // Open connection to system log daemon. For the use of the options and
01550    // facility see the Unix openlog man page.
01551 
01552    AbstractMethod("Openlog");
01553 }
01554 
01555 //______________________________________________________________________________
01556 void TSystem::Syslog(ELogLevel, const char *)
01557 {
01558    // Send mess to syslog daemon. Level is the logging level and mess the
01559    // message that will be written on the log.
01560 
01561    AbstractMethod("Syslog");
01562 }
01563 
01564 //______________________________________________________________________________
01565 void TSystem::Closelog()
01566 {
01567    // Close connection to system log daemon.
01568 
01569    AbstractMethod("Closelog");
01570 }
01571 
01572 //---- Standard output redirection ---------------------------------------------
01573 
01574 //______________________________________________________________________________
01575 Int_t TSystem::RedirectOutput(const char *, const char *, RedirectHandle_t *)
01576 {
01577    // Redirect standard output (stdout, stderr) to the specified file.
01578    // If the file argument is 0 the output is set again to stderr, stdout.
01579    // The second argument specifies whether the output should be added to the
01580    // file ("a", default) or the file be truncated before ("w").
01581    // The implementations of this function save internally the current state into
01582    // a static structure.
01583    // The call can be made reentrant by specifying the opaque structure pointed
01584    // by 'h', which is filled with the relevant information. The handle 'h'
01585    // obtained on the first call must then be used in any subsequent call,
01586    // included ShowOutput, to display the redirected output.
01587    // Returns 0 on success, -1 in case of error.
01588 
01589    AbstractMethod("RedirectOutput");
01590    return -1;
01591 }
01592 
01593 //______________________________________________________________________________
01594 void TSystem::ShowOutput(RedirectHandle_t *h)
01595 {
01596    // Display the content associated with the redirection described by the
01597    // opaque handle 'h'.
01598 
01599    // Check input ...
01600    if (!h) {
01601       Error("ShowOutput", "handle not specified");
01602       return;
01603    }
01604 
01605    // ... and file access
01606    if (gSystem->AccessPathName(h->fFile, kReadPermission)) {
01607       Error("ShowOutput", "file '%s' cannot be read", h->fFile.Data());
01608       return;
01609    }
01610 
01611    // Open the file
01612    FILE *f = 0;
01613    if (!(f = fopen(h->fFile.Data(), "r"))) {
01614       Error("ShowOutput", "file '%s' cannot be open", h->fFile.Data());
01615       return;
01616    }
01617 
01618    // Determine the number of bytes to be read from the file.
01619    off_t ltot = lseek(fileno(f), (off_t) 0, SEEK_END);
01620    Int_t begin = (h->fReadOffSet > 0 && h->fReadOffSet < ltot) ? h->fReadOffSet : 0;
01621    lseek(fileno(f), (off_t) begin, SEEK_SET);
01622    Int_t left = ltot - begin;
01623 
01624    // Now readout from file
01625    const Int_t kMAXBUF = 16384;
01626    char buf[kMAXBUF];
01627    Int_t wanted = (left > kMAXBUF-1) ? kMAXBUF-1 : left;
01628    Int_t len;
01629    do {
01630       while ((len = read(fileno(f), buf, wanted)) < 0 &&
01631                TSystem::GetErrno() == EINTR)
01632          TSystem::ResetErrno();
01633 
01634       if (len < 0) {
01635          SysError("ShowOutput", "error reading log file");
01636          break;
01637       }
01638 
01639       // Null-terminate
01640       buf[len] = 0;
01641       fprintf(stderr,"%s", buf);
01642 
01643       // Update counters
01644       left -= len;
01645       wanted = (left > kMAXBUF) ? kMAXBUF : left;
01646 
01647    } while (len > 0 && left > 0);
01648 
01649    // Do not display twice the same thing
01650    h->fReadOffSet = ltot;
01651    fclose(f);
01652 }
01653 
01654 //---- Dynamic Loading ---------------------------------------------------------
01655 
01656 //______________________________________________________________________________
01657 void TSystem::AddDynamicPath(const char *)
01658 {
01659    // Add a new directory to the dynamic path.
01660    
01661    AbstractMethod("AddDynamicPath");
01662 }
01663 
01664 //______________________________________________________________________________
01665 const char* TSystem::GetDynamicPath()
01666 {
01667    // Return the dynamic path (used to find shared libraries).
01668 
01669    AbstractMethod("GetDynamicPath");
01670    return 0;
01671 }
01672 
01673 //______________________________________________________________________________
01674 void TSystem::SetDynamicPath(const char *)
01675 {
01676    // Set the dynamic path to a new value.
01677    // If the value of 'path' is zero, the dynamic path is reset to its
01678    // default value.
01679 
01680    AbstractMethod("SetDynamicPath");
01681 }
01682 
01683 
01684 //______________________________________________________________________________
01685 static bool R__MatchFilename(const char *left, const char *right)
01686 {
01687    // Figure out if left and right points to the same
01688    // object in the file system.
01689 
01690    if (left == right) return kTRUE;
01691 
01692    if (left==0 || right==0) return kFALSE;
01693 
01694    if ( (strcmp(right,left)==0) ) {
01695       return kTRUE;
01696    }
01697 
01698 #ifdef G__WIN32
01699 
01700    char leftname[_MAX_PATH];
01701    char rightname[_MAX_PATH];
01702    _fullpath( leftname, left, _MAX_PATH );
01703    _fullpath( rightname, right, _MAX_PATH );
01704    return ((stricmp(leftname, rightname)==0));
01705 #else
01706    struct stat rightBuf;
01707    struct stat leftBuf;
01708    return (   ( 0 == stat( left, & leftBuf ) )
01709        && ( 0 == stat( right, & rightBuf ) )
01710        && ( leftBuf.st_dev == rightBuf.st_dev )     // Files on same device
01711        && ( leftBuf.st_ino == rightBuf.st_ino )     // Files on same inode (but this is not unique on AFS so we need the next 2 test
01712        && ( leftBuf.st_size == rightBuf.st_size )   // Files of same size
01713        && ( leftBuf.st_mtime == rightBuf.st_mtime ) // Files modified at the same time
01714            );
01715 #endif
01716 }
01717 
01718 //______________________________________________________________________________
01719 int TSystem::Load(const char *module, const char *entry, Bool_t system)
01720 {
01721    // Load a shared library. Returns 0 on successful loading, 1 in
01722    // case lib was already loaded, -1 in case lib does not exist
01723    // or in case of error and -2 in case of version mismatch.
01724    // When entry is specified the loaded lib is
01725    // searched for this entry point (return -1 when entry does not exist,
01726    // 0 otherwise). When the system flag is kTRUE, the library is consisdered
01727    // a permanent systen library that should not be unloaded during the
01728    // course of the session.
01729 
01730 #ifdef NOCINT
01731    AbstractMethod("Load");
01732    return 0;
01733 #else
01734    static int recCall = 0;
01735 
01736    // don't load libraries that have already been loaded
01737    TString libs( GetLibraries() );
01738    TString moduleBasename( BaseName(module) );
01739    TString l(moduleBasename);
01740 
01741    Ssiz_t idx = l.Last('.');
01742    if (idx != kNPOS) {
01743       l.Remove(idx+1);
01744    }
01745    idx = libs.Index(l);
01746    if (idx != kNPOS) {
01747       // The libs contains the sub-string 'l', let's make sure it is
01748       // not just part of a larger name.
01749       if (idx == 0 || libs[idx-1] == '/' || libs[idx-1] == '\\') {
01750          Ssiz_t len = libs.Length();
01751          idx += l.Length();
01752          if (!l.EndsWith(".") && libs[idx]=='.')
01753             idx++;
01754          // Skip the soversion.
01755          while (idx < len && isdigit(libs[idx])) {
01756             ++idx;
01757             // No need to test for len here, at worse idx==len and lib[idx]=='\0'
01758             if (libs[idx] == '.') {
01759                ++idx;
01760             }
01761          }
01762          while (idx < len && libs[idx] != '.') {
01763             if (libs[idx] == ' ' || idx+1 == len) {
01764                return 1;
01765             }
01766             ++idx;
01767          }
01768       }
01769    }
01770    if (l[l.Length()-1] == '.') {
01771       l.Remove(l.Length()-1);
01772    }
01773    if (l.BeginsWith("lib")) {
01774       l.Replace(0, 3, "-l");
01775       idx = libs.Index(l);
01776       if (idx != kNPOS &&
01777           (idx == 0 || libs[idx-1] == ' ') &&
01778           (libs[idx+l.Length()] == ' ' || libs[idx+l.Length()] == 0)) {
01779          return 1;
01780       }
01781    }
01782 
01783    recCall++;
01784 
01785    char *path = DynamicPathName(module);
01786 
01787    // load any dependent libraries
01788    int ret;
01789    TString deplibs = gInterpreter->GetSharedLibDeps(moduleBasename);
01790    if (deplibs.IsNull()) {
01791       TString libmapfilename;
01792       if (path) {
01793          libmapfilename = path;
01794          idx = libmapfilename.Last('.');
01795          if (idx != kNPOS) {
01796             libmapfilename.Remove(idx);
01797          }
01798          libmapfilename += ".rootmap";
01799       }
01800       if (gSystem->GetPathInfo(libmapfilename, 0, (Long_t*)0, 0, 0) == 0) {
01801          if (gDebug > 0) Info("Load", "loading %s", libmapfilename.Data());
01802          gInterpreter->LoadLibraryMap(libmapfilename);
01803          deplibs = gInterpreter->GetSharedLibDeps(moduleBasename);
01804       }
01805    }
01806    if (!deplibs.IsNull()) {
01807       TString delim(" ");
01808       TObjArray *tokens = deplibs.Tokenize(delim);
01809       for (Int_t i = tokens->GetEntriesFast()-1; i > 0; i--) {
01810          const char *deplib = ((TObjString*)tokens->At(i))->GetName();
01811          if (gDebug > 0)
01812             Info("Load", "loading dependent library %s for library %s",
01813                  deplib, ((TObjString*)tokens->At(0))->GetName());
01814          if ((ret = Load(deplib, "", system)) < 0) {
01815             delete tokens;
01816             recCall--;
01817             return ret;
01818          }
01819       }
01820       delete tokens;
01821    }
01822 
01823    ret = -1;
01824    if (path) {
01825       if (!system) {
01826          // Mark the library in $ROOTSYS/lib as system.
01827          const char *dirname = DirName(path);
01828 #ifdef ROOTLIBDIR
01829          TString rootlibdir = ROOTLIBDIR;
01830 #else
01831          TString rootlibdir = "lib";
01832          PrependPathName(gRootDir, rootlibdir);
01833 #endif
01834          system = R__MatchFilename(rootlibdir,dirname);
01835 
01836          if (!system) {
01837 #ifdef ROOTBINDIR
01838             TString rootbindir = ROOTBINDIR;
01839 #else
01840             TString rootbindir = "bin";
01841             PrependPathName(gRootDir, rootbindir);
01842 #endif
01843             system = R__MatchFilename(rootbindir,dirname);
01844          }
01845       }
01846 
01847       gLibraryVersionIdx++;
01848       if (gLibraryVersionIdx == gLibraryVersionMax) {
01849          gLibraryVersionMax *= 2;
01850          gLibraryVersion = TStorage::ReAllocInt(gLibraryVersion, gLibraryVersionMax, gLibraryVersionIdx);
01851       }
01852       ret = gInterpreter->Load(path, system);
01853       if (ret < 0) ret = -1;
01854       if (gDebug > 0)
01855          Info("Load", "loaded library %s, status %d", path, ret);
01856       if (ret == 0 && gLibraryVersion[gLibraryVersionIdx]) {
01857          int v = TROOT::ConvertVersionCode2Int(gLibraryVersion[gLibraryVersionIdx]);
01858          Error("Load", "version mismatch, %s = %d, ROOT = %d",
01859                path, v, gROOT->GetVersionInt());
01860          ret = -2;
01861          gLibraryVersion[gLibraryVersionIdx] = 0;
01862       }
01863       gLibraryVersionIdx--;
01864       delete [] path;
01865    }
01866 
01867    recCall--;
01868 
01869    // will load and initialize graphics libraries if
01870    // TApplication::NeedGraphicsLibs() has been called by a
01871    // library static initializer, only do this when Load() is
01872    // not called recursively
01873    if (recCall == 0 && gApplication)
01874       gApplication->InitializeGraphics();
01875 
01876    if (!entry || !entry[0] || ret < 0) return ret;
01877 
01878    Func_t f = DynFindSymbol(module, entry);
01879    if (f) return 0;
01880    return -1;
01881 #endif
01882 }
01883 
01884 //______________________________________________________________________________
01885 char *TSystem::DynamicPathName(const char *, Bool_t)
01886 {
01887    // Need to return the equivalent of LD_LIBRARY_PATH.
01888 
01889    AbstractMethod("DynamicPathName");
01890    return 0;
01891 }
01892 //______________________________________________________________________________
01893 Func_t TSystem::DynFindSymbol(const char * /*lib*/, const char *entry)
01894 {
01895    // Find specific entry point in specified library. Specify "*" for lib
01896    // to search in all libraries.
01897 
01898 #ifdef NOCINT
01899    AbstractMethod("DynFindSymbol");
01900    return 0;
01901 #else
01902    return (Func_t) gInterpreter->FindSym(entry);
01903 #endif
01904 }
01905 
01906 //______________________________________________________________________________
01907 void TSystem::Unload(const char *module)
01908 {
01909    // Unload a shared library.
01910 
01911 #ifdef NOCINT
01912    AbstractMethod("UnLoad");
01913 #else
01914    char *path;
01915    if ((path = DynamicPathName(module))) {
01916       gInterpreter->UnloadFile(path);
01917       delete [] path;
01918    }
01919 #endif
01920 }
01921 
01922 //______________________________________________________________________________
01923 void TSystem::ListSymbols(const char *, const char *)
01924 {
01925    // List symbols in a shared library.
01926 
01927    AbstractMethod("ListSymbols");
01928 }
01929 
01930 //______________________________________________________________________________
01931 void TSystem::ListLibraries(const char *regexp)
01932 {
01933    // List all loaded shared libraries. Regexp is a wildcard expression,
01934    // see TRegexp::MakeWildcard.
01935 
01936    TString libs = GetLibraries(regexp);
01937    TRegexp separator("[^ \\t\\s]+");
01938    TString s;
01939    Ssiz_t start = 0, index = 0, end = 0;
01940    int i = 0;
01941 
01942    Printf(" ");
01943    Printf("Loaded shared libraries");
01944    Printf("=======================");
01945 
01946    while ((start < libs.Length()) && (index != kNPOS)) {
01947       index = libs.Index(separator, &end, start);
01948       if (index >= 0) {
01949          s = libs(index, end);
01950          if (s.BeginsWith("-")) {
01951             if (s.BeginsWith("-l")) {
01952                Printf("%s", s.Data());
01953                i++;
01954             }
01955          } else {
01956             Printf("%s", s.Data());
01957             i++;
01958          }
01959       }
01960       start += end+1;
01961    }
01962 
01963    Printf("-----------------------");
01964    Printf("%d libraries loaded", i);
01965    Printf("=======================");
01966 }
01967 
01968 //______________________________________________________________________________
01969 const char *TSystem::GetLinkedLibraries()
01970 {
01971    // Get list of shared libraries loaded at the start of the executable.
01972    // Returns 0 in case list cannot be obtained or in case of error.
01973 
01974    return 0;
01975 }
01976 
01977 //______________________________________________________________________________
01978 const char *TSystem::GetLibraries(const char *regexp, const char *options,
01979                                   Bool_t isRegexp)
01980 {
01981    // Return a space separated list of loaded shared libraries.
01982    // Regexp is a wildcard expression, see TRegexp::MakeWildcard.
01983    // This list is of a format suitable for a linker, i.e it may contain
01984    // -Lpathname and/or -lNameOfLib.
01985    // Option can be any of:
01986    //   S: shared libraries loaded at the start of the executable, because
01987    //      they were specified on the link line.
01988    //   D: shared libraries dynamically loaded after the start of the program.
01989    // For MacOS only:
01990    //   L: list the .dylib rather than the .so (this is intended for linking)
01991    //      This options is not the default
01992 
01993    fListLibs.Clear();
01994 
01995    TString libs;
01996    TString opt(options);
01997    Bool_t so2dylib = (opt.First('L') != kNPOS);
01998    if (so2dylib)
01999       opt.ReplaceAll("L", "");
02000 
02001    if (opt.IsNull() || opt.First('D') != kNPOS)
02002       libs += gInterpreter->GetSharedLibs();
02003 
02004    // Cint currently register all libraries that
02005    // are loaded and have a dictionary in them, this
02006    // includes all the libraries that are included
02007    // in the list of (hard) linked libraries.
02008 
02009    TString slinked;
02010    const char *linked;
02011    if ((linked = GetLinkedLibraries())) {
02012       if (fLinkedLibs != LINKEDLIBS) {
02013          // This is not the default value, we need to keep the custom part.
02014          TString custom = fLinkedLibs;
02015          custom.ReplaceAll(LINKEDLIBS,linked);
02016          if (custom == fLinkedLibs) {
02017             // no replacement done, let's append linked
02018             slinked.Append(linked);
02019             slinked.Append(" ");
02020          }
02021          slinked.Append(custom);
02022       } else {
02023          slinked.Append(linked);
02024       }
02025    } else {
02026       slinked.Append(fLinkedLibs);
02027    }
02028 
02029    if (opt.IsNull() || opt.First('S') != kNPOS) {
02030       // We are done, the statically linked library
02031       // are already included.
02032       if (libs.Length() == 0) {
02033          libs = slinked;
02034       } else {
02035          // We need to add the missing linked library
02036 
02037          static TString lastLinked;
02038          static TString lastAddMissing;
02039          if ( lastLinked != slinked ) {
02040             // Recalculate only if there was a change.
02041             static TRegexp separator("[^ \\t\\s]+");
02042             lastLinked = slinked;
02043             lastAddMissing.Clear();
02044 
02045             Ssiz_t start, index, end;
02046             start = index = end = 0;
02047 
02048             while ((start < slinked.Length()) && (index != kNPOS)) {
02049                index = slinked.Index(separator,&end,start);
02050                if (index >= 0) {
02051                   TString sub = slinked(index,end);
02052                   if (sub[0]=='-' && sub[1]=='L') {
02053                      lastAddMissing.Prepend(" ");
02054                      lastAddMissing.Prepend(sub);
02055                   } else {
02056                      if (libs.Index(sub) == kNPOS) {
02057                         lastAddMissing.Prepend(" ");
02058                         lastAddMissing.Prepend(sub);
02059                      }
02060                   }
02061                }
02062                start += end+1;
02063             }
02064          }
02065          libs.Prepend(lastAddMissing);
02066       }
02067    } else if (libs.Length() != 0) {
02068       // Let remove the statically linked library
02069       // from the list.
02070       static TRegexp separator("[^ \\t\\s]+");
02071       Ssiz_t start, index, end;
02072       start = index = end = 0;
02073 
02074       while ((start < slinked.Length()) && (index != kNPOS)) {
02075          index = slinked.Index(separator,&end,start);
02076          if (index >= 0) {
02077             TString sub = slinked(index,end);
02078             if (sub[0]!='-' && sub[1]!='L') {
02079                libs.ReplaceAll(sub,"");
02080             }
02081          }
02082          start += end+1;
02083       }
02084       libs = libs.Strip(TString::kBoth);
02085    }
02086 
02087    // Select according to regexp
02088    if (regexp && *regexp) {
02089       static TRegexp separator("[^ \\t\\s]+");
02090       TRegexp user_re(regexp, kTRUE);
02091       TString s;
02092       Ssiz_t start, index, end;
02093       start = index = end = 0;
02094 
02095       while ((start < libs.Length()) && (index != kNPOS)) {
02096          index = libs.Index(separator,&end,start);
02097          if (index >= 0) {
02098             s = libs(index,end);
02099             if ((isRegexp && s.Index(user_re) != kNPOS) ||
02100                 (!isRegexp && s.Index(regexp) != kNPOS)) {
02101                if (!fListLibs.IsNull())
02102                   fListLibs.Append(" ");
02103                fListLibs.Append(s);
02104             }
02105          }
02106          start += end+1;
02107       }
02108    } else
02109       fListLibs = libs;
02110 
02111 #if defined(R__MACOSX) && !defined(MAC_OS_X_VERSION_10_5)
02112    if (so2dylib) {
02113       TString libs2 = fListLibs;
02114       TString maclibs;
02115 
02116       static TRegexp separator("[^ \\t\\s]+");
02117       static TRegexp user_so("\\.so$");
02118 
02119       Ssiz_t start, index, end;
02120       start = index = end = 0;
02121 
02122       while ((start < libs2.Length()) && (index != kNPOS)) {
02123          index = libs2.Index(separator, &end, start);
02124          if (index >= 0) {
02125             // Change .so into .dylib and remove the
02126             // path info if it is not accessible
02127             TString s = libs2(index, end);
02128             if (s.Index(user_so) != kNPOS) {
02129                s.ReplaceAll(".so",".dylib");
02130                if ( GetPathInfo( s, 0, (Long_t*)0, 0, 0 ) != 0 ) {
02131                   s.Replace( 0, s.Last('/')+1, 0, 0);
02132                   s.Replace( 0, s.Last('\\')+1, 0, 0);
02133                }
02134             }
02135             if (!maclibs.IsNull()) maclibs.Append(" ");
02136             maclibs.Append(s);
02137          }
02138          start += end+1;
02139       }
02140       fListLibs = maclibs;
02141    }
02142 #endif
02143 
02144    return fListLibs;
02145 }
02146 
02147 //---- RPC ---------------------------------------------------------------------
02148 
02149 //______________________________________________________________________________
02150 TInetAddress TSystem::GetHostByName(const char *)
02151 {
02152    // Get Internet Protocol (IP) address of host.
02153 
02154    AbstractMethod("GetHostByName");
02155    return TInetAddress();
02156 }
02157 
02158 //______________________________________________________________________________
02159 TInetAddress TSystem::GetPeerName(int)
02160 {
02161    // Get Internet Protocol (IP) address of remote host and port #.
02162 
02163    AbstractMethod("GetPeerName");
02164    return TInetAddress();
02165 }
02166 
02167 //______________________________________________________________________________
02168 TInetAddress TSystem::GetSockName(int)
02169 {
02170    // Get Internet Protocol (IP) address of host and port #.
02171 
02172    AbstractMethod("GetSockName");
02173    return TInetAddress();
02174 }
02175 
02176 //______________________________________________________________________________
02177 int TSystem::GetServiceByName(const char *)
02178 {
02179    // Get port # of internet service.
02180 
02181    AbstractMethod("GetServiceByName");
02182    return -1;
02183 }
02184 
02185 //______________________________________________________________________________
02186 char *TSystem::GetServiceByPort(int)
02187 {
02188    // Get name of internet service.
02189    AbstractMethod("GetServiceByPort");
02190    return 0;
02191 }
02192 
02193 //______________________________________________________________________________
02194 int TSystem::OpenConnection(const char*, int, int)
02195 {
02196    // Open a connection to another host.
02197 
02198    AbstractMethod("OpenConnection");
02199    return -1;
02200 }
02201 
02202 //______________________________________________________________________________
02203 int TSystem::AnnounceTcpService(int, Bool_t, int, int)
02204 {
02205    // Announce TCP/IP service.
02206 
02207    AbstractMethod("AnnounceTcpService");
02208    return -1;
02209 }
02210 
02211 //______________________________________________________________________________
02212 int TSystem::AnnounceUnixService(int, int)
02213 {
02214    // Announce unix domain service.
02215 
02216    AbstractMethod("AnnounceUnixService");
02217    return -1;
02218 }
02219 
02220 //______________________________________________________________________________
02221 int TSystem::AnnounceUnixService(const char *, int)
02222 {
02223    // Announce unix domain service.
02224 
02225    AbstractMethod("AnnounceUnixService");
02226    return -1;
02227 }
02228 
02229 //______________________________________________________________________________
02230 int TSystem::AcceptConnection(int)
02231 {
02232    // Accept a connection.
02233 
02234    AbstractMethod("AcceptConnection");
02235    return -1;
02236 }
02237 
02238 //______________________________________________________________________________
02239 void TSystem::CloseConnection(int, Bool_t)
02240 {
02241    // Close socket connection.
02242 
02243    AbstractMethod("CloseConnection");
02244 }
02245 
02246 //______________________________________________________________________________
02247 int TSystem::RecvRaw(int, void *, int, int)
02248 {
02249    // Receive exactly length bytes into buffer. Use opt to receive out-of-band
02250    // data or to have a peek at what is in the buffer (see TSocket).
02251 
02252    AbstractMethod("RecvRaw");
02253    return -1;
02254 }
02255 
02256 //______________________________________________________________________________
02257 int TSystem::SendRaw(int, const void *, int, int)
02258 {
02259    // Send exactly length bytes from buffer. Use opt to send out-of-band
02260    // data (see TSocket).
02261 
02262    AbstractMethod("SendRaw");
02263    return -1;
02264 }
02265 
02266 //______________________________________________________________________________
02267 int TSystem::RecvBuf(int, void *, int)
02268 {
02269    // Receive a buffer headed by a length indicator.
02270 
02271    AbstractMethod("RecvBuf");
02272    return -1;
02273 }
02274 
02275 //______________________________________________________________________________
02276 int TSystem::SendBuf(int, const void *, int)
02277 {
02278    // Send a buffer headed by a length indicator.
02279 
02280    AbstractMethod("SendBuf");
02281    return -1;
02282 }
02283 
02284 //______________________________________________________________________________
02285 int TSystem::SetSockOpt(int, int, int)
02286 {
02287    // Set socket option.
02288 
02289    AbstractMethod("SetSockOpt");
02290    return -1;
02291 }
02292 
02293 //______________________________________________________________________________
02294 int TSystem::GetSockOpt(int, int, int*)
02295 {
02296    // Get socket option.
02297 
02298    AbstractMethod("GetSockOpt");
02299    return -1;
02300 }
02301 
02302 //---- System, CPU and Memory info ---------------------------------------------
02303 
02304 //______________________________________________________________________________
02305 int TSystem::GetSysInfo(SysInfo_t *) const
02306 {
02307    // Returns static system info, like OS type, CPU type, number of CPUs
02308    // RAM size, etc into the SysInfo_t structure. Returns -1 in case of error,
02309    // 0 otherwise.
02310 
02311    AbstractMethod("GetSysInfo");
02312    return -1;
02313 }
02314 
02315 //______________________________________________________________________________
02316 int TSystem::GetCpuInfo(CpuInfo_t *, Int_t) const
02317 {
02318    // Returns cpu load average and load info into the CpuInfo_t structure.
02319    // Returns -1 in case of error, 0 otherwise. Use sampleTime to set the
02320    // interval over which the CPU load will be measured, in ms (default 1000).
02321 
02322    AbstractMethod("GetCpuInfo");
02323    return -1;
02324 }
02325 
02326 //______________________________________________________________________________
02327 int TSystem::GetMemInfo(MemInfo_t *) const
02328 {
02329    // Returns ram and swap memory usage info into the MemInfo_t structure.
02330    // Returns -1 in case of error, 0 otherwise.
02331 
02332    AbstractMethod("GetMemInfo");
02333    return -1;
02334 }
02335 
02336 //______________________________________________________________________________
02337 int TSystem::GetProcInfo(ProcInfo_t *) const
02338 {
02339    // Returns cpu and memory used by this process into the ProcInfo_t structure.
02340    // Returns -1 in case of error, 0 otherwise.
02341 
02342    AbstractMethod("GetProcInfo");
02343    return -1;
02344 }
02345 
02346 //---- Script Compiler ---------------------------------------------------------
02347 
02348 void AssignAndDelete(TString& target, char *tobedeleted) {
02349    target = tobedeleted;
02350    delete [] tobedeleted;
02351 }
02352 
02353 #ifdef WIN32
02354 
02355 static TString R__Exec(const char *cmd)
02356 {
02357    // Execute a command and return the stdout in a string.
02358 
02359    FILE * f = gSystem->OpenPipe(cmd,"r");
02360    if (!f) {
02361       return "";
02362    }
02363    TString result;
02364 
02365    char x;
02366    while ((x = fgetc(f))!=EOF ) {
02367       if (x=='\n' || x=='\r') break;
02368       result += x;
02369    }
02370 
02371    fclose(f);
02372    return result;
02373 }
02374 
02375 static void R__FixLink(TString &cmd)
02376 {
02377    // Replace the call to 'link' by a full path name call based on where cl.exe is.
02378    // This prevents us from using inadvertently the link.exe provided by cygwin.
02379 
02380    // check if link is the microsoft one...
02381    TString res = R__Exec("link 2>&1");
02382    if (res.Length()) {
02383       if (res.Contains("Microsoft (R) Incremental Linker"))
02384          return;
02385    }
02386    // else check availability of cygpath...
02387    res = R__Exec("cygpath . 2>&1");
02388    if (res.Length()) {
02389       if (res != ".")
02390          return;
02391    }
02392 
02393    res = R__Exec("which cl.exe 2>&1|grep cl|sed 's,cl\\.exe$,link\\.exe,' 2>&1");
02394    if (res.Length()) {
02395       res = R__Exec(Form("cygpath -w '%s' 2>&1",res.Data()));
02396       if (res.Length()) {
02397          cmd.ReplaceAll(" link ",Form(" \"%s\" ",res.Data()));
02398       }
02399    }
02400 }
02401 #endif
02402 
02403 #ifndef WIN32
02404 static void R__AddPath(TString &target, const TString &path) {
02405    target += path;
02406 }
02407 #else
02408 static void R__AddPath(TString &target, const TString &path) {
02409    if (path.Length() > 2 && path[1]==':') {
02410       target += TString::Format("/cygdrive/%c",path[0]) + path(2,path.Length()-2);
02411    } else {
02412       target += path;
02413    }
02414 }
02415 #endif
02416 
02417 #ifndef WIN32
02418 static void R__WriteDependencyFile(const TString & build_loc, const TString &depfilename, const TString &filename, const TString &library, const TString &libname,
02419                                    const TString &extension, const char *version_var_prefix, const TString &includes, const TString &defines, const TString &incPath) {
02420 #else
02421 static void R__WriteDependencyFile(const TString &build_loc, const TString &depfilename, const TString &filename, const TString &library, const TString &libname,
02422                                    const TString &extension, const char *version_var_prefix, const TString &includes, const TString &defines, const TString &incPath) {
02423 #endif
02424    // Generate the dependency via standard output, not searching the
02425    // standard include directories,
02426 
02427 #ifndef WIN32
02428    const char * stderrfile = "/dev/null";
02429 #else
02430    TString stderrfile;
02431    AssignAndDelete( stderrfile, gSystem->ConcatFileName(build_loc,"stderr.tmp") );
02432 #endif
02433    TString bakdepfilename = depfilename + ".bak";
02434 
02435 #ifdef WIN32
02436    TString touch = "echo # > "; touch += "\"" + depfilename + "\"";
02437 #else
02438    TString touch = "echo > "; touch += "\"" + depfilename + "\"";
02439 #endif
02440    TString builddep = "rmkdepend \"-f";
02441    builddep += depfilename;
02442    builddep += "\" -o_" + extension + "." + gSystem->GetSoExt() + " ";
02443    if (build_loc.BeginsWith(gSystem->WorkingDirectory())) {
02444       Int_t len = strlen(gSystem->WorkingDirectory());
02445       if ( build_loc.Length() > (len+1) ) {
02446          builddep += " \"-p";
02447          if (build_loc[len] == '/' || build_loc[len+1] != '\\' ) {
02448             // Since the path is now ran through TSystem::ExpandPathName the single \ is also possible.
02449             R__AddPath(builddep, build_loc.Data() + len + 1 );
02450          } else {
02451             // Case of dir\\name
02452             R__AddPath(builddep, build_loc.Data() + len + 2 );
02453          }
02454          builddep += "/\" ";
02455       }
02456    } else {
02457       builddep += " \"-p";
02458       R__AddPath(builddep, build_loc);
02459       builddep += "/\" ";
02460    }
02461    builddep += " -Y -- ";
02462 #ifndef ROOTINCDIR
02463    TString rootsys = gSystem->Getenv("ROOTSYS");
02464 #else
02465    TString rootsys = ROOTINCDIR;
02466 #endif
02467    builddep += " \"-I"+rootsys+"/include\" "; // cflags
02468    builddep += includes;
02469    builddep += defines;
02470    builddep += " -- \"";
02471    builddep += filename;
02472    builddep += "\" ";
02473    TString targetname;
02474    if (library.BeginsWith(gSystem->WorkingDirectory())) {
02475       Int_t len = strlen(gSystem->WorkingDirectory());
02476       if ( library.Length() > (len+1) ) {
02477          if (library[len] == '/' || library[len+1] != '\\' ) {
02478             targetname = library.Data() + len + 1;
02479          } else {
02480             targetname = library.Data() + len + 2;
02481          }
02482       } else {
02483          targetname = library;
02484       }
02485    } else {
02486       targetname = library;
02487    }
02488    builddep += " \"";
02489    builddep += "-t";
02490    R__AddPath(builddep, targetname);
02491    builddep += "\" > ";
02492    builddep += stderrfile;
02493    builddep += " 2>&1 ";
02494 
02495    TString adddictdep = "echo ";
02496    R__AddPath(adddictdep,targetname);
02497    adddictdep += ": ";
02498    {
02499       char *cintdictversion = gSystem->Which(incPath,"cintdictversion.h");
02500       if (cintdictversion) {
02501          R__AddPath(adddictdep,cintdictversion);
02502          adddictdep += " ";
02503          delete [] cintdictversion;
02504       } else {
02505          R__AddPath(adddictdep,rootsys+"/include/cintdictversion.h ");
02506       }
02507    }
02508    {
02509       char *rootVersion = gSystem->Which(incPath,"RVersion.h");
02510       if (rootVersion) {
02511          R__AddPath(adddictdep,rootVersion);
02512          adddictdep += " ";
02513          delete [] rootVersion;
02514       } else {
02515          R__AddPath(adddictdep,rootsys+"/include/RVersion.h ");
02516       }
02517    }
02518    adddictdep += " >> \""+depfilename+"\"";
02519 
02520    TString addversiondep( "echo ");
02521    addversiondep += libname + version_var_prefix + " \"" + ROOT_RELEASE + "\" >> \""+depfilename+"\"";
02522 
02523    if (gDebug > 4)  {
02524       ::Info("ACLiC", "%s", touch.Data());
02525       ::Info("ACLiC", "%s", builddep.Data());
02526       ::Info("ACLiC", "%s", adddictdep.Data());
02527    }
02528 
02529    Int_t depbuilt = !gSystem->Exec(touch);
02530    if (depbuilt) depbuilt = !gSystem->Exec(builddep);
02531    if (depbuilt) depbuilt = !gSystem->Exec(adddictdep);
02532    if (depbuilt) depbuilt = !gSystem->Exec(addversiondep);
02533 
02534    if (!depbuilt) {
02535       ::Warning("ACLiC","Failed to generate the dependency file for %s",
02536                 library.Data());
02537    } else {
02538 #ifdef WIN32
02539       gSystem->Unlink(stderrfile);
02540 #endif
02541       gSystem->Unlink(bakdepfilename);
02542    }
02543 }
02544 
02545 //______________________________________________________________________________
02546 int TSystem::CompileMacro(const char *filename, Option_t *opt,
02547                           const char *library_specified,
02548                           const char *build_dir,
02549                           UInt_t dirmode)
02550 {
02551    // This method compiles and loads a shared library containing
02552    // the code from the file "filename".
02553    //
02554    // The possible options are:
02555    //     k : keep the shared library after the session end.
02556    //     f : force recompilation.
02557    //     g : compile with debug symbol
02558    //     O : optimized the code (ignore if 'g' is specified)
02559    //     c : compile only, do not attempt to load the library.
02560    //     - : if buildir is set, use a flat structure (see buildir below)
02561    //
02562    // If library_specified is specified, CompileMacro generates the file
02563    // "library_specified".soext where soext is the shared library extension for
02564    // the current platform.
02565    //
02566    // If build_dir is specified, it is used as an alternative 'root' for the
02567    // generation of the shared library.  The library is stored in a sub-directories
02568    // of 'build_dir' including the full pathname of the script unless a flat
02569    // directory structure is requested ('-' option).  With the '-' option the libraries
02570    // are created directly in the directory 'build_dir'; in particular this means that
02571    // 2 scripts with the same name in different source directory will over-write each
02572    // other's library.
02573    // See also TSystem::SetBuildDir.
02574    //
02575    // If dirmode is not zero and we need to create the target directory, the
02576    // file mode bit will be change to 'dirmode' using chmod.
02577    //
02578    // If library_specified is not specified, CompileMacro generate a default name
02579    // for library by taking the name of the file "filename" but replacing the
02580    // dot before the extension by an underscore and by adding the shared
02581    // library extension for the current platform.
02582    // For example on most platform, hsimple.cxx will generate hsimple_cxx.so
02583    //
02584    // It uses the directive fMakeSharedLibs to create a shared library.
02585    // If loading the shared library fails, it tries to output a list of missing
02586    // symbols by creating an executable (on some platforms like OSF, this does
02587    // not HAVE to be an executable) containing the script. It uses the
02588    // directive fMakeExe to do so.
02589    // For both directives, before passing them to TSystem::Exec, it expands the
02590    // variables $SourceFiles, $SharedLib, $LibName, $IncludePath, $LinkedLibs,
02591    // $DepLibs, $ExeName and $ObjectFiles. See SetMakeSharedLib() for more
02592    // information on those variables.
02593    //
02594    // This method is used to implement the following feature:
02595    //
02596    // Synopsis:
02597    //
02598    // The purpose of this addition is to allow the user to use an external
02599    // compiler to create a shared library from its C++ macro (scripts).
02600    // Currently in order to execute a script, a user has to type at the root
02601    // prompt
02602    //
02603    //  .X myfunc.C(arg1,arg2)
02604    //
02605    // We allow him to type:
02606    //
02607    //  .X myfunc.C++(arg1,arg2)
02608    // or
02609    //  .X myfunc.C+(arg1,arg2)
02610    //
02611    // In which case an external compiler will be called to create a shared
02612    // library.  This shared library will then be loaded and the function
02613    // myfunc will be called with the two arguments.  With '++' the shared library
02614    // is always recompiled.  With '+' the shared library is recompiled only
02615    // if it does not exist yet or the macro file is newer than the shared
02616    // library.
02617    //
02618    // Of course the + and ++ notation is supported in similar way for .x and .L.
02619    //
02620    // Through the function TSystem::SetMakeSharedLib(), the user will be able to
02621    // indicate, with shell commands, how to build a shared library (a good
02622    // default will be provided). The most common change, namely where to find
02623    // header files, will be available through the function
02624    // TSystem::SetIncludePath().
02625    // A good default will be provided so that a typical user session should be at
02626    // most:
02627    //
02628    // root[1] gSystem->SetIncludePath("-I$ROOTSYS/include
02629    // -I$HOME/mypackage/include");
02630    // root[2] .x myfunc.C++(10,20);
02631    //
02632    // The user may sometimes try to compile a script before it has loaded all the
02633    // needed shared libraries.  In this case we want to be helpfull and output a
02634    // list of the unresolved symbols. So if the loading of the created shared
02635    // library fails, we will try to build a executable that contains the
02636    // script. The linker should then output a list of missing symbols.
02637    //
02638    // To support this we provide a TSystem::SetMakeExe() function, that sets the
02639    // directive telling how to create an executable. The loader will need
02640    // to be informed of all the libraries available. The information about
02641    // the libraries that has been loaded by .L and TSystem::Load() is accesible
02642    // to the script compiler. However, the information about
02643    // the libraries that have been selected at link time by the application
02644    // builder (like the root libraries for root.exe) are not available and need
02645    // to be explictly listed in fLinkedLibs (either by default or by a call to
02646    // TSystem::SetLinkedLibs()).
02647    //
02648    // To simplify customization we could also add to the .rootrc support for the
02649    // variables
02650    //
02651    // Unix.*.Root.IncludePath:     -I$ROOTSYS/include
02652    // WinNT.*.Root.IncludePath:    -I%ROOTSYS%/include
02653    //
02654    // Unix.*.Root.LinkedLibs:      -L$ROOTSYS/lib -lBase ....
02655    // WinNT.*.Root.LinkedLibs:     %ROOTSYS%/lib/*.lib msvcrt.lib ....
02656    //
02657    // And also support for MakeSharedLibs() and MakeExe().
02658    //
02659    // (the ... have to be replaced by the actual values and are here only to
02660    // shorten this comment).
02661    //
02662 
02663    static const char *version_var_prefix = "__ROOTBUILDVERSION=";
02664 
02665    // ======= Analyze the options
02666    Bool_t keep = kFALSE;
02667    Bool_t recompile = kFALSE;
02668    EAclicMode mode = fAclicMode;
02669    Bool_t loadLib = kTRUE;
02670    if (opt) {
02671       keep = (strchr(opt,'k')!=0);
02672       recompile = (strchr(opt,'f')!=0);
02673       if (strchr(opt,'O')!=0) {
02674          mode = kOpt;
02675       }
02676       if (strchr(opt,'g')!=0) {
02677          mode = kDebug;
02678       }
02679       if (strchr(opt,'c')!=0) {
02680          loadLib = kFALSE;
02681       }
02682    }
02683    if (mode==kDefault) {
02684       TString rootbuild = ROOTBUILD;
02685       if (rootbuild.Index("debug",0,TString::kIgnoreCase)==kNPOS) {
02686          mode=kOpt;
02687       } else {
02688          mode=kDebug;
02689       }
02690    }
02691    Bool_t flatBuildDir = (fAclicProperties & kFlatBuildDir) || (strchr(opt,'-')!=0);
02692 
02693    // if non-zero, build_loc indicates where to build the shared library.
02694    TString build_loc = ExpandFileName(GetBuildDir());
02695    if (build_dir && strlen(build_dir)) build_loc = build_dir;
02696    if (build_loc == ".") {
02697       build_loc = WorkingDirectory();
02698    } else if (build_loc.Length() && (!IsAbsoluteFileName(build_loc)) ) {
02699       AssignAndDelete( build_loc , ConcatFileName( WorkingDirectory(), build_loc ) );
02700    }
02701 
02702    // Get the include directory list in the dir1:dir2:dir3 format
02703    // [Used for generating the .d file and to look for header files for
02704    // the linkdef file]
02705    TString incPath = GetIncludePath(); // of the form -Idir1  -Idir2 -Idir3
02706    incPath.Append(":").Prepend(" ");
02707    if (gEnv) {
02708       TString fromConfig = gEnv->GetValue("ACLiC.IncludePaths","");
02709       incPath.Append(fromConfig);
02710    }
02711    incPath.ReplaceAll(" -I",":");       // of form :dir1 :dir2:dir3
02712    while ( incPath.Index(" :") != -1 ) {
02713       incPath.ReplaceAll(" :",":");
02714    }
02715    incPath.Prepend(":.:");
02716    incPath.Prepend(WorkingDirectory());
02717 
02718    // ======= Get the right file names for the dictionnary and the shared library
02719    TString expFileName(filename);
02720    ExpandPathName( expFileName );
02721    TString library = expFileName;
02722    if (! IsAbsoluteFileName(library) )
02723    {
02724       const char *whichlibrary = Which(incPath,library);
02725       if (whichlibrary) {
02726          library = whichlibrary;
02727          delete [] whichlibrary;
02728       } else {
02729          ::Error("ACLiC","The file %s can not be found in the include path: %s",filename,incPath.Data());
02730          return kFALSE;
02731       }
02732    } else {
02733       if (gSystem->AccessPathName(library)) {
02734          ::Error("ACLiC","The file %s can not be found.",filename);
02735          return kFALSE;
02736       }
02737    }
02738    { // Remove multiple '/' characters, rootcint treats them as comments.
02739       Ssiz_t pos = 0;
02740       while ((pos = library.Index("//", 2, pos, TString::kExact)) != kNPOS) {
02741          library.Remove(pos, 1);
02742       }
02743    }
02744    TString filename_fullpath = library;
02745 
02746    TString file_dirname = DirName( filename_fullpath );
02747    // For some probably good reason, DirName on Windows returns the 'name' of
02748    // the directory, omitting the drive letter (even if there was one). In
02749    // consequence the result is not useable as a 'root directory', we need to
02750    // add the drive letter if there was one..
02751    if (library.Length()>1 && isalpha(library[0]) && library[1]==':') {
02752       file_dirname.Prepend(library(0,2));
02753    }
02754    TString file_location( file_dirname  ); // Location of the script.
02755    incPath.Prepend( file_location + ":" );
02756 
02757    Ssiz_t dot_pos = library.Last('.');
02758    TString extension = library;
02759    extension.Replace( 0, dot_pos+1, 0 , 0);
02760    TString libname_noext = library;
02761    if (dot_pos>=0) libname_noext.Remove( dot_pos );
02762 
02763    // Extension of shared library is platform dependent!!
02764    library.Replace( dot_pos, library.Length()-dot_pos,
02765                     TString("_") + extension + "." + fSoExt );
02766 
02767    TString libname ( BaseName( libname_noext ) );
02768    libname.Append("_").Append(extension);
02769 
02770    if (library_specified && strlen(library_specified) ) {
02771       // Use the specified name instead of the default
02772       libname = BaseName( library_specified );
02773       library = library_specified;
02774       ExpandPathName( library );
02775       if (! IsAbsoluteFileName(library) ) {
02776          AssignAndDelete( library , ConcatFileName( WorkingDirectory(), library ) );
02777       }
02778       library = TString(library) + "." + fSoExt;
02779    }
02780 
02781    TString libname_ext ( libname );
02782    libname_ext +=  "." + fSoExt;
02783 
02784    TString lib_dirname = DirName( library );
02785    // For some probably good reason, DirName on Windows returns the 'name' of
02786    // the directory, omitting the drive letter (even if there was one). In
02787    // consequence the result is not useable as a 'root directory', we need to
02788    // add the drive letter if there was one..
02789    if (library.Length()>1 && isalpha(library[0]) && library[1]==':') {
02790       lib_dirname.Prepend(library(0,2));
02791    }
02792    // Strip potential, somewhat redundant '/.' from the pathname ...
02793    if ( strncmp( &(lib_dirname[lib_dirname.Length()-2]), "/.", 2) == 0 ) {
02794       lib_dirname.Remove(lib_dirname.Length()-2);
02795    }
02796    if ( strncmp( &(lib_dirname[lib_dirname.Length()-2]), "\\.", 2) == 0 ) {
02797       lib_dirname.Remove(lib_dirname.Length()-2);
02798    }
02799    TString lib_location( lib_dirname );
02800    Bool_t mkdirFailed = kFALSE;
02801 
02802    if (build_loc.Length()==0) {
02803       build_loc = lib_location;
02804    } else {
02805       // Removes an existing disk specification from the names
02806       TRegexp disk_finder ("[A-z]:");
02807       Int_t pos = library.Index( disk_finder );
02808       if (pos==0) library.Remove(pos,3);
02809       pos = lib_location.Index( disk_finder );
02810       if (pos==0) lib_location.Remove(pos,3);
02811 
02812       if (flatBuildDir) {
02813          AssignAndDelete( library, ConcatFileName( build_loc, libname_ext) );
02814       } else {
02815          AssignAndDelete( library, ConcatFileName( build_loc, library) );
02816       }
02817 
02818       Bool_t canWriteBuild_loc = !gSystem->AccessPathName(build_loc,kWritePermission);
02819       TString build_loc_store( build_loc );
02820       if (!flatBuildDir) {
02821          AssignAndDelete( build_loc, ConcatFileName( build_loc, lib_location) );
02822       }
02823 
02824       if (gSystem->AccessPathName(build_loc,kFileExists)) {
02825          mkdirFailed = (0 != mkdir(build_loc, true));
02826          if (mkdirFailed && !canWriteBuild_loc) {
02827             // The mkdir failed __and__ we can not write to the target directory,
02828             // let make sure the error message will be about the target directory
02829             build_loc = build_loc_store;
02830             mkdirFailed = kFALSE;
02831          } else if (!mkdirFailed && dirmode!=0) {
02832             Chmod(build_loc,dirmode);
02833          }
02834       }
02835    }
02836 
02837    // ======= Check if the library need to loaded or compiled
02838    if ( gInterpreter->IsLoaded(expFileName) ) {
02839       // the script has already been loaded in interpreted mode
02840       // Let's warn the user and unload it.
02841 
02842       ::Info("ACLiC","script has already been loaded in interpreted mode");
02843       ::Info("ACLiC","unloading %s and compiling it", filename);
02844 
02845       if ( gInterpreter->UnloadFile( expFileName ) != 0 ) {
02846          // We can not unload it.
02847          return kFALSE;
02848       }
02849    }
02850 
02851    // Calculate the -I lines
02852    TString includes = GetIncludePath();
02853    includes.Prepend(' ');
02854 
02855    {
02856       // I need to replace the -Isomerelativepath by -I../ (or -I..\ on NT)
02857       TRegexp rel_inc(" -I[^\"/\\$%-][^:-]+");
02858       Int_t len,pos;
02859       pos = rel_inc.Index(includes,&len);
02860       while( len != 0 ) {
02861          TString sub = includes(pos,len);
02862          sub.Remove(0,3); // Remove ' -I'
02863          AssignAndDelete( sub, ConcatFileName( WorkingDirectory(), sub ) );
02864          sub.Prepend(" -I");
02865          includes.Replace(pos,len,sub);
02866          pos = rel_inc.Index(includes,&len);
02867       }
02868    }
02869    {
02870        // I need to replace the -I"somerelativepath" by -I"$cwd/ (or -I"$cwd\ on NT)
02871       TRegexp rel_inc(" -I\"[^/\\$%-][^:-]+");
02872       Int_t len,pos;
02873       pos = rel_inc.Index(includes,&len);
02874       while( len != 0 ) {
02875          TString sub = includes(pos,len);
02876          sub.Remove(0,4); // Remove ' -I"'
02877          AssignAndDelete( sub, ConcatFileName( WorkingDirectory(), sub ) );
02878          sub.Prepend(" -I\"");
02879          includes.Replace(pos,len,sub);
02880          pos = rel_inc.Index(includes,&len);
02881       }
02882    }
02883    includes += " -I\"" + build_loc;
02884    includes += "\" -I\"";
02885    includes += WorkingDirectory();
02886    includes += "\"";
02887    if (gEnv) {
02888       TString fromConfig = gEnv->GetValue("ACLiC.IncludePaths","");
02889       includes.Append(" ").Append(fromConfig).Append(" ");
02890    }
02891 
02892    // Extract the -D for the dependency generation.
02893    TString defines = " ";
02894    {
02895       TString cmd = GetMakeSharedLib();
02896       TRegexp rel_def("-D[^\\s\\t\\n\\r]*");
02897       Int_t len,pos;
02898       pos = rel_def.Index(cmd,&len);
02899       while( len != 0 ) {
02900          defines += cmd(pos,len);
02901          defines += " ";
02902          pos = rel_def.Index(cmd,&len,pos+1);
02903       }
02904 
02905    }
02906 
02907    TString emergency_loc;
02908    {
02909       UserGroup_t *ug = gSystem->GetUserInfo(gSystem->GetUid());
02910       if (ug) {
02911          AssignAndDelete( emergency_loc, ConcatFileName( TempDirectory(), ug->fUser ) );
02912          delete ug;
02913       } else {
02914          emergency_loc = TempDirectory();
02915       }
02916    }
02917 
02918    Bool_t canWrite = !gSystem->AccessPathName(build_loc,kWritePermission);
02919 
02920    Bool_t modified = kFALSE;
02921 
02922    // Generate the dependency filename
02923    TString depdir = build_loc;
02924    TString depfilename;
02925    AssignAndDelete( depfilename, ConcatFileName(depdir, BaseName(libname_noext)) );
02926    depfilename += "_" + extension + ".d";
02927 
02928    if ( !recompile ) {
02929 
02930       Long_t lib_time, file_time;
02931 
02932       if ((gSystem->GetPathInfo( library, 0, (Long_t*)0, 0, &lib_time ) != 0) ||
02933           (gSystem->GetPathInfo( expFileName, 0, (Long_t*)0, 0, &file_time ) == 0 &&
02934           (lib_time < file_time))) {
02935 
02936          // the library does not exist or is older than the script.
02937          recompile = kTRUE;
02938          modified  = kTRUE;
02939 
02940       } else {
02941 
02942          if ( gSystem->GetPathInfo( depfilename, 0,(Long_t*) 0, 0, &file_time ) != 0 ) {
02943             if (!canWrite) {
02944                depdir = emergency_loc;
02945                AssignAndDelete( depfilename, ConcatFileName(depdir, BaseName(libname_noext)) );
02946                depfilename += "_" + extension + ".d";
02947             }
02948             R__WriteDependencyFile(build_loc, depfilename, filename_fullpath, library, libname, extension, version_var_prefix, includes, defines, incPath);
02949          }
02950       }
02951 
02952       if (!modified) {
02953 
02954          // We need to check the dependencies
02955          FILE * depfile = fopen(depfilename.Data(),"r");
02956          if (depfile==0) {
02957             // there is no acessible dependency file, let's assume the library has been
02958             // modified
02959             modified = kTRUE;
02960             recompile = kTRUE;
02961 
02962          } else {
02963 
02964             TString version_var = libname + version_var_prefix;
02965 
02966             Int_t sz = 256;
02967             char *line = new char[sz];
02968             line[0] = 0;
02969 
02970             int c;
02971             Int_t current = 0;
02972             Int_t nested = 0;
02973             Bool_t hasversion = false;
02974 
02975             while ((c = fgetc(depfile)) != EOF) {
02976                if (c=='#') {
02977                   // skip comment
02978                   while ((c = fgetc(depfile)) != EOF) {
02979                      if (c=='\n') {
02980                         break;
02981                      }
02982                   }
02983                   continue;
02984                }
02985                if (current && line[current-1]=='=' && strncmp(version_var.Data(),line,current)==0) {
02986 
02987                   // The next word will be the version number.
02988                   hasversion = kTRUE;
02989                   line[0] = 0;
02990                   current = 0;
02991                } else if (isspace(c) && !nested) {
02992                   if (current) {
02993                      if (line[current-1]!=':') {
02994                         // ignore target
02995                         line[current] = 0;
02996 
02997                         Long_t filetime;
02998                         if (hasversion) {
02999                            modified |= strcmp(ROOT_RELEASE,line)!=0;
03000                            hasversion = kFALSE;
03001                         } else if ( gSystem->GetPathInfo( line, 0, (Long_t*)0, 0, &filetime ) == 0 ) {
03002                            modified |= ( lib_time <= filetime );
03003                         }
03004                      }
03005                   }
03006                   current = 0;
03007                   line[0] = 0;
03008                } else {
03009                   if (current==sz-1) {
03010                      sz = 2*sz;
03011                      char *newline = new char[sz];
03012                      strcpy(newline,line);
03013                      delete [] line;
03014                      line = newline;
03015                   }
03016                   if (c=='"') nested = !nested;
03017                   else {
03018                      line[current] = c;
03019                      current++;
03020                   }
03021                }
03022             }
03023             delete [] line;
03024             fclose(depfile);
03025             recompile = modified;
03026 
03027          }
03028 
03029       }
03030    }
03031 
03032    if ( gInterpreter->IsLoaded(library)
03033         || strlen(GetLibraries(library,"D",kFALSE)) != 0 ) {
03034       // The library has already been built and loaded.
03035 
03036       Bool_t reload = kFALSE;
03037       TNamed *libinfo = (TNamed*)fCompiled->FindObject(library);
03038       if (libinfo) {
03039          Long_t load_time = libinfo->GetUniqueID();
03040          Long_t lib_time;
03041          if ( gSystem->GetPathInfo( library, 0, (Long_t*)0, 0, &lib_time ) == 0
03042               && (lib_time>load_time)) {
03043             reload = kTRUE;
03044          }
03045       }
03046 
03047       if ( !recompile && reload ) {
03048 
03049          ::Info("ACLiC","%s has been modified and will be reloaded",
03050                 libname.Data());
03051          if ( gInterpreter->UnloadFile( library.Data() ) != 0 ) {
03052             // The library is being used. We can not unload it.
03053             return kFALSE;
03054          }
03055          if (libinfo) {
03056             fCompiled->Remove(libinfo);
03057             delete libinfo;
03058             libinfo = 0;
03059          }
03060          TNamed *k = new TNamed(library,library);
03061          Long_t lib_time;
03062          gSystem->GetPathInfo( library, 0, (Long_t*)0, 0, &lib_time );
03063          k->SetUniqueID(lib_time);
03064          if (!keep) k->SetBit(kMustCleanup);
03065          fCompiled->Add(k);
03066 
03067          return !gSystem->Load(library);
03068       }
03069 
03070       ::Info("ACLiC","%s script has already been compiled and loaded",
03071                 modified ? "modified" : "unmodified");
03072 
03073       if ( !recompile ) {
03074          return kTRUE;
03075       } else {
03076          ::Info("ACLiC","it will be regenerated and reloaded!");
03077          if ( gInterpreter->UnloadFile( library.Data() ) != 0 ) {
03078             // The library is being used. We can not unload it.
03079             return kFALSE;
03080          }
03081          if (libinfo) {
03082             fCompiled->Remove(libinfo);
03083             delete libinfo;
03084             libinfo = 0;
03085          }
03086          Unlink(library);
03087       }
03088 
03089    }
03090 
03091    TString libmapfilename;
03092    AssignAndDelete( libmapfilename, ConcatFileName( build_loc, libname ) );
03093    libmapfilename += ".rootmap";
03094 #if (defined(R__MACOSX) && !defined(MAC_OS_X_VERSION_10_5)) || defined(R__WIN32)
03095    Bool_t produceRootmap = kTRUE;
03096 #else
03097    Bool_t produceRootmap = kFALSE;
03098 #endif
03099    Bool_t linkDepLibraries = !produceRootmap;
03100    if (gEnv) {
03101 #if (defined(R__MACOSX) && !defined(MAC_OS_X_VERSION_10_5))
03102       Int_t linkLibs = gEnv->GetValue("ACLiC.LinkLibs",2);
03103 #elif defined(R__WIN32)
03104       Int_t linkLibs = gEnv->GetValue("ACLiC.LinkLibs",3);
03105 #else
03106       Int_t linkLibs = gEnv->GetValue("ACLiC.LinkLibs",1);
03107 #endif
03108       produceRootmap = linkLibs & 0x2;
03109       linkDepLibraries = linkLibs & 0x1;
03110    }
03111 
03112    if (!recompile) {
03113       // The library already exist, let's just load it.
03114       if (loadLib) {
03115          TNamed *k = new TNamed(library,library);
03116          Long_t lib_time;
03117          gSystem->GetPathInfo( library, 0, (Long_t*)0, 0, &lib_time );
03118          k->SetUniqueID(lib_time);
03119          if (!keep) k->SetBit(kMustCleanup);
03120          fCompiled->Add(k);
03121 
03122          if (gInterpreter->GetSharedLibDeps(libname) == 0) {
03123             gInterpreter->LoadLibraryMap(libmapfilename);
03124          }
03125 
03126          return !gSystem->Load(library);
03127       }
03128       else return kTRUE;
03129    }
03130 
03131    if (!canWrite && recompile) {
03132 
03133       if (mkdirFailed) {
03134          ::Warning("ACLiC","Could not create the directory: %s",
03135                 build_loc.Data());
03136       } else {
03137          ::Warning("ACLiC","%s is not writeable!",
03138                    build_loc.Data());
03139       }
03140       if (emergency_loc == build_dir ) {
03141          ::Error("ACLiC","%s is the last resort location (i.e. temp location)",build_loc.Data());
03142          return kFALSE;
03143       }
03144       ::Warning("ACLiC","Output will be written to %s",
03145                 emergency_loc.Data());
03146       return CompileMacro(expFileName, opt, library_specified, emergency_loc, dirmode);
03147    }
03148 
03149    Info("ACLiC","creating shared library %s",library.Data());
03150 
03151    R__WriteDependencyFile(build_loc, depfilename, filename_fullpath, library, libname, extension, version_var_prefix, includes, defines, incPath);
03152 
03153    // ======= Select the dictionary name
03154    TString dict = libname + "_ACLiC_dict";
03155 
03156    // the file name end up in the file produced
03157    // by rootcint as a variable name so all character need to be valid!
03158    static const int maxforbidden = 27;
03159    static const char *forbidden_chars[maxforbidden] =
03160       { "+","-","*","/","&","%","|","^",">","<",
03161         "=","~",".","(",")","[","]","!",",","$",
03162         " ",":","'","#","@","\\","\"" };
03163    for( int ic = 0; ic < maxforbidden; ic++ ) {
03164       dict.ReplaceAll( forbidden_chars[ic],"_" );
03165    }
03166    if ( dict.Last('.')!=dict.Length()-1 ) dict.Append(".");
03167    AssignAndDelete( dict, ConcatFileName( build_loc, dict ) );
03168    TString dicth = dict;
03169    TString dictObj = dict;
03170    dict += "cxx"; //no need to keep the extention of the original file, any extension will do
03171    dicth += "h";
03172    dictObj += fObjExt;
03173 
03174    // ======= Generate a linkdef file
03175 
03176    TString linkdef;
03177    AssignAndDelete( linkdef, ConcatFileName( build_loc, libname ) );
03178    linkdef += "_ACLiC_linkdef.h";
03179    ofstream linkdefFile( linkdef, ios::out );
03180    linkdefFile << "// File Automatically generated by the ROOT Script Compiler "
03181                << endl;
03182    linkdefFile << endl;
03183    linkdefFile << "#ifdef __CINT__" << endl;
03184    linkdefFile << endl;
03185    linkdefFile << "#pragma link C++ nestedclasses;" << endl;
03186    linkdefFile << "#pragma link C++ nestedtypedefs;" << endl;
03187    linkdefFile << endl;
03188 
03189    // We want to look for a header file that has the same name as the macro
03190 
03191    const char * extensions[] = { ".h", ".hh", ".hpp", ".hxx",  ".hPP", ".hXX" };
03192 
03193    int i;
03194    for (i = 0; i < 6; i++ ) {
03195       char * name;
03196       TString extra_linkdef = BaseName( libname_noext );
03197       extra_linkdef.Append(GetLinkdefSuffix());
03198       extra_linkdef.Append(extensions[i]);
03199       name = Which(incPath,extra_linkdef);
03200       if (name) {
03201          if (gDebug>4) Info("ACLiC","including extra linkdef file: %s",name);
03202          linkdefFile << "#include \"" << name << "\"" << endl;
03203          delete [] name;
03204       }
03205    }
03206 
03207    if (gDebug>5) Info("ACLiC","looking for header in: %s",incPath.Data());
03208    for (i = 0; i < 6; i++ ) {
03209       char * name;
03210       TString lookup = BaseName( libname_noext );
03211       lookup.Append(extensions[i]);
03212       name = Which(incPath,lookup);
03213       if (name) {
03214          linkdefFile << "#pragma link C++ defined_in "<<name<<";"<< endl;
03215          delete [] name;
03216       }
03217    }
03218    linkdefFile << "#pragma link C++ defined_in \""<<filename_fullpath << "\";" << endl;
03219    linkdefFile << endl;
03220    linkdefFile << "#endif" << endl;
03221    linkdefFile.close();
03222 
03223    // ======= Generate the list of rootmap files to be looked at
03224 
03225    TString mapfile;
03226    AssignAndDelete( mapfile, ConcatFileName( build_loc, libname ) );
03227    mapfile += "_ACLiC_map";
03228    TString mapfilein = mapfile + ".in";
03229    TString mapfileout = mapfile + ".out";
03230 
03231    Bool_t needLoadMap = kFALSE;
03232    if (gInterpreter->GetSharedLibDeps(libname) !=0 ) {
03233        gInterpreter->UnloadLibraryMap(libname);
03234       needLoadMap = kTRUE;
03235    }
03236 
03237    ofstream mapfileStream( mapfilein, ios::out );
03238    {
03239       TString name = ".rootmap";
03240       TString sname = "system.rootmap";
03241       TString file;
03242 #ifdef ROOTETCDIR
03243       AssignAndDelete(file, ConcatFileName(ROOTETCDIR, sname) );
03244 #else
03245       TString etc = gRootDir;
03246 #ifdef WIN32
03247       etc += "\\etc";
03248 #else
03249       etc += "/etc";
03250 #endif
03251       AssignAndDelete(file, ConcatFileName(etc, sname));
03252       if (gSystem->AccessPathName(file)) {
03253          // for backward compatibility check also $ROOTSYS/system<name> if
03254          // $ROOTSYS/etc/system<name> does not exist
03255          AssignAndDelete(file, ConcatFileName(gRootDir, sname));
03256          if (gSystem->AccessPathName(file)) {
03257             // for backward compatibility check also $ROOTSYS/<name> if
03258             // $ROOTSYS/system<name> does not exist
03259             AssignAndDelete(file, ConcatFileName(gRootDir, name));
03260          }
03261       }
03262 #endif
03263       mapfileStream << file << endl;
03264       AssignAndDelete(file, ConcatFileName(gSystem->HomeDirectory(), name) );
03265       mapfileStream << file << endl;
03266       mapfileStream << name << endl;
03267       if (gInterpreter->GetRootMapFiles()) {
03268          for (i = 0; i < gInterpreter->GetRootMapFiles()->GetEntriesFast(); i++) {
03269             mapfileStream << ((TNamed*)gInterpreter->GetRootMapFiles()->At(i))->GetTitle() << endl;
03270          }
03271       }
03272    }
03273    mapfileStream.close();
03274 
03275    // ======= Generate the rootcint command line
03276    TString rcint;
03277 #ifndef ROOTBINDIR
03278    rcint = gSystem->Getenv("ROOTSYS");
03279 #ifndef R__WIN32
03280    rcint += "/bin/";
03281 #else
03282    rcint += "\\bin\\";
03283 #endif
03284 #else
03285    rcint = ROOTBINDIR;
03286 #ifndef R__WIN32
03287    rcint += "/";
03288 #else
03289    rcint += "\\";
03290 #endif
03291 #endif
03292    rcint += "rootcint \"--lib-list-prefix=";
03293    rcint += mapfile;
03294    rcint += "\" -f \"";
03295    rcint.Append(dict).Append("\" -c -p ").Append(GetIncludePath()).Append(" ");
03296    if (produceRootmap) {
03297       rcint.Append("-DR__ACLIC_ROOTMAP ");
03298    }
03299    if (gEnv) {
03300       TString fromConfig = gEnv->GetValue("ACLiC.IncludePaths","");
03301       rcint.Append(fromConfig).Append(" \"");
03302    }
03303    rcint.Append(filename_fullpath).Append("\" \"").Append(linkdef).Append("\"");;
03304 
03305    // ======= Run rootcint
03306    if (gDebug>3) {
03307       ::Info("ACLiC","creating the dictionary files");
03308       if (gDebug>4)  ::Info("ACLiC", "%s", rcint.Data());
03309    }
03310 
03311    Int_t dictResult = gSystem->Exec(rcint);
03312    if (dictResult) {
03313       if (dictResult==139) ::Error("ACLiC","Dictionary generation failed with a core dump!");
03314       else ::Error("ACLiC","Dictionary generation failed!");
03315    }
03316 
03317    Bool_t result = !dictResult;
03318    TString depLibraries;
03319 
03320    // ======= Load the library the script might depend on
03321    if (result) {
03322       TString linkedlibs = GetLibraries("", "S");
03323       TString libtoload;
03324       TString all_libtoload;
03325       ifstream liblist(mapfileout);
03326 
03327       ofstream libmapfile;
03328       if (produceRootmap) {
03329          libmapfile.open(libmapfilename);
03330          libmapfile << "Library." << libname << ": " << libname;
03331       }
03332 
03333       while ( liblist >> libtoload ) {
03334          // Load the needed library except for the library we are currently building!
03335          if (libtoload != library && libtoload != libname && libtoload != libname_ext) {
03336             if (produceRootmap) {
03337                if (loadLib || linkDepLibraries /* For GetLibraries to Work */) gROOT->LoadClass("", libtoload);
03338                if (!linkedlibs.Contains(libtoload)) {
03339                   libmapfile << " " << libtoload;
03340                   all_libtoload.Append(" ").Append(libtoload);
03341                   depLibraries.Append(" ");
03342                   depLibraries.Append(GetLibraries(libtoload,"DSL",kFALSE));
03343                   depLibraries = depLibraries.Strip(); // Remove any trailing spaces.
03344                }
03345             } else {
03346                gROOT->LoadClass("", libtoload);
03347             }
03348          }
03349          unsigned char c = liblist.peek();
03350          if (c=='\n' || c=='\r') {
03351             // Consume the character
03352             liblist.get();
03353             break;
03354          }
03355       }
03356       if (produceRootmap) {
03357 
03358          std::string clname;
03359          while ( std::getline(liblist,clname) ) {
03360             std::replace(clname.begin(), clname.end(), ':', '@');
03361             std::replace(clname.begin(), clname.end(), ' ', '_');
03362             libmapfile << endl;
03363             libmapfile << "Library." << clname << ": " << libname << " " << all_libtoload;
03364          }
03365 
03366          libmapfile << endl;
03367          libmapfile.close();
03368       }
03369 //      depLibraries = all_libtoload;
03370 //      depLibraries.ReplaceAll(" lib"," -l");
03371 //      depLibraries.ReplaceAll(TString::Format(".%s",fSoExt.Data()),"");
03372    }
03373 
03374    // ======= Calculate the libraries for linking:
03375    TString linkLibraries;
03376    /*
03377      this is intentionally disabled until it can become usefull
03378      if (gEnv) {
03379         linkLibraries =  gEnv->GetValue("ACLiC.Libraries","");
03380         linkLibraries.Prepend(" ");
03381      }
03382    */
03383    linkLibraries.Prepend(GetLibraries("","SDL"));
03384 
03385    // ======= Generate the build command lines
03386    TString cmd = fMakeSharedLib;
03387    // we do not add filename because it is already included via the dictionary(in dicth) !
03388    // dict.Append(" ").Append(filename);
03389    cmd.ReplaceAll("$SourceFiles","\"$SourceFiles\"");
03390    cmd.ReplaceAll("$SourceFiles",dict);
03391    cmd.ReplaceAll("$ObjectFiles","\"$ObjectFiles\"");
03392    cmd.ReplaceAll("$ObjectFiles",dictObj);
03393    cmd.ReplaceAll("$IncludePath",includes);
03394    cmd.ReplaceAll("$SharedLib","\"$SharedLib\"");
03395    cmd.ReplaceAll("$SharedLib",library);
03396    if (linkDepLibraries) {
03397       if (produceRootmap) {
03398          cmd.ReplaceAll("$DepLibs",depLibraries);
03399       } else {
03400          cmd.ReplaceAll("$DepLibs",linkLibraries);
03401       }
03402    }
03403    cmd.ReplaceAll("$LinkedLibs",linkLibraries);
03404    cmd.ReplaceAll("$LibName",libname);
03405    cmd.ReplaceAll("\"$BuildDir","$BuildDir");
03406    cmd.ReplaceAll("$BuildDir","\"$BuildDir\"");
03407    cmd.ReplaceAll("$BuildDir",build_loc);
03408    if (mode==kDebug) {
03409       cmd.ReplaceAll("$Opt",fFlagsDebug);
03410    } else {
03411       cmd.ReplaceAll("$Opt",fFlagsOpt);
03412    }
03413 #ifdef WIN32
03414    R__FixLink(cmd);
03415 #endif
03416 
03417    TString testcmd = fMakeExe;
03418    TString fakeMain;
03419    AssignAndDelete( fakeMain, ConcatFileName( build_loc, libname ) );
03420    fakeMain += "_ACLiC_main";
03421    fakeMain += extension;
03422    ofstream fakeMainFile( fakeMain, ios::out );
03423    fakeMainFile << "// File Automatically generated by the ROOT Script Compiler "
03424                 << endl;
03425    fakeMainFile << "int main(char*argc,char**argvv) {};" << endl;
03426    fakeMainFile.close();
03427    // We could append this fake main routine to the compilation line.
03428    // But in this case compiler may output the name of the dictionary file
03429    // and of the fakeMain file while it compiles it. (this would be useless
03430    // confusing output).
03431    // We could also the fake main routine to the end of the dictionnary file
03432    // however compilation would fail if a main is already there
03433    // (like stress.cxx)
03434    // dict.Append(" ").Append(fakeMain);
03435    TString exec;
03436    AssignAndDelete( exec, ConcatFileName( build_loc, libname ) );
03437    exec += "_ACLiC_exec";
03438    testcmd.ReplaceAll("$SourceFiles",dict);
03439    testcmd.ReplaceAll("$ObjectFiles",dictObj);
03440    testcmd.ReplaceAll("$IncludePath",includes);
03441    testcmd.ReplaceAll("$ExeName",exec);
03442    testcmd.ReplaceAll("$LinkedLibs",linkLibraries);
03443    testcmd.ReplaceAll("$BuildDir",build_loc);
03444    if (mode==kDebug)
03445       testcmd.ReplaceAll("$Opt",fFlagsDebug);
03446    else
03447       testcmd.ReplaceAll("$Opt",fFlagsOpt);
03448 
03449 #ifdef WIN32
03450    R__FixLink(testcmd);
03451 #endif
03452 
03453    // ======= Build the library
03454    if (result) {
03455       if (gDebug>3) {
03456          ::Info("ACLiC","compiling the dictionary and script files");
03457          if (gDebug>4)  ::Info("ACLiC", "%s", cmd.Data());
03458       }
03459       Int_t compilationResult = gSystem->Exec( cmd );
03460       if (compilationResult) {
03461          if (compilationResult==139) ::Error("ACLiC","Compilation failed with a core dump!");
03462          else ::Error("ACLiC","Compilation failed!");
03463          if (produceRootmap) {
03464             gSystem->Unlink(libmapfilename);
03465          }
03466       }
03467       result = !compilationResult;
03468    } else {
03469       // rootcint failed
03470       // compile macro, to check its validity and to inform the user
03471       // of (possibly) invalid code
03472       ::Info("ACLiC","Invoking compiler to check macro's validity");
03473 
03474       // Need to extract the compiler call from MakeSharedLib.
03475       // Assume that the compiler call has $SourceFiles and
03476       // $IncludePath, as arguments, and that it's before the last
03477       // $ObjectFiles occurrence
03478 
03479       TString line(fMakeSharedLib);
03480       TString comp;
03481       Ssiz_t posEOL=kNPOS;
03482       // split cmd into command lines
03483       while ((kNPOS!=(posEOL=line.Index(";")) // ";" is end of line
03484               || kNPOS!=(posEOL=line.Index("&&"))) // and so is "&&"
03485              // stop if we passed through all $ObjectFiles occurrences
03486              && kNPOS!=line.Index("$ObjectFiles")) {
03487          Ssiz_t posSource=line.Index("$SourceFiles");
03488          Ssiz_t posInclude=line.Index("$IncludePath");
03489          if (posSource!=kNPOS && posSource<posEOL
03490              && posInclude!=kNPOS && posInclude<posEOL)
03491             comp=line(0, posEOL);
03492 
03493          line.Remove(0, posEOL+(line(posEOL)==';'?1:2));
03494       }
03495 
03496       if (!comp.Length())
03497          ::Info("ACLiC","Cannot extract compiler call from MakeSharedLibs().");
03498       else {
03499          // if filename is a header compiler won't compile it
03500          // instead, create temp source file which is a copy of the header
03501          Bool_t compileHeader=kFALSE;
03502          size_t lenFilename=expFileName.Length();
03503          const char* endOfFilename=expFileName.Data()+lenFilename;
03504          // check all known header extensions
03505          for (Int_t iExt=0; !compileHeader && iExt<6; iExt++) {
03506             size_t lenExt=strlen(extensions[iExt]);
03507             compileHeader |=lenFilename>lenExt
03508                && !strcmp(extensions[iExt], endOfFilename-lenExt);
03509          }
03510 
03511          TString filenameForCompiler(expFileName);
03512          if (compileHeader) {
03513             // create temp source file
03514             filenameForCompiler= libname + "_ACLiC";
03515             filenameForCompiler+=".check.cxx";
03516             gSystem->Link(expFileName, filenameForCompiler);
03517          }
03518 
03519          comp.ReplaceAll("$SourceFiles",filenameForCompiler);
03520          comp.ReplaceAll("$ObjectFiles",dictObj);
03521          comp.ReplaceAll("$IncludePath",includes);
03522          comp.ReplaceAll("$SharedLib",library);
03523          comp.ReplaceAll("$LinkedLibs",linkLibraries);
03524          comp.ReplaceAll("$LibName",libname);
03525          comp.ReplaceAll("$BuildDir",build_loc);
03526          if (mode==kDebug) comp.ReplaceAll("$Opt",fFlagsDebug);
03527          else comp.ReplaceAll("$Opt",fFlagsOpt);
03528 
03529          if (gDebug>4)  ::Info("ACLiC", "%s", comp.Data());
03530 
03531          Int_t compilationResult = gSystem->Exec( comp );
03532 
03533          if (filenameForCompiler.CompareTo(expFileName))
03534             // remove temporary file
03535             gSystem->Unlink(filenameForCompiler);
03536 
03537          if (!compilationResult) {
03538             ::Info("ACLiC","The compiler has not found any problem with your macro.\n"
03539             "\tProbably your macro uses something rootcint can't parse.\n"
03540             "\tCheck http://root.cern.ch/root/Cint.phtml?limitations for Cint's limitations.");
03541             TString objfile=expFileName;
03542             Ssiz_t len=objfile.Length();
03543             objfile.Replace(len-extension.Length(), len, GetObjExt());
03544             gSystem->Unlink(objfile);
03545          }
03546       }
03547    }
03548 
03549    if ( result ) {
03550 
03551       TNamed *k = new TNamed(library,library);
03552       Long_t lib_time;
03553       gSystem->GetPathInfo( library, 0, (Long_t*)0, 0, &lib_time );
03554       k->SetUniqueID(lib_time);
03555       if (!keep) k->SetBit(kMustCleanup);
03556       fCompiled->Add(k);
03557 
03558 #ifndef NOCINT
03559       // This is intended to force a failure if not all symbols needed
03560       // by the library are present.
03561       gInterpreter->SetRTLD_NOW();
03562 #endif
03563       if (needLoadMap) {
03564           gInterpreter->LoadLibraryMap(libmapfilename);
03565       }
03566       if (gDebug>3)  ::Info("ACLiC","loading the shared library");
03567       if (loadLib) result = !gSystem->Load(library);
03568       else result = kTRUE;
03569 #ifndef NOCINT
03570       gInterpreter->SetRTLD_LAZY();
03571 #endif
03572 
03573       if ( !result ) {
03574          if (gDebug>3) {
03575             ::Info("ACLiC","testing for missing symbols:");
03576             if (gDebug>4)  ::Info("ACLiC", "%s", testcmd.Data());
03577          }
03578          gSystem->Exec(testcmd);
03579          gSystem->Unlink( exec );
03580       }
03581 
03582    };
03583 
03584    if (gDebug<=5) {
03585       gSystem->Unlink( dict );
03586       gSystem->Unlink( dicth );
03587       gSystem->Unlink( dictObj );
03588       gSystem->Unlink( linkdef );
03589       gSystem->Unlink( mapfilein );
03590       gSystem->Unlink( mapfileout );
03591       gSystem->Unlink( fakeMain );
03592       gSystem->Unlink( exec );
03593    }
03594    if (gDebug>6) {
03595       rcint.Prepend("echo ");
03596       cmd.Prepend("echo \" ").Append(" \" ");
03597       testcmd.Prepend("echo \" ").Append(" \" ");
03598       gSystem->Exec(rcint);
03599       gSystem->Exec( cmd );
03600       gSystem->Exec(testcmd);
03601    }
03602 
03603    return result;
03604 }
03605 
03606 //______________________________________________________________________________
03607 Int_t TSystem::GetAclicProperties() const
03608 {
03609    // Return the ACLiC properties field.   See EAclicProperties for details
03610    // on the semantic of each bit.
03611 
03612    return fAclicProperties;
03613 }
03614 
03615 //______________________________________________________________________________
03616 const char *TSystem::GetBuildArch() const
03617 {
03618    // Return the build architecture.
03619    return fBuildArch;
03620 }
03621 
03622 //______________________________________________________________________________
03623 const char *TSystem::GetBuildCompiler() const
03624 {
03625    // Return the build compiler
03626    return fBuildCompiler;
03627 }
03628 
03629 //______________________________________________________________________________
03630 const char *TSystem::GetBuildCompilerVersion() const
03631 {
03632    // Return the build compiler version
03633    return fBuildCompilerVersion;
03634 }
03635 
03636 //______________________________________________________________________________
03637 const char *TSystem::GetBuildNode() const
03638 {
03639    // Return the build node name.
03640    return fBuildNode;
03641 }
03642 
03643 //______________________________________________________________________________
03644 const char *TSystem::GetBuildDir() const
03645 {
03646    // Return the path of the build directory.
03647    if (fBuildDir.Length()==0) {
03648       if (!gEnv) return "";
03649       const_cast<TSystem*>(this)->fBuildDir = gEnv->GetValue("ACLiC.BuildDir","");
03650    }
03651    return fBuildDir;
03652 }
03653 
03654 //______________________________________________________________________________
03655 const char *TSystem::GetFlagsDebug() const
03656 {
03657    // Return the debug flags.
03658    return fFlagsDebug;
03659 }
03660 
03661 //______________________________________________________________________________
03662 const char *TSystem::GetFlagsOpt() const
03663 {
03664    // Return the optimization flags.
03665    return fFlagsOpt;
03666 }
03667 
03668 //______________________________________________________________________________
03669 TSystem::EAclicMode TSystem::GetAclicMode() const
03670 {
03671    // AclicMode indicates whether the library should be built in
03672    // debug mode or optimized.  The values are:
03673    // TSystem::kDefault : compile the same as the current ROOT
03674    // TSystem::kDebug : compiled in debug mode
03675    // TSystem::kOpt : optimized the library
03676 
03677    return fAclicMode;
03678 }
03679 
03680 //______________________________________________________________________________
03681 const char *TSystem::GetMakeSharedLib() const
03682 {
03683    // Return the command line use to make a shared library.
03684    // See TSystem::CompileMacro for more details.
03685    return fMakeSharedLib;
03686 }
03687 
03688 //______________________________________________________________________________
03689 const char *TSystem::GetMakeExe() const
03690 {
03691    // Return the command line use to make an executable.
03692    // See TSystem::CompileMacro for more details.
03693    return fMakeExe;
03694 }
03695 
03696 //______________________________________________________________________________
03697 const char *TSystem::GetIncludePath()
03698 {
03699    // Get the list of include path.
03700    fListPaths = fIncludePath;
03701    fListPaths.Append(" ").Append(gInterpreter->GetIncludePath());
03702    return fListPaths;
03703 }
03704 
03705 //______________________________________________________________________________
03706 const char *TSystem::GetLinkedLibs() const
03707 {
03708    // Return the list of library linked to this executable.
03709    // See TSystem::CompileMacro for more details.
03710    return fLinkedLibs;
03711 }
03712 
03713 //______________________________________________________________________________
03714 const char *TSystem::GetLinkdefSuffix() const
03715 {
03716    // Return the linkdef suffix chosen by the user for ACLiC.
03717    // See TSystem::CompileMacro for more details.
03718    if (fLinkdefSuffix.Length()==0) {
03719       if (!gEnv) return "_linkdef";
03720       const_cast<TSystem*>(this)->fLinkdefSuffix = gEnv->GetValue("ACLiC.Linkdef","_linkdef");
03721    }
03722    return fLinkdefSuffix;
03723 }
03724 
03725 //______________________________________________________________________________
03726 const char *TSystem::GetSoExt() const
03727 {
03728    // Get the shared library extension.
03729    return fSoExt;
03730 }
03731 
03732 //______________________________________________________________________________
03733 const char *TSystem::GetObjExt() const
03734 {
03735    // Get the object file extension.
03736    return fObjExt;
03737 }
03738 
03739 //______________________________________________________________________________
03740 void TSystem::SetBuildDir(const char* build_dir, Bool_t isflat)
03741 {
03742    // Set the location where ACLiC will create libraries and use as
03743    // a scratch area.
03744    // If isflast is flase, then the libraries are actually stored in
03745    // sub-directories of 'build_dir' including the full pathname of the
03746    // script.  If the script is location at /full/path/name/macro.C
03747    // the library will be located at 'build_dir+/full/path/name/macro_C.so'
03748    // If 'isflat' is true, then no subdirectory is created and the library
03749    // is created directly in the directory 'build_dir'.  Note that in this
03750    // mode there is a risk than 2 script of the same in different source
03751    // directory will over-write each other.
03752 
03753    fBuildDir = build_dir;
03754    if (isflat) fAclicProperties |= (kFlatBuildDir & kBitMask);
03755    else fAclicProperties &= ~(kFlatBuildDir & kBitMask);
03756 }
03757 
03758 //______________________________________________________________________________
03759 void TSystem::SetFlagsDebug(const char *flags)
03760 {
03761    // FlagsDebug should contain the options to pass to the C++ compiler
03762    // in order to compile the library in debug mode.
03763 
03764    fFlagsDebug = flags;
03765 }
03766 
03767 //______________________________________________________________________________
03768 void TSystem::SetFlagsOpt(const char *flags)
03769 {
03770    // FlagsOpt should contain the options to pass to the C++ compiler
03771    // in order to compile the library in optimized mode.
03772 
03773    fFlagsOpt = flags;
03774 }
03775 
03776 //______________________________________________________________________________
03777 void TSystem::SetAclicMode(EAclicMode mode)
03778 {
03779    // AclicMode indicates whether the library should be built in
03780    // debug mode or optimized.  The values are:
03781    // TSystem::kDefault : compile the same as the current ROOT
03782    // TSystem::kDebug : compiled in debug mode
03783    // TSystem::kOpt : optimized the library
03784 
03785    fAclicMode = mode;
03786 }
03787 
03788 //______________________________________________________________________________
03789 void TSystem::SetMakeExe(const char *directives)
03790 {
03791    // Directives has the same syntax as the argument of SetMakeSharedLib but is
03792    // used to create an executable. This creation is used as a means to output
03793    // a list of unresolved symbols, when loading a shared library has failed.
03794    // The required variable is $ExeName rather than $SharedLib, e.g.:
03795    // gSystem->SetMakeExe(
03796    // "g++ -Wall -fPIC $IncludePath $SourceFiles
03797    //  -o $ExeName $LinkedLibs -L/usr/X11R6/lib -lX11 -lm -ldl -rdynamic");
03798 
03799    fMakeExe = directives;
03800    // NOTE: add verification that the directives has the required variables
03801 }
03802 
03803 //______________________________________________________________________________
03804 void TSystem::SetMakeSharedLib(const char *directives)
03805 {
03806    // Directives should contain the description on how to compile and link a
03807    // shared lib. This description can be any valid shell command, including
03808    // the use of ';' to separate several instructions. However, shell specific
03809    // construct should be avoided. In particular this description can contain
03810    // environment variables, like $ROOTSYS (or %ROOTSYS% on windows).
03811    //
03812    // Five special variables will be expanded before execution:
03813    //   Variable name       Expands to
03814    //   -------------       ----------
03815    //   $SourceFiles        Name of source files to be compiled
03816    //   $SharedLib          Name of the shared library being created
03817    //   $LibName            Name of shared library without extension
03818    //   $BuildDir           Directory where the files will be created
03819    //   $IncludePath        value of fIncludePath
03820    //   $LinkedLibs         value of fLinkedLibs
03821    //   $DepLibs            libraries on which this library depends on
03822    //   $ObjectFiles        Name of source files to be compiler with
03823    //                       their extension changed to .o or .obj
03824    //   $Opt                location of the optimization/debug options
03825    //                       set fFlagsDebug and fFlagsOpt
03826    //
03827    // e.g.:
03828    // gSystem->SetMakeSharedLib(
03829    // "KCC -n32 --strict $IncludePath -K0 \$Opt $SourceFile
03830    //  --no_exceptions --signed_chars --display_error_number
03831    //  --diag_suppress 68 -o $SharedLib");
03832    //
03833    // gSystem->setMakeSharedLib(
03834    // "Cxx $IncludePath -c $SourceFile;
03835    //  ld  -L/usr/lib/cmplrs/cxx -rpath /usr/lib/cmplrs/cxx -expect_unresolved
03836    //  \$Opt -shared /usr/lib/cmplrs/cc/crt0.o /usr/lib/cmplrs/cxx/_main.o
03837    //  -o $SharedLib $ObjectFile -lcxxstd -lcxx -lexc -lots -lc"
03838    //
03839    // gSystem->SetMakeSharedLib(
03840    // "$HOME/mygcc/bin/g++ \$Opt -Wall -fPIC $IncludePath $SourceFile
03841    //  -shared -o $SharedLib");
03842    //
03843    // gSystem->SetMakeSharedLib(
03844    // "cl -DWIN32  -D_WIN32 -D_MT -D_DLL -MD /O2 /G5 /MD -DWIN32
03845    //  -D_WINDOWS $IncludePath $SourceFile
03846    //  /link -PDB:NONE /NODEFAULTLIB /INCREMENTAL:NO /RELEASE /NOLOGO
03847    //  $LinkedLibs -entry:_DllMainCRTStartup@12 -dll /out:$SharedLib")
03848 
03849    fMakeSharedLib = directives;
03850    // NOTE: add verification that the directives has the required variables
03851 }
03852 
03853 //______________________________________________________________________________
03854 void TSystem::AddIncludePath(const char *includePath)
03855 {
03856    // Add includePath to the already set include path.
03857 
03858    if (includePath) {
03859       fIncludePath += " ";
03860       fIncludePath += includePath;
03861    }
03862 }
03863 
03864 //______________________________________________________________________________
03865 void TSystem::AddLinkedLibs(const char *linkedLib)
03866 {
03867    // Add linkedLib to already set linked libs.
03868 
03869    if (linkedLib) {
03870       fLinkedLibs += " ";
03871       fLinkedLibs += linkedLib;
03872    }
03873 }
03874 
03875 //______________________________________________________________________________
03876 void TSystem::SetIncludePath(const char *includePath)
03877 {
03878    // IncludePath should contain the list of compiler flags to indicate where
03879    // to find user defined header files. It is used to expand $IncludePath in
03880    // the directives given to SetMakeSharedLib() and SetMakeExe(), e.g.:
03881    //    gSystem->SetInclude("-I$ROOTSYS/include -Imydirectory/include");
03882    // the default value of IncludePath on Unix is:
03883    //    "-I$ROOTSYS/include "
03884    // and on Windows:
03885    //    "/I%ROOTSYS%/include "
03886 
03887    fIncludePath = includePath;
03888 }
03889 
03890 //______________________________________________________________________________
03891 void  TSystem::SetLinkedLibs(const char *linkedLibs)
03892 {
03893    // LinkedLibs should contain the library directory and list of libraries
03894    // needed to recreate the current executable. It is used to expand $LinkedLibs
03895    // in the directives given to SetMakeSharedLib() and SetMakeExe()
03896    // The default value on Unix is: root-config --glibs
03897 
03898    fLinkedLibs = linkedLibs;
03899 }
03900 
03901 //______________________________________________________________________________
03902 void  TSystem::SetLinkdefSuffix(const char *suffix)
03903 {
03904    // The 'suffix' will be appended to the name of a script loaded by ACLiC
03905    // and used to locate any eventual additional linkdef information that
03906    // ACLiC should used to produce the dictionary.
03907    // So by default, when doing .L MyScript.cxx, ACLiC will look
03908    // for a file name MyScript_linkdef and having one of the .h (.hpp,
03909    // etc.) extensions.  If such a file exist, it will be added to
03910    // the end of the linkdef file used to created the ACLiC dictionary.
03911    // This effectively enable the full customization of the creation
03912    // of the dictionary.  It should be noted that the file is intended
03913    // as a linkdef 'fragment', so usually you would not list the
03914    // typical '#pragma link off ....".
03915 
03916    fLinkdefSuffix = suffix;
03917 }
03918 
03919 
03920 //______________________________________________________________________________
03921 void TSystem::SetSoExt(const char *SoExt)
03922 {
03923    // Set shared library extension, should be either .so, .sl, .a, .dll, etc.
03924 
03925    fSoExt = SoExt;
03926 }
03927 
03928 //______________________________________________________________________________
03929 void TSystem::SetObjExt(const char *ObjExt)
03930 {
03931    // Set object files extension, should be either .o, .obj, etc.
03932 
03933    fObjExt = ObjExt;
03934 }
03935 
03936 //______________________________________________________________________________
03937 TString TSystem::SplitAclicMode(const char* filename, TString &aclicMode,
03938                                 TString &arguments, TString &io) const
03939 {
03940    // This method split a filename of the form:
03941    //   [path/]macro.C[+|++[g|O]][(args)].
03942    // It stores the ACliC mode [+|++[g|O]] in 'mode',
03943    // the arguments (including paranthesis) in arg
03944    // and the I/O indirection in io
03945 
03946    char *fname = Strip(filename);
03947 
03948    char *arg = strchr(fname, '(');
03949    // special case for $(HOME)/aap.C(10)
03950    while (arg && *arg && (arg > fname && *(arg-1) == '$') && *(arg+1))
03951       arg = strchr(arg+1, '(');
03952    if (arg && arg > fname) {
03953       *arg = 0;
03954       char *t = arg-1;
03955       while (*t == ' ') {
03956          *t = 0; t--;
03957       }
03958       arg++;
03959    }
03960 
03961    // strip off I/O redirect tokens from filename
03962    {
03963       char *s2   = 0;
03964       char *s3;
03965       s2 = strstr(fname, ">>");
03966       if (!s2) s2 = strstr(fname, "2>");
03967       if (!s2) s2 = strchr(fname, '>');
03968       s3 = strchr(fname, '<');
03969       if (s2 && s3) s2 = s2<s3 ? s2 : s3;
03970       if (s3 && !s2) s2 = s3;
03971       if (s2==fname) {
03972          io = fname;
03973          aclicMode = "";
03974          arguments = "";
03975          delete []fname;
03976          return "";
03977       } else if (s2) {
03978          s2--;
03979          while (s2 && *s2 == ' ') s2--;
03980          s2++;
03981          io = s2; // ssave = *s2;
03982          *s2 = 0;
03983       } else
03984          io = "";
03985    }
03986 
03987    // remove the possible ACLiC + or ++ and g or O
03988    aclicMode.Clear();
03989    int len = strlen(fname);
03990    const char *mode = 0;
03991    if (len > 1) {
03992       if (strcmp(fname+len-1, "g") == 0)
03993          mode = "g";
03994       else if (strcmp(fname+len-1, "O") == 0)
03995          mode = "O";
03996       if (mode)
03997          len--;
03998    }
03999    Bool_t compile = len && fname[len - 1] == '+';
04000    Bool_t remove  = compile && len > 1 && fname[len - 2] == '+';
04001    if (compile) {
04002       if (mode) {
04003          fname[len] = 0;
04004       }
04005       if (remove) {
04006          fname[strlen(fname)-2] = 0;
04007          aclicMode = "++";
04008       } else {
04009          fname[strlen(fname)-1] = 0;
04010          aclicMode = "+";
04011       }
04012       if (mode)
04013          aclicMode += mode;
04014    }
04015 
04016    TString resFilename = fname;
04017    arguments = "(";
04018    if (arg) arguments += arg;
04019    else arguments = "";
04020 
04021    delete []fname;
04022    return resFilename;
04023 }
04024 
04025 //______________________________________________________________________________
04026 void TSystem::CleanCompiledMacros()
04027 {
04028    // Remove the shared libs produced by the CompileMacro() function.
04029 
04030    TIter next(fCompiled);
04031    TNamed *lib;
04032    while ((lib = (TNamed*)next())) {
04033       if (lib->TestBit(kMustCleanup)) Unlink(lib->GetTitle());
04034    }
04035 }
04036 
04037 //______________________________________________________________________________
04038 TVersionCheck::TVersionCheck(int versionCode)
04039 {
04040    // Register version of plugin library.
04041 
04042    if (versionCode != TROOT::RootVersionCode() && gLibraryVersion)
04043       gLibraryVersion[gLibraryVersionIdx] = versionCode;
04044 }

Generated on Tue Jul 5 14:11:24 2011 for ROOT_528-00b_version by  doxygen 1.5.1