TEnv.cxx

Go to the documentation of this file.
00001 // @(#)root/base:$Id: TEnv.cxx 37323 2010-12-06 11:02:44Z rdm $
00002 // Author: Fons Rademakers   22/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 // TEnv                                                                 //
00015 //                                                                      //
00016 // The TEnv class reads config files, by default named .rootrc. Three   //
00017 // types of config files are read: global, user and local files. The    //
00018 // global file is $ROOTSYS/etc/system<name> (or ROOTETCDIR/system<name>)//
00019 // the user file is $HOME/<name> and the local file is ./<name>.        //
00020 // By setting the shell variable ROOTENV_NO_HOME=1 the reading of       //
00021 // the $HOME/<name> resource file will be skipped. This might be useful //
00022 // in case the home directory resides on an automounted remote file     //
00023 // system and one wants to avoid this file system from being mounted.   //
00024 //                                                                      //
00025 // The format of the .rootrc file is similar to the .Xdefaults format:  //
00026 //                                                                      //
00027 //   [+]<SystemName>.<RootName|ProgName>.<name>[(type)]:  <value>       //
00028 //                                                                      //
00029 // Where <SystemName> is either Unix, WinNT, MacOS or Vms,              //
00030 // <RootName> the name as given in the TApplication ctor (or "RootApp"  //
00031 // in case no explicit TApplication derived object was created),        //
00032 // <ProgName> the current program name and <name> the resource name,    //
00033 // with optionally a type specification. <value> can be either a        //
00034 // string, an integer, a float/double or a boolean with the values      //
00035 // TRUE, FALSE, ON, OFF, YES, NO, OK, NOT. Booleans will be returned as //
00036 // an integer 0 or 1. The options [+] allows the concatenation of       //
00037 // values to the same resouce name.                                     //
00038 //                                                                      //
00039 // E.g.:                                                                //
00040 //                                                                      //
00041 //   Unix.Rint.Root.DynamicPath: .:$ROOTSYS/lib:~/lib                   //
00042 //   myapp.Root.Debug:  FALSE                                           //
00043 //   TH.Root.Debug: YES                                                 //
00044 //   *.Root.MemStat: 1                                                  //
00045 //                                                                      //
00046 // <SystemName> and <ProgName> or <RootName> may be the wildcard "*".   //
00047 // A # in the first column starts comment line.                         //
00048 //                                                                      //
00049 // For the currently defined resources (and their default values) see   //
00050 // $ROOTSYS/etc/system.rootrc.                                          //
00051 //                                                                      //
00052 // Note that the .rootrc config files contain the config for all ROOT   //
00053 // based applications.                                                  //
00054 //                                                                      //
00055 // To add new entries to a TEnv:                                        //
00056 // TEnv env(".myfile");                                                 //
00057 // env.SetValue("myname","value");                                      //
00058 // env.SaveLevel(kEnvLocal);                                            //
00059 //                                                                      //
00060 // All new entries will be saved in the file corresponding to the       //
00061 // first SaveLevel() command.  If Save() is used, new entries go        //
00062 // into the local file by default.                                      //
00063 //                                                                      //
00064 //////////////////////////////////////////////////////////////////////////
00065 
00066 #include "RConfigure.h"
00067 
00068 #include <string.h>
00069 #include <stdio.h>
00070 #include <stdlib.h>
00071 #include <ctype.h>
00072 
00073 #include "TEnv.h"
00074 #include "TROOT.h"
00075 #include "TSystem.h"
00076 #include "THashList.h"
00077 #include "TError.h"
00078 
00079 
00080 TEnv *gEnv;  // main environment created in TROOT
00081 
00082 
00083 static struct BoolNameTable_t {
00084    const char *fName;
00085    Int_t       fValue;
00086 } gBoolNames[]= {
00087    { "TRUE",  1 },
00088    { "FALSE", 0 },
00089    { "ON",    1 },
00090    { "OFF",   0 },
00091    { "YES",   1 },
00092    { "NO",    0 },
00093    { "OK",    1 },
00094    { "NOT",   0 },
00095    { 0, 0 }
00096 };
00097 
00098 
00099 //---- TEnvParser --------------------------------------------------------------
00100 
00101 class TEnvParser {
00102 
00103 private:
00104    FILE    *fIfp;
00105 
00106 protected:
00107    TEnv    *fEnv;
00108 
00109 public:
00110    TEnvParser(TEnv *e, FILE *f) : fIfp(f), fEnv(e) { }
00111    virtual ~TEnvParser() { }
00112    virtual void KeyValue(const TString&, const TString&, const TString&) { }
00113    virtual void Char(Int_t) { }
00114    void Parse();
00115 };
00116 
00117 //______________________________________________________________________________
00118 void TEnvParser::Parse()
00119 {
00120    // Parse a line of the env file and create an entry in the resource
00121    // dictionary (i.e. add a KeyValue pair).
00122 
00123    TString name(1024);
00124    TString type(1024);
00125    TString value(1024);
00126    int c, state = 0;
00127 
00128    while ((c = fgetc(fIfp)) != EOF) {
00129       if (c == 13)        // ignore CR
00130          continue;
00131       if (c == '\n') {
00132          state = 0;
00133          if (name.Length() > 0) {
00134             KeyValue(name, value, type);
00135             name.Clear();
00136             value.Clear();
00137             type.Clear();
00138          }
00139          Char(c);
00140          continue;
00141       }
00142       switch (state) {
00143       case 0:             // start of line
00144          switch (c) {
00145          case ' ':
00146          case '\t':
00147             break;
00148          case '#':
00149             state = 1;
00150             break;
00151          default:
00152             state = 2;
00153             break;
00154          }
00155          break;
00156 
00157       case 1:             // comment
00158          break;
00159 
00160       case 2:             // name
00161          switch (c) {
00162          case ' ':
00163          case '\t':
00164          case ':':
00165             state = 3;
00166             break;
00167          case '(':
00168             state = 7;
00169             break;
00170          default:
00171             break;
00172          }
00173          break;
00174 
00175       case 3:             // ws before value
00176          if (c != ' ' && c != '\t')
00177             state = 4;
00178          break;
00179 
00180       case 4:             // value
00181          break;
00182 
00183       case 5:             // type
00184          if (c == ')')
00185             state = 6;
00186          break;
00187 
00188       case 6:             // optional ':'
00189          state = (c == ':') ? 3 : 4;
00190          break;
00191 
00192       case 7:
00193          state = (c == ')') ? 6 : 5;
00194          break;
00195 
00196       }
00197       switch (state) {
00198       case 2:
00199          name.Append(c);
00200          break;
00201       case 4:
00202          value.Append(c);
00203          break;
00204       case 5:
00205          type.Append(c);
00206          break;
00207       }
00208       if (state != 4)
00209          Char(c);
00210    }
00211 }
00212 
00213 //---- TReadEnvParser ----------------------------------------------------------
00214 
00215 class TReadEnvParser : public TEnvParser {
00216 
00217 private:
00218    EEnvLevel fLevel;
00219 
00220 public:
00221    TReadEnvParser(TEnv *e, FILE *f, EEnvLevel l) : TEnvParser(e, f), fLevel(l) { }
00222    void KeyValue(const TString &name, const TString &value, const TString &type)
00223       { fEnv->SetValue(name, value, fLevel, type); }
00224 };
00225 
00226 //---- TWriteEnvParser ---------------------------------------------------------
00227 
00228 class TWriteEnvParser : public TEnvParser {
00229 
00230 private:
00231    FILE *fOfp;
00232 
00233 public:
00234    TWriteEnvParser(TEnv *e, FILE *f, FILE *of) : TEnvParser(e, f), fOfp(of) { }
00235    void KeyValue(const TString &name, const TString &value, const TString &type);
00236    void Char(Int_t c) { fputc(c, fOfp); }
00237 };
00238 
00239 //______________________________________________________________________________
00240 void TWriteEnvParser::KeyValue(const TString &name, const TString &value,
00241                                const TString &)
00242 {
00243    // Write resources out to a new file.
00244 
00245    TEnvRec *er = fEnv->Lookup(name);
00246    if (er && er->fModified) {
00247       er->fModified = kFALSE;
00248       fprintf(fOfp, "%s", er->fValue.Data());
00249    } else
00250       fprintf(fOfp, "%s", value.Data());
00251 }
00252 
00253 
00254 //---- TEnvRec -----------------------------------------------------------------
00255 
00256 //______________________________________________________________________________
00257 TEnvRec::TEnvRec(const char *n, const char *v, const char *t, EEnvLevel l)
00258    : fName(n), fType(t), fLevel(l)
00259 {
00260    // Ctor of a single resource.
00261 
00262    fValue = ExpandValue(v);
00263    fModified = (l == kEnvChange);
00264 }
00265 
00266 //______________________________________________________________________________
00267 void TEnvRec::ChangeValue(const char *v, const char *, EEnvLevel l,
00268                           Bool_t append, Bool_t ignoredup)
00269 {
00270    // Change the value of a resource.
00271 
00272    if (l != kEnvChange && fLevel == l && !append) {
00273       // use global Warning() since interpreter might not yet be initialized
00274       // at this stage (called from TROOT ctor)
00275       if (fValue != v && !ignoredup)
00276          ::Warning("TEnvRec::ChangeValue",
00277            "duplicate entry <%s=%s> for level %d; ignored", fName.Data(), v, l);
00278       return;
00279    }
00280    if (!append) {
00281       if (fValue != v) {
00282          if (l == kEnvChange)
00283             fModified = kTRUE;
00284          else
00285             fModified = kFALSE;
00286          fLevel = l;
00287          fValue = ExpandValue(v);
00288       }
00289    } else {
00290       if (l == kEnvChange)
00291          fModified = kTRUE;
00292       fLevel = l;
00293       fValue += " ";
00294       fValue += ExpandValue(v);
00295    }
00296 }
00297 
00298 //______________________________________________________________________________
00299 Int_t TEnvRec::Compare(const TObject *op) const
00300 {
00301    // Comparison function for resources.
00302 
00303    return fName.CompareTo(((TEnvRec*)op)->fName);
00304 }
00305 
00306 //______________________________________________________________________________
00307 TString TEnvRec::ExpandValue(const char *value)
00308 {
00309    // Replace all $(XXX) strings by the value defined in the shell
00310    // (obtained via TSystem::Getenv()).
00311 
00312    const char *vv;
00313    char *v, *vorg = StrDup(value);
00314    v = vorg;
00315 
00316    char *s1, *s2;
00317    int len = 0;
00318    while ((s1 = (char*)strstr(v, "$("))) {
00319       s1 += 2;
00320       s2 = (char*)strchr(s1, ')');
00321       if (!s2) {
00322          len = 0;
00323          break;
00324       }
00325       *s2 = 0;
00326       vv = gSystem->Getenv(s1);
00327       if (vv) len += strlen(vv);
00328       *s2 = ')';
00329       v = s2 + 1;
00330    }
00331 
00332    if (!len) {
00333       delete [] vorg;
00334       return TString(value);
00335    }
00336 
00337    v = vorg;
00338    int nch = strlen(v) + len;
00339    char *nv = new char[nch];
00340    *nv = 0;
00341 
00342    while ((s1 = (char*)strstr(v, "$("))) {
00343       *s1 = 0;
00344       strlcat(nv, v,nch);
00345       *s1 = '$';
00346       s1 += 2;
00347       s2 = (char*)strchr(s1, ')');
00348       *s2 = 0;
00349       vv = gSystem->Getenv(s1);
00350       if (vv) strlcat(nv, vv,nch);
00351       *s2 = ')';
00352       v = s2 + 1;
00353    }
00354 
00355    if (*v) strlcat(nv, v,nch);
00356 
00357    TString val = nv;
00358    delete [] nv;
00359    delete [] vorg;
00360 
00361    return val;
00362 }
00363 
00364 
00365 //---- TEnv --------------------------------------------------------------------
00366 
00367 ClassImp(TEnv)
00368 
00369 //______________________________________________________________________________
00370 TEnv::TEnv(const char *name)
00371 {
00372    // Create a resource table and read the (possibly) three resource files, i.e
00373    // $ROOTSYS/etc/system<name> (or ROOTETCDIR/system<name>), $HOME/<name> and
00374    // ./<name>. ROOT always reads ".rootrc" (in TROOT::InitSystem()). You can
00375    // read additional user defined resource files by creating addtional TEnv
00376    // objects. By setting the shell variable ROOTENV_NO_HOME=1 the reading of
00377    // the $HOME/<name> resource file will be skipped. This might be useful in
00378    // case the home directory resides on an automounted remote file system
00379    // and one wants to avoid the file system from being mounted.
00380 
00381    fIgnoreDup = kFALSE;
00382 
00383    if (!name || !strlen(name) || !gSystem)
00384       fTable = 0;
00385    else {
00386       fTable  = new THashList(1000);
00387       fRcName = name;
00388 
00389       TString sname = "system";
00390       sname += name;
00391 #ifdef ROOTETCDIR
00392       char *s = gSystem->ConcatFileName(ROOTETCDIR, sname);
00393 #else
00394       TString etc = gRootDir;
00395 #ifdef WIN32
00396       etc += "\\etc";
00397 #else
00398       etc += "/etc";
00399 #endif
00400 #if defined(R__MACOSX) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)
00401       // on iOS etc does not exist and system<name> resides in $ROOTSYS
00402       etc = gRootDir;
00403 #endif
00404       char *s = gSystem->ConcatFileName(etc, sname);
00405 #endif
00406       ReadFile(s, kEnvGlobal);
00407       delete [] s;
00408       if (!gSystem->Getenv("ROOTENV_NO_HOME")) {
00409          s = gSystem->ConcatFileName(gSystem->HomeDirectory(), name);
00410          ReadFile(s, kEnvUser);
00411          delete [] s;
00412          if (strcmp(gSystem->HomeDirectory(), gSystem->WorkingDirectory()))
00413             ReadFile(name, kEnvLocal);
00414       } else
00415          ReadFile(name, kEnvLocal);
00416    }
00417 }
00418 
00419 //______________________________________________________________________________
00420 TEnv::~TEnv()
00421 {
00422    // Delete the resource table.
00423 
00424    if (fTable) {
00425       fTable->Delete();
00426       SafeDelete(fTable);
00427    }
00428 }
00429 
00430 //______________________________________________________________________________
00431 const char *TEnv::Getvalue(const char *name)
00432 {
00433    // Returns the character value for a named resouce.
00434 
00435    Bool_t haveProgName = kFALSE;
00436    if (gProgName && strlen(gProgName) > 0)
00437       haveProgName = kTRUE;
00438 
00439    TString aname;
00440    TEnvRec *er = 0;
00441    if (haveProgName && gSystem && gProgName) {
00442       aname = gSystem->GetName(); aname += "."; aname += gProgName;
00443       aname += "."; aname += name;
00444       er = Lookup(aname);
00445    }
00446    if (er == 0 && gSystem && gROOT) {
00447       aname = gSystem->GetName(); aname += "."; aname += gROOT->GetName();
00448       aname += "."; aname += name;
00449       er = Lookup(aname);
00450    }
00451    if (er == 0 && gSystem) {
00452       aname = gSystem->GetName(); aname += ".*."; aname += name;
00453       er = Lookup(aname);
00454    }
00455    if (er == 0 && haveProgName && gProgName) {
00456       aname = gProgName; aname += "."; aname += name;
00457       er = Lookup(aname);
00458    }
00459    if (er == 0 && gROOT) {
00460       aname = gROOT->GetName(); aname += "."; aname += name;
00461       er = Lookup(aname);
00462    }
00463    if (er == 0) {
00464       aname = "*.*."; aname += name;
00465       er = Lookup(aname);
00466    }
00467    if (er == 0) {
00468       aname = "*."; aname += name;
00469       er = Lookup(aname);
00470    }
00471    if (er == 0) {
00472       er = Lookup(name);
00473    }
00474    if (er == 0)
00475       return 0;
00476    return er->fValue;
00477 }
00478 
00479 //______________________________________________________________________________
00480 Int_t TEnv::GetValue(const char *name, Int_t dflt)
00481 {
00482    // Returns the integer value for a resource. If the resource is not found
00483    // return the dflt value.
00484 
00485    const char *cp = TEnv::Getvalue(name);
00486    if (cp) {
00487       char buf2[512], *cp2 = buf2;
00488 
00489       while (isspace((int)*cp))
00490          cp++;
00491       if (*cp) {
00492          BoolNameTable_t *bt;
00493          if (isdigit((int)*cp) || *cp == '-' || *cp == '+')
00494             return atoi(cp);
00495          while (isalpha((int)*cp))
00496             *cp2++ = toupper((int)*cp++);
00497          *cp2 = 0;
00498          for (bt = gBoolNames; bt->fName; bt++)
00499             if (strcmp(buf2, bt->fName) == 0)
00500                return bt->fValue;
00501       }
00502    }
00503    return dflt;
00504 }
00505 
00506 //______________________________________________________________________________
00507 Double_t TEnv::GetValue(const char *name, Double_t dflt)
00508 {
00509    // Returns the double value for a resource. If the resource is not found
00510    // return the dflt value.
00511 
00512    const char *cp = TEnv::Getvalue(name);
00513    if (cp) {
00514       char *endptr;
00515       Double_t val = strtod(cp, &endptr);
00516       if (val == 0.0 && cp == endptr)
00517          return dflt;
00518       return val;
00519    }
00520    return dflt;
00521 }
00522 
00523 //______________________________________________________________________________
00524 const char *TEnv::GetValue(const char *name, const char *dflt)
00525 {
00526    // Returns the character value for a named resouce. If the resource is
00527    // not found the dflt value is returned.
00528 
00529    const char *cp = TEnv::Getvalue(name);
00530    if (cp)
00531       return cp;
00532    return dflt;
00533 }
00534 
00535 //______________________________________________________________________________
00536 TEnvRec *TEnv::Lookup(const char *name)
00537 {
00538    // Loop over all resource records and return the one with name.
00539    // Return 0 in case name is not in the resoucre table.
00540 
00541    if (!fTable) return 0;
00542    return (TEnvRec*) fTable->FindObject(name);
00543 }
00544 
00545 //______________________________________________________________________________
00546 void TEnv::Print(Option_t *opt) const
00547 {
00548    // Print all resources or the global, user or local resources separately.
00549 
00550    if (!opt || !strlen(opt)) {
00551       PrintEnv();
00552       return;
00553    }
00554 
00555    if (!strcmp(opt, "global"))
00556       PrintEnv(kEnvGlobal);
00557    if (!strcmp(opt, "user"))
00558       PrintEnv(kEnvUser);
00559    if (!strcmp(opt, "local"))
00560       PrintEnv(kEnvLocal);
00561 }
00562 
00563 //______________________________________________________________________________
00564 void TEnv::PrintEnv(EEnvLevel level) const
00565 {
00566    // Print all resources for a certain level (global, user, local, changed).
00567 
00568    if (!fTable) return;
00569 
00570    TIter next(fTable);
00571    TEnvRec *er;
00572    static const char *lc[] = { "Global", "User", "Local", "Changed", "All" };
00573 
00574    while ((er = (TEnvRec*) next()))
00575       if (er->fLevel == level || level == kEnvAll)
00576          Printf("%-25s %-30s [%s]", Form("%s:", er->fName.Data()),
00577                 er->fValue.Data(), lc[er->fLevel]);
00578 }
00579 
00580 //______________________________________________________________________________
00581 Int_t TEnv::ReadFile(const char *fname, EEnvLevel level)
00582 {
00583    // Read and parse the resource file for a certain level.
00584    // Returns -1 on case of error, 0 in case of success.
00585 
00586    if (!fname || !strlen(fname)) {
00587       Error("ReadFile", "no file name specified");
00588       return -1;
00589    }
00590 
00591    FILE *ifp;
00592    if ((ifp = fopen(fname, "r"))) {
00593       TReadEnvParser rp(this, ifp, level);
00594       rp.Parse();
00595       fclose(ifp);
00596       return 0;
00597    }
00598 
00599    // no Error() here since we are allowed to try to read from a non-existing
00600    // file (like ./.rootrc, $HOME/.rootrc, etc.)
00601    return -1;
00602 }
00603 
00604 //______________________________________________________________________________
00605 Int_t TEnv::WriteFile(const char *fname, EEnvLevel level)
00606 {
00607    // Write resourse records to file fname for a certain level. Use
00608    // level kEnvAll to write all resources. Returns -1 on case of error,
00609    // 0 in case of success.
00610 
00611    if (!fname || !strlen(fname)) {
00612       Error("WriteFile", "no file name specified");
00613       return -1;
00614    }
00615 
00616    if (!fTable) {
00617       Error("WriteFile", "TEnv table is empty");
00618       return -1;
00619    }
00620 
00621    FILE *ofp;
00622    if ((ofp = fopen(fname, "w"))) {
00623       TIter next(fTable);
00624       TEnvRec *er;
00625       while ((er = (TEnvRec*) next()))
00626          if (er->fLevel == level || level == kEnvAll)
00627             fprintf(ofp, "%-40s %s\n", Form("%s:", er->fName.Data()),
00628                     er->fValue.Data());
00629       fclose(ofp);
00630       return 0;
00631    }
00632 
00633    Error("WriteFile", "cannot open %s for writing", fname);
00634    return -1;
00635 }
00636 
00637 //______________________________________________________________________________
00638 void TEnv::Save()
00639 {
00640    // Write the resource files for each level. The new files have the same
00641    // name as the original files. The old files are renamed to *.bak.
00642 
00643    if (fRcName == "") {
00644       Error("Save", "no resource file name specified");
00645       return;
00646    }
00647 
00648    SaveLevel(kEnvLocal);  // Be default, new items will be put into Local.
00649    SaveLevel(kEnvUser);
00650    SaveLevel(kEnvGlobal);
00651 }
00652 
00653 //______________________________________________________________________________
00654 void TEnv::SaveLevel(EEnvLevel level)
00655 {
00656    // Write the resource file for a certain level.
00657 
00658    if (fRcName == "") {
00659       Error("SaveLevel", "no resource file name specified");
00660       return;
00661    }
00662 
00663    if (!fTable) {
00664       Error("SaveLevel", "TEnv table is empty");
00665       return;
00666    }
00667 
00668    TString   rootrcdir;
00669    FILE     *ifp, *ofp;
00670 
00671    if (level == kEnvGlobal) {
00672 
00673       TString sname = "system";
00674       sname += fRcName;
00675 #ifdef ROOTETCDIR
00676       char *s = gSystem->ConcatFileName(ROOTETCDIR, sname);
00677 #else
00678       TString etc = gRootDir;
00679 #ifdef WIN32
00680       etc += "\\etc";
00681 #else
00682       etc += "/etc";
00683 #endif
00684       char *s = gSystem->ConcatFileName(etc, sname);
00685 #endif
00686       rootrcdir = s;
00687       delete [] s;
00688    } else if (level == kEnvUser) {
00689       char *s = gSystem->ConcatFileName(gSystem->HomeDirectory(), fRcName);
00690       rootrcdir = s;
00691       delete [] s;
00692    } else if (level == kEnvLocal)
00693       rootrcdir = fRcName;
00694    else
00695       return;
00696 
00697    if ((ofp = fopen(Form("%s.new", rootrcdir.Data()), "w"))) {
00698       ifp = fopen(rootrcdir.Data(), "r");
00699       if (ifp == 0) {     // try to create file
00700          ifp = fopen(rootrcdir.Data(), "w");
00701          if (ifp) {
00702             fclose(ifp);
00703             ifp = 0;
00704          }
00705       }
00706       if (ifp || (ifp = fopen(rootrcdir.Data(), "r"))) {
00707          TWriteEnvParser wp(this, ifp, ofp);
00708          wp.Parse();
00709 
00710          TIter next(fTable);
00711          TEnvRec *er;
00712          while ((er = (TEnvRec*) next())) {
00713             if (er->fModified) {
00714 
00715                // If it doesn't have a level yet, make it this one.
00716                if (er->fLevel == kEnvChange) er->fLevel = level;
00717                if (er->fLevel == level) {
00718                   er->fModified = kFALSE;
00719                   fprintf(ofp, "%-40s %s\n", Form("%s:", er->fName.Data()),
00720                           er->fValue.Data());
00721                }
00722             }
00723          }
00724          fclose(ifp);
00725          fclose(ofp);
00726          gSystem->Rename(rootrcdir.Data(), Form("%s.bak", rootrcdir.Data()));
00727          gSystem->Rename(Form("%s.new", rootrcdir.Data()), rootrcdir.Data());
00728          return;
00729       }
00730       fclose(ofp);
00731    } else
00732       Error("SaveLevel", "cannot write to file %s", rootrcdir.Data());
00733 }
00734 
00735 //______________________________________________________________________________
00736 void TEnv::SetValue(const char *name, const char *value, EEnvLevel level,
00737                     const char *type)
00738 {
00739    // Set the value of a resource or create a new resource.
00740 
00741    if (!fTable)
00742       fTable  = new THashList(1000);
00743 
00744    const char *nam = name;
00745    Bool_t append = kFALSE;
00746    if (name[0] == '+') {
00747       nam    = &name[1];
00748       append = kTRUE;
00749    }
00750 
00751    TEnvRec *er = Lookup(nam);
00752    if (er)
00753       er->ChangeValue(value, type, level, append, fIgnoreDup);
00754    else
00755       fTable->Add(new TEnvRec(nam, value, type, level));
00756 }
00757 
00758 //______________________________________________________________________________
00759 void TEnv::SetValue(const char *name, EEnvLevel level)
00760 {
00761    // Set the value of a resource or create a new resource.
00762    // Use this method to set a resource like, "name=val".
00763    // If just "name" is given it will be interpreted as "name=1".
00764 
00765    TString buf = name;
00766    int l = buf.Index("=");
00767    if (l > 0) {
00768       TString nm  = buf(0, l);
00769       TString val = buf(l+1, buf.Length());
00770       SetValue(nm, val, level);
00771    } else
00772       SetValue(name, "1", level);
00773 }
00774 
00775 //______________________________________________________________________________
00776 void TEnv::SetValue(const char *name, Int_t value)
00777 {
00778    // Set or create an integer resource value.
00779 
00780    SetValue(name, Form("%d", value));
00781 }
00782 
00783 //______________________________________________________________________________
00784 void TEnv::SetValue(const char *name, double value)
00785 {
00786    // Set or create a double resource value.
00787 
00788    SetValue(name, Form("%g", value));
00789 }
00790 
00791 //______________________________________________________________________________
00792 Bool_t TEnv::IgnoreDuplicates(Bool_t ignore)
00793 {
00794    // If set to true, no warnings in case of duplicates are issued.
00795    // Returns previous value.
00796 
00797    Bool_t ret = fIgnoreDup;
00798    fIgnoreDup = ignore;
00799    return ret;
00800 }

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